summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py')
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py386
1 files changed, 0 insertions, 386 deletions
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py b/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
deleted file mode 100644
index 8845480e660..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
+++ /dev/null
@@ -1,386 +0,0 @@
-# Copyright (C) 2013 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Resolve interface dependencies, producing a merged IdlDefinitions object.
-
-This library computes interface dependencies (partial interfaces and
-includes), reads the dependency files, and merges them to the IdlDefinitions
-for the main IDL file, producing an IdlDefinitions object representing the
-entire interface.
-
-Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Dependency-resolution
-"""
-
-import os.path
-from utilities import idl_filename_to_component, is_valid_component_dependency, merge_dict_recursively
-
-# The following extended attributes can be applied to a dependency interface,
-# and are then applied to the individual members when merging.
-# Note that this moves the extended attribute from the interface to the member,
-# which changes the semantics and yields different code than the same extended
-# attribute on the main interface.
-DEPENDENCY_EXTENDED_ATTRIBUTES = frozenset([
- 'CrossOriginIsolated',
- 'DirectSocketEnabled',
- 'RuntimeEnabled',
- 'SecureContext',
-])
-
-
-class InterfaceDependencyResolver(object):
- def __init__(self, interfaces_info, reader):
- """Initialize dependency resolver.
-
- Args:
- interfaces_info:
- dict of interfaces information, from compute_dependencies.py
- reader:
- IdlReader, used for reading dependency files
- """
- self.interfaces_info = interfaces_info
- self.reader = reader
-
- def resolve_dependencies(self, definitions, component):
- """Resolve dependencies, merging them into IDL definitions of main file.
-
- Dependencies consist of 'partial interface' for the same interface as
- in the main file, and mixins that this interface 'includes'.
- These are merged into the main IdlInterface, as the main IdlInterface
- implements all these members.
-
- Partial interfaces and mixins are added to IdlDefinitions, but not
- merged into the main IdlInterface, as these are only referenced (their
- members are introspected, but not implemented in this interface).
-
- Inherited extended attributes are also added to the main IdlInterface.
-
- Modifies definitions in place by adding parsed dependencies.
-
- Args:
- definitions: IdlDefinitions object, modified in place
- component:
- string, describing where the above definitions are defined,
- 'core' or 'modules'. See KNOWN_COMPONENTS in utilities.py
-
- Returns:
- A dictionary whose key is component and value is IdlDefinitions
- object whose dependency is resolved.
-
- Raises:
- Exception:
- A given IdlDefinitions object doesn't have any interfaces,
- or a given IdlDefinitions object has incorrect referenced
- interfaces.
- """
- # TODO(crbug.com/579896): we need to resolve dependency when we
- # support partial dictionary.
- if not definitions.interfaces:
- raise Exception('No need to resolve any dependencies of '
- 'this definition: %s, because this should '
- 'have a dictionary.' % definitions.idl_name)
-
- target_interface = next(iter(definitions.interfaces.values()))
- interface_name = target_interface.name
- interface_info = self.interfaces_info[interface_name]
-
- if 'inherited_extended_attributes' in interface_info:
- target_interface.extended_attributes.update(
- interface_info['inherited_extended_attributes'])
-
- resolved_definitions = merge_interface_dependencies(
- definitions, component, target_interface,
- interface_info['dependencies_full_paths'] +
- interface_info['dependencies_other_component_full_paths'],
- self.reader)
-
- inherit_unforgeable_attributes(resolved_definitions,
- self.interfaces_info)
-
- for referenced_interface_name in \
- interface_info['referenced_interfaces']:
- referenced_definitions = self.reader.read_idl_definitions(
- self.interfaces_info[referenced_interface_name]['full_path'])
-
- for referenced_component in referenced_definitions:
- if not is_valid_component_dependency(component,
- referenced_component):
- raise Exception('This definitions: %s is defined in %s '
- 'but reference interface:%s is defined '
- 'in %s' % (definitions.idl_name, component,
- referenced_interface_name,
- referenced_component))
-
- resolved_definitions[component].update(
- referenced_definitions[component])
-
- return resolved_definitions
-
-
-def merge_interface_dependencies(definitions, component, target_interface,
- dependency_idl_filenames, reader):
- """Merge dependencies ('partial interface' and 'implements') in dependency_idl_filenames into target_interface.
-
- Args:
- definitions: IdlDefinitions object, modified in place
- component:
- string, describing where the above definitions are defined,
- 'core' or 'modules'. See KNOWN_COMPONENTS in utilities.py
- target_interface: IdlInterface object, modified in place
- dependency_idl_filenames:
- Idl filenames which depend on the above definitions.
- reader: IdlReader object.
- Returns:
- A dictionary whose key is component and value is IdlDefinitions
- object whose dependency is resolved.
- """
- resolved_definitions = {component: definitions}
- # Sort so order consistent, so can compare output from run to run.
- for dependency_idl_filename in sorted(dependency_idl_filenames):
- dependency_definitions = reader.read_idl_file(dependency_idl_filename)
- dependency_component = idl_filename_to_component(
- dependency_idl_filename)
-
- dependency_interface = next(
- iter(dependency_definitions.interfaces.values()))
-
- transfer_extended_attributes(dependency_interface,
- dependency_idl_filename)
-
- # We need to use different checkdeps here for partial interface and
- # inheritance.
- if dependency_interface.is_partial:
- # Case: dependency_interface is a partial interface of
- # target_interface.
- # So,
- # - A partial interface defined in modules can update
- # the original interface defined in core.
- # However,
- # - A partial interface defined in core cannot update
- # the original interface defined in modules.
- if not is_valid_component_dependency(dependency_component,
- component):
- raise Exception(
- 'The partial interface:%s in %s cannot update '
- 'the original interface:%s in %s' %
- (dependency_interface.name, dependency_component,
- target_interface.name, component))
-
- if dependency_component in resolved_definitions:
- # When merging a new partial interfaces, should not overwrite
- # ImpelemntedAs extended attributes in merged partial
- # interface.
- # See also the below "if 'ImplementedAs' not in ... " line's
- # comment.
- dependency_interface.extended_attributes.pop(
- 'ImplementedAs', None)
- resolved_definitions[dependency_component].update(
- dependency_definitions)
- continue
-
- dependency_interface.extended_attributes.update(
- target_interface.extended_attributes)
- assert target_interface == \
- definitions.interfaces[dependency_interface.name]
- # A partial interface should use its original interface's
- # ImplementedAs. If the original interface doesn't have,
- # remove ImplementedAs defined in the partial interface.
- # Because partial interface needs the original interface's
- # cpp class to obtain partial interface's cpp class.
- # e.g.. V8WindowPartial.cpp:
- # DOMWindow* impl = V8Window::ToImpl(holder);
- # DOMWindowQuota* cpp_value(DOMWindowQuota::webkitStorageInfo(impl));
- # TODO(tasak): remove ImplementedAs extended attributes
- # from all partial interfaces. Instead, rename all cpp/header
- # files correctly. ImplementedAs should not be allowed in
- # partial interfaces.
- if 'ImplementedAs' not in target_interface.extended_attributes:
- dependency_interface.extended_attributes.pop(
- 'ImplementedAs', None)
- dependency_interface.original_interface = target_interface
- target_interface.partial_interfaces.append(dependency_interface)
- resolved_definitions[dependency_component] = dependency_definitions
- else:
- # Case: |target_interface| includes |dependency_interface| mixin.
- # So,
- # - An interface defined in modules can include any interface mixin
- # defined in core.
- # However,
- # - An interface defined in core cannot include an interface mixin
- # defined in modules.
- if not dependency_interface.is_mixin:
- raise Exception(
- 'The interface:%s cannot include '
- 'the non-mixin interface: %s.' %
- (target_interface.name, dependency_interface.name))
-
- if not is_valid_component_dependency(component,
- dependency_component):
- raise Exception(
- 'The interface:%s in %s cannot include '
- 'the interface mixin:%s in %s.' %
- (target_interface.name, component,
- dependency_interface.name, dependency_component))
-
- # merges partial interfaces
- resolved_definitions[component].update(dependency_definitions)
- # Mixins are also merged into the target interface, so Code
- # Generator can just iterate over one list (and not need to handle
- # 'includes' itself).
- target_interface.merge(dependency_interface)
-
- return resolved_definitions
-
-
-def transfer_extended_attributes(dependency_interface,
- dependency_idl_filename):
- """Transfer extended attributes from dependency interface onto members.
-
- Merging consists of storing certain interface-level data in extended
- attributes of the *members* (because there is no separate dependency
- interface post-merging).
-
- The data storing consists of:
- * moving certain extended attributes from the dependency interface
- to its members (deleting the extended attribute from the interface)
- * storing the C++ class of the implementation in an internal
- extended attribute of each member, [PartialInterfaceImplementedAs]
-
- No return: modifies dependency_interface in place.
- """
- merged_extended_attributes = {}
- for key in DEPENDENCY_EXTENDED_ATTRIBUTES:
- if key not in dependency_interface.extended_attributes:
- continue
-
- merged_extended_attributes[key] = \
- dependency_interface.extended_attributes[key]
- # Remove the merged attributes from the original dependency interface.
- # This ensures that if other dependency interfaces are merged onto this
- # one, its extended_attributes do not leak through
- # (https://crbug.com/603782).
- del dependency_interface.extended_attributes[key]
-
- # A partial interface's members are implemented as static member functions
- # in a separate C++ class. This class name is stored in
- # [PartialInterfaceImplementedAs] which is copied from [ImplementedAs] on
- # the partial interface definition.
- #
- # Note that implemented interfaces do *not* need [ImplementedAs], since
- # they are implemented on the C++ object |impl| itself, just like members of
- # the main interface definition, so the bindings do not need to know in
- # which class implemented interfaces are implemented.
- #
- # Currently [LegacyTreatAsPartialInterface] can be used to have partial
- # interface behavior on mixins, but this is being removed as legacy cruft:
- # http://crbug.com/360435
- #
- # Note that [ImplementedAs] is used with different meanings on interfaces
- # and members:
- # for Blink class name and function name (or constant name), respectively.
- # Thus we do not want to copy this from the interface to the member, but
- # instead extract it and handle it separately.
- if dependency_interface.is_partial:
- if 'ImplementedAs' not in dependency_interface.extended_attributes:
- raise ValueError('Partial interface in %s must have ImplementedAs.'
- % dependency_idl_filename)
- merged_extended_attributes['PartialInterfaceImplementedAs'] = \
- dependency_interface.extended_attributes.pop('ImplementedAs')
- elif 'LegacyTreatAsPartialInterface' in \
- dependency_interface.extended_attributes:
- merged_extended_attributes['PartialInterfaceImplementedAs'] = (
- dependency_interface.extended_attributes.pop(
- 'ImplementedAs', dependency_interface.name))
-
- def update_attributes(attributes, extras):
- for key, value in extras.items():
- if key not in attributes:
- attributes[key] = value
-
- for attribute in dependency_interface.attributes:
- update_attributes(attribute.extended_attributes,
- merged_extended_attributes)
- for constant in dependency_interface.constants:
- update_attributes(constant.extended_attributes,
- merged_extended_attributes)
- for operation in dependency_interface.operations:
- update_attributes(operation.extended_attributes,
- merged_extended_attributes)
-
-
-def inherit_unforgeable_attributes(resolved_definitions, interfaces_info):
- """Inherits [LegacyUnforgeable] attributes and updates the arguments
- accordingly.
-
- For each interface in |resolved_definitions|, collects all
- [LegacyUnforgeable] attributes in ancestor interfaces and adds them to the
- interface. 'referenced_interfaces' and 'cpp_includes' in |interfaces_info|
- are updated accordingly.
- """
-
- def collect_unforgeable_attributes_in_ancestors(interface_name, component):
- if not interface_name:
- # unforgeable_attributes, referenced_interfaces, cpp_includes
- return [], [], set()
- interface = interfaces_info[interface_name]
- unforgeable_attributes, referenced_interfaces, cpp_includes = \
- collect_unforgeable_attributes_in_ancestors(
- interface.get('parent'), component)
- this_unforgeable = interface.get('unforgeable_attributes', [])
- for attr in this_unforgeable:
- if attr.defined_in is None:
- attr.defined_in = interface_name
- unforgeable_attributes.extend(this_unforgeable)
- this_referenced = [
- attr.idl_type.base_type for attr in this_unforgeable
- if attr.idl_type.base_type in interface.get(
- 'referenced_interfaces', [])
- ]
- referenced_interfaces.extend(this_referenced)
- cpp_includes.update(
- interface.get('cpp_includes', {}).get(component, {}))
- return unforgeable_attributes, referenced_interfaces, cpp_includes
-
- for component, definitions in resolved_definitions.items():
- for interface_name, interface in definitions.interfaces.items():
- interface_info = interfaces_info[interface_name]
- inherited_unforgeable_attributes, referenced_interfaces, cpp_includes = \
- collect_unforgeable_attributes_in_ancestors(
- interface_info.get('parent'), component)
- # This loop may process the same interface many times, so it's
- # possible that we're adding the same attributes twice or more.
- # So check if there is a duplicate.
- for attr in inherited_unforgeable_attributes:
- if attr not in interface.attributes:
- interface.attributes.append(attr)
- referenced_interfaces.extend(
- interface_info.get('referenced_interfaces', []))
- interface_info['referenced_interfaces'] = sorted(
- set(referenced_interfaces))
- merge_dict_recursively(interface_info,
- {'cpp_includes': {
- component: cpp_includes
- }})