blob: 60e6dccfea98bb32a7461503d6e90f8e995ed8dd [file] [log] [blame]
{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %}
{% from 'methods.cpp.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %}
{##############################################################################}
{% macro attribute_getter(attribute, world_suffix) %}
static void {{attribute.name}}AttributeGetter{{world_suffix}}(
{%- if attribute.is_data_type_property %}
const v8::PropertyCallbackInfo<v8::Value>& info
{%- else %}
const v8::FunctionCallbackInfo<v8::Value>& info
{%- endif %}) {
{% filter format_remove_duplicates(['ExceptionState exceptionState']) %}
{% set define_exception_state -%}
ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kGetterContext, "{{interface_name}}", "{{attribute.name}}");
{%- endset %}
{% if attribute.is_lenient_this %}
// [LenientThis]
// Make sure that info.Holder() really points to an instance if [LenientThis].
if (!{{v8_class}}::hasInstance(info.Holder(), info.GetIsolate()))
return; // Return silently because of [LenientThis].
{% elif attribute.has_promise_type %}
// This attribute returns a Promise.
// Per https://heycam.github.io/webidl/#dfn-attribute-getter, all exceptions
// must be turned into a Promise rejection.
{{define_exception_state}}
ExceptionToRejectPromiseScope rejectPromiseScope(info, exceptionState);
// Returning a Promise type requires us to disable some of V8's type checks,
// so we have to manually check that info.Holder() really points to an
// instance of the type.
if (!{{v8_class}}::hasInstance(info.Holder(), info.GetIsolate())) {
exceptionState.ThrowTypeError("Illegal invocation");
return;
}
{% endif %}
{% if not attribute.is_static or attribute.is_save_same_object %}
v8::Local<v8::Object> holder = info.Holder();
{% endif %}
{% if attribute.is_save_same_object %}
// [SaveSameObject]
{% set same_object_private_key = interface_name + attribute.name[0]|capitalize + attribute.name[1:] %}
// If you see a compile error that
// V8PrivateProperty::GetSameObject{{same_object_private_key}}
// is not defined, then you need to register your attribute at
// V8_PRIVATE_PROPERTY_FOR_EACH defined in V8PrivateProperty.h as
// X(SameObject, {{same_object_private_key}})
auto privateSameObject = V8PrivateProperty::GetSameObject{{same_object_private_key}}(info.GetIsolate());
{
v8::Local<v8::Value> v8Value;
if (privateSameObject.GetOrUndefined(holder).ToLocal(&v8Value) && !v8Value->IsUndefined()) {
V8SetReturnValue(info, v8Value);
return;
}
}
{% endif %}
{% if not attribute.is_static %}
{% set local_dom_window_only = interface_name == 'Window' and not attribute.has_cross_origin_getter %}
{% if local_dom_window_only %}
{% if attribute.is_check_security_for_receiver %}
{{cpp_class}}* uncheckedImpl = {{v8_class}}::ToImpl(holder);
{% else %}
// Same-origin attribute getters are never exposed via the cross-origin
// interceptors. Since same-origin access requires a LocalDOMWindow, it is
// safe to downcast here.
LocalDOMWindow* impl = ToLocalDOMWindow({{v8_class}}::ToImpl(holder));
{% endif %}{# attribute.is_check_security_for_receiver #}
{% else %}
{{cpp_class}}* impl = {{v8_class}}::ToImpl(holder);
{% endif %}{# local_dom_window_only #}
{% endif %}{# not attribute.is_static #}
{% if attribute.cached_attribute_validation_method %}
// [CachedAttribute]
V8PrivateProperty::Symbol propertySymbol =
V8PrivateProperty::GetSymbol(info.GetIsolate(),
"{{cpp_class}}#{{attribute.name.capitalize()}}");
if (!static_cast<const {{cpp_class}}*>(impl)->{{attribute.cached_attribute_validation_method}}()) {
v8::Local<v8::Value> v8Value;
if (propertySymbol.GetOrUndefined(holder).ToLocal(&v8Value) && !v8Value->IsUndefined()) {
V8SetReturnValue(info, v8Value);
return;
}
}
{% endif %}
{% if attribute.is_check_security_for_receiver and not attribute.is_data_type_property %}
// Perform a security check for the receiver object.
{{define_exception_state}}
{% if local_dom_window_only %}
if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), uncheckedImpl, exceptionState)) {
{% else %}
if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), impl, exceptionState)) {
{% endif %}{# local_dom_window_only #}
V8SetReturnValueNull(info);
return;
}
{% if local_dom_window_only %}
LocalDOMWindow* impl = ToLocalDOMWindow(uncheckedImpl);
{% endif %}{# local_dom_window_only #}
{% endif %}
{% if attribute.is_check_security_for_return_value %}
// Perform a security check for the returned object.
{{define_exception_state}}
if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), {{attribute.cpp_value}}, BindingSecurity::ErrorReportOption::kDoNotReport)) {
UseCounter::Count(CurrentExecutionContext(info.GetIsolate()),
WebFeature::kCrossOrigin{{interface_name}}{{attribute.name|blink_capitalize}});
V8SetReturnValueNull(info);
return;
}
{% endif %}
{% if attribute.is_call_with_execution_context %}
{% if attribute.is_static %}
ExecutionContext* executionContext = ExecutionContext::ForCurrentRealm(info);
{% else %}
ExecutionContext* executionContext = ExecutionContext::ForRelevantRealm(info);
{% endif %}
{% endif %}
{% if attribute.is_call_with_script_state %}
{% if attribute.is_static %}
ScriptState* scriptState = ScriptState::ForCurrentRealm(info);
{% else %}
ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
{% endif %}
{% endif %}
{% if attribute.is_getter_raises_exception %}
{{define_exception_state}}
{% endif %}
{% if attribute.is_explicit_nullable %}
bool isNull = false;
{% endif %}
{% if attribute.cpp_value_original %}
{{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_original}});
{% endif %}
{% if attribute.use_output_parameter_for_result %}
{{attribute.cpp_type}} result;
{{attribute.cpp_value}};
{% endif %}
{% if attribute.is_getter_raises_exception %}
if (UNLIKELY(exceptionState.HadException()))
return;
{% endif %}
{% if attribute.reflect_only %}
{{release_only_check(attribute.reflect_only, attribute.reflect_missing,
attribute.reflect_invalid, attribute.reflect_empty,
attribute.cpp_value)
| trim | indent(2)}}
{% endif %}
{% if attribute.cached_attribute_validation_method %}
// [CachedAttribute]
v8::Local<v8::Value> v8Value({{attribute.cpp_value_to_v8_value}});
propertySymbol.Set(holder, v8Value);
{% endif %}
{% if attribute.is_explicit_nullable %}
if (isNull) {
V8SetReturnValueNull(info);
return;
}
{% endif %}
{% if attribute.is_keep_alive_for_gc %}
// Keep the wrapper object for the return value alive as long as |this|
// object is alive in order to save creation time of the wrapper object.
if ({{attribute.cpp_value}} && DOMDataStore::SetReturnValue{{world_suffix}}(info.GetReturnValue(), {{attribute.cpp_value_to_script_wrappable}}))
return;
v8::Local<v8::Value> v8Value(ToV8({{attribute.cpp_value_to_script_wrappable}}, holder, info.GetIsolate()));
V8PrivateProperty::GetSymbol(
info.GetIsolate(), "KeepAlive#{{interface_name}}#{{attribute.name}}")
.Set(holder, v8Value);
{% endif %}
{% if world_suffix %}
{{attribute.v8_set_return_value_for_main_world}};
{% else %}
{{attribute.v8_set_return_value}};
{% endif %}
{% if attribute.is_save_same_object %}
// [SaveSameObject]
privateSameObject.Set(holder, info.GetReturnValue().Get());
{% endif %}
{% endfilter %}{# format_remove_duplicates #}
}
{% endmacro %}
{######################################}
{% macro release_only_check(reflect_only_values, reflect_missing,
reflect_invalid, reflect_empty, cpp_value) %}
{# Attribute is limited to only known values: check that the attribute value is
one of those. If not, set it to the empty string.
http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
{% if reflect_empty %}
if ({{cpp_value}}.IsNull()) {
{% if reflect_missing %}
{{cpp_value}} = "{{reflect_missing}}";
{% else %}
;
{% endif %}
} else if ({{cpp_value}}.IsEmpty()) {
{{cpp_value}} = "{{reflect_empty}}";
{% else %}
if ({{cpp_value}}.IsEmpty()) {
{# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
{% if reflect_missing %}
{{cpp_value}} = "{{reflect_missing}}";
{% else %}
;
{% endif %}
{% endif %}
{% for value in reflect_only_values %}
} else if (EqualIgnoringASCIICase({{cpp_value}}, "{{value}}")) {
{{cpp_value}} = "{{value}}";
{% endfor %}
} else {
{{cpp_value}} = "{{reflect_invalid}}";
}
{% endmacro %}
{##############################################################################}
{% macro attribute_getter_callback(attribute, world_suffix) %}
void {{v8_class_or_partial}}::{{attribute.name}}AttributeGetterCallback{{world_suffix}}(
{%- if attribute.is_data_type_property %}
v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info
{%- else %}
const v8::FunctionCallbackInfo<v8::Value>& info
{%- endif %}) {
{% if attribute.runtime_call_stats.extended_attribute_defined %}
{{ runtime_timer_scope(attribute.runtime_call_stats.getter_counter) | trim | indent(2) }}
{% else %}
{{ runtime_timer_scope_disabled_by_default(attribute.runtime_call_stats.getter_counter) }}
{% endif %}
{% if attribute.deprecate_as %}
Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
{% endif %}
{% if attribute.measure_as %}
UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('AttributeGetter')}});
{% endif %}
{% if world_suffix in attribute.activity_logging_world_list_for_getter %}
{% if attribute.is_static %}
ScriptState* scriptState = ScriptState::ForCurrentRealm(info);
{% else %}
ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
{% endif %}
V8PerContextData* contextData = scriptState->PerContextData();
if (
{%- if attribute.activity_logging_world_check -%}
scriptState->World().IsIsolatedWorld() && {# one space at the end #}
{%- endif -%}
contextData && contextData->ActivityLogger()) {
contextData->ActivityLogger()->LogGetter("{{interface_name}}.{{attribute.name}}");
}
{% endif %}
{% if attribute.has_custom_getter %}
{{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
{% else %}
{{cpp_class_or_partial}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
{% endif %}
}
{% endmacro %}
{##############################################################################}
{% macro constructor_getter_callback(attribute, world_suffix) %}
void {{v8_class_or_partial}}::{{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
{{ runtime_timer_scope_disabled_by_default(attribute.runtime_call_stats.constructor_getter_callback_counter) }}
{% if attribute.deprecate_as %}
Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
{% endif %}
{% if attribute.measure_as %}
UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('ConstructorGetter')}});
{% endif %}
{% if attribute.is_named_constructor %}
V8{{attribute.constructor_type}}::NamedConstructorAttributeGetter(property, info);
{% else %}
V8ConstructorAttributeGetter(property, info, &V8{{attribute.constructor_type}}::wrapperTypeInfo);
{% endif %}
}
{% endmacro %}
{##############################################################################}
{% macro attribute_setter(attribute, world_suffix) %}
static void {{attribute.name}}AttributeSetter{{world_suffix}}(
{%- if attribute.has_cross_origin_setter %}
v8::Local<v8::Value> v8Value, const V8CrossOriginSetterInfo& info
{%- elif attribute.is_data_type_property %}
v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
{%- else %}
v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
{%- endif %}) {
{% filter format_remove_duplicates(['ExceptionState exceptionState']) %}
v8::Isolate* isolate = info.GetIsolate();
ALLOW_UNUSED_LOCAL(isolate);
v8::Local<v8::Object> holder = info.Holder();
ALLOW_UNUSED_LOCAL(holder);
{% set define_exception_state -%}
ExceptionState exceptionState(isolate, ExceptionState::kSetterContext, "{{interface_name}}", "{{attribute.name}}");
{%- endset %}
{% if attribute.is_lenient_this %}
// [LenientThis]
// Make sure that info.Holder() really points to an instance if [LenientThis].
if (!{{v8_class}}::hasInstance(holder, isolate))
return; // Return silently because of [LenientThis].
{% endif %}
{% if not attribute.is_static and not attribute.is_replaceable and not attribute.is_put_forwards %}
{% set local_dom_window_only = interface_name == 'Window' and not attribute.has_cross_origin_setter %}
{% if local_dom_window_only %}
{% if attribute.is_check_security_for_receiver %}
{{cpp_class}}* uncheckedImpl = {{v8_class}}::ToImpl(holder);
{% else %}
// Same-origin attributes setters are never exposed via the cross-origin
// interceptors. Since same-origin access requires a LocalDOMWindow, it is
// safe to downcast here.
LocalDOMWindow* impl = ToLocalDOMWindow({{v8_class}}::ToImpl(holder));
{% endif %}{# attribute.is_check_security_for_receiver #}
{% else %}
{{cpp_class}}* impl = {{v8_class}}::ToImpl(holder);
{% endif %}{# local_dom_window_only #}
{% endif %}
{% if attribute.is_check_security_for_receiver and not attribute.is_data_type_property %}
// Perform a security check for the receiver object.
{{define_exception_state}}
{% if local_dom_window_only %}
if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(isolate), uncheckedImpl, exceptionState)) {
{% else %}
if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(isolate), impl, exceptionState)) {
{% endif %}{# local_dom_window_only #}
V8SetReturnValue(info, v8Value);
return;
}
{% if local_dom_window_only %}
LocalDOMWindow* impl = ToLocalDOMWindow(uncheckedImpl);
{% endif %}{# local_dom_window_only #}
{% endif %}
{% if attribute.is_check_security_for_return_value %}
#error Attribute setter with the security check for the return value is not supported. Since the return value is the given value to be set, it\'s meaningless to perform the security check for the return value.
{% endif %}
{% if attribute.is_put_forwards %}
// [PutForwards] => {{attribute.name}}.{{attribute.target_attribute_name}}
{{define_exception_state}}
v8::Local<v8::Value> target;
if (!holder->Get(isolate->GetCurrentContext(), V8AtomicString(isolate, "{{attribute.name}}")).ToLocal(&target))
return;
if (!target->IsObject()) {
exceptionState.ThrowTypeError("The attribute value is not an object");
return;
}
bool result;
if (!target.As<v8::Object>()->Set(isolate->GetCurrentContext(), V8AtomicString(isolate, "{{attribute.target_attribute_name}}"), v8Value).To(&result))
return;
if (!result)
return;
{% else %}{# attribute.is_put_forwards #}
{% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
V0CustomElementProcessingStack::CallbackDeliveryScope deliveryScope;
{% endif %}
{% if attribute.has_setter_exception_state %}
{{define_exception_state}}
{% endif %}
// Prepare the value to be set.
{% if attribute.idl_type != 'EventHandler' %}
{{v8_value_to_local_cpp_value(attribute) | trim | indent(2)}}
{% endif %}
{% if attribute.has_type_checking_interface %}
// Type check per: http://heycam.github.io/webidl/#es-interface
if (!cppValue{% if attribute.is_nullable %} && !IsUndefinedOrNull(v8Value){% endif %}) {
exceptionState.ThrowTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
return;
}
{% endif %}
{% if attribute.enum_values %}
// Type check per: http://heycam.github.io/webidl/#dfn-attribute-setter
// Returns undefined without setting the value if the value is invalid.
DummyExceptionStateForTesting dummyExceptionState;
{{declare_enum_validation_variable(attribute.enum_values) | trim | indent(2)}}
if (!IsValidEnum(cppValue, validValues, base::size(validValues), "{{attribute.enum_type}}", dummyExceptionState)) {
ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage(
ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
dummyExceptionState.Message()));
return;
}
{% endif %}
{% if attribute.is_call_with_execution_context or
attribute.is_setter_call_with_execution_context %}
{% if attribute.is_static %}
ExecutionContext* executionContext = ExecutionContext::ForCurrentRealm(info);
{% else %}
ExecutionContext* executionContext = ExecutionContext::ForRelevantRealm(info);
{% endif %}
{% endif %}
{% if attribute.is_call_with_script_state %}
{% if attribute.is_static %}
ScriptState* scriptState = ScriptState::ForCurrentRealm(info);
{% else %}
ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
{% endif %}
{% endif %}
{% if attribute.is_replaceable %}
v8::Local<v8::String> propertyName = V8AtomicString(isolate, "{{attribute.name}}");
{% endif %}
{% if attribute.is_explicit_nullable %}
bool isNull = IsUndefinedOrNull(v8Value);
{% endif %}
{{attribute.cpp_setter}};
{% if attribute.cached_attribute_validation_method %}
// [CachedAttribute]
// Invalidate the cached value.
V8PrivateProperty::GetSymbol(
isolate, "{{cpp_class}}#{{attribute.name.capitalize()}}")
.DeleteProperty(holder, v8::Undefined(isolate));
{% endif %}
{% endif %}{# attribute.is_put_forwards #}
{% endfilter %}{# format_remove_duplicates #}
}
{% endmacro %}
{##############################################################################}
{% macro attribute_setter_callback(attribute, world_suffix) %}
void {{v8_class_or_partial}}::{{attribute.name}}AttributeSetterCallback{{world_suffix}}(
{%- if attribute.is_data_type_property %}
v8::Local<v8::Name>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
{%- else %}
const v8::FunctionCallbackInfo<v8::Value>& info
{%- endif %}) {
{% if attribute.is_lenient_setter %}
// Setter for {{attribute.name}} is no-op because [LenientSetter] is specified.
{% else %}
{% if attribute.runtime_call_stats.extended_attribute_defined %}
{{ runtime_timer_scope(attribute.runtime_call_stats.setter_counter) | trim | indent(2) }}
{% else %}
{{ runtime_timer_scope_disabled_by_default(attribute.runtime_call_stats.setter_counter) }}
{% endif %}
{% if not attribute.is_data_type_property %}
v8::Local<v8::Value> v8Value = info[0];
{% endif %}
{% if attribute.deprecate_as %}
Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
{% endif %}
{% if attribute.measure_as %}
UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('AttributeSetter')}});
{% endif %}
{% if world_suffix in attribute.activity_logging_world_list_for_setter %}
{% if attribute.is_static %}
ScriptState* scriptState = ScriptState::ForCurrentRealm(info);
{% else %}
ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
{% endif %}
V8PerContextData* contextData = scriptState->PerContextData();
if (
{%- if attribute.activity_logging_world_check -%}
scriptState->World().IsIsolatedWorld() && {# one space at the end #}
{%- endif -%}
contextData && contextData->ActivityLogger()) {
contextData->ActivityLogger()->LogSetter("{{interface_name}}.{{attribute.name}}", v8Value);
}
{% endif %}
{% if attribute.is_ce_reactions %}
CEReactionsScope ceReactionsScope;
{% endif %}
{% if attribute.has_custom_setter %}
{{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info);
{% elif attribute.has_cross_origin_setter %}
{{cpp_class_or_partial}}V8Internal::{{attribute.name}}AttributeSetter(v8Value, V8CrossOriginSetterInfo(info.GetIsolate(), info.Holder()));
{% else %}
{{cpp_class_or_partial}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info);
{% endif %}
{% endif %}{# attribute.is_lenient_setter #}
}
{% endmacro %}
{##############################################################################}
{% macro build_attribute_or_accessor_configuration(attribute, config_type) %}
{% from 'utilities.cpp.tmpl' import property_location %}
{% if attribute.constructor_type %}
{% set getter_callback = '%s::%sConstructorGetterCallback' % (v8_class_or_partial, attribute.name) %}
{% set setter_callback = 'nullptr' %}
{% else %}{# regular attributes #}
{% set getter_callback = '%s::%sAttributeGetterCallback' % (v8_class_or_partial, attribute.name) %}
{% set setter_callback = '%s::%sAttributeSetterCallback' % (v8_class_or_partial, attribute.name)
if attribute.has_setter else 'nullptr' %}
{% endif %}
{% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' %
' | '.join(attribute.property_attributes) %}
{% set cached_property_key = 'V8PrivateProperty::k' +
(attribute.cached_accessor_name if attribute.is_cached_accessor
else 'NoCachedAccessor') %}
{% set holder_check = 'V8DOMConfiguration::kDoNotCheckHolder'
if attribute.is_lenient_this or attribute.has_promise_type
else 'V8DOMConfiguration::kCheckHolder' %}
{% set getter_side_effect_type = 'V8DOMConfiguration::kHasNoSideEffect'
if attribute.getter_has_no_side_effect else 'V8DOMConfiguration::kHasSideEffect' %}
{% if attribute.is_per_world_bindings %}
{% set getter_callback_for_main_world = '%sForMainWorld' % getter_callback %}
{% set setter_callback_for_main_world =
'%sForMainWorld' % setter_callback if attribute.has_setter else 'nullptr' %}
{% endif %}
{% set config_pre = {
'main' : [
'"%s"' % attribute.name,
getter_callback_for_main_world,
setter_callback_for_main_world,
],
'non_main' : [
'"%s"' % attribute.name,
getter_callback,
setter_callback,
],
} %}
{% set accessor_only_fields = [] if config_type == 'attribute' else [cached_property_key] %}
{% set config_post = [
property_attribute,
property_location(attribute),
holder_check,
getter_side_effect_type,
] %}
{% if attribute.is_per_world_bindings %}
{% set main_config_list = config_pre["main"] + accessor_only_fields +
config_post + ['V8DOMConfiguration::kMainWorld'] %}
{% set non_main_config_list = config_pre["non_main"] + accessor_only_fields +
config_post + ['V8DOMConfiguration::kNonMainWorlds'] %}
{# Emit for main world then non-main.#}
{ {{main_config_list | join(', ')}} },
{ {{non_main_config_list | join(', ')}} }
{%- else -%}
{% set all_worlds_config_list = config_pre["non_main"] + accessor_only_fields +
config_post + ['V8DOMConfiguration::kAllWorlds'] %}
{# Emit only for all worlds #}
{ {{all_worlds_config_list | join(', ')}} }
{%- endif -%}
{% endmacro %}
{##############################################################################}
{% macro attribute_configuration(attribute) %}
{{build_attribute_or_accessor_configuration(attribute, 'attribute')}}
{% endmacro %}
{##############################################################################}
{% macro accessor_configuration(attribute) %}
{{build_attribute_or_accessor_configuration(attribute, 'accessor')}}
{% endmacro %}
{##############################################################################}
{# This macro installs |attributes_to_install| on v8::Object/v8::Function, not on v8::ObjectTemplate/v8::FunctionTemplate. #}
{% macro install_conditional_attributes(attributes_to_install) %}
{% for exposed_test, exposed_attribute_list in attributes_to_install | groupby('exposed_test') %}
{% filter exposed(exposed_test) %}
{% for secure_context_test, secure_context_attribute_list in exposed_attribute_list | groupby('secure_context_test') %}
{% filter secure_context(secure_context_test) %}
{% for feature_name, attribute_list in secure_context_attribute_list | groupby('runtime_enabled_feature_name') %}
{% filter runtime_enabled(feature_name) %}
static const V8DOMConfiguration::AccessorConfiguration accessor_configurations[] = {
{% for attribute in attribute_list | sort %}
{{accessor_configuration(attribute) | trim | indent(4)}},
{% endfor %}
};
V8DOMConfiguration::InstallAccessors(
isolate, world, instanceObject, prototypeObject, interfaceObject,
signature, accessor_configurations,
base::size(accessor_configurations));
{% endfilter %}{# runtime_enabled #}
{% endfor %}{# secure_context_attribute_list grouped by runtime_enabled #}
{% endfilter %}{# secure_context #}
{% endfor %}{# exposed_attribute_list grouped by secure_context_text #}
{% endfilter %}{# exposed #}
{% endfor %}{# attributes grouped by exposed_test #}
{% endmacro %}
{##############################################################################}
{% macro install_conditional_interface_objects(attributes_to_install) %}
{% for exposed_test, exposed_attribute_list in attributes_to_install | groupby('exposed_test') %}
{% filter exposed(exposed_test) %}
{% for secure_context_test, secure_context_attribute_list in exposed_attribute_list | groupby('secure_context_test') %}
{% filter secure_context(secure_context_test) %}
{% for feature_name, attribute_list in secure_context_attribute_list | groupby('runtime_enabled_feature_name') %}
{% filter runtime_enabled(feature_name) %}
static const V8DOMConfiguration::AttributeConfiguration attribute_configurations[] = {
{% for attribute in attribute_list | sort %}
{{attribute_configuration(attribute) | trim | indent(4)}},
{% endfor %}
};
V8DOMConfiguration::InstallAttributes(
isolate, world, instanceObject, prototypeObject,
attribute_configurations, base::size(attribute_configurations));
{% endfilter %}{# runtime_enabled #}
{% endfor %}{# secure_context_attribute_list grouped by runtime_enabled #}
{% endfilter %}{# secure_context #}
{% endfor %}{# exposed_attribute_list grouped by secure_context_text #}
{% endfilter %}{# exposed #}
{% endfor %}{# attributes grouped by exposed_test #}
{% endmacro %}