blob: 7104fef8f177e83543ccdfd8c9595624ce27088b [file] [log] [blame]
{% 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 %}