| {% extends 'interface_base.cpp.tmpl' %} |
| |
| {% set has_prepare_prototype_and_interface_object = |
| unscopables or has_conditional_attributes_on_prototype or |
| methods | conditionally_exposed(is_partial) %} |
| {% set prepare_prototype_and_interface_object_func = |
| '%s::preparePrototypeAndInterfaceObject' % v8_class |
| if has_prepare_prototype_and_interface_object |
| else 'nullptr' %} |
| |
| |
| {##############################################################################} |
| {% block indexed_property_getter %} |
| {% if indexed_property_getter and not indexed_property_getter.is_custom %} |
| {% set getter = indexed_property_getter %} |
| static void indexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| {% if getter.is_raises_exception %} |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::IndexedGetterContext, "{{interface_name}}"); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| |
| // We assume that all the implementations support length() method, although |
| // the spec doesn't require that length() must exist. It's okay that |
| // the interface does not have length attribute as long as the |
| // implementation supports length() member function. |
| if (index >= impl->length()) |
| return; // Returns undefined due to out-of-range. |
| |
| {% set getter_name = getter.name or 'anonymousIndexedGetter' %} |
| {% set getter_arguments = ['index'] %} |
| {% if getter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% set getter_arguments = ['scriptState'] + getter_arguments %} |
| {% endif %} |
| {% if getter.is_raises_exception %} |
| {% set getter_arguments = getter_arguments + ['exceptionState'] %} |
| {% endif %} |
| {{getter.cpp_type}} result = impl->{{getter_name}}({{getter_arguments | join(', ')}}); |
| {{getter.v8_set_return_value}}; |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block indexed_property_getter_callback %} |
| {% if indexed_property_getter or named_property_getter %} |
| {% set getter = indexed_property_getter or named_property_getter %} |
| void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| {% if indexed_property_getter %} |
| |
| {% if getter.is_custom %} |
| {{v8_class}}::indexedPropertyGetterCustom(index, info); |
| {% else %} |
| {{cpp_class}}V8Internal::indexedPropertyGetter(index, info); |
| {% endif %} |
| |
| {% else %}{# otherwise, named property #} |
| |
| const AtomicString& propertyName = AtomicString::number(index); |
| |
| {% if getter.is_custom %} |
| {{v8_class}}::namedPropertyGetterCustom(propertyName, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertyGetter(propertyName, info); |
| {% endif %} |
| |
| {% endif %}{# indexed_property_getter #} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block indexed_property_setter %} |
| {% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} |
| {% if indexed_property_setter and not indexed_property_setter.is_custom %} |
| {% set setter = indexed_property_setter %} |
| static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| {% if setter.has_exception_state %} |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::IndexedSetterContext, "{{interface_name}}"); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| {{v8_value_to_local_cpp_value(setter) | indent}} |
| {% if setter.has_type_checking_interface %} |
| {# Type checking for interface types (if interface not implemented, throw |
| TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} |
| if (!propertyValue{% if setter.is_nullable %} && !isUndefinedOrNull(v8Value){% endif %}) { |
| exceptionState.throwTypeError("The provided value is not of type '{{setter.idl_type}}'."); |
| return; |
| } |
| {% endif %} |
| |
| {% set setter_name = setter.name or 'anonymousIndexedSetter' %} |
| {% set setter_arguments = ['index', 'propertyValue'] %} |
| {% if setter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% set setter_arguments = ['scriptState'] + setter_arguments %} |
| {% endif %} |
| {% if setter.is_raises_exception %} |
| {% set setter_arguments = setter_arguments + ['exceptionState'] %} |
| {% endif %} |
| bool result = impl->{{setter_name}}({{setter_arguments | join(', ')}}); |
| {% if setter.is_raises_exception %} |
| if (exceptionState.hadException()) |
| return; |
| {% endif %} |
| if (!result) |
| return; |
| v8SetReturnValue(info, v8Value); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block indexed_property_setter_callback %} |
| {% if indexed_property_setter or named_property_setter %} |
| {% set setter = indexed_property_setter or named_property_setter %} |
| void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| {% if setter.is_ce_reactions %} |
| CEReactionsScope ceReactionsScope; |
| {% endif %} |
| |
| {% if indexed_property_setter %} |
| |
| {% if setter.is_custom %} |
| {{v8_class}}::indexedPropertySetterCustom(index, v8Value, info); |
| {% else %} |
| {{cpp_class}}V8Internal::indexedPropertySetter(index, v8Value, info); |
| {% endif %} |
| |
| {% else %}{# otherwise, named property #} |
| |
| const AtomicString& propertyName = AtomicString::number(index); |
| |
| {% if setter.is_custom %} |
| {{v8_class}}::namedPropertySetterCustom(propertyName, v8Value, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertySetter(propertyName, v8Value, info); |
| {% endif %} |
| |
| {% endif %}{# indexed_property_setter #} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block indexed_property_deleter %} |
| {% if indexed_property_deleter and not indexed_property_deleter.is_custom %} |
| {% set deleter = indexed_property_deleter %} |
| static void indexedPropertyDeleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) |
| { |
| {% if deleter.is_raises_exception %} |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::IndexedDeletionContext, "{{interface_name}}"); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| |
| {% set deleter_name = deleter.name or 'anonymousIndexedDeleter' %} |
| {% set deleter_arguments = ['index'] %} |
| {% if deleter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% set deleter_arguments = ['scriptState'] + deleter_arguments %} |
| {% endif %} |
| {% if deleter.is_raises_exception %} |
| {% set deleter_arguments = deleter_arguments + ['exceptionState'] %} |
| {% endif %} |
| DeleteResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}}); |
| {% if deleter.is_raises_exception %} |
| if (exceptionState.hadException()) |
| return; |
| {% endif %} |
| if (result == DeleteUnknownProperty) |
| return; |
| v8SetReturnValue(info, result == DeleteSuccess); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block indexed_property_deleter_callback %} |
| {% if indexed_property_deleter or named_property_deleter %} |
| {% set deleter = indexed_property_deleter or named_property_deleter %} |
| void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) |
| { |
| {% if deleter.is_ce_reactions %} |
| CEReactionsScope ceReactionsScope; |
| {% endif %} |
| |
| {% if indexed_property_deleter %} |
| |
| {% if deleter.is_custom %} |
| {{v8_class}}::indexedPropertyDeleterCustom(index, info); |
| {% else %} |
| {{cpp_class}}V8Internal::indexedPropertyDeleter(index, info); |
| {% endif %} |
| |
| {% else %}{# otherwise, named property #} |
| |
| const AtomicString& propertyName = AtomicString::number(index); |
| |
| {% if deleter.is_custom %} |
| {{v8_class}}::namedPropertyDeleterCustom(propertyName, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertyDeleter(propertyName, info); |
| {% endif %} |
| |
| {% endif %}{# indexed_property_deleter #} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_getter %} |
| {% if named_property_getter and not named_property_getter.is_custom %} |
| {% set getter = named_property_getter %} |
| static void namedPropertyGetter(const AtomicString& name, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| {% if getter.is_raises_exception %} |
| const CString& nameInUtf8 = name.utf8(); |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::GetterContext, "{{interface_name}}", nameInUtf8.data()); |
| {% endif %} |
| {% if getter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| {% if getter.use_output_parameter_for_result %} |
| {{getter.cpp_type}} result; |
| {{getter.cpp_value}}; |
| {% else %} |
| {{getter.cpp_type}} result = {{getter.cpp_value}}; |
| {% endif %} |
| if ({{getter.is_null_expression}}) |
| return; |
| {{getter.v8_set_return_value}}; |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_getter_callback %} |
| {% if named_property_getter %} |
| {% set getter = named_property_getter %} |
| void namedPropertyGetterCallback(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| if (!name->IsString()) |
| return; |
| const AtomicString& propertyName = toCoreAtomicString(name.As<v8::String>()); |
| |
| {% if getter.is_custom %} |
| {{v8_class}}::namedPropertyGetterCustom(propertyName, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertyGetter(propertyName, info); |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_setter %} |
| {% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} |
| {% if named_property_setter and not named_property_setter.is_custom %} |
| {% set setter = named_property_setter %} |
| static void namedPropertySetter(const AtomicString& name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| {% if setter.has_exception_state %} |
| const CString& nameInUtf8 = name.utf8(); |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::SetterContext, "{{interface_name}}", nameInUtf8.data()); |
| {% endif %} |
| {% if setter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| {{v8_value_to_local_cpp_value(setter) | indent}} |
| {% if setter.has_type_checking_interface %} |
| {# Type checking for interface types (if interface not implemented, throw |
| TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} |
| if (!propertyValue{% if setter.is_nullable %} && !isUndefinedOrNull(v8Value){% endif %}) { |
| exceptionState.throwTypeError("The provided value is not of type '{{setter.idl_type}}'."); |
| return; |
| } |
| {% endif %} |
| |
| {% set setter_name = setter.name or 'anonymousNamedSetter' %} |
| {% set setter_arguments = ['name', 'propertyValue'] %} |
| {% if setter.is_call_with_script_state %} |
| {% set setter_arguments = ['scriptState'] + setter_arguments %} |
| {% endif %} |
| {% if setter.is_raises_exception %} |
| {% set setter_arguments = setter_arguments + ['exceptionState'] %} |
| {% endif %} |
| bool result = impl->{{setter_name}}({{setter_arguments | join(', ')}}); |
| {% if setter.is_raises_exception %} |
| if (exceptionState.hadException()) |
| return; |
| {% endif %} |
| if (!result) |
| return; |
| v8SetReturnValue(info, v8Value); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_setter_callback %} |
| {% if named_property_setter %} |
| {% set setter = named_property_setter %} |
| void namedPropertySetterCallback(v8::Local<v8::Name> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) |
| { |
| if (!name->IsString()) |
| return; |
| const AtomicString& propertyName = toCoreAtomicString(name.As<v8::String>()); |
| |
| {% if setter.is_ce_reactions %} |
| CEReactionsScope ceReactionsScope; |
| {% endif %} |
| |
| {% if setter.is_custom %} |
| {{v8_class}}::namedPropertySetterCustom(propertyName, v8Value, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertySetter(propertyName, v8Value, info); |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_deleter %} |
| {% if named_property_deleter and not named_property_deleter.is_custom %} |
| {% set deleter = named_property_deleter %} |
| static void namedPropertyDeleter(const AtomicString& name, const v8::PropertyCallbackInfo<v8::Boolean>& info) |
| { |
| {% if deleter.is_raises_exception %} |
| const CString& nameInUtf8 = name.utf8(); |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::DeletionContext, "{{interface_name}}", nameInUtf8.data()); |
| {% endif %} |
| {% if deleter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| |
| {% set deleter_name = deleter.name or 'anonymousNamedDeleter' %} |
| {% set deleter_arguments = ['name'] %} |
| {% if deleter.is_call_with_script_state %} |
| {% set deleter_arguments = ['scriptState'] + deleter_arguments %} |
| {% endif %} |
| {% if deleter.is_raises_exception %} |
| {% set deleter_arguments = deleter_arguments + ['exceptionState'] %} |
| {% endif %} |
| DeleteResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}}); |
| {% if deleter.is_raises_exception %} |
| if (exceptionState.hadException()) |
| return; |
| {% endif %} |
| if (result == DeleteUnknownProperty) |
| return; |
| v8SetReturnValue(info, result == DeleteSuccess); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_deleter_callback %} |
| {% if named_property_deleter %} |
| {% set deleter = named_property_deleter %} |
| void namedPropertyDeleterCallback(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) |
| { |
| if (!name->IsString()) |
| return; |
| const AtomicString& propertyName = toCoreAtomicString(name.As<v8::String>()); |
| |
| {% if deleter.is_ce_reactions %} |
| CEReactionsScope ceReactionsScope; |
| {% endif %} |
| |
| {% if deleter.is_custom %} |
| {{v8_class}}::namedPropertyDeleterCustom(propertyName, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertyDeleter(propertyName, info); |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_query %} |
| {% if named_property_getter and named_property_getter.is_enumerable and |
| not named_property_getter.is_custom_property_query %} |
| {% set getter = named_property_getter %} |
| {# If there is an enumerator, there MUST be a query method to properly |
| communicate property attributes. #} |
| static void namedPropertyQuery(const AtomicString& name, const v8::PropertyCallbackInfo<v8::Integer>& info) |
| { |
| const CString& nameInUtf8 = name.utf8(); |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::GetterContext, "{{interface_name}}", nameInUtf8.data()); |
| {% if getter.is_call_with_script_state %} |
| ScriptState* scriptState = ScriptState::forReceiverObject(info); |
| {% endif %} |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| |
| {% set getter_arguments = ['name', 'exceptionState'] %} |
| {% if getter.is_call_with_script_state %} |
| {% set getter_arguments = ['scriptState'] + getter_arguments %} |
| {% endif %} |
| bool result = impl->namedPropertyQuery({{getter_arguments | join(', ')}}); |
| if (!result) |
| return; |
| v8SetReturnValueInt(info, v8::None); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_query_callback %} |
| {% if named_property_getter and named_property_getter.is_enumerable %} |
| {% set getter = named_property_getter %} |
| void namedPropertyQueryCallback(v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) |
| { |
| if (!name->IsString()) |
| return; |
| const AtomicString& propertyName = toCoreAtomicString(name.As<v8::String>()); |
| |
| {% if getter.is_custom_property_query %} |
| {{v8_class}}::namedPropertyQueryCustom(propertyName, info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertyQuery(propertyName, info); |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_enumerator %} |
| {% if named_property_getter and named_property_getter.is_enumerable and |
| not named_property_getter.is_custom_property_enumerator %} |
| static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) |
| { |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::EnumerationContext, "{{interface_name}}"); |
| |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); |
| |
| Vector<String> names; |
| impl->namedPropertyEnumerator(names, exceptionState); |
| if (exceptionState.hadException()) |
| return; |
| v8SetReturnValue(info, toV8(names, info.Holder(), info.GetIsolate()).As<v8::Array>()); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_property_enumerator_callback %} |
| {% if named_property_getter and named_property_getter.is_enumerable %} |
| {% set getter = named_property_getter %} |
| void namedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>& info) |
| { |
| {% if getter.is_custom_property_enumerator %} |
| {{v8_class}}::namedPropertyEnumeratorCustom(info); |
| {% else %} |
| {{cpp_class}}V8Internal::namedPropertyEnumerator(info); |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block origin_safe_method_setter %} |
| {% if has_origin_safe_method_setter %} |
| static void {{cpp_class}}OriginSafeMethodSetter(v8::Local<v8::Name> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info) |
| { |
| if (!name->IsString()) |
| return; |
| v8::Local<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.Holder(), info.GetIsolate()); |
| if (holder.IsEmpty()) |
| return; |
| {{cpp_class}}* impl = {{v8_class}}::toImpl(holder); |
| v8::String::Utf8Value attributeName(name); |
| ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), info.GetIsolate()); |
| if (!BindingSecurity::shouldAllowAccessTo(currentDOMWindow(info.GetIsolate()), impl, exceptionState)) { |
| return; |
| } |
| |
| {# The findInstanceInPrototypeChain() call above only returns a non-empty handle if info.Holder() is an Object. #} |
| V8HiddenValue::setHiddenValue(ScriptState::current(info.GetIsolate()), v8::Local<v8::Object>::Cast(info.Holder()), name.As<v8::String>(), v8Value); |
| } |
| |
| void {{cpp_class}}OriginSafeMethodSetterCallback(v8::Local<v8::Name> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info) |
| { |
| {{cpp_class}}V8Internal::{{cpp_class}}OriginSafeMethodSetter(name, v8Value, info); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block named_constructor %} |
| {% from 'methods.cpp.tmpl' import generate_constructor with context %} |
| {% if named_constructor %} |
| {% set active_scriptwrappable_inheritance = |
| 'InheritFromActiveScriptWrappable' |
| if active_scriptwrappable else |
| 'NotInheritFromActiveScriptWrappable' %} |
| // Suppress warning: global constructors, because struct WrapperTypeInfo is trivial |
| // and does not depend on another global objects. |
| #if defined(COMPONENT_BUILD) && defined(WIN32) && COMPILER(CLANG) |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wglobal-constructors" |
| #endif |
| const WrapperTypeInfo {{v8_class}}Constructor::wrapperTypeInfo = { gin::kEmbedderBlink, {{v8_class}}Constructor::domTemplate, {{v8_class}}::trace, {{v8_class}}::traceWrappers, 0, {{prepare_prototype_and_interface_object_func}}, "{{interface_name}}", 0, WrapperTypeInfo::WrapperTypeObjectPrototype, WrapperTypeInfo::{{wrapper_class_id}}, WrapperTypeInfo::{{active_scriptwrappable_inheritance}}, WrapperTypeInfo::{{event_target_inheritance}}, WrapperTypeInfo::{{lifetime}} }; |
| #if defined(COMPONENT_BUILD) && defined(WIN32) && COMPILER(CLANG) |
| #pragma clang diagnostic pop |
| #endif |
| |
| {{generate_constructor(named_constructor)}} |
| v8::Local<v8::FunctionTemplate> {{v8_class}}Constructor::domTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world) |
| { |
| static int domTemplateKey; // This address is used for a key to look up the dom template. |
| V8PerIsolateData* data = V8PerIsolateData::from(isolate); |
| v8::Local<v8::FunctionTemplate> result = data->findInterfaceTemplate(world, &domTemplateKey); |
| if (!result.IsEmpty()) |
| return result; |
| |
| result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback); |
| v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate(); |
| instanceTemplate->SetInternalFieldCount({{v8_class}}::internalFieldCount); |
| result->SetClassName(v8AtomicString(isolate, "{{cpp_class}}")); |
| result->Inherit({{v8_class}}::domTemplate(isolate, world)); |
| data->setInterfaceTemplate(world, &domTemplateKey, result); |
| return result; |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| {##############################################################################} |
| {% block overloaded_constructor %} |
| {% if constructor_overloads %} |
| static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) |
| { |
| ExceptionState exceptionState(info.GetIsolate(), ExceptionState::ConstructionContext, "{{interface_name}}"); |
| {# 2. Initialize argcount to be min(maxarg, n). #} |
| switch (std::min({{constructor_overloads.maxarg}}, info.Length())) { |
| {# 3. Remove from S all entries whose type list is not of length argcount. #} |
| {% for length, tests_constructors in constructor_overloads.length_tests_methods %} |
| case {{length}}: |
| {# Then resolve by testing argument #} |
| {% for test, constructor in tests_constructors %} |
| {# 10. If i = d, then: #} |
| if ({{test}}) { |
| {{cpp_class}}V8Internal::constructor{{constructor.overload_index}}(info); |
| return; |
| } |
| {% endfor %} |
| break; |
| {% endfor %} |
| default: |
| {# Invalid arity, throw error #} |
| {# Report full list of valid arities if gaps and above minimum #} |
| {% if constructor_overloads.valid_arities %} |
| if (info.Length() >= {{constructor_overloads.length}}) { |
| exceptionState.throwTypeError(ExceptionMessages::invalidArity("{{constructor_overloads.valid_arities}}", info.Length())); |
| return; |
| } |
| {% endif %} |
| {# Otherwise just report "not enough arguments" #} |
| exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{constructor_overloads.length}}, info.Length())); |
| return; |
| } |
| {# No match, throw error #} |
| exceptionState.throwTypeError("No matching constructor signature."); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block visit_dom_wrapper %} |
| {% if has_visit_dom_wrapper %} |
| void {{v8_class}}::visitDOMWrapper(v8::Isolate* isolate, ScriptWrappable* scriptWrappable, const v8::Persistent<v8::Object>& wrapper) |
| { |
| {% if has_visit_dom_wrapper_custom %} |
| {{v8_class}}::visitDOMWrapperCustom(isolate, scriptWrappable, wrapper); |
| {% endif %} |
| {% if set_wrapper_reference_to or set_wrapper_reference_from %} |
| {{cpp_class}}* impl = scriptWrappable->toImpl<{{cpp_class}}>(); |
| {% endif %} |
| {% if set_wrapper_reference_to %} |
| {{set_wrapper_reference_to.cpp_type}} {{set_wrapper_reference_to.name}} = impl->{{set_wrapper_reference_to.name}}(); |
| if ({{set_wrapper_reference_to.name}}) { |
| DOMWrapperWorld::setWrapperReferencesInAllWorlds(wrapper, {{set_wrapper_reference_to.name}}, isolate); |
| } |
| {% endif %} |
| {% if set_wrapper_reference_from %} |
| // The {{set_wrapper_reference_from}}() method may return a reference or a pointer. |
| if (Node* owner = WTF::getPtr(impl->{{set_wrapper_reference_from}}())) { |
| Node* root = V8GCController::opaqueRootForGC(isolate, owner); |
| isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(root)), wrapper); |
| return; |
| } |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block constructor_callback %} |
| {% if constructors or has_custom_constructor or has_event_constructor or has_html_constructor %} |
| void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| { |
| {% if measure_as %} |
| UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{measure_as('Constructor')}}); |
| {% endif %} |
| if (!info.IsConstructCall()) { |
| V8ThrowException::throwTypeError(info.GetIsolate(), ExceptionMessages::constructorNotCallableAsFunction("{{interface_name}}")); |
| return; |
| } |
| |
| if (ConstructorMode::current(info.GetIsolate()) == ConstructorMode::WrapExistingObject) { |
| v8SetReturnValue(info, info.Holder()); |
| return; |
| } |
| |
| {% if has_custom_constructor %} |
| {{v8_class}}::constructorCustom(info); |
| {% elif has_html_constructor %} |
| V8HTMLConstructor::htmlConstructor(info, {{v8_class}}::wrapperTypeInfo, HTMLElementType::k{{interface_name}}); |
| {% else %} |
| {{cpp_class}}V8Internal::constructor(info); |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% macro install_do_not_check_security_method(method, world_suffix, instance_template, prototype_template) %} |
| {% from 'utilities.cpp.tmpl' import property_location %} |
| {# Methods that are [DoNotCheckSecurity] are always readable, but if they are |
| changed and then accessed from a different origin, we do not return the |
| underlying value, but instead return a new copy of the original function. |
| This is achieved by storing the changed value as a hidden property. #} |
| {% set getter_callback = |
| '%sV8Internal::%sOriginSafeMethodGetterCallback%s' % |
| (cpp_class, method.name, world_suffix) %} |
| {% set setter_callback = |
| '{0}V8Internal::{0}OriginSafeMethodSetterCallback'.format(cpp_class) |
| if not method.is_unforgeable else '0' %} |
| {% if method.is_per_world_bindings %} |
| {% set getter_callback_for_main_world = '%sForMainWorld' % getter_callback %} |
| {% set setter_callback_for_main_world = '%sForMainWorld' % setter_callback |
| if not method.is_unforgeable else '0' %} |
| {% else %} |
| {% set getter_callback_for_main_world = '0' %} |
| {% set setter_callback_for_main_world = '0' %} |
| {% endif %} |
| {% set property_attribute = |
| 'static_cast<v8::PropertyAttribute>(%s)' % |
| ' | '.join(method.property_attributes or ['v8::None']) %} |
| {% set only_exposed_to_private_script = 'V8DOMConfiguration::OnlyExposedToPrivateScript' if method.only_exposed_to_private_script else 'V8DOMConfiguration::ExposedToAllScripts' %} |
| {% set holder_check = 'V8DOMConfiguration::CheckHolder' %} |
| const V8DOMConfiguration::AttributeConfiguration {{method.name}}OriginSafeAttributeConfiguration = { |
| "{{method.name}}", {{getter_callback}}, {{setter_callback}}, {{getter_callback_for_main_world}}, {{setter_callback_for_main_world}}, &{{v8_class}}::wrapperTypeInfo, v8::ALL_CAN_READ, {{property_attribute}}, {{only_exposed_to_private_script}}, {{property_location(method)}}, {{holder_check}}, |
| }; |
| V8DOMConfiguration::installAttribute(isolate, world, {{instance_template}}, {{prototype_template}}, {{method.name}}OriginSafeAttributeConfiguration); |
| {%- endmacro %} |
| |
| |
| {##############################################################################} |
| {% macro install_indexed_property_handler(target) %} |
| {% set indexed_property_getter_callback = |
| '%sV8Internal::indexedPropertyGetterCallback' % cpp_class %} |
| {% set indexed_property_setter_callback = |
| '%sV8Internal::indexedPropertySetterCallback' % cpp_class |
| if indexed_property_setter or named_property_setter else '0' %} |
| {% set indexed_property_query_callback = '0' %}{# Unused #} |
| {% set indexed_property_deleter_callback = |
| '%sV8Internal::indexedPropertyDeleterCallback' % cpp_class |
| if indexed_property_deleter or named_property_deleter else '0' %} |
| {% set indexed_property_enumerator_callback = |
| 'indexedPropertyEnumerator<%s>' % cpp_class |
| if indexed_property_getter.is_enumerable else '0' %} |
| {% set property_handler_flags = |
| 'v8::PropertyHandlerFlags::kAllCanRead' |
| if indexed_property_getter.do_not_check_security |
| else 'v8::PropertyHandlerFlags::kNone' %} |
| v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig({{indexed_property_getter_callback}}, {{indexed_property_setter_callback}}, {{indexed_property_query_callback}}, {{indexed_property_deleter_callback}}, {{indexed_property_enumerator_callback}}, v8::Local<v8::Value>(), {{property_handler_flags}}); |
| {{target}}->SetHandler(indexedPropertyHandlerConfig); |
| {%- endmacro %} |
| |
| |
| {##############################################################################} |
| {% macro install_named_property_handler(target) %} |
| {% set named_property_getter_callback = |
| '%sV8Internal::namedPropertyGetterCallback' % cpp_class %} |
| {% set named_property_setter_callback = |
| '%sV8Internal::namedPropertySetterCallback' % cpp_class |
| if named_property_setter else '0' %} |
| {% set named_property_query_callback = |
| '%sV8Internal::namedPropertyQueryCallback' % cpp_class |
| if named_property_getter.is_enumerable else '0' %} |
| {% set named_property_deleter_callback = |
| '%sV8Internal::namedPropertyDeleterCallback' % cpp_class |
| if named_property_deleter else '0' %} |
| {% set named_property_enumerator_callback = |
| '%sV8Internal::namedPropertyEnumeratorCallback' % cpp_class |
| if named_property_getter.is_enumerable else '0' %} |
| {% set property_handler_flags_list = |
| ['int(v8::PropertyHandlerFlags::kOnlyInterceptStrings)'] %} |
| {% if named_property_getter.do_not_check_security %} |
| {% set property_handler_flags_list = |
| property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kAllCanRead)'] %} |
| {% endif %} |
| {% if not is_override_builtins %} |
| {% set property_handler_flags_list = |
| property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kNonMasking)'] %} |
| {% endif %} |
| {% set property_handler_flags = |
| 'static_cast<v8::PropertyHandlerFlags>(%s)' % |
| ' | '.join(property_handler_flags_list) %} |
| v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}, v8::Local<v8::Value>(), {{property_handler_flags}}); |
| {{target}}->SetHandler(namedPropertyHandlerConfig); |
| {%- endmacro %} |
| |
| |
| {##############################################################################} |
| {% block get_dom_template %} |
| {% if not is_array_buffer_or_view %} |
| v8::Local<v8::FunctionTemplate> {{v8_class}}::domTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world) |
| { |
| {% set installTemplateFunction = '%s::install%sTemplateFunction' % (v8_class, v8_class) if has_partial_interface else 'install%sTemplate' % v8_class %} |
| return V8DOMConfiguration::domClassTemplate(isolate, world, const_cast<WrapperTypeInfo*>(&wrapperTypeInfo), {{installTemplateFunction}}); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block get_dom_template_for_named_properties_object %} |
| {% if has_named_properties_object %} |
| v8::Local<v8::FunctionTemplate> {{v8_class}}::domTemplateForNamedPropertiesObject(v8::Isolate* isolate, const DOMWrapperWorld& world) |
| { |
| v8::Local<v8::FunctionTemplate> parentTemplate = V8{{parent_interface}}::domTemplate(isolate, world); |
| |
| v8::Local<v8::FunctionTemplate> namedPropertiesObjectFunctionTemplate = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode); |
| namedPropertiesObjectFunctionTemplate->SetClassName(v8AtomicString(isolate, "{{interface_name}}Properties")); |
| namedPropertiesObjectFunctionTemplate->Inherit(parentTemplate); |
| |
| v8::Local<v8::ObjectTemplate> namedPropertiesObjectTemplate = namedPropertiesObjectFunctionTemplate->PrototypeTemplate(); |
| namedPropertiesObjectTemplate->SetInternalFieldCount({{v8_class}}::internalFieldCount); |
| V8DOMConfiguration::setClassString(isolate, namedPropertiesObjectTemplate, "{{interface_name}}Properties"); |
| {{install_named_property_handler('namedPropertiesObjectTemplate') | indent}} |
| |
| return namedPropertiesObjectFunctionTemplate; |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block has_instance %} |
| {% if not is_array_buffer_or_view %} |
| |
| bool {{v8_class}}::hasInstance(v8::Local<v8::Value> v8Value, v8::Isolate* isolate) |
| { |
| return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, v8Value); |
| } |
| |
| v8::Local<v8::Object> {{v8_class}}::findInstanceInPrototypeChain(v8::Local<v8::Value> v8Value, v8::Isolate* isolate) |
| { |
| return V8PerIsolateData::from(isolate)->findInstanceInPrototypeChain(&wrapperTypeInfo, v8Value); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block to_impl %} |
| {% if interface_name == 'ArrayBuffer' or interface_name == 'SharedArrayBuffer' %} |
| {{cpp_class}}* V8{{interface_name}}::toImpl(v8::Local<v8::Object> object) |
| { |
| ASSERT(object->Is{{interface_name}}()); |
| v8::Local<v8::{{interface_name}}> v8buffer = object.As<v8::{{interface_name}}>(); |
| if (v8buffer->IsExternal()) { |
| const WrapperTypeInfo* wrapperTypeInfo = toWrapperTypeInfo(object); |
| RELEASE_ASSERT(wrapperTypeInfo); |
| RELEASE_ASSERT(wrapperTypeInfo->ginEmbedder == gin::kEmbedderBlink); |
| return toScriptWrappable(object)->toImpl<{{cpp_class}}>(); |
| } |
| |
| // Transfer the ownership of the allocated memory to an {{interface_name}} without |
| // copying. |
| v8::{{interface_name}}::Contents v8Contents = v8buffer->Externalize(); |
| WTF::ArrayBufferContents contents(v8Contents.Data(), v8Contents.ByteLength(), WTF::ArrayBufferContents::{% if interface_name == 'ArrayBuffer' %}Not{% endif %}Shared); |
| {{cpp_class}}* buffer = {{cpp_class}}::create(contents); |
| v8::Local<v8::Object> associatedWrapper = buffer->associateWithWrapper(v8::Isolate::GetCurrent(), buffer->wrapperTypeInfo(), object); |
| DCHECK(associatedWrapper == object); |
| |
| return buffer; |
| } |
| |
| {% elif interface_name == 'ArrayBufferView' %} |
| {{cpp_class}}* V8ArrayBufferView::toImpl(v8::Local<v8::Object> object) |
| { |
| ASSERT(object->IsArrayBufferView()); |
| ScriptWrappable* scriptWrappable = toScriptWrappable(object); |
| if (scriptWrappable) |
| return scriptWrappable->toImpl<{{cpp_class}}>(); |
| |
| if (object->IsInt8Array()) |
| return V8Int8Array::toImpl(object); |
| if (object->IsInt16Array()) |
| return V8Int16Array::toImpl(object); |
| if (object->IsInt32Array()) |
| return V8Int32Array::toImpl(object); |
| if (object->IsUint8Array()) |
| return V8Uint8Array::toImpl(object); |
| if (object->IsUint8ClampedArray()) |
| return V8Uint8ClampedArray::toImpl(object); |
| if (object->IsUint16Array()) |
| return V8Uint16Array::toImpl(object); |
| if (object->IsUint32Array()) |
| return V8Uint32Array::toImpl(object); |
| if (object->IsFloat32Array()) |
| return V8Float32Array::toImpl(object); |
| if (object->IsFloat64Array()) |
| return V8Float64Array::toImpl(object); |
| if (object->IsDataView()) |
| return V8DataView::toImpl(object); |
| |
| ASSERT_NOT_REACHED(); |
| return 0; |
| } |
| |
| {% elif is_array_buffer_or_view %} |
| {{cpp_class}}* {{v8_class}}::toImpl(v8::Local<v8::Object> object) |
| { |
| ASSERT(object->Is{{interface_name}}()); |
| ScriptWrappable* scriptWrappable = toScriptWrappable(object); |
| if (scriptWrappable) |
| return scriptWrappable->toImpl<{{cpp_class}}>(); |
| |
| v8::Local<v8::{{interface_name}}> v8View = object.As<v8::{{interface_name}}>(); |
| v8::Local<v8::Object> arrayBuffer = v8View->Buffer(); |
| {{cpp_class}}* typedArray = nullptr; |
| if (arrayBuffer->IsArrayBuffer()) { |
| typedArray = {{cpp_class}}::create(V8ArrayBuffer::toImpl(arrayBuffer), v8View->ByteOffset(), v8View->{% if interface_name == 'DataView' %}Byte{% endif %}Length()); |
| } else if (arrayBuffer->IsSharedArrayBuffer()) { |
| typedArray = {{cpp_class}}::create(V8SharedArrayBuffer::toImpl(arrayBuffer), v8View->ByteOffset(), v8View->{% if interface_name == 'DataView' %}Byte{% endif %}Length()); |
| } else { |
| ASSERT_NOT_REACHED(); |
| } |
| v8::Local<v8::Object> associatedWrapper = typedArray->associateWithWrapper(v8::Isolate::GetCurrent(), typedArray->wrapperTypeInfo(), object); |
| DCHECK(associatedWrapper == object); |
| |
| return typedArray->toImpl<{{cpp_class}}>(); |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block to_impl_with_type_check %} |
| {{cpp_class}}* {{v8_class}}::toImplWithTypeCheck(v8::Isolate* isolate, v8::Local<v8::Value> value) |
| { |
| {% if is_array_buffer_or_view %} |
| return value->Is{{interface_name}}() ? toImpl(v8::Local<v8::Object>::Cast(value)) : nullptr; |
| {% else %} |
| return hasInstance(value, isolate) ? toImpl(v8::Local<v8::Object>::Cast(value)) : nullptr; |
| {% endif %} |
| } |
| |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% block prepare_prototype_and_interface_object %} |
| {% from 'methods.cpp.tmpl' import install_conditionally_enabled_methods with context %} |
| {% if has_prepare_prototype_and_interface_object %} |
| void {{v8_class}}::preparePrototypeAndInterfaceObject(v8::Local<v8::Context> context, const DOMWrapperWorld& world, v8::Local<v8::Object> prototypeObject, v8::Local<v8::Function> interfaceObject, v8::Local<v8::FunctionTemplate> interfaceTemplate) |
| { |
| v8::Isolate* isolate = context->GetIsolate(); |
| {% if unscopables %} |
| {{install_unscopables() | indent}} |
| {% endif %} |
| {% if has_conditional_attributes_on_prototype %} |
| {{install_conditionally_enabled_attributes_on_prototype() | indent}} |
| {% endif %} |
| {% if methods | conditionally_exposed(is_partial) %} |
| {{install_conditionally_enabled_methods() | indent}} |
| {% endif %} |
| } |
| |
| {% endif %} |
| {% endblock %} |
| |
| |
| {##############################################################################} |
| {% macro install_unscopables() %} |
| v8::Local<v8::Name> unscopablesSymbol(v8::Symbol::GetUnscopables(isolate)); |
| v8::Local<v8::Object> unscopables; |
| if (v8CallBoolean(prototypeObject->HasOwnProperty(context, unscopablesSymbol))) |
| unscopables = prototypeObject->Get(context, unscopablesSymbol).ToLocalChecked().As<v8::Object>(); |
| else |
| unscopables = v8::Object::New(isolate); |
| {% for name, runtime_enabled_function in unscopables %} |
| {% filter runtime_enabled(runtime_enabled_function) %} |
| unscopables->CreateDataProperty(context, v8AtomicString(isolate, "{{name}}"), v8::True(isolate)).FromJust(); |
| {% endfilter %} |
| {% endfor %} |
| prototypeObject->CreateDataProperty(context, unscopablesSymbol, unscopables).FromJust(); |
| {% endmacro %} |
| |
| |
| {##############################################################################} |
| {% macro install_conditionally_enabled_attributes_on_prototype() %} |
| {% from 'attributes.cpp.tmpl' import attribute_configuration with context %} |
| ExecutionContext* executionContext = toExecutionContext(context); |
| v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate); |
| {% for attribute in attributes if (attribute.exposed_test or attribute.secure_context_test) and attribute.on_prototype %} |
| {% filter exposed(attribute.exposed_test) %} |
| {% filter secure_context(attribute.secure_context_test) %} |
| {% filter runtime_enabled(attribute.runtime_enabled_function) %} |
| const V8DOMConfiguration::AccessorConfiguration accessorConfiguration = {{attribute_configuration(attribute)}}; |
| V8DOMConfiguration::installAccessor(isolate, world, v8::Local<v8::Object>(), prototypeObject, interfaceObject, signature, accessorConfiguration); |
| {% endfilter %}{# runtime_enabled #} |
| {% endfilter %}{# secure_context #} |
| {% endfilter %}{# exposed #} |
| {% endfor %} |
| {% endmacro %} |
| |
| |
| {##############################################################################} |
| {% block partial_interface %} |
| {% if has_partial_interface %} |
| InstallTemplateFunction {{v8_class}}::install{{v8_class}}TemplateFunction = (InstallTemplateFunction)&{{v8_class}}::install{{v8_class}}Template; |
| |
| void {{v8_class}}::updateWrapperTypeInfo(InstallTemplateFunction installTemplateFunction, PreparePrototypeAndInterfaceObjectFunction preparePrototypeAndInterfaceObjectFunction) |
| { |
| {{v8_class}}::install{{v8_class}}TemplateFunction = installTemplateFunction; |
| if (preparePrototypeAndInterfaceObjectFunction) |
| {{v8_class}}::wrapperTypeInfo.preparePrototypeAndInterfaceObjectFunction = preparePrototypeAndInterfaceObjectFunction; |
| } |
| |
| {% for method in methods if method.overloads and method.overloads.has_partial_overloads %} |
| void {{v8_class}}::register{{method.name | blink_capitalize}}MethodForPartialInterface(void (*method)(const v8::FunctionCallbackInfo<v8::Value>&)) |
| { |
| {{cpp_class}}V8Internal::{{method.name}}MethodForPartialInterface = method; |
| } |
| |
| {% endfor %} |
| {% endif %} |
| {% endblock %} |