| // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_IMPL_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_IMPL_H_ |
| |
| #include "third_party/blink/renderer/bindings/core/v8/idl_types.h" |
| #include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h" |
| #include "third_party/blink/renderer/bindings/core/v8/script_iterator.h" |
| #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" |
| #include "third_party/blink/renderer/bindings/core/v8/script_value.h" |
| #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" |
| #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_html.h" |
| #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_script.h" |
| #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_script_url.h" |
| #include "third_party/blink/renderer/core/core_export.h" |
| #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h" |
| #include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h" |
| #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" |
| #include "third_party/blink/renderer/platform/bindings/exception_messages.h" |
| #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" |
| |
| namespace blink { |
| |
| class CallbackFunctionBase; |
| class CallbackInterfaceBase; |
| class EventListener; |
| class FlexibleArrayBufferView; |
| class IDLDictionaryBase; |
| class ScriptWrappable; |
| class XPathNSResolver; |
| struct WrapperTypeInfo; |
| |
| namespace bindings { |
| |
| class DictionaryBase; |
| class EnumerationBase; |
| class UnionBase; |
| |
| CORE_EXPORT void NativeValueTraitsInterfaceNotOfType( |
| const WrapperTypeInfo* wrapper_type_info, |
| ExceptionState& exception_state); |
| |
| CORE_EXPORT void NativeValueTraitsInterfaceNotOfType( |
| const WrapperTypeInfo* wrapper_type_info, |
| int argument_index, |
| ExceptionState& exception_state); |
| |
| } // namespace bindings |
| |
| // any |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLAny> |
| : public NativeValueTraitsBase<IDLAny> { |
| static ScriptValue NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ScriptValue(isolate, value); |
| } |
| }; |
| |
| // IDLNullable<IDLAny> must not be used. |
| template <> |
| struct NativeValueTraits<IDLNullable<IDLAny>>; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLAny>> |
| : public NativeValueTraitsBase<IDLAny> { |
| static ScriptValue NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ScriptValue(isolate, value); |
| } |
| }; |
| |
| // boolean |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLBoolean> |
| : public NativeValueTraitsBase<IDLBoolean> { |
| static bool NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToBoolean(isolate, value, exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLBoolean>> |
| : public NativeValueTraitsBase<IDLBoolean> { |
| static bool NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToBoolean(isolate, value, exception_state); |
| } |
| }; |
| |
| // Integer types |
| #define DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(T, Func) \ |
| template <bindings::IDLIntegerConvMode mode> \ |
| struct NativeValueTraits<IDLIntegerTypeBase<T, mode>> \ |
| : public NativeValueTraitsBase<IDLIntegerTypeBase<T, mode>> { \ |
| static T NativeValue(v8::Isolate* isolate, \ |
| v8::Local<v8::Value> value, \ |
| ExceptionState& exception_state) { \ |
| return Func(isolate, value, \ |
| static_cast<IntegerConversionConfiguration>(mode), \ |
| exception_state); \ |
| } \ |
| } |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(int8_t, ToInt8); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(uint8_t, ToUInt8); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(int16_t, ToInt16); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(uint16_t, ToUInt16); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(int32_t, ToInt32); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(uint32_t, ToUInt32); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(int64_t, ToInt64); |
| DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE(uint64_t, ToUInt64); |
| #undef DEFINE_NATIVE_VALUE_TRAITS_INTEGER_TYPE |
| |
| // Floats and doubles |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLDouble> |
| : public NativeValueTraitsBase<IDLDouble> { |
| static double NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToRestrictedDouble(isolate, value, exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLUnrestrictedDouble> |
| : public NativeValueTraitsBase<IDLUnrestrictedDouble> { |
| static double NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToDouble(isolate, value, exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLFloat> |
| : public NativeValueTraitsBase<IDLFloat> { |
| static float NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToRestrictedFloat(isolate, value, exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLUnrestrictedFloat> |
| : public NativeValueTraitsBase<IDLUnrestrictedFloat> { |
| static float NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToFloat(isolate, value, exception_state); |
| } |
| }; |
| |
| // Strings |
| template <V8StringResourceMode mode> |
| struct NativeValueTraits<IDLByteStringBase<mode>> |
| : public NativeValueTraitsBase<IDLByteStringBase<mode>> { |
| // http://heycam.github.io/webidl/#es-ByteString |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| V8StringResource<mode> string_resource(value); |
| // 1. Let x be ToString(v) |
| if (!string_resource.Prepare(isolate, exception_state)) |
| return String(); |
| String x = string_resource; |
| // 2. If the value of any element of x is greater than 255, then throw a |
| // TypeError. |
| if (!x.ContainsOnlyLatin1OrEmpty()) { |
| exception_state.ThrowTypeError("Value is not a valid ByteString."); |
| return String(); |
| } |
| |
| // 3. Return an IDL ByteString value whose length is the length of x, and |
| // where the value of each element is the value of the corresponding |
| // element of x. |
| // Blink: A ByteString is simply a String with a range constrained per |
| // the above, so this is the identity operation. |
| return x; |
| } |
| }; |
| |
| template <V8StringResourceMode mode> |
| struct NativeValueTraits<IDLStringBase<mode>> |
| : public NativeValueTraitsBase<IDLStringBase<mode>> { |
| // https://heycam.github.io/webidl/#es-DOMString |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| V8StringResource<mode> string(value); |
| if (!string.Prepare(isolate, exception_state)) |
| return String(); |
| return string; |
| } |
| }; |
| |
| template <V8StringResourceMode mode> |
| struct NativeValueTraits<IDLStringStringContextTrustedHTMLBase<mode>> |
| : public NativeValueTraitsBase< |
| IDLStringStringContextTrustedHTMLBase<mode>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| if (V8TrustedHTML::HasInstance(value, isolate)) { |
| TrustedHTML* trusted_value = |
| V8TrustedHTML::ToImpl(v8::Local<v8::Object>::Cast(value)); |
| return trusted_value->toString(); |
| } else { |
| V8StringResource<mode> string(value); |
| if (!string.Prepare(isolate, exception_state)) |
| return String(); |
| return TrustedTypesCheckForHTML(string, execution_context, |
| exception_state); |
| } |
| } |
| }; |
| |
| template <V8StringResourceMode mode> |
| struct NativeValueTraits<IDLStringStringContextTrustedScriptBase<mode>> |
| : public NativeValueTraitsBase< |
| IDLStringStringContextTrustedScriptBase<mode>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| if (V8TrustedScript::HasInstance(value, isolate)) { |
| TrustedScript* trusted_value = |
| V8TrustedScript::ToImpl(v8::Local<v8::Object>::Cast(value)); |
| return trusted_value->toString(); |
| } else { |
| V8StringResource<mode> string(value); |
| if (!string.Prepare(isolate, exception_state)) |
| return String(); |
| return TrustedTypesCheckForScript(string, execution_context, |
| exception_state); |
| } |
| } |
| }; |
| |
| template <V8StringResourceMode mode> |
| struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBase<mode>> |
| : public NativeValueTraitsBase< |
| IDLUSVStringStringContextTrustedScriptURLBase<mode>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| if (V8TrustedScriptURL::HasInstance(value, isolate)) { |
| TrustedScriptURL* trusted_value = |
| V8TrustedScriptURL::ToImpl(v8::Local<v8::Object>::Cast(value)); |
| return trusted_value->toString(); |
| } else { |
| V8StringResource<mode> string(value); |
| if (!string.Prepare(isolate, exception_state)) |
| return String(); |
| return TrustedTypesCheckForScriptURL(string, execution_context, |
| exception_state); |
| } |
| } |
| }; |
| |
| template <V8StringResourceMode mode> |
| struct NativeValueTraits<IDLUSVStringBase<mode>> |
| : public NativeValueTraitsBase<IDLUSVStringBase<mode>> { |
| // http://heycam.github.io/webidl/#es-USVString |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| // 1. Let string be the result of converting V to a DOMString. |
| V8StringResource<mode> string(value); |
| if (!string.Prepare(isolate, exception_state)) |
| return String(); |
| // 2. Return an IDL USVString value that is the result of converting string |
| // to a sequence of Unicode scalar values. |
| return ReplaceUnmatchedSurrogates(string); |
| } |
| }; |
| |
| // Strings for the new bindings generator |
| |
| namespace bindings { |
| |
| // ToBlinkString implements AtomicString- and String-specific conversions from |
| // v8::String. NativeValueTraitsStringAdapter helps select the best conversion. |
| // |
| // Example: |
| // void F(const AtomicString& s); |
| // void G(const String& s); |
| // |
| // const NativeValueTraitsStringAdapter& x = ...; |
| // F(x); // ToBlinkString<AtomicString> is used. |
| // G(x); // ToBlinkString<String> is used. |
| class CORE_EXPORT NativeValueTraitsStringAdapter { |
| STACK_ALLOCATED(); |
| |
| public: |
| NativeValueTraitsStringAdapter() = default; |
| NativeValueTraitsStringAdapter(const NativeValueTraitsStringAdapter&) = |
| delete; |
| NativeValueTraitsStringAdapter(NativeValueTraitsStringAdapter&&) = default; |
| explicit NativeValueTraitsStringAdapter(v8::Local<v8::String> value) |
| : v8_string_(value) {} |
| explicit NativeValueTraitsStringAdapter(const String& value) |
| : wtf_string_(value) {} |
| explicit NativeValueTraitsStringAdapter(int32_t value) |
| : wtf_string_(ToBlinkString(value)) {} |
| |
| NativeValueTraitsStringAdapter& operator=( |
| const NativeValueTraitsStringAdapter&) = delete; |
| NativeValueTraitsStringAdapter& operator=(NativeValueTraitsStringAdapter&&) = |
| default; |
| NativeValueTraitsStringAdapter& operator=(const String& value) { |
| v8_string_.Clear(); |
| wtf_string_ = value; |
| return *this; |
| } |
| |
| void Init(v8::Local<v8::String> value) { |
| DCHECK(v8_string_.IsEmpty()); |
| DCHECK(wtf_string_.IsNull()); |
| v8_string_ = value; |
| } |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator String() const { return ToString<String>(); } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator AtomicString() const { return ToString<AtomicString>(); } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator StringView() const& { return ToStringView(); } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator StringView() const&& = delete; |
| |
| private: |
| template <class StringType> |
| StringType ToString() const { |
| if (LIKELY(!v8_string_.IsEmpty())) |
| return ToBlinkString<StringType>(v8_string_, kExternalize); |
| return StringType(wtf_string_); |
| } |
| |
| StringView ToStringView() const& { |
| if (LIKELY(!v8_string_.IsEmpty())) { |
| return ToBlinkStringView(v8_string_, string_view_backing_store_, |
| kExternalize); |
| } |
| return wtf_string_; |
| } |
| |
| v8::Local<v8::String> v8_string_; |
| String wtf_string_; |
| mutable StringView::StackBackingStore string_view_backing_store_; |
| }; |
| |
| } // namespace bindings |
| |
| template <bindings::IDLStringConvMode mode> |
| struct NativeValueTraits<IDLByteStringBaseV2<mode>> |
| : public NativeValueTraitsBase<IDLByteStringBaseV2<mode>> { |
| // http://heycam.github.io/webidl/#es-ByteString |
| static bindings::NativeValueTraitsStringAdapter NativeValue( |
| v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsString() and value.As<v8::String>()->ContainsOnlyOneByte()) |
| return bindings::NativeValueTraitsStringAdapter(value.As<v8::String>()); |
| if (value->IsInt32()) { |
| return bindings::NativeValueTraitsStringAdapter( |
| value.As<v8::Int32>()->Value()); |
| } |
| |
| if (mode == bindings::IDLStringConvMode::kNullable) { |
| if (value->IsNullOrUndefined()) |
| return bindings::NativeValueTraitsStringAdapter(); |
| } |
| |
| v8::TryCatch try_catch(isolate); |
| v8::Local<v8::String> v8_string; |
| if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&v8_string)) { |
| exception_state.RethrowV8Exception(try_catch.Exception()); |
| return bindings::NativeValueTraitsStringAdapter(); |
| } |
| if (!v8_string->ContainsOnlyOneByte()) { |
| exception_state.ThrowTypeError( |
| "String contains non ISO-8859-1 code point."); |
| return bindings::NativeValueTraitsStringAdapter(); |
| } |
| return bindings::NativeValueTraitsStringAdapter(v8_string); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLByteStringV2>> |
| : public NativeValueTraitsBase<IDLNullable<IDLByteStringV2>> { |
| static decltype(auto) NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValueTraits<IDLByteStringBaseV2< |
| bindings::IDLStringConvMode::kNullable>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLByteStringV2>> |
| : public NativeValueTraitsBase<IDLByteStringV2> { |
| static decltype(auto) NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return bindings::NativeValueTraitsStringAdapter(); |
| return NativeValueTraits<IDLByteStringV2>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| template <bindings::IDLStringConvMode mode> |
| struct NativeValueTraits<IDLStringBaseV2<mode>> |
| : public NativeValueTraitsBase<IDLStringBaseV2<mode>> { |
| // https://heycam.github.io/webidl/#es-DOMString |
| static bindings::NativeValueTraitsStringAdapter NativeValue( |
| v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsString()) |
| return bindings::NativeValueTraitsStringAdapter(value.As<v8::String>()); |
| if (value->IsInt32()) { |
| return bindings::NativeValueTraitsStringAdapter( |
| value.As<v8::Int32>()->Value()); |
| } |
| |
| if (mode == bindings::IDLStringConvMode::kNullable) { |
| if (value->IsNullOrUndefined()) |
| return bindings::NativeValueTraitsStringAdapter(); |
| } |
| if (mode == bindings::IDLStringConvMode::kTreatNullAsEmptyString) { |
| if (value->IsNull()) |
| return bindings::NativeValueTraitsStringAdapter(g_empty_string); |
| } |
| |
| v8::TryCatch try_catch(isolate); |
| v8::Local<v8::String> v8_string; |
| if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&v8_string)) { |
| exception_state.RethrowV8Exception(try_catch.Exception()); |
| return bindings::NativeValueTraitsStringAdapter(); |
| } |
| return bindings::NativeValueTraitsStringAdapter(v8_string); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLStringV2>> |
| : public NativeValueTraitsBase<IDLNullable<IDLStringV2>> { |
| static decltype(auto) NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValueTraits<IDLStringBaseV2< |
| bindings::IDLStringConvMode::kNullable>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLStringV2>> |
| : public NativeValueTraitsBase<IDLStringV2> { |
| static decltype(auto) NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return bindings::NativeValueTraitsStringAdapter(); |
| return NativeValueTraits<IDLStringV2>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| template <bindings::IDLStringConvMode mode> |
| struct NativeValueTraits<IDLUSVStringBaseV2<mode>> |
| : public NativeValueTraitsBase<IDLUSVStringBaseV2<mode>> { |
| // http://heycam.github.io/webidl/#es-USVString |
| static bindings::NativeValueTraitsStringAdapter NativeValue( |
| v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| String string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue( |
| isolate, value, exception_state); |
| if (exception_state.HadException()) |
| return bindings::NativeValueTraitsStringAdapter(); |
| |
| return bindings::NativeValueTraitsStringAdapter( |
| ReplaceUnmatchedSurrogates(string)); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLUSVStringV2>> |
| : public NativeValueTraitsBase<IDLNullable<IDLUSVStringV2>> { |
| static decltype(auto) NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValueTraits<IDLUSVStringBaseV2< |
| bindings::IDLStringConvMode::kNullable>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOptional<IDLUSVStringV2>> |
| : public NativeValueTraitsBase<IDLUSVStringV2> { |
| static decltype(auto) NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return bindings::NativeValueTraitsStringAdapter(); |
| return NativeValueTraits<IDLUSVStringV2>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| template <bindings::IDLStringConvMode mode> |
| struct NativeValueTraits<IDLStringStringContextTrustedHTMLBaseV2<mode>> |
| : public NativeValueTraitsBase< |
| IDLStringStringContextTrustedHTMLBaseV2<mode>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| if (TrustedHTML* trusted_html = |
| V8TrustedHTML::ToImplWithTypeCheck(isolate, value)) { |
| return trusted_html->toString(); |
| } |
| |
| auto&& string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue( |
| isolate, value, exception_state); |
| if (exception_state.HadException()) |
| return String(); |
| return TrustedTypesCheckForHTML(string, execution_context, exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT |
| NativeValueTraits<IDLNullable<IDLStringStringContextTrustedHTMLV2>> |
| : public NativeValueTraitsBase< |
| IDLNullable<IDLStringStringContextTrustedHTMLV2>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| return NativeValueTraits<IDLStringStringContextTrustedHTMLBaseV2< |
| bindings::IDLStringConvMode::kNullable>>:: |
| NativeValue(isolate, value, exception_state, execution_context); |
| } |
| }; |
| |
| template <bindings::IDLStringConvMode mode> |
| struct NativeValueTraits<IDLStringStringContextTrustedScriptBaseV2<mode>> |
| : public NativeValueTraitsBase< |
| IDLStringStringContextTrustedScriptBaseV2<mode>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| if (TrustedScript* trusted_script = |
| V8TrustedScript::ToImplWithTypeCheck(isolate, value)) { |
| return trusted_script->toString(); |
| } |
| |
| auto&& string = NativeValueTraits<IDLStringBaseV2<mode>>::NativeValue( |
| isolate, value, exception_state); |
| if (exception_state.HadException()) |
| return String(); |
| return TrustedTypesCheckForScript(string, execution_context, |
| exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT |
| NativeValueTraits<IDLNullable<IDLStringStringContextTrustedScriptV2>> |
| : public NativeValueTraitsBase< |
| IDLNullable<IDLStringStringContextTrustedScriptV2>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| return NativeValueTraits<IDLStringStringContextTrustedScriptBaseV2< |
| bindings::IDLStringConvMode::kNullable>>:: |
| NativeValue(isolate, value, exception_state, execution_context); |
| } |
| }; |
| |
| template <bindings::IDLStringConvMode mode> |
| struct NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBaseV2<mode>> |
| : public NativeValueTraitsBase< |
| IDLUSVStringStringContextTrustedScriptURLBaseV2<mode>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| if (TrustedScriptURL* trusted_script_url = |
| V8TrustedScriptURL::ToImplWithTypeCheck(isolate, value)) { |
| return trusted_script_url->toString(); |
| } |
| |
| auto&& string = NativeValueTraits<IDLUSVStringBaseV2<mode>>::NativeValue( |
| isolate, value, exception_state); |
| if (exception_state.HadException()) |
| return String(); |
| return TrustedTypesCheckForScriptURL(string, execution_context, |
| exception_state); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT |
| NativeValueTraits<IDLNullable<IDLUSVStringStringContextTrustedScriptURLV2>> |
| : public NativeValueTraitsBase< |
| IDLNullable<IDLUSVStringStringContextTrustedScriptURLV2>> { |
| static String NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state, |
| ExecutionContext* execution_context) { |
| return NativeValueTraits<IDLUSVStringStringContextTrustedScriptURLBaseV2< |
| bindings::IDLStringConvMode::kNullable>>:: |
| NativeValue(isolate, value, exception_state, execution_context); |
| } |
| }; |
| |
| // Buffer source types |
| template <> |
| struct CORE_EXPORT NativeValueTraits<DOMArrayBuffer> |
| : public NativeValueTraitsBase<DOMArrayBuffer*> { |
| static DOMArrayBuffer* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static DOMArrayBuffer* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<DOMArrayBuffer>> |
| : public NativeValueTraitsBase<DOMArrayBuffer*> { |
| static DOMArrayBuffer* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static DOMArrayBuffer* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| NotShared<T>, |
| typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> |
| : public NativeValueTraitsBase<NotShared<T>> { |
| static NotShared<T> NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static NotShared<T> ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<NotShared<T>>, |
| typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> |
| : public NativeValueTraitsBase<NotShared<T>> { |
| static NotShared<T> NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static NotShared<T> ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| MaybeShared<T>, |
| typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> |
| : public NativeValueTraitsBase<MaybeShared<T>> { |
| static MaybeShared<T> NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static MaybeShared<T> ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<MaybeShared<T>>, |
| typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> |
| : public NativeValueTraitsBase<MaybeShared<T>> { |
| static MaybeShared<T> NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static MaybeShared<T> ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t< |
| std::is_base_of<FlexibleArrayBufferView, T>::value>> |
| : public NativeValueTraitsBase<T> { |
| // FlexibleArrayBufferView must be used only as arguments. |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) = delete; |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<T>, |
| typename std::enable_if_t< |
| std::is_base_of<FlexibleArrayBufferView, T>::value>> |
| : public NativeValueTraitsBase<T> { |
| // FlexibleArrayBufferView must be used only as arguments. |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) = delete; |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| // object |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLObject> |
| : public NativeValueTraitsBase<IDLObject> { |
| static ScriptValue NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return ScriptValue(isolate, value); |
| exception_state.ThrowTypeError( |
| ExceptionMessages::FailedToConvertJSValue("object")); |
| return ScriptValue(); |
| } |
| |
| static ScriptValue ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return ScriptValue(isolate, value); |
| exception_state.ThrowTypeError( |
| ExceptionMessages::ArgumentNotOfType(argument_index, "object")); |
| return ScriptValue(); |
| } |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLObject>> |
| : public NativeValueTraitsBase<IDLNullable<IDLObject>> { |
| static ScriptValue NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return ScriptValue(isolate, value); |
| if (value->IsNullOrUndefined()) |
| return ScriptValue(isolate, v8::Null(isolate)); |
| exception_state.ThrowTypeError( |
| ExceptionMessages::FailedToConvertJSValue("object")); |
| return ScriptValue(); |
| } |
| |
| static ScriptValue ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return ScriptValue(isolate, value); |
| if (value->IsNullOrUndefined()) |
| return ScriptValue(isolate, v8::Null(isolate)); |
| exception_state.ThrowTypeError( |
| ExceptionMessages::ArgumentNotOfType(argument_index, "object")); |
| return ScriptValue(); |
| } |
| }; |
| |
| // Promise types |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLPromise> |
| : public NativeValueTraitsBase<IDLPromise> { |
| static ScriptPromise NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ScriptPromise::Cast(ScriptState::From(isolate->GetCurrentContext()), |
| value); |
| } |
| }; |
| |
| // IDLNullable<IDLPromise> must not be used. |
| template <> |
| struct NativeValueTraits<IDLNullable<IDLPromise>>; |
| |
| // Sequence types |
| template <typename T> |
| struct NativeValueTraits<IDLSequence<T>> |
| : public NativeValueTraitsBase<IDLSequence<T>> { |
| // Nondependent types need to be explicitly qualified to be accessible. |
| using typename NativeValueTraitsBase<IDLSequence<T>>::ImplType; |
| |
| // https://heycam.github.io/webidl/#es-sequence |
| static ImplType NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| // 1. If Type(V) is not Object, throw a TypeError. |
| if (!value->IsObject()) { |
| exception_state.ThrowTypeError( |
| "The provided value cannot be converted to a sequence."); |
| return ImplType(); |
| } |
| |
| ImplType result; |
| // TODO(https://crbug.com/715122): Checking for IsArray() may not be |
| // enough. Other engines also prefer regular array iteration over a custom |
| // @@iterator when the latter is defined, but it is not clear if this is a |
| // valid optimization. |
| if (value->IsArray()) { |
| ConvertSequenceFast(isolate, value.As<v8::Array>(), exception_state, |
| result); |
| } else { |
| // 2. Let method be ? GetMethod(V, @@iterator). |
| // 3. If method is undefined, throw a TypeError. |
| // 4. Return the result of creating a sequence from V and method. |
| auto script_iterator = ScriptIterator::FromIterable( |
| isolate, value.As<v8::Object>(), exception_state); |
| if (exception_state.HadException()) |
| return ImplType(); |
| if (script_iterator.IsNull()) { |
| // A null ScriptIterator with an empty |exception_state| means the |
| // object is lacking a callable @@iterator property. |
| exception_state.ThrowTypeError( |
| "The object must have a callable @@iterator property."); |
| return ImplType(); |
| } |
| ConvertSequenceSlow(isolate, std::move(script_iterator), exception_state, |
| result); |
| } |
| |
| if (exception_state.HadException()) |
| return ImplType(); |
| return result; |
| } |
| |
| // https://heycam.github.io/webidl/#es-sequence |
| // This is a special case, used when converting an IDL union that contains a |
| // sequence or frozen array type. |
| static ImplType NativeValue(v8::Isolate* isolate, |
| ScriptIterator script_iterator, |
| ExceptionState& exception_state) { |
| DCHECK(!script_iterator.IsNull()); |
| ImplType result; |
| ConvertSequenceSlow(isolate, std::move(script_iterator), exception_state, |
| result); |
| return result; |
| } |
| |
| private: |
| // Fast case: we're interating over an Array that adheres to |
| // %ArrayIteratorPrototype%'s protocol. |
| static void ConvertSequenceFast(v8::Isolate* isolate, |
| v8::Local<v8::Array> v8_array, |
| ExceptionState& exception_state, |
| ImplType& result) { |
| const uint32_t length = v8_array->Length(); |
| if (length > ImplType::MaxCapacity()) { |
| exception_state.ThrowRangeError("Array length exceeds supported limit."); |
| return; |
| } |
| result.ReserveInitialCapacity(length); |
| v8::TryCatch block(isolate); |
| // Array length may change if array is mutated during iteration. |
| for (uint32_t i = 0; i < v8_array->Length(); ++i) { |
| v8::Local<v8::Value> element; |
| if (!v8_array->Get(isolate->GetCurrentContext(), i).ToLocal(&element)) { |
| exception_state.RethrowV8Exception(block.Exception()); |
| return; |
| } |
| result.push_back( |
| NativeValueTraits<T>::NativeValue(isolate, element, exception_state)); |
| if (exception_state.HadException()) |
| return; |
| } |
| } |
| |
| // Slow case: follow WebIDL's "Creating a sequence from an iterable" steps to |
| // iterate through each element. |
| static void ConvertSequenceSlow(v8::Isolate* isolate, |
| ScriptIterator script_iterator, |
| ExceptionState& exception_state, |
| ImplType& result) { |
| // https://heycam.github.io/webidl/#create-sequence-from-iterable |
| // 2. Initialize i to be 0. |
| // 3. Repeat: |
| ExecutionContext* execution_context = |
| ToExecutionContext(isolate->GetCurrentContext()); |
| while (script_iterator.Next(execution_context, exception_state)) { |
| // 3.1. Let next be ? IteratorStep(iter). |
| // 3.2. If next is false, then return an IDL sequence value of type |
| // sequence<T> of length i, where the value of the element at index |
| // j is Sj. |
| // 3.3. Let nextItem be ? IteratorValue(next). |
| if (exception_state.HadException()) |
| return; |
| |
| // The value should already be non-empty, as guaranteed by the call to |
| // Next() and the |exception_state| check above. |
| v8::Local<v8::Value> element = |
| script_iterator.GetValue().ToLocalChecked(); |
| DCHECK(!element.IsEmpty()); |
| |
| // 3.4. Initialize Si to the result of converting nextItem to an IDL |
| // value of type T. |
| // 3.5. Set i to i + 1. |
| result.push_back( |
| NativeValueTraits<T>::NativeValue(isolate, element, exception_state)); |
| if (exception_state.HadException()) |
| return; |
| } |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits<IDLOptional<IDLSequence<T>>> |
| : public NativeValueTraitsBase<IDLSequence<T>> { |
| static typename NativeValueTraits<IDLSequence<T>>::ImplType NativeValue( |
| v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return {}; |
| return NativeValueTraits<IDLSequence<T>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| }; |
| |
| // Record types |
| template <typename K, typename V> |
| struct NativeValueTraits<IDLRecord<K, V>> |
| : public NativeValueTraitsBase<IDLRecord<K, V>> { |
| // Nondependent types need to be explicitly qualified to be accessible. |
| using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType; |
| |
| // Converts a JavaScript value |O| to an IDL record<K, V> value. In C++, a |
| // record is represented as a Vector<std::pair<k, v>> (or a HeapVector if |
| // necessary). See https://heycam.github.io/webidl/#es-record. |
| static ImplType NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> v8_value, |
| ExceptionState& exception_state) { |
| v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| |
| // "1. If Type(O) is not Object, throw a TypeError." |
| if (!v8_value->IsObject()) { |
| exception_state.ThrowTypeError( |
| "Only objects can be converted to record<K,V> types"); |
| return ImplType(); |
| } |
| v8::Local<v8::Object> v8_object = v8::Local<v8::Object>::Cast(v8_value); |
| v8::TryCatch block(isolate); |
| |
| // "3. Let keys be ? O.[[OwnPropertyKeys]]()." |
| v8::Local<v8::Array> keys; |
| // While we could pass v8::ONLY_ENUMERABLE below, doing so breaks |
| // web-platform-tests' headers-record.html. It might be worthwhile to try |
| // changing the test. |
| if (!v8_object |
| ->GetOwnPropertyNames(context, |
| static_cast<v8::PropertyFilter>( |
| v8::PropertyFilter::ALL_PROPERTIES), |
| v8::KeyConversionMode::kConvertToString) |
| .ToLocal(&keys)) { |
| exception_state.RethrowV8Exception(block.Exception()); |
| return ImplType(); |
| } |
| if (keys->Length() > ImplType::MaxCapacity()) { |
| exception_state.ThrowRangeError("Array length exceeds supported limit."); |
| return ImplType(); |
| } |
| |
| // "2. Let result be a new empty instance of record<K, V>." |
| ImplType result; |
| result.ReserveInitialCapacity(keys->Length()); |
| |
| // The conversion algorithm needs a data structure with fast insertion at |
| // the end while at the same time requiring fast checks for previous insert |
| // of a given key. |seenKeys| is a key/position in |result| map that aids in |
| // the latter part. |
| HashMap<String, uint32_t> seen_keys; |
| |
| for (uint32_t i = 0; i < keys->Length(); ++i) { |
| // "4. Repeat, for each element key of keys in List order:" |
| v8::Local<v8::Value> key; |
| if (!keys->Get(context, i).ToLocal(&key)) { |
| exception_state.RethrowV8Exception(block.Exception()); |
| return ImplType(); |
| } |
| |
| // "4.1. Let desc be ? O.[[GetOwnProperty]](key)." |
| v8::Local<v8::Value> desc; |
| if (!v8_object->GetOwnPropertyDescriptor(context, key.As<v8::Name>()) |
| .ToLocal(&desc)) { |
| exception_state.RethrowV8Exception(block.Exception()); |
| return ImplType(); |
| } |
| |
| // "4.2. If desc is not undefined and desc.[[Enumerable]] is true:" |
| // We can call ToLocalChecked() and ToChecked() here because |
| // GetOwnPropertyDescriptor is responsible for catching any exceptions |
| // and failures, and if we got to this point of the code we have a proper |
| // object that was not created by a user. |
| if (desc->IsUndefined()) |
| continue; |
| DCHECK(desc->IsObject()); |
| v8::Local<v8::Value> enumerable = |
| v8::Local<v8::Object>::Cast(desc) |
| ->Get(context, V8AtomicString(isolate, "enumerable")) |
| .ToLocalChecked(); |
| if (!enumerable->BooleanValue(isolate)) |
| continue; |
| |
| // "4.2.1. Let typedKey be key converted to an IDL value of type K." |
| String typed_key = |
| NativeValueTraits<K>::NativeValue(isolate, key, exception_state); |
| if (exception_state.HadException()) |
| return ImplType(); |
| |
| // "4.2.2. Let value be ? Get(O, key)." |
| v8::Local<v8::Value> value; |
| if (!v8_object->Get(context, key).ToLocal(&value)) { |
| exception_state.RethrowV8Exception(block.Exception()); |
| return ImplType(); |
| } |
| |
| // "4.2.3. Let typedValue be value converted to an IDL value of type V." |
| typename ImplType::ValueType::second_type typed_value = |
| NativeValueTraits<V>::NativeValue(isolate, value, exception_state); |
| if (exception_state.HadException()) |
| return ImplType(); |
| |
| if (seen_keys.Contains(typed_key)) { |
| // "4.2.4. If typedKey is already a key in result, set its value to |
| // typedValue. |
| // Note: This can happen when O is a proxy object." |
| const uint32_t pos = seen_keys.at(typed_key); |
| result[pos].second = std::move(typed_value); |
| } else { |
| // "4.2.5. Otherwise, append to result a mapping (typedKey, |
| // typedValue)." |
| // Note we can take this shortcut because we are always appending. |
| const uint32_t pos = result.size(); |
| seen_keys.Set(typed_key, pos); |
| result.UncheckedAppend( |
| std::make_pair(std::move(typed_key), std::move(typed_value))); |
| } |
| } |
| // "5. Return result." |
| return result; |
| } |
| }; |
| |
| // Callback function types |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t<std::is_base_of<CallbackFunctionBase, T>::value>> |
| : public NativeValueTraitsBase<T*> { |
| static T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsFunction()) |
| return T::Create(value.As<v8::Function>()); |
| exception_state.ThrowTypeError("The given value is not a function."); |
| return nullptr; |
| } |
| |
| static T* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsFunction()) |
| return T::Create(value.As<v8::Function>()); |
| exception_state.ThrowTypeError( |
| ExceptionMessages::ArgumentNotOfType(argument_index, "Function")); |
| return nullptr; |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<T>, |
| typename std::enable_if_t<std::is_base_of<CallbackFunctionBase, T>::value>> |
| : public NativeValueTraitsBase<IDLNullable<T>> { |
| static T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsFunction()) |
| return T::Create(value.As<v8::Function>()); |
| if (value->IsNullOrUndefined()) |
| return nullptr; |
| exception_state.ThrowTypeError("The given value is not a function."); |
| return nullptr; |
| } |
| |
| static T* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsFunction()) |
| return T::Create(value.As<v8::Function>()); |
| if (value->IsNullOrUndefined()) |
| return nullptr; |
| exception_state.ThrowTypeError( |
| ExceptionMessages::ArgumentNotOfType(argument_index, "Function")); |
| return nullptr; |
| } |
| }; |
| |
| // Callback interface types |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t<std::is_base_of<CallbackInterfaceBase, T>::value>> |
| : public NativeValueTraitsBase<T*> { |
| static T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return T::Create(value.As<v8::Object>()); |
| exception_state.ThrowTypeError("The given value is not an object."); |
| return nullptr; |
| } |
| |
| static T* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return T::Create(value.As<v8::Object>()); |
| exception_state.ThrowTypeError( |
| ExceptionMessages::ArgumentNotOfType(argument_index, "Object")); |
| return nullptr; |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<T>, |
| typename std::enable_if_t<std::is_base_of<CallbackInterfaceBase, T>::value>> |
| : public NativeValueTraitsBase<IDLNullable<T>> { |
| static T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return T::Create(value.As<v8::Object>()); |
| if (value->IsNullOrUndefined()) |
| return nullptr; |
| exception_state.ThrowTypeError("The given value is not an object."); |
| return nullptr; |
| } |
| |
| static T* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsObject()) |
| return T::Create(value.As<v8::Object>()); |
| if (value->IsNullOrUndefined()) |
| return nullptr; |
| exception_state.ThrowTypeError( |
| ExceptionMessages::ArgumentNotOfType(argument_index, "Object")); |
| return nullptr; |
| } |
| }; |
| |
| // Dictionary types |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t< |
| std::is_base_of<bindings::DictionaryBase, T>::value>> |
| : public NativeValueTraitsBase<T*> { |
| static T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return T::Create(isolate, value, exception_state); |
| } |
| }; |
| |
| // We don't support nullable dictionary types for the time being since it's |
| // quite confusing. |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<T>, |
| typename std::enable_if_t< |
| std::is_base_of<bindings::DictionaryBase, T>::value>>; |
| |
| // Migration Adapters: Nullable dictionary types generated by the old bindings |
| // generator. |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<T>, |
| typename std::enable_if_t<std::is_base_of<IDLDictionaryBase, T>::value>>; |
| |
| // Enumeration types |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t< |
| std::is_base_of<bindings::EnumerationBase, T>::value>> |
| : public NativeValueTraitsBase<T> { |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return T::Create(isolate, value, exception_state); |
| } |
| }; |
| |
| // Interface types |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t<std::is_base_of<ScriptWrappable, T>::value>> |
| : public NativeValueTraitsBase<T*> { |
| static inline T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| const WrapperTypeInfo* wrapper_type_info = T::GetStaticWrapperTypeInfo(); |
| if (V8PerIsolateData::From(isolate)->HasInstance(wrapper_type_info, value)) |
| return ToScriptWrappable(value.As<v8::Object>())->template ToImpl<T>(); |
| |
| bindings::NativeValueTraitsInterfaceNotOfType(wrapper_type_info, |
| exception_state); |
| return nullptr; |
| } |
| |
| static inline T* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| const WrapperTypeInfo* wrapper_type_info = T::GetStaticWrapperTypeInfo(); |
| if (V8PerIsolateData::From(isolate)->HasInstance(wrapper_type_info, value)) |
| return ToScriptWrappable(value.As<v8::Object>())->template ToImpl<T>(); |
| |
| bindings::NativeValueTraitsInterfaceNotOfType( |
| wrapper_type_info, argument_index, exception_state); |
| return nullptr; |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| IDLNullable<T>, |
| typename std::enable_if_t<std::is_base_of<ScriptWrappable, T>::value>> |
| : public NativeValueTraitsBase<IDLNullable<T>> { |
| static inline T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| const WrapperTypeInfo* wrapper_type_info = T::GetStaticWrapperTypeInfo(); |
| if (V8PerIsolateData::From(isolate)->HasInstance(wrapper_type_info, value)) |
| return ToScriptWrappable(value.As<v8::Object>())->template ToImpl<T>(); |
| |
| if (value->IsNullOrUndefined()) |
| return nullptr; |
| |
| bindings::NativeValueTraitsInterfaceNotOfType(wrapper_type_info, |
| exception_state); |
| return nullptr; |
| } |
| |
| static inline T* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| const WrapperTypeInfo* wrapper_type_info = T::GetStaticWrapperTypeInfo(); |
| if (V8PerIsolateData::From(isolate)->HasInstance(wrapper_type_info, value)) |
| return ToScriptWrappable(value.As<v8::Object>())->template ToImpl<T>(); |
| |
| if (value->IsNullOrUndefined()) |
| return nullptr; |
| |
| bindings::NativeValueTraitsInterfaceNotOfType( |
| wrapper_type_info, argument_index, exception_state); |
| return nullptr; |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits< |
| T, |
| typename std::enable_if_t<std::is_base_of<bindings::UnionBase, T>::value>> |
| : public NativeValueTraitsBase<T*> { |
| static T* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return T::Create(isolate, value, exception_state); |
| } |
| }; |
| |
| // Migration Adapters: union types generated by the old bindings generator. |
| template <typename T> |
| struct NativeValueTraits<IDLUnionNotINT<T>> : public NativeValueTraitsBase<T> { |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| T impl; |
| V8TypeOf<T>::Type::ToImpl(isolate, value, impl, |
| UnionTypeConversionMode::kNotNullable, |
| exception_state); |
| return impl; |
| } |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValue(isolate, value, exception_state); |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits<IDLUnionINT<T>> : public NativeValueTraitsBase<T> { |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| T impl; |
| V8TypeOf<T>::Type::ToImpl(isolate, value, impl, |
| UnionTypeConversionMode::kNullable, |
| exception_state); |
| return impl; |
| } |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValue(isolate, value, exception_state); |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits<IDLNullable<IDLUnionNotINT<T>>> |
| : public NativeValueTraitsBase<T> { |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsNullOrUndefined()) |
| return T(); |
| return NativeValueTraits<IDLUnionNotINT<T>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValue(isolate, value, exception_state); |
| } |
| }; |
| |
| // IDLNullable<IDLUnionINT<T>> must not be used. |
| template <typename T> |
| struct NativeValueTraits<IDLNullable<IDLUnionINT<T>>>; |
| |
| template <typename T> |
| struct NativeValueTraits<IDLOptional<IDLUnionNotINT<T>>> |
| : public NativeValueTraitsBase<T> { |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return T(); |
| return NativeValueTraits<IDLUnionNotINT<T>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValue(isolate, value, exception_state); |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits<IDLOptional<IDLUnionINT<T>>> |
| : public NativeValueTraitsBase<T> { |
| static T NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValueTraits<IDLUnionINT<T>>::NativeValue(isolate, value, |
| exception_state); |
| } |
| |
| static T ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return NativeValue(isolate, value, exception_state); |
| } |
| }; |
| |
| // Nullable types |
| template <typename InnerType> |
| struct NativeValueTraits< |
| IDLNullable<InnerType>, |
| typename std::enable_if_t<!NativeValueTraits<InnerType>::has_null_value>> |
| : public NativeValueTraitsBase<IDLNullable<InnerType>> { |
| // https://heycam.github.io/webidl/#es-nullable-type |
| using ImplType = |
| base::Optional<typename NativeValueTraits<InnerType>::ImplType>; |
| |
| static ImplType NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsNullOrUndefined()) |
| return base::nullopt; |
| return NativeValueTraits<InnerType>::NativeValue(isolate, value, |
| exception_state); |
| } |
| |
| static ImplType ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsNullOrUndefined()) |
| return base::nullopt; |
| return NativeValueTraits<InnerType>::ArgumentValue(isolate, argument_index, |
| value, exception_state); |
| } |
| }; |
| |
| // IDLNullable<IDLNullable<T>> must not be used. |
| template <typename T> |
| struct NativeValueTraits<IDLNullable<IDLNullable<T>>>; |
| |
| // Optional types |
| template <typename T> |
| struct NativeValueTraits<IDLOptional<T>, |
| typename std::enable_if_t<std::is_arithmetic< |
| typename NativeValueTraits<T>::ImplType>::value>> |
| : public NativeValueTraitsBase<typename NativeValueTraits<T>::ImplType> { |
| using ImplType = typename NativeValueTraits<T>::ImplType; |
| |
| static ImplType NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| // Just let ES undefined to be converted into 0. |
| return NativeValueTraits<T>::NativeValue(isolate, value, exception_state); |
| } |
| |
| static ImplType ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| // Just let ES undefined to be converted into 0. |
| return NativeValueTraits<T>::ArgumentValue(isolate, argument_index, value, |
| exception_state); |
| } |
| }; |
| |
| template <typename T> |
| struct NativeValueTraits<IDLOptional<T>, |
| typename std::enable_if_t<std::is_pointer< |
| typename NativeValueTraits<T>::ImplType>::value>> |
| : public NativeValueTraitsBase<typename NativeValueTraits<T>::ImplType> { |
| using ImplType = typename NativeValueTraits<T>::ImplType; |
| |
| static ImplType NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return nullptr; |
| return NativeValueTraits<T>::NativeValue(isolate, value, exception_state); |
| } |
| |
| static ImplType ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| if (value->IsUndefined()) |
| return nullptr; |
| return NativeValueTraits<T>::ArgumentValue(isolate, argument_index, value, |
| exception_state); |
| } |
| }; |
| |
| // Date |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLDate> |
| : public NativeValueTraitsBase<IDLDate> { |
| // IDLDate must be always used as IDLNullable<IDLDate>. |
| static base::Optional<base::Time> NativeValue( |
| v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) = delete; |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<IDLDate>> |
| : public NativeValueTraitsBase<IDLNullable<IDLDate>> { |
| static base::Optional<base::Time> NativeValue( |
| v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state) { |
| return ToCoreNullableDate(isolate, value, exception_state); |
| } |
| }; |
| |
| // EventHandler |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLEventHandler> |
| : public NativeValueTraitsBase<IDLEventHandler> { |
| static EventListener* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOnBeforeUnloadEventHandler> |
| : public NativeValueTraitsBase<IDLOnBeforeUnloadEventHandler> { |
| static EventListener* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLOnErrorEventHandler> |
| : public NativeValueTraitsBase<IDLOnErrorEventHandler> { |
| static EventListener* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| // EventHandler and its family are nullable, so IDLNullable<IDLEventHandler> |
| // must not be used. |
| template <> |
| struct NativeValueTraits<IDLNullable<IDLEventHandler>>; |
| template <> |
| struct NativeValueTraits<IDLNullable<IDLOnBeforeUnloadEventHandler>>; |
| template <> |
| struct NativeValueTraits<IDLNullable<IDLOnErrorEventHandler>>; |
| |
| // Workaround https://crbug.com/345529 |
| template <> |
| struct CORE_EXPORT NativeValueTraits<XPathNSResolver> |
| : public NativeValueTraitsBase<XPathNSResolver*> { |
| static XPathNSResolver* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static XPathNSResolver* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| template <> |
| struct CORE_EXPORT NativeValueTraits<IDLNullable<XPathNSResolver>> |
| : public NativeValueTraitsBase<IDLNullable<XPathNSResolver>> { |
| static XPathNSResolver* NativeValue(v8::Isolate* isolate, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| |
| static XPathNSResolver* ArgumentValue(v8::Isolate* isolate, |
| int argument_index, |
| v8::Local<v8::Value> value, |
| ExceptionState& exception_state); |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_IMPL_H_ |