def interface_context()

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