blob: d4a62780e01eef6522ed409279628c0d65cbc7be [file] [log] [blame]
// Copyright 2020 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.
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_big_int_64_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_big_uint_64_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_data_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_float32_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_float64_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_int16_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_int32_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_int8_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint16_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint32_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_clamped_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_xpath_ns_resolver.h"
#include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
namespace blink {
namespace bindings {
static_assert(static_cast<IntegerConversionConfiguration>(
IDLIntegerConvMode::kDefault) == kNormalConversion,
"IDLIntegerConvMode::kDefault == kNormalConversion");
static_assert(static_cast<IntegerConversionConfiguration>(
IDLIntegerConvMode::kClamp) == kClamp,
"IDLIntegerConvMode::kClamp == kClamp");
static_assert(static_cast<IntegerConversionConfiguration>(
IDLIntegerConvMode::kEnforceRange) == kEnforceRange,
"IDLIntegerConvMode::kEnforceRange == kEnforceRange");
void NativeValueTraitsInterfaceNotOfType(
const WrapperTypeInfo* wrapper_type_info,
ExceptionState& exception_state) {
exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
wrapper_type_info->interface_name));
}
void NativeValueTraitsInterfaceNotOfType(
const WrapperTypeInfo* wrapper_type_info,
int argument_index,
ExceptionState& exception_state) {
exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
argument_index, wrapper_type_info->interface_name));
}
} // namespace bindings
// Buffer source types
namespace {
enum class IDLBufferSourceTypeConvMode {
kDefault,
kNullable,
};
template <
typename T,
typename V8T,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
T* NativeValueTraitsBufferSourcePtrNativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
T* native_value = V8T::ToImplWithTypeCheck(isolate, value);
if (native_value)
return native_value;
if (mode == IDLBufferSourceTypeConvMode::kNullable) {
if (value->IsNullOrUndefined())
return nullptr;
}
exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
V8T::GetWrapperTypeInfo()->interface_name));
return nullptr;
}
template <
typename T,
typename V8T,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
T* NativeValueTraitsBufferSourcePtrArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
T* native_value = V8T::ToImplWithTypeCheck(isolate, value);
if (native_value)
return native_value;
if (mode == IDLBufferSourceTypeConvMode::kNullable) {
if (value->IsNullOrUndefined())
return nullptr;
}
exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
argument_index, V8T::GetWrapperTypeInfo()->interface_name));
return nullptr;
}
template <
typename T,
typename V8T,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
NotShared<T> NativeValueTraitsBufferSourceNotSharedNativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
T* native_value = NativeValueTraitsBufferSourcePtrNativeValue<T, V8T, mode>(
isolate, value, exception_state);
if (!native_value)
return NotShared<T>();
if (native_value->IsShared()) {
exception_state.ThrowTypeError(
"The provided ArrayBufferView value must not be shared.");
return NotShared<T>();
}
return NotShared<T>(native_value);
}
template <
typename T,
typename V8T,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
NotShared<T> NativeValueTraitsBufferSourceNotSharedArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
T* native_value = NativeValueTraitsBufferSourcePtrArgumentValue<T, V8T, mode>(
isolate, argument_index, value, exception_state);
if (!native_value)
return NotShared<T>();
if (native_value->IsShared()) {
exception_state.ThrowTypeError(
"The provided ArrayBufferView value must not be shared.");
return NotShared<T>();
}
return NotShared<T>(native_value);
}
template <
typename T,
typename V8T,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
MaybeShared<T> NativeValueTraitsBufferSourceMaybeSharedNativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return MaybeShared<T>(
NativeValueTraitsBufferSourcePtrNativeValue<T, V8T, mode>(
isolate, value, exception_state));
}
template <
typename T,
typename V8T,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
MaybeShared<T> NativeValueTraitsBufferSourceMaybeSharedArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return MaybeShared<T>(
NativeValueTraitsBufferSourcePtrArgumentValue<T, V8T, mode>(
isolate, argument_index, value, exception_state));
}
template <
typename T,
typename V8T,
typename FLEXIBLE,
IDLBufferSourceTypeConvMode mode = IDLBufferSourceTypeConvMode::kDefault>
FLEXIBLE NativeValueTraitsBufferSourceFlexibleArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (V8T::HasInstance(isolate, value))
return FLEXIBLE(value.As<v8::ArrayBufferView>());
if (mode == IDLBufferSourceTypeConvMode::kNullable) {
if (value->IsNullOrUndefined())
return FLEXIBLE();
}
exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
argument_index, V8T::GetWrapperTypeInfo()->interface_name));
return FLEXIBLE();
}
} // namespace
DOMArrayBuffer* NativeValueTraits<DOMArrayBuffer>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return NativeValueTraitsBufferSourcePtrNativeValue<DOMArrayBuffer,
V8ArrayBuffer>(
isolate, value, exception_state);
}
DOMArrayBuffer* NativeValueTraits<DOMArrayBuffer>::ArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return NativeValueTraitsBufferSourcePtrArgumentValue<DOMArrayBuffer,
V8ArrayBuffer>(
isolate, argument_index, value, exception_state);
}
DOMArrayBuffer* NativeValueTraits<IDLNullable<DOMArrayBuffer>>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return NativeValueTraitsBufferSourcePtrNativeValue<
DOMArrayBuffer, V8ArrayBuffer, IDLBufferSourceTypeConvMode::kNullable>(
isolate, value, exception_state);
}
DOMArrayBuffer* NativeValueTraits<IDLNullable<DOMArrayBuffer>>::ArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return NativeValueTraitsBufferSourcePtrArgumentValue<
DOMArrayBuffer, V8ArrayBuffer, IDLBufferSourceTypeConvMode::kNullable>(
isolate, argument_index, value, exception_state);
}
#define DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_NOT_SHARED(T, V8T) \
template <> \
CORE_EXPORT NotShared<T> NativeValueTraits<NotShared<T>>::NativeValue( \
v8::Isolate* isolate, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceNotSharedNativeValue<T, V8T>( \
isolate, value, exception_state); \
} \
template <> \
CORE_EXPORT NotShared<T> NativeValueTraits<NotShared<T>>::ArgumentValue( \
v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceNotSharedArgumentValue<T, V8T>( \
isolate, argument_index, value, exception_state); \
} \
template <> \
CORE_EXPORT NotShared<T> \
NativeValueTraits<IDLNullable<NotShared<T>>>::NativeValue( \
v8::Isolate* isolate, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceNotSharedNativeValue< \
T, V8T, IDLBufferSourceTypeConvMode::kNullable>(isolate, value, \
exception_state); \
} \
template <> \
CORE_EXPORT NotShared<T> \
NativeValueTraits<IDLNullable<NotShared<T>>>::ArgumentValue( \
v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceNotSharedArgumentValue< \
T, V8T, IDLBufferSourceTypeConvMode::kNullable>( \
isolate, argument_index, value, exception_state); \
}
#define DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_MAYBE_SHARED(T, V8T) \
template <> \
CORE_EXPORT MaybeShared<T> NativeValueTraits<MaybeShared<T>>::NativeValue( \
v8::Isolate* isolate, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceMaybeSharedNativeValue<T, V8T>( \
isolate, value, exception_state); \
} \
template <> \
CORE_EXPORT MaybeShared<T> NativeValueTraits<MaybeShared<T>>::ArgumentValue( \
v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceMaybeSharedArgumentValue<T, V8T>( \
isolate, argument_index, value, exception_state); \
} \
template <> \
CORE_EXPORT MaybeShared<T> \
NativeValueTraits<IDLNullable<MaybeShared<T>>>::NativeValue( \
v8::Isolate* isolate, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceMaybeSharedNativeValue< \
T, V8T, IDLBufferSourceTypeConvMode::kNullable>(isolate, value, \
exception_state); \
} \
template <> \
CORE_EXPORT MaybeShared<T> \
NativeValueTraits<IDLNullable<MaybeShared<T>>>::ArgumentValue( \
v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceMaybeSharedArgumentValue< \
T, V8T, IDLBufferSourceTypeConvMode::kNullable>( \
isolate, argument_index, value, exception_state); \
}
#define DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_FLEXIBLE(T, V8T, \
FLEXIBLE) \
template <> \
CORE_EXPORT FLEXIBLE NativeValueTraits<FLEXIBLE>::ArgumentValue( \
v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceFlexibleArgumentValue<T, V8T, \
FLEXIBLE>( \
isolate, argument_index, value, exception_state); \
} \
template <> \
CORE_EXPORT FLEXIBLE \
NativeValueTraits<IDLNullable<FLEXIBLE>>::ArgumentValue( \
v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, \
ExceptionState& exception_state) { \
return NativeValueTraitsBufferSourceFlexibleArgumentValue< \
T, V8T, FLEXIBLE, IDLBufferSourceTypeConvMode::kNullable>( \
isolate, argument_index, value, exception_state); \
}
#define DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(T) \
DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_NOT_SHARED(DOM##T, V8##T) \
DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_MAYBE_SHARED(DOM##T, V8##T) \
DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_FLEXIBLE(DOM##T, V8##T, \
Flexible##T)
#define DEFINE_NATIVE_VALUE_TRAITS_DATA_VIEW(T) \
DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_NOT_SHARED(DOM##T, V8##T) \
DEFINE_NATIVE_VALUE_TRAITS_BUFFER_SOURCE_TYPE_MAYBE_SHARED(DOM##T, V8##T)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(ArrayBufferView)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Int8Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Int16Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Int32Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint8Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint8ClampedArray)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint16Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Uint32Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(BigInt64Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(BigUint64Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Float32Array)
DEFINE_NATIVE_VALUE_TRAITS_TYPED_ARRAY(Float64Array)
DEFINE_NATIVE_VALUE_TRAITS_DATA_VIEW(DataView)
// EventHandler
EventListener* NativeValueTraits<IDLEventHandler>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return JSEventHandler::CreateOrNull(
value, JSEventHandler::HandlerType::kEventHandler);
}
EventListener* NativeValueTraits<IDLOnBeforeUnloadEventHandler>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return JSEventHandler::CreateOrNull(
value, JSEventHandler::HandlerType::kOnBeforeUnloadEventHandler);
}
EventListener* NativeValueTraits<IDLOnErrorEventHandler>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return JSEventHandler::CreateOrNull(
value, JSEventHandler::HandlerType::kOnErrorEventHandler);
}
// Workaround https://crbug.com/345529
XPathNSResolver* NativeValueTraits<XPathNSResolver>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (XPathNSResolver* xpath_ns_resolver =
V8XPathNSResolver::ToImplWithTypeCheck(isolate, value)) {
return xpath_ns_resolver;
}
if (value->IsObject()) {
ScriptState* script_state = ScriptState::From(isolate->GetCurrentContext());
return MakeGarbageCollected<V8CustomXPathNSResolver>(
script_state, value.As<v8::Object>());
}
exception_state.ThrowTypeError(
ExceptionMessages::FailedToConvertJSValue("XPathNSResolver"));
return nullptr;
}
XPathNSResolver* NativeValueTraits<XPathNSResolver>::ArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (XPathNSResolver* xpath_ns_resolver =
V8XPathNSResolver::ToImplWithTypeCheck(isolate, value)) {
return xpath_ns_resolver;
}
if (value->IsObject()) {
ScriptState* script_state = ScriptState::From(isolate->GetCurrentContext());
return MakeGarbageCollected<V8CustomXPathNSResolver>(
script_state, value.As<v8::Object>());
}
exception_state.ThrowTypeError(
ExceptionMessages::ArgumentNotOfType(argument_index, "XPathNSResolver"));
return nullptr;
}
XPathNSResolver* NativeValueTraits<IDLNullable<XPathNSResolver>>::NativeValue(
v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (XPathNSResolver* xpath_ns_resolver =
V8XPathNSResolver::ToImplWithTypeCheck(isolate, value)) {
return xpath_ns_resolver;
}
if (value->IsObject()) {
ScriptState* script_state = ScriptState::From(isolate->GetCurrentContext());
return MakeGarbageCollected<V8CustomXPathNSResolver>(
script_state, value.As<v8::Object>());
}
if (value->IsNullOrUndefined())
return nullptr;
exception_state.ThrowTypeError(
ExceptionMessages::FailedToConvertJSValue("XPathNSResolver"));
return nullptr;
}
XPathNSResolver* NativeValueTraits<IDLNullable<XPathNSResolver>>::ArgumentValue(
v8::Isolate* isolate,
int argument_index,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
if (XPathNSResolver* xpath_ns_resolver =
V8XPathNSResolver::ToImplWithTypeCheck(isolate, value)) {
return xpath_ns_resolver;
}
if (value->IsObject()) {
ScriptState* script_state = ScriptState::From(isolate->GetCurrentContext());
return MakeGarbageCollected<V8CustomXPathNSResolver>(
script_state, value.As<v8::Object>());
}
if (value->IsNullOrUndefined())
return nullptr;
exception_state.ThrowTypeError(
ExceptionMessages::ArgumentNotOfType(argument_index, "XPathNSResolver"));
return nullptr;
}
} // namespace blink