2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "bindings/core/v8/ArrayValue.h"
29 #include "bindings/core/v8/DictionaryHelperForBindings.h"
30 #include "bindings/core/v8/ExceptionMessages.h"
31 #include "bindings/core/v8/ExceptionState.h"
32 #include "bindings/core/v8/V8ArrayBufferView.h"
33 #include "bindings/core/v8/V8Binding.h"
34 #include "bindings/core/v8/V8DOMError.h"
35 #include "bindings/core/v8/V8Element.h"
36 #include "bindings/core/v8/V8EventTarget.h"
37 #include "bindings/core/v8/V8MediaKeyError.h"
38 #include "bindings/core/v8/V8MessagePort.h"
39 #include "bindings/core/v8/V8Path2D.h"
40 #include "bindings/core/v8/V8Storage.h"
41 #include "bindings/core/v8/V8TextTrack.h"
42 #include "bindings/core/v8/V8Uint8Array.h"
43 #include "bindings/core/v8/V8VoidCallback.h"
44 #include "bindings/core/v8/V8Window.h"
45 #include "core/html/track/TrackBase.h"
46 #include "wtf/MathExtras.h"
51 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, v8::Local<v8::Value>& value)
53 return dictionary.get(key, value);
57 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, Dictionary& value)
59 return dictionary.get(key, value);
63 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, bool& value)
65 v8::Local<v8::Value> v8Value;
66 if (!dictionary.get(key, v8Value))
69 v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean();
72 value = v8Bool->Value();
77 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, bool& value)
79 Dictionary::ConversionContextScope scope(context);
80 DictionaryHelper::get(dictionary, key, value);
85 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, int32_t& value)
87 v8::Local<v8::Value> v8Value;
88 if (!dictionary.get(key, v8Value))
91 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
92 if (v8Int32.IsEmpty())
94 value = v8Int32->Value();
99 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, double& value, bool& hasValue)
101 v8::Local<v8::Value> v8Value;
102 if (!dictionary.get(key, v8Value)) {
108 TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
109 if (v8Number.IsEmpty())
111 value = v8Number->Value();
116 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, double& value)
119 return DictionaryHelper::get(dictionary, key, value, unused);
123 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, double& value)
125 Dictionary::ConversionContextScope scope(context);
127 bool hasValue = false;
128 if (!DictionaryHelper::get(dictionary, key, value, hasValue) && hasValue) {
129 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'."));
135 template<typename StringType>
136 bool getStringType(const Dictionary& dictionary, const String& key, StringType& value)
138 v8::Local<v8::Value> v8Value;
139 if (!dictionary.get(key, v8Value))
142 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
148 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, String& value)
150 return getStringType(dictionary, key, value);
154 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, AtomicString& value)
156 return getStringType(dictionary, key, value);
160 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, String& value)
162 Dictionary::ConversionContextScope scope(context);
164 v8::Local<v8::Value> v8Value;
165 if (!dictionary.get(key, v8Value))
168 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
174 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, ScriptValue& value)
176 v8::Local<v8::Value> v8Value;
177 if (!dictionary.get(key, v8Value))
180 value = ScriptValue(ScriptState::current(dictionary.isolate()), v8Value);
185 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, ScriptValue& value)
187 Dictionary::ConversionContextScope scope(context);
189 DictionaryHelper::get(dictionary, key, value);
193 template<typename NumericType>
194 bool getNumericType(const Dictionary& dictionary, const String& key, NumericType& value)
196 v8::Local<v8::Value> v8Value;
197 if (!dictionary.get(key, v8Value))
200 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
201 if (v8Int32.IsEmpty())
203 value = static_cast<NumericType>(v8Int32->Value());
208 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, short& value)
210 return getNumericType<short>(dictionary, key, value);
214 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned short& value)
216 return getNumericType<unsigned short>(dictionary, key, value);
220 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned& value)
222 return getNumericType<unsigned>(dictionary, key, value);
226 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned long& value)
228 v8::Local<v8::Value> v8Value;
229 if (!dictionary.get(key, v8Value))
232 v8::Local<v8::Integer> v8Integer = v8Value->ToInteger();
233 if (v8Integer.IsEmpty())
235 value = static_cast<unsigned long>(v8Integer->Value());
240 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned long long& value)
242 v8::Local<v8::Value> v8Value;
243 if (!dictionary.get(key, v8Value))
246 TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
247 if (v8Number.IsEmpty())
249 double d = v8Number->Value();
250 doubleToInteger(d, value);
255 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, RefPtrWillBeMember<LocalDOMWindow>& value)
257 v8::Local<v8::Value> v8Value;
258 if (!dictionary.get(key, v8Value))
261 // We need to handle a DOMWindow specially, because a DOMWindow wrapper
262 // exists on a prototype chain of v8Value.
263 value = toDOMWindow(v8Value, dictionary.isolate());
268 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, HashSet<AtomicString>& value)
270 v8::Local<v8::Value> v8Value;
271 if (!dictionary.get(key, v8Value))
274 // FIXME: Support array-like objects
275 if (!v8Value->IsArray())
278 ASSERT(dictionary.isolate());
279 ASSERT(dictionary.isolate() == v8::Isolate::GetCurrent());
280 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
281 for (size_t i = 0; i < v8Array->Length(); ++i) {
282 v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(dictionary.isolate(), i));
283 TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false);
284 value.add(stringValue);
291 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, HashSet<AtomicString>& value)
293 Dictionary::ConversionContextScope scope(context);
295 v8::Local<v8::Value> v8Value;
296 if (!dictionary.get(key, v8Value))
299 if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
302 if (!v8Value->IsArray()) {
303 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
307 return DictionaryHelper::get(dictionary, key, value);
311 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, RefPtrWillBeMember<TrackBase>& value)
313 v8::Local<v8::Value> v8Value;
314 if (!dictionary.get(key, v8Value))
317 TrackBase* source = 0;
318 if (v8Value->IsObject()) {
319 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
321 // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once
323 v8::Handle<v8::Object> track = V8TextTrack::findInstanceInPrototypeChain(wrapper, dictionary.isolate());
324 if (!track.IsEmpty())
325 source = V8TextTrack::toImpl(track);
332 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, RefPtrWillBeMember<EventTarget>& value)
334 v8::Local<v8::Value> v8Value;
335 if (!dictionary.get(key, v8Value))
339 // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper
340 // exists on a prototype chain of v8Value.
341 if (v8Value->IsObject()) {
342 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
343 v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(wrapper, dictionary.isolate());
344 if (!window.IsEmpty()) {
345 value = toWrapperTypeInfo(window)->toEventTarget(window);
350 if (V8DOMWrapper::isDOMWrapper(v8Value)) {
351 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
352 value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper);
358 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, Vector<String>& value)
360 v8::Local<v8::Value> v8Value;
361 if (!dictionary.get(key, v8Value))
364 if (!v8Value->IsArray())
367 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
368 for (size_t i = 0; i < v8Array->Length(); ++i) {
369 v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(dictionary.isolate(), i));
370 TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false);
371 value.append(stringValue);
378 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, Vector<Vector<String> >& value, ExceptionState& exceptionState)
380 v8::Local<v8::Value> v8Value;
381 if (!dictionary.get(key, v8Value))
384 if (!v8Value->IsArray())
387 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
388 for (size_t i = 0; i < v8Array->Length(); ++i) {
389 v8::Local<v8::Value> v8IndexedValue = v8Array->Get(v8::Uint32::New(dictionary.isolate(), i));
390 Vector<String> indexedValue = toImplArray<String>(v8IndexedValue, i, dictionary.isolate(), exceptionState);
391 if (exceptionState.hadException())
393 value.append(indexedValue);
400 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, Vector<String>& value)
402 Dictionary::ConversionContextScope scope(context);
404 v8::Local<v8::Value> v8Value;
405 if (!dictionary.get(key, v8Value))
408 if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
411 if (!v8Value->IsArray()) {
412 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
416 return DictionaryHelper::get(dictionary, key, value);
420 bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, ArrayValue& value)
422 v8::Local<v8::Value> v8Value;
423 if (!dictionary.get(key, v8Value))
426 if (!v8Value->IsArray())
429 ASSERT(dictionary.isolate());
430 ASSERT(dictionary.isolate() == v8::Isolate::GetCurrent());
431 value = ArrayValue(v8::Local<v8::Array>::Cast(v8Value), dictionary.isolate());
436 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, ArrayValue& value)
438 Dictionary::ConversionContextScope scope(context);
440 v8::Local<v8::Value> v8Value;
441 if (!dictionary.get(key, v8Value))
444 if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
447 if (!v8Value->IsArray()) {
448 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
452 return DictionaryHelper::get(dictionary, key, value);
456 struct DictionaryHelperTraits<DOMUint8Array> {
457 typedef V8Uint8Array type;
461 struct DictionaryHelperTraits<DOMArrayBufferView> {
462 typedef V8ArrayBufferView type;
466 struct DictionaryHelperTraits<MediaKeyError> {
467 typedef V8MediaKeyError type;
471 struct DictionaryHelperTraits<DOMError> {
472 typedef V8DOMError type;
476 struct DictionaryHelperTraits<Storage> {
477 typedef V8Storage type;
481 struct DictionaryHelperTraits<Element> {
482 typedef V8Element type;
486 struct DictionaryHelperTraits<Path2D> {
487 typedef V8Path2D type;
490 template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtr<DOMUint8Array>& value);
491 template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtr<DOMArrayBufferView>& value);
492 template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<MediaKeyError>& value);
493 template bool DictionaryHelper::get(const Dictionary&, const String& key, Member<DOMError>& value);
494 template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<Storage>& value);
495 template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<Element>& value);
496 template bool DictionaryHelper::get(const Dictionary&, const String& key, RawPtr<Element>& value);
497 template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<Path2D>& value);
498 template bool DictionaryHelper::get(const Dictionary&, const String& key, RawPtr<Path2D>& value);
500 template <typename T>
501 struct IntegralTypeTraits {
505 struct IntegralTypeTraits<uint8_t> {
506 static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
508 return toUInt8(value, configuration, exceptionState);
510 static const String typeName() { return "UInt8"; }
514 struct IntegralTypeTraits<int8_t> {
515 static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
517 return toInt8(value, configuration, exceptionState);
519 static const String typeName() { return "Int8"; }
523 struct IntegralTypeTraits<unsigned short> {
524 static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
526 return toUInt16(value, configuration, exceptionState);
528 static const String typeName() { return "UInt16"; }
532 struct IntegralTypeTraits<short> {
533 static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
535 return toInt16(value, configuration, exceptionState);
537 static const String typeName() { return "Int16"; }
541 struct IntegralTypeTraits<unsigned> {
542 static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
544 return toUInt32(value, configuration, exceptionState);
546 static const String typeName() { return "UInt32"; }
550 struct IntegralTypeTraits<unsigned long> {
551 static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
553 return toUInt32(value, configuration, exceptionState);
555 static const String typeName() { return "UInt32"; }
559 struct IntegralTypeTraits<int> {
560 static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
562 return toInt32(value, configuration, exceptionState);
564 static const String typeName() { return "Int32"; }
568 struct IntegralTypeTraits<long> {
569 static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
571 return toInt32(value, configuration, exceptionState);
573 static const String typeName() { return "Int32"; }
577 struct IntegralTypeTraits<unsigned long long> {
578 static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
580 return toUInt64(value, configuration, exceptionState);
582 static const String typeName() { return "UInt64"; }
586 struct IntegralTypeTraits<long long> {
587 static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
589 return toInt64(value, configuration, exceptionState);
591 static const String typeName() { return "Int64"; }
595 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, T& value)
597 Dictionary::ConversionContextScope scope(context);
599 v8::Local<v8::Value> v8Value;
600 if (!dictionary.get(key, v8Value))
603 value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState());
604 if (context.exceptionState().throwIfNeeded())
610 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, uint8_t& value);
611 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, int8_t& value);
612 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned short& value);
613 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, short& value);
614 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned& value);
615 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned long& value);
616 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, int& value);
617 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, long& value);
618 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, long long& value);
619 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned long long& value);
622 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, Nullable<T>& value)
624 Dictionary::ConversionContextScope scope(context);
626 v8::Local<v8::Value> v8Value;
627 if (!dictionary.get(key, v8Value))
630 if (context.isNullable() && blink::isUndefinedOrNull(v8Value)) {
631 value = Nullable<T>();
635 T converted = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState());
637 if (context.exceptionState().throwIfNeeded())
640 value = Nullable<T>(converted);
644 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<uint8_t>& value);
645 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<int8_t>& value);
646 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned short>& value);
647 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<short>& value);
648 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned>& value);
649 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned long>& value);
650 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<int>& value);
651 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<long>& value);
652 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<long long>& value);
653 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned long long>& value);
655 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<LocalDOMWindow>& value);
656 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<Storage>& value);
657 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtr<DOMUint8Array>& value);
658 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtr<DOMArrayBufferView>& value);
659 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<MediaKeyError>& value);
660 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<TrackBase>& value);
661 template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<EventTarget>& value);
664 bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, MessagePortArray& value)
666 Dictionary::ConversionContextScope scope(context);
668 v8::Local<v8::Value> v8Value;
669 if (!dictionary.get(key, v8Value))
672 ASSERT(dictionary.isolate());
673 ASSERT(dictionary.isolate() == v8::Isolate::GetCurrent());
675 if (isUndefinedOrNull(v8Value))
678 value = toRefPtrWillBeMemberNativeArray<MessagePort, V8MessagePort>(v8Value, key, dictionary.isolate(), context.exceptionState());
680 if (context.exceptionState().throwIfNeeded())