in bindings/scripts/v8_interface.py [0:0]
def interface_context(interface, interfaces):
"""Creates a Jinja template context for an interface.
Args:
interface: An interface to create the context for
interfaces: A dict which maps an interface name to the definition
which can be referred if needed
Returns:
A Jinja template context for |interface|
"""
includes.clear()
includes.update(INTERFACE_CPP_INCLUDES)
header_includes = set(INTERFACE_H_INCLUDES)
if interface.is_partial:
# A partial interface definition cannot specify that the interface
# inherits from another interface. Inheritance must be specified on
# the original interface definition.
parent_interface = None
is_event_target = False
# partial interface needs the definition of its original interface.
includes.add('bindings/core/v8/V8%s.h' % interface.name)
else:
parent_interface = interface.parent
if parent_interface:
header_includes.update(v8_types.includes_for_interface(parent_interface))
is_event_target = inherits_interface(interface.name, 'EventTarget')
extended_attributes = interface.extended_attributes
is_array_buffer_or_view = interface.idl_type.is_array_buffer_or_view
is_typed_array_type = interface.idl_type.is_typed_array
if is_array_buffer_or_view:
includes.update(('bindings/core/v8/V8ArrayBuffer.h',
'bindings/core/v8/V8SharedArrayBuffer.h'))
if interface.name == 'ArrayBufferView':
includes.update((
'bindings/core/v8/V8Int8Array.h',
'bindings/core/v8/V8Int16Array.h',
'bindings/core/v8/V8Int32Array.h',
'bindings/core/v8/V8Uint8Array.h',
'bindings/core/v8/V8Uint8ClampedArray.h',
'bindings/core/v8/V8Uint16Array.h',
'bindings/core/v8/V8Uint32Array.h',
'bindings/core/v8/V8Float32Array.h',
'bindings/core/v8/V8Float64Array.h',
'bindings/core/v8/V8DataView.h'))
# [ActiveScriptWrappable]
active_scriptwrappable = 'ActiveScriptWrappable' in extended_attributes
# [CheckSecurity]
is_check_security = 'CheckSecurity' in extended_attributes
if is_check_security:
includes.add('bindings/core/v8/BindingSecurity.h')
includes.add('core/frame/LocalDOMWindow.h')
# [DependentLifetime]
is_dependent_lifetime = 'DependentLifetime' in extended_attributes
# [PrimaryGlobal] and [Global]
is_global = ('PrimaryGlobal' in extended_attributes or
'Global' in extended_attributes)
# [ImmutablePrototype]
# TODO(littledan): Is it possible to deduce this based on inheritance,
# as in the WebIDL spec?
is_immutable_prototype = is_global or 'ImmutablePrototype' in extended_attributes
wrapper_class_id = ('kNodeClassId' if inherits_interface(interface.name, 'Node') else 'kObjectClassId')
# [ActiveScriptWrappable] must be accompanied with [DependentLifetime].
if active_scriptwrappable and not is_dependent_lifetime:
raise Exception('[ActiveScriptWrappable] interface must also specify '
'[DependentLifetime]: %s' % interface.name)
# [LegacyUnenumerableNamedProperties]
# pylint: disable=C0103
has_legacy_unenumerable_named_properties = (interface.has_named_property_getter and
'LegacyUnenumerableNamedProperties' in extended_attributes)
v8_class_name = v8_utilities.v8_class_name(interface)
cpp_class_name = cpp_name(interface)
cpp_class_name_or_partial = cpp_name_or_partial(interface)
v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface)
# TODO(peria): Generate the target list from 'Window' and 'HTMLDocument'.
needs_runtime_enabled_installer = v8_class_name in [
'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget']
context = {
'active_scriptwrappable': active_scriptwrappable,
'context_enabled_feature_name': context_enabled_feature_name(interface), # [ContextEnabled]
'cpp_class': cpp_class_name,
'cpp_class_or_partial': cpp_class_name_or_partial,
'is_gc_type': True,
# FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699
'has_access_check_callbacks': (is_check_security and
interface.name != 'EventTarget'),
'has_custom_legacy_call_as_function': has_extended_attribute_value(interface, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction]
'has_legacy_unenumerable_named_properties': has_legacy_unenumerable_named_properties,
'has_partial_interface': len(interface.partial_interfaces) > 0,
'header_includes': header_includes,
'interface_name': interface.name,
'is_array_buffer_or_view': is_array_buffer_or_view,
'is_check_security': is_check_security,
'is_event_target': is_event_target,
'is_global': is_global,
'is_immutable_prototype': is_immutable_prototype,
'is_node': inherits_interface(interface.name, 'Node'),
'is_partial': interface.is_partial,
'is_typed_array_type': is_typed_array_type,
'lifetime': 'kDependent' if is_dependent_lifetime else 'kIndependent',
'measure_as': v8_utilities.measure_as(interface, None), # [MeasureAs]
'needs_runtime_enabled_installer': needs_runtime_enabled_installer,
'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(interface),
'parent_interface': parent_interface,
'pass_cpp_type': cpp_name(interface) + '*',
'runtime_call_stats': runtime_call_stats_context(interface),
'runtime_enabled_feature_name': runtime_enabled_feature_name(interface), # [RuntimeEnabled]
'v8_class': v8_class_name,
'v8_class_or_partial': v8_class_name_or_partial,
'wrapper_class_id': wrapper_class_id,
}
# Constructors
constructors = [constructor_context(interface, constructor)
for constructor in interface.constructors
# FIXME: shouldn't put named constructors with constructors
# (currently needed for Perl compatibility)
# Handle named constructors separately
if constructor.name == 'Constructor']
if len(constructors) > 1:
context['constructor_overloads'] = overloads_context(interface, constructors)
# [CustomConstructor]
custom_constructors = [{ # Only needed for computing interface length
'number_of_required_arguments':
number_of_required_arguments(constructor),
} for constructor in interface.custom_constructors]
# [HTMLConstructor]
has_html_constructor = 'HTMLConstructor' in extended_attributes
# https://html.spec.whatwg.org/multipage/dom.html#html-element-constructors
if has_html_constructor:
if ('Constructor' in extended_attributes) or ('NoInterfaceObject' in extended_attributes):
raise Exception('[Constructor] and [NoInterfaceObject] MUST NOT be'
' specified with [HTMLConstructor]: '
'%s' % interface.name)
includes.add('bindings/core/v8/V8HTMLConstructor.h')
# [NamedConstructor]
named_constructor = named_constructor_context(interface)
if constructors or custom_constructors or named_constructor:
if interface.is_partial:
raise Exception('[Constructor] and [NamedConstructor] MUST NOT be'
' specified on partial interface definitions: '
'%s' % interface.name)
if named_constructor:
includes.add('platform/bindings/V8PrivateProperty.h')
includes.add('platform/bindings/V8ObjectConstructor.h')
includes.add('core/frame/LocalDOMWindow.h')
elif 'Measure' in extended_attributes or 'MeasureAs' in extended_attributes:
if not interface.is_partial:
raise Exception('[Measure] or [MeasureAs] specified for interface without a constructor: '
'%s' % interface.name)
# [ConstructorCallWith=Document]
if has_extended_attribute_value(interface, 'ConstructorCallWith', 'Document'):
includes.add('core/dom/Document.h')
# [Unscopable] attributes and methods
unscopables = []
for attribute in interface.attributes:
if 'Unscopable' in attribute.extended_attributes:
unscopables.append((attribute.name, runtime_enabled_feature_name(attribute)))
for method in interface.operations:
if 'Unscopable' in method.extended_attributes:
unscopables.append((method.name, runtime_enabled_feature_name(method)))
# [CEReactions]
setter_or_deleters = (
interface.indexed_property_setter,
interface.indexed_property_deleter,
interface.named_property_setter,
interface.named_property_deleter,
)
has_ce_reactions = any(setter_or_deleter and 'CEReactions' in setter_or_deleter.extended_attributes
for setter_or_deleter in setter_or_deleters)
if has_ce_reactions:
includes.add('core/html/custom/CEReactionsScope.h')
context.update({
'constructors': constructors,
'has_custom_constructor': bool(custom_constructors),
'has_html_constructor': has_html_constructor,
'interface_length':
interface_length(constructors + custom_constructors),
'is_constructor_raises_exception': extended_attributes.get('RaisesException') == 'Constructor', # [RaisesException=Constructor]
'named_constructor': named_constructor,
'unscopables': sorted(unscopables),
})
# Constants
context.update({
'constants': [constant_context(constant, interface) for constant in interface.constants],
'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes,
})
# Attributes
attributes = attributes_context(interface, interfaces)
context.update({
'attributes': attributes,
# Elements in attributes are broken in following members.
'accessors': v8_attributes.filter_accessors(attributes),
'data_attributes': v8_attributes.filter_data_attributes(attributes),
'lazy_data_attributes': v8_attributes.filter_lazy_data_attributes(attributes),
'runtime_enabled_attributes': v8_attributes.filter_runtime_enabled(attributes),
})
# Conditionally enabled attributes
conditional_enabled_attributes = v8_attributes.filter_conditionally_enabled(attributes)
has_conditional_attributes_on_prototype = any( # pylint: disable=invalid-name
attribute['on_prototype'] for attribute in conditional_enabled_attributes)
has_conditionally_enabled_constructors = any( # pylint: disable=invalid-name
attribute['constructor_type'] for attribute in conditional_enabled_attributes)
has_conditionally_enabled_secure_attributes = any( # pylint: disable=invalid-name
v8_attributes.is_secure_context(attribute) for attribute in conditional_enabled_attributes)
context.update({
'has_conditionally_enabled_constructors':
has_conditionally_enabled_constructors,
'has_conditionally_enabled_secure_attributes':
has_conditionally_enabled_secure_attributes,
'conditionally_enabled_attributes': conditional_enabled_attributes,
})
# Methods
context.update(methods_context(interface))
methods = context['methods']
context.update({
'has_origin_safe_method_setter': any(method['is_cross_origin'] and not method['is_unforgeable']
for method in methods),
})
# Conditionally enabled methods
conditionally_enabled_methods = v8_methods.filter_conditionally_enabled(methods, interface.is_partial)
has_conditionally_enabled_secure_methods = any( # pylint: disable=invalid-name
v8_methods.is_secure_context(method) for method in conditionally_enabled_methods)
context.update({
'has_conditionally_enabled_secure_methods':
has_conditionally_enabled_secure_methods,
'conditionally_enabled_methods': conditionally_enabled_methods,
})
# Window.idl in Blink has indexed properties, but the spec says Window
# interface doesn't have indexed properties, instead the WindowProxy exotic
# object has indexed properties. Thus, Window interface must not support
# iterators.
has_array_iterator = (not interface.is_partial and
interface.has_indexed_elements and
interface.name != 'Window')
context.update({
'has_array_iterator': has_array_iterator,
'iterable': interface.iterable,
})
# Conditionally enabled members
prepare_prototype_and_interface_object_func = None # pylint: disable=invalid-name
if (unscopables or has_conditional_attributes_on_prototype or
context['conditionally_enabled_methods']):
prepare_prototype_and_interface_object_func = '%s::preparePrototypeAndInterfaceObject' % v8_class_name_or_partial # pylint: disable=invalid-name
has_install_conditional_features_on_global_func = has_conditionally_enabled_constructors # pylint: disable=invalid-name
context.update({
'prepare_prototype_and_interface_object_func': prepare_prototype_and_interface_object_func,
'has_install_conditional_features_on_global_func': has_install_conditional_features_on_global_func,
})
context.update({
'legacy_caller': legacy_caller(interface.legacy_caller, interface),
'indexed_property_getter': property_getter(interface.indexed_property_getter, ['index']),
'indexed_property_setter': property_setter(interface.indexed_property_setter, interface),
'indexed_property_deleter': property_deleter(interface.indexed_property_deleter),
'is_override_builtins': 'OverrideBuiltins' in extended_attributes,
'named_property_getter': property_getter(interface.named_property_getter, ['name']),
'named_property_setter': property_setter(interface.named_property_setter, interface),
'named_property_deleter': property_deleter(interface.named_property_deleter),
})
context.update({
'has_named_properties_object': is_global and context['named_property_getter'],
})
# Origin Trials and ContextEnabled features
context.update({
'optional_features':
sorted(origin_trial_features(interface, context['constants'], context['attributes'], context['methods']) +
context_enabled_features(context['attributes'])),
})
# Cross-origin interceptors
has_cross_origin_named_getter = False
has_cross_origin_named_setter = False
has_cross_origin_indexed_getter = False
for attribute in attributes:
if attribute['has_cross_origin_getter']:
has_cross_origin_named_getter = True
if attribute['has_cross_origin_setter']:
has_cross_origin_named_setter = True
# Methods are exposed as getter attributes on the interface: e.g.
# window.location gets the location attribute on the Window interface. For
# the cross-origin case, this attribute getter is guaranteed to only return
# a Function object, which the actual call is dispatched against.
for method in methods:
if method['is_cross_origin']:
has_cross_origin_named_getter = True
has_cross_origin_named_enumerator = has_cross_origin_named_getter or has_cross_origin_named_setter # pylint: disable=invalid-name
if context['named_property_getter'] and context['named_property_getter']['is_cross_origin']:
has_cross_origin_named_getter = True
if context['indexed_property_getter'] and context['indexed_property_getter']['is_cross_origin']:
has_cross_origin_indexed_getter = True
context.update({
'has_cross_origin_named_getter': has_cross_origin_named_getter,
'has_cross_origin_named_setter': has_cross_origin_named_setter,
'has_cross_origin_named_enumerator': has_cross_origin_named_enumerator,
'has_cross_origin_indexed_getter': has_cross_origin_indexed_getter,
})
return context