summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/bindings/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/bindings/scripts')
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn4
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py23
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf1
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py47
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py406
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py63
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py717
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py456
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py211
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py181
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py20
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py158
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py54
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_format.py21
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py178
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py875
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py360
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py4405
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py107
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py34
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py180
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py107
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py188
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py25
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py56
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py17
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/code_generator.py88
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py117
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py18
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py30
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py139
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py90
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py56
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps6
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py59
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py91
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py137
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps51
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py47
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py120
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py162
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py60
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py324
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py38
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_types.py127
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py169
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py20
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py137
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py11
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/scripts.gni16
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/utilities.py140
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py458
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py53
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py76
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py245
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py1
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py981
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py522
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_types.py677
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_union.py82
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py162
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/.style.yapf1
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py24
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_function.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_interface.py8
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py7
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py23
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/constant.py10
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py20
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py45
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/demonstration_and_testing.idl2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/enumeration.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/exposure.py61
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py42
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute_test.py1
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py17
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/function_like.py20
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py292
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py303
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py6
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py351
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py96
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/migration_adapter.idl4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py10
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/operation.py53
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py53
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/user_defined_type.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/validator.py1
95 files changed, 12006 insertions, 3877 deletions
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn b/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn
index 8868829c30d..a6cc71426b1 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/scripts/BUILD.gn
@@ -37,9 +37,7 @@ action("cached_jinja_templates") {
# Dummy file to track dependency.
stamp_file = "$bindings_scripts_output_dir/cached_jinja_templates.stamp"
- outputs = [
- stamp_file,
- ]
+ outputs = [ stamp_file ]
args = [
rebase_path(bindings_scripts_output_dir, root_build_dir),
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py b/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
index e8a1fd2c9a9..71283002ba8 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
@@ -31,7 +31,6 @@
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Generates a .cpp file that includes all V8 binding .cpp files for interfaces.
It is expected to preserve symbol space, and to be acceptable to make static
@@ -47,6 +46,8 @@ Usage:
Design doc: http://www.chromium.org/developers/design-documents/idl-build
"""
+from __future__ import print_function
+
import errno
import optparse
import os
@@ -86,32 +87,35 @@ COPYRIGHT_TEMPLATE = """/*
*/
"""
+
def parse_options():
parser = optparse.OptionParser()
parser.add_option('--component')
options, args = parser.parse_args()
if len(args) < 2:
- raise Exception('Expected 2 filenames; one is for input, and the other is for output.')
+ raise Exception(
+ 'Expected 2 filenames; one is for input, and the other is for output.'
+ )
return options, args
def generate_content(component, basenames):
# Add fixed content.
- output = [COPYRIGHT_TEMPLATE,
- '#define NO_IMPLICIT_ATOMICSTRING\n\n']
+ output = [COPYRIGHT_TEMPLATE, '#define NO_IMPLICIT_ATOMICSTRING\n\n']
basenames.sort()
- output.extend('#include "third_party/blink/renderer/bindings/%s/v8/v8_%s.cc"\n' %
- (component, to_snake_case(basename)) for basename in basenames)
+ output.extend(
+ '#include "third_party/blink/renderer/bindings/%s/v8/v8_%s.cc"\n' %
+ (component, to_snake_case(basename)) for basename in basenames)
return ''.join(output)
def write_content(content, output_file_name):
parent_path, file_name = os.path.split(output_file_name)
if not os.path.exists(parent_path):
- print 'Creating directory: %s' % parent_path
+ print('Creating directory: %s' % parent_path)
os.makedirs(parent_path)
with open(output_file_name, 'w') as f:
f.write(content)
@@ -121,8 +125,9 @@ def main():
options, filenames = parse_options()
component = options.component
idl_filenames = read_idl_files_list_from_file(filenames[0])
- basenames = [idl_filename_to_basename(file_path)
- for file_path in idl_filenames]
+ basenames = [
+ idl_filename_to_basename(file_path) for file_path in idl_filenames
+ ]
file_contents = generate_content(component, basenames)
write_content(file_contents, filenames[1])
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf
index 0169b9a6487..2ae9158e446 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf
@@ -1,3 +1,4 @@
[style]
# https://www.chromium.org/blink/coding-style
based_on_style = pep8
+column_limit = 79
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
index 94a51e669b6..ab16bdb63da 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
@@ -3,7 +3,6 @@
# found in the LICENSE file.
import os.path
-import platform
import sys
@@ -13,9 +12,10 @@ def _setup_sys_path():
expected_path = 'third_party/blink/renderer/bindings/scripts/bind_gen/'
this_dir = os.path.dirname(__file__)
- root_dir = os.path.join(this_dir, *(['..'] * expected_path.count('/')))
+ root_dir = os.path.abspath(
+ os.path.join(this_dir, *(['..'] * expected_path.count('/'))))
- sys.path = [
+ module_dirs = (
# //third_party/blink/renderer/bindings/scripts/web_idl
os.path.join(root_dir, 'third_party', 'blink', 'renderer', 'bindings',
'scripts'),
@@ -24,37 +24,34 @@ def _setup_sys_path():
'scripts'),
# //third_party/mako/mako
os.path.join(root_dir, 'third_party', 'mako'),
- ] + sys.path
+ )
+ for module_dir in reversed(module_dirs):
+ # Preserve sys.path[0] as is.
+ # https://docs.python.org/3/library/sys.html?highlight=path[0]#sys.path
+ sys.path.insert(1, module_dir)
_setup_sys_path()
-
-from . import clang_format
+from . import style_format
from .dictionary import generate_dictionaries
+from .enumeration import generate_enumerations
from .interface import generate_interfaces
from .path_manager import PathManager
+from .union import generate_unions
-def _setup_clang_format():
- expected_path = 'third_party/blink/renderer/bindings/scripts/bind_gen/'
-
- this_dir = os.path.dirname(__file__)
- root_dir = os.path.join(this_dir, *(['..'] * expected_path.count('/')))
-
- # //third_party/depot_tools/clang-format
- command_name = ('clang-format.bat'
- if platform.system() == 'Windows' else 'clang-format')
- command_path = os.path.abspath(
- os.path.join(root_dir, 'third_party', 'depot_tools', command_name))
-
- clang_format.init(command_path=command_path)
-
-
-def init(output_dirs):
+def init(root_src_dir, root_gen_dir, component_reldirs):
"""
Args:
- output_dirs: Pairs of component and output directory.
+ root_src_dir: Project's root directory, which corresponds to "//" in GN.
+ root_gen_dir: Root directory of generated files, which corresponds to
+ "//out/Default/gen" in GN.
+ component_reldirs: Pairs of component and output directory.
"""
- _setup_clang_format()
- PathManager.init(output_dirs)
+ style_format.init(root_src_dir)
+
+ PathManager.init(
+ root_src_dir=root_src_dir,
+ root_gen_dir=root_gen_dir,
+ component_reldirs=component_reldirs)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
index 22438ad3c9f..495a813c64f 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
@@ -5,12 +5,13 @@
import web_idl
from . import name_style
-from .code_node import CodeNode
+from .code_node import Likeliness
from .code_node import SymbolDefinitionNode
from .code_node import SymbolNode
-from .code_node import SymbolScopeNode
from .code_node import TextNode
-from .code_node import UnlikelyExitNode
+from .code_node_cxx import CxxIfElseNode
+from .code_node_cxx import CxxLikelyIfNode
+from .code_node_cxx import CxxUnlikelyIfNode
from .codegen_format import format_template as _format
@@ -18,17 +19,32 @@ def blink_class_name(idl_definition):
"""
Returns the class name of Blink implementation.
"""
- try:
- class_name = idl_definition.extended_attributes.get(
- "ImplementedAs").value
- except:
- class_name = idl_definition.identifier
-
+ class_name = idl_definition.code_generator_info.receiver_implemented_as
+ if class_name:
+ return class_name
+
+ assert idl_definition.identifier[0].isupper()
+ # Do not apply |name_style.class_| in order to respect the original name
+ # (Web spec'ed name) as much as possible. For example, |interface EXTsRGB|
+ # is implemented as |class EXTsRGB|, not as |ExtSRgb| nor |ExtsRgb|.
if isinstance(idl_definition,
- (web_idl.CallbackFunction, web_idl.CallbackInterface)):
- return name_style.class_("v8", class_name)
+ (web_idl.CallbackFunction, web_idl.CallbackInterface,
+ web_idl.Enumeration)):
+ return "V8{}".format(idl_definition.identifier)
else:
- return name_style.class_(class_name)
+ return idl_definition.identifier
+
+
+def v8_bridge_class_name(idl_definition):
+ """
+ Returns the name of V8-from/to-Blink bridge class.
+ """
+ assert isinstance(idl_definition, (web_idl.Namespace, web_idl.Interface))
+
+ assert idl_definition.identifier[0].isupper()
+ # Do not apply |name_style.class_| due to the same reason as
+ # |blink_class_name|.
+ return "V8{}".format(idl_definition.identifier)
def blink_type_info(idl_type):
@@ -39,10 +55,11 @@ def blink_type_info(idl_type):
member_t: The type of a member variable. E.g. T => Member<T>
ref_t: The type of a local variable that references to an already-existing
value. E.g. String => String&
+ const_ref_t: A const-qualified reference type.
value_t: The type of a variable that behaves as a value. E.g. String =>
String
- is_nullable: True if the Blink implementation type can represent IDL null
- value by itself.
+ has_null_value: True if the Blink implementation type can represent IDL
+ null value by itself without use of base::Optional<T>.
"""
assert isinstance(idl_type, web_idl.IdlType)
@@ -51,13 +68,16 @@ def blink_type_info(idl_type):
typename,
member_fmt="{}",
ref_fmt="{}",
+ const_ref_fmt="const {}",
value_fmt="{}",
- is_nullable=False):
+ has_null_value=False):
+ self.typename = typename
self.member_t = member_fmt.format(typename)
self.ref_t = ref_fmt.format(typename)
+ self.const_ref_t = const_ref_fmt.format(typename)
self.value_t = value_fmt.format(typename)
# Whether Blink impl type can represent IDL null or not.
- self.is_nullable = is_nullable
+ self.has_null_value = has_null_value
real_type = idl_type.unwrap(typedef=True)
@@ -77,69 +97,150 @@ def blink_type_info(idl_type):
"double": "double",
"unrestricted double": "double",
}
- return TypeInfo(cxx_type[real_type.keyword_typename])
+ return TypeInfo(
+ cxx_type[real_type.keyword_typename], const_ref_fmt="{}")
if real_type.is_string:
- return TypeInfo("String", ref_fmt="{}&", is_nullable=True)
+ return TypeInfo(
+ "String",
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ value_fmt="bindings::NativeValueTraitsStringAdapter",
+ has_null_value=True)
+
+ if real_type.is_array_buffer:
+ assert "AllowShared" not in real_type.extended_attributes
+ return TypeInfo(
+ 'DOM{}'.format(real_type.keyword_typename),
+ member_fmt="Member<{}>",
+ ref_fmt="{}*",
+ const_ref_fmt="const {}*",
+ value_fmt="{}*",
+ has_null_value=True)
+
+ if real_type.is_buffer_source_type:
+ if "FlexibleArrayBufferView" in real_type.extended_attributes:
+ assert "AllowShared" in real_type.extended_attributes
+ return TypeInfo(
+ "Flexible{}".format(real_type.keyword_typename),
+ member_fmt="void",
+ ref_fmt="{}",
+ const_ref_fmt="const {}",
+ value_fmt="{}",
+ has_null_value=True)
+ elif "AllowShared" in real_type.extended_attributes:
+ return TypeInfo(
+ "MaybeShared<DOM{}>".format(real_type.keyword_typename),
+ has_null_value=True)
+ else:
+ return TypeInfo(
+ "NotShared<DOM{}>".format(real_type.keyword_typename),
+ has_null_value=True)
if real_type.is_symbol:
assert False, "Blink does not support/accept IDL symbol type."
if real_type.is_any or real_type.is_object:
- return TypeInfo("ScriptValue", ref_fmt="{}&", is_nullable=True)
+ return TypeInfo(
+ "ScriptValue",
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ has_null_value=True)
if real_type.is_void:
assert False, "Blink does not support/accept IDL void type."
+ if real_type.is_enumeration:
+ blink_impl_type = blink_class_name(real_type.type_definition_object)
+ return TypeInfo(blink_impl_type)
+
if real_type.type_definition_object is not None:
- type_def_obj = real_type.type_definition_object
- blink_impl_type = (
- type_def_obj.code_generator_info.receiver_implemented_as
- or name_style.class_(type_def_obj.identifier))
+ blink_impl_type = blink_class_name(real_type.type_definition_object)
return TypeInfo(
blink_impl_type,
member_fmt="Member<{}>",
ref_fmt="{}*",
+ const_ref_fmt="const {}*",
value_fmt="{}*",
- is_nullable=True)
+ has_null_value=True)
if (real_type.is_sequence or real_type.is_frozen_array
or real_type.is_variadic):
- element_type = blink_type_info(real_type.element_type)
+ element_type = real_type.element_type
+ element_type_info = blink_type_info(real_type.element_type)
+ if element_type.type_definition_object is not None:
+ # In order to support recursive IDL data structures, we have to
+ # avoid recursive C++ header inclusions and utilize C++ forward
+ # declarations. Since |VectorOf| requires complete type
+ # definition, |HeapVector<Member<T>>| is preferred as it
+ # requires only forward declaration.
+ vector_fmt = "HeapVector<Member<{}>>"
+ else:
+ vector_fmt = "VectorOf<{}>"
return TypeInfo(
- "VectorOf<{}>".format(element_type.value_t), ref_fmt="{}&")
+ vector_fmt.format(element_type_info.typename),
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&")
if real_type.is_record:
key_type = blink_type_info(real_type.key_type)
value_type = blink_type_info(real_type.value_type)
return TypeInfo(
- "VectorOfPairs<{}, {}>".format(key_type.value_t,
- value_type.value_t),
- ref_fmt="{}&")
+ "VectorOfPairs<{}, {}>".format(key_type.typename,
+ value_type.typename),
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&")
if real_type.is_promise:
- return TypeInfo("ScriptPromise", ref_fmt="{}&")
+ return TypeInfo(
+ "ScriptPromise", ref_fmt="{}&", const_ref_fmt="const {}&")
if real_type.is_union:
- return TypeInfo("ToBeImplementedUnion")
+ blink_impl_type = blink_class_name(real_type.union_definition_object)
+ return TypeInfo(
+ blink_impl_type,
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&",
+ has_null_value=True)
if real_type.is_nullable:
inner_type = blink_type_info(real_type.inner_type)
- if inner_type.is_nullable:
+ if inner_type.has_null_value:
return inner_type
return TypeInfo(
- "base::Optional<{}>".format(inner_type.value_t), ref_fmt="{}&")
+ "base::Optional<{}>".format(inner_type.value_t),
+ ref_fmt="{}&",
+ const_ref_fmt="const {}&")
+
+ assert False, "Unknown type: {}".format(idl_type.syntactic_form)
def native_value_tag(idl_type):
"""Returns the tag type of NativeValueTraits."""
assert isinstance(idl_type, web_idl.IdlType)
+ if idl_type.is_typedef:
+ if idl_type.identifier in ("EventHandler",
+ "OnBeforeUnloadEventHandler",
+ "OnErrorEventHandler"):
+ return "IDL{}".format(idl_type.identifier)
+
real_type = idl_type.unwrap(typedef=True)
- if (real_type.is_boolean or real_type.is_numeric or real_type.is_string
- or real_type.is_any or real_type.is_object):
- return "IDL{}".format(real_type.type_name)
+ if (real_type.is_boolean or real_type.is_numeric or real_type.is_any
+ or real_type.is_object):
+ return "IDL{}".format(
+ idl_type.type_name_with_extended_attribute_key_values)
+
+ if real_type.is_string:
+ return "IDL{}V2".format(
+ idl_type.type_name_with_extended_attribute_key_values)
+
+ if real_type.is_array_buffer:
+ return blink_type_info(real_type).typename
+
+ if real_type.is_buffer_source_type:
+ return blink_type_info(real_type).value_t
if real_type.is_symbol:
assert False, "Blink does not support/accept IDL symbol type."
@@ -147,13 +248,16 @@ def native_value_tag(idl_type):
if real_type.is_void:
assert False, "Blink does not support/accept IDL void type."
- if real_type.type_definition_object is not None:
- return blink_type_info(real_type).value_t
+ if real_type.type_definition_object:
+ return blink_class_name(real_type.type_definition_object)
if real_type.is_sequence:
return "IDLSequence<{}>".format(
native_value_tag(real_type.element_type))
+ if real_type.is_frozen_array:
+ return "IDLArray<{}>".format(native_value_tag(real_type.element_type))
+
if real_type.is_record:
return "IDLRecord<{}, {}>".format(
native_value_tag(real_type.key_type),
@@ -168,10 +272,140 @@ def native_value_tag(idl_type):
if real_type.is_nullable:
return "IDLNullable<{}>".format(native_value_tag(real_type.inner_type))
+ assert False, "Unknown type: {}".format(idl_type.syntactic_form)
+
+
+def make_default_value_expr(idl_type, default_value):
+ """
+ Returns a set of C++ expressions to be used for initialization with default
+ values. The returned object has the following attributes.
+
+ initializer: Used as "Type var(|initializer|);". This is None if
+ "Type var;" sets an appropriate default value.
+ assignment_value: Used as "var = |assignment_value|;".
+ """
+ assert default_value.is_type_compatible_with(idl_type)
+
+ class DefaultValueExpr:
+ def __init__(self, initializer, is_initializer_lightweight,
+ assignment_value):
+ assert initializer is None or isinstance(initializer, str)
+ assert isinstance(is_initializer_lightweight, bool)
+ assert isinstance(assignment_value, str)
+ self.initializer = initializer
+ self.is_initializer_lightweight = is_initializer_lightweight
+ self.assignment_value = assignment_value
+
+ if idl_type.unwrap(typedef=True).is_union:
+ union_type = idl_type.unwrap(typedef=True)
+ member_type = None
+ for member_type in union_type.flattened_member_types:
+ if default_value.is_type_compatible_with(member_type):
+ member_type = member_type
+ break
+ assert member_type is not None
+
+ union_class_name = blink_class_name(union_type.union_definition_object)
+ member_default_expr = make_default_value_expr(member_type,
+ default_value)
+ if default_value.idl_type.is_nullable:
+ initializer = None
+ assignment_value = _format("{}()", union_class_name)
+ else:
+ func_name = name_style.func("From", member_type.type_name)
+ argument = member_default_expr.assignment_value
+ initializer = _format("{}::{}({})", union_class_name, func_name,
+ argument)
+ assignment_value = initializer
+ return DefaultValueExpr(
+ initializer=initializer,
+ is_initializer_lightweight=False,
+ assignment_value=assignment_value)
+
+ type_info = blink_type_info(idl_type)
+
+ is_initializer_lightweight = False
+ if default_value.idl_type.is_nullable:
+ if idl_type.unwrap().type_definition_object is not None:
+ initializer = "nullptr"
+ is_initializer_lightweight = True
+ assignment_value = "nullptr"
+ elif idl_type.unwrap().is_string:
+ initializer = None # String::IsNull() by default
+ assignment_value = "String()"
+ elif idl_type.unwrap().is_buffer_source_type:
+ initializer = "nullptr"
+ is_initializer_lightweight = True
+ assignment_value = "nullptr"
+ elif type_info.value_t == "ScriptValue":
+ initializer = None # ScriptValue::IsEmpty() by default
+ assignment_value = "ScriptValue()"
+ elif idl_type.unwrap().is_union:
+ initializer = None # <union_type>::IsNull() by default
+ assignment_value = "{}()".format(type_info.value_t)
+ else:
+ assert not type_info.has_null_value
+ initializer = None # !base::Optional::has_value() by default
+ assignment_value = "base::nullopt"
+ elif default_value.idl_type.is_sequence:
+ initializer = None # VectorOf<T>::size() == 0 by default
+ assignment_value = "{}()".format(type_info.value_t)
+ elif default_value.idl_type.is_object:
+ dict_name = blink_class_name(idl_type.unwrap().type_definition_object)
+ value = _format("{}::Create()", dict_name)
+ initializer = value
+ assignment_value = value
+ elif default_value.idl_type.is_boolean:
+ value = "true" if default_value.value else "false"
+ initializer = value
+ is_initializer_lightweight = True
+ assignment_value = value
+ elif default_value.idl_type.is_integer:
+ initializer = default_value.literal
+ is_initializer_lightweight = True
+ assignment_value = default_value.literal
+ elif default_value.idl_type.is_floating_point_numeric:
+ if default_value.value == float("NaN"):
+ value_fmt = "std::numeric_limits<{type}>::quiet_NaN()"
+ elif default_value.value == float("Infinity"):
+ value_fmt = "std::numeric_limits<{type}>::infinity()"
+ elif default_value.value == float("-Infinity"):
+ value_fmt = "-std::numeric_limits<{type}>::infinity()"
+ else:
+ value_fmt = "{value}"
+ value = value_fmt.format(
+ type=type_info.value_t, value=default_value.literal)
+ initializer = value
+ is_initializer_lightweight = True
+ assignment_value = value
+ elif default_value.idl_type.is_string:
+ if idl_type.unwrap().is_string:
+ value = "\"{}\"".format(default_value.value)
+ initializer = value
+ assignment_value = value
+ elif idl_type.unwrap().is_enumeration:
+ enum_class_name = blink_class_name(
+ idl_type.unwrap().type_definition_object)
+ enum_value_name = name_style.constant(default_value.value)
+ initializer = "{}::Enum::{}".format(enum_class_name,
+ enum_value_name)
+ is_initializer_lightweight = True
+ assignment_value = "{}({})".format(enum_class_name, initializer)
+ else:
+ assert False
+ else:
+ assert False
+
+ return DefaultValueExpr(
+ initializer=initializer,
+ is_initializer_lightweight=is_initializer_lightweight,
+ assignment_value=assignment_value)
+
def make_v8_to_blink_value(blink_var_name,
v8_value_expr,
idl_type,
+ argument_index=None,
default_value=None):
"""
Returns a SymbolNode whose definition converts a v8::Value to a Blink value.
@@ -179,23 +413,71 @@ def make_v8_to_blink_value(blink_var_name,
assert isinstance(blink_var_name, str)
assert isinstance(v8_value_expr, str)
assert isinstance(idl_type, web_idl.IdlType)
+ assert (argument_index is None or isinstance(argument_index, (int, long)))
assert (default_value is None
or isinstance(default_value, web_idl.LiteralConstant))
- pattern = (
- "const auto& ${{{_1}}} = NativeValueTraits<{_2}>::NativeValue({_3});")
- _1 = blink_var_name
- _2 = native_value_tag(idl_type)
- _3 = ["${isolate}", v8_value_expr, "${exception_state}"]
- text = _format(pattern, _1=_1, _2=_2, _3=", ".join(_3))
+ T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
def create_definition(symbol_node):
- return SymbolDefinitionNode(symbol_node, [
- TextNode(text),
- UnlikelyExitNode(
- cond=TextNode("${exception_state}.HadException()"),
- body=SymbolScopeNode([TextNode("return;")])),
- ])
+ if argument_index is None:
+ func_name = "NativeValue"
+ arguments = ["${isolate}", v8_value_expr, "${exception_state}"]
+ else:
+ func_name = "ArgumentValue"
+ arguments = [
+ "${isolate}",
+ str(argument_index),
+ v8_value_expr,
+ "${exception_state}",
+ ]
+ if "StringContext" in idl_type.effective_annotations:
+ arguments.append("${execution_context_of_document_tree}")
+ blink_value_expr = _format(
+ "NativeValueTraits<{_1}>::{_2}({_3})",
+ _1=native_value_tag(idl_type),
+ _2=func_name,
+ _3=", ".join(arguments))
+
+ if default_value is None:
+ return SymbolDefinitionNode(symbol_node, [
+ F("auto&& ${{{}}} = {};", blink_var_name, blink_value_expr),
+ CxxUnlikelyIfNode(
+ cond="${exception_state}.HadException()",
+ body=T("return;")),
+ ])
+
+ nodes = []
+ type_info = blink_type_info(idl_type)
+ default_expr = make_default_value_expr(idl_type, default_value)
+ if default_expr.is_initializer_lightweight:
+ nodes.append(
+ F("{} ${{{}}}{{{}}};", type_info.value_t, blink_var_name,
+ default_expr.initializer))
+ else:
+ nodes.append(F("{} ${{{}}};", type_info.value_t, blink_var_name))
+ assignment = [
+ F("${{{}}} = {};", blink_var_name, blink_value_expr),
+ CxxUnlikelyIfNode(
+ cond="${exception_state}.HadException()", body=T("return;")),
+ ]
+ if (default_expr.initializer is None
+ or default_expr.is_initializer_lightweight):
+ nodes.append(
+ CxxLikelyIfNode(
+ cond="!{}->IsUndefined()".format(v8_value_expr),
+ body=assignment))
+ else:
+ nodes.append(
+ CxxIfElseNode(
+ cond="{}->IsUndefined()".format(v8_value_expr),
+ then=F("${{{}}} = {};", blink_var_name,
+ default_expr.assignment_value),
+ then_likeliness=Likeliness.LIKELY,
+ else_=assignment,
+ else_likeliness=Likeliness.LIKELY))
+ return SymbolDefinitionNode(symbol_node, nodes)
return SymbolNode(blink_var_name, definition_constructor=create_definition)
@@ -211,18 +493,26 @@ def make_v8_to_blink_value_variadic(blink_var_name, v8_array,
assert isinstance(v8_array_start_index, (int, long))
assert isinstance(idl_type, web_idl.IdlType)
- pattern = "const auto& ${{{_1}}} = ToImplArguments<{_2}>({_3});"
- _1 = blink_var_name
- _2 = native_value_tag(idl_type.element_type)
- _3 = [v8_array, str(v8_array_start_index), "${exception_state}"]
- text = _format(pattern, _1=_1, _2=_2, _3=", ".join(_3))
+ pattern = ("auto&& ${{{_1}}} = "
+ "bindings::VariadicArgumentsToNativeValues<{_2}>({_3});")
+ arguments = [
+ "${isolate}", v8_array,
+ str(v8_array_start_index), "${exception_state}"
+ ]
+ if "StringContext" in idl_type.element_type.effective_annotations:
+ arguments.append("${execution_context_of_document_tree}")
+ text = _format(
+ pattern,
+ _1=blink_var_name,
+ _2=native_value_tag(idl_type.element_type),
+ _3=", ".join(arguments))
def create_definition(symbol_node):
return SymbolDefinitionNode(symbol_node, [
TextNode(text),
- UnlikelyExitNode(
- cond=TextNode("${exception_state}.HadException()"),
- body=SymbolScopeNode([TextNode("return;")])),
+ CxxUnlikelyIfNode(
+ cond="${exception_state}.HadException()",
+ body=TextNode("return;")),
])
return SymbolNode(blink_var_name, definition_constructor=create_definition)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py
deleted file mode 100644
index ac060bc80da..00000000000
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os.path
-import subprocess
-
-_clang_format_command_path = None
-
-
-def init(command_path):
- """
- Args:
- command_path: Path to the clang_format command.
- """
- assert isinstance(command_path, str)
- assert os.path.exists(command_path)
-
- global _clang_format_command_path
- assert _clang_format_command_path is None
- _clang_format_command_path = command_path
-
-
-def clang_format(contents, filename=None):
- command_line = [_clang_format_command_path]
- if filename is not None:
- command_line.append('-assume-filename={}'.format(filename))
-
- proc = subprocess.Popen(
- command_line, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
- stdout_output, stderr_output = proc.communicate(input=contents)
- exit_code = proc.wait()
-
- return ClangFormatResult(
- stdout_output=stdout_output,
- stderr_output=stderr_output,
- exit_code=exit_code,
- filename=filename)
-
-
-class ClangFormatResult(object):
- def __init__(self, stdout_output, stderr_output, exit_code, filename):
- self._stdout_output = stdout_output
- self._stderr_output = stderr_output
- self._exit_code = exit_code
- self._filename = filename
-
- @property
- def did_succeed(self):
- return self._exit_code == 0
-
- @property
- def contents(self):
- assert self.did_succeed
- return self._stdout_output
-
- @property
- def error_message(self):
- return self._stderr_output
-
- @property
- def filename(self):
- return self._filename
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
index 53fe4fe1fce..2e29538399c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
@@ -8,11 +8,34 @@ provides a collection of the classes that represent code nodes independent from
specific bindings, such as ECMAScript bindings.
"""
-import copy
-
from .codegen_accumulator import CodeGenAccumulator
from .codegen_format import format_template
from .mako_renderer import MakoRenderer
+from .mako_renderer import MakoTemplate
+
+
+def render_code_node(code_node):
+ """
+ Renders |code_node| and turns it into text letting |code_node| apply all
+ necessary changes (side effects). Returns the resulting text.
+ """
+ assert isinstance(code_node, CodeNode)
+ assert code_node.outer is None
+
+ renderer = code_node.renderer
+ accumulator = code_node.accumulator
+
+ accumulated_size = accumulator.total_size()
+ while True:
+ prev_accumulated_size = accumulated_size
+ renderer.reset()
+ code_node.render(renderer)
+ accumulated_size = accumulator.total_size()
+ if (renderer.is_rendering_complete()
+ and accumulated_size == prev_accumulated_size):
+ break
+
+ return renderer.to_text()
class Likeliness(object):
@@ -58,10 +81,15 @@ class CodeNode(object):
"""
def __init__(self):
- # Symbols used in generated code, but not yet defined. See also
- # SymbolNode. Code symbols are accumulated in order from the first
- # appearance to the last. This order affects the insertion order of
- # SymbolDefinitionNodes at SymbolScopeNode.
+ # List of SymbolNodes that are defined at this point of rendering.
+ # Used to determine whether a certain symbol is already defined by
+ # this point of rendering.
+ self.defined_code_symbols = []
+
+ # List of SymbolNodes that are not yet defined at this point of
+ # rendering. SymbolNodes are accumulated in order of their first
+ # appearance. The order affects the insertion order of
+ # SymbolDefinitionNodes.
self.undefined_code_symbols = []
# Dict from a SymbolNode to a set of tuples of SymbolScopeNodes
@@ -89,7 +117,7 @@ class CodeNode(object):
# (Scope1, Scope2A, Scope3), # [1]
# (Scope1, Scope2B), # [4]
# ])
- self.undefined_code_symbols_scope_chains = {}
+ self.symbol_to_scope_chains = {}
_gensym_seq_id = 0
@@ -135,11 +163,18 @@ class CodeNode(object):
self._prev = None
# Mako's template text, bindings dict
- self._template_text = template_text
- self._template_vars = {}
+ if template_text is None:
+ self._template = None
+ else:
+ self._template = MakoTemplate(template_text)
+
+ # Template variable bindings
+ self._own_template_vars = None
+ self._base_template_vars = None
+ self._cached_template_vars = None
self._accumulator = None # CodeGenAccumulator
- self._accumulate_requests = []
+ self._accumulate_requests = None
self._renderer = None # MakoRenderer
@@ -151,36 +186,42 @@ class CodeNode(object):
def __str__(self):
"""
- Renders this CodeNode object into a Mako template. This is supposed to
- be used in a Mako template as ${code_node}.
+ Renders this CodeNode object directly into the renderer's text buffer
+ and always returns the empty string. This is because it's faster to
+ accumulate the rendering result directly in a single text buffer than
+ making a lot of string pieces and concatenating them.
+
+ This function is supposed to be used in a Mako template as ${code_node}.
"""
- return self.render()
+ renderer = self.renderer
+ assert renderer
- def render(self):
+ self.render(renderer)
+ return ""
+
+ def render(self, renderer):
"""
Renders this CodeNode object as a text string and also propagates
updates to related CodeNode objects. As this method has side-effects
not only to this object but also other related objects, the resulting
text may change on each invocation.
"""
- assert self.renderer
-
last_render_state = self._render_state
self._render_state = CodeNode._RenderState()
self._is_rendering = True
try:
- text = self._render(
- renderer=self.renderer, last_render_state=last_render_state)
+ self._render(
+ renderer=renderer, last_render_state=last_render_state)
finally:
self._is_rendering = False
if self._accumulate_requests:
- assert self.accumulator
+ accumulator = self.accumulator
+ assert accumulator
for request in self._accumulate_requests:
- request(self.accumulator)
-
- return text
+ request(accumulator)
+ self._accumulate_requests = None
def _render(self, renderer, last_render_state):
"""
@@ -189,10 +230,9 @@ class CodeNode(object):
Only limited subclasses may override this method.
"""
- assert self._template_text is not None
- return renderer.render(
+ renderer.render(
caller=self,
- template_text=self._template_text,
+ template=self._template,
template_vars=self.template_vars)
@property
@@ -223,65 +263,112 @@ class CodeNode(object):
assert isinstance(prev, CodeNode) or prev is None
self._prev = prev
- @property
- def upstream_of_scope(self):
- """
- Returns the upstream CodeNode in the same or outer scope. Only the set
- of recursively-collected |upstream_of_scope|s can bring symbol
- definitions effective to this node.
- """
- if self.prev is None:
- return self.outer
-
- node = self.prev
- while isinstance(node, SequenceNode):
+ def outer_scope(self):
+ """Returns the outer scope closest to this scope or None."""
+ node = self.outer
+ while node is not None:
if isinstance(node, SymbolScopeNode):
- return node.upstream_of_scope
- if not node:
- break
- node = node[-1]
+ return node
+ node = node.outer
+ return None
+
+ def outermost(self):
+ """Returns the outermost node, i.e. the node whose |outer| is None."""
+ node = self
+ while node.outer is not None:
+ node = node.outer
return node
+ def inclusive_outers(self):
+ """
+ Returns a list of outer nodes including this node in order from this
+ node to the outermost node.
+ """
+ outers = []
+ node = self
+ while node is not None:
+ outers.append(node)
+ node = node.outer
+ return outers
+
@property
def template_vars(self):
"""
Returns the template variable bindings available at this point, i.e.
bound at this node or outer nodes.
- CAUTION: Do not modify the returned dict. This method may return the
- original dict in a CodeNode.
+ CAUTION: This accessor caches the result. This accessor must not be
+ called during construction of a code node tree.
"""
- if not self.outer:
- return self._template_vars
+ if self._cached_template_vars is not None:
+ return self._cached_template_vars
- if not self._template_vars:
- return self.outer.template_vars
+ outers = self.inclusive_outers()
+ bindings = None
- binds = copy.copy(self.outer.template_vars)
- for name, value in self._template_vars.iteritems():
- assert name not in binds, (
- "Duplicated template variable binding: {}".format(name))
- binds[name] = value
- return binds
+ for node in outers:
+ if node.base_template_vars is not None:
+ bindings = dict(node.base_template_vars)
+ break
+ if bindings is None:
+ bindings = {}
+
+ for node in outers:
+ if node.own_template_vars is None:
+ continue
+ for name, value in node.own_template_vars.items():
+ assert name not in bindings, (
+ "Duplicated template variable binding: {}".format(name))
+ bindings[name] = value
+
+ self._cached_template_vars = bindings
+ return self._cached_template_vars
+
+ @property
+ def own_template_vars(self):
+ """Returns the template variables bound at this code node."""
+ return self._own_template_vars
def add_template_var(self, name, value):
- assert name not in self._template_vars, (
+ if self._own_template_vars is None:
+ self._own_template_vars = {}
+ assert isinstance(name, str)
+ assert name not in self._own_template_vars, (
"Duplicated template variable binding: {}".format(name))
if isinstance(value, CodeNode):
value.set_outer(self)
- self._template_vars[name] = value
+ self._own_template_vars[name] = value
def add_template_vars(self, template_vars):
assert isinstance(template_vars, dict)
- for name, value in template_vars.iteritems():
+ for name, value in template_vars.items():
self.add_template_var(name, value)
@property
+ def base_template_vars(self):
+ """
+ Returns the base template variables if it's set at this code node.
+
+ The base template variables are a set of template variables that of
+ the innermost code node takes effect. It means that the base template
+ variables are layered and shadowable.
+ """
+ return self._base_template_vars
+
+ def set_base_template_vars(self, template_vars):
+ assert isinstance(template_vars, dict)
+ for name, value in template_vars.items():
+ assert isinstance(name, str)
+ assert not isinstance(value, CodeNode)
+ assert self._base_template_vars is None
+ self._base_template_vars = template_vars
+
+ @property
def accumulator(self):
# Always consistently use the accumulator of the root node.
- if self.outer is not None:
- return self.outer.accumulator
- return self._accumulator
+ if self.outer is None:
+ return self._accumulator
+ return self.outermost().accumulator
def set_accumulator(self, accumulator):
assert isinstance(accumulator, CodeGenAccumulator)
@@ -294,15 +381,16 @@ class CodeNode(object):
argument of self.accumulator.
"""
assert callable(request)
+ if self._accumulate_requests is None:
+ self._accumulate_requests = []
self._accumulate_requests.append(request)
@property
def renderer(self):
- # Always use the renderer of the root node in order not to mix renderers
- # during rendering of a single code node tree.
- if self.outer is not None:
- return self.outer.renderer
- return self._renderer
+ # Always consistently use the renderer of the root node.
+ if self.outer is None:
+ return self._renderer
+ return self.outermost().renderer
def set_renderer(self, renderer):
assert isinstance(renderer, MakoRenderer)
@@ -319,53 +407,68 @@ class CodeNode(object):
assert not self._is_rendering
return self._render_state
- def is_code_symbol_defined(self, symbol_node):
- """
- Returns True if |symbol_node| is defined at this point or upstream.
- """
- if self.outer:
- return self.upstream_of_scope.is_code_symbol_defined(symbol_node)
- return False
-
- def is_code_symbol_registered(self, symbol_node):
- """
- Returns True if |symbol_node| is registered and available for use at
- this point. See also |SymbolScopeNode.register_code_symbol|.
- """
- if self.outer is not None:
- return self.outer.is_code_symbol_registered(symbol_node)
- return False
-
- def on_undefined_code_symbol_found(self, symbol_node, symbol_scope_chain):
- """Receives a report of use of an undefined symbol node."""
+ def on_code_symbol_referenced(self, symbol_node, symbol_scope_chain):
+ """Receives a report of use of a symbol node."""
assert isinstance(symbol_node, SymbolNode)
assert isinstance(symbol_scope_chain, tuple)
assert all(
isinstance(scope, SymbolScopeNode) for scope in symbol_scope_chain)
- state = self.current_render_state
- if symbol_node not in state.undefined_code_symbols:
- state.undefined_code_symbols.append(symbol_node)
- state.undefined_code_symbols_scope_chains.setdefault(
+ self.current_render_state.symbol_to_scope_chains.setdefault(
symbol_node, set()).add(symbol_scope_chain)
+class EmptyNode(CodeNode):
+ """Represents the zero-length text and renders nothing."""
+
+ def __init__(self):
+ CodeNode.__init__(self)
+
+ def _render(self, renderer, last_render_state):
+ pass
+
+
class LiteralNode(CodeNode):
"""
Represents a literal text, which will be rendered as is without any template
- magic applied.
+ magic applied. The given literal text object will be stringified on each
+ rendering.
"""
def __init__(self, literal_text):
- literal_text_gensym = CodeNode.gensym()
- template_text = format_template(
- "${{{literal_text}}}", literal_text=literal_text_gensym)
- template_vars = {literal_text_gensym: literal_text}
+ CodeNode.__init__(self)
- CodeNode.__init__(
- self, template_text=template_text, template_vars=template_vars)
+ self._literal_text = literal_text
+
+ def _render(self, renderer, last_render_state):
+ renderer.push_caller(self)
+ try:
+ renderer.render_text(str(self._literal_text))
+ finally:
+ renderer.pop_caller()
+
+
+def TextNode(template_text):
+ """
+ Represents a template text node.
+ TextNode is designed to be a leaf node of a code node tree. TextNode
+ represents a template text while LiteralNode represents a literal text.
+ All template magics will be applied to |template_text|.
-class TextNode(CodeNode):
+ This function is pretending to be a CodeNode subclass and instantiates one
+ of text-ish code node subclass depending on the content of |template_text|.
+ """
+ assert isinstance(template_text, str)
+
+ if "$" in template_text or "%" in template_text:
+ return _TextNode(template_text)
+ elif template_text:
+ return LiteralNode(template_text)
+ else:
+ return EmptyNode()
+
+
+class _TextNode(CodeNode):
"""
Represents a template text node.
@@ -404,7 +507,7 @@ class CompositeNode(CodeNode):
gensym = CodeNode.gensym()
gensym_args.append("${{{}}}".format(gensym))
template_vars[gensym] = arg
- for key, value in kwargs.iteritems():
+ for key, value in kwargs.items():
assert isinstance(key, (int, long, str))
assert isinstance(value, (CodeNode, int, long, str))
gensym = CodeNode.gensym()
@@ -425,31 +528,27 @@ class ListNode(CodeNode):
except that addition and removal of None have no effect.
"""
- def __init__(self, code_nodes=None, separator=" ", separator_last=""):
+ def __init__(self, code_nodes=None, separator="\n", head="", tail=""):
+ """
+ Args:
+ code_nodes: A list of CodeNode to be rendered.
+ separator: A str inserted between code nodes.
+ head:
+ tail: The head and tail sections that will be rendered iff the
+ content list is not empty.
+ """
assert isinstance(separator, str)
- assert isinstance(separator_last, str)
-
- element_nodes_gensym = CodeNode.gensym()
- element_nodes = []
- template_text = format_template(
- """\
-% for node in {element_nodes}:
-${node}\\
-% if not loop.last:
-{separator}\\
-% endif
-% endfor
-{separator_last}\\
-""",
- element_nodes=element_nodes_gensym,
- separator=separator,
- separator_last=separator_last)
- template_vars = {element_nodes_gensym: element_nodes}
+ assert isinstance(head, str)
+ assert isinstance(tail, str)
- CodeNode.__init__(
- self, template_text=template_text, template_vars=template_vars)
+ CodeNode.__init__(self)
- self._element_nodes = element_nodes
+ self._element_nodes = []
+ self._separator = separator
+ self._head = head
+ self._tail = tail
+
+ self._will_skip_separator = False
if code_nodes is not None:
self.extend(code_nodes)
@@ -463,6 +562,26 @@ ${node}\\
def __len__(self):
return len(self._element_nodes)
+ def _render(self, renderer, last_render_state):
+ renderer.push_caller(self)
+ try:
+ if self._element_nodes:
+ renderer.render_text(self._head)
+ self._will_skip_separator = True
+ for node in self._element_nodes:
+ if self._will_skip_separator:
+ self._will_skip_separator = False
+ else:
+ renderer.render_text(self._separator)
+ node.render(renderer)
+ if self._element_nodes:
+ renderer.render_text(self._tail)
+ finally:
+ renderer.pop_caller()
+
+ def skip_separator(self):
+ self._will_skip_separator = True
+
def append(self, node):
if node is None:
return
@@ -523,25 +642,30 @@ class SequenceNode(ListNode):
and provides the points where SymbolDefinitionNodes can be inserted.
"""
- def __init__(self, code_nodes=None, separator="\n", separator_last=""):
+ def __init__(self, code_nodes=None, separator="\n", head="", tail=""):
ListNode.__init__(
self,
code_nodes=code_nodes,
separator=separator,
- separator_last=separator_last)
+ head=head,
+ tail=tail)
+
+ self._to_be_removed = []
def _render(self, renderer, last_render_state):
- duplicates = []
- for element_node in self:
- if (isinstance(element_node, SymbolDefinitionNode)
- and element_node.is_duplicated()):
- duplicates.append(element_node)
- for element_node in duplicates:
- self.remove(element_node)
-
- return super(SequenceNode, self)._render(
+ if self._to_be_removed:
+ for node in self._to_be_removed:
+ self.remove(node)
+ self._to_be_removed = []
+
+ super(SequenceNode, self)._render(
renderer=renderer, last_render_state=last_render_state)
+ def schedule_to_remove(self, node):
+ """Schedules a task to remove the |node| in the next rendering cycle."""
+ assert node in self
+ self._to_be_removed.append(node)
+
class SymbolScopeNode(SequenceNode):
"""
@@ -551,52 +675,72 @@ class SymbolScopeNode(SequenceNode):
insert corresponding SymbolDefinitionNodes appropriately.
"""
- def __init__(self, code_nodes=None, separator="\n", separator_last=""):
+ def __init__(self, code_nodes=None, separator="\n", head="", tail=""):
SequenceNode.__init__(
self,
code_nodes=code_nodes,
separator=separator,
- separator_last=separator_last)
+ head=head,
+ tail=tail)
self._likeliness = Likeliness.ALWAYS
self._registered_code_symbols = set()
def _render(self, renderer, last_render_state):
for symbol_node in last_render_state.undefined_code_symbols:
- if (self.is_code_symbol_registered(symbol_node)
- and not self.is_code_symbol_defined(symbol_node)):
+ assert self.is_code_symbol_registered(symbol_node)
+ if not self.is_code_symbol_defined(symbol_node):
self._insert_symbol_definition(symbol_node, last_render_state)
- return super(SymbolScopeNode, self)._render(
+ super(SymbolScopeNode, self)._render(
renderer=renderer, last_render_state=last_render_state)
+ if self.current_render_state.undefined_code_symbols:
+ renderer.invalidate_rendering_result()
+
def _insert_symbol_definition(self, symbol_node, last_render_state):
- def count_by_likeliness(render_state):
- counts = {
- Likeliness.UNLIKELY: 0,
- Likeliness.LIKELY: 0,
- Likeliness.ALWAYS: 0,
- }
-
- scope_chains = (render_state.undefined_code_symbols_scope_chains.
- get(symbol_node))
+ DIRECT_USES = "u"
+ DIRECT_CHILD_SCOPES = "s"
+ ANALYSIS_RESULT_KEYS = (
+ # Number of direct uses in this scope
+ DIRECT_USES,
+ # Number of direct child scopes
+ DIRECT_CHILD_SCOPES,
+ # Number of direct child scopes per likeliness
+ Likeliness.ALWAYS,
+ Likeliness.LIKELY,
+ Likeliness.UNLIKELY,
+ )
+
+ def analyze_symbol_usage(render_state):
+ counts = dict.fromkeys(ANALYSIS_RESULT_KEYS, 0)
+
+ scope_chains = render_state.symbol_to_scope_chains.get(symbol_node)
if not scope_chains:
return counts
self_index = iter(scope_chains).next().index(self)
scope_chains = map(
lambda scope_chain: scope_chain[self_index + 1:], scope_chains)
+ scope_to_likeliness = {}
for scope_chain in scope_chains:
if not scope_chain:
- counts[Likeliness.ALWAYS] += 1
+ counts[DIRECT_USES] += 1
else:
likeliness = min(
map(lambda scope: scope.likeliness, scope_chain))
- counts[likeliness] += 1
+ scope = scope_chain[0]
+ scope_to_likeliness[scope] = max(
+ likeliness, scope_to_likeliness.get(scope, likeliness))
+ for likeliness in scope_to_likeliness.values():
+ counts[DIRECT_CHILD_SCOPES] += 1
+ counts[likeliness] += 1
return counts
def likeliness_at(render_state):
- counts = count_by_likeliness(render_state)
+ counts = analyze_symbol_usage(render_state)
+ if counts[DIRECT_USES] >= 1:
+ return Likeliness.ALWAYS
for likeliness in (Likeliness.ALWAYS, Likeliness.LIKELY,
Likeliness.UNLIKELY):
if counts[likeliness] > 0:
@@ -616,21 +760,32 @@ class SymbolScopeNode(SequenceNode):
return True
return False
- counts = count_by_likeliness(last_render_state)
- if counts[Likeliness.ALWAYS] >= 1:
+ counts = analyze_symbol_usage(last_render_state)
+ if counts[DIRECT_USES] >= 1:
did_insert = insert_before_threshold(self, Likeliness.UNLIKELY)
assert did_insert
- elif counts[Likeliness.LIKELY] >= 2:
+ elif counts[DIRECT_CHILD_SCOPES] == 1:
+ pass # Let the child SymbolScopeNode do the work.
+ elif counts[Likeliness.ALWAYS] + counts[Likeliness.LIKELY] >= 2:
did_insert = insert_before_threshold(self, Likeliness.LIKELY)
assert did_insert
else:
- pass # Do nothing and let descendant SymbolScopeNodes do the work.
+ pass # Let descendant SymbolScopeNodes do the work.
def is_code_symbol_registered(self, symbol_node):
+ """
+ Returns True if |symbol_node| is registered and available for use within
+ this scope.
+ """
+ assert isinstance(symbol_node, SymbolNode)
+
if symbol_node in self._registered_code_symbols:
return True
- return super(SymbolScopeNode,
- self).is_code_symbol_registered(symbol_node)
+
+ outer = self.outer_scope()
+ if outer is None:
+ return False
+ return outer.is_code_symbol_registered(symbol_node)
def register_code_symbol(self, symbol_node):
"""Registers a SymbolNode and makes it available in this scope."""
@@ -655,6 +810,33 @@ class SymbolScopeNode(SequenceNode):
assert isinstance(likeliness, Likeliness.Level)
self._likeliness = likeliness
+ def is_code_symbol_defined(self, symbol_node):
+ """
+ Returns True if |symbol_node| is defined in this scope by the moment
+ when the method is called.
+ """
+ assert isinstance(symbol_node, SymbolNode)
+
+ if symbol_node in self.current_render_state.defined_code_symbols:
+ return True
+
+ outer = self.outer_scope()
+ if outer is None:
+ return False
+ return outer.is_code_symbol_defined(symbol_node)
+
+ def on_code_symbol_defined(self, symbol_node):
+ """Receives a report that a symbol gets defined."""
+ assert isinstance(symbol_node, SymbolNode)
+ self.current_render_state.defined_code_symbols.append(symbol_node)
+
+ def on_undefined_code_symbol_found(self, symbol_node):
+ """Receives a report of use of an undefined symbol node."""
+ assert isinstance(symbol_node, SymbolNode)
+ state = self.current_render_state
+ if symbol_node not in state.undefined_code_symbols:
+ state.undefined_code_symbols.append(symbol_node)
+
class SymbolNode(CodeNode):
"""
@@ -676,19 +858,14 @@ class SymbolNode(CodeNode):
given.
"""
assert isinstance(name, str) and name
- assert (template_text is not None
- or definition_constructor is not None)
- assert template_text is None or definition_constructor is None
- if template_text is not None:
- assert isinstance(template_text, str)
- if definition_constructor is not None:
- assert callable(definition_constructor)
CodeNode.__init__(self)
self._name = name
if template_text is not None:
+ assert isinstance(template_text, str)
+ assert definition_constructor is None
def constructor(symbol_node):
return SymbolDefinitionNode(
@@ -697,19 +874,34 @@ class SymbolNode(CodeNode):
self._definition_constructor = constructor
else:
+ assert template_text is None
+ assert callable(definition_constructor)
+
self._definition_constructor = definition_constructor
def _render(self, renderer, last_render_state):
+ self._request_symbol_definition(renderer)
+
+ renderer.render_text(self.name)
+
+ def request_symbol_definition(self):
+ self._request_symbol_definition(self.renderer)
+
+ def _request_symbol_definition(self, renderer):
symbol_scope_chain = tuple(
filter(lambda node: isinstance(node, SymbolScopeNode),
renderer.callers_from_first_to_last))
for caller in renderer.callers_from_last_to_first:
- if caller.is_code_symbol_defined(self):
+ caller.on_code_symbol_referenced(self, symbol_scope_chain)
+ if caller is self.outer:
break
- caller.on_undefined_code_symbol_found(self, symbol_scope_chain)
- return self.name
+ if not symbol_scope_chain[-1].is_code_symbol_defined(self):
+ for scope in reversed(symbol_scope_chain):
+ scope.on_undefined_code_symbol_found(self)
+ if scope is self.outer:
+ break
@property
def name(self):
@@ -719,7 +911,7 @@ class SymbolNode(CodeNode):
"""Creates a new definition node."""
node = self._definition_constructor(self)
assert isinstance(node, SymbolDefinitionNode)
- assert node.is_code_symbol_defined(self)
+ assert node.target_symbol is self
return node
@@ -739,195 +931,18 @@ class SymbolDefinitionNode(SequenceNode):
self._symbol_node = symbol_node
def _render(self, renderer, last_render_state):
- if self.is_duplicated():
- return ""
-
- return super(SymbolDefinitionNode, self)._render(
- renderer=renderer, last_render_state=last_render_state)
-
- def is_code_symbol_defined(self, symbol_node):
- if symbol_node is self._symbol_node:
- return True
- return super(SymbolDefinitionNode,
- self).is_code_symbol_defined(symbol_node)
-
- def is_duplicated(self):
- return self.upstream_of_scope.is_code_symbol_defined(self._symbol_node)
-
-
-class ConditionalNode(CodeNode):
- """
- This is the base class of code nodes that directly contain conditional
- execution. Not all the code nodes inside this node will be executed.
- """
-
-
-class CaseBranchNode(ConditionalNode):
- """
- Represents a set of nodes that will be conditionally executed.
-
- This node mostly follows the concept of 'cond' in Lisp, which is a chain of
- if - else if - else if - ... - else.
- """
-
- def __init__(self, clause_nodes):
- # clause_nodes = [
- # (conditional_node1, body_node1, likeliness1),
- # (conditional_node2, body_node2, likeliness2),
- # ...,
- # (None, body_nodeN, likelinessN), # Corresponds to 'else { ... }'
- # ]
- assert False
-
-
-class ConditionalExitNode(ConditionalNode):
- """
- Represents a conditional node that always exits whenever the condition
- meets. It's not supposed that the body node does not exit. Equivalent to
-
- if (CONDITIONAL) { BODY }
-
- where BODY ends with a return statement.
- """
-
- def __init__(self, cond, body, body_likeliness):
- assert isinstance(cond, CodeNode)
- assert isinstance(body, SymbolScopeNode)
- assert isinstance(body_likeliness, Likeliness.Level)
-
- gensyms = {
- "conditional": CodeNode.gensym(),
- "body": CodeNode.gensym(),
- }
- template_text = format_template(
- """\
-if (${{{conditional}}}) {{
- ${{{body}}}
-}}\\
-""", **gensyms)
- template_vars = {
- gensyms["conditional"]: cond,
- gensyms["body"]: body,
- }
-
- ConditionalNode.__init__(
- self, template_text=template_text, template_vars=template_vars)
-
- self._cond_node = cond
- self._body_node = body
- self._body_node.set_likeliness(body_likeliness)
-
-
-class LikelyExitNode(ConditionalExitNode):
- """
- Represents a conditional exit node where it's likely that the condition
- meets.
- """
-
- def __init__(self, cond, body):
- ConditionalExitNode.__init__(
- self, cond=cond, body=body, body_likeliness=Likeliness.LIKELY)
-
-
-class UnlikelyExitNode(ConditionalExitNode):
- """
- Represents a conditional exit node where it's unlikely that the condition
- meets.
- """
-
- def __init__(self, cond, body):
- ConditionalExitNode.__init__(
- self, cond=cond, body=body, body_likeliness=Likeliness.UNLIKELY)
-
-
-class FunctionDefinitionNode(CodeNode):
- """Represents a function definition."""
-
- def __init__(self,
- name,
- arg_decls,
- return_type,
- member_initializer_list=None,
- local_vars=None,
- body=None,
- comment=None):
- """
- Args:
- name: Function name node, which may include nested-name-specifier
- (i.e. 'namespace_name::' and/or 'type_name::').
- arg_decls: List of argument declaration nodes.
- return_type: Return type node.
- member_initializer_list: List of initializer nodes.
- local_vars: List of SymbolNodes that can be used in the function
- body.
- body: Function body node (of type SymbolScopeNode).
- comment: Function header comment node.
- """
- assert isinstance(name, CodeNode)
- assert isinstance(arg_decls, (list, tuple))
- assert all(isinstance(arg_decl, CodeNode) for arg_decl in arg_decls)
- assert isinstance(return_type, CodeNode)
- if member_initializer_list is None:
- member_initializer_list = []
- assert isinstance(member_initializer_list, (list, tuple))
- assert all(
- isinstance(initializer, CodeNode)
- for initializer in member_initializer_list)
- if local_vars is None:
- local_vars = []
- assert isinstance(local_vars, (list, tuple))
- assert all(
- isinstance(local_var, SymbolNode) for local_var in local_vars)
- if body is None:
- body = SymbolScopeNode()
- assert isinstance(body, CodeNode)
- if comment is None:
- comment = LiteralNode("")
- assert isinstance(comment, CodeNode)
-
- gensyms = {
- "name": CodeNode.gensym(),
- "arg_decls": CodeNode.gensym(),
- "return_type": CodeNode.gensym(),
- "member_initializer_list": CodeNode.gensym(),
- "body": CodeNode.gensym(),
- "comment": CodeNode.gensym(),
- }
-
- maybe_colon = " : " if member_initializer_list else ""
-
- template_text = format_template(
- """\
-${{{comment}}}
-${{{return_type}}} ${{{name}}}(${{{arg_decls}}})\
-{maybe_colon}${{{member_initializer_list}}} {{
- ${{{body}}}
-}}\\
-""",
- maybe_colon=maybe_colon,
- **gensyms)
- template_vars = {
- gensyms["name"]:
- name,
- gensyms["arg_decls"]:
- ListNode(arg_decls, separator=", "),
- gensyms["return_type"]:
- return_type,
- gensyms["member_initializer_list"]:
- ListNode(member_initializer_list, separator=", "),
- gensyms["body"]:
- body,
- gensyms["comment"]:
- comment,
- }
-
- CodeNode.__init__(
- self, template_text=template_text, template_vars=template_vars)
+ scope = self.outer_scope()
+ if scope.is_code_symbol_defined(self._symbol_node):
+ assert isinstance(self.outer, SequenceNode)
+ self.outer.schedule_to_remove(self)
+ self.outer.skip_separator()
+ return
- self._body_node = body
+ scope.on_code_symbol_defined(self._symbol_node)
- self._body_node.register_code_symbols(local_vars)
+ super(SymbolDefinitionNode, self)._render(
+ renderer=renderer, last_render_state=last_render_state)
@property
- def body(self):
- return self._body_node
+ def target_symbol(self):
+ return self._symbol_node
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py
new file mode 100644
index 00000000000..b52c867c855
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py
@@ -0,0 +1,456 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+This module provides C++ language specific implementations of
+code_node.CodeNode.
+"""
+
+from .code_node import CodeNode
+from .code_node import CompositeNode
+from .code_node import Likeliness
+from .code_node import ListNode
+from .code_node import SymbolScopeNode
+from .code_node import TextNode
+from .codegen_expr import CodeGenExpr
+from .codegen_format import format_template
+
+
+class CxxBlockNode(CompositeNode):
+ def __init__(self, body):
+ template_format = (
+ "{{\n" #
+ " {body}\n"
+ "}}")
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ body=_to_symbol_scope_node(body, Likeliness.ALWAYS))
+
+
+class CxxIfNode(CompositeNode):
+ def __init__(self, cond, body, likeliness):
+ template_format = (
+ "if ({cond}) {{\n" #
+ " {body}\n"
+ "}}")
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ cond=_to_conditional_node(cond),
+ body=_to_symbol_scope_node(body, likeliness))
+
+
+class CxxIfElseNode(CompositeNode):
+ def __init__(self, cond, then, then_likeliness, else_, else_likeliness):
+ template_format = (
+ "if ({cond}) {{\n" #
+ " {then}\n"
+ "}} else {{\n"
+ " {else_}\n"
+ "}}")
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ cond=_to_conditional_node(cond),
+ then=_to_symbol_scope_node(then, then_likeliness),
+ else_=_to_symbol_scope_node(else_, else_likeliness))
+
+
+class CxxLikelyIfNode(CxxIfNode):
+ def __init__(self, cond, body):
+ CxxIfNode.__init__(self, cond, body, Likeliness.LIKELY)
+
+
+class CxxUnlikelyIfNode(CxxIfNode):
+ def __init__(self, cond, body):
+ CxxIfNode.__init__(self, cond, body, Likeliness.UNLIKELY)
+
+
+class CxxMultiBranchesNode(CodeNode):
+ class _Clause(object):
+ def __init__(self, cond, body):
+ assert isinstance(cond, (CodeNode, bool))
+ assert isinstance(body, SymbolScopeNode)
+ self.cond = cond
+ self.body = body
+
+ def __init__(self):
+ clauses_gensym = CodeNode.gensym()
+ clauses = []
+ template_text = format_template(
+ """\
+% for {clause} in {clauses}:
+% if not loop.first:
+ else \\
+% endif
+% if {clause}.cond is not False:
+% if {clause}.cond is not True:
+if (${{{clause}.cond}}) \\
+% endif
+{{
+ ${{{clause}.body}}
+}}\\
+% if {clause}.cond is True:
+ <% break %>
+% endif
+% endif
+% endfor\
+""",
+ clause=CodeNode.gensym(),
+ clauses=clauses_gensym)
+ template_vars = {clauses_gensym: clauses}
+
+ CodeNode.__init__(
+ self, template_text=template_text, template_vars=template_vars)
+
+ self._clauses = clauses
+
+ def append(self, cond, body, likeliness=Likeliness.LIKELY):
+ if cond is None:
+ cond = False
+ elif isinstance(cond, CodeGenExpr):
+ if cond.is_always_true:
+ cond = True
+ elif cond.is_always_false:
+ cond = False
+
+ if not isinstance(cond, bool):
+ cond = _to_conditional_node(cond)
+ body = _to_symbol_scope_node(body, likeliness)
+
+ if isinstance(cond, CodeNode):
+ cond.set_outer(self)
+ body.set_outer(self)
+
+ self._clauses.append(self._Clause(cond, body))
+
+
+class CxxBreakableBlockNode(CompositeNode):
+ def __init__(self, body, likeliness=Likeliness.LIKELY):
+ template_format = ("do {{ // Dummy loop for use of 'break'.\n"
+ " {body}\n"
+ "}} while (false);")
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ body=_to_symbol_scope_node(body, likeliness))
+
+
+class CxxFuncDeclNode(CompositeNode):
+ def __init__(self,
+ name,
+ arg_decls,
+ return_type,
+ template_params=None,
+ static=False,
+ explicit=False,
+ constexpr=False,
+ const=False,
+ override=False,
+ default=False,
+ delete=False):
+ """
+ Args:
+ name: Function name.
+ arg_decls: List of argument declarations.
+ return_type: Return type.
+ template_params: List of template parameters or None.
+ static: True makes this a static function.
+ explicit: True makes this an explicit constructor.
+ constexpr: True makes this a constexpr function.
+ const: True makes this a const function.
+ override: True makes this an overriding function.
+ default: True makes this have the default implementation.
+ delete: True makes this function be deleted.
+ """
+ assert isinstance(static, bool)
+ assert isinstance(explicit, bool)
+ assert isinstance(constexpr, bool)
+ assert isinstance(const, bool)
+ assert isinstance(override, bool)
+ assert isinstance(default, bool)
+ assert isinstance(delete, bool)
+ assert not (default and delete)
+
+ template_format = ("{template}"
+ "{static}{explicit}{constexpr}"
+ "{return_type} "
+ "{name}({arg_decls})"
+ "{const}"
+ "{override}"
+ "{default_or_delete}"
+ ";")
+
+ if template_params is None:
+ template = ""
+ else:
+ template = "template <{}>\n".format(", ".join(template_params))
+
+ static = "static " if static else ""
+ explicit = "explicit " if explicit else ""
+ constexpr = "constexpr " if constexpr else ""
+ const = " const" if const else ""
+ override = " override" if override else ""
+
+ if default:
+ default_or_delete = " = default"
+ elif delete:
+ default_or_delete = " = delete"
+ else:
+ default_or_delete = ""
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ name=_to_maybe_text_node(name),
+ arg_decls=ListNode(
+ map(_to_maybe_text_node, arg_decls), separator=", "),
+ return_type=_to_maybe_text_node(return_type),
+ template=template,
+ static=static,
+ explicit=explicit,
+ constexpr=constexpr,
+ const=const,
+ override=override,
+ default_or_delete=default_or_delete)
+
+
+class CxxFuncDefNode(CompositeNode):
+ def __init__(self,
+ name,
+ arg_decls,
+ return_type,
+ class_name=None,
+ template_params=None,
+ static=False,
+ inline=False,
+ explicit=False,
+ constexpr=False,
+ const=False,
+ override=False,
+ member_initializer_list=None):
+ """
+ Args:
+ name: Function name.
+ arg_decls: List of argument declarations.
+ return_type: Return type.
+ class_name: Class name to be used as nested-name-specifier.
+ template_params: List of template parameters or None.
+ static: True makes this a static function.
+ inline: True makes this an inline function.
+ explicit: True makes this an explicit constructor.
+ constexpr: True makes this a constexpr function.
+ const: True makes this a const function.
+ override: True makes this an overriding function.
+ member_initializer_list: List of member initializers.
+ """
+ assert isinstance(static, bool)
+ assert isinstance(inline, bool)
+ assert isinstance(explicit, bool)
+ assert isinstance(constexpr, bool)
+ assert isinstance(const, bool)
+ assert isinstance(override, bool)
+
+ template_format = ("{template}"
+ "{static}{inline}{explicit}{constexpr}"
+ "{return_type} "
+ "{class_name}{name}({arg_decls})"
+ "{const}"
+ "{override}"
+ "{member_initializer_list} {{\n"
+ " {body}\n"
+ "}}")
+
+ if class_name is None:
+ class_name = ""
+ else:
+ class_name = ListNode([_to_maybe_text_node(class_name)], tail="::")
+
+ if template_params is None:
+ template = ""
+ else:
+ template = "template <{}>\n".format(", ".join(template_params))
+
+ static = "static " if static else ""
+ inline = "inline " if inline else ""
+ explicit = "explicit " if explicit else ""
+ constexpr = "constexpr " if constexpr else ""
+ const = " const" if const else ""
+ override = " override" if override else ""
+
+ if member_initializer_list is None:
+ member_initializer_list = ""
+ else:
+ member_initializer_list = ListNode(
+ map(_to_maybe_text_node, member_initializer_list),
+ separator=", ",
+ head=" : ")
+
+ self._body_node = SymbolScopeNode()
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ name=_to_maybe_text_node(name),
+ arg_decls=ListNode(
+ map(_to_maybe_text_node, arg_decls), separator=", "),
+ return_type=_to_maybe_text_node(return_type),
+ class_name=class_name,
+ template=template,
+ static=static,
+ inline=inline,
+ explicit=explicit,
+ constexpr=constexpr,
+ const=const,
+ override=override,
+ member_initializer_list=member_initializer_list,
+ body=self._body_node)
+
+ @property
+ def body(self):
+ return self._body_node
+
+
+class CxxClassDefNode(CompositeNode):
+ def __init__(self, name, base_class_names=None, final=False, export=None):
+ """
+ Args:
+ name: The class name to be defined.
+ base_class_names: The list of base class names.
+ final: True makes this a final class.
+ export: Class export annotation.
+ """
+ assert isinstance(final, bool)
+
+ template_format = ("class{export} {name}{final}{base_clause} {{\n"
+ " {top_section}\n"
+ " {public_section}\n"
+ " {protected_section}\n"
+ " {private_section}\n"
+ " {bottom_section}\n"
+ "}};")
+
+ if export is None:
+ export = ""
+ else:
+ export = ListNode([_to_maybe_text_node(export)], head=" ")
+
+ final = " final" if final else ""
+
+ if base_class_names is None:
+ base_clause = ""
+ else:
+ base_specifier_list = [
+ CompositeNode(
+ "public {base_class_name}",
+ base_class_name=_to_maybe_text_node(base_class_name))
+ for base_class_name in base_class_names
+ ]
+ base_clause = ListNode(
+ base_specifier_list, separator=", ", head=" : ")
+
+ self._top_section = ListNode(tail="\n")
+ self._public_section = ListNode(head="public:\n", tail="\n")
+ self._protected_section = ListNode(head="protected:\n", tail="\n")
+ self._private_section = ListNode(head="private:\n", tail="\n")
+ self._bottom_section = ListNode()
+
+ CompositeNode.__init__(
+ self,
+ template_format,
+ name=_to_maybe_text_node(name),
+ base_clause=base_clause,
+ final=final,
+ export=export,
+ top_section=self._top_section,
+ public_section=self._public_section,
+ protected_section=self._protected_section,
+ private_section=self._private_section,
+ bottom_section=self._bottom_section)
+
+ @property
+ def top_section(self):
+ return self._top_section
+
+ @property
+ def public_section(self):
+ return self._public_section
+
+ @property
+ def protected_section(self):
+ return self._protected_section
+
+ @property
+ def private_section(self):
+ return self._private_section
+
+ @property
+ def bottom_section(self):
+ return self._bottom_section
+
+
+class CxxNamespaceNode(CompositeNode):
+ def __init__(self, name="", body=None):
+ template_format = ("namespace {name} {{\n"
+ "\n"
+ "{body}\n"
+ "\n"
+ "}} // namespace {name}")
+
+ if body is None:
+ self._body = ListNode()
+ else:
+ self._body = _to_list_node(body)
+
+ CompositeNode.__init__(
+ self, template_format, name=name, body=self._body)
+
+ @property
+ def body(self):
+ return self._body
+
+
+def _to_conditional_node(cond):
+ if isinstance(cond, CodeNode):
+ return cond
+ if isinstance(cond, CodeGenExpr):
+ return TextNode(cond.to_text())
+ if isinstance(cond, str):
+ return TextNode(cond)
+ assert False
+
+
+def _to_list_node(node):
+ if isinstance(node, ListNode):
+ return node
+ if isinstance(node, CodeNode):
+ return ListNode([node])
+ if isinstance(node, (list, tuple)):
+ return ListNode(node)
+ assert False
+
+
+def _to_maybe_text_node(node):
+ if isinstance(node, CodeNode):
+ return node
+ if isinstance(node, str):
+ return TextNode(node)
+ assert False
+
+
+def _to_symbol_scope_node(node, likeliness):
+ if isinstance(node, SymbolScopeNode):
+ pass
+ elif isinstance(node, CodeNode):
+ node = SymbolScopeNode([node])
+ elif isinstance(node, (list, tuple)):
+ node = SymbolScopeNode(node)
+ else:
+ assert False
+ node.set_likeliness(likeliness)
+ return node
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py
new file mode 100644
index 00000000000..a18f304eadb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py
@@ -0,0 +1,211 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from .code_node import SymbolNode
+from .code_node import SymbolScopeNode
+from .code_node import TextNode
+from .code_node import render_code_node
+from .code_node_cxx import CxxClassDefNode
+from .code_node_cxx import CxxFuncDefNode
+from .code_node_cxx import CxxLikelyIfNode
+from .code_node_cxx import CxxUnlikelyIfNode
+from .codegen_accumulator import CodeGenAccumulator
+from .mako_renderer import MakoRenderer
+
+
+class CodeNodeCxxTest(unittest.TestCase):
+ def setUp(self):
+ super(CodeNodeCxxTest, self).setUp()
+ self.addTypeEqualityFunc(str, self.assertMultiLineEqual)
+
+ def assertRenderResult(self, node, expected):
+ if node.renderer is None:
+ node.set_renderer(MakoRenderer())
+ if node.accumulator is None:
+ node.set_accumulator(CodeGenAccumulator())
+
+ def simplify(text):
+ return "\n".join(
+ [" ".join(line.split()) for line in text.split("\n")])
+
+ actual = simplify(render_code_node(node))
+ expected = simplify(expected)
+
+ self.assertEqual(actual, expected)
+
+ def test_symbol_definition_with_branches(self):
+ root = SymbolScopeNode()
+
+ root.register_code_symbols([
+ SymbolNode("var1", "int ${var1} = 1;"),
+ SymbolNode("var2", "int ${var2} = 2;"),
+ SymbolNode("var3", "int ${var3} = 3;"),
+ SymbolNode("var4", "int ${var4} = 4;"),
+ SymbolNode("var5", "int ${var5} = 5;"),
+ SymbolNode("var6", "int ${var6} = 6;"),
+ ])
+
+ root.extend([
+ TextNode("${var1};"),
+ CxxUnlikelyIfNode(
+ cond=TextNode("${var2}"),
+ body=[
+ TextNode("${var3};"),
+ TextNode("return ${var4};"),
+ ]),
+ CxxLikelyIfNode(
+ cond=TextNode("${var5}"), body=[
+ TextNode("return ${var6};"),
+ ]),
+ TextNode("${var3};"),
+ ])
+
+ self.assertRenderResult(
+ root, """\
+int var1 = 1;
+var1;
+int var2 = 2;
+int var3 = 3;
+if (var2) {
+ var3;
+ int var4 = 4;
+ return var4;
+}
+int var5 = 5;
+if (var5) {
+ int var6 = 6;
+ return var6;
+}
+var3;\
+""")
+
+ def test_symbol_definition_with_nested_branches(self):
+ root = SymbolScopeNode()
+
+ root.register_code_symbols([
+ SymbolNode("var1", "int ${var1} = 1;"),
+ SymbolNode("var2", "int ${var2} = 2;"),
+ SymbolNode("var3", "int ${var3} = 3;"),
+ SymbolNode("var4", "int ${var4} = 4;"),
+ SymbolNode("var5", "int ${var5} = 5;"),
+ SymbolNode("var6", "int ${var6} = 6;"),
+ ])
+
+ root.extend([
+ CxxUnlikelyIfNode(
+ cond=TextNode("false"),
+ body=[
+ CxxUnlikelyIfNode(
+ cond=TextNode("false"),
+ body=[
+ TextNode("return ${var1};"),
+ ]),
+ TextNode("return;"),
+ ]),
+ CxxLikelyIfNode(
+ cond=TextNode("true"),
+ body=[
+ CxxLikelyIfNode(
+ cond=TextNode("true"),
+ body=[
+ TextNode("return ${var2};"),
+ ]),
+ TextNode("return;"),
+ ]),
+ ])
+
+ self.assertRenderResult(
+ root, """\
+if (false) {
+ if (false) {
+ int var1 = 1;
+ return var1;
+ }
+ return;
+}
+if (true) {
+ if (true) {
+ int var2 = 2;
+ return var2;
+ }
+ return;
+}\
+""")
+
+ def test_function_definition_minimum(self):
+ root = CxxFuncDefNode(
+ name="blink::bindings::func", arg_decls=[], return_type="void")
+
+ self.assertRenderResult(root, """\
+void blink::bindings::func() {
+
+}\
+""")
+
+ def test_function_definition_full(self):
+ root = CxxFuncDefNode(
+ name="blink::bindings::func",
+ arg_decls=["int arg1", "int arg2"],
+ return_type="void",
+ const=True,
+ override=True,
+ member_initializer_list=[
+ "member1(0)",
+ "member2(\"str\")",
+ ])
+
+ root.body.register_code_symbols([
+ SymbolNode("var1", "int ${var1} = 1;"),
+ SymbolNode("var2", "int ${var2} = 2;"),
+ ])
+
+ root.body.extend([
+ CxxUnlikelyIfNode(
+ cond=TextNode("${var1}"), body=[TextNode("return ${var1};")]),
+ TextNode("return ${var2};"),
+ ])
+
+ self.assertRenderResult(
+ root, """\
+void blink::bindings::func(int arg1, int arg2) const override\
+ : member1(0), member2("str") {
+ int var1 = 1;
+ if (var1) {
+ return var1;
+ }
+ int var2 = 2;
+ return var2;
+}\
+""")
+
+ def test_class_definition(self):
+ root = CxxClassDefNode("X", ["A", "B"], final=True)
+
+ root.public_section.extend([
+ TextNode("void m1();"),
+ TextNode("void m2();"),
+ ])
+ root.private_section.extend([
+ TextNode("int m1_;"),
+ TextNode("int m2_;"),
+ ])
+
+ self.assertRenderResult(
+ root, """\
+class X final : public A, public B {
+
+ public:
+ void m1();
+ void m2();
+
+
+ private:
+ int m1_;
+ int m2_;
+
+
+};\
+""")
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
index de94c59f49e..24756d58e94 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
@@ -4,15 +4,13 @@
import unittest
-from .code_node import FunctionDefinitionNode
-from .code_node import LikelyExitNode
-from .code_node import LiteralNode
from .code_node import ListNode
+from .code_node import LiteralNode
from .code_node import SymbolNode
from .code_node import SymbolScopeNode
from .code_node import TextNode
-from .code_node import UnlikelyExitNode
-from .codegen_utils import render_code_node
+from .code_node import render_code_node
+from .codegen_accumulator import CodeGenAccumulator
from .mako_renderer import MakoRenderer
@@ -24,6 +22,8 @@ class CodeNodeTest(unittest.TestCase):
def assertRenderResult(self, node, expected):
if node.renderer is None:
node.set_renderer(MakoRenderer())
+ if node.accumulator is None:
+ node.set_accumulator(CodeGenAccumulator())
def simplify(text):
return "\n".join(
@@ -75,6 +75,14 @@ class CodeNodeTest(unittest.TestCase):
root.remove(root[-1])
self.assertRenderResult(root, "2,3,5")
+ def test_list_node_head_and_tail(self):
+ self.assertRenderResult(ListNode(), "")
+ self.assertRenderResult(ListNode(head="head"), "")
+ self.assertRenderResult(ListNode(tail="tail"), "")
+ self.assertRenderResult(
+ ListNode([TextNode("-content-")], head="head", tail="tail"),
+ "head-content-tail")
+
def test_nested_sequence(self):
"""Tests nested ListNodes."""
root = ListNode(separator=",")
@@ -96,7 +104,7 @@ class CodeNodeTest(unittest.TestCase):
Tests that use of SymbolNode inserts necessary SymbolDefinitionNode
appropriately.
"""
- root = SymbolScopeNode(separator_last="\n")
+ root = SymbolScopeNode(tail="\n")
root.register_code_symbols([
SymbolNode("var1", "int ${var1} = ${var2} + ${var3};"),
@@ -118,164 +126,6 @@ int var1 = var2 + var3;
(void)var1;
""")
- def test_symbol_definition_with_exit_branches(self):
- root = SymbolScopeNode(separator_last="\n")
-
- root.register_code_symbols([
- SymbolNode("var1", "int ${var1} = 1;"),
- SymbolNode("var2", "int ${var2} = 2;"),
- SymbolNode("var3", "int ${var3} = 3;"),
- SymbolNode("var4", "int ${var4} = 4;"),
- SymbolNode("var5", "int ${var5} = 5;"),
- SymbolNode("var6", "int ${var6} = 6;"),
- ])
-
- root.extend([
- TextNode("${var1};"),
- UnlikelyExitNode(
- cond=TextNode("${var2}"),
- body=SymbolScopeNode([
- TextNode("${var3};"),
- TextNode("return ${var4};"),
- ])),
- LikelyExitNode(
- cond=TextNode("${var5}"),
- body=SymbolScopeNode([
- TextNode("return ${var6};"),
- ])),
- TextNode("${var3};"),
- ])
-
- self.assertRenderResult(
- root, """\
-int var1 = 1;
-var1;
-int var2 = 2;
-int var3 = 3;
-if (var2) {
- var3;
- int var4 = 4;
- return var4;
-}
-int var5 = 5;
-if (var5) {
- int var6 = 6;
- return var6;
-}
-var3;
-""")
-
- def test_symbol_definition_with_nested_exit_branches(self):
- root = SymbolScopeNode(separator_last="\n")
-
- root.register_code_symbols([
- SymbolNode("var1", "int ${var1} = 1;"),
- SymbolNode("var2", "int ${var2} = 2;"),
- SymbolNode("var3", "int ${var3} = 3;"),
- SymbolNode("var4", "int ${var4} = 4;"),
- SymbolNode("var5", "int ${var5} = 5;"),
- SymbolNode("var6", "int ${var6} = 6;"),
- ])
-
- root.extend([
- UnlikelyExitNode(
- cond=LiteralNode("false"),
- body=SymbolScopeNode([
- UnlikelyExitNode(
- cond=LiteralNode("false"),
- body=SymbolScopeNode([
- TextNode("return ${var1};"),
- ])),
- LiteralNode("return;"),
- ])),
- LikelyExitNode(
- cond=LiteralNode("true"),
- body=SymbolScopeNode([
- LikelyExitNode(
- cond=LiteralNode("true"),
- body=SymbolScopeNode([
- TextNode("return ${var2};"),
- ])),
- LiteralNode("return;"),
- ])),
- ])
-
- self.assertRenderResult(
- root, """\
-if (false) {
- if (false) {
- int var1 = 1;
- return var1;
- }
- return;
-}
-if (true) {
- if (true) {
- int var2 = 2;
- return var2;
- }
- return;
-}
-""")
-
- def test_function_definition_minimum(self):
- root = SymbolScopeNode(separator_last="\n")
- root.append(
- FunctionDefinitionNode(
- name=LiteralNode("blink::bindings::func"),
- arg_decls=[],
- return_type=LiteralNode("void")))
-
- self.assertRenderResult(root, """\
-
-void blink::bindings::func() {
-
-}
-""")
-
- def test_function_definition_full(self):
- root = SymbolScopeNode(separator_last="\n")
-
- local_vars = [
- SymbolNode("var1", "int ${var1} = 1;"),
- SymbolNode("var2", "int ${var2} = 2;"),
- ]
-
- func_body = SymbolScopeNode([
- UnlikelyExitNode(
- cond=TextNode("${var1}"),
- body=SymbolScopeNode([TextNode("return ${var1};")])),
- TextNode("return ${var2};"),
- ])
-
- root.append(
- FunctionDefinitionNode(
- name=LiteralNode("blink::bindings::func"),
- arg_decls=[LiteralNode("int arg1"),
- LiteralNode("int arg2")],
- return_type=LiteralNode("void"),
- member_initializer_list=[
- LiteralNode("member1(0)"),
- LiteralNode("member2(\"str\")")
- ],
- local_vars=local_vars,
- body=func_body,
- comment=LiteralNode("// comment1\n// comment2")))
-
- self.assertRenderResult(
- root, """\
-// comment1
-// comment2
-void blink::bindings::func(int arg1, int arg2) : member1(0), member2("str") {
- int var1 = 1;
- if (var1) {
- return var1;
- }
- int var2 = 2;
- return var2;
-}
-""")
-
def test_template_error_handling(self):
renderer = MakoRenderer()
root = SymbolScopeNode()
@@ -288,7 +138,8 @@ void blink::bindings::func(int arg1, int arg2) : member1(0), member2("str") {
]))
with self.assertRaises(NameError):
- root.render()
+ renderer.reset()
+ root.render(renderer)
callers_on_error = list(renderer.callers_on_error)
self.assertEqual(len(callers_on_error), 3)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py
index 910c4bb185e..f72e41a7421 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_accumulator.py
@@ -14,6 +14,12 @@ class CodeGenAccumulator(object):
self._include_headers = set()
# Forward declarations of C++ class
self._class_decls = set()
+ # Forward declarations of C++ struct
+ self._struct_decls = set()
+
+ def total_size(self):
+ return (len(self.include_headers) + len(self.class_decls) + len(
+ self.struct_decls))
@property
def include_headers(self):
@@ -42,3 +48,17 @@ class CodeGenAccumulator(object):
@staticmethod
def require_class_decls(class_names):
return lambda accumulator: accumulator.add_class_decls(class_names)
+
+ @property
+ def struct_decls(self):
+ return self._struct_decls
+
+ def add_struct_decl(self, struct_name):
+ self._struct_decls.add(struct_name)
+
+ def add_struct_decls(self, struct_names):
+ self._struct_decls.update(struct_names)
+
+ @staticmethod
+ def require_struct_decls(struct_names):
+ return lambda accumulator: accumulator.add_struct_decls(struct_names)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
index 8b06e878898..ae9defa40a2 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
@@ -4,7 +4,10 @@
import copy
+import web_idl
+
from . import name_style
+from .codegen_format import NonRenderable
from .path_manager import PathManager
@@ -20,8 +23,26 @@ class CodeGenContext(object):
# "for_world" attribute values
MAIN_WORLD = "main"
+ NON_MAIN_WORLDS = "other"
ALL_WORLDS = "all"
+ # "v8_callback_type" attribute values
+ #
+ # void (*)(const v8::FunctionCallbackInfo<v8::Value>&)
+ V8_FUNCTION_CALLBACK = "v8::FunctionCallback"
+ # void (*)(v8::Local<v8::Name>,
+ # const v8::PropertyCallbackInfo<v8::Value>&)
+ V8_ACCESSOR_NAME_GETTER_CALLBACK = "v8::AccessorNameGetterCallback"
+ # void (*)(v8::Local<v8::Name>, v8::Local<v8::Value>,
+ # const v8::PropertyCallbackInfo<void>&)
+ V8_ACCESSOR_NAME_SETTER_CALLBACK = "v8::AccessorNameSetterCallback"
+ # void (*)(v8::Local<v8::Name>, v8::Local<v8::Value>,
+ # const v8::PropertyCallbackInfo<v8::Value>&)
+ V8_GENERIC_NAMED_PROPERTY_SETTER_CALLBACK = (
+ "v8::GenericNamedPropertySetterCallback")
+ # Others
+ V8_OTHER_CALLBACK = "other callback type"
+
@classmethod
def init(cls):
"""Initialize the class. Must be called exactly once."""
@@ -49,11 +70,31 @@ class CodeGenContext(object):
"constructor": None,
"constructor_group": None,
"dict_member": None,
+ "exposed_construct": None,
+ "legacy_window_alias": None,
"operation": None,
"operation_group": None,
+ # Special member-ish definition
+ "indexed_property_getter": None,
+ "indexed_property_setter": None,
+ "named_property_getter": None,
+ "named_property_setter": None,
+ "named_property_deleter": None,
+ "stringifier": None,
+
+ # The names of the class being generated and its base class.
+ "base_class_name": None,
+ "class_name": None,
+
# Main world or all worlds
+ # Used via [PerWorldBindings] to optimize the code path of the main
+ # world.
"for_world": cls.ALL_WORLDS,
+
+ # Type of V8 callback function which implements IDL attribute,
+ # IDL operation, etc.
+ "v8_callback_type": cls.V8_FUNCTION_CALLBACK
}
# List of computational attribute names
@@ -69,11 +110,10 @@ class CodeGenContext(object):
"member_like",
"property_",
"return_type",
- "v8_class",
)
# Define public readonly properties of this class.
- for attr in cls._context_attrs.iterkeys():
+ for attr in cls._context_attrs.keys():
def make_get():
_attr = cls._internal_attr(attr)
@@ -92,11 +132,11 @@ class CodeGenContext(object):
def __init__(self, **kwargs):
assert CodeGenContext._was_initialized
- for arg in kwargs.iterkeys():
+ for arg in kwargs.keys():
assert arg in self._context_attrs, "Unknown argument: {}".format(
arg)
- for attr, default_value in self._context_attrs.iteritems():
+ for attr, default_value in self._context_attrs.items():
value = kwargs[attr] if attr in kwargs else default_value
assert (default_value is None
or type(value) is type(default_value)), (
@@ -108,13 +148,13 @@ class CodeGenContext(object):
Returns a copy of this context applying the updates given as the
arguments.
"""
- for arg in kwargs.iterkeys():
+ for arg in kwargs.keys():
assert arg in self._context_attrs, "Unknown argument: {}".format(
arg)
new_object = copy.copy(self)
- for attr, new_value in kwargs.iteritems():
+ for attr, new_value in kwargs.items():
old_value = getattr(self, attr)
assert old_value is None or type(new_value) is type(old_value), (
"Type mismatch at argument: {}".format(attr))
@@ -131,15 +171,17 @@ class CodeGenContext(object):
"""
bindings = {}
- for attr in self._context_attrs.iterkeys():
+ for attr in self._context_attrs.keys():
value = getattr(self, attr)
- if value is not None:
- bindings[attr] = value
+ if value is None:
+ value = NonRenderable(attr)
+ bindings[attr] = value
for attr in self._computational_attrs:
value = getattr(self, attr)
- if value is not None:
- bindings[attr.strip("_")] = value
+ if value is None:
+ value = NonRenderable(attr)
+ bindings[attr.strip("_")] = value
return bindings
@@ -149,8 +191,18 @@ class CodeGenContext(object):
or self.namespace)
@property
+ def does_override_idl_return_type(self):
+ # Blink implementation returns in a type different from the IDL type.
+ # Namely, IndexedPropertySetterResult, NamedPropertySetterResult, and
+ # NamedPropertyDeleterResult are returned ignoring the operation's
+ # return type.
+ return (self.indexed_property_setter or self.named_property_setter
+ or self.named_property_deleter)
+
+ @property
def function_like(self):
- return (self.callback_function or self.constructor or self.operation)
+ return (self.callback_function or self.constructor or self.operation
+ or self._indexed_or_named_property)
@property
def idl_definition(self):
@@ -161,9 +213,9 @@ class CodeGenContext(object):
@property
def idl_location(self):
idl_def = self.member_like or self.idl_definition
- if idl_def:
+ if idl_def and not isinstance(idl_def, web_idl.Union):
location = idl_def.debug_info.location
- text = PathManager.relpath_to_project_root(location.filepath)
+ text = location.filepath
if location.line_number is not None:
text += ":{}".format(location.line_number)
return text
@@ -185,15 +237,16 @@ class CodeGenContext(object):
@property
def is_return_by_argument(self):
+ if self.does_override_idl_return_type:
+ return False
if self.return_type is None:
- return None
- return_type = self.return_type.unwrap()
- return return_type.is_dictionary or return_type.is_union
+ return False
+ return self.return_type.unwrap().is_union
@property
def may_throw_exception(self):
if not self.member_like:
- return None
+ return False
ext_attr = self.member_like.extended_attributes.get("RaisesException")
if not ext_attr:
return False
@@ -204,28 +257,77 @@ class CodeGenContext(object):
@property
def member_like(self):
return (self.attribute or self.constant or self.constructor
- or self.dict_member or self.operation)
+ or self.dict_member or self.operation
+ or self._indexed_or_named_property)
@property
def property_(self):
+ if self.stringifier:
+ return _StringifierProperty(self.stringifier)
+
return (self.attribute or self.constant or self.constructor_group
- or self.dict_member or self.operation_group)
+ or self.dict_member
+ or (self.legacy_window_alias or self.exposed_construct)
+ or self.operation_group or self._indexed_or_named_property)
@property
def return_type(self):
if self.attribute_get:
return self.attribute.idl_type
- if self.callback_function:
- return self.callback_function.return_type
- if self.operation:
- return self.operation.return_type
+ function_like = self.function_like
+ if function_like:
+ return function_like.return_type
return None
@property
- def v8_class(self):
- if not self.idl_definition:
- return None
- return name_style.class_("v8", self.idl_definition.identifier)
+ def _indexed_or_named_property(self):
+ return (self.indexed_property_getter or self.indexed_property_setter
+ or self.named_property_getter or self.named_property_setter
+ or self.named_property_deleter)
CodeGenContext.init()
+
+
+class _PropertyBase(object):
+ def __init__(self, identifier, extended_attributes, owner, debug_info):
+ assert isinstance(identifier, web_idl.Identifier)
+ assert identifier
+ assert isinstance(extended_attributes, web_idl.ExtendedAttributes)
+ assert isinstance(debug_info, web_idl.DebugInfo)
+
+ self._identifier = identifier
+ self._extended_attributes = extended_attributes
+ self._owner = owner
+ self._debug_info = debug_info
+
+ @property
+ def identifier(self):
+ return self._identifier
+
+ @property
+ def extended_attributes(self):
+ return self._extended_attributes
+
+ @property
+ def owner(self):
+ return self._owner
+
+ @property
+ def debug_info(self):
+ return self._debug_info
+
+
+class _StringifierProperty(_PropertyBase):
+ def __init__(self, stringifier):
+ if stringifier.attribute:
+ extended_attributes = stringifier.attribute.extended_attributes
+ else:
+ extended_attributes = stringifier.operation.extended_attributes
+
+ _PropertyBase.__init__(
+ self,
+ identifier=web_idl.Identifier("toString"),
+ extended_attributes=extended_attributes,
+ owner=stringifier.owner,
+ debug_info=stringifier.debug_info)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
index de9fb61d764..e1b6c8b1b08 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
@@ -4,7 +4,6 @@
import web_idl
-
_CODE_GEN_EXPR_PASS_KEY = object()
@@ -144,18 +143,22 @@ def expr_uniq(terms):
return uniq_terms
-def expr_from_exposure(exposure, in_global=None):
+def expr_from_exposure(exposure, global_names=None):
"""
Args:
- exposure: web_idl.Exposure
- in_global: A global name of [Exposed] that the ExecutionContext is
- supposed to be / represent.
+ exposure: web_idl.Exposure of the target construct.
+ global_names: When specified, it's taken into account that the global
+ object implements |global_names|.
"""
assert isinstance(exposure, web_idl.Exposure)
- assert in_global is None or isinstance(in_global, str)
+ assert (global_names is None
+ or (isinstance(global_names, (list, tuple))
+ and all(isinstance(name, str) for name in global_names)))
def ref_enabled(feature):
- return _Expr("RuntimeEnabledFeatures::{}Enabled()".format(feature))
+ arg = "${execution_context}" if feature.is_context_dependent else ""
+ return _Expr("RuntimeEnabledFeatures::{}Enabled({})".format(
+ feature, arg))
top_terms = [_Expr(True)]
@@ -172,22 +175,26 @@ def expr_from_exposure(exposure, in_global=None):
"Worker": "IsWorkerGlobalScope",
"Worklet": "IsWorkletGlobalScope",
}
- in_globals = set()
- if in_global:
- in_globals.add(in_global)
- for category_name in ("Worker", "Worklet"):
- if in_global.endswith(category_name):
- in_globals.add(category_name)
exposed_terms = []
- for entry in exposure.global_names_and_features:
- terms = []
- if entry.global_name not in in_globals:
+ if global_names:
+ matched_global_count = 0
+ for entry in exposure.global_names_and_features:
+ if entry.global_name not in global_names:
+ continue
+ matched_global_count += 1
+ if entry.feature:
+ exposed_terms.append(ref_enabled(entry.feature))
+ assert (not exposure.global_names_and_features
+ or matched_global_count > 0)
+ else:
+ for entry in exposure.global_names_and_features:
+ terms = []
pred = GLOBAL_NAME_TO_EXECUTION_CONTEXT_TEST[entry.global_name]
terms.append(_Expr("${{execution_context}}->{}()".format(pred)))
- if entry.feature:
- terms.append(ref_enabled(entry.feature))
- if terms:
- exposed_terms.append(expr_and(terms))
+ if entry.feature:
+ terms.append(ref_enabled(entry.feature))
+ if terms:
+ exposed_terms.append(expr_and(terms))
if exposed_terms:
top_terms.append(expr_or(exposed_terms))
@@ -198,13 +205,14 @@ def expr_from_exposure(exposure, in_global=None):
# [SecureContext]
if exposure.only_in_secure_contexts is True:
- top_terms.append(_Expr("${in_secure_context}"))
+ top_terms.append(_Expr("${is_in_secure_context}"))
elif exposure.only_in_secure_contexts is False:
top_terms.append(_Expr(True))
else:
terms = map(ref_enabled, exposure.only_in_secure_contexts)
top_terms.append(
- expr_or([_Expr("${in_secure_context}"),
- expr_not(expr_and(terms))]))
+ expr_or(
+ [_Expr("${is_in_secure_context}"),
+ expr_not(expr_and(terms))]))
return expr_and(top_terms)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_format.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_format.py
index 3b215153021..87d26eec3ca 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_format.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_format.py
@@ -27,7 +27,7 @@ class _TemplateFormatter(string.Formatter):
return args[key]
assert isinstance(key, str)
if not key:
- # Before Python 3.1, when a positional argument specifier is
+ # Prior to Python 3.1, when a positional argument specifier is
# omitted, |format_string="{}"| produces |key=""|. Should be
# removed once Python2 gets retired.
index = self._template_formatter_indexing_count_
@@ -37,3 +37,22 @@ class _TemplateFormatter(string.Formatter):
return kwargs[key]
else:
return "{" + key + "}"
+
+
+class NonRenderable(object):
+ """
+ Represents a non-renderable object.
+
+ Unlike a template variable bound to None, which is a valid Python value,
+ this object raises an exception when rendered, just like an unbound template
+ variable.
+ """
+
+ def __init__(self, error_message="Undefined"):
+ self._error_message = error_message
+
+ def __bool__(self):
+ raise NameError(self._error_message)
+
+ def __str__(self):
+ raise NameError(self._error_message)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
index 2635adbafae..7021f1a618c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
@@ -4,10 +4,14 @@
import web_idl
-from .clang_format import clang_format
+from . import name_style
+from . import style_format
+from .blink_v8_bridge import blink_type_info
from .code_node import CodeNode
+from .code_node import EmptyNode
from .code_node import LiteralNode
from .code_node import SequenceNode
+from .code_node import render_code_node
from .codegen_accumulator import CodeGenAccumulator
from .path_manager import PathManager
@@ -20,6 +24,25 @@ def make_copyright_header():
""")
+def make_forward_declarations(accumulator):
+ assert isinstance(accumulator, CodeGenAccumulator)
+
+ class ForwardDeclarations(object):
+ def __init__(self, accumulator):
+ self._accumulator = accumulator
+
+ def __str__(self):
+ return "\n".join([
+ "class {};".format(class_name)
+ for class_name in sorted(self._accumulator.class_decls)
+ ] + [
+ "struct {};".format(struct_name)
+ for struct_name in sorted(self._accumulator.struct_decls)
+ ])
+
+ return LiteralNode(ForwardDeclarations(accumulator))
+
+
def make_header_include_directives(accumulator):
assert isinstance(accumulator, CodeGenAccumulator)
@@ -36,6 +59,23 @@ def make_header_include_directives(accumulator):
return LiteralNode(HeaderIncludeDirectives(accumulator))
+def component_export(component):
+ assert isinstance(component, web_idl.Component)
+
+ return name_style.macro(component, "EXPORT")
+
+
+def component_export_header(component):
+ assert isinstance(component, web_idl.Component)
+
+ if component == "core":
+ return "third_party/blink/renderer/core/core_export.h"
+ elif component == "modules":
+ return "third_party/blink/renderer/modules/modules_export.h"
+ else:
+ assert False
+
+
def enclose_with_header_guard(code_node, header_guard):
assert isinstance(code_node, CodeNode)
assert isinstance(header_guard, str)
@@ -43,93 +83,64 @@ def enclose_with_header_guard(code_node, header_guard):
return SequenceNode([
LiteralNode("#ifndef {}".format(header_guard)),
LiteralNode("#define {}".format(header_guard)),
- LiteralNode(""),
+ EmptyNode(),
code_node,
- LiteralNode(""),
+ EmptyNode(),
LiteralNode("#endif // {}".format(header_guard)),
])
-def enclose_with_namespace(code_node, namespace):
- assert isinstance(code_node, CodeNode)
- assert isinstance(namespace, str)
-
- return SequenceNode([
- LiteralNode("namespace {} {{".format(namespace)),
- LiteralNode(""),
- code_node,
- LiteralNode(""),
- LiteralNode("}} // namespace {}".format(namespace)),
- ])
-
-
-def traverse_idl_types(idl_definition, callback):
+def collect_include_headers_of_idl_types(idl_types):
"""
- Traverses in the given |idl_definition| to find all the web_idl.IdlType used
- in the IDL definition. Invokes |callback| with each web_idl.IdlType.
+ Returns a set of header paths that are required by |idl_types|.
"""
- assert callable(callback)
-
- def get(obj, attr):
- try:
- return getattr(obj, attr)
- except:
- return ()
-
- xs = (get(idl_definition, "attributes") + get(idl_definition, "constants")
- + get(idl_definition, "own_members") + (idl_definition, ))
- for x in xs:
- idl_type = get(x, "idl_type")
- if idl_type:
- callback(idl_type)
-
- xs = (get(idl_definition, "constructors") + get(idl_definition,
- "operations"))
- for x in xs:
- for argument in x.arguments:
- callback(argument.idl_type)
- if x.return_type is not None:
- callback(x.return_type)
-
- xs = get(idl_definition, "flattened_member_types")
- for x in xs:
- callback(x)
-
-
-def collect_include_headers(idl_definition):
- """
- Returns a list of include headers that are required by generated bindings of
- |idl_definition|.
- """
- type_def_objs = set()
-
- def collect_type_def_obj(idl_type):
- type_def_obj = idl_type.unwrap().type_definition_object
- if type_def_obj is not None:
- type_def_objs.add(type_def_obj)
-
- traverse_idl_types(idl_definition, collect_type_def_obj)
-
header_paths = set()
- for type_def_obj in type_def_objs:
- if isinstance(type_def_obj, web_idl.Enumeration):
- continue
- header_paths.add(PathManager(type_def_obj).blink_path(ext="h"))
-
- return header_paths
+ def add_header_path(idl_type):
+ assert isinstance(idl_type, web_idl.IdlType)
+
+ if idl_type.is_numeric or idl_type.is_boolean or idl_type.is_typedef:
+ pass
+ elif idl_type.is_string:
+ header_paths.add(
+ "third_party/blink/renderer/platform/wtf/text/wtf_string.h")
+ elif idl_type.is_buffer_source_type:
+ header_paths.update([
+ "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h",
+ "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h",
+ "third_party/blink/renderer/platform/heap/handle.h",
+ ])
+ elif idl_type.is_object or idl_type.is_any:
+ header_paths.add(
+ "third_party/blink/renderer/bindings/core/v8/script_value.h")
+ elif idl_type.type_definition_object:
+ type_def_obj = idl_type.type_definition_object
+ header_paths.update([
+ PathManager(type_def_obj).api_path(ext="h"),
+ "third_party/blink/renderer/platform/heap/handle.h",
+ ])
+ elif (idl_type.is_sequence or idl_type.is_frozen_array
+ or idl_type.is_variadic or idl_type.is_record):
+ header_paths.update([
+ "third_party/blink/renderer/platform/wtf/vector.h",
+ "third_party/blink/renderer/platform/heap/heap_allocator.h",
+ ])
+ elif idl_type.is_promise:
+ header_paths.add(
+ "third_party/blink/renderer/bindings/core/v8/script_promise.h")
+ elif idl_type.is_union:
+ union_def_obj = idl_type.union_definition_object
+ header_paths.add(PathManager(union_def_obj).api_path(ext="h"))
+ elif idl_type.is_nullable:
+ if not blink_type_info(idl_type.inner_type).has_null_value:
+ header_paths.add("base/optional.h")
+ else:
+ assert False, "Unknown type: {}".format(idl_type.syntactic_form)
+
+ for idl_type in idl_types:
+ idl_type.apply_to_all_composing_elements(add_header_path)
-def render_code_node(code_node):
- """
- Renders |code_node| and turns it into text letting |code_node| apply all
- necessary changes (side effects). Returns the resulting text.
- """
- prev = "_"
- current = ""
- while current != prev:
- prev = current
- current = str(code_node)
- return current
+ return header_paths
def write_code_node_to_file(code_node, filepath):
@@ -139,7 +150,12 @@ def write_code_node_to_file(code_node, filepath):
rendered_text = render_code_node(code_node)
- format_result = clang_format(rendered_text, filename=filepath)
+ format_result = style_format.auto_format(rendered_text, filename=filepath)
+ if not format_result.did_succeed:
+ raise RuntimeError("Style-formatting failed: filename = {filename}\n"
+ "---- stderr ----\n"
+ "{stderr}:".format(
+ filename=format_result.filename,
+ stderr=format_result.error_message))
- with open(filepath, "w") as output_file:
- output_file.write(format_result.contents)
+ web_idl.file_io.write_to_file_if_changed(filepath, format_result.contents)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
index 9f2cfae5a15..baeeebbb697 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
@@ -9,20 +9,35 @@ import web_idl
from . import name_style
from .blink_v8_bridge import blink_class_name
from .blink_v8_bridge import blink_type_info
+from .blink_v8_bridge import make_default_value_expr
from .blink_v8_bridge import make_v8_to_blink_value
from .code_node import CodeNode
-from .code_node import FunctionDefinitionNode
+from .code_node import Likeliness
+from .code_node import ListNode
from .code_node import SequenceNode
+from .code_node import SymbolNode
from .code_node import SymbolScopeNode
from .code_node import TextNode
+from .code_node_cxx import CxxClassDefNode
+from .code_node_cxx import CxxFuncDeclNode
+from .code_node_cxx import CxxFuncDefNode
+from .code_node_cxx import CxxIfElseNode
+from .code_node_cxx import CxxLikelyIfNode
+from .code_node_cxx import CxxNamespaceNode
+from .codegen_accumulator import CodeGenAccumulator
from .codegen_context import CodeGenContext
from .codegen_expr import expr_from_exposure
from .codegen_format import format_template as _format
-from .codegen_utils import enclose_with_namespace
+from .codegen_utils import collect_include_headers_of_idl_types
+from .codegen_utils import component_export
+from .codegen_utils import component_export_header
+from .codegen_utils import enclose_with_header_guard
from .codegen_utils import make_copyright_header
+from .codegen_utils import make_forward_declarations
+from .codegen_utils import make_header_include_directives
from .codegen_utils import write_code_node_to_file
from .mako_renderer import MakoRenderer
-
+from .path_manager import PathManager
_DICT_MEMBER_PRESENCE_PREDICATES = {
"ScriptValue": "{}.IsEmpty()",
@@ -71,178 +86,337 @@ def _member_presence_expr(member):
return _format(_DICT_MEMBER_PRESENCE_PREDICATES[blink_type], _1)
-def make_dict_member_get_def(cg_context):
+def bind_member_iteration_local_vars(code_node):
+ local_vars = [
+ SymbolNode(
+ "current_context", "v8::Local<v8::Context> ${current_context} = "
+ "${isolate}->GetCurrentContext();"),
+ SymbolNode(
+ "member_names", "const auto* ${member_names} = "
+ "GetV8MemberNames(${isolate}).data();"),
+ SymbolNode(
+ "is_in_secure_context", "const bool ${is_in_secure_context} = "
+ "${execution_context}->IsSecureContext();"),
+ ]
+
+ # Execution context
+ node = SymbolNode(
+ "execution_context", "ExecutionContext* ${execution_context} = "
+ "ToExecutionContext(${current_context});")
+ node.accumulate(
+ CodeGenAccumulator.require_include_headers([
+ "third_party/blink/renderer/core/execution_context/execution_context.h"
+ ]))
+ local_vars.append(node)
+
+ code_node.register_code_symbols(local_vars)
+
+
+def _make_include_headers(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
+ dictionary = cg_context.dictionary
- member = cg_context.dict_member
+ header_includes = set()
+ source_includes = set()
- func_name = "{}::{}".format(
- blink_class_name(cg_context.dictionary),
- _blink_member_name(member).get_api)
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[],
- return_type=T(blink_type_info(member.idl_type).ref_t))
+ if dictionary.inherited:
+ header_includes.add(
+ PathManager(dictionary.inherited).api_path(ext="h"))
+ else:
+ header_includes.add(
+ "third_party/blink/renderer/platform/bindings/dictionary_base.h")
+
+ header_includes.update([
+ component_export_header(dictionary.components[0]),
+ "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
+ "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h",
+ "v8/include/v8.h",
+ ])
+ source_includes.update([
+ "third_party/blink/renderer/platform/bindings/exception_messages.h",
+ "third_party/blink/renderer/platform/bindings/exception_state.h",
+ "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h",
+ "third_party/blink/renderer/platform/heap/visitor.h",
+ ])
- body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
+ header_includes.update(
+ collect_include_headers_of_idl_types(
+ [member.idl_type for member in dictionary.own_members]))
- _1 = _blink_member_name(member).has_api
- body.append(T(_format("DCHECK({_1}());", _1=_1)))
+ return header_includes, source_includes
- _1 = _blink_member_name(member).value_var
- body.append(T(_format("return {_1};", _1=_1)))
- return func_def
+def _make_forward_declarations(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ dictionary = cg_context.dictionary
+
+ header_class_fwd_decls = set([
+ "ExceptionState",
+ "Visitor",
+ ])
+ header_struct_fwd_decls = set()
+
+ source_class_fwd_decls = set()
+ source_struct_fwd_decls = set()
+
+ return (header_class_fwd_decls, header_struct_fwd_decls,
+ source_class_fwd_decls, source_struct_fwd_decls)
-def make_dict_member_has_def(cg_context):
+def make_dict_member_get(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
+ member = cg_context.dict_member
+ blink_member_name = _blink_member_name(member)
+ name = blink_member_name.get_api
+ blink_type = blink_type_info(member.idl_type)
+
+ decls = ListNode()
+ defs = ListNode()
+
+ func_def = CxxFuncDefNode(
+ name=name,
+ arg_decls=[],
+ return_type=blink_type.const_ref_t,
+ const=True)
+ decls.append(func_def)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.extend([
+ TextNode(_format("DCHECK({}());", blink_member_name.has_api)),
+ TextNode(_format("return {};", blink_member_name.value_var)),
+ ])
+
+ if blink_type.ref_t != blink_type.const_ref_t:
+ func_def = CxxFuncDefNode(
+ name=name, arg_decls=[], return_type=blink_type.ref_t)
+ decls.append(func_def)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.extend([
+ TextNode(_format("DCHECK({}());", blink_member_name.has_api)),
+ TextNode(_format("return {};", blink_member_name.value_var)),
+ ])
+
+ return decls, defs
+
+
+def make_dict_member_has(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
member = cg_context.dict_member
- func_name = "{}::{}".format(
- blink_class_name(cg_context.dictionary),
- _blink_member_name(member).has_api)
- func_def = FunctionDefinitionNode(
- name=T(func_name), arg_decls=[], return_type=T("bool"))
+ decls = ListNode()
+ defs = ListNode()
+ func_def = CxxFuncDefNode(
+ name=_blink_member_name(member).has_api,
+ arg_decls=[],
+ return_type="bool",
+ const=True)
+ decls.append(func_def)
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
_1 = _member_presence_expr(member)
- body.append(T(_format("return {_1};", _1=_1)))
+ body.append(TextNode(_format("return {_1};", _1=_1)))
- return func_def
+ return decls, defs
-def make_dict_member_set_def(cg_context):
+def make_dict_member_set(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
member = cg_context.dict_member
+ blink_member_name = _blink_member_name(member)
+ real_type = member.idl_type.unwrap(typedef=True)
+ type_info = blink_type_info(real_type)
+
+ decls = ListNode()
+ defs = ListNode()
+
+ template_func_def = CxxFuncDefNode(
+ name=blink_member_name.set_api,
+ arg_decls=["T&& value"],
+ return_type="void",
+ template_params=["typename T"])
+ decls.append(template_func_def)
+
+ # This setter with the explicit type declaration makes it possible to set
+ # the dictionary member with uniform initialization (especially aggregate
+ # initialization), e.g. setIntVector({3, 1, 4, 1, 5}).
+ move_func_decl = CxxFuncDeclNode(
+ name=blink_member_name.set_api,
+ arg_decls=[_format("{}&&", type_info.member_t)],
+ return_type="void")
+ decls.append(move_func_decl)
+
+ move_func_def = CxxFuncDefNode(
+ name=blink_member_name.set_api,
+ arg_decls=[_format("{}&& value", type_info.member_t)],
+ return_type="void",
+ class_name=cg_context.class_name)
+ defs.append(move_func_def)
+
+ _1 = blink_member_name.value_var
+ template_func_def.body.append(
+ T(_format("{_1} = std::forward<T>(value);", _1=_1)))
+ move_func_def.body.append(T(_format("{_1} = value;", _1=_1)))
+
+ if _does_use_presence_flag(member):
+ set_presense_expr = _format("{} = true;",
+ blink_member_name.presence_var)
+ template_func_def.body.append(T(set_presense_expr))
+ move_func_def.body.append(T(set_presense_expr))
+
+ # Migration Adapter
+ if (real_type.is_nullable and
+ blink_type_info(real_type).typename.startswith("base::Optional")):
+ to_null_func_def = CxxFuncDefNode(
+ name=_format("{}ToNull", blink_member_name.set_api),
+ arg_decls=[],
+ return_type="void")
+ decls.append(to_null_func_def)
+ to_null_func_def.set_base_template_vars(cg_context.template_bindings())
+ to_null_func_def.body.append(
+ T(_format("{}(base::nullopt);", blink_member_name.set_api)))
+
+ return decls, defs
+
+
+def make_dict_member_vars(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
- func_name = "{}::{}".format(
- blink_class_name(cg_context.dictionary),
- _blink_member_name(member).set_api)
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[
- T(_format("{} value",
- blink_type_info(member.idl_type).ref_t))
- ],
- return_type=T("void"))
+ member = cg_context.dict_member
- body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
+ default_value_initializer = ""
+ if member.default_value:
+ default_expr = make_default_value_expr(member.idl_type,
+ member.default_value)
+ if default_expr.initializer is not None:
+ default_value_initializer = _format("{{{}}}",
+ default_expr.initializer)
- _1 = _blink_member_name(member).value_var
- body.append(T(_format("{_1} = value;", _1=_1)))
+ _1 = blink_type_info(member.idl_type).member_t
+ _2 = _blink_member_name(member).value_var
+ _3 = default_value_initializer
+ value_var_def = TextNode(_format("{_1} {_2}{_3};", _1=_1, _2=_2, _3=_3))
if _does_use_presence_flag(member):
_1 = _blink_member_name(member).presence_var
- body.append(T(_format("{_1} = true;", _1=_1)))
+ presense_var_def = TextNode(_format("bool {_1} = false;", _1=_1))
+ else:
+ presense_var_def = None
- return func_def
+ return value_var_def, presense_var_def
-def make_get_v8_dict_member_names_def(cg_context):
+def make_get_v8_dict_member_names_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
-
dictionary = cg_context.dictionary
-
- func_name = _format("{}::GetV8MemberNames",
- blink_class_name(cg_context.dictionary))
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[T("v8::Isolate* isolate")],
- return_type=T("const v8::Eternal<v8::Name>*"),
- comment=T("// static"))
-
+ name = "GetV8MemberNames"
+ arg_decls = ["v8::Isolate* isolate"]
+ return_type = "const base::span<const v8::Eternal<v8::Name>>"
+
+ func_decl = CxxFuncDeclNode(
+ name=name, arg_decls=arg_decls, return_type=return_type, static=True)
+ func_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- pattern = ("static const char* kKeyStrings[] = {{{_1}}};")
- _1 = ", ".join(
- _format("\"{}\"", member.identifier) for member in dictionary.members)
- body.extend([
- T(_format(pattern, _1=_1)),
- T("return V8PerIsolateData::From(isolate)"
- "->FindOrCreateEternalNameCache("
- "kKeyStrings, kKeyStrings, base::size(kKeyStrings));")
- ])
+ if dictionary.own_members:
+ pattern = "static const char* kKeyStrings[] = {{{_1}}};"
+ _1 = ", ".join(
+ _format("\"{}\"", member.identifier)
+ for member in dictionary.own_members)
+ body.extend([
+ TextNode(_format(pattern, _1=_1)),
+ TextNode("return V8PerIsolateData::From(isolate)"
+ "->FindOrCreateEternalNameCache(kKeyStrings, "
+ "kKeyStrings);"),
+ ])
+ else:
+ body.append(TextNode("return {};"))
- return func_def
+ return func_decl, func_def
-def make_fill_with_dict_members_def(cg_context):
+def make_fill_with_dict_members_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
-
dictionary = cg_context.dictionary
-
- func_name = _format(
- "{_1}::FillWithMembers", _1=blink_class_name(dictionary))
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[
- T("v8::Isolate* isolate"),
- T("v8::Local<v8::Object> creation_context"),
- T("v8::Local<v8::Object> v8_dictionary"),
- ],
- return_type=T("bool"))
-
+ name = "FillWithMembers"
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Object> creation_context",
+ "v8::Local<v8::Object> v8_dictionary",
+ ]
+ return_type = "bool"
+
+ func_decl = CxxFuncDeclNode(
+ name=name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ const=True,
+ override=True)
+ func_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
if dictionary.inherited:
text = """\
if (!BaseClass::FillWithMembers(isolate, creation_context, v8_dictionary)) {
return false;
}"""
- body.append(T(text))
+ body.append(TextNode(text))
body.append(
- T("return FillWithOwnMembers("
- "isolate, creation_context, v8_dictionary)"))
+ TextNode("return FillWithOwnMembers("
+ "isolate, creation_context, v8_dictionary);"))
- return func_def
+ return func_decl, func_def
-def make_fill_with_own_dict_members_def(cg_context):
+def make_fill_with_own_dict_members_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
-
- func_name = _format(
- "{_1}::FillWithOwnMembers", _1=blink_class_name(dictionary))
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[
- T("v8::Isolate* isolate"),
- T("v8::Local<v8::Object> creation_context"),
- T("v8::Local<v8::Object> v8_dictionary")
- ],
- return_type=T("bool"))
-
+ name = "FillWithOwnMembers"
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Object> creation_context",
+ "v8::Local<v8::Object> v8_dictionary",
+ ]
+ return_type = "bool"
+
+ func_decl = CxxFuncDeclNode(
+ name=name, arg_decls=arg_decls, return_type=return_type, const=True)
+ func_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ const=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
-
- text = """\
-const v8::Eternal<v8::Name>* member_names = GetV8MemberNames(isolate);
-v8::Local<v8::Context> current_context = isolate->GetCurrentContext();"""
- body.append(T(text))
+ body.add_template_var("isolate", "isolate")
+ bind_member_iteration_local_vars(body)
- # TODO(peria): Support runtime enabled / origin trial members.
for key_index, member in enumerate(own_members):
_1 = _blink_member_name(member).has_api
_2 = key_index
@@ -251,8 +425,8 @@ v8::Local<v8::Context> current_context = isolate->GetCurrentContext();"""
if ({_1}()) {{
if (!v8_dictionary
->CreateDataProperty(
- current_context,
- member_names[{_2}].Get(isolate),
+ ${current_context},
+ ${member_names}[{_2}].Get(isolate),
ToV8({_3}(), creation_context, isolate))
.ToChecked()) {{
return false;
@@ -263,133 +437,162 @@ if ({_1}()) {{
conditional = expr_from_exposure(member.exposure)
if not conditional.is_always_true:
- node = SequenceNode([
- T(_format("if ({}) {{", conditional.to_text())),
- node,
- T("}"),
- ])
+ node = CxxLikelyIfNode(cond=conditional, body=node)
body.append(node)
body.append(T("return true;"))
- return func_def
+ return func_decl, func_def
-def make_dict_create_def(cg_context):
+def make_dict_create_funcs(cg_context):
assert isinstance(cg_context, CodeGenContext)
- T = TextNode
-
- dictionary = cg_context.dictionary
- class_name = blink_class_name(dictionary)
-
- func_def = FunctionDefinitionNode(
- name=T(_format("{_1}::Create", _1=class_name)),
- arg_decls=[
- T("v8::Isolate* isolate"),
- T("v8::Local<v8::Object> v8_dictionary"),
- T("ExceptionState& exception_state"),
- ],
- return_type=T(_format("{_1}*", _1=class_name)),
- comment=T("// static"))
-
- body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
-
- pattern = """\
-{_1}* dictionary = MakeGarbageCollected<{_1}>();
-dictionary->FillMembers(isolate, v8_dictionary, exception_state);
+ name = "Create"
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> v8_value",
+ "ExceptionState& exception_state",
+ ]
+ return_type = "${class_name}*"
+
+ default_create_def = CxxFuncDefNode(
+ name=name, arg_decls=[], return_type=return_type, static=True)
+ default_create_def.set_base_template_vars(cg_context.template_bindings())
+
+ default_create_def.body.append(
+ TextNode("return MakeGarbageCollected<${class_name}>();"))
+
+ create_decl = CxxFuncDeclNode(
+ name=name, arg_decls=arg_decls, return_type=return_type, static=True)
+ create_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ create_def.set_base_template_vars(cg_context.template_bindings())
+
+ create_def.body.append(
+ TextNode("""\
+DCHECK(!v8_value.IsEmpty());
+
+${class_name}* dictionary = MakeGarbageCollected<${class_name}>();
+dictionary->FillMembers(isolate, v8_value, exception_state);
if (exception_state.HadException()) {
return nullptr;
}
-return dictionary;"""
- body.append(T(_format(pattern, _1=class_name)))
+return dictionary;"""))
- return func_def
+ decls = ListNode([
+ default_create_def,
+ create_decl,
+ ])
+ defs = ListNode([
+ create_def,
+ ])
+ return decls, defs
-def make_fill_dict_members_def(cg_context):
+
+def make_fill_dict_members_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
- class_name = blink_class_name(dictionary)
own_members = dictionary.own_members
required_own_members = list(
member for member in own_members if member.is_required)
-
- func_name = _format("{_1}::FillMembers", _1=class_name)
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[
- T("v8::Isolate* isolate"),
- T("v8::Local<v8::Object> v8_dictionary"),
- T("ExceptionState& exception_state"),
- ],
- return_type=T("void"))
-
- body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
-
- text = "if (v8_dictionary->IsUndefinedOrNull()) { return; }"
- if len(required_own_members) > 0:
- text = """\
-if (v8_dictionary->IsUndefinedOrNull()) {
- exception_state.ThrowError(ExceptionMessages::FailedToConstruct(
+ name = "FillMembers"
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> v8_value",
+ "ExceptionState& exception_state",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=name, arg_decls=arg_decls, return_type=return_type)
+ func_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+
+ if required_own_members:
+ check_required_members_node = T("""\
+if (v8_value->IsNullOrUndefined()) {
+ exception_state.ThrowTypeError(ExceptionMessages::FailedToConstruct(
"${dictionary.identifier}",
"has required members, but null/undefined was passed."));
return;
-}"""
- body.append(T(text))
+}""")
+ else:
+ check_required_members_node = T("""\
+if (v8_value->IsNullOrUndefined()) {
+ return;
+}""")
# [PermissiveDictionaryConversion]
if "PermissiveDictionaryConversion" in dictionary.extended_attributes:
- text = """\
-if (!v8_dictionary->IsObject()) {
+ permissive_conversion_node = T("""\
+if (!v8_value->IsObject()) {
// [PermissiveDictionaryConversion]
return;
-}"""
+}""")
else:
- text = """\
-if (!v8_dictionary->IsObject()) {
+ permissive_conversion_node = T("""\
+if (!v8_value->IsObject()) {
exception_state.ThrowTypeError(
ExceptionMessages::FailedToConstruct(
"${dictionary.identifier}", "The value is not of type Object"));
return;
-}"""
- body.append(T(text))
+}""")
- body.append(
- T("FillMembersInternal(isolate, v8_dictionary, exception_state);"))
+ call_internal_func_node = T("""\
+FillMembersInternal(isolate, v8_value.As<v8::Object>(), exception_state);""")
- return func_def
+ func_def.body.extend([
+ check_required_members_node,
+ permissive_conversion_node,
+ call_internal_func_node,
+ ])
+
+ return func_decl, func_def
-def make_fill_dict_members_internal_def(cg_context):
+def make_fill_dict_members_internal_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
- class_name = blink_class_name(dictionary)
-
- func_name = _format("{_1}::FillMembersInternal", _1=class_name)
- func_def = FunctionDefinitionNode(
- name=T(func_name),
- arg_decls=[
- T("v8::Isolate* isolate"),
- T("v8::Local<v8::Object> v8_dictionary"),
- T("ExceptionState& exception_state"),
- ],
- return_type=T("void"))
-
+ name = "FillMembersInternal"
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Object> v8_dictionary",
+ "ExceptionState& exception_state",
+ ]
+ return_type = "void"
+ func_decl = CxxFuncDeclNode(
+ name=name, arg_decls=arg_decls, return_type=return_type)
+ func_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
body.add_template_var("isolate", "isolate")
body.add_template_var("exception_state", "exception_state")
+ bind_member_iteration_local_vars(body)
+ body.register_code_symbols([
+ SymbolNode("try_block", "v8::TryCatch ${try_block}(${isolate});"),
+ SymbolNode("v8_value", "v8::Local<v8::Value> ${v8_value};"),
+ ])
if dictionary.inherited:
text = """\
@@ -400,20 +603,10 @@ if (${exception_state}.HadException()) {
"""
body.append(T(text))
- body.extend([
- T("const v8::Eternal<v8::Name>* member_names = "
- "GetV8MemberNames(${isolate});"),
- T("v8::TryCatch try_block(${isolate});"),
- T("v8::Local<v8::Context> current_context = "
- "${isolate}->GetCurrentContext();"),
- T("v8::Local<v8::Value> v8_value;"),
- ])
-
- # TODO(peria): Support origin-trials and runtime enabled features.
for key_index, member in enumerate(own_members):
body.append(make_fill_own_dict_member(key_index, member))
- return func_def
+ return func_decl, func_def
def make_fill_own_dict_member(key_index, member):
@@ -423,116 +616,266 @@ def make_fill_own_dict_member(key_index, member):
T = TextNode
pattern = """
-if (!v8_dictionary->Get(current_context, member_names[{_1}].Get(${isolate}))
- .ToLocal(&v8_memer)) {{
- ${exception_state}.RethrowV8Exception(try_block.Exception());
+if (!<% try_block %>v8_dictionary->Get(${current_context}, ${member_names}[{_1}].Get(${isolate}))
+ .ToLocal(&${v8_value})) {{
+ ${exception_state}.RethrowV8Exception(${try_block}.Exception());
return;
}}"""
get_v8_value_node = T(_format(pattern, _1=key_index))
api_call_node = SymbolScopeNode()
api_call_node.register_code_symbol(
- make_v8_to_blink_value("blink_value", "v8_value", member.idl_type))
+ make_v8_to_blink_value("blink_value", "${v8_value}", member.idl_type))
_1 = _blink_member_name(member).set_api
api_call_node.append(T(_format("{_1}(${blink_value});", _1=_1)))
- throw_if_required_member_is_missing_node = None
if member.is_required:
- pattern = """\
+ exception_pattern = """\
${exception_state}.ThrowTypeError(
ExceptionMessages::FailedToGet(
- "{_1}", "${{dictionary.identifier}}",
+ "{}", "${{dictionary.identifier}}",
"Required member is undefined."));
"""
- throw_if_required_member_is_missing_node = T(
- _format(pattern, _1=member.identifier))
+
+ check_and_fill_node = CxxIfElseNode(
+ cond="!${v8_value}->IsUndefined()",
+ then=api_call_node,
+ then_likeliness=Likeliness.LIKELY,
+ else_=T(_format(exception_pattern, member.identifier)),
+ else_likeliness=Likeliness.UNLIKELY)
+ else:
+ check_and_fill_node = CxxLikelyIfNode(
+ cond="!${v8_value}->IsUndefined()", body=api_call_node)
node = SequenceNode([
get_v8_value_node,
- T("if (!v8_value->IsUndefined()) {"),
- api_call_node,
- T("} else {") if throw_if_required_member_is_missing_node else None,
- throw_if_required_member_is_missing_node,
- T("}"),
+ check_and_fill_node,
])
conditional = expr_from_exposure(member.exposure)
if not conditional.is_always_true:
- node = SequenceNode([
- T(_format("if ({}) {{", conditional.to_text())),
- node,
- T("}"),
- ])
+ node = CxxLikelyIfNode(cond=conditional, body=node)
return node
-def make_dict_trace_def(cg_context):
+def make_dict_trace_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
- class_name = blink_class_name(dictionary)
-
- func_def = FunctionDefinitionNode(
- name=T(_format("{_1}::Trace", _1=class_name)),
- arg_decls=[
- T("Visitor* visitor"),
- ],
- return_type=T("void"))
-
+ name = "Trace"
+ arg_decls = ["Visitor* visitor"]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=name, arg_decls=arg_decls, return_type=return_type, override=True)
+ func_def = CxxFuncDefNode(
+ name=name,
+ class_name=cg_context.class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- body.add_template_vars(cg_context.template_bindings())
- def trace_member_node(member):
+ def make_trace_member_node(member):
pattern = "TraceIfNeeded<{_1}>::Trace(visitor, {_2});"
_1 = blink_type_info(member.idl_type).member_t
_2 = _blink_member_name(member).value_var
- return T(_format(pattern, _1=_1, _2=_2))
-
- body.extend(map(trace_member_node, own_members))
+ return TextNode(_format(pattern, _1=_1, _2=_2))
- if dictionary.inherited:
- body.append(T("BaseClass::Trace(visitor);"))
-
- return func_def
-
-
-def generate_dictionaries(web_idl_database, output_dirs):
- dictionary = web_idl_database.find("MediaDecodingConfiguration")
- filename = "example_dictionary.cc"
- filepath = os.path.join(output_dirs['core'], filename)
+ body.extend(map(make_trace_member_node, own_members))
+ body.append(TextNode("BaseClass::Trace(visitor);"))
- cg_context = CodeGenContext(dictionary=dictionary)
+ return func_decl, func_def
- root_node = SymbolScopeNode(separator_last="\n")
- root_node.set_renderer(MakoRenderer())
- code_node = SequenceNode()
+def generate_dictionary(dictionary):
+ assert len(dictionary.components) == 1, (
+ "We don't support partial dictionaries across components yet.")
+ component = dictionary.components[0]
- code_node.extend([
- make_get_v8_dict_member_names_def(cg_context),
- make_dict_create_def(cg_context),
- make_fill_dict_members_def(cg_context),
- make_fill_dict_members_internal_def(cg_context),
- make_fill_with_dict_members_def(cg_context),
- make_fill_with_own_dict_members_def(cg_context),
- make_dict_trace_def(cg_context),
- ])
-
- for member in dictionary.own_members:
- code_node.extend([
- make_dict_member_get_def(cg_context.make_copy(dict_member=member)),
- make_dict_member_has_def(cg_context.make_copy(dict_member=member)),
- make_dict_member_set_def(cg_context.make_copy(dict_member=member)),
+ path_manager = PathManager(dictionary)
+ class_name = name_style.class_(blink_class_name(dictionary))
+ if dictionary.inherited:
+ base_class_name = blink_class_name(dictionary.inherited)
+ else:
+ base_class_name = "bindings::DictionaryBase"
+
+ cg_context = CodeGenContext(
+ dictionary=dictionary,
+ class_name=class_name,
+ base_class_name=base_class_name)
+
+ # Filepaths
+ basename = "dictionary_example"
+ header_path = path_manager.api_path(filename=basename, ext="h")
+ source_path = path_manager.api_path(filename=basename, ext="cc")
+
+ # Root nodes
+ header_node = ListNode(tail="\n")
+ header_node.set_accumulator(CodeGenAccumulator())
+ header_node.set_renderer(MakoRenderer())
+ source_node = ListNode(tail="\n")
+ source_node.set_accumulator(CodeGenAccumulator())
+ source_node.set_renderer(MakoRenderer())
+
+ # Namespaces
+ header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+
+ # Class definitions
+ class_def = CxxClassDefNode(
+ cg_context.class_name,
+ base_class_names=[cg_context.base_class_name],
+ export=component_export(component))
+ class_def.set_base_template_vars(cg_context.template_bindings())
+ class_def.top_section.append(
+ TextNode("using BaseClass = ${base_class_name};"))
+
+ # Create functions
+ create_decl, create_def = make_dict_create_funcs(cg_context)
+
+ # Constructor and destructor
+ constructor_decl = CxxFuncDeclNode(
+ name=cg_context.class_name, arg_decls=[], return_type="", default=True)
+ destructor_decl = CxxFuncDeclNode(
+ name="~${class_name}", arg_decls=[], return_type="", default=True)
+
+ # Fill with members (Blink -> V8 conversion)
+ (fill_with_members_decl,
+ fill_with_members_def) = make_fill_with_dict_members_func(cg_context)
+ (fill_with_own_members_decl, fill_with_own_members_def
+ ) = make_fill_with_own_dict_members_func(cg_context)
+
+ # Fill members (V8 -> Blink conversion)
+ (fill_members_decl,
+ fill_members_def) = make_fill_dict_members_func(cg_context)
+ (fill_members_internal_decl, fill_members_internal_def
+ ) = make_fill_dict_members_internal_func(cg_context)
+
+ # Misc. functions
+ (get_v8_member_names_decl,
+ get_v8_member_names_def) = make_get_v8_dict_member_names_func(cg_context)
+ trace_decl, trace_def = make_dict_trace_func(cg_context)
+
+ member_accessor_decls = ListNode()
+ member_accessor_defs = ListNode()
+ member_value_var_defs = ListNode()
+ member_presense_var_defs = ListNode()
+ for member in cg_context.dictionary.own_members:
+ member_context = cg_context.make_copy(dict_member=member)
+ get_decls, get_defs = make_dict_member_get(member_context)
+ has_decls, has_defs = make_dict_member_has(member_context)
+ set_decls, set_defs = make_dict_member_set(member_context)
+ value_var_def, presense_var_def = make_dict_member_vars(member_context)
+ member_accessor_decls.extend([
+ TextNode(""),
+ get_decls,
+ has_decls,
+ set_decls,
])
-
- root_node.extend([
+ member_accessor_defs.extend([
+ TextNode(""),
+ get_defs,
+ has_defs,
+ set_defs,
+ ])
+ member_value_var_defs.append(value_var_def)
+ member_presense_var_defs.append(presense_var_def)
+
+ # Header part (copyright, include directives, and forward declarations)
+ header_includes, source_includes = _make_include_headers(cg_context)
+ header_node.accumulator.add_include_headers(header_includes)
+ source_node.accumulator.add_include_headers(source_includes)
+
+ (header_class_fwd_decls, header_struct_fwd_decls, source_class_fwd_decls,
+ source_struct_fwd_decls) = _make_forward_declarations(cg_context)
+ header_node.accumulator.add_class_decls(header_class_fwd_decls)
+ header_node.accumulator.add_struct_decls(header_struct_fwd_decls)
+ source_node.accumulator.add_class_decls(source_class_fwd_decls)
+ source_node.accumulator.add_struct_decls(source_struct_fwd_decls)
+
+ header_node.extend([
+ make_copyright_header(),
+ TextNode(""),
+ enclose_with_header_guard(
+ ListNode([
+ make_header_include_directives(header_node.accumulator),
+ TextNode(""),
+ header_blink_ns,
+ ]), name_style.header_guard(header_path)),
+ ])
+ header_blink_ns.body.extend([
+ make_forward_declarations(header_node.accumulator),
+ TextNode(""),
+ ])
+ source_node.extend([
make_copyright_header(),
TextNode(""),
- enclose_with_namespace(code_node, name_style.namespace("blink")),
+ TextNode("#include \"{}\"".format(header_path)),
+ TextNode(""),
+ make_header_include_directives(source_node.accumulator),
+ TextNode(""),
+ source_blink_ns,
+ ])
+ source_blink_ns.body.extend([
+ make_forward_declarations(source_node.accumulator),
+ TextNode(""),
+ ])
+
+ # Assemble the parts.
+ header_blink_ns.body.append(class_def)
+ class_def.public_section.extend([
+ create_decl,
+ constructor_decl,
+ destructor_decl,
+ TextNode(""),
+ trace_decl,
+ TextNode(""),
+ member_accessor_decls,
+ ])
+ class_def.protected_section.extend([
+ fill_with_members_decl,
+ TextNode(""),
+ fill_members_internal_decl,
+ ])
+ class_def.private_section.extend([
+ get_v8_member_names_decl,
+ TextNode(""),
+ fill_with_own_members_decl,
+ TextNode(""),
+ fill_members_decl,
+ TextNode(""),
+ member_value_var_defs,
+ TextNode(""),
+ member_presense_var_defs,
+ ])
+ source_blink_ns.body.extend([
+ get_v8_member_names_def,
+ TextNode(""),
+ create_def,
+ TextNode(""),
+ fill_with_members_def,
+ TextNode(""),
+ fill_with_own_members_def,
+ TextNode(""),
+ fill_members_def,
+ TextNode(""),
+ fill_members_internal_def,
+ TextNode(""),
+ member_accessor_defs,
+ TextNode(""),
+ trace_def,
])
- write_code_node_to_file(root_node, filepath)
+ # Write down to the files.
+ write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
+ write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))
+
+
+def generate_dictionaries(web_idl_database):
+ dictionary = web_idl_database.find("RTCQuicStreamWriteParameters")
+ generate_dictionary(dictionary)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py
new file mode 100644
index 00000000000..3401ff9de18
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/enumeration.py
@@ -0,0 +1,360 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from . import name_style
+from .blink_v8_bridge import blink_class_name
+from .code_node import EmptyNode
+from .code_node import ListNode
+from .code_node import TextNode
+from .code_node_cxx import CxxClassDefNode
+from .code_node_cxx import CxxFuncDeclNode
+from .code_node_cxx import CxxFuncDefNode
+from .code_node_cxx import CxxNamespaceNode
+from .codegen_accumulator import CodeGenAccumulator
+from .codegen_context import CodeGenContext
+from .codegen_format import format_template as _format
+from .codegen_utils import component_export
+from .codegen_utils import component_export_header
+from .codegen_utils import enclose_with_header_guard
+from .codegen_utils import make_copyright_header
+from .codegen_utils import make_forward_declarations
+from .codegen_utils import make_header_include_directives
+from .codegen_utils import write_code_node_to_file
+from .mako_renderer import MakoRenderer
+from .path_manager import PathManager
+
+
+def make_factory_method(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+
+ factory_method_def = CxxFuncDefNode(
+ name="Create",
+ arg_decls=[
+ "v8::Isolate* isolate",
+ "v8::Local<v8::Value> value",
+ "ExceptionState& exception_state",
+ ],
+ return_type="${class_name}",
+ static=True)
+ factory_method_def.set_base_template_vars(cg_context.template_bindings())
+
+ factory_method_def.body.extend([
+ T("const auto& result = bindings::FindIndexInEnumStringTable("
+ "isolate, value, string_table_, \"${enumeration.identifier}\", "
+ "exception_state);"),
+ T("return result.has_value() ? "
+ "${class_name}(static_cast<Enum>(result.value())) : "
+ "${class_name}();"),
+ ])
+
+ return factory_method_def, None
+
+
+def make_constructors(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+
+ class_name = cg_context.class_name
+
+ decls = ListNode([
+ CxxFuncDeclNode(
+ name=class_name,
+ arg_decls=[],
+ return_type="",
+ constexpr=True,
+ default=True),
+ CxxFuncDefNode(
+ name=class_name,
+ arg_decls=["Enum value"],
+ return_type="",
+ explicit=True,
+ constexpr=True,
+ member_initializer_list=[
+ "${base_class_name}("
+ "static_cast<enum_int_t>(value), "
+ "string_table_[static_cast<enum_int_t>(value)])"
+ ]),
+ CxxFuncDeclNode(
+ name=class_name,
+ arg_decls=["const ${class_name}&"],
+ return_type="",
+ constexpr=True,
+ default=True),
+ CxxFuncDeclNode(
+ name=class_name,
+ arg_decls=["${class_name}&&"],
+ return_type="",
+ constexpr=True,
+ default=True),
+ CxxFuncDeclNode(
+ name="~${class_name}", arg_decls=[], return_type="", default=True),
+ ])
+
+ defs = ListNode([
+ T("static_assert("
+ "std::is_trivially_copyable<${class_name}>::value, \"\");"),
+ ])
+ defs.set_base_template_vars(cg_context.template_bindings())
+
+ return decls, defs
+
+
+def make_assignment_operators(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ decls = ListNode([
+ CxxFuncDeclNode(
+ name="operator=",
+ arg_decls=["const ${class_name}&"],
+ return_type="${class_name}&",
+ default=True),
+ CxxFuncDeclNode(
+ name="operator=",
+ arg_decls=["${class_name}&&"],
+ return_type="${class_name}&",
+ default=True),
+ ])
+ defs = ListNode()
+
+ # Migration adapter
+ func_decl = CxxFuncDeclNode(
+ name="operator=",
+ arg_decls=["const String&"],
+ return_type="${class_name}&")
+ func_def = CxxFuncDefNode(
+ name="operator=",
+ arg_decls=["const String& str_value"],
+ return_type="${class_name}&",
+ class_name=cg_context.class_name)
+ decls.append(func_decl)
+ defs.append(func_def)
+
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(
+ TextNode("""\
+const auto& index =
+ bindings::FindIndexInEnumStringTable(str_value, string_table_);
+CHECK(index.has_value());
+return operator=(${class_name}(static_cast<Enum>(index.value())));
+"""))
+
+ return decls, defs
+
+
+def make_equality_operators(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ func1_def = CxxFuncDefNode(
+ name="operator==",
+ arg_decls=["const ${class_name}& lhs", "${class_name}::Enum rhs"],
+ return_type="bool",
+ inline=True)
+ func1_def.set_base_template_vars(cg_context.template_bindings())
+ func1_def.body.append(TextNode("return lhs.AsEnum() == rhs;"))
+
+ func2_def = CxxFuncDefNode(
+ name="operator==",
+ arg_decls=["${class_name}::Enum lhs", "const ${class_name}& rhs"],
+ return_type="bool",
+ inline=True)
+ func2_def.set_base_template_vars(cg_context.template_bindings())
+ func2_def.body.append(TextNode("return lhs == rhs.AsEnum();"))
+
+ decls = ListNode([func1_def, EmptyNode(), func2_def])
+
+ # Migration adapter
+ func3_def = CxxFuncDefNode(
+ name="operator==",
+ arg_decls=["const ${class_name}& lhs", "const String& rhs"],
+ return_type="bool",
+ inline=True)
+ func3_def.set_base_template_vars(cg_context.template_bindings())
+ func3_def.body.append(TextNode("return lhs.AsString() == rhs;"))
+
+ func4_def = CxxFuncDefNode(
+ name="operator==",
+ arg_decls=["const String& lhs", "const ${class_name}& rhs"],
+ return_type="bool",
+ inline=True)
+ func4_def.set_base_template_vars(cg_context.template_bindings())
+ func4_def.body.append(TextNode("return lhs == rhs.AsString();"))
+
+ decls.extend([EmptyNode(), func3_def, EmptyNode(), func4_def])
+
+ return decls, None
+
+
+def make_as_enum_function(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ func_def = CxxFuncDefNode(
+ name="AsEnum", arg_decls=[], return_type="Enum", const=True)
+ func_def.body.append(TextNode("return static_cast<Enum>(GetEnumValue());"))
+
+ return func_def, None
+
+
+def make_nested_enum_class_def(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ enum_values = [
+ TextNode(name_style.constant(value))
+ for value in cg_context.enumeration.values
+ ]
+
+ return ListNode([
+ TextNode("enum class Enum : enum_int_t {"),
+ ListNode(enum_values, separator=", "),
+ TextNode("};"),
+ ])
+
+
+def make_enum_string_table(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ str_values = [
+ TextNode("\"{}\"".format(value))
+ for value in cg_context.enumeration.values
+ ]
+
+ decls = ListNode([
+ TextNode("static constexpr const char* const string_table_[] = {"),
+ ListNode(str_values, separator=", "),
+ TextNode("};"),
+ ])
+
+ defs = TextNode("const char* const ${class_name}::string_table_[];")
+ defs.set_base_template_vars(cg_context.template_bindings())
+
+ return decls, defs
+
+
+def generate_enumeration(enumeration):
+ path_manager = PathManager(enumeration)
+ assert path_manager.api_component == path_manager.impl_component
+ api_component = path_manager.api_component
+
+ # Class names
+ class_name = blink_class_name(enumeration)
+
+ cg_context = CodeGenContext(
+ enumeration=enumeration,
+ class_name=class_name,
+ base_class_name="bindings::EnumerationBase")
+
+ # Filepaths
+ header_path = path_manager.api_path(ext="h")
+ source_path = path_manager.api_path(ext="cc")
+
+ # Root nodes
+ header_node = ListNode(tail="\n")
+ header_node.set_accumulator(CodeGenAccumulator())
+ header_node.set_renderer(MakoRenderer())
+ source_node = ListNode(tail="\n")
+ source_node.set_accumulator(CodeGenAccumulator())
+ source_node.set_renderer(MakoRenderer())
+
+ # Namespaces
+ header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+
+ # Class definition
+ class_def = CxxClassDefNode(
+ cg_context.class_name,
+ base_class_names=["bindings::EnumerationBase"],
+ final=True,
+ export=component_export(api_component))
+ class_def.set_base_template_vars(cg_context.template_bindings())
+
+ # Implementation parts
+ factory_decls, factory_defs = make_factory_method(cg_context)
+ ctor_decls, ctor_defs = make_constructors(cg_context)
+ assign_decls, assign_defs = make_assignment_operators(cg_context)
+ equal_decls, equal_defs = make_equality_operators(cg_context)
+ nested_enum_class_def = make_nested_enum_class_def(cg_context)
+ table_decls, table_defs = make_enum_string_table(cg_context)
+ as_enum_decl, as_enum_def = make_as_enum_function(cg_context)
+
+ # Header part (copyright, include directives, and forward declarations)
+ header_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ enclose_with_header_guard(
+ ListNode([
+ make_header_include_directives(header_node.accumulator),
+ EmptyNode(),
+ header_blink_ns,
+ ]), name_style.header_guard(header_path)),
+ ])
+ header_blink_ns.body.extend([
+ make_forward_declarations(header_node.accumulator),
+ EmptyNode(),
+ ])
+ source_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ TextNode("#include \"{}\"".format(header_path)),
+ EmptyNode(),
+ make_header_include_directives(source_node.accumulator),
+ EmptyNode(),
+ source_blink_ns,
+ ])
+ source_blink_ns.body.extend([
+ make_forward_declarations(source_node.accumulator),
+ EmptyNode(),
+ ])
+ header_node.accumulator.add_include_headers([
+ component_export_header(api_component),
+ "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
+ "third_party/blink/renderer/platform/bindings/enumeration_base.h",
+ ])
+
+ # Assemble the parts.
+ header_blink_ns.body.append(class_def)
+ header_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(nested_enum_class_def)
+ class_def.public_section.append(EmptyNode())
+
+ class_def.public_section.append(factory_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(factory_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.private_section.append(table_decls)
+ class_def.private_section.append(EmptyNode())
+ source_blink_ns.body.append(table_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(ctor_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(ctor_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(assign_decls)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(assign_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ class_def.public_section.append(as_enum_decl)
+ class_def.public_section.append(EmptyNode())
+ source_blink_ns.body.append(as_enum_def)
+ source_blink_ns.body.append(EmptyNode())
+
+ header_blink_ns.body.append(equal_decls)
+ header_blink_ns.body.append(EmptyNode())
+ source_blink_ns.body.append(equal_defs)
+ source_blink_ns.body.append(EmptyNode())
+
+ # Write down to the files.
+ write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
+ write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))
+
+
+def generate_enumerations(web_idl_database):
+ for enumeration in web_idl_database.enumerations:
+ generate_enumeration(enumeration)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index 03b2a99a629..9d2ce6944de 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import itertools
+import multiprocessing
import os.path
import web_idl
@@ -12,26 +13,184 @@ from .blink_v8_bridge import blink_class_name
from .blink_v8_bridge import blink_type_info
from .blink_v8_bridge import make_v8_to_blink_value
from .blink_v8_bridge import make_v8_to_blink_value_variadic
-from .code_node import CodeNode
-from .code_node import FunctionDefinitionNode
-from .code_node import LiteralNode
+from .blink_v8_bridge import v8_bridge_class_name
+from .code_node import EmptyNode
+from .code_node import ListNode
from .code_node import SequenceNode
from .code_node import SymbolDefinitionNode
from .code_node import SymbolNode
from .code_node import SymbolScopeNode
from .code_node import TextNode
-from .code_node import UnlikelyExitNode
+from .code_node_cxx import CxxBlockNode
+from .code_node_cxx import CxxBreakableBlockNode
+from .code_node_cxx import CxxClassDefNode
+from .code_node_cxx import CxxFuncDeclNode
+from .code_node_cxx import CxxFuncDefNode
+from .code_node_cxx import CxxLikelyIfNode
+from .code_node_cxx import CxxMultiBranchesNode
+from .code_node_cxx import CxxNamespaceNode
+from .code_node_cxx import CxxUnlikelyIfNode
from .codegen_accumulator import CodeGenAccumulator
from .codegen_context import CodeGenContext
+from .codegen_expr import CodeGenExpr
from .codegen_expr import expr_from_exposure
from .codegen_expr import expr_or
from .codegen_format import format_template as _format
-from .codegen_utils import collect_include_headers
-from .codegen_utils import enclose_with_namespace
+from .codegen_utils import component_export
+from .codegen_utils import component_export_header
+from .codegen_utils import enclose_with_header_guard
from .codegen_utils import make_copyright_header
+from .codegen_utils import make_forward_declarations
from .codegen_utils import make_header_include_directives
from .codegen_utils import write_code_node_to_file
from .mako_renderer import MakoRenderer
+from .path_manager import PathManager
+
+
+def _is_none_or_str(arg):
+ return arg is None or isinstance(arg, str)
+
+
+def backward_compatible_api_func(cg_context):
+ """
+ Returns the Blink function name compatible with the old bindings generator.
+ """
+ assert isinstance(cg_context, CodeGenContext)
+
+ name = (cg_context.member_like.code_generator_info.property_implemented_as
+ or cg_context.member_like.identifier
+ or cg_context.property_.identifier)
+
+ if cg_context.attribute_get:
+ # modules/webaudio/biquad_filter_node.idl has readonly attribute "Q"
+ # and somehow it's implemented as "q" in Blink.
+ if name == "Q":
+ name = "q"
+
+ if cg_context.attribute_set:
+ tokens = name_style.raw.tokenize(name)
+ if tokens[0] in ("IDL", "css", "xml"):
+ tokens[0] = tokens[0].upper()
+ else:
+ tokens[0] = tokens[0].capitalize()
+ tokens.insert(0, "set")
+ name = "".join(tokens)
+
+ if cg_context.indexed_property_getter and not name:
+ name = "AnonymousIndexedGetter"
+ if cg_context.indexed_property_setter and not name:
+ name = "AnonymousIndexedSetter"
+ if cg_context.named_property_getter and not name:
+ name = "AnonymousNamedGetter"
+ if cg_context.named_property_setter and not name:
+ name = "AnonymousNamedSetter"
+ if cg_context.named_property_deleter and not name:
+ name = "AnonymousNamedDeleter"
+
+ return name
+
+
+def callback_function_name(cg_context,
+ overload_index=None,
+ for_cross_origin=False):
+ assert isinstance(cg_context, CodeGenContext)
+
+ def _cxx_name(name):
+ """
+ Returns a property name that the bindings generator can use in
+ generated code.
+
+ Note that Web IDL allows '-' (hyphen-minus) and '_' (low line) in
+ identifiers but C++ does not allow or recommend them. This function
+ encodes these characters.
+ """
+ # In Python3, we can use str.maketrans and str.translate.
+ #
+ # We're optimistic about name conflict. It's highly unlikely that
+ # these replacements will cause a conflict.
+ assert "Dec45" not in name
+ assert "Dec95" not in name
+ name = name.replace("-", "Dec45")
+ name = name.replace("_", "Dec95")
+ return name
+
+ if cg_context.constant:
+ property_name = cg_context.property_.identifier
+ else:
+ property_name = _cxx_name(cg_context.property_.identifier)
+
+ if cg_context.attribute_get:
+ kind = "AttributeGet"
+ elif cg_context.attribute_set:
+ kind = "AttributeSet"
+ elif cg_context.constant:
+ kind = "Constant"
+ elif cg_context.constructor_group:
+ property_name = ""
+ kind = "Constructor"
+ elif cg_context.exposed_construct:
+ if cg_context.legacy_window_alias:
+ kind = "LegacyWindowAlias"
+ else:
+ kind = "ExposedConstruct"
+ elif cg_context.operation_group:
+ kind = "Operation"
+ elif cg_context.stringifier:
+ kind = "Operation"
+
+ if for_cross_origin:
+ suffix = "CrossOrigin"
+ elif overload_index is not None:
+ suffix = "Overload{}".format(overload_index + 1)
+ else:
+ suffix = "Callback"
+
+ if cg_context.for_world == CodeGenContext.MAIN_WORLD:
+ world_suffix = "ForMainWorld"
+ elif cg_context.for_world == CodeGenContext.NON_MAIN_WORLDS:
+ world_suffix = "ForNonMainWorlds"
+ elif cg_context.for_world == CodeGenContext.ALL_WORLDS:
+ world_suffix = ""
+
+ return name_style.func(property_name, kind, suffix, world_suffix)
+
+
+def constant_name(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+ assert cg_context.constant
+
+ property_name = cg_context.property_.identifier.lower()
+
+ kind = "Constant"
+
+ return name_style.constant(kind, property_name)
+
+
+def custom_function_name(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ if cg_context.named_property_getter:
+ return "NamedPropertyGetterCustom"
+ if cg_context.named_property_setter:
+ return "NamedPropertySetterCustom"
+ if cg_context.named_property_deleter:
+ return "NamedPropertyDeleterCustom"
+
+ if cg_context.attribute_get:
+ suffix = "AttributeGetterCustom"
+ elif cg_context.attribute_set:
+ suffix = "AttributeSetterCustom"
+ elif cg_context.operation_group:
+ suffix = "MethodCustom"
+ else:
+ assert False
+
+ return name_style.func(cg_context.property_.identifier, suffix)
+
+
+# ----------------------------------------------------------------------------
+# Callback functions
+# ----------------------------------------------------------------------------
def bind_blink_api_arguments(code_node, cg_context):
@@ -43,7 +202,7 @@ def bind_blink_api_arguments(code_node, cg_context):
if cg_context.attribute_set:
name = "arg1_value"
- v8_value = "${info}[0]"
+ v8_value = "${v8_property_value}"
code_node.register_code_symbol(
make_v8_to_blink_value(name, v8_value,
cg_context.attribute.idl_type))
@@ -58,8 +217,12 @@ def bind_blink_api_arguments(code_node, cg_context):
else:
v8_value = "${{info}}[{}]".format(argument.index)
code_node.register_code_symbol(
- make_v8_to_blink_value(name, v8_value, argument.idl_type,
- argument.default_value))
+ make_v8_to_blink_value(
+ name,
+ v8_value,
+ argument.idl_type,
+ argument_index=index,
+ default_value=argument.default_value))
def bind_callback_local_vars(code_node, cg_context):
@@ -73,17 +236,15 @@ def bind_callback_local_vars(code_node, cg_context):
template_vars = {}
local_vars.extend([
+ S("blink_property_name",
+ ("const AtomicString& ${blink_property_name} = "
+ "ToCoreAtomicString(${v8_property_name}.As<v8::String>());")),
S("class_like_name", ("const char* const ${class_like_name} = "
"\"${class_like.identifier}\";")),
S("current_context", ("v8::Local<v8::Context> ${current_context} = "
"${isolate}->GetCurrentContext();")),
- S("current_execution_context",
- ("ExecutionContext* ${current_execution_context} = "
- "ExecutionContext::From(${current_script_state});")),
S("current_script_state", ("ScriptState* ${current_script_state} = "
"ScriptState::From(${current_context});")),
- S("execution_context", ("ExecutionContext* ${execution_context} = "
- "ExecutionContext::From(${script_state});")),
S("isolate", "v8::Isolate* ${isolate} = ${info}.GetIsolate();"),
S("per_context_data", ("V8PerContextData* ${per_context_data} = "
"${script_state}->PerContextData();")),
@@ -101,7 +262,8 @@ def bind_callback_local_vars(code_node, cg_context):
])
is_receiver_context = (cg_context.member_like
- and not cg_context.member_like.is_static)
+ and not cg_context.member_like.is_static
+ and not cg_context.constructor)
# creation_context
pattern = "const v8::Local<v8::Context>& ${creation_context} = {_1};"
@@ -119,6 +281,24 @@ def bind_callback_local_vars(code_node, cg_context):
if is_receiver_context else "${current_script_state}")
local_vars.append(S("script_state", _format(pattern, _1=_1)))
+ # execution_context
+ node = S("execution_context", ("ExecutionContext* ${execution_context} = "
+ "ExecutionContext::From(${script_state});"))
+ node.accumulate(
+ CodeGenAccumulator.require_include_headers([
+ "third_party/blink/renderer/core/execution_context/execution_context.h"
+ ]))
+ local_vars.append(node)
+
+ # execution_context_of_document_tree
+ pattern = "ExecutionContext* ${execution_context_of_document_tree} = {_1};"
+ if is_receiver_context:
+ _1 = "bindings::ExecutionContextFromV8Wrappable(${blink_receiver})"
+ else:
+ _1 = "${execution_context}" # of the current context
+ text = _format(pattern, _1=_1)
+ local_vars.append(S("execution_context_of_document_tree", text))
+
# exception_state_context_type
pattern = (
"const ExceptionState::ContextType ${exception_state_context_type} = "
@@ -129,6 +309,16 @@ def bind_callback_local_vars(code_node, cg_context):
_1 = "ExceptionState::kSetterContext"
elif cg_context.constructor:
_1 = "ExceptionState::kConstructionContext"
+ elif cg_context.indexed_property_getter:
+ _1 = "ExceptionState::kIndexedGetterContext"
+ elif cg_context.indexed_property_setter:
+ _1 = "ExceptionState::kIndexedSetterContext"
+ elif cg_context.named_property_getter:
+ _1 = "ExceptionState::kGetterContext"
+ elif cg_context.named_property_setter:
+ _1 = "ExceptionState::kSetterContext"
+ elif cg_context.named_property_deleter:
+ _1 = "ExceptionState::kDeletionContext"
else:
_1 = "ExceptionState::kExecutionContext"
local_vars.append(
@@ -138,8 +328,9 @@ def bind_callback_local_vars(code_node, cg_context):
pattern = "ExceptionState ${exception_state}({_1});{_2}"
_1 = [
"${isolate}", "${exception_state_context_type}", "${class_like_name}",
- "${property_name}"
]
+ if cg_context.property_ and cg_context.property_.identifier:
+ _1.append("${property_name}")
_2 = ""
if cg_context.return_type and cg_context.return_type.unwrap().is_promise:
_2 = ("\n"
@@ -154,26 +345,174 @@ def bind_callback_local_vars(code_node, cg_context):
# [ImplementedAs=LocalDOMWindow] instead of [ImplementedAs=DOMWindow],
# and [CrossOrigin] properties should be implemented specifically with
# DOMWindow class. Then, we'll have less hacks.
- if "CrossOrigin" in cg_context.member_like.extended_attributes:
+ if (not cg_context.member_like or
+ "CrossOrigin" in cg_context.member_like.extended_attributes):
text = ("DOMWindow* ${blink_receiver} = "
- "${v8_class}::ToBlinkUnsafe(${v8_receiver});")
+ "${class_name}::ToWrappableUnsafe(${v8_receiver});")
else:
text = ("LocalDOMWindow* ${blink_receiver} = To<LocalDOMWindow>("
- "${v8_class}::ToBlinkUnsafe(${v8_receiver}));")
+ "${class_name}::ToWrappableUnsafe(${v8_receiver}));")
else:
pattern = ("{_1}* ${blink_receiver} = "
- "${v8_class}::ToBlinkUnsafe(${v8_receiver});")
+ "${class_name}::ToWrappableUnsafe(${v8_receiver});")
_1 = blink_class_name(cg_context.class_like)
text = _format(pattern, _1=_1)
local_vars.append(S("blink_receiver", text))
+ # v8_property_value
+ if cg_context.v8_callback_type == CodeGenContext.V8_FUNCTION_CALLBACK:
+ # In case of V8_ACCESSOR_NAME_SETTER_CALLBACK, |v8_property_value| is
+ # defined as an argument. In case of V8_FUNCTION_CALLBACK (of IDL
+ # attribute set function), |info[0]| is the value to be set.
+ local_vars.append(
+ S("v8_property_value",
+ "v8::Local<v8::Value> ${v8_property_value} = ${info}[0];"))
+
code_node.register_code_symbols(local_vars)
code_node.add_template_vars(template_vars)
-def _make_blink_api_call(cg_context, num_of_args=None):
+def _make_reflect_content_attribute_key(code_node, cg_context):
+ assert isinstance(code_node, SymbolScopeNode)
+ assert isinstance(cg_context, CodeGenContext)
+
+ name = (cg_context.attribute.extended_attributes.value_of("Reflect")
+ or cg_context.attribute.identifier.lower())
+ if cg_context.attribute_get and name in ("class", "id", "name"):
+ return None
+
+ if cg_context.class_like.identifier.startswith("SVG"):
+ namespace = "svg_names"
+ code_node.accumulate(
+ CodeGenAccumulator.require_include_headers(
+ ["third_party/blink/renderer/core/svg_names.h"]))
+ else:
+ namespace = "html_names"
+ code_node.accumulate(
+ CodeGenAccumulator.require_include_headers(
+ ["third_party/blink/renderer/core/html_names.h"]))
+ return "{}::{}".format(namespace, name_style.constant(name, "attr"))
+
+
+def _make_reflect_accessor_func_name(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+ assert cg_context.attribute_get or cg_context.attribute_set
+
+ if cg_context.attribute_get:
+ name = (cg_context.attribute.extended_attributes.value_of("Reflect")
+ or cg_context.attribute.identifier.lower())
+ if name in ("class", "id", "name"):
+ return name_style.func("get", name, "attribute")
+
+ if "URL" in cg_context.attribute.extended_attributes:
+ return "GetURLAttribute"
+
+ FAST_ACCESSORS = {
+ "boolean": ("FastHasAttribute", "SetBooleanAttribute"),
+ "long": ("GetIntegralAttribute", "SetIntegralAttribute"),
+ "unsigned long": ("GetUnsignedIntegralAttribute",
+ "SetUnsignedIntegralAttribute"),
+ }
+ idl_type = cg_context.attribute.idl_type.unwrap()
+ accessors = FAST_ACCESSORS.get(idl_type.keyword_typename)
+ if accessors:
+ return accessors[0 if cg_context.attribute_get else 1]
+
+ if (idl_type.is_interface
+ and idl_type.type_definition_object.does_implement("Element")):
+ if cg_context.attribute_get:
+ return "GetElementAttribute"
+ else:
+ return "SetElementAttribute"
+
+ if idl_type.element_type:
+ element_type = idl_type.element_type.unwrap()
+ if (element_type.is_interface and
+ element_type.type_definition_object.does_implement("Element")):
+ if cg_context.attribute_get:
+ return "GetElementArrayAttribute"
+ else:
+ return "SetElementArrayAttribute"
+
+ if cg_context.attribute_get:
+ return "FastGetAttribute"
+ else:
+ return "setAttribute"
+
+
+def _make_reflect_process_keyword_state(cg_context):
+ # https://html.spec.whatwg.org/C/#keywords-and-enumerated-attributes
+
+ assert isinstance(cg_context, CodeGenContext)
+ assert cg_context.attribute_get or cg_context.attribute_set
+
+ T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+
+ if not cg_context.attribute_get:
+ return None
+
+ ext_attrs = cg_context.attribute.extended_attributes
+ keywords = ext_attrs.values_of("ReflectOnly")
+ missing_default = ext_attrs.value_of("ReflectMissing")
+ empty_default = ext_attrs.value_of("ReflectEmpty")
+ invalid_default = ext_attrs.value_of("ReflectInvalid")
+
+ def constant(keyword):
+ if not keyword:
+ return "g_empty_atom"
+ return "keywords::{}".format(name_style.constant(keyword))
+
+ branches = CxxMultiBranchesNode()
+ branches.accumulate(
+ CodeGenAccumulator.require_include_headers(
+ ["third_party/blink/renderer/core/keywords.h"]))
+ nodes = [
+ T("// [ReflectOnly]"),
+ T("const AtomicString reflect_value(${return_value}.LowerASCII());"),
+ branches,
+ ]
+
+ if missing_default is not None:
+ branches.append(
+ cond="reflect_value.IsNull()",
+ body=F("${return_value} = {};", constant(missing_default)))
+ elif cg_context.return_type.unwrap(nullable=False).is_nullable:
+ branches.append(
+ cond="reflect_value.IsNull()",
+ body=T("// Null string to IDL null."))
+
+ if empty_default is not None:
+ branches.append(
+ cond="reflect_value.IsEmpty()",
+ body=F("${return_value} = {};", constant(empty_default)))
+
+ expr = " || ".join(
+ map(lambda keyword: "reflect_value == {}".format(constant(keyword)),
+ keywords))
+ branches.append(cond=expr, body=T("${return_value} = reflect_value;"))
+
+ if invalid_default is not None:
+ branches.append(
+ cond=True,
+ body=F("${return_value} = {};", constant(invalid_default)))
+ else:
+ branches.append(
+ cond=True, body=F("${return_value} = {};", constant("")))
+
+ return SequenceNode(nodes)
+
+
+def _make_blink_api_call(code_node,
+ cg_context,
+ num_of_args=None,
+ overriding_args=None):
+ assert isinstance(code_node, SymbolScopeNode)
assert isinstance(cg_context, CodeGenContext)
assert num_of_args is None or isinstance(num_of_args, (int, long))
+ assert (overriding_args is None
+ or (isinstance(overriding_args, (list, tuple))
+ and all(isinstance(arg, str) for arg in overriding_args)))
arguments = []
ext_attrs = cg_context.member_like.extended_attributes
@@ -187,8 +526,24 @@ def _make_blink_api_call(cg_context, num_of_args=None):
arguments.append("${script_state}")
if "ExecutionContext" in values:
arguments.append("${execution_context}")
+ if "Document" in values:
+ arguments.append(
+ "*bindings::ToDocumentFromExecutionContext(${execution_context})")
- if cg_context.attribute_get:
+ code_generator_info = cg_context.member_like.code_generator_info
+ is_partial = code_generator_info.defined_in_partial
+ if (is_partial and
+ not (cg_context.constructor or cg_context.member_like.is_static)):
+ arguments.append("*${blink_receiver}")
+
+ if "Reflect" in ext_attrs: # [Reflect]
+ key = _make_reflect_content_attribute_key(code_node, cg_context)
+ if key:
+ arguments.append(key)
+
+ if overriding_args is not None:
+ arguments.extend(overriding_args)
+ elif cg_context.attribute_get:
pass
elif cg_context.attribute_set:
arguments.append("${arg1_value}")
@@ -205,86 +560,106 @@ def _make_blink_api_call(cg_context, num_of_args=None):
if cg_context.may_throw_exception:
arguments.append("${exception_state}")
- code_generator_info = cg_context.member_like.code_generator_info
-
- func_name = (code_generator_info.property_implemented_as
- or name_style.api_func(cg_context.member_like.identifier))
- if cg_context.attribute_set:
- func_name = name_style.api_func("set", func_name)
+ func_name = backward_compatible_api_func(cg_context)
+ if cg_context.constructor:
+ func_name = "Create"
+ if "Reflect" in ext_attrs: # [Reflect]
+ func_name = _make_reflect_accessor_func_name(cg_context)
- is_partial_or_mixin = (code_generator_info.defined_in_partial
- or code_generator_info.defined_in_mixin)
- if cg_context.member_like.is_static or is_partial_or_mixin:
+ if (cg_context.constructor or cg_context.member_like.is_static
+ or is_partial):
class_like = cg_context.member_like.owner_mixin or cg_context.class_like
class_name = (code_generator_info.receiver_implemented_as
or name_style.class_(class_like.identifier))
func_designator = "{}::{}".format(class_name, func_name)
- if not cg_context.member_like.is_static:
- arguments.insert(0, "*${blink_receiver}")
else:
func_designator = _format("${blink_receiver}->{}", func_name)
return _format("{_1}({_2})", _1=func_designator, _2=", ".join(arguments))
-def bind_return_value(code_node, cg_context):
+def bind_return_value(code_node, cg_context, overriding_args=None):
assert isinstance(code_node, SymbolScopeNode)
assert isinstance(cg_context, CodeGenContext)
+ assert (overriding_args is None
+ or (isinstance(overriding_args, (list, tuple))
+ and all(isinstance(arg, str) for arg in overriding_args)))
T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
def create_definition(symbol_node):
- api_calls = []
- arguments = (cg_context.function_like.arguments
- if cg_context.function_like else [])
- for index, arg in enumerate(arguments):
- if arg.is_optional and not arg.default_value:
- api_calls.append((index, _make_blink_api_call(
- cg_context, index)))
- api_calls.append((None, _make_blink_api_call(cg_context)))
+ api_calls = [] # Pairs of (num_of_args, api_call_text)
+ if overriding_args is None:
+ arguments = (cg_context.function_like.arguments
+ if cg_context.function_like else [])
+ for index, arg in enumerate(arguments):
+ if arg.is_optional and not arg.default_value:
+ api_calls.append((index,
+ _make_blink_api_call(
+ code_node, cg_context, index)))
+ api_calls.append((None, _make_blink_api_call(
+ code_node, cg_context)))
+ else:
+ api_calls.append((None,
+ _make_blink_api_call(
+ code_node,
+ cg_context,
+ overriding_args=overriding_args)))
nodes = []
- is_return_type_void = cg_context.return_type.unwrap().is_void
- if not is_return_type_void:
+ is_return_type_void = ((not cg_context.return_type
+ or cg_context.return_type.unwrap().is_void) and
+ not cg_context.does_override_idl_return_type)
+ if not (is_return_type_void
+ or cg_context.does_override_idl_return_type):
return_type = blink_type_info(cg_context.return_type).value_t
if len(api_calls) == 1:
_, api_call = api_calls[0]
if is_return_type_void:
- nodes.append(T(_format("{};", api_call)))
+ nodes.append(F("{};", api_call))
elif cg_context.is_return_by_argument:
- nodes.append(T(_format("{} ${return_value};", return_type)))
- nodes.append(T(_format("{};", api_call)))
+ nodes.append(F("{} ${return_value};", return_type))
+ nodes.append(F("{};", api_call))
+ elif "ReflectOnly" in cg_context.member_like.extended_attributes:
+ # [ReflectOnly]
+ nodes.append(F("auto ${return_value} = {};", api_call))
else:
- nodes.append(
- T(_format("const auto& ${return_value} = {};", api_call)))
+ nodes.append(F("auto&& ${return_value} = {};", api_call))
else:
- branches = SymbolScopeNode()
+ branches = SequenceNode()
for index, api_call in api_calls:
if is_return_type_void or cg_context.is_return_by_argument:
- assignment = api_call
+ assignment = "{};".format(api_call)
else:
- assignment = _format("${return_value} = {}", api_call)
+ assignment = _format("${return_value} = {};", api_call)
if index is not None:
- pattern = ("if (${info}[{index}]->IsUndefined()) {{\n"
- " {assignment};\n"
- " break;\n"
- "}}")
+ branches.append(
+ CxxLikelyIfNode(
+ cond=_format("${info}[{}]->IsUndefined()", index),
+ body=[
+ T(assignment),
+ T("break;"),
+ ]))
else:
- pattern = "{assignment};"
- text = _format(pattern, index=index, assignment=assignment)
- branches.append(T(text))
+ branches.append(T(assignment))
if not is_return_type_void:
- nodes.append(T(_format("{} ${return_value};", return_type)))
- nodes.append(T("do { // Dummy loop for use of 'break'"))
- nodes.append(branches)
- nodes.append(T("} while (false);"))
+ nodes.append(F("{} ${return_value};", return_type))
+ nodes.append(CxxBreakableBlockNode(branches))
if cg_context.may_throw_exception:
nodes.append(
- UnlikelyExitNode(
- cond=T("${exception_state}.HadException()"),
- body=SymbolScopeNode([T("return;")])))
+ CxxUnlikelyIfNode(
+ cond="${exception_state}.HadException()",
+ body=T("return;")))
+
+ if "ReflectOnly" in cg_context.member_like.extended_attributes:
+ # [ReflectOnly]
+ node = _make_reflect_process_keyword_state(cg_context)
+ if node:
+ nodes.append(EmptyNode())
+ nodes.append(node)
return SymbolDefinitionNode(symbol_node, nodes)
@@ -292,35 +667,81 @@ def bind_return_value(code_node, cg_context):
SymbolNode("return_value", definition_constructor=create_definition))
-def bind_v8_set_return_value(code_node, cg_context):
- assert isinstance(code_node, SymbolScopeNode)
+def make_bindings_trace_event(cg_context):
assert isinstance(cg_context, CodeGenContext)
- pattern = "{_1}({_2});"
- _1 = "V8SetReturnValue"
- _2 = ["${info}", "${return_value}"]
+ event_name = "{}.{}".format(cg_context.class_like.identifier,
+ cg_context.property_.identifier)
+ if cg_context.attribute_get:
+ event_name = "{}.{}".format(event_name, "get")
+ elif cg_context.attribute_set:
+ event_name = "{}.{}".format(event_name, "set")
+ elif cg_context.constructor_group:
+ event_name = "{}.{}".format(cg_context.class_like.identifier,
+ "constructor")
- return_type = cg_context.return_type.unwrap(nullable=True, typedef=True)
- if return_type.is_void:
- # Render a SymbolNode |return_value| discarding the content text, and
- # let a symbol definition be added.
- pattern = "<% str(return_value) %>"
- elif (cg_context.for_world == cg_context.MAIN_WORLD
- and return_type.is_interface):
- _1 = "V8SetReturnValueForMainWorld"
- elif return_type.is_interface:
- _2.append("${creation_context_object}")
+ return TextNode("BLINK_BINDINGS_TRACE_EVENT(\"{}\");".format(event_name))
- text = _format(pattern, _1=_1, _2=", ".join(_2))
- code_node.add_template_var("v8_set_return_value", TextNode(text))
+def make_check_argument_length(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
-_callback_common_binders = (
- bind_blink_api_arguments,
- bind_callback_local_vars,
- bind_return_value,
- bind_v8_set_return_value,
-)
+ T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+
+ if cg_context.v8_callback_type != CodeGenContext.V8_FUNCTION_CALLBACK:
+ return None
+
+ if cg_context.attribute_get:
+ num_of_required_args = 0
+ elif cg_context.attribute_set:
+ idl_type = cg_context.attribute.idl_type
+ if not (idl_type.does_include_nullable_or_dict
+ or idl_type.unwrap().is_any or
+ "TreatNonObjectAsNull" in idl_type.unwrap().extended_attributes
+ or "PutForwards" in cg_context.attribute.extended_attributes
+ or "Replaceable" in cg_context.attribute.extended_attributes):
+ # ES undefined in ${v8_property_value} will cause a TypeError
+ # anyway, so omit the check against the number of arguments.
+ return None
+ num_of_required_args = 1
+ elif cg_context.function_like:
+ num_of_required_args = (
+ cg_context.function_like.num_of_required_arguments)
+ else:
+ assert False
+
+ if num_of_required_args == 0:
+ return None
+
+ return CxxUnlikelyIfNode(
+ cond=_format("UNLIKELY(${info}.Length() < {})", num_of_required_args),
+ body=[
+ F(("${exception_state}.ThrowTypeError("
+ "ExceptionMessages::NotEnoughArguments"
+ "({}, ${info}.Length()));"), num_of_required_args),
+ T("return;"),
+ ])
+
+
+def make_check_constructor_call(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+
+ return SequenceNode([
+ CxxUnlikelyIfNode(
+ cond="!${info}.IsConstructCall()",
+ body=T("${exception_state}.ThrowTypeError("
+ "ExceptionMessages::ConstructorNotCallableAsFunction("
+ "${class_like_name}));\n"
+ "return;")),
+ CxxLikelyIfNode(
+ cond=("ConstructorMode::Current(${isolate}) == "
+ "ConstructorMode::kWrapExistingObject"),
+ body=T("bindings::V8SetReturnValue(${info}, ${v8_receiver});\n"
+ "return;")),
+ ])
def make_check_receiver(cg_context):
@@ -332,24 +753,22 @@ def make_check_receiver(cg_context):
and "LenientThis" in cg_context.attribute.extended_attributes):
return SequenceNode([
T("// [LenientThis]"),
- UnlikelyExitNode(
- cond=T(
- "!${v8_class}::HasInstance(${v8_receiver}, ${isolate})"),
- body=SymbolScopeNode([T("return;")])),
+ CxxUnlikelyIfNode(
+ cond="!${class_name}::HasInstance(${isolate}, ${v8_receiver})",
+ body=T("return;")),
])
- if cg_context.return_type.unwrap().is_promise:
+ if cg_context.return_type and cg_context.return_type.unwrap().is_promise:
return SequenceNode([
T("// Promise returning function: "
"Convert a TypeError to a reject promise."),
- UnlikelyExitNode(
- cond=T(
- "!${v8_class}::HasInstance(${v8_receiver}, ${isolate})"),
- body=SymbolScopeNode([
+ CxxUnlikelyIfNode(
+ cond="!${class_name}::HasInstance(${isolate}, ${v8_receiver})",
+ body=[
T("${exception_state}.ThrowTypeError("
"\"Illegal invocation\");"),
- T("return;")
- ])),
+ T("return;"),
+ ])
])
return None
@@ -368,27 +787,47 @@ def make_check_security_of_return_value(cg_context):
web_feature = _format(
"WebFeature::{}",
name_style.constant("CrossOrigin", cg_context.class_like.identifier,
- cg_context.member_like.identifier))
- use_counter = _format(
- "UseCounter::Count(${current_execution_context}, {});", web_feature)
+ cg_context.property_.identifier))
+ use_counter = _format("UseCounter::Count(${execution_context}, {});",
+ web_feature)
cond = T("!BindingSecurity::ShouldAllowAccessTo("
"ToLocalDOMWindow(${current_context}), ${return_value}, "
"BindingSecurity::ErrorReportOption::kDoNotReport)")
- body = SymbolScopeNode([
+ body = [
T(use_counter),
- T("V8SetReturnValueNull(${info});\n"
+ T("bindings::V8SetReturnValue(${info}, nullptr);\n"
"return;"),
- ])
- return SequenceNode([
+ ]
+ node = SequenceNode([
T("// [CheckSecurity=ReturnValue]"),
- UnlikelyExitNode(cond=cond, body=body),
+ CxxUnlikelyIfNode(cond=cond, body=body),
])
+ node.accumulate(
+ CodeGenAccumulator.require_include_headers([
+ "third_party/blink/renderer/bindings/core/v8/binding_security.h",
+ "third_party/blink/renderer/core/frame/web_feature.h",
+ "third_party/blink/renderer/platform/instrumentation/use_counter.h",
+ ]))
+ return node
+
+
+def make_cooperative_scheduling_safepoint(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ node = TextNode("scheduler::CooperativeSchedulingManager::Instance()"
+ "->Safepoint();")
+ node.accumulate(
+ CodeGenAccumulator.require_include_headers([
+ "third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h"
+ ]))
+ return node
def make_log_activity(cg_context):
assert isinstance(cg_context, CodeGenContext)
- ext_attrs = cg_context.member_like.extended_attributes
+ target = cg_context.member_like or cg_context.property_
+ ext_attrs = target.extended_attributes
if "LogActivity" not in ext_attrs:
return None
target = ext_attrs.value_of("LogActivity")
@@ -414,10 +853,10 @@ def make_log_activity(cg_context):
if cg_context.attribute_get:
_1 = "LogGetter"
_4 = ""
- if cg_context.attribute_set:
+ elif cg_context.attribute_set:
_1 = "LogSetter"
- _4 = ", ${info}[0]"
- if cg_context.operation_group:
+ _4 = ", ${v8_property_value}"
+ elif cg_context.operation_group:
_1 = "LogMethod"
_4 = ", ${info}"
body = _format(pattern, _1=_1, _2=_2, _3=_3, _4=_4)
@@ -426,22 +865,13 @@ def make_log_activity(cg_context):
node = TextNode(_format(pattern, _1=cond, _2=body))
node.accumulate(
CodeGenAccumulator.require_include_headers([
- "third_party/blink/renderer/"
- "platform/bindings/v8_dom_activity_logger.h",
+ "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h",
+ "third_party/blink/renderer/platform/bindings/v8_per_context_data.h",
]))
return node
-def _make_overloaded_function_name(function_like):
- if isinstance(function_like, web_idl.Constructor):
- return name_style.func("constructor", "overload",
- function_like.overload_index + 1)
- else:
- return name_style.func(function_like.identifier, "op", "overload",
- function_like.overload_index + 1)
-
-
-def _make_overload_dispatcher_per_arg_size(items):
+def _make_overload_dispatcher_per_arg_size(cg_context, items):
"""
https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
@@ -454,6 +884,12 @@ def _make_overload_dispatcher_per_arg_size(items):
exists a case that overload resolution will fail, i.e. a bailout that
throws a TypeError is necessary.
"""
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(items, (list, tuple))
+ assert all(
+ isinstance(item, web_idl.OverloadGroup.EffectiveOverloadItem)
+ for item in items)
+
# Variables shared with nested functions
if len(items) > 1:
arg_index = web_idl.OverloadGroup.distinguishing_argument_index(items)
@@ -496,7 +932,8 @@ def _make_overload_dispatcher_per_arg_size(items):
def make_node(pattern):
value = _format("${info}[{}]", arg_index)
- func_name = _make_overloaded_function_name(func_like)
+ func_name = callback_function_name(cg_context,
+ func_like.overload_index)
return TextNode(_format(pattern, value=value, func_name=func_name))
def dispatch_if(expr):
@@ -509,11 +946,7 @@ def _make_overload_dispatcher_per_arg_size(items):
node = make_node(pattern)
conditional = expr_from_exposure(func_like.exposure)
if not conditional.is_always_true:
- node = SymbolScopeNode([
- TextNode("if (" + conditional.to_text() + ") {"),
- node,
- TextNode("}"),
- ])
+ node = CxxUnlikelyIfNode(cond=conditional, body=node)
dispatcher_nodes.append(node)
return expr is True and conditional.is_always_true
@@ -528,8 +961,7 @@ def _make_overload_dispatcher_per_arg_size(items):
dispatch_if("{value}->IsUndefined()")
# 12.3. if V is null or undefined, ...
- func_like = find(
- lambda t, u: t.does_include_nullable_type or u.is_dictionary)
+ func_like = find(lambda t, u: t.does_include_nullable_or_dict)
if func_like:
dispatch_if("{value}->IsNullOrUndefined()")
@@ -541,27 +973,19 @@ def _make_overload_dispatcher_per_arg_size(items):
# Attempt to match from most derived to least derived.
for func_like, idl_type in sorted(
find_all_interfaces(), key=inheritance_length, reverse=True):
- cgc = CodeGenContext(
- interface=idl_type.unwrap().type_definition_object)
+ v8_bridge_name = v8_bridge_class_name(
+ idl_type.unwrap().type_definition_object)
dispatch_if(
- _format("{}::HasInstance(${isolate}, {value})", cgc.v8_class))
+ _format("{}::HasInstance(${isolate}, {value})", v8_bridge_name))
+ # V8 specific optimization: BufferSource = ArrayBufferView or ArrayBuffer
is_typedef_name = lambda t, name: t.is_typedef and t.identifier == name
- func_like_a = find(
- lambda t, u: is_typedef_name(t.unwrap(typedef=False),
- "ArrayBufferView"))
- func_like_b = find(
+ func_like = find(
lambda t, u: is_typedef_name(t.unwrap(typedef=False), "BufferSource"))
- if func_like_a or func_like_b:
- # V8 specific optimization: ArrayBufferView
- if func_like_a:
- func_like = func_like_a
- dispatch_if("{value}->IsArrayBufferView()")
- if func_like_b:
- func_like = func_like_b
- dispatch_if("{value}->IsArrayBufferView() || "
- "{value}->IsArrayBuffer() || "
- "{value}->IsSharedArrayBuffer()")
+ if func_like:
+ dispatch_if("{value}->IsArrayBufferView() || "
+ "{value}->IsArrayBuffer() || "
+ "{value}->IsSharedArrayBuffer()")
else:
# 12.5. if Type(V) is Object, V has an [[ArrayBufferData]] internal
# slot, ...
@@ -570,16 +994,24 @@ def _make_overload_dispatcher_per_arg_size(items):
dispatch_if("{value}->IsArrayBuffer() || "
"{value}->IsSharedArrayBuffer()")
- # 12.6. if Type(V) is Object, V has a [[DataView]] internal slot, ...
- func_like = find(lambda t, u: u.is_data_view)
+ # V8 specific optimization: ArrayBufferView
+ func_like = find(lambda t, u: u.is_array_buffer_view)
if func_like:
- dispatch_if("{value}->IsDataView()")
+ dispatch_if("{value}->IsArrayBufferView()")
- # 12.7. if Type(V) is Object, V has a [[TypedArrayName]] internal slot,
- # ...
- func_like = find(lambda t, u: u.is_typed_array_type)
+ # 12.6. if Type(V) is Object, V has a [[DataView]] internal slot, ...
+ func_like = find(lambda t, u: u.is_data_view)
+ if func_like:
+ dispatch_if("{value}->IsDataView()")
+
+ # 12.7. if Type(V) is Object, V has a [[TypedArrayName]] internal slot, ...
+ typed_array_types = ("Int8Array", "Int16Array", "Int32Array", "Uint8Array",
+ "Uint16Array", "Uint32Array", "Uint8ClampedArray",
+ "Float32Array", "Float64Array")
+ for typed_array_type in typed_array_types:
+ func_like = find(lambda t, u: u.keyword_typename == typed_array_type)
if func_like:
- dispatch_if("{value}->IsTypedArray()")
+ dispatch_if(_format("{value}->Is{}()", typed_array_type))
# 12.8. if IsCallable(V) is true, ...
func_like = find(lambda t, u: u.is_callback_function)
@@ -653,46 +1085,32 @@ def make_overload_dispatcher(cg_context):
for arg_size, items in items_grouped_by_arg_size:
items = list(items)
- node, can_fail = _make_overload_dispatcher_per_arg_size(items)
+ node, can_fail = _make_overload_dispatcher_per_arg_size(
+ cg_context, items)
if arg_size > 0:
- node = SymbolScopeNode([
- T("if (${info}.Length() >= " + str(arg_size) + ") {"),
- node,
- T("break;") if can_fail else None,
- T("}"),
- ])
+ node = CxxLikelyIfNode(
+ cond=_format("${info}.Length() >= {}", arg_size),
+ body=[node, T("break;") if can_fail else None])
did_use_break = did_use_break or can_fail
- terms = map(
- lambda item: expr_from_exposure(item.function_like.exposure),
- items)
- conditional = expr_or(terms)
+ conditional = expr_or(
+ map(lambda item: expr_from_exposure(item.function_like.exposure),
+ items))
if not conditional.is_always_true:
- node = SymbolScopeNode([
- T("if (" + conditional.to_text() + ") {"),
- node,
- T("}"),
- ])
+ node = CxxUnlikelyIfNode(cond=conditional, body=node)
branches.append(node)
if did_use_break:
- branches = SymbolScopeNode([
- T("do { // Dummy loop for use of 'break'"),
- branches,
- T("} while (false);"),
- ])
- # Make the entire branches an indivisible chunk so that SymbolDefinitionNode
- # will not be inserted in-between.
- branches = LiteralNode(branches)
+ branches = CxxBreakableBlockNode(branches)
if not did_use_break and arg_size == 0 and conditional.is_always_true:
return branches
return SequenceNode([
branches,
- T(""),
+ EmptyNode(),
T("${exception_state}.ThrowTypeError"
"(\"Overload resolution failed.\");\n"
"return;"),
@@ -702,7 +1120,8 @@ def make_overload_dispatcher(cg_context):
def make_report_deprecate_as(cg_context):
assert isinstance(cg_context, CodeGenContext)
- name = cg_context.member_like.extended_attributes.value_of("DeprecateAs")
+ target = cg_context.member_like or cg_context.property_
+ name = target.extended_attributes.value_of("DeprecateAs")
if not name:
return None
@@ -712,16 +1131,16 @@ def make_report_deprecate_as(cg_context):
_1 = name
node = TextNode(_format(pattern, _1=_1))
node.accumulate(
- CodeGenAccumulator.require_include_headers([
- "third_party/blink/renderer/core/frame/deprecation.h",
- ]))
+ CodeGenAccumulator.require_include_headers(
+ ["third_party/blink/renderer/core/frame/deprecation.h"]))
return node
def make_report_measure_as(cg_context):
assert isinstance(cg_context, CodeGenContext)
- ext_attrs = cg_context.member_like.extended_attributes
+ target = cg_context.member_like or cg_context.property_
+ ext_attrs = target.extended_attributes
if not ("Measure" in ext_attrs or "MeasureAs" in ext_attrs):
assert "HighEntropy" not in ext_attrs, "{}: {}".format(
cg_context.idl_location_and_name,
@@ -736,9 +1155,11 @@ def make_report_measure_as(cg_context):
suffix = "_AttributeSetter"
elif cg_context.constructor:
suffix = "_Constructor"
+ elif cg_context.exposed_construct:
+ suffix = "_ConstructorGetter"
elif cg_context.operation:
suffix = "_Method"
- name = cg_context.member_like.extended_attributes.value_of("MeasureAs")
+ name = ext_attrs.value_of("MeasureAs") or ext_attrs.value_of("Measure")
if name:
name = "k{}".format(name)
elif cg_context.constructor:
@@ -746,7 +1167,7 @@ def make_report_measure_as(cg_context):
else:
name = "kV8{}_{}{}".format(
cg_context.class_like.identifier,
- name_style.raw.upper_camel_case(cg_context.member_like.identifier),
+ name_style.raw.upper_camel_case(cg_context.property_.identifier),
suffix)
node = SequenceNode()
@@ -770,9 +1191,8 @@ def make_report_measure_as(cg_context):
_1 = name
node.append(TextNode(_format(pattern, _1=_1)))
node.accumulate(
- CodeGenAccumulator.require_include_headers([
- "third_party/blink/renderer/core/frame/dactyloscoper.h",
- ]))
+ CodeGenAccumulator.require_include_headers(
+ ["third_party/blink/renderer/core/frame/dactyloscoper.h"]))
return node
@@ -786,13 +1206,13 @@ def make_return_value_cache_return_early(cg_context):
return TextNode("""\
// [CachedAttribute]
static const V8PrivateProperty::SymbolKey kPrivatePropertyCachedAttribute;
-auto v8_private_cached_attribute =
+auto&& v8_private_cached_attribute =
V8PrivateProperty::GetSymbol(${isolate}, kPrivatePropertyCachedAttribute);
-if (!impl->""" + pred + """()) {
+if (!${blink_receiver}->""" + pred + """()) {
v8::Local<v8::Value> v8_value;
if (v8_private_cached_attribute.GetOrUndefined(${v8_receiver})
.ToLocal(&v8_value) && !v8_value->IsUndefined()) {
- V8SetReturnValue(${info}, v8_value);
+ bindings::V8SetReturnValue(${info}, v8_value);
return;
}
}""")
@@ -801,13 +1221,13 @@ if (!impl->""" + pred + """()) {
return TextNode("""\
// [SaveSameObject]
static const V8PrivateProperty::SymbolKey kPrivatePropertySaveSameObject;
-auto v8_private_save_same_object =
+auto&& v8_private_save_same_object =
V8PrivateProperty::GetSymbol(${isolate}, kPrivatePropertySaveSameObject);
{
v8::Local<v8::Value> v8_value;
if (v8_private_save_same_object.GetOrUndefined(${v8_receiver})
.ToLocal(&v8_value) && !v8_value->IsUndefined()) {
- V8SetReturnValue(${info}, v8_value);
+ bindings::V8SetReturnValue(${info}, v8_value);
return;
}
}""")
@@ -827,63 +1247,266 @@ def make_return_value_cache_update_value(cg_context):
"(${v8_receiver}, ${info}.GetReturnValue().Get());")
-def make_runtime_call_timer_scope(cg_context):
+def make_runtime_call_timer_scope(cg_context, overriding_name=None):
assert isinstance(cg_context, CodeGenContext)
+ assert _is_none_or_str(overriding_name)
+
+ target = cg_context.member_like or cg_context.property_
- pattern = "RUNTIME_CALL_TIMER_SCOPE{_1}(${isolate}, {_2});"
- _1 = "_DISABLED_BY_DEFAULT"
suffix = ""
if cg_context.attribute_get:
suffix = "_Getter"
elif cg_context.attribute_set:
suffix = "_Setter"
- counter = cg_context.member_like.extended_attributes.value_of(
- "RuntimeCallStatsCounter")
+ elif cg_context.exposed_construct:
+ suffix = "_ConstructorGetterCallback"
+
+ counter = (target and
+ target.extended_attributes.value_of("RuntimeCallStatsCounter"))
if counter:
- _2 = "k{}{}".format(counter, suffix)
+ macro_name = "RUNTIME_CALL_TIMER_SCOPE"
+ counter_name = "RuntimeCallStats::CounterId::k{}{}".format(
+ counter, suffix)
else:
- _2 = "\"Blink_{}_{}{}\"".format(
- blink_class_name(cg_context.class_like),
- cg_context.member_like.identifier, suffix)
- node = TextNode(_format(pattern, _1=_1, _2=_2))
- node.accumulate(
+ macro_name = "RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT"
+ counter_name = "\"Blink_{}_{}{}\"".format(
+ blink_class_name(cg_context.class_like), overriding_name
+ or target.identifier, suffix)
+
+ return TextNode(
+ _format(
+ "{macro_name}(${info}.GetIsolate(), {counter_name});",
+ macro_name=macro_name,
+ counter_name=counter_name))
+
+
+def make_steps_of_ce_reactions(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+ assert (cg_context.attribute_set or cg_context.operation
+ or cg_context.indexed_property_setter
+ or cg_context.named_property_setter
+ or cg_context.named_property_deleter)
+
+ T = TextNode
+
+ nodes = []
+
+ ext_attrs = cg_context.member_like.extended_attributes
+ if "CustomElementCallbacks" in ext_attrs or "Reflect" in ext_attrs:
+ if "CustomElementCallbacks" in ext_attrs:
+ nodes.append(T("// [CustomElementCallbacks]"))
+ elif "Reflect" in ext_attrs:
+ nodes.append(T("// [Reflect]"))
+ nodes.append(
+ T("V0CustomElementProcessingStack::CallbackDeliveryScope "
+ "v0_custom_element_scope;"))
+
+ if "CEReactions" in ext_attrs:
+ nodes.append(T("// [CEReactions]"))
+ nodes.append(T("CEReactionsScope ce_reactions_scope;"))
+
+ if not nodes:
+ return None
+
+ nodes = SequenceNode(nodes)
+ nodes.accumulate(
CodeGenAccumulator.require_include_headers([
- "third_party/blink/renderer/platform/bindings/runtime_call_stats.h",
+ "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h",
+ "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
]))
- return node
+ return nodes
-def make_attribute_get_callback_def(cg_context, function_name):
+def make_steps_of_put_forwards(cg_context):
assert isinstance(cg_context, CodeGenContext)
- assert isinstance(function_name, str)
T = TextNode
- cg_context = cg_context.make_copy(attribute_get=True)
+ return SequenceNode([
+ T("// [PutForwards]"),
+ T("v8::Local<v8::Value> target;"),
+ T("if (!${v8_receiver}->Get(${current_context}, "
+ "V8AtomicString(${isolate}, ${property_name}))"
+ ".ToLocal(&target)) {\n"
+ " return;\n"
+ "}"),
+ CxxUnlikelyIfNode(
+ cond="!target->IsObject()",
+ body=[
+ T("${exception_state}.ThrowTypeError("
+ "\"The attribute value is not an object\");"),
+ T("return;"),
+ ]),
+ T("bool did_set;"),
+ T("if (!target.As<v8::Object>()->Set(${current_context}, "
+ "V8AtomicString(${isolate}, "
+ "\"${attribute.extended_attributes.value_of(\"PutForwards\")}\""
+ "), ${v8_property_value}).To(&did_set)) {{\n"
+ " return;\n"
+ "}}"),
+ ])
+
+
+def make_steps_of_replaceable(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+
+ return SequenceNode([
+ T("// [Replaceable]"),
+ T("bool did_create;"),
+ T("if (!${v8_receiver}->CreateDataProperty(${current_context}, "
+ "V8AtomicString(${isolate}, ${property_name}), "
+ "${v8_property_value}).To(&did_create)) {\n"
+ " return;\n"
+ "}"),
+ ])
+
+
+def make_v8_set_return_value(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+
+ if cg_context.does_override_idl_return_type:
+ return T("bindings::V8SetReturnValue(${info}, ${return_value});")
+
+ if not cg_context.return_type or cg_context.return_type.unwrap().is_void:
+ # Request a SymbolNode |return_value| to define itself without
+ # rendering any text.
+ return T("<% return_value.request_symbol_definition() %>")
+
+ operation = cg_context.operation
+ if operation and (operation.is_setter or operation.is_deleter):
+ # Blink implementation returns in a type different from the IDL type.
+ # Namely, IndexedPropertySetterResult, NamedPropertySetterResult, and
+ # NamedPropertyDeleterResult are returned ignoring the operation's
+ # return type.
+ return T("bindings::V8SetReturnValue(${info}, ${return_value});")
+
+ return_type = cg_context.return_type
+ if return_type.is_typedef:
+ if return_type.identifier in ("EventHandler",
+ "OnBeforeUnloadEventHandler",
+ "OnErrorEventHandler"):
+ return T("bindings::V8SetReturnValue(${info}, ${return_value}, "
+ "${isolate}, ${blink_receiver});")
+
+ return_type = return_type.unwrap(typedef=True)
+ return_type_body = return_type.unwrap()
+
+ V8_RETURN_VALUE_FAST_TYPES = ("boolean", "byte", "octet", "short",
+ "unsigned short", "long", "unsigned long")
+ if return_type.keyword_typename in V8_RETURN_VALUE_FAST_TYPES:
+ return T("bindings::V8SetReturnValue(${info}, ${return_value});")
+
+ if return_type_body.is_string:
+ args = ["${info}", "${return_value}", "${isolate}"]
+ if return_type.is_nullable:
+ args.append("bindings::V8ReturnValue::kNullable")
+ else:
+ args.append("bindings::V8ReturnValue::kNonNullable")
+ return T("bindings::V8SetReturnValue({});".format(", ".join(args)))
+
+ if return_type_body.is_interface:
+ args = ["${info}", "${return_value}"]
+ if cg_context.for_world == cg_context.MAIN_WORLD:
+ args.append("bindings::V8ReturnValue::kMainWorld")
+ elif cg_context.constructor or cg_context.member_like.is_static:
+ args.append("${creation_context}")
+ else:
+ args.append("${blink_receiver}")
+ return T("bindings::V8SetReturnValue({});".format(", ".join(args)))
+
+ if return_type.is_frozen_array:
+ return T("bindings::V8SetReturnValue(${info}, FreezeV8Object(ToV8("
+ "${return_value}, ${creation_context_object}, ${isolate}), "
+ "${isolate}));")
+
+ if return_type.is_promise:
+ return T("bindings::V8SetReturnValue"
+ "(${info}, ${return_value}.V8Value());")
- func_def = FunctionDefinitionNode(
- name=T(function_name),
- arg_decls=[T("const v8::FunctionCallbackInfo<v8::Value>& info")],
- return_type=T("void"))
+ return T("bindings::V8SetReturnValue(${info}, "
+ "ToV8(${return_value}, ${creation_context_object}, ${isolate}));")
+
+def _make_empty_callback_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ if cg_context.v8_callback_type == CodeGenContext.V8_FUNCTION_CALLBACK:
+ arg_decls = ["const v8::FunctionCallbackInfo<v8::Value>& info"]
+ arg_names = ["info"]
+ elif (cg_context.v8_callback_type == CodeGenContext.
+ V8_ACCESSOR_NAME_GETTER_CALLBACK):
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ arg_names = ["v8_property_name", "info"]
+ elif (cg_context.v8_callback_type == CodeGenContext.
+ V8_ACCESSOR_NAME_SETTER_CALLBACK):
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "v8::Local<v8::Value> v8_property_value",
+ "const v8::PropertyCallbackInfo<void>& info",
+ ]
+ arg_names = ["v8_property_name", "v8_property_value", "info"]
+ elif (cg_context.v8_callback_type == CodeGenContext.
+ V8_GENERIC_NAMED_PROPERTY_SETTER_CALLBACK):
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "v8::Local<v8::Value> v8_property_value",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ arg_names = ["v8_property_name", "v8_property_value", "info"]
+
+ func_def = CxxFuncDefNode(
+ name=function_name, arg_decls=arg_decls, return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
- body.add_template_var("info", "info")
- body.add_template_vars(cg_context.template_bindings())
- for bind in _callback_common_binders:
- bind(body, cg_context)
+ for arg_name in arg_names:
+ body.add_template_var(arg_name, arg_name)
+
+ bind_callback_local_vars(body, cg_context)
+ if cg_context.attribute or cg_context.function_like:
+ bind_blink_api_arguments(body, cg_context)
+ bind_return_value(body, cg_context)
+
+ return func_def
+
+
+def make_attribute_get_callback_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = _make_empty_callback_def(cg_context, function_name)
+ body = func_def.body
body.extend([
make_runtime_call_timer_scope(cg_context),
+ make_bindings_trace_event(cg_context),
make_report_deprecate_as(cg_context),
make_report_measure_as(cg_context),
make_log_activity(cg_context),
- T(""),
+ EmptyNode(),
+ ])
+
+ if "Getter" in cg_context.property_.extended_attributes.values_of(
+ "Custom"):
+ text = _format("${class_name}::{}(${info});",
+ custom_function_name(cg_context))
+ body.append(TextNode(text))
+ return func_def
+
+ body.extend([
make_check_receiver(cg_context),
make_return_value_cache_return_early(cg_context),
- T(""),
+ EmptyNode(),
make_check_security_of_return_value(cg_context),
- T("${v8_set_return_value}"),
+ make_v8_set_return_value(cg_context),
make_return_value_cache_update_value(cg_context),
])
@@ -894,59 +1517,263 @@ def make_attribute_set_callback_def(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
- return None
+ ext_attrs = cg_context.attribute.extended_attributes
+ if cg_context.attribute.is_readonly and not any(
+ ext_attr in ext_attrs
+ for ext_attr in ("LenientSetter", "PutForwards", "Replaceable")):
+ return None
+ func_def = _make_empty_callback_def(cg_context, function_name)
+ body = func_def.body
-def make_operation_function_def(cg_context, function_name):
+ if "LenientSetter" in ext_attrs:
+ body.append(TextNode("// [LenientSetter]"))
+ return func_def
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context),
+ make_bindings_trace_event(cg_context),
+ make_report_deprecate_as(cg_context),
+ make_report_measure_as(cg_context),
+ make_log_activity(cg_context),
+ EmptyNode(),
+ ])
+
+ if "Setter" in cg_context.property_.extended_attributes.values_of(
+ "Custom"):
+ text = _format("${class_name}::{}(${v8_property_value}, ${info});",
+ custom_function_name(cg_context))
+ body.append(TextNode(text))
+ return func_def
+
+ body.extend([
+ make_check_receiver(cg_context),
+ make_check_argument_length(cg_context),
+ EmptyNode(),
+ ])
+
+ if "PutForwards" in ext_attrs:
+ body.append(make_steps_of_put_forwards(cg_context))
+ return func_def
+
+ if "Replaceable" in ext_attrs:
+ body.append(make_steps_of_replaceable(cg_context))
+ return func_def
+
+ body.extend([
+ make_steps_of_ce_reactions(cg_context),
+ EmptyNode(),
+ make_v8_set_return_value(cg_context),
+ ])
+
+ return func_def
+
+
+def make_constant_callback_def(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
- T = TextNode
+ logging_nodes = SequenceNode([
+ make_report_deprecate_as(cg_context),
+ make_report_measure_as(cg_context),
+ make_log_activity(cg_context),
+ ])
+ if not logging_nodes:
+ return None
- func_def = FunctionDefinitionNode(
- name=T(function_name),
- arg_decls=[T("const v8::FunctionCallbackInfo<v8::Value>& info")],
- return_type=T("void"))
+ func_def = _make_empty_callback_def(cg_context, function_name)
+ body = func_def.body
+ v8_set_return_value = _format(
+ "bindings::V8SetReturnValue(${info}, ${class_name}::{});",
+ constant_name(cg_context))
+ body.extend([
+ make_runtime_call_timer_scope(cg_context),
+ make_bindings_trace_event(cg_context),
+ logging_nodes,
+ EmptyNode(),
+ TextNode(v8_set_return_value),
+ ])
+
+ return func_def
+
+
+def make_constant_constant_def(cg_context, constant_name):
+ # IDL constant's C++ constant definition
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(constant_name, str)
+
+ constant_type = blink_type_info(cg_context.constant.idl_type).value_t
+ return TextNode("static constexpr {type} {name} = {value};".format(
+ type=constant_type,
+ name=constant_name,
+ value=cg_context.constant.value.literal))
+
+
+def make_overload_dispatcher_function_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = _make_empty_callback_def(cg_context, function_name)
body = func_def.body
- body.add_template_var("info", "info")
- body.add_template_vars(cg_context.template_bindings())
- for bind in _callback_common_binders:
- bind(body, cg_context)
+ if cg_context.operation_group:
+ body.append(make_operation_entry(cg_context))
+ body.append(EmptyNode())
+ body.append(make_cooperative_scheduling_safepoint(cg_context))
+ body.append(EmptyNode())
- body.extend([
+ if cg_context.constructor_group:
+ body.append(make_constructor_entry(cg_context))
+ body.append(EmptyNode())
+
+ body.append(make_overload_dispatcher(cg_context))
+
+ return func_def
+
+
+def make_constructor_entry(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ return SequenceNode([
make_runtime_call_timer_scope(cg_context),
+ make_bindings_trace_event(cg_context),
+ EmptyNode(),
+ make_check_constructor_call(cg_context),
+ ])
+
+
+def make_constructor_function_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ T = TextNode
+
+ func_def = _make_empty_callback_def(cg_context, function_name)
+ body = func_def.body
+
+ if len(cg_context.constructor_group) == 1:
+ body.append(make_constructor_entry(cg_context))
+ body.append(EmptyNode())
+
+ body.extend([
make_report_deprecate_as(cg_context),
make_report_measure_as(cg_context),
make_log_activity(cg_context),
- T(""),
- make_check_receiver(cg_context),
- T(""),
- T("${v8_set_return_value}"),
+ EmptyNode(),
+ make_check_argument_length(cg_context),
+ EmptyNode(),
])
+ if "HTMLConstructor" in cg_context.constructor.extended_attributes:
+ body.append(T("// [HTMLConstructor]"))
+ text = _format(
+ "V8HTMLConstructor::HtmlConstructor("
+ "${info}, *${class_name}::GetWrapperTypeInfo(), "
+ "HTMLElementType::{});",
+ name_style.constant(cg_context.class_like.identifier))
+ body.append(T(text))
+ else:
+ body.append(
+ T("v8::Local<v8::Object> v8_wrapper = "
+ "${return_value}->AssociateWithWrapper(${isolate}, "
+ "${class_name}::GetWrapperTypeInfo(), ${v8_receiver});"))
+ body.append(T("bindings::V8SetReturnValue(${info}, v8_wrapper);"))
+
return func_def
-def make_overload_dispatcher_function_def(cg_context, function_name):
+def make_constructor_callback_def(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
- T = TextNode
+ constructor_group = cg_context.constructor_group
+
+ if len(constructor_group) == 1:
+ return make_constructor_function_def(
+ cg_context.make_copy(constructor=constructor_group[0]),
+ function_name)
+
+ node = SequenceNode()
+ for constructor in constructor_group:
+ cgc = cg_context.make_copy(constructor=constructor)
+ node.extend([
+ make_constructor_function_def(
+ cgc, callback_function_name(cgc, constructor.overload_index)),
+ EmptyNode(),
+ ])
+ node.append(
+ make_overload_dispatcher_function_def(cg_context, function_name))
+ return node
- func_def = FunctionDefinitionNode(
- name=T(function_name),
- arg_decls=[T("const v8::FunctionCallbackInfo<v8::Value>& info")],
- return_type=T("void"))
+def make_exposed_construct_callback_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = _make_empty_callback_def(cg_context, function_name)
body = func_def.body
- body.add_template_var("info", "info")
- body.add_template_vars(cg_context.template_bindings())
- bind_callback_local_vars(body, cg_context)
+ v8_set_return_value = _format(
+ "bindings::V8SetReturnValue"
+ "(${info}, {}::GetWrapperTypeInfo(), "
+ "bindings::V8ReturnValue::kInterfaceObject);",
+ v8_bridge_class_name(cg_context.exposed_construct))
+ body.extend([
+ make_runtime_call_timer_scope(cg_context),
+ make_bindings_trace_event(cg_context),
+ make_report_deprecate_as(cg_context),
+ make_report_measure_as(cg_context),
+ make_log_activity(cg_context),
+ EmptyNode(),
+ TextNode(v8_set_return_value),
+ ])
- body.append(make_overload_dispatcher(cg_context))
+ return func_def
+
+
+def make_operation_entry(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ return SequenceNode([
+ make_runtime_call_timer_scope(cg_context),
+ make_bindings_trace_event(cg_context),
+ ])
+
+
+def make_operation_function_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = _make_empty_callback_def(cg_context, function_name)
+ body = func_def.body
+
+ if not cg_context.operation_group or len(cg_context.operation_group) == 1:
+ body.append(make_operation_entry(cg_context))
+ body.append(EmptyNode())
+
+ body.extend([
+ make_report_deprecate_as(cg_context),
+ make_report_measure_as(cg_context),
+ make_log_activity(cg_context),
+ EmptyNode(),
+ ])
+
+ if "Custom" in cg_context.property_.extended_attributes:
+ text = _format("${class_name}::{}(${info});",
+ custom_function_name(cg_context))
+ body.append(TextNode(text))
+ return func_def
+
+ body.extend([
+ make_check_receiver(cg_context),
+ make_check_argument_length(cg_context),
+ EmptyNode(),
+ make_steps_of_ce_reactions(cg_context),
+ EmptyNode(),
+ make_check_security_of_return_value(cg_context),
+ make_v8_set_return_value(cg_context),
+ ])
return func_def
@@ -955,7 +1782,10 @@ def make_operation_callback_def(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
- operation_group = cg_context.constructor_group or cg_context.operation_group
+ operation_group = cg_context.operation_group
+
+ assert (not ("Custom" in operation_group.extended_attributes)
+ or len(operation_group) == 1)
if len(operation_group) == 1:
return make_operation_function_def(
@@ -963,16 +1793,938 @@ def make_operation_callback_def(cg_context, function_name):
node = SequenceNode()
for operation in operation_group:
- node.append(
+ cgc = cg_context.make_copy(operation=operation)
+ node.extend([
make_operation_function_def(
- cg_context.make_copy(operation=operation),
- _make_overloaded_function_name(operation)))
+ cgc, callback_function_name(cgc, operation.overload_index)),
+ EmptyNode(),
+ ])
node.append(
make_overload_dispatcher_function_def(cg_context, function_name))
return node
-def bind_template_installer_local_vars(code_node, cg_context):
+def make_indexed_property_getter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = [
+ "uint32_t index",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("index", "index")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+ bind_return_value(body, cg_context, overriding_args=["${index}"])
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context, "IndexedPropertyGetter"),
+ EmptyNode(),
+ make_v8_set_return_value(cg_context),
+ ])
+
+ return func_decl, func_def
+
+
+def make_indexed_property_setter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ if cg_context.indexed_property_setter is None:
+ return None, None
+
+ arg_decls = [
+ "uint32_t index",
+ "v8::Local<v8::Value> v8_value",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("index", "index")
+ body.add_template_var("v8_value", "v8_value")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+ bind_return_value(
+ body, cg_context, overriding_args=["${index}", "${blink_value}"])
+ body.register_code_symbol(
+ make_v8_to_blink_value(
+ "blink_value",
+ "${v8_value}",
+ cg_context.indexed_property_setter.arguments[1].idl_type,
+ argument_index=2))
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context, "IndexedPropertySetter"),
+ EmptyNode(),
+ make_steps_of_ce_reactions(cg_context),
+ EmptyNode(),
+ make_v8_set_return_value(cg_context),
+ ])
+
+ return func_decl, func_def
+
+
+def make_indexed_property_definer_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = [
+ "uint32_t index",
+ "const v8::PropertyDescriptor& desc",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("index", "index")
+ body.add_template_var("desc", "desc")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ body.append(
+ TextNode("""\
+// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
+// 3.8.3. [[DefineOwnProperty]]
+// step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then
+// return false.
+if (desc.has_get() || desc.has_set()) {
+ bindings::V8SetReturnValue(${info}, nullptr);
+ if (${info}.ShouldThrowOnError()) {
+ ExceptionState exception_state(${info}.GetIsolate(),
+ ExceptionState::kIndexedSetterContext,
+ "${interface.identifier}");
+ exception_state.ThrowTypeError("Accessor properties are not allowed.");
+ }
+ return;
+}
+"""))
+
+ writable = bool(
+ cg_context.interface.indexed_and_named_properties.indexed_setter)
+ if writable:
+ body.append(
+ TextNode("""\
+// step 1.3. Invoke the indexed property setter with P and Desc.[[Value]].
+//
+// Return nothing and fall back to
+// ${class_name}::IndexedPropertySetterCallback."""))
+ else:
+ body.append(
+ TextNode("""\
+// step 1.2. If O does not implement an interface with an indexed property
+// setter, then return false.
+bindings::V8SetReturnValue(${info}, nullptr);
+if (${info}.ShouldThrowOnError()) {
+ ExceptionState exception_state(${info}.GetIsolate(),
+ ExceptionState::kIndexedSetterContext,
+ "${interface.identifier}");
+ exception_state.ThrowTypeError("Index property setter is not supported.");
+ return;
+}"""))
+
+ return func_decl, func_def
+
+
+def make_indexed_property_descriptor_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = [
+ "uint32_t index",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("index", "index")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ pattern = """\
+// https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+// Steps 1.1. to 1.2. are covered here: we rely on
+// IndexedPropertyGetterCallback() to call the getter function and check
+// that |index| is a valid property index, in which case it will have set
+// info.GetReturnValue() to something other than undefined.
+${class_name}::IndexedPropertyGetterCallback(${index}, ${info});
+v8::Local<v8::Value> v8_value = ${info}.GetReturnValue().Get();
+if (v8_value->IsUndefined())
+ return;
+
+// 1.2.5. Let |desc| be a newly created Property Descriptor with no fields.
+// 1.2.6. Set desc.[[Value]] to the result of converting value to an
+// ECMAScript value.
+// 1.2.7. If O implements an interface with an indexed property setter,
+// then set desc.[[Writable]] to true, otherwise set it to false.
+v8::PropertyDescriptor desc(v8_value, /*writable=*/{cxx_writable});
+// 1.2.8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
+desc.set_enumerable(true);
+desc.set_configurable(true);
+// 1.2.9. Return |desc|.
+bindings::V8SetReturnValue(${info}, desc);"""
+ writable = bool(
+ cg_context.interface.indexed_and_named_properties.indexed_setter)
+ cxx_writable = "true" if writable else "false"
+ body.append(TextNode(_format(pattern, cxx_writable=cxx_writable)))
+
+ return func_decl, func_def
+
+
+def make_indexed_property_enumerator_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = ["const v8::PropertyCallbackInfo<v8::Array>& info"]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ body.append(
+ TextNode("""\
+uint32_t length = ${blink_receiver}->length();
+v8::Local<v8::Array> array =
+ bindings::EnumerateIndexedProperties(${isolate}, length);
+bindings::V8SetReturnValue(${info}, array);"""))
+
+ return func_decl, func_def
+
+
+def make_named_property_getter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+ bind_return_value(
+ body, cg_context, overriding_args=["${blink_property_name}"])
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context, "NamedPropertyGetter"),
+ EmptyNode(),
+ ])
+
+ if "Custom" in cg_context.named_property_getter.extended_attributes:
+ text = _format("${class_name}::{}(${blink_property_name}, ${info});",
+ custom_function_name(cg_context))
+ body.append(TextNode(text))
+ else:
+ body.append(make_v8_set_return_value(cg_context))
+
+ return func_decl, func_def
+
+
+def make_named_property_setter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ if cg_context.named_property_setter is None:
+ return None, None
+
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "v8::Local<v8::Value> v8_property_value",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("v8_property_value", "v8_property_value")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+ bind_return_value(
+ body,
+ cg_context,
+ overriding_args=["${blink_property_name}", "${blink_value}"])
+ body.register_code_symbol(
+ make_v8_to_blink_value(
+ "blink_value",
+ "${v8_property_value}",
+ cg_context.named_property_setter.arguments[1].idl_type,
+ argument_index=2))
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context, "NamedPropertySetter"),
+ EmptyNode(),
+ ])
+
+ if "Custom" in cg_context.named_property_setter.extended_attributes:
+ text = _format(
+ "${class_name}::{}"
+ "(${blink_property_name}, ${v8_property_value}, ${info});",
+ custom_function_name(cg_context))
+ body.append(TextNode(text))
+ else:
+ body.extend([
+ make_steps_of_ce_reactions(cg_context),
+ EmptyNode(),
+ make_v8_set_return_value(cg_context),
+ ])
+
+ return func_decl, func_def
+
+
+def make_named_property_deleter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ if cg_context.named_property_deleter is None:
+ return None, None
+
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyCallbackInfo<v8::Boolean>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+ bind_return_value(
+ body, cg_context, overriding_args=["${blink_property_name}"])
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context),
+ EmptyNode(),
+ ])
+
+ if "Custom" in cg_context.named_property_deleter.extended_attributes:
+ text = _format("${class_name}::{}(${blink_property_name}, ${info});",
+ custom_function_name(cg_context))
+ body.append(TextNode(text))
+ else:
+ body.extend([
+ make_steps_of_ce_reactions(cg_context),
+ EmptyNode(),
+ make_v8_set_return_value(cg_context),
+ ])
+
+ return func_decl, func_def
+
+
+def make_named_property_definer_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyDescriptor& desc",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("desc", "desc")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ body.append(
+ TextNode("""\
+// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
+// 3.8.3. [[DefineOwnProperty]]
+// step 2.2.2.1. If the result of calling IsDataDescriptor(Desc) is false,
+// then return false.
+if (desc.has_get() || desc.has_set()) {
+ bindings::V8SetReturnValue(${info}, nullptr);
+ if (${info}.ShouldThrowOnError()) {
+ ExceptionState exception_state(${info}.GetIsolate(),
+ ExceptionState::kSetterContext,
+ "${interface.identifier}");
+ exception_state.ThrowTypeError("Accessor properties are not allowed.");
+ }
+ return;
+}
+"""))
+
+ writable = bool(
+ cg_context.interface.indexed_and_named_properties.named_setter)
+ if writable:
+ body.append(
+ TextNode("""\
+// step 2.2.2. Invoke the named property setter with P and Desc.[[Value]].
+//
+// Return nothing and fall back to
+// ${class_name}::NamedPropertySetterCallback."""))
+ else:
+ body.append(
+ TextNode("""\
+// step 2.2.1. If creating is false and O does not implement an interface
+// with a named property setter, then return false.
+bindings::V8SetReturnValue(${info}, nullptr);
+if (${info}.ShouldThrowOnError()) {
+ ExceptionState exception_state(${info}.GetIsolate(),
+ ExceptionState::kSetterContext,
+ "${interface.identifier}");
+ exception_state.ThrowTypeError("Named property setter is not supported.");
+ return;
+}"""))
+
+ return func_decl, func_def
+
+
+def make_named_property_descriptor_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ arg_decls = [
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ pattern = """\
+// https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
+// Steps 2.1. is covered here: we rely on
+// NamedPropertyGetterCallback() to call the getter function and check
+// that |v8_property_name| is a valid property name, in which case it will
+// have set info.GetReturnValue() to something other than undefined.
+${class_name}::NamedPropertyGetterCallback(${v8_property_name}, ${info});
+v8::Local<v8::Value> v8_value = ${info}.GetReturnValue().Get();
+if (v8_value->IsUndefined())
+ return;
+
+// 2.1.5. Let |desc| be a newly created Property Descriptor with no fields.
+// 2.1.6. Set desc.[[Value]] to the result of converting value to an
+// ECMAScript value.
+// 2.1.7. If O implements an interface with a named property setter, then
+// set desc.[[Writable]] to true, otherwise set it to false.
+v8::PropertyDescriptor desc(v8_value, /*writable=*/{cxx_writable});
+// 2.1.8. If O implements an interface with the
+// [LegacyUnenumerableNamedProperties] extended attribute, then set
+// desc.[[Enumerable]] to false, otherwise set it to true.
+desc.set_enumerable({cxx_enumerable});
+// 2.1.9. Set desc.[[Configurable]] to true.
+desc.set_configurable(true);
+// 1.2.9. Return |desc|.
+bindings::V8SetReturnValue(${info}, desc);"""
+ props = cg_context.interface.indexed_and_named_properties
+ writable = bool(props.named_setter)
+ cxx_writable = "true" if writable else "false"
+ enumerable = props.is_named_property_enumerable
+ cxx_enumerable = "true" if enumerable else "false"
+ body.append(
+ TextNode(
+ _format(
+ pattern,
+ cxx_writable=cxx_writable,
+ cxx_enumerable=cxx_enumerable)))
+
+ return func_decl, func_def
+
+
+def make_named_property_enumerator_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ if not (cg_context.interface.indexed_and_named_properties.
+ is_named_property_enumerable):
+ return None, None
+
+ arg_decls = ["const v8::PropertyCallbackInfo<v8::Array>& info"]
+ return_type = "void"
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ class_name=cg_context.class_name)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ body.append(
+ TextNode("""\
+Vector<String> blink_property_names;
+${blink_receiver}->NamedPropertyEnumerator(
+ blink_property_names, ${exception_state});
+if (${exception_state}.HadException())
+ return;
+bindings::V8SetReturnValue(
+ ${info},
+ ToV8(blink_property_names, ${creation_context_object}, ${isolate}));
+"""))
+
+ return func_decl, func_def
+
+
+def make_stringifier_callback_def(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ if cg_context.stringifier.attribute:
+ return make_attribute_get_callback_def(
+ cg_context.make_copy(
+ attribute=cg_context.stringifier.attribute,
+ attribute_get=True), function_name)
+ elif cg_context.stringifier.operation:
+ return make_operation_function_def(
+ cg_context.make_copy(operation=cg_context.stringifier.operation),
+ function_name)
+ assert False
+
+
+# ----------------------------------------------------------------------------
+# Callback functions of cross origin properties
+# ----------------------------------------------------------------------------
+
+
+def make_cross_origin_access_check_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=[
+ "v8::Local<v8::Context> accessing_context",
+ "v8::Local<v8::Object> accessed_object",
+ "v8::Local<v8::Value> unused_data",
+ ],
+ return_type="bool")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("accessing_context", "accessing_context")
+ body.add_template_var("accessed_object", "accessed_object")
+ bind_callback_local_vars(body, cg_context)
+
+ if cg_context.interface.identifier == "Window":
+ blink_class = "DOMWindow"
+ else:
+ blink_class = blink_class_name(cg_context.interface)
+ body.extend([
+ TextNode(
+ _format(
+ "{blink_class}* blink_accessed_object = "
+ "${class_name}::ToWrappableUnsafe(${accessed_object});",
+ blink_class=blink_class)),
+ TextNode("return BindingSecurity::ShouldAllowAccessTo("
+ "ToLocalDOMWindow(${accessing_context}), "
+ "blink_accessed_object, "
+ "BindingSecurity::ErrorReportOption::kDoNotReport);"),
+ ])
+
+ return func_def
+
+
+def make_cross_origin_property_getter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=[
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ string_case_body = []
+ string_case_body.append(
+ TextNode("""\
+for (const auto& attribute : kCrossOriginAttributeTable) {
+ if (${blink_property_name} != attribute.name)
+ continue;
+ if (UNLIKELY(!attribute.get_value)) {
+ BindingSecurity::FailedAccessCheckFor(
+ ${info}.GetIsolate(),
+ ${class_name}::GetWrapperTypeInfo(),
+ ${info}.This());
+ return;
+ }
+ return attribute.get_value(${v8_property_name}, ${info});
+}
+for (const auto& operation : kCrossOriginOperationTable) {
+ if (${blink_property_name} != operation.name)
+ continue;
+ v8::Local<v8::Function> function;
+ if (bindings::GetCrossOriginFunction(
+ ${info}.GetIsolate(), operation.callback, operation.func_length,
+ ${class_name}::GetWrapperTypeInfo())
+ .ToLocal(&function)) {
+ bindings::V8SetReturnValue(${info}, function);
+ }
+ return;
+}
+% if interface.identifier == "Window":
+
+// Window object's document-tree child browsing context name property set
+//
+// TODO(yukishiino): Update the following hard-coded call to an appropriate
+// one.
+V8Window::NamedPropertyGetterCustom(${blink_property_name}, ${info});
+if (!${info}.GetReturnValue().Get()->IsUndefined())
+ return;
+% endif"""))
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context, "CrossOriginPropertyGetter"),
+ EmptyNode(),
+ CxxLikelyIfNode(
+ cond="${v8_property_name}->IsString()", body=string_case_body),
+ EmptyNode(),
+ TextNode("""\
+// 7.2.3.2 CrossOriginPropertyFallback ( P )
+// https://html.spec.whatwg.org/C/#crossoriginpropertyfallback-(-p-)
+if (bindings::IsSupportedInCrossOriginPropertyFallback(
+ ${info}.GetIsolate(), ${v8_property_name})) {
+ return ${info}.GetReturnValue().SetUndefined();
+}
+BindingSecurity::FailedAccessCheckFor(
+ ${info}.GetIsolate(),
+ ${class_name}::GetWrapperTypeInfo(),
+ ${info}.This());"""),
+ ])
+
+ return func_def
+
+
+def make_cross_origin_property_setter_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=[
+ "v8::Local<v8::Name> v8_property_name",
+ "v8::Local<v8::Value> v8_property_value",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("v8_property_value", "v8_property_value")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ string_case_body = []
+ string_case_body.append(
+ TextNode("""\
+for (const auto& attribute : kCrossOriginAttributeTable) {
+ if (${blink_property_name} == attribute.name && attribute.set_value) {
+ return attribute.set_value(
+ ${v8_property_name}, ${v8_property_value}, ${info});
+ }
+}"""))
+
+ body.extend([
+ make_runtime_call_timer_scope(cg_context, "CrossOriginPropertySetter"),
+ EmptyNode(),
+ CxxLikelyIfNode(
+ cond="${v8_property_name}->IsString()", body=string_case_body),
+ EmptyNode(),
+ TextNode("""\
+BindingSecurity::FailedAccessCheckFor(
+ ${info}.GetIsolate(),
+ ${class_name}::GetWrapperTypeInfo(),
+ ${info}.This());"""),
+ ])
+
+ return func_def
+
+
+def make_cross_origin_property_descriptor_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=[
+ "v8::Local<v8::Name> v8_property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>& info",
+ ],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("v8_property_name", "v8_property_name")
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ string_case_body = []
+ string_case_body.append(
+ TextNode("""\
+// 7.2.3.4 CrossOriginGetOwnPropertyHelper ( O, P )
+// https://html.spec.whatwg.org/C/#crossorigingetownpropertyhelper-(-o,-p-)
+for (const auto& attribute : kCrossOriginAttributeTable) {
+ if (${blink_property_name} != attribute.name)
+ continue;
+ v8::Local<v8::Value> get;
+ v8::Local<v8::Value> set;
+ if (!bindings::GetCrossOriginFunctionOrUndefined(
+ ${info}.GetIsolate(), attribute.get_callback, 0,
+ ${class_name}::GetWrapperTypeInfo())
+ .ToLocal(&get) ||
+ !bindings::GetCrossOriginFunctionOrUndefined(
+ ${info}.GetIsolate(), attribute.set_callback, 1,
+ ${class_name}::GetWrapperTypeInfo())
+ .ToLocal(&set)) {
+ return;
+ }
+ v8::PropertyDescriptor desc(get, set);
+ desc.set_enumerable(false);
+ desc.set_configurable(true);
+ return;
+}
+for (const auto& operation : kCrossOriginOperationTable) {
+ if (${blink_property_name} != operation.name)
+ continue;
+ v8::Local<v8::Function> function;
+ if (!bindings::GetCrossOriginFunction(
+ ${info}.GetIsolate(), operation.callback, operation.func_length,
+ ${class_name}::GetWrapperTypeInfo())
+ .ToLocal(&function)) {
+ return;
+ }
+ v8::PropertyDescriptor desc(function, /*writable=*/false);
+ desc.set_enumerable(false);
+ desc.set_configurable(true);
+ bindings::V8SetReturnValue(${info}, desc);
+ return;
+}
+% if interface.identifier == "Window":
+
+// Window object's document-tree child browsing context name property set
+//
+// TODO(yukishiino): Update the following hard-coded call to an appropriate
+// one.
+V8Window::NamedPropertyGetterCustom(${blink_property_name}, ${info});
+if (!${info}.GetReturnValue().Get()->IsUndefined()) {
+ v8::PropertyDescriptor desc(${info}.GetReturnValue().Get(),
+ /*writable=*/false);
+ desc.set_enumerable(false);
+ desc.set_configurable(true);
+ bindings::V8SetReturnValue(${info}, desc);
+ return;
+}
+% endif"""))
+
+ body.extend([
+ CxxLikelyIfNode(
+ cond="${v8_property_name}->IsString()", body=string_case_body),
+ EmptyNode(),
+ TextNode("""\
+// 7.2.3.2 CrossOriginPropertyFallback ( P )
+// https://html.spec.whatwg.org/C/#crossoriginpropertyfallback-(-p-)
+if (bindings::IsSupportedInCrossOriginPropertyFallback(
+ ${info}.GetIsolate(), ${v8_property_name})) {
+ v8::PropertyDescriptor desc(v8::Undefined(${info}.GetIsolate()),
+ /*writable=*/false);
+ desc.set_enumerable(false);
+ desc.set_configurable(true);
+ bindings::V8SetReturnValue(${info}, desc);
+ return;
+}
+BindingSecurity::FailedAccessCheckFor(
+ ${info}.GetIsolate(),
+ ${class_name}::GetWrapperTypeInfo(),
+ ${info}.This());"""),
+ ])
+
+ return func_def
+
+
+def make_cross_origin_property_enumerator_callback(cg_context, function_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=["const v8::PropertyCallbackInfo<v8::Array>& info"],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ body = func_def.body
+ body.add_template_var("info", "info")
+ bind_callback_local_vars(body, cg_context)
+
+ body.append(
+ TextNode("""\
+bindings::V8SetReturnValue(
+ ${info},
+ bindings::EnumerateCrossOriginProperties(
+ ${isolate},
+ kCrossOriginAttributeTable,
+ kCrossOriginOperationTable));"""))
+
+ return func_def
+
+
+# ----------------------------------------------------------------------------
+# Installer functions
+# ----------------------------------------------------------------------------
+
+# FN = function name
+FN_INSTALL_INTERFACE_TEMPLATE = name_style.func("InstallInterfaceTemplate")
+FN_INSTALL_UNCONDITIONAL_PROPS = name_style.func(
+ "InstallUnconditionalProperties")
+FN_INSTALL_CONTEXT_INDEPENDENT_PROPS = name_style.func(
+ "InstallContextIndependentProperties")
+FN_INSTALL_CONTEXT_DEPENDENT_PROPS = name_style.func(
+ "InstallContextDependentProperties")
+
+# TP = trampoline name
+TP_INSTALL_INTERFACE_TEMPLATE = name_style.member_var(
+ "install_interface_template_func")
+TP_INSTALL_UNCONDITIONAL_PROPS = name_style.member_var(
+ "install_unconditional_props_func")
+TP_INSTALL_CONTEXT_INDEPENDENT_PROPS = name_style.member_var(
+ "install_context_independent_props_func")
+TP_INSTALL_CONTEXT_DEPENDENT_PROPS = name_style.member_var(
+ "install_context_dependent_props_func")
+
+
+def bind_installer_local_vars(code_node, cg_context):
assert isinstance(code_node, SymbolScopeNode)
assert isinstance(cg_context, CodeGenContext)
@@ -984,17 +2736,36 @@ def bind_template_installer_local_vars(code_node, cg_context):
S("instance_template",
("v8::Local<v8::ObjectTemplate> ${instance_template} = "
"${interface_template}->InstanceTemplate();")),
+ S("interface_template",
+ ("v8::Local<v8::FunctionTemplate> ${interface_template} = "
+ "${wrapper_type_info}->DomTemplate(${isolate}, ${world});")),
+ S("is_in_secure_context",
+ ("const bool ${is_in_secure_context} = "
+ "${execution_context}->IsSecureContext();")),
+ S("isolate", "v8::Isolate* ${isolate} = ${v8_context}->GetIsolate();"),
S("prototype_template",
("v8::Local<v8::ObjectTemplate> ${prototype_template} = "
"${interface_template}->PrototypeTemplate();")),
+ S("script_state",
+ "ScriptState* ${script_state} = ScriptState::From(${v8_context});"),
S("signature",
("v8::Local<v8::Signature> ${signature} = "
"v8::Signature::New(${isolate}, ${interface_template});")),
S("wrapper_type_info",
("const WrapperTypeInfo* const ${wrapper_type_info} = "
- "${v8_class}::GetWrapperTypeInfo();")),
+ "${class_name}::GetWrapperTypeInfo();")),
])
+ # execution_context
+ node = S("execution_context", ("ExecutionContext* ${execution_context} = "
+ "ExecutionContext::From(${script_state});"))
+ node.accumulate(
+ CodeGenAccumulator.require_include_headers([
+ "third_party/blink/renderer/core/execution_context/execution_context.h"
+ ]))
+ local_vars.append(node)
+
+ # parent_interface_template
pattern = (
"v8::Local<v8::FunctionTemplate> ${parent_interface_template}{_1};")
_1 = (" = ${wrapper_type_info}->parent_class->dom_template_function"
@@ -1003,105 +2774,2093 @@ def bind_template_installer_local_vars(code_node, cg_context):
_1 = ""
local_vars.append(S("parent_interface_template", _format(pattern, _1=_1)))
- code_node.register_code_symbols(local_vars)
+ # Arguments have priority over local vars.
+ template_vars = code_node.template_vars
+ for symbol_node in local_vars:
+ if symbol_node.name not in template_vars:
+ code_node.register_code_symbol(symbol_node)
+
+
+def _make_property_entry_v8_property_attribute(property_):
+ values = []
+ if "NotEnumerable" in property_.extended_attributes:
+ values.append("v8::DontEnum")
+ if "Unforgeable" in property_.extended_attributes:
+ values.append("v8::DontDelete")
+ if not values:
+ values.append("v8::None")
+ return "static_cast<v8::PropertyAttribute>({})".format(" | ".join(values))
+
+
+def _make_property_entry_on_which_object(property_):
+ ON_INSTANCE = "V8DOMConfiguration::kOnInstance"
+ ON_PROTOTYPE = "V8DOMConfiguration::kOnPrototype"
+ ON_INTERFACE = "V8DOMConfiguration::kOnInterface"
+ if isinstance(property_, web_idl.Constant):
+ return ON_INTERFACE
+ if hasattr(property_, "is_static") and property_.is_static:
+ return ON_INTERFACE
+ if "Global" in property_.owner.extended_attributes:
+ return ON_INSTANCE
+ if "Unforgeable" in property_.extended_attributes:
+ return ON_INSTANCE
+ return ON_PROTOTYPE
+
+
+def _make_property_entry_check_receiver(property_):
+ if ("LenientThis" in property_.extended_attributes
+ or (isinstance(property_, web_idl.Attribute)
+ and property_.idl_type.unwrap().is_promise)
+ or (isinstance(property_, web_idl.OverloadGroup)
+ and property_[0].return_type.unwrap().is_promise)):
+ return "V8DOMConfiguration::kDoNotCheckHolder"
+ else:
+ return "V8DOMConfiguration::kCheckHolder"
-def make_install_interface_template_def(cg_context):
- assert isinstance(cg_context, CodeGenContext)
+def _make_property_entry_has_side_effect(property_):
+ if property_.extended_attributes.value_of("Affects") == "Nothing":
+ return "V8DOMConfiguration::kHasNoSideEffect"
+ else:
+ return "V8DOMConfiguration::kHasSideEffect"
+
+
+def _make_property_entry_world(world):
+ if world == CodeGenContext.MAIN_WORLD:
+ return "V8DOMConfiguration::kMainWorld"
+ if world == CodeGenContext.NON_MAIN_WORLDS:
+ return "V8DOMConfiguration::kNonMainWorlds"
+ if world == CodeGenContext.ALL_WORLDS:
+ return "V8DOMConfiguration::kAllWorlds"
+ assert False
+
+
+def _make_property_entry_constant_type_and_value_format(property_):
+ idl_type = property_.idl_type.unwrap()
+ if (idl_type.keyword_typename == "long long"
+ or idl_type.keyword_typename == "unsigned long long"):
+ assert False, "64-bit constants are not yet supported."
+ if idl_type.keyword_typename == "unsigned long":
+ return ("V8DOMConfiguration::kConstantTypeUnsignedLong",
+ "static_cast<int>({value})")
+ if idl_type.is_integer:
+ return ("V8DOMConfiguration::kConstantTypeLong",
+ "static_cast<int>({value})")
+ if idl_type.is_floating_point_numeric:
+ return ("V8DOMConfiguration::kConstantTypeDouble",
+ "static_cast<double>({value})")
+ assert False, "Unsupported type: {}".format(idl_type.syntactic_form)
+
+
+def _make_attribute_registration_table(table_name, attribute_entries):
+ assert isinstance(table_name, str)
+ assert isinstance(attribute_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryAttribute) for entry in attribute_entries)
T = TextNode
- func_def = FunctionDefinitionNode(
- name=T("InstallInterfaceTemplate"),
- arg_decls=[
- T("v8::Isolate* isolate"),
- T("const DOMWrapperWorld& world"),
- T("v8::Local<v8::FunctionTemplate> interface_template"),
- ],
- return_type=T("void"))
+ entry_nodes = []
+ for entry in attribute_entries:
+ pattern = ("{{"
+ "\"{property_name}\", "
+ "{attribute_get_callback}, "
+ "{attribute_set_callback}, "
+ "V8PrivateProperty::kNoCachedAccessor, "
+ "{v8_property_attribute}, "
+ "{on_which_object}, "
+ "{check_receiver}, "
+ "{has_side_effect}, "
+ "V8DOMConfiguration::kAlwaysCallGetter, "
+ "{world}"
+ "}},")
+ text = _format(
+ pattern,
+ property_name=entry.property_.identifier,
+ attribute_get_callback=entry.attr_get_callback_name,
+ attribute_set_callback=(entry.attr_set_callback_name or "nullptr"),
+ v8_property_attribute=_make_property_entry_v8_property_attribute(
+ entry.property_),
+ on_which_object=_make_property_entry_on_which_object(
+ entry.property_),
+ check_receiver=_make_property_entry_check_receiver(
+ entry.property_),
+ has_side_effect=_make_property_entry_has_side_effect(
+ entry.property_),
+ world=_make_property_entry_world(entry.world))
+ entry_nodes.append(T(text))
+
+ return ListNode([
+ T("static constexpr V8DOMConfiguration::AccessorConfiguration " +
+ table_name + "[] = {"),
+ ListNode(entry_nodes),
+ T("};"),
+ ])
- body = func_def.body
- body.add_template_var("isolate", "isolate")
- body.add_template_var("world", "world")
- body.add_template_var("interface_template", "interface_template")
- body.add_template_vars(cg_context.template_bindings())
- binders = [
- bind_template_installer_local_vars,
+def _make_constant_callback_registration_table(table_name, constant_entries):
+ assert isinstance(table_name, str)
+ assert isinstance(constant_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryConstant)
+ and isinstance(entry.const_callback_name, str)
+ for entry in constant_entries)
+
+ T = TextNode
+
+ entry_nodes = []
+ for entry in constant_entries:
+ pattern = ("{{" "\"{property_name}\", " "{constant_callback}" "}},")
+ text = _format(
+ pattern,
+ property_name=entry.property_.identifier,
+ constant_callback=entry.const_callback_name)
+ entry_nodes.append(T(text))
+
+ return ListNode([
+ T("static constexpr V8DOMConfiguration::ConstantCallbackConfiguration "
+ + table_name + "[] = {"),
+ ListNode(entry_nodes),
+ T("};"),
+ ])
+
+
+def _make_constant_value_registration_table(table_name, constant_entries):
+ assert isinstance(table_name, str)
+ assert isinstance(constant_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryConstant)
+ and entry.const_callback_name is None for entry in constant_entries)
+
+ T = TextNode
+
+ entry_nodes = []
+ for entry in constant_entries:
+ pattern = ("{{"
+ "\"{property_name}\", "
+ "{constant_type}, "
+ "{constant_value}"
+ "}},")
+ constant_type, constant_value_fmt = (
+ _make_property_entry_constant_type_and_value_format(
+ entry.property_))
+ constant_value = _format(
+ constant_value_fmt, value=entry.const_constant_name)
+ text = _format(
+ pattern,
+ property_name=entry.property_.identifier,
+ constant_type=constant_type,
+ constant_value=constant_value)
+ entry_nodes.append(T(text))
+
+ return ListNode([
+ T("static constexpr V8DOMConfiguration::ConstantConfiguration " +
+ table_name + "[] = {"),
+ ListNode(entry_nodes),
+ T("};"),
+ ])
+
+
+def _make_exposed_construct_registration_table(table_name,
+ exposed_construct_entries):
+ assert isinstance(table_name, str)
+ assert isinstance(exposed_construct_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryExposedConstruct)
+ for entry in exposed_construct_entries)
+
+ T = TextNode
+
+ entry_nodes = []
+ for entry in exposed_construct_entries:
+ pattern = ("{{"
+ "\"{property_name}\", "
+ "{exposed_construct_callback}, "
+ "nullptr, "
+ "static_cast<v8::PropertyAttribute>(v8::DontEnum), "
+ "V8DOMConfiguration::kOnInstance, "
+ "V8DOMConfiguration::kDoNotCheckHolder, "
+ "V8DOMConfiguration::kHasNoSideEffect, "
+ "V8DOMConfiguration::kAlwaysCallGetter, "
+ "{world}"
+ "}}, ")
+ text = _format(
+ pattern,
+ property_name=entry.property_.identifier,
+ exposed_construct_callback=entry.prop_callback_name,
+ world=_make_property_entry_world(entry.world))
+ entry_nodes.append(T(text))
+
+ return ListNode([
+ T("static constexpr V8DOMConfiguration::AttributeConfiguration " +
+ table_name + "[] = {"),
+ ListNode(entry_nodes),
+ T("};"),
+ ])
+
+
+def _make_operation_registration_table(table_name, operation_entries):
+ assert isinstance(table_name, str)
+ assert isinstance(operation_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryOperationGroup)
+ for entry in operation_entries)
+
+ T = TextNode
+
+ entry_nodes = []
+ for entry in operation_entries:
+ pattern = ("{{"
+ "\"{property_name}\", "
+ "{operation_callback}, "
+ "{function_length}, "
+ "{v8_property_attribute}, "
+ "{on_which_object}, "
+ "{check_receiver}, "
+ "V8DOMConfiguration::kDoNotCheckAccess, "
+ "{has_side_effect}, "
+ "{world}"
+ "}}, ")
+ text = _format(
+ pattern,
+ property_name=entry.property_.identifier,
+ operation_callback=entry.op_callback_name,
+ function_length=entry.op_func_length,
+ v8_property_attribute=_make_property_entry_v8_property_attribute(
+ entry.property_),
+ on_which_object=_make_property_entry_on_which_object(
+ entry.property_),
+ check_receiver=_make_property_entry_check_receiver(
+ entry.property_),
+ has_side_effect=_make_property_entry_has_side_effect(
+ entry.property_),
+ world=_make_property_entry_world(entry.world))
+ entry_nodes.append(T(text))
+
+ return ListNode([
+ T("static constexpr V8DOMConfiguration::MethodConfiguration " +
+ table_name + "[] = {"),
+ ListNode(entry_nodes),
+ T("};"),
+ ])
+
+
+class _PropEntryBase(object):
+ def __init__(self, is_context_dependent, exposure_conditional, world,
+ property_):
+ assert isinstance(is_context_dependent, bool)
+ assert isinstance(exposure_conditional, CodeGenExpr)
+
+ self.is_context_dependent = is_context_dependent
+ self.exposure_conditional = exposure_conditional
+ self.world = world
+ self.property_ = property_
+
+
+class _PropEntryAttribute(_PropEntryBase):
+ def __init__(self, is_context_dependent, exposure_conditional, world,
+ attribute, attr_get_callback_name, attr_set_callback_name):
+ assert isinstance(attr_get_callback_name, str)
+ assert _is_none_or_str(attr_set_callback_name)
+
+ _PropEntryBase.__init__(self, is_context_dependent,
+ exposure_conditional, world, attribute)
+ self.attr_get_callback_name = attr_get_callback_name
+ self.attr_set_callback_name = attr_set_callback_name
+
+
+class _PropEntryConstant(_PropEntryBase):
+ def __init__(self, is_context_dependent, exposure_conditional, world,
+ constant, const_callback_name, const_constant_name):
+ assert _is_none_or_str(const_callback_name)
+ assert isinstance(const_constant_name, str)
+
+ _PropEntryBase.__init__(self, is_context_dependent,
+ exposure_conditional, world, constant)
+ self.const_callback_name = const_callback_name
+ self.const_constant_name = const_constant_name
+
+
+class _PropEntryConstructorGroup(_PropEntryBase):
+ def __init__(self, is_context_dependent, exposure_conditional, world,
+ constructor_group, ctor_callback_name, ctor_func_length):
+ assert isinstance(ctor_callback_name, str)
+ assert isinstance(ctor_func_length, (int, long))
+
+ _PropEntryBase.__init__(self, is_context_dependent,
+ exposure_conditional, world, constructor_group)
+ self.ctor_callback_name = ctor_callback_name
+ self.ctor_func_length = ctor_func_length
+
+
+class _PropEntryExposedConstruct(_PropEntryBase):
+ def __init__(self, is_context_dependent, exposure_conditional, world,
+ exposed_construct, prop_callback_name):
+ assert isinstance(prop_callback_name, str)
+
+ _PropEntryBase.__init__(self, is_context_dependent,
+ exposure_conditional, world, exposed_construct)
+ self.prop_callback_name = prop_callback_name
+
+
+class _PropEntryOperationGroup(_PropEntryBase):
+ def __init__(self, is_context_dependent, exposure_conditional, world,
+ operation_group, op_callback_name, op_func_length):
+ assert isinstance(op_callback_name, str)
+ assert isinstance(op_func_length, (int, long))
+
+ _PropEntryBase.__init__(self, is_context_dependent,
+ exposure_conditional, world, operation_group)
+ self.op_callback_name = op_callback_name
+ self.op_func_length = op_func_length
+
+
+def _make_property_entries_and_callback_defs(
+ cg_context, attribute_entries, constant_entries, constructor_entries,
+ exposed_construct_entries, operation_entries):
+ """
+ Creates intermediate objects to help property installation and also makes
+ code nodes of callback functions.
+
+ Args:
+ attribute_entries:
+ constructor_entries:
+ exposed_construct_entries:
+ operation_entries:
+ Output parameters to store the intermediate objects.
+ """
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(attribute_entries, list)
+ assert isinstance(constant_entries, list)
+ assert isinstance(constructor_entries, list)
+ assert isinstance(exposed_construct_entries, list)
+ assert isinstance(operation_entries, list)
+
+ interface = cg_context.interface
+ global_names = interface.extended_attributes.values_of("Global")
+
+ callback_def_nodes = ListNode()
+
+ def iterate(members, callback):
+ for member in members:
+ is_context_dependent = member.exposure.is_context_dependent(
+ global_names)
+ exposure_conditional = expr_from_exposure(member.exposure,
+ global_names)
+
+ if "PerWorldBindings" in member.extended_attributes:
+ worlds = (CodeGenContext.MAIN_WORLD,
+ CodeGenContext.NON_MAIN_WORLDS)
+ else:
+ worlds = (CodeGenContext.ALL_WORLDS, )
+
+ for world in worlds:
+ callback(member, is_context_dependent, exposure_conditional,
+ world)
+
+ def process_attribute(attribute, is_context_dependent,
+ exposure_conditional, world):
+ cgc_attr = cg_context.make_copy(attribute=attribute, for_world=world)
+ cgc = cgc_attr.make_copy(attribute_get=True)
+ attr_get_callback_name = callback_function_name(cgc)
+ attr_get_callback_node = make_attribute_get_callback_def(
+ cgc, attr_get_callback_name)
+ cgc = cgc_attr.make_copy(attribute_set=True)
+ attr_set_callback_name = callback_function_name(cgc)
+ attr_set_callback_node = make_attribute_set_callback_def(
+ cgc, attr_set_callback_name)
+ if attr_set_callback_node is None:
+ attr_set_callback_name = None
+
+ callback_def_nodes.extend([
+ attr_get_callback_node,
+ EmptyNode(),
+ attr_set_callback_node,
+ EmptyNode(),
+ ])
+
+ attribute_entries.append(
+ _PropEntryAttribute(
+ is_context_dependent=is_context_dependent,
+ exposure_conditional=exposure_conditional,
+ world=world,
+ attribute=attribute,
+ attr_get_callback_name=attr_get_callback_name,
+ attr_set_callback_name=attr_set_callback_name))
+
+ def process_constant(constant, is_context_dependent, exposure_conditional,
+ world):
+ cgc = cg_context.make_copy(
+ constant=constant,
+ for_world=world,
+ v8_callback_type=CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK)
+ const_callback_name = callback_function_name(cgc)
+ const_callback_node = make_constant_callback_def(
+ cgc, const_callback_name)
+ if const_callback_node is None:
+ const_callback_name = None
+ # IDL constant's C++ constant name
+ const_constant_name = _format("${class_name}::{}", constant_name(cgc))
+
+ callback_def_nodes.extend([
+ const_callback_node,
+ EmptyNode(),
+ ])
+
+ constant_entries.append(
+ _PropEntryConstant(
+ is_context_dependent=is_context_dependent,
+ exposure_conditional=exposure_conditional,
+ world=world,
+ constant=constant,
+ const_callback_name=const_callback_name,
+ const_constant_name=const_constant_name))
+
+ def process_constructor_group(constructor_group, is_context_dependent,
+ exposure_conditional, world):
+ cgc = cg_context.make_copy(
+ constructor_group=constructor_group, for_world=world)
+ ctor_callback_name = callback_function_name(cgc)
+ ctor_callback_node = make_constructor_callback_def(
+ cgc, ctor_callback_name)
+
+ callback_def_nodes.extend([
+ ctor_callback_node,
+ EmptyNode(),
+ ])
+
+ constructor_entries.append(
+ _PropEntryConstructorGroup(
+ is_context_dependent=is_context_dependent,
+ exposure_conditional=exposure_conditional,
+ world=world,
+ constructor_group=constructor_group,
+ ctor_callback_name=ctor_callback_name,
+ ctor_func_length=(
+ constructor_group.min_num_of_required_arguments)))
+
+ def process_exposed_construct(exposed_construct, is_context_dependent,
+ exposure_conditional, world):
+ if isinstance(exposed_construct, web_idl.LegacyWindowAlias):
+ cgc = cg_context.make_copy(
+ exposed_construct=exposed_construct.original,
+ legacy_window_alias=exposed_construct,
+ for_world=world,
+ v8_callback_type=CodeGenContext.
+ V8_ACCESSOR_NAME_GETTER_CALLBACK)
+ else:
+ cgc = cg_context.make_copy(
+ exposed_construct=exposed_construct,
+ for_world=world,
+ v8_callback_type=CodeGenContext.
+ V8_ACCESSOR_NAME_GETTER_CALLBACK)
+ prop_callback_name = callback_function_name(cgc)
+ prop_callback_node = make_exposed_construct_callback_def(
+ cgc, prop_callback_name)
+
+ callback_def_nodes.extend([
+ prop_callback_node,
+ EmptyNode(),
+ ])
+
+ exposed_construct_entries.append(
+ _PropEntryExposedConstruct(
+ is_context_dependent=is_context_dependent,
+ exposure_conditional=exposure_conditional,
+ world=world,
+ exposed_construct=exposed_construct,
+ prop_callback_name=prop_callback_name))
+
+ def process_operation_group(operation_group, is_context_dependent,
+ exposure_conditional, world):
+ cgc = cg_context.make_copy(
+ operation_group=operation_group, for_world=world)
+ op_callback_name = callback_function_name(cgc)
+ op_callback_node = make_operation_callback_def(cgc, op_callback_name)
+
+ callback_def_nodes.extend([
+ op_callback_node,
+ EmptyNode(),
+ ])
+
+ operation_entries.append(
+ _PropEntryOperationGroup(
+ is_context_dependent=is_context_dependent,
+ exposure_conditional=exposure_conditional,
+ world=world,
+ operation_group=operation_group,
+ op_callback_name=op_callback_name,
+ op_func_length=operation_group.min_num_of_required_arguments))
+
+ def process_stringifier(_, is_context_dependent, exposure_conditional,
+ world):
+ cgc = cg_context.make_copy(
+ stringifier=interface.stringifier, for_world=world)
+ op_callback_name = callback_function_name(cgc)
+ op_callback_node = make_stringifier_callback_def(cgc, op_callback_name)
+
+ callback_def_nodes.extend([
+ op_callback_node,
+ EmptyNode(),
+ ])
+
+ operation_entries.append(
+ _PropEntryOperationGroup(
+ is_context_dependent=is_context_dependent,
+ exposure_conditional=exposure_conditional,
+ world=world,
+ operation_group=cgc.property_,
+ op_callback_name=op_callback_name,
+ op_func_length=0))
+
+ iterate(interface.attributes, process_attribute)
+ iterate(interface.constants, process_constant)
+ iterate(interface.constructor_groups, process_constructor_group)
+ iterate(interface.exposed_constructs, process_exposed_construct)
+ iterate(interface.legacy_window_aliases, process_exposed_construct)
+ iterate(interface.operation_groups, process_operation_group)
+ if interface.stringifier:
+ iterate([interface.stringifier.operation], process_stringifier)
+
+ return callback_def_nodes
+
+
+def make_install_interface_template(
+ cg_context, function_name, class_name, trampoline_var_name,
+ constructor_entries, indexed_and_named_property_install_nodes,
+ cross_origin_property_install_nodes, install_unconditional_func_name,
+ install_context_independent_func_name):
+ """
+ Returns:
+ A triplet of CodeNode of:
+ - function declaration
+ - function definition
+ - trampoline function definition (from the API class to the
+ implementation class), which is supposed to be defined inline
+ """
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+ assert _is_none_or_str(class_name)
+ assert _is_none_or_str(trampoline_var_name)
+ assert isinstance(constructor_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryConstructorGroup)
+ for entry in constructor_entries)
+ assert isinstance(indexed_and_named_property_install_nodes, SequenceNode)
+ assert isinstance(cross_origin_property_install_nodes, SequenceNode)
+ assert _is_none_or_str(install_unconditional_func_name)
+ assert _is_none_or_str(install_context_independent_func_name)
+
+ T = TextNode
+
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "const DOMWrapperWorld& world",
+ "v8::Local<v8::FunctionTemplate> interface_template",
]
- for bind in binders:
- bind(body, cg_context)
+ return_type = "void"
+
+ if trampoline_var_name is None:
+ trampoline_def = None
+ else:
+ trampoline_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+ trampoline_def.body.append(
+ TextNode(
+ _format("return {}(isolate, world, interface_template);",
+ trampoline_var_name)))
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ class_name=class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+
+ body = func_def.body
+ body.add_template_vars({
+ "isolate": "isolate",
+ "world": "world",
+ "interface_template": "interface_template",
+ })
+ bind_installer_local_vars(body, cg_context)
body.extend([
T("V8DOMConfiguration::InitializeDOMInterfaceTemplate("
"${isolate}, ${interface_template}, "
"${wrapper_type_info}->interface_name, ${parent_interface_template}, "
"kV8DefaultWrapperInternalFieldCount);"),
+ EmptyNode(),
])
- if cg_context.class_like.constructor_groups:
+ for entry in constructor_entries:
+ set_callback = _format("${interface_template}->SetCallHandler({});",
+ entry.ctor_callback_name)
+ set_length = _format("${interface_template}->SetLength({});",
+ entry.ctor_func_length)
+ if entry.world == CodeGenContext.MAIN_WORLD:
+ body.append(
+ CxxLikelyIfNode(
+ cond="${world}.IsMainWorld()",
+ body=[T(set_callback), T(set_length)]))
+ elif entry.world == CodeGenContext.NON_MAIN_WORLDS:
+ body.append(
+ CxxLikelyIfNode(
+ cond="!${world}.IsMainWorld()",
+ body=[T(set_callback), T(set_length)]))
+ elif entry.world == CodeGenContext.ALL_WORLDS:
+ body.extend([T(set_callback), T(set_length)])
+ else:
+ assert False
+ body.append(EmptyNode())
+
+ if cross_origin_property_install_nodes:
body.extend([
- T("${interface_template}->SetCallHandler(ConstructorCallback);"),
- T("${interface_template}->SetLength("
- "${class_like.constructor_groups[0]"
- ".min_num_of_required_arguments});"),
+ cross_origin_property_install_nodes,
+ EmptyNode(),
])
- return func_def
+ if cg_context.class_like.identifier == "Location":
+ body.append(
+ T("""\
+// https://html.spec.whatwg.org/C/#the-location-interface
+// To create a Location object, run these steps:
+// step 3. Let valueOf be location's relevant
+// Realm.[[Intrinsics]].[[%ObjProto_valueOf%]].
+// step 3. Perform ! location.[[DefineOwnProperty]]("valueOf",
+// { [[Value]]: valueOf, [[Writable]]: false, [[Enumerable]]: false,
+// [[Configurable]]: false }).
+${instance_template}->SetIntrinsicDataProperty(
+ V8AtomicString(${isolate}, "valueOf"),
+ v8::kObjProto_valueOf,
+ static_cast<v8::PropertyAttribute>(
+ int(v8::ReadOnly) | int(v8::DontEnum) | int(v8::DontDelete)));
+// step 4. Perform ! location.[[DefineOwnProperty]](@@toPrimitive,
+// { [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false,
+// [[Configurable]]: false }).
+${instance_template}->Set(
+ v8::Symbol::GetToPrimitive(${isolate}),
+ v8::Undefined(${isolate}),
+ static_cast<v8::PropertyAttribute>(
+ int(v8::ReadOnly) | int(v8::DontEnum) | int(v8::DontDelete)));
+"""))
+
+ if indexed_and_named_property_install_nodes:
+ body.extend([
+ indexed_and_named_property_install_nodes,
+ EmptyNode(),
+ ])
+ if ("Global" in cg_context.class_like.extended_attributes
+ or cg_context.class_like.identifier == "Location"):
+ if "Global" in cg_context.class_like.extended_attributes:
+ body.append(T("// [Global]"))
+ if cg_context.class_like.identifier == "Location":
+ body.append(T("// Location exotic object"))
+ body.extend([
+ T("${instance_template}->SetImmutableProto();"),
+ T("${prototype_template}->SetImmutableProto();"),
+ EmptyNode(),
+ ])
+
+ if cg_context.class_like.identifier == "HTMLAllCollection":
+ body.extend([
+ T("// HTMLAllCollection"),
+ T("// https://html.spec.whatwg.org/C/"
+ "#the-htmlallcollection-interface"),
+ T("${instance_template}->SetCallAsFunctionHandler"
+ "(${class_name}::LegacyCallCustom);"),
+ T("${instance_template}->MarkAsUndetectable();"),
+ EmptyNode(),
+ ])
+
+ func_call_pattern = ("{}(${isolate}, ${world}, ${instance_template}, "
+ "${prototype_template}, ${interface_template});")
+ if install_unconditional_func_name:
+ func_call = _format(func_call_pattern, install_unconditional_func_name)
+ body.append(T(func_call))
+ if install_context_independent_func_name:
+ func_call = _format(func_call_pattern,
+ install_context_independent_func_name)
+ body.append(T(func_call))
-def generate_interfaces(web_idl_database, output_dirs):
- filename = "v8_example_interface.cc"
- filepath = os.path.join(output_dirs['core'], filename)
+ return func_decl, func_def, trampoline_def
- interface = web_idl_database.find("TestNamespace")
- cg_context = CodeGenContext(interface=interface)
+def make_install_properties(cg_context, function_name, class_name,
+ trampoline_var_name, is_context_dependent,
+ attribute_entries, constant_entries,
+ exposed_construct_entries, operation_entries):
+ """
+ Returns:
+ A triplet of CodeNode of:
+ - function declaration
+ - function definition
+ - trampoline function definition (from the API class to the
+ implementation class), which is supposed to be defined inline
+ """
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+ assert _is_none_or_str(class_name)
+ assert _is_none_or_str(trampoline_var_name)
+ assert isinstance(is_context_dependent, bool)
+ assert isinstance(attribute_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryAttribute) for entry in attribute_entries)
+ assert isinstance(constant_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryConstant) for entry in constant_entries)
+ assert isinstance(exposed_construct_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryExposedConstruct)
+ for entry in exposed_construct_entries)
+ assert isinstance(operation_entries, (list, tuple))
+ assert all(
+ isinstance(entry, _PropEntryOperationGroup)
+ for entry in operation_entries)
+
+ if not (attribute_entries or constant_entries or exposed_construct_entries
+ or operation_entries):
+ return None, None, None
+
+ if is_context_dependent:
+ arg_decls = [
+ "v8::Local<v8::Context> context",
+ "const DOMWrapperWorld& world",
+ "v8::Local<v8::Object> instance_object",
+ "v8::Local<v8::Object> prototype_object",
+ "v8::Local<v8::Function> interface_object",
+ ]
+ else:
+ arg_decls = [
+ "v8::Isolate* isolate",
+ "const DOMWrapperWorld& world",
+ "v8::Local<v8::ObjectTemplate> instance_template",
+ "v8::Local<v8::ObjectTemplate> prototype_template",
+ "v8::Local<v8::FunctionTemplate> interface_template",
+ ]
+ return_type = "void"
+
+ if trampoline_var_name is None:
+ trampoline_def = None
+ else:
+ trampoline_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+ if is_context_dependent:
+ args = [
+ "context",
+ "world",
+ "instance_object",
+ "prototype_object",
+ "interface_object",
+ ]
+ else:
+ args = [
+ "isolate",
+ "world",
+ "instance_template",
+ "prototype_template",
+ "interface_template",
+ ]
+ text = _format(
+ "return {func}({args});",
+ func=trampoline_var_name,
+ args=", ".join(args))
+ trampoline_def.body.append(TextNode(text))
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name,
+ arg_decls=arg_decls,
+ return_type=return_type,
+ static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ class_name=class_name,
+ arg_decls=arg_decls,
+ return_type=return_type)
+ func_def.set_base_template_vars(cg_context.template_bindings())
- root_node = SymbolScopeNode(separator_last="\n")
- root_node.set_accumulator(CodeGenAccumulator())
- root_node.set_renderer(MakoRenderer())
+ body = func_def.body
+ if is_context_dependent:
+ body.add_template_vars({
+ "v8_context": "context", # 'context' is reserved by Mako.
+ "world": "world",
+ "instance_object": "instance_object",
+ "prototype_object": "prototype_object",
+ "interface_object": "interface_object",
+ })
+ else:
+ body.add_template_vars({
+ "isolate": "isolate",
+ "world": "world",
+ "instance_template": "instance_template",
+ "prototype_template": "prototype_template",
+ "interface_template": "interface_template",
+ })
+ bind_installer_local_vars(body, cg_context)
+
+ def group_by_condition(entries):
+ unconditional_entries = []
+ conditional_to_entries = {}
+ for entry in entries:
+ assert entry.is_context_dependent == is_context_dependent
+ if entry.exposure_conditional.is_always_true:
+ unconditional_entries.append(entry)
+ else:
+ conditional_to_entries.setdefault(entry.exposure_conditional,
+ []).append(entry)
+ return unconditional_entries, conditional_to_entries
+
+ def install_properties(table_name, target_entries, make_table_func,
+ installer_call_text):
+ unconditional_entries, conditional_to_entries = group_by_condition(
+ target_entries)
+ if unconditional_entries:
+ body.append(
+ CxxBlockNode([
+ make_table_func(table_name, unconditional_entries),
+ TextNode(installer_call_text),
+ ]))
+ body.append(EmptyNode())
+ for conditional, entries in conditional_to_entries.items():
+ body.append(
+ CxxUnlikelyIfNode(
+ cond=conditional,
+ body=[
+ make_table_func(table_name, entries),
+ TextNode(installer_call_text),
+ ]))
+ body.append(EmptyNode())
+
+ table_name = "kAttributeTable"
+ if is_context_dependent:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallAccessors(${isolate}, ${world}, "
+ "${instance_object}, ${prototype_object}, ${interface_object}, "
+ "${signature}, kAttributeTable, base::size(kAttributeTable));")
+ else:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallAccessors(${isolate}, ${world}, "
+ "${instance_template}, ${prototype_template}, "
+ "${interface_template}, ${signature}, "
+ "kAttributeTable, base::size(kAttributeTable));")
+ install_properties(table_name, attribute_entries,
+ _make_attribute_registration_table, installer_call_text)
+
+ table_name = "kConstantCallbackTable"
+ if is_context_dependent:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallConstants(${isolate}, "
+ "${interface_object}, ${prototype_object}, "
+ "kConstantCallbackTable, base::size(kConstantCallbackTable));")
+ else:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallConstants(${isolate}, "
+ "${interface_template}, ${prototype_template}, "
+ "kConstantCallbackTable, base::size(kConstantCallbackTable));")
+ constant_callback_entries = filter(lambda entry: entry.const_callback_name,
+ constant_entries)
+ install_properties(table_name, constant_callback_entries,
+ _make_constant_callback_registration_table,
+ installer_call_text)
+
+ table_name = "kConstantValueTable"
+ if is_context_dependent:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallConstants(${isolate}, "
+ "${interface_object}, ${prototype_object}, "
+ "kConstantValueTable, base::size(kConstantValueTable));")
+ else:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallConstants(${isolate}, "
+ "${interface_template}, ${prototype_template}, "
+ "kConstantValueTable, base::size(kConstantValueTable));")
+ constant_value_entries = filter(
+ lambda entry: not entry.const_callback_name, constant_entries)
+ install_properties(table_name, constant_value_entries,
+ _make_constant_value_registration_table,
+ installer_call_text)
+
+ table_name = "kExposedConstructTable"
+ if is_context_dependent:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallAttributes(${isolate}, ${world}, "
+ "${instance_object}, ${prototype_object}, "
+ "kExposedConstructTable, base::size(kExposedConstructTable));")
+ else:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallAttributes(${isolate}, ${world}, "
+ "${instance_template}, ${prototype_template}, "
+ "kExposedConstructTable, base::size(kExposedConstructTable));")
+ install_properties(table_name, exposed_construct_entries,
+ _make_exposed_construct_registration_table,
+ installer_call_text)
+
+ table_name = "kOperationTable"
+ if is_context_dependent:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallMethods(${isolate}, ${world}, "
+ "${instance_object}, ${prototype_object}, ${interface_object}, "
+ "${signature}, kOperationTable, base::size(kOperationTable));")
+ else:
+ installer_call_text = (
+ "V8DOMConfiguration::InstallMethods(${isolate}, ${world}, "
+ "${instance_template}, ${prototype_template}, "
+ "${interface_template}, ${signature}, "
+ "kOperationTable, base::size(kOperationTable));")
+ install_properties(table_name, operation_entries,
+ _make_operation_registration_table, installer_call_text)
- root_node.accumulator.add_include_headers(
- collect_include_headers(interface))
+ return func_decl, func_def, trampoline_def
- code_node = SequenceNode()
- for attribute in interface.attributes:
- func_name = name_style.func(attribute.identifier,
- "AttributeGetCallback")
- code_node.append(
- make_attribute_get_callback_def(
- cg_context.make_copy(attribute=attribute), func_name))
- func_name = name_style.func(attribute.identifier,
- "AttributeSetCallback")
- code_node.append(
- make_attribute_set_callback_def(
- cg_context.make_copy(attribute=attribute), func_name))
-
- for constructor_group in interface.constructor_groups:
- func_name = name_style.func("ConstructorCallback")
- code_node.append(
- make_operation_callback_def(
- cg_context.make_copy(constructor_group=constructor_group),
- func_name))
+def make_indexed_and_named_property_callbacks_and_install_nodes(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+ func_decls = ListNode()
+ func_defs = ListNode()
+ install_nodes = SequenceNode()
+
+ interface = cg_context.interface
+ if not (interface and interface.indexed_and_named_properties):
+ return func_decls, func_defs, install_nodes
+ props = interface.indexed_and_named_properties
+
+ def add_callback(func_decl, func_def):
+ func_decls.append(func_decl)
+ if func_def:
+ func_defs.append(func_def)
+ func_defs.append(EmptyNode())
+
+ def most_derived_interface(*interfaces):
+ key = lambda interface: len(interface.inclusive_inherited_interfaces)
+ return sorted(filter(None, interfaces), key=key)[-1]
+
+ cg_context = cg_context.make_copy(
+ v8_callback_type=CodeGenContext.V8_OTHER_CALLBACK)
+
+ if props.own_indexed_getter or props.own_indexed_setter:
+ add_callback(*make_indexed_property_getter_callback(
+ cg_context.make_copy(indexed_property_getter=props.indexed_getter),
+ "IndexedPropertyGetterCallback"))
+ add_callback(*make_indexed_property_setter_callback(
+ cg_context.make_copy(indexed_property_setter=props.indexed_setter),
+ "IndexedPropertySetterCallback"))
+ add_callback(*make_indexed_property_definer_callback(
+ cg_context, "IndexedPropertyDefinerCallback"))
+ add_callback(*make_indexed_property_descriptor_callback(
+ cg_context, "IndexedPropertyDescriptorCallback"))
+ add_callback(*make_indexed_property_enumerator_callback(
+ cg_context, "IndexedPropertyEnumeratorCallback"))
+
+ if props.has_indexed_properties:
+ impl_bridge = v8_bridge_class_name(
+ most_derived_interface(
+ props.indexed_getter.owner,
+ props.indexed_setter and props.indexed_setter.owner,
+ ))
+ flags = []
+ if (props.indexed_getter.extended_attributes.value_of("Affects") ==
+ "Nothing"):
+ flags.append("v8::PropertyHandlerFlags::kHasNoSideEffect")
+ else:
+ flags.append("v8::PropertyHandlerFlags::kNone")
+ property_handler_flags = flags[0]
+ pattern = """\
+// Indexed properties
+${instance_template}->SetHandler(
+ v8::IndexedPropertyHandlerConfiguration(
+ {impl_bridge}::IndexedPropertyGetterCallback,
+% if interface.indexed_and_named_properties.indexed_setter:
+ {impl_bridge}::IndexedPropertySetterCallback,
+% else:
+ nullptr, // setter
+% endif
+ {impl_bridge}::IndexedPropertyDescriptorCallback,
+ nullptr, // deleter
+ {impl_bridge}::IndexedPropertyEnumeratorCallback,
+ {impl_bridge}::IndexedPropertyDefinerCallback,
+ v8::Local<v8::Value>(),
+ {property_handler_flags}));"""
+ install_nodes.append(
+ TextNode(
+ _format(
+ pattern,
+ impl_bridge=impl_bridge,
+ property_handler_flags=property_handler_flags)))
+
+ if (props.own_named_getter or props.own_named_setter
+ or props.own_named_deleter):
+ add_callback(*make_named_property_getter_callback(
+ cg_context.make_copy(named_property_getter=props.named_getter),
+ "NamedPropertyGetterCallback"))
+ add_callback(*make_named_property_setter_callback(
+ cg_context.make_copy(named_property_setter=props.named_setter),
+ "NamedPropertySetterCallback"))
+ add_callback(*make_named_property_deleter_callback(
+ cg_context.make_copy(named_property_deleter=props.named_deleter),
+ "NamedPropertyDeleterCallback"))
+ add_callback(*make_named_property_definer_callback(
+ cg_context, "NamedPropertyDefinerCallback"))
+ add_callback(*make_named_property_descriptor_callback(
+ cg_context, "NamedPropertyDescriptorCallback"))
+ add_callback(*make_named_property_enumerator_callback(
+ cg_context, "NamedPropertyEnumeratorCallback"))
+
+ if props.has_named_properties:
+ impl_bridge = v8_bridge_class_name(
+ most_derived_interface(
+ props.named_getter.owner,
+ props.named_setter and props.named_setter.owner,
+ props.named_deleter and props.named_deleter.owner,
+ ))
+ flags = ["v8::PropertyHandlerFlags::kOnlyInterceptStrings"]
+ if "OverrideBuiltins" not in interface.extended_attributes:
+ flags.append("v8::PropertyHandlerFlags::kNonMasking")
+ if (props.named_getter.extended_attributes.value_of("Affects") ==
+ "Nothing"):
+ flags.append("v8::PropertyHandlerFlags::kHasNoSideEffect")
+ property_handler_flags = (
+ "static_cast<v8::PropertyHandlerFlags>({})".format(" | ".join(
+ map(lambda flag: "int({})".format(flag), flags))))
+ pattern = """\
+// Named properties
+${instance_template}->SetHandler(
+ v8::NamedPropertyHandlerConfiguration(
+ {impl_bridge}::NamedPropertyGetterCallback,
+% if interface.indexed_and_named_properties.named_setter:
+ {impl_bridge}::NamedPropertySetterCallback,
+% else:
+ nullptr, // setter
+% endif
+ {impl_bridge}::NamedPropertyDescriptorCallback,
+% if interface.indexed_and_named_properties.named_deleter:
+ {impl_bridge}::NamedPropertyDeleterCallback,
+% else:
+ nullptr, // deleter
+% endif
+% if interface.indexed_and_named_properties.is_named_property_enumerable:
+ {impl_bridge}::NamedPropertyEnumeratorCallback,
+% else:
+ nullptr, // enumerator
+% endif
+ {impl_bridge}::NamedPropertyDefinerCallback,
+ v8::Local<v8::Value>(),
+ {property_handler_flags}));"""
+ install_nodes.append(
+ TextNode(
+ _format(
+ pattern,
+ impl_bridge=impl_bridge,
+ property_handler_flags=property_handler_flags)))
+
+ return func_decls, func_defs, install_nodes
+
+
+def make_cross_origin_property_callbacks_and_install_nodes(
+ cg_context, attribute_entries, operation_entries):
+ assert isinstance(cg_context, CodeGenContext)
+
+ callback_defs = []
+ install_nodes = SequenceNode()
+
+ CROSS_ORIGIN_INTERFACES = ("Window", "Location")
+ if cg_context.interface.identifier not in CROSS_ORIGIN_INTERFACES:
+ return callback_defs, install_nodes
+
+ entry_nodes = []
+ for entry in attribute_entries:
+ attribute = entry.property_
+ if "CrossOrigin" not in attribute.extended_attributes:
+ continue
+ assert entry.world == CodeGenContext.ALL_WORLDS
+ values = attribute.extended_attributes.values_of("CrossOrigin")
+ get_func = "nullptr"
+ set_func = "nullptr"
+ get_value = "nullptr"
+ set_value = "nullptr"
+ if not values or "Getter" in values:
+ get_func = entry.attr_get_callback_name
+ cgc = cg_context.make_copy(
+ attribute=attribute,
+ attribute_get=True,
+ v8_callback_type=(
+ CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK))
+ get_value = callback_function_name(cgc, for_cross_origin=True)
+ func_def = make_attribute_get_callback_def(cgc, get_value)
+ callback_defs.extend([func_def, EmptyNode()])
+ if (not values or "Setter" in values) and entry.attr_set_callback_name:
+ set_func = entry.attr_set_callback_name
+ cgc = cg_context.make_copy(
+ attribute=attribute,
+ attribute_set=True,
+ v8_callback_type=(
+ CodeGenContext.V8_GENERIC_NAMED_PROPERTY_SETTER_CALLBACK))
+ set_value = callback_function_name(cgc, for_cross_origin=True)
+ func_def = make_attribute_set_callback_def(cgc, set_value)
+ callback_defs.extend([func_def, EmptyNode()])
+ pattern = ("{{\"{property_name}\", "
+ "{get_func}, {set_func}, {get_value}, {set_value}}},")
+ entry_nodes.append(
+ TextNode(
+ _format(
+ pattern,
+ property_name=attribute.identifier,
+ get_func=get_func,
+ set_func=set_func,
+ get_value=get_value,
+ set_value=set_value)))
+ callback_defs.append(
+ ListNode([
+ TextNode("constexpr bindings::CrossOriginAttributeTableEntry "
+ "kCrossOriginAttributeTable[] = {"),
+ ListNode(entry_nodes),
+ TextNode("};"),
+ EmptyNode(),
+ ]))
+
+ entry_nodes = []
+ for entry in operation_entries:
+ operation_group = entry.property_
+ if "CrossOrigin" not in operation_group.extended_attributes:
+ continue
+ assert entry.world == CodeGenContext.ALL_WORLDS
+ entry_nodes.append(
+ TextNode(
+ _format(
+ "{{\"{property_name}\", {op_callback}, {op_func_length}}},",
+ property_name=operation_group.identifier,
+ op_callback=entry.op_callback_name,
+ op_func_length=entry.op_func_length)))
+ callback_defs.append(
+ ListNode([
+ TextNode("constexpr bindings::CrossOriginOperationTableEntry "
+ "kCrossOriginOperationTable[] = {"),
+ ListNode(entry_nodes),
+ TextNode("};"),
+ EmptyNode(),
+ ]))
+
+ cg_context = cg_context.make_copy(
+ v8_callback_type=CodeGenContext.V8_OTHER_CALLBACK)
+
+ callback_defs.extend([
+ make_cross_origin_access_check_callback(
+ cg_context, "CrossOriginAccessCheckCallback"),
+ EmptyNode(),
+ make_cross_origin_property_getter_callback(
+ cg_context, "CrossOriginPropertyGetterCallback"),
+ EmptyNode(),
+ make_cross_origin_property_setter_callback(
+ cg_context, "CrossOriginPropertySetterCallback"),
+ EmptyNode(),
+ make_cross_origin_property_descriptor_callback(
+ cg_context, "CrossOriginPropertyDescriptorCallback"),
+ EmptyNode(),
+ make_cross_origin_property_enumerator_callback(
+ cg_context, "CrossOriginPropertyEnumeratorCallback"),
+ ])
+
+ text = """\
+// Cross origin properties
+${instance_template}->SetAccessCheckCallbackAndHandler(
+ CrossOriginAccessCheckCallback,
+ v8::NamedPropertyHandlerConfiguration(
+ CrossOriginPropertyGetterCallback,
+ CrossOriginPropertySetterCallback,
+ CrossOriginPropertyDescriptorCallback,
+ nullptr, // deleter
+ CrossOriginPropertyEnumeratorCallback,
+ nullptr, // definer,
+ v8::Local<v8::Value>(),
+ v8::PropertyHandlerFlags::kNone),
+% if interface.indexed_and_named_properties and \
+ interface.indexed_and_named_properties.has_indexed_properties:
+ // Reuse non-cross origin indexed property callbacks.
+ v8::IndexedPropertyHandlerConfiguration(
+ ${class_name}::IndexedPropertyGetterCallback,
+ nullptr, // setter
+ ${class_name}::IndexedPropertyDescriptorCallback,
+ nullptr, // deleter
+ ${class_name}::IndexedPropertyEnumeratorCallback,
+ nullptr, // definer
+ v8::Local<v8::Value>(),
+ v8::PropertyHandlerFlags::kNone),
+% else:
+ v8::IndexedPropertyHandlerConfiguration(
+ nullptr, // getter
+ nullptr, // setter
+ nullptr, // descriptor
+ nullptr, // deleter
+ nullptr, // enumerator
+ nullptr, // definer
+ v8::Local<v8::Value>(),
+ v8::PropertyHandlerFlags::kNone),
+% endif
+ v8::Local<v8::Value>());"""
+ install_nodes.append(TextNode(text))
+ install_nodes.accumulate(
+ CodeGenAccumulator.require_include_headers([
+ "third_party/blink/renderer/bindings/core/v8/binding_security.h",
+ "third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h",
+ ]))
+
+ return callback_defs, install_nodes
+
+
+def make_cross_component_init(
+ cg_context, function_name, class_name, has_unconditional_props,
+ has_context_independent_props, has_context_dependent_props):
+ """
+ Returns:
+ A triplet of CodeNode of:
+ - function declaration
+ - function definition
+ - trampoline member variable definitions
+ """
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+ assert isinstance(class_name, str)
+ assert isinstance(has_unconditional_props, bool)
+ assert isinstance(has_context_independent_props, bool)
+ assert isinstance(has_context_dependent_props, bool)
+
+ T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+
+ def filter_four_trampolines(nodes):
+ assert len(nodes) == 4
+ flags = (True, has_unconditional_props, has_context_independent_props,
+ has_context_dependent_props)
+ return [node for node, flag in zip(nodes, flags) if flag]
+
+ trampoline_var_decls = ListNode(
+ filter_four_trampolines([
+ F("static InstallInterfaceTemplateFuncType {};",
+ TP_INSTALL_INTERFACE_TEMPLATE),
+ F("static InstallUnconditionalPropertiesFuncType {};",
+ TP_INSTALL_UNCONDITIONAL_PROPS),
+ F("static InstallContextIndependentPropertiesFuncType {};",
+ TP_INSTALL_CONTEXT_INDEPENDENT_PROPS),
+ F("static InstallContextDependentPropertiesFuncType {};",
+ TP_INSTALL_CONTEXT_DEPENDENT_PROPS),
+ ]))
+
+ trampoline_var_defs = ListNode(
+ filter_four_trampolines([
+ F(("${class_name}::InstallInterfaceTemplateFuncType "
+ "${class_name}::{} = nullptr;"), TP_INSTALL_INTERFACE_TEMPLATE),
+ F(("${class_name}::InstallUnconditionalPropertiesFuncType "
+ "${class_name}::{} = nullptr;"),
+ TP_INSTALL_UNCONDITIONAL_PROPS),
+ F(("${class_name}::InstallContextIndependentPropertiesFuncType "
+ "${class_name}::{} = nullptr;"),
+ TP_INSTALL_CONTEXT_INDEPENDENT_PROPS),
+ F(("${class_name}::InstallContextDependentPropertiesFuncType "
+ "${class_name}::{} = nullptr;"),
+ TP_INSTALL_CONTEXT_DEPENDENT_PROPS),
+ ]))
+ trampoline_var_defs.set_base_template_vars(cg_context.template_bindings())
+
+ func_decl = CxxFuncDeclNode(
+ name=function_name, arg_decls=[], return_type="void", static=True)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ class_name=class_name,
+ arg_decls=[],
+ return_type="void")
+ func_def.set_base_template_vars(cg_context.template_bindings())
+
+ body = func_def.body
+ body.extend(
+ filter_four_trampolines([
+ F("${class_name}::{} = {};", TP_INSTALL_INTERFACE_TEMPLATE,
+ FN_INSTALL_INTERFACE_TEMPLATE),
+ F("${class_name}::{} = {};", TP_INSTALL_UNCONDITIONAL_PROPS,
+ FN_INSTALL_UNCONDITIONAL_PROPS),
+ F("${class_name}::{} = {};", TP_INSTALL_CONTEXT_INDEPENDENT_PROPS,
+ FN_INSTALL_CONTEXT_INDEPENDENT_PROPS),
+ F("${class_name}::{} = {};", TP_INSTALL_CONTEXT_DEPENDENT_PROPS,
+ FN_INSTALL_CONTEXT_DEPENDENT_PROPS),
+ ]))
+
+ return func_decl, func_def, trampoline_var_decls, trampoline_var_defs
+
+
+# ----------------------------------------------------------------------------
+# WrapperTypeInfo
+# ----------------------------------------------------------------------------
+
+# FN = function name
+FN_GET_WRAPPER_TYPE_INFO = name_style.func("GetWrapperTypeInfo")
+
+# MN = member name
+MN_WRAPPER_TYPE_INFO = name_style.member_var("wrapper_type_info_")
+
+
+def make_wrapper_type_info(cg_context, function_name, member_var_name,
+ install_context_dependent_func_name):
+ assert isinstance(cg_context, CodeGenContext)
+ assert isinstance(function_name, str)
+ assert isinstance(member_var_name, str)
+ assert _is_none_or_str(install_context_dependent_func_name)
+
+ func_def = CxxFuncDefNode(
+ name=function_name,
+ arg_decls=[],
+ return_type="constexpr const WrapperTypeInfo*",
+ static=True)
+ func_def.set_base_template_vars(cg_context.template_bindings())
+ func_def.body.append(TextNode("return &{};".format(member_var_name)))
+
+ member_var_def = TextNode(
+ "static const WrapperTypeInfo {};".format(member_var_name))
+
+ pattern = """\
+// Migration adapter
+v8::Local<v8::FunctionTemplate> ${class_name}::DomTemplate(
+ v8::Isolate* isolate,
+ const DOMWrapperWorld& world) {{
+ return V8DOMConfiguration::DomClassTemplate(
+ isolate, world,
+ const_cast<WrapperTypeInfo*>(${class_name}::GetWrapperTypeInfo()),
+ ${class_name}::InstallInterfaceTemplate);
+}}
+
+const WrapperTypeInfo ${class_name}::wrapper_type_info_{{
+ gin::kEmbedderBlink,
+ ${class_name}::DomTemplate,
+ {install_context_dependent_func},
+ "${{class_like.identifier}}",
+ {wrapper_type_info_of_inherited},
+ {wrapper_type_prototype},
+ {wrapper_class_id},
+ {active_script_wrappable_inheritance},
+}};"""
+ class_like = cg_context.class_like
+ install_context_dependent_func = (
+ "${class_name}::InstallContextDependentAdapter"
+ if install_context_dependent_func_name else "nullptr")
+ if class_like.inherited:
+ wrapper_type_info_of_inherited = "{}::GetWrapperTypeInfo()".format(
+ v8_bridge_class_name(class_like.inherited))
+ else:
+ wrapper_type_info_of_inherited = "nullptr"
+ wrapper_type_prototype = ("WrapperTypeInfo::kWrapperTypeObjectPrototype"
+ if isinstance(class_like, web_idl.Interface) else
+ "WrapperTypeInfo::kWrapperTypeNoPrototype")
+ wrapper_class_id = ("WrapperTypeInfo::kNodeClassId"
+ if class_like.does_implement("Node") else
+ "WrapperTypeInfo::kObjectClassId")
+ active_script_wrappable_inheritance = (
+ "WrapperTypeInfo::kInheritFromActiveScriptWrappable"
+ if class_like.code_generator_info.is_active_script_wrappable else
+ "WrapperTypeInfo::kNotInheritFromActiveScriptWrappable")
+ text = _format(
+ pattern,
+ install_context_dependent_func=install_context_dependent_func,
+ wrapper_type_info_of_inherited=wrapper_type_info_of_inherited,
+ wrapper_type_prototype=wrapper_type_prototype,
+ wrapper_class_id=wrapper_class_id,
+ active_script_wrappable_inheritance=active_script_wrappable_inheritance
+ )
+ bridge_wrapper_type_info_def = TextNode(text)
+
+ blink_class = blink_class_name(class_like)
+ pattern = ("const WrapperTypeInfo& {blink_class}::wrapper_type_info_ = "
+ "${class_name}::wrapper_type_info_;")
+ blink_wrapper_type_info_def = TextNode(
+ _format(pattern, blink_class=blink_class))
+
+ if class_like.code_generator_info.is_active_script_wrappable:
+ pattern = """\
+// [ActiveScriptWrappable]
+static_assert(
+ std::is_base_of<ActiveScriptWrappableBase, {blink_class}>::value,
+ "{blink_class} does not inherit from ActiveScriptWrappable<> despite "
+ "the IDL has [ActiveScriptWrappable] extended attribute.");
+static_assert(
+ !std::is_same<decltype(&{blink_class}::HasPendingActivity),
+ decltype(&ScriptWrappable::HasPendingActivity)>::value,
+ "{blink_class} is not overriding hasPendingActivity() despite "
+ "the IDL has [ActiveScriptWrappable] extended attribute.");"""
+ else:
+ pattern = """\
+// non-[ActiveScriptWrappable]
+static_assert(
+ !std::is_base_of<ActiveScriptWrappableBase, {blink_class}>::value,
+ "{blink_class} inherits from ActiveScriptWrappable<> without "
+ "[ActiveScriptWrappable] extended attribute.");
+static_assert(
+ std::is_same<decltype(&{blink_class}::HasPendingActivity),
+ decltype(&ScriptWrappable::HasPendingActivity)>::value,
+ "{blink_class} is overriding hasPendingActivity() without "
+ "[ActiveScriptWrappable] extended attribute.");"""
+ check_active_script_wrappable = TextNode(
+ _format(pattern, blink_class=blink_class))
+
+ wrapper_type_info_def = ListNode([
+ bridge_wrapper_type_info_def,
+ EmptyNode(),
+ blink_wrapper_type_info_def,
+ EmptyNode(),
+ check_active_script_wrappable,
+ ])
+ wrapper_type_info_def.set_base_template_vars(
+ cg_context.template_bindings())
+
+ return func_def, member_var_def, wrapper_type_info_def
+
+
+# ----------------------------------------------------------------------------
+# Main functions
+# ----------------------------------------------------------------------------
+
+
+def _collect_include_headers(interface):
+ headers = set(interface.code_generator_info.blink_headers)
+
+ def collect_from_idl_type(idl_type):
+ idl_type.apply_to_all_composing_elements(add_include_headers)
+
+ def add_include_headers(idl_type):
+ # ScriptPromise doesn't require any header for the result type.
+ if idl_type.is_promise:
+ raise StopIteration(idl_type.syntactic_form)
+
+ type_def_obj = idl_type.type_definition_object
+ if type_def_obj is not None:
+ headers.add(PathManager(type_def_obj).api_path(ext="h"))
+ if isinstance(type_def_obj, web_idl.Interface):
+ headers.add(PathManager(type_def_obj).blink_path(ext="h"))
+ raise StopIteration(idl_type.syntactic_form)
+
+ union_def_obj = idl_type.union_definition_object
+ if union_def_obj is not None:
+ headers.add(PathManager(union_def_obj).api_path(ext="h"))
+
+ for attribute in interface.attributes:
+ collect_from_idl_type(attribute.idl_type)
+ for constructor in interface.constructors:
+ for argument in constructor.arguments:
+ collect_from_idl_type(argument.idl_type)
+ for operation in interface.operations:
+ collect_from_idl_type(operation.return_type)
+ for argument in operation.arguments:
+ collect_from_idl_type(argument.idl_type)
+
+ for exposed_construct in interface.exposed_constructs:
+ headers.add(PathManager(exposed_construct).api_path(ext="h"))
+ for legacy_window_alias in interface.legacy_window_aliases:
+ headers.add(
+ PathManager(legacy_window_alias.original).api_path(ext="h"))
+
+ path_manager = PathManager(interface)
+ headers.discard(path_manager.api_path(ext="h"))
+ headers.discard(path_manager.impl_path(ext="h"))
+
+ # TODO(yukishiino): Window interface should be
+ # [ImplementedAs=LocalDOMWindow] instead of [ImplementedAs=DOMWindow], and
+ # [CrossOrigin] properties should be implemented specifically with
+ # DOMWindow class. Then, we'll have less hacks.
+ if interface.identifier == "Window":
+ headers.add("third_party/blink/renderer/core/frame/local_dom_window.h")
+
+ return headers
+
+
+def generate_interface(interface):
+ path_manager = PathManager(interface)
+ api_component = path_manager.api_component
+ impl_component = path_manager.impl_component
+ is_cross_components = path_manager.is_cross_components
+
+ # Class names
+ api_class_name = v8_bridge_class_name(interface)
+ if is_cross_components:
+ impl_class_name = "{}::Impl".format(api_class_name)
+ else:
+ impl_class_name = api_class_name
+
+ cg_context = CodeGenContext(interface=interface, class_name=api_class_name)
+
+ # Filepaths
+ api_header_path = path_manager.api_path(ext="h")
+ api_source_path = path_manager.api_path(ext="cc")
+ if is_cross_components:
+ impl_header_path = path_manager.impl_path(ext="h")
+ impl_source_path = path_manager.impl_path(ext="cc")
+
+ # Root nodes
+ api_header_node = ListNode(tail="\n")
+ api_header_node.set_accumulator(CodeGenAccumulator())
+ api_header_node.set_renderer(MakoRenderer())
+ api_source_node = ListNode(tail="\n")
+ api_source_node.set_accumulator(CodeGenAccumulator())
+ api_source_node.set_renderer(MakoRenderer())
+ if is_cross_components:
+ impl_header_node = ListNode(tail="\n")
+ impl_header_node.set_accumulator(CodeGenAccumulator())
+ impl_header_node.set_renderer(MakoRenderer())
+ impl_source_node = ListNode(tail="\n")
+ impl_source_node.set_accumulator(CodeGenAccumulator())
+ impl_source_node.set_renderer(MakoRenderer())
+ else:
+ impl_header_node = api_header_node
+ impl_source_node = api_source_node
+
+ # Namespaces
+ api_header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ api_source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ if is_cross_components:
+ impl_header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ impl_source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ else:
+ impl_header_blink_ns = api_header_blink_ns
+ impl_source_blink_ns = api_source_blink_ns
+
+ # Class definitions
+ api_class_def = CxxClassDefNode(
+ cg_context.class_name,
+ base_class_names=[
+ _format("bindings::V8InterfaceBridge<${class_name}, {}>",
+ blink_class_name(interface)),
+ ],
+ final=True,
+ export=component_export(api_component))
+ api_class_def.set_base_template_vars(cg_context.template_bindings())
+ api_class_def.bottom_section.append(
+ TextNode("friend class {};".format(blink_class_name(interface))))
+ if is_cross_components:
+ impl_class_def = CxxClassDefNode(
+ impl_class_name,
+ final=True,
+ export=component_export(impl_component))
+ impl_class_def.set_base_template_vars(cg_context.template_bindings())
+ api_class_def.public_section.extend([
+ TextNode("// Cross-component implementation class"),
+ TextNode("class Impl;"),
+ EmptyNode(),
+ ])
+ else:
+ impl_class_def = api_class_def
+
+ # Constants
+ constant_defs = ListNode()
+ for constant in interface.constants:
+ cgc = cg_context.make_copy(constant=constant)
+ constant_defs.append(
+ make_constant_constant_def(cgc, constant_name(cgc)))
+
+ # Custom callback implementations
+ custom_callback_impl_decls = ListNode()
+
+ def add_custom_callback_impl_decl(**params):
+ arg_decls = params.pop("arg_decls")
+ name = params.pop("name", None)
+ if name is None:
+ name = custom_function_name(cg_context.make_copy(**params))
+ custom_callback_impl_decls.append(
+ CxxFuncDeclNode(
+ name=name,
+ arg_decls=arg_decls,
+ return_type="void",
+ static=True))
+
+ if interface.identifier == "HTMLAllCollection":
+ add_custom_callback_impl_decl(
+ name=name_style.func("LegacyCallCustom"),
+ arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"])
+ for attribute in interface.attributes:
+ custom_values = attribute.extended_attributes.values_of("Custom")
+ is_cross_origin = "CrossOrigin" in attribute.extended_attributes
+ cross_origin_values = attribute.extended_attributes.values_of(
+ "CrossOrigin")
+ if "Getter" in custom_values:
+ add_custom_callback_impl_decl(
+ attribute=attribute,
+ attribute_get=True,
+ arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"])
+ if is_cross_origin and (not cross_origin_values
+ or "Getter" in cross_origin_values):
+ add_custom_callback_impl_decl(
+ attribute=attribute,
+ attribute_get=True,
+ arg_decls=["const v8::PropertyCallbackInfo<v8::Value>&"])
+ if "Setter" in custom_values:
+ add_custom_callback_impl_decl(
+ attribute=attribute,
+ attribute_set=True,
+ arg_decls=[
+ "v8::Local<v8::Value>",
+ "const v8::FunctionCallbackInfo<v8::Value>&",
+ ])
+ if is_cross_origin and (not cross_origin_values
+ or "Setter" in cross_origin_values):
+ add_custom_callback_impl_decl(
+ attribute=attribute,
+ attribute_set=True,
+ arg_decls=[
+ "v8::Local<v8::Value>",
+ "const v8::PropertyCallbackInfo<v8::Value>&",
+ ])
for operation_group in interface.operation_groups:
- func_name = name_style.func(operation_group.identifier,
- "OperationCallback")
- code_node.append(
- make_operation_callback_def(
- cg_context.make_copy(operation_group=operation_group),
- func_name))
+ if "Custom" in operation_group.extended_attributes:
+ add_custom_callback_impl_decl(
+ operation_group=operation_group,
+ arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"])
+ if interface.indexed_and_named_properties:
+ props = interface.indexed_and_named_properties
+ operation = props.own_named_getter
+ if operation and "Custom" in operation.extended_attributes:
+ add_custom_callback_impl_decl(
+ named_property_getter=operation,
+ arg_decls=[
+ "const AtomicString& property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>&",
+ ])
+ operation = props.own_named_setter
+ if operation and "Custom" in operation.extended_attributes:
+ add_custom_callback_impl_decl(
+ named_property_setter=operation,
+ arg_decls=[
+ "const AtomicString& property_name",
+ "v8::Local<v8::Value> v8_property_value",
+ "const v8::PropertyCallbackInfo<v8::Value>&",
+ ])
+ operation = props.own_named_deleter
+ if operation and "Custom" in operation.extended_attributes:
+ add_custom_callback_impl_decl(
+ named_property_deleter=operation,
+ arg_decls=[
+ "const AtomicString& property_name",
+ "const v8::PropertyCallbackInfo<v8::Value>&",
+ ])
+
+ # Cross-component trampolines
+ if is_cross_components:
+ # tp_ = trampoline name
+ tp_install_interface_template = TP_INSTALL_INTERFACE_TEMPLATE
+ tp_install_unconditional_props = TP_INSTALL_UNCONDITIONAL_PROPS
+ tp_install_context_independent_props = (
+ TP_INSTALL_CONTEXT_INDEPENDENT_PROPS)
+ tp_install_context_dependent_props = TP_INSTALL_CONTEXT_DEPENDENT_PROPS
+ else:
+ tp_install_interface_template = None
+ tp_install_unconditional_props = None
+ tp_install_context_independent_props = None
+ tp_install_context_dependent_props = None
+
+ # Callback functions
+ attribute_entries = []
+ constant_entries = []
+ constructor_entries = []
+ exposed_construct_entries = []
+ operation_entries = []
+ callback_defs = _make_property_entries_and_callback_defs(
+ cg_context,
+ attribute_entries=attribute_entries,
+ constant_entries=constant_entries,
+ constructor_entries=constructor_entries,
+ exposed_construct_entries=exposed_construct_entries,
+ operation_entries=operation_entries)
+
+ # Indexed and named properties
+ (indexed_and_named_property_decls, indexed_and_named_property_defs,
+ indexed_and_named_property_install_nodes) = (
+ make_indexed_and_named_property_callbacks_and_install_nodes(
+ cg_context))
+
+ # Cross origin properties
+ (cross_origin_property_callback_defs,
+ cross_origin_property_install_nodes) = (
+ make_cross_origin_property_callbacks_and_install_nodes(
+ cg_context, attribute_entries, operation_entries))
+ callback_defs.extend(cross_origin_property_callback_defs)
+
+ # Installer functions
+ is_unconditional = lambda entry: entry.exposure_conditional.is_always_true
+ is_context_dependent = lambda entry: entry.is_context_dependent
+ is_context_independent = (
+ lambda e: not is_context_dependent(e) and not is_unconditional(e))
+ (install_unconditional_props_decl, install_unconditional_props_def,
+ install_unconditional_props_trampoline) = make_install_properties(
+ cg_context,
+ FN_INSTALL_UNCONDITIONAL_PROPS,
+ class_name=impl_class_name,
+ trampoline_var_name=tp_install_unconditional_props,
+ is_context_dependent=False,
+ attribute_entries=filter(is_unconditional, attribute_entries),
+ constant_entries=filter(is_unconditional, constant_entries),
+ exposed_construct_entries=filter(is_unconditional,
+ exposed_construct_entries),
+ operation_entries=filter(is_unconditional, operation_entries))
+ (install_context_independent_props_decl,
+ install_context_independent_props_def,
+ install_context_independent_props_trampoline) = make_install_properties(
+ cg_context,
+ FN_INSTALL_CONTEXT_INDEPENDENT_PROPS,
+ class_name=impl_class_name,
+ trampoline_var_name=tp_install_context_independent_props,
+ is_context_dependent=False,
+ attribute_entries=filter(is_context_independent, attribute_entries),
+ constant_entries=filter(is_context_independent, constant_entries),
+ exposed_construct_entries=filter(is_context_independent,
+ exposed_construct_entries),
+ operation_entries=filter(is_context_independent, operation_entries))
+ (install_context_dependent_props_decl, install_context_dependent_props_def,
+ install_context_dependent_props_trampoline) = make_install_properties(
+ cg_context,
+ FN_INSTALL_CONTEXT_DEPENDENT_PROPS,
+ class_name=impl_class_name,
+ trampoline_var_name=tp_install_context_dependent_props,
+ is_context_dependent=True,
+ attribute_entries=filter(is_context_dependent, attribute_entries),
+ constant_entries=filter(is_context_dependent, constant_entries),
+ exposed_construct_entries=filter(is_context_dependent,
+ exposed_construct_entries),
+ operation_entries=filter(is_context_dependent, operation_entries))
+ (install_interface_template_decl, install_interface_template_def,
+ install_interface_template_trampoline) = make_install_interface_template(
+ cg_context,
+ FN_INSTALL_INTERFACE_TEMPLATE,
+ class_name=impl_class_name,
+ trampoline_var_name=tp_install_interface_template,
+ constructor_entries=constructor_entries,
+ indexed_and_named_property_install_nodes=(
+ indexed_and_named_property_install_nodes),
+ cross_origin_property_install_nodes=(
+ cross_origin_property_install_nodes),
+ install_unconditional_func_name=(install_unconditional_props_def
+ and FN_INSTALL_UNCONDITIONAL_PROPS),
+ install_context_independent_func_name=(
+ install_context_independent_props_def
+ and FN_INSTALL_CONTEXT_INDEPENDENT_PROPS))
+ installer_function_decls = ListNode([
+ install_interface_template_decl,
+ install_unconditional_props_decl,
+ install_context_independent_props_decl,
+ install_context_dependent_props_decl,
+ ])
+ installer_function_defs = ListNode([
+ install_interface_template_def,
+ EmptyNode(),
+ install_unconditional_props_def,
+ EmptyNode(),
+ install_context_independent_props_def,
+ EmptyNode(),
+ install_context_dependent_props_def,
+ ])
+ installer_function_trampolines = ListNode([
+ install_interface_template_trampoline,
+ install_unconditional_props_trampoline,
+ install_context_independent_props_trampoline,
+ install_context_dependent_props_trampoline,
+ ])
+
+ # WrapperTypeInfo
+ (get_wrapper_type_info_def, wrapper_type_info_var_def,
+ wrapper_type_info_init) = make_wrapper_type_info(
+ cg_context,
+ FN_GET_WRAPPER_TYPE_INFO,
+ MN_WRAPPER_TYPE_INFO,
+ install_context_dependent_func_name=(
+ install_context_dependent_props_def
+ and FN_INSTALL_CONTEXT_DEPENDENT_PROPS))
+
+ # Cross-component trampolines
+ if is_cross_components:
+ (cross_component_init_decl, cross_component_init_def,
+ trampoline_var_decls,
+ trampoline_var_defs) = make_cross_component_init(
+ cg_context,
+ "Init",
+ class_name=impl_class_name,
+ has_unconditional_props=bool(
+ install_unconditional_props_trampoline),
+ has_context_independent_props=bool(
+ install_context_independent_props_trampoline),
+ has_context_dependent_props=bool(
+ install_context_dependent_props_trampoline))
+
+ # Header part (copyright, include directives, and forward declarations)
+ api_header_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ enclose_with_header_guard(
+ ListNode([
+ make_header_include_directives(api_header_node.accumulator),
+ EmptyNode(),
+ api_header_blink_ns,
+ ]), name_style.header_guard(api_header_path)),
+ ])
+ api_header_blink_ns.body.extend([
+ make_forward_declarations(api_header_node.accumulator),
+ EmptyNode(),
+ ])
+ api_source_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ TextNode("#include \"{}\"".format(api_header_path)),
+ EmptyNode(),
+ make_header_include_directives(api_source_node.accumulator),
+ EmptyNode(),
+ api_source_blink_ns,
+ ])
+ api_source_blink_ns.body.extend([
+ make_forward_declarations(api_source_node.accumulator),
+ EmptyNode(),
+ ])
+ if is_cross_components:
+ impl_header_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ enclose_with_header_guard(
+ ListNode([
+ make_header_include_directives(
+ impl_header_node.accumulator),
+ EmptyNode(),
+ impl_header_blink_ns,
+ ]), name_style.header_guard(impl_header_path)),
+ ])
+ impl_header_blink_ns.body.extend([
+ make_forward_declarations(impl_header_node.accumulator),
+ EmptyNode(),
+ ])
+ impl_source_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ TextNode("#include \"{}\"".format(impl_header_path)),
+ EmptyNode(),
+ make_header_include_directives(impl_source_node.accumulator),
+ EmptyNode(),
+ impl_source_blink_ns,
+ ])
+ impl_source_blink_ns.body.extend([
+ make_forward_declarations(impl_source_node.accumulator),
+ EmptyNode(),
+ ])
+ api_header_node.accumulator.add_include_headers([
+ interface.code_generator_info.blink_headers[0],
+ component_export_header(api_component),
+ "third_party/blink/renderer/platform/bindings/v8_interface_bridge.h",
+ ])
+ api_source_node.accumulator.add_include_headers([
+ "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h",
+ ])
+ if interface.inherited:
+ api_source_node.accumulator.add_include_header(
+ PathManager(interface.inherited).api_path(ext="h"))
+ if is_cross_components:
+ impl_header_node.accumulator.add_include_headers([
+ api_header_path,
+ component_export_header(impl_component),
+ ])
+ impl_source_node.accumulator.add_include_headers([
+ "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h",
+ "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h",
+ "third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h",
+ "third_party/blink/renderer/platform/bindings/exception_messages.h",
+ "third_party/blink/renderer/platform/bindings/runtime_call_stats.h",
+ "third_party/blink/renderer/platform/bindings/v8_binding.h",
+ ])
+ impl_source_node.accumulator.add_include_headers(
+ _collect_include_headers(interface))
+ if interface.constructor_groups:
+ impl_source_node.accumulator.add_include_headers([
+ "third_party/blink/renderer/platform/bindings/v8_object_constructor.h",
+ ])
+
+ # Assemble the parts.
+ api_header_blink_ns.body.append(api_class_def)
+ if is_cross_components:
+ impl_header_blink_ns.body.append(impl_class_def)
+
+ api_class_def.public_section.append(get_wrapper_type_info_def)
+ api_class_def.public_section.append(EmptyNode())
+ api_class_def.public_section.extend([
+ TextNode("// Migration adapter"),
+ TextNode("static v8::Local<v8::FunctionTemplate> DomTemplate("
+ "v8::Isolate* isolate, "
+ "const DOMWrapperWorld& world);"),
+ EmptyNode(),
+ ])
+ api_class_def.private_section.append(wrapper_type_info_var_def)
+ api_class_def.private_section.append(EmptyNode())
+ api_source_blink_ns.body.extend([
+ wrapper_type_info_init,
+ EmptyNode(),
+ ])
+
+ if is_cross_components:
+ api_class_def.public_section.append(installer_function_trampolines)
+ api_class_def.private_section.extend([
+ TextNode("// Cross-component trampolines"),
+ trampoline_var_decls,
+ EmptyNode(),
+ ])
+ api_source_blink_ns.body.extend([
+ TextNode("// Cross-component trampolines"),
+ trampoline_var_defs,
+ EmptyNode(),
+ ])
+ impl_class_def.public_section.append(cross_component_init_decl)
+ impl_class_def.private_section.append(installer_function_decls)
+ impl_source_blink_ns.body.extend([
+ cross_component_init_def,
+ EmptyNode(),
+ ])
+ else:
+ api_class_def.public_section.append(installer_function_decls)
+ api_class_def.public_section.append(EmptyNode())
+
+ if constant_defs:
+ api_class_def.public_section.extend([
+ TextNode("// Constants"),
+ constant_defs,
+ EmptyNode(),
+ ])
+
+ if custom_callback_impl_decls:
+ api_class_def.public_section.extend([
+ TextNode("// Custom callback implementations"),
+ custom_callback_impl_decls,
+ EmptyNode(),
+ ])
+
+ if indexed_and_named_property_decls:
+ api_class_def.public_section.extend([
+ TextNode("// Indexed properties and named properties"),
+ indexed_and_named_property_decls,
+ EmptyNode(),
+ ])
+
+ impl_source_blink_ns.body.extend([
+ CxxNamespaceNode(name="", body=callback_defs),
+ EmptyNode(),
+ installer_function_defs,
+ EmptyNode(),
+ indexed_and_named_property_defs,
+ EmptyNode(),
+ ])
- code_node.append(make_install_interface_template_def(cg_context))
+ # Write down to the files.
+ write_code_node_to_file(api_header_node,
+ path_manager.gen_path_to(api_header_path))
+ write_code_node_to_file(api_source_node,
+ path_manager.gen_path_to(api_source_path))
+ if path_manager.is_cross_components:
+ write_code_node_to_file(impl_header_node,
+ path_manager.gen_path_to(impl_header_path))
+ write_code_node_to_file(impl_source_node,
+ path_manager.gen_path_to(impl_source_path))
+
+
+def generate_init_idl_interfaces(web_idl_database):
+ # Filepaths
+ header_path = PathManager.component_path("modules",
+ "init_idl_interfaces.h")
+ source_path = PathManager.component_path("modules",
+ "init_idl_interfaces.cc")
+
+ # Root nodes
+ header_node = ListNode(tail="\n")
+ header_node.set_accumulator(CodeGenAccumulator())
+ header_node.set_renderer(MakoRenderer())
+ source_node = ListNode(tail="\n")
+ source_node.set_accumulator(CodeGenAccumulator())
+ source_node.set_renderer(MakoRenderer())
+
+ # Namespaces
+ header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+ header_bindings_ns = CxxNamespaceNode(name_style.namespace("bindings"))
+ source_bindings_ns = CxxNamespaceNode(name_style.namespace("bindings"))
+ header_blink_ns.body.append(header_bindings_ns)
+ source_blink_ns.body.append(source_bindings_ns)
+
+ # Function nodes
+ func_decl = CxxFuncDeclNode(
+ name="InitIDLInterfaces", arg_decls=[], return_type="void")
+ func_def = CxxFuncDefNode(
+ name="InitIDLInterfaces", arg_decls=[], return_type="void")
+ header_bindings_ns.body.extend([
+ TextNode("""\
+// Initializes cross-component trampolines of IDL interface implementations.\
+"""),
+ func_decl,
+ ])
+ source_bindings_ns.body.append(func_def)
- root_node.extend([
+ # Assemble the parts.
+ header_node.extend([
+ make_copyright_header(),
+ EmptyNode(),
+ enclose_with_header_guard(
+ ListNode([
+ make_header_include_directives(header_node.accumulator),
+ EmptyNode(),
+ header_blink_ns,
+ ]), name_style.header_guard(header_path)),
+ ])
+ source_node.extend([
make_copyright_header(),
- TextNode(""),
- make_header_include_directives(root_node.accumulator),
- TextNode(""),
- enclose_with_namespace(code_node, name_style.namespace("blink")),
+ EmptyNode(),
+ TextNode("#include \"{}\"".format(header_path)),
+ EmptyNode(),
+ make_header_include_directives(source_node.accumulator),
+ EmptyNode(),
+ source_blink_ns,
])
- write_code_node_to_file(root_node, filepath)
+ init_calls = []
+ for interface in web_idl_database.interfaces:
+ # 'Internals' is the only test-only interface that needs
+ # cross-component trampoline initialization.
+ if interface.identifier == "Internals":
+ continue
+
+ path_manager = PathManager(interface)
+ if path_manager.is_cross_components:
+ source_node.accumulator.add_include_header(
+ path_manager.impl_path(ext="h"))
+
+ class_name = v8_bridge_class_name(interface)
+ init_calls.append(_format("{}::Impl::Init();", class_name))
+ for init_call in sorted(init_calls):
+ func_def.body.append(TextNode(init_call))
+
+ # Write down to the files.
+ write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
+ write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))
+
+
+def generate_interfaces(web_idl_database):
+ # More processes do not mean better performance. The default size was
+ # chosen heuristically.
+ process_pool_size = 8
+ cpu_count = multiprocessing.cpu_count()
+ process_pool_size = max(1, min(cpu_count / 2, process_pool_size))
+
+ pool = multiprocessing.Pool(process_pool_size)
+ # Prior to Python3, Pool.map doesn't support user interrupts (e.g. Ctrl-C),
+ # although Pool.map_async(...).get(...) does.
+ timeout_in_sec = 3600 # Just enough long time
+ pool.map_async(generate_interface,
+ web_idl_database.interfaces).get(timeout_in_sec)
+
+ generate_init_idl_interfaces(web_idl_database)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
index f75b959c3df..b4c70553863 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
@@ -4,59 +4,91 @@
import sys
-import mako.lookup
+import mako.runtime
import mako.template
+import mako.util
+_MAKO_TEMPLATE_PASS_KEY = object()
-class MakoRenderer(object):
- """Represents a renderer object implemented with Mako templates."""
- def __init__(self, template_dirs=None):
- self._template_params = {
+class MakoTemplate(object):
+ """Represents a compiled template object."""
+
+ _mako_template_cache = {}
+
+ def __init__(self, template_text):
+ assert isinstance(template_text, str)
+
+ template_params = {
"strict_undefined": True,
}
- self._template_lookup = mako.lookup.TemplateLookup(
- directories=template_dirs, **self._template_params)
+ template = self._mako_template_cache.get(template_text)
+ if template is None:
+ template = mako.template.Template(
+ text=template_text, **template_params)
+ self._mako_template_cache[template_text] = template
+ self._template = template
+
+ def mako_template(self, pass_key=None):
+ assert pass_key is _MAKO_TEMPLATE_PASS_KEY
+ return self._template
+
+class MakoRenderer(object):
+ """Represents a renderer object implemented with Mako templates."""
+
+ def __init__(self):
+ self._text_buffer = None
+ self._is_invalidated = False
self._caller_stack = []
self._caller_stack_on_error = []
- def render(self,
- caller,
- template_path=None,
- template_text=None,
- template_vars=None):
+ def reset(self):
+ """
+ Resets the rendering states of this object. Must be called before
+ the first call to |render| or |render_text|.
+ """
+ self._text_buffer = mako.util.FastEncodingBuffer()
+ self._is_invalidated = False
+
+ def is_rendering_complete(self):
+ return not (self._is_invalidated or self._text_buffer is None
+ or self._caller_stack)
+
+ def invalidate_rendering_result(self):
+ self._is_invalidated = True
+
+ def to_text(self):
+ """Returns the rendering result."""
+ assert self._text_buffer is not None
+ return self._text_buffer.getvalue()
+
+ def render(self, caller, template, template_vars):
"""
Renders the template with variable bindings.
It's okay to invoke |render| method recursively and |caller| is pushed
- onto the call stack, which is accessible via |callers| and |last_caller|
- methods.
+ onto the call stack, which is accessible via
+ |callers_from_first_to_last| method, etc.
Args:
- template_path: A filepath to a template file.
- template_text: A text content to be used as a template. Either of
- |template_path| or |template_text| must be specified.
- template_vars: Template variable bindings.
caller: An object to be pushed onto the call stack.
+ template: A MakoTemplate.
+ template_vars: A dict of template variable bindings.
"""
-
- assert template_path is not None or template_text is not None
- assert template_path is None or template_text is None
- assert isinstance(template_vars, dict)
assert caller is not None
+ assert isinstance(template, MakoTemplate)
+ assert isinstance(template_vars, dict)
self._caller_stack.append(caller)
try:
- if template_path is not None:
- template = self._template_lookup.get_template(template_path)
- elif template_text is not None:
- template = mako.template.Template(
- text=template_text, **self._template_params)
-
- text = template.render(**template_vars)
+ mako_template = template.mako_template(
+ pass_key=_MAKO_TEMPLATE_PASS_KEY)
+ mako_context = mako.runtime.Context(self._text_buffer,
+ **template_vars)
+ mako_template.render_context(mako_context)
except:
# Print stacktrace of template rendering.
sys.stderr.write("\n")
@@ -64,9 +96,9 @@ class MakoRenderer(object):
sys.stderr.write(" * name: {}, type: {}\n".format(
_guess_caller_name(self.last_caller), type(self.last_caller)))
sys.stderr.write(" * depth: {}, module_id: {}\n".format(
- len(self._caller_stack), template.module_id))
+ len(self._caller_stack), mako_template.module_id))
sys.stderr.write("---- template source ----\n")
- sys.stderr.write(template.source)
+ sys.stderr.write(mako_template.source)
# Save the error state at the deepest call.
current = self._caller_stack
@@ -82,7 +114,16 @@ class MakoRenderer(object):
finally:
self._caller_stack.pop()
- return text
+ def render_text(self, text):
+ """Renders a plain text as is."""
+ assert isinstance(text, str)
+ self._text_buffer.write(text)
+
+ def push_caller(self, caller):
+ self._caller_stack.append(caller)
+
+ def pop_caller(self):
+ self._caller_stack.pop()
@property
def callers_from_first_to_last(self):
@@ -125,7 +166,7 @@ def _guess_caller_name(caller):
"""Returns the best-guessed name of |caller|."""
try:
# Outer CodeNode may have a binding to the caller.
- for name, value in caller.outer.template_vars.iteritems():
+ for name, value in caller.outer.template_vars.items():
if value is caller:
return name
try:
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py
index 137de2b88d3..36a858cecbb 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py
@@ -14,7 +14,7 @@ xxx_f(format_string, *args, **kwargs):
The name is formatted with the given format string and arguments.
"""
-from blinkbuild.name_style_converter import NameStyleConverter
+from blinkbuild import name_style_converter
def api_func(*args):
@@ -132,19 +132,29 @@ def namespace_f(format_string, *args, **kwargs):
def _concat(style_func, args):
assert callable(style_func)
- return style_func(" ".join(map(str, args)))
+ return style_func(" ".join(map(_tokenize, args)))
def _format(style_func, format_string, *args, **kwargs):
assert callable(style_func)
assert isinstance(format_string, str)
- args = map(style_func, map(str, args))
- for key, value in kwargs.iteritems():
- kwargs[key] = style_func(str(value))
+ args = map(style_func, map(_tokenize, args))
+ for key, value in kwargs.items():
+ kwargs[key] = style_func(_tokenize(value))
return format_string.format(*args, **kwargs)
+def _tokenize(s):
+ s = str(s)
+ if "_" in s and s.isupper():
+ # NameStyleConverter doesn't treat "ABC_DEF" as two tokens of "abc" and
+ # "def" while treating "abc_def" as "abc" and "def". Help
+ # NameStyleConverter by lowering the string.
+ return s.lower()
+ return s
+
+
class raw(object):
"""
Namespace to provide (unrecommended) raw controls on case conversions.
@@ -152,21 +162,27 @@ class raw(object):
This class is pretending to be a module.
"""
+ _NameStyleConverter = name_style_converter.NameStyleConverter
+
def __init__(self):
assert False
@staticmethod
+ def tokenize(name):
+ return name_style_converter.tokenize_name(name)
+
+ @staticmethod
def snake_case(name):
- return NameStyleConverter(name).to_snake_case()
+ return raw._NameStyleConverter(name).to_snake_case()
@staticmethod
def upper_camel_case(name):
- return NameStyleConverter(name).to_upper_camel_case()
+ return raw._NameStyleConverter(name).to_upper_camel_case()
@staticmethod
def lower_camel_case(name):
- return NameStyleConverter(name).to_lower_camel_case()
+ return raw._NameStyleConverter(name).to_lower_camel_case()
@staticmethod
def macro_case(name):
- return NameStyleConverter(name).to_macro_case()
+ return raw._NameStyleConverter(name).to_macro_case()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
index b6997d71e65..47d6c08b8ee 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import os.path
import posixpath
import web_idl
@@ -12,7 +13,16 @@ from .blink_v8_bridge import blink_class_name
class PathManager(object):
"""
- Provides a variety of paths such as Blink headers and output files.
+ Provides a variety of paths such as Blink headers and output files. Unless
+ explicitly specified, returned paths are relative to the project's root
+ directory or the root directory of generated files, e.g.
+ "third_party/blink/renderer/..."
+
+ Relative paths are represented in POSIX style so that it fits nicely in
+ generated code, e.g. #include "third_party/blink/renderer/...", while
+ absolute paths are represented in a platform-specific style so that it works
+ well with a platform-specific notion, e.g. a drive letter in Windows path
+ such as "C:\\chromium\\src\\...".
About output files, there are two cases.
- cross-components case:
@@ -26,36 +36,72 @@ class PathManager(object):
_is_initialized = False
@classmethod
- def init(cls, output_dirs):
+ def init(cls, root_src_dir, root_gen_dir, component_reldirs):
"""
Args:
- output_dirs: Pairs of component and output directory.
+ root_src_dir: Project's root directory, which corresponds to "//"
+ in GN.
+ root_gen_dir: Root directory of generated files, which corresponds
+ to "//out/Default/gen" in GN.
+ component_reldirs: Pairs of component and output directory relative
+ to |root_gen_dir|.
"""
assert not cls._is_initialized
- assert isinstance(output_dirs, dict)
- cls._output_dirs = output_dirs
+ assert isinstance(root_src_dir, str)
+ assert isinstance(root_gen_dir, str)
+ assert isinstance(component_reldirs, dict)
+
cls._blink_path_prefix = posixpath.sep + posixpath.join(
"third_party", "blink", "renderer", "")
+
+ cls._root_src_dir = os.path.abspath(root_src_dir)
+ cls._root_gen_dir = os.path.abspath(root_gen_dir)
+ cls._component_reldirs = {
+ component: posixpath.normpath(rel_dir)
+ for component, rel_dir in component_reldirs.items()
+ }
cls._is_initialized = True
@classmethod
- def relpath_to_project_root(cls, path):
- index = path.find(cls._blink_path_prefix)
- if index < 0:
- assert path.startswith(cls._blink_path_prefix[1:])
- return path
- return path[index + 1:]
+ def component_path(cls, component, filepath):
+ """
+ Returns the relative path to |filepath| in |component|'s directory.
+ """
+ assert cls._is_initialized, cls._REQUIRE_INIT_MESSAGE
+ return posixpath.join(cls._component_reldirs[component], filepath)
+
+ @classmethod
+ def gen_path_to(cls, path):
+ """
+ Returns the absolute path of |path| that must be relative to the root
+ directory of generated files.
+ """
+ assert cls._is_initialized, cls._REQUIRE_INIT_MESSAGE
+ return os.path.abspath(os.path.join(cls._root_gen_dir, path))
+
+ @classmethod
+ def src_path_to(cls, path):
+ """
+ Returns the absolute path of |path| that must be relative to the
+ project root directory.
+ """
+ assert cls._is_initialized, cls._REQUIRE_INIT_MESSAGE
+ return os.path.abspath(os.path.join(cls._root_src_dir, path))
def __init__(self, idl_definition):
assert self._is_initialized, self._REQUIRE_INIT_MESSAGE
- idl_path = idl_definition.debug_info.location.filepath
- self._idl_basepath, _ = posixpath.splitext(idl_path)
- self._idl_dir, self._idl_basename = posixpath.split(self._idl_basepath)
-
- components = sorted(idl_definition.components)
+ components = sorted(idl_definition.components) # "core" < "modules"
- if len(components) == 1:
+ if len(components) == 0:
+ assert isinstance(idl_definition, web_idl.Union)
+ # Unions of built-in types, e.g. DoubleOrString, do not have a
+ # component.
+ self._is_cross_components = False
+ default_component = web_idl.Component("core")
+ self._api_component = default_component
+ self._impl_component = default_component
+ elif len(components) == 1:
component = components[0]
self._is_cross_components = False
self._api_component = component
@@ -64,37 +110,36 @@ class PathManager(object):
assert components[0] == "core"
assert components[1] == "modules"
self._is_cross_components = True
- self._api_component = "core"
- self._impl_component = "modules"
+ # Union does not have to support cross-component code generation
+ # because clients of IDL union must be on an upper or same layer to
+ # any of union members.
+ if isinstance(idl_definition, web_idl.Union):
+ self._api_component = components[1]
+ else:
+ self._api_component = components[0]
+ self._impl_component = components[1]
else:
assert False
- self._api_dir = self._output_dirs[self._api_component]
- self._impl_dir = self._output_dirs[self._impl_component]
- self._out_basename = name_style.file("v8", idl_definition.identifier)
-
- if isinstance(idl_definition,
- (web_idl.CallbackFunction, web_idl.CallbackInterface)):
- self._blink_dir = self._api_dir
- else:
- self._blink_dir = self._idl_dir
- self._blink_basename = name_style.file(
- blink_class_name(idl_definition))
-
- @property
- def idl_dir(self):
- return self._idl_dir
-
- def blink_path(self, filename=None, ext=None):
- """
- Returns a path to a Blink implementation file relative to the project
- root directory, e.g. "third_party/blink/renderer/..."
- """
- return self.relpath_to_project_root(
- self._join(
- dirpath=self._blink_dir,
- filename=(filename or self._blink_basename),
- ext=ext))
+ self._api_dir = self._component_reldirs[self._api_component]
+ self._impl_dir = self._component_reldirs[self._impl_component]
+ self._api_basename = name_style.file("v8", idl_definition.identifier)
+ self._impl_basename = name_style.file("v8", idl_definition.identifier)
+ # TODO(peria, yukishiino): Add "v8" prefix to union's files. Trying to
+ # produce the same filepaths with the old bindings generator for the
+ # time being.
+ if isinstance(idl_definition, web_idl.Union):
+ union_class_name = idl_definition.identifier
+ union_filepath = _BACKWARD_COMPATIBLE_UNION_FILEPATHS.get(
+ union_class_name, union_class_name)
+ self._api_basename = name_style.file(union_filepath)
+ self._impl_basename = name_style.file(union_filepath)
+
+ if not isinstance(idl_definition, web_idl.Union):
+ idl_path = idl_definition.debug_info.location.filepath
+ self._blink_dir = posixpath.dirname(idl_path)
+ self._blink_basename = name_style.file(
+ blink_class_name(idl_definition))
@property
def is_cross_components(self):
@@ -111,7 +156,7 @@ class PathManager(object):
def api_path(self, filename=None, ext=None):
return self._join(
dirpath=self.api_dir,
- filename=(filename or self._out_basename),
+ filename=(filename or self._api_basename),
ext=ext)
@property
@@ -125,7 +170,17 @@ class PathManager(object):
def impl_path(self, filename=None, ext=None):
return self._join(
dirpath=self.impl_dir,
- filename=(filename or self._out_basename),
+ filename=(filename or self._impl_basename),
+ ext=ext)
+
+ @property
+ def blink_dir(self):
+ return self._blink_dir
+
+ def blink_path(self, filename=None, ext=None):
+ return self._join(
+ dirpath=self.blink_dir,
+ filename=(filename or self._blink_basename),
ext=ext)
@staticmethod
@@ -133,3 +188,34 @@ class PathManager(object):
if ext is not None:
filename = posixpath.extsep.join([filename, ext])
return posixpath.join(dirpath, filename)
+
+
+# A hack to make the filepaths to generated IDL unions compatible with the old
+# bindings generator.
+#
+# Copied from |shorten_union_name| defined in
+# //third_party/blink/renderer/bindings/scripts/utilities.py
+_BACKWARD_COMPATIBLE_UNION_FILEPATHS = {
+ # modules/canvas2d/CanvasRenderingContext2D.idl
+ "CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas":
+ "CanvasImageSource",
+ # modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
+ "CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext":
+ "RenderingContext",
+ # modules/canvas/htmlcanvas/html_canvas_element_module.idl
+ "CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext":
+ "RenderingContext",
+ # core/frame/window_or_worker_global_scope.idl
+ "HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas":
+ "ImageBitmapSource",
+ # bindings/tests/idls/core/TestTypedefs.idl
+ "NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord":
+ "NestedUnionType",
+ # modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl.
+ # Due to offscreen_canvas_module_support_webgl2_compute.idl and offscreen_canvas_module.idl are exclusive in modules_idl_files.gni, they have same shorten name.
+ "OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContext":
+ "OffscreenRenderingContext",
+ # modules/canvas/offscreencanvas/offscreen_canvas_module.idl
+ "OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContext":
+ "OffscreenRenderingContext",
+}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py
new file mode 100644
index 00000000000..dc3493cc394
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/style_format.py
@@ -0,0 +1,107 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+import subprocess
+import sys
+
+_clang_format_command_path = None
+_gn_command_path = None
+
+
+def init(root_src_dir):
+ global _clang_format_command_path
+ global _gn_command_path
+
+ assert _clang_format_command_path is None
+ assert _gn_command_path is None
+
+ root_src_dir = os.path.abspath(root_src_dir)
+
+ # Determine //buildtools/<platform>/ directory
+ if sys.platform.startswith("linux"):
+ platform = "linux64"
+ exe_suffix = ""
+ elif sys.platform.startswith("darwin"):
+ platform = "mac"
+ exe_suffix = ""
+ elif sys.platform.startswith(("cygwin", "win")):
+ platform = "win"
+ exe_suffix = ".exe"
+ else:
+ assert False, "Unknown platform: {}".format(sys.platform)
+ buildtools_platform_dir = os.path.join(root_src_dir, "buildtools",
+ platform)
+
+ # //buildtools/<platform>/clang-format
+ _clang_format_command_path = os.path.join(
+ buildtools_platform_dir, "clang-format{}".format(exe_suffix))
+
+ # //buildtools/<platform>/gn
+ _gn_command_path = os.path.join(buildtools_platform_dir,
+ "gn{}".format(exe_suffix))
+
+
+def auto_format(contents, filename):
+ assert isinstance(filename, str)
+
+ _, ext = os.path.splitext(filename)
+ if ext in (".gn", ".gni"):
+ return gn_format(contents, filename)
+
+ return clang_format(contents, filename)
+
+
+def clang_format(contents, filename=None):
+ command_line = [_clang_format_command_path]
+ if filename is not None:
+ command_line.append('-assume-filename={}'.format(filename))
+
+ return _invoke_format_command(command_line, filename, contents)
+
+
+def gn_format(contents, filename=None):
+ command_line = [_gn_command_path, "format", "--stdin"]
+ if filename is not None:
+ command_line.append('-assume-filename={}'.format(filename))
+
+ return _invoke_format_command(command_line, filename, contents)
+
+
+def _invoke_format_command(command_line, filename, contents):
+ proc = subprocess.Popen(
+ command_line, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout_output, stderr_output = proc.communicate(input=contents)
+ exit_code = proc.wait()
+
+ return StyleFormatResult(
+ stdout_output=stdout_output,
+ stderr_output=stderr_output,
+ exit_code=exit_code,
+ filename=filename)
+
+
+class StyleFormatResult(object):
+ def __init__(self, stdout_output, stderr_output, exit_code, filename):
+ self._stdout_output = stdout_output
+ self._stderr_output = stderr_output
+ self._exit_code = exit_code
+ self._filename = filename
+
+ @property
+ def did_succeed(self):
+ return self._exit_code == 0
+
+ @property
+ def contents(self):
+ assert self.did_succeed
+ return self._stdout_output
+
+ @property
+ def error_message(self):
+ return self._stderr_output
+
+ @property
+ def filename(self):
+ return self._filename
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
new file mode 100644
index 00000000000..18c9d64f92d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
@@ -0,0 +1,188 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+
+import web_idl
+
+from . import name_style
+from .blink_v8_bridge import blink_type_info
+from .code_node import ListNode
+from .code_node import TextNode
+from .code_node_cxx import CxxClassDefNode
+from .code_node_cxx import CxxFuncDeclNode
+from .code_node_cxx import CxxNamespaceNode
+from .codegen_accumulator import CodeGenAccumulator
+from .codegen_context import CodeGenContext
+from .codegen_format import format_template as _format
+from .codegen_utils import component_export
+from .codegen_utils import enclose_with_header_guard
+from .codegen_utils import make_copyright_header
+from .codegen_utils import make_forward_declarations
+from .codegen_utils import make_header_include_directives
+from .codegen_utils import write_code_node_to_file
+from .mako_renderer import MakoRenderer
+from .path_manager import PathManager
+
+
+def _member_type_name(idl_type):
+ assert isinstance(idl_type, web_idl.IdlType)
+
+ class MemberTypeName(object):
+ def __init__(self, idl_type):
+ type_name = idl_type.type_name
+ self.old_is_api = name_style.func("Is", type_name)
+ self.old_get_api = name_style.func("GetAs", type_name)
+ self.old_set_api = name_style.func("Set", type_name)
+ # C++ data member that holds a union member. The prefix "um"
+ # stands for "Union Member."
+ self.member_var = name_style.member_var("um", type_name)
+
+ return MemberTypeName(idl_type)
+
+
+def make_union_constructor_defs(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ class_name = cg_context.class_name
+
+ return ListNode([
+ CxxFuncDeclNode(
+ name=class_name, arg_decls=[], return_type="", default=True),
+ CxxFuncDeclNode(
+ name=class_name,
+ arg_decls=["const ${class_name}&"],
+ return_type="",
+ default=True),
+ CxxFuncDeclNode(
+ name=class_name,
+ arg_decls=["${class_name}&&"],
+ return_type="",
+ default=True),
+ CxxFuncDeclNode(
+ name="~${class_name}",
+ arg_decls=[],
+ return_type="",
+ override=True,
+ default=True),
+ ])
+
+
+def make_union_member_type_enum(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+
+ union = cg_context.union
+ node = ListNode()
+ enum_members = ListNode(separator=", ")
+
+ node.extend([
+ T("enum class MemberType {"),
+ enum_members,
+ T("};"),
+ T("MemberType active_member_type_ = MemberType::kEmpty;"),
+ ])
+
+ enum_members.append(T("kEmpty"))
+ for idl_type in union.flattened_member_types:
+ enum_members.append(T(name_style.constant(idl_type.type_name)))
+ if union.does_include_nullable_type:
+ enum_members.append(T("kNull"))
+
+ return node
+
+
+def make_union_member_vars(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+ F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+
+ union = cg_context.union
+ node = ListNode()
+
+ node.append(
+ T("""\
+// C++ data members that hold union members. The prefix "um" stands
+// for "Union Member."\
+"""))
+ for idl_type in union.flattened_member_types:
+ _1 = blink_type_info(idl_type).member_t
+ _2 = _member_type_name(idl_type).member_var
+ node.append(F("{_1} {_2};", _1=_1, _2=_2))
+
+ return node
+
+
+def make_union_class_def(cg_context):
+ assert isinstance(cg_context, CodeGenContext)
+
+ T = TextNode
+
+ union = cg_context.union
+ component = union.components[0]
+
+ class_def = CxxClassDefNode(
+ cg_context.class_name, export=component_export(component))
+ class_def.set_base_template_vars(cg_context.template_bindings())
+
+ public_section = class_def.public_section
+ public_section.extend([
+ make_union_constructor_defs(cg_context),
+ T(""),
+ CxxFuncDeclNode(
+ name="Trace", arg_decls=["Visitor*"], return_type="void"),
+ ])
+
+ class_def.private_section.extend([
+ make_union_member_type_enum(cg_context),
+ T(""),
+ make_union_member_vars(cg_context),
+ ])
+
+ return class_def
+
+
+def generate_union(union):
+ path_manager = PathManager(union)
+ class_name = union.identifier
+ cg_context = CodeGenContext(union=union, class_name=class_name)
+
+ filename = "union_example.h"
+ header_path = path_manager.api_path(filename=filename)
+
+ header_node = ListNode(tail="\n")
+ header_node.set_accumulator(CodeGenAccumulator())
+ header_node.set_renderer(MakoRenderer())
+
+ header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
+
+ class_def = make_union_class_def(cg_context)
+
+ header_node.extend([
+ make_copyright_header(),
+ TextNode(""),
+ enclose_with_header_guard(
+ ListNode([
+ make_header_include_directives(header_node.accumulator),
+ TextNode(""),
+ header_blink_ns,
+ ]), name_style.header_guard(header_path)),
+ ])
+ header_blink_ns.body.extend([
+ make_forward_declarations(header_node.accumulator),
+ TextNode(""),
+ ])
+
+ header_blink_ns.body.append(class_def)
+
+ # Write down to the files.
+ write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
+
+
+def generate_unions(web_idl_database):
+ union = list(web_idl_database.union_types)[0]
+ generate_union(union)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py b/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py
index c14b1451115..d041f1dc23f 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py
@@ -25,7 +25,6 @@
# 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.
-
"""Lexer for Blink IDL.
The lexer uses the PLY (Python Lex-Yacc) library to build a tokenizer which
@@ -54,12 +53,15 @@ http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end
# Disable attribute validation, as lint can't import parent class to check
# pylint: disable=E1101
+from __future__ import print_function
+
import os.path
import sys
# PLY is in Chromium src/third_party/ply
module_path, module_name = os.path.split(__file__)
-third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir)
+third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir,
+ os.pardir)
# Insert at front to override system libraries, and after path[0] == script dir
sys.path.insert(1, third_party)
from ply import lex
@@ -73,7 +75,10 @@ LEXTAB = 'lextab'
class BlinkIDLLexer(IDLLexer):
- def __init__(self, debug=False, optimize=True, outputdir=None,
+ def __init__(self,
+ debug=False,
+ optimize=True,
+ outputdir=None,
rewrite_tables=False):
if debug:
# Turn off optimization and caching to help debugging
@@ -103,21 +108,23 @@ class BlinkIDLLexer(IDLLexer):
# error checking), and also allows use of Python's optimized mode.
# See: Optimized Mode
# http://www.dabeaz.com/ply/ply.html#ply_nn15
- self._lexobj = lex.lex(object=self,
- debug=debug,
- optimize=optimize,
- lextab=lextab,
- outputdir=outputdir)
+ self._lexobj = lex.lex(
+ object=self,
+ debug=debug,
+ optimize=optimize,
+ lextab=lextab,
+ outputdir=outputdir)
################################################################################
+
def main(argv):
# If file itself executed, build and cache lex table
try:
outputdir = argv[1]
except IndexError as err:
- print 'Usage: %s OUTPUT_DIR' % argv[0]
+ print('Usage: %s OUTPUT_DIR' % argv[0])
return 1
# Important: rewrite_tables=True causes the cache file to be deleted if it
# exists, thus making sure that PLY doesn't load it instead of regenerating
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py b/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py
index a0c2054f7ff..0361deed5df 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py
@@ -25,7 +25,6 @@
# 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.
-
"""Parser for Blink IDL.
The parser uses the PLY (Python Lex-Yacc) library to build a set of parsing
@@ -55,18 +54,22 @@ http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end
# pylint: disable=E1101
#
+from __future__ import print_function
+
import os.path
import sys
# PLY is in Chromium src/third_party/ply
module_path, module_name = os.path.split(__file__)
-third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir)
+third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir,
+ os.pardir)
# Insert at front to override system libraries, and after path[0] == script dir
sys.path.insert(1, third_party)
from ply import yacc
# Base parser is in Chromium src/tools/idl_parser
-tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'tools')
+tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir,
+ os.pardir, os.pardir, 'tools')
sys.path.append(tools_dir)
from idl_parser.idl_parser import IDLParser # pylint: disable=import-error
from idl_parser.idl_parser import ParseFile as parse_file
@@ -76,16 +79,21 @@ import blink_idl_lexer
class BlinkIDLParser(IDLParser):
- def __init__(self,
- # common parameters
- debug=False,
- # local parameters
- rewrite_tables=False,
- # idl_parser parameters
- lexer=None, verbose=False, mute_error=False,
- # yacc parameters
- outputdir='', optimize=True, write_tables=False,
- picklefile=None):
+ def __init__(
+ self,
+ # common parameters
+ debug=False,
+ # local parameters
+ rewrite_tables=False,
+ # idl_parser parameters
+ lexer=None,
+ verbose=False,
+ mute_error=False,
+ # yacc parameters
+ outputdir='',
+ optimize=True,
+ write_tables=False,
+ picklefile=None):
if debug:
# Turn off optimization and caching, and write out tables,
# to help debugging
@@ -94,16 +102,16 @@ class BlinkIDLParser(IDLParser):
picklefile = None
write_tables = True
if outputdir:
- picklefile = picklefile or os.path.join(outputdir, 'parsetab.pickle')
+ picklefile = picklefile or os.path.join(outputdir,
+ 'parsetab.pickle')
if rewrite_tables:
try:
os.unlink(picklefile)
except OSError:
pass
- lexer = lexer or BlinkIDLLexer(debug=debug,
- outputdir=outputdir,
- optimize=optimize)
+ lexer = lexer or BlinkIDLLexer(
+ debug=debug, outputdir=outputdir, optimize=optimize)
self.lexer = lexer
self.tokens = lexer.KnownTokens()
# Optimized mode substantially decreases startup time (by disabling
@@ -115,11 +123,12 @@ class BlinkIDLParser(IDLParser):
# as we don't need to modify sys.path; virtually identical speed.
# See: CHANGES, Version 3.2
# http://ply.googlecode.com/svn/trunk/CHANGES
- self.yaccobj = yacc.yacc(module=self,
- debug=debug,
- optimize=optimize,
- write_tables=write_tables,
- picklefile=picklefile)
+ self.yaccobj = yacc.yacc(
+ module=self,
+ debug=debug,
+ optimize=optimize,
+ write_tables=write_tables,
+ picklefile=picklefile)
# See IDLParser.__init__() why we set defaulted_states.
self.yaccobj.defaulted_states = {}
self.parse_debug = debug
@@ -134,12 +143,13 @@ class BlinkIDLParser(IDLParser):
################################################################################
+
def main(argv):
# If file itself executed, cache lex/parse tables
try:
outputdir = argv[1]
except IndexError as err:
- print 'Usage: %s OUTPUT_DIR' % argv[0]
+ print('Usage: %s OUTPUT_DIR' % argv[0])
return 1
blink_idl_lexer.main(argv)
# Important: rewrite_tables=True causes the cache file to be deleted if it
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py b/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py
index 309b463dba9..df0719c519e 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py
@@ -3,7 +3,6 @@
# found in the LICENSE file.
# pylint: disable=no-member,relative-import
-
"""Unit tests for blink_idl_parser.py."""
import unittest
@@ -12,7 +11,6 @@ from blink_idl_parser import BlinkIDLParser
class BlinkIDLParserTest(unittest.TestCase):
-
def test_missing_semicolon_between_definitions(self):
# No semicolon after enum definition.
text = '''enum TestEnum { "value" } dictionary TestDictionary {};'''
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py b/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
index a277ddb0ccb..3629e9c51ba 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
@@ -1,7 +1,6 @@
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""
Builds Web IDL database.
@@ -17,11 +16,13 @@ import web_idl
def parse_options():
parser = optparse.OptionParser()
- parser.add_option('--output', type='string',
- help="filepath of the resulting database")
- parser.add_option('--runtime_enabled_features', type='string',
- action='append',
- help="filepath to runtime_enabled_features.json5")
+ parser.add_option(
+ '--output', type='string', help="filepath of the resulting database")
+ parser.add_option(
+ '--runtime_enabled_features',
+ type='string',
+ action='append',
+ help="filepath to runtime_enabled_features.json5")
options, args = parser.parse_args()
required_option_names = ('output', 'runtime_enabled_features')
@@ -47,8 +48,8 @@ def main():
was_error_reported[0] = True
sys.stderr.writelines([message, "\n"])
- database = web_idl.build_database(filepaths=filepaths,
- report_error=report_error)
+ database = web_idl.build_database(
+ filepaths=filepaths, report_error=report_error)
if was_error_reported[0]:
sys.exit("Aborted due to error.")
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py b/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py
index 1905aa85e5a..adbc4876d97 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/code_generator.py
@@ -3,9 +3,10 @@
# found in the LICENSE file.
# pylint: disable=import-error,print-statement,relative-import
-
"""Plumbing for a Jinja-based code generator, including CodeGeneratorBase, a base class for all generators."""
+from __future__ import print_function
+
import os
import posixpath
import re
@@ -17,9 +18,10 @@ from v8_interface import constant_filters
from v8_types import set_component_dirs
from v8_methods import method_filters
from v8_utilities import capitalize
-from utilities import (idl_filename_to_component, is_valid_component_dependency,
- format_remove_duplicates, format_blink_cpp_source_code,
- to_snake_case, normalize_path)
+from utilities import (idl_filename_to_component,
+ is_valid_component_dependency, format_remove_duplicates,
+ format_blink_cpp_source_code, to_snake_case,
+ normalize_path)
import v8_utilities
# Path handling for libraries and templates
@@ -31,10 +33,10 @@ import v8_utilities
# is regenerated, which causes a race condition and breaks concurrent build,
# since some compile processes will try to read the partially written cache.
MODULE_PATH, _ = os.path.split(os.path.realpath(__file__))
-THIRD_PARTY_DIR = os.path.normpath(os.path.join(
- MODULE_PATH, os.pardir, os.pardir, os.pardir, os.pardir))
-TEMPLATES_DIR = os.path.normpath(os.path.join(
- MODULE_PATH, os.pardir, 'templates'))
+THIRD_PARTY_DIR = os.path.normpath(
+ os.path.join(MODULE_PATH, os.pardir, os.pardir, os.pardir, os.pardir))
+TEMPLATES_DIR = os.path.normpath(
+ os.path.join(MODULE_PATH, os.pardir, 'templates'))
# jinja2 is in chromium's third_party directory.
# Insert at 1 so at front to override system libraries, and
@@ -47,15 +49,15 @@ def generate_indented_conditional(code, conditional):
# Indent if statement to level of original code
indent = re.match(' *', code).group(0)
return ('%sif (%s) {\n' % (indent, conditional) +
- ' %s\n' % '\n '.join(code.splitlines()) +
- '%s}\n' % indent)
+ ' %s\n' % '\n '.join(code.splitlines()) + '%s}\n' % indent)
# [Exposed]
def exposed_if(code, exposed_test):
if not exposed_test:
return code
- return generate_indented_conditional(code, 'execution_context && (%s)' % exposed_test)
+ return generate_indented_conditional(
+ code, 'execution_context && (%s)' % exposed_test)
# [SecureContext]
@@ -66,7 +68,9 @@ def secure_context_if(code, secure_context_test):
# [RuntimeEnabled]
-def origin_trial_enabled_if(code, origin_trial_feature_name, execution_context=None):
+def origin_trial_enabled_if(code,
+ origin_trial_feature_name,
+ execution_context=None):
if not origin_trial_feature_name:
return code
@@ -94,14 +98,23 @@ def initialize_jinja_env(cache_dir):
lstrip_blocks=True, # so can indent control flow tags
trim_blocks=True)
jinja_env.filters.update({
- 'blink_capitalize': capitalize,
- 'exposed': exposed_if,
- 'format_blink_cpp_source_code': format_blink_cpp_source_code,
- 'format_remove_duplicates': format_remove_duplicates,
- 'origin_trial_enabled': origin_trial_enabled_if,
- 'runtime_enabled': runtime_enabled_if,
- 'runtime_enabled_function': v8_utilities.runtime_enabled_function,
- 'secure_context': secure_context_if})
+ 'blink_capitalize':
+ capitalize,
+ 'exposed':
+ exposed_if,
+ 'format_blink_cpp_source_code':
+ format_blink_cpp_source_code,
+ 'format_remove_duplicates':
+ format_remove_duplicates,
+ 'origin_trial_enabled':
+ origin_trial_enabled_if,
+ 'runtime_enabled':
+ runtime_enabled_if,
+ 'runtime_enabled_function':
+ v8_utilities.runtime_enabled_function,
+ 'secure_context':
+ secure_context_if
+ })
jinja_env.filters.update(constant_filters())
jinja_env.filters.update(method_filters())
return jinja_env
@@ -109,10 +122,12 @@ def initialize_jinja_env(cache_dir):
_BLINK_RELATIVE_PATH_PREFIXES = ('bindings/', 'core/', 'modules/', 'platform/')
+
def normalize_and_sort_includes(include_paths):
normalized_include_paths = set()
for include_path in include_paths:
- match = re.search(r'/gen/(third_party/blink/.*)$', posixpath.abspath(include_path))
+ match = re.search(r'/gen/(third_party/blink/.*)$',
+ posixpath.abspath(include_path))
if match:
include_path = match.group(1)
elif include_path.startswith(_BLINK_RELATIVE_PATH_PREFIXES):
@@ -133,6 +148,7 @@ def render_template(template, context):
class CodeGeneratorBase(object):
"""Base class for jinja-powered jinja template generation.
"""
+
def __init__(self, generator_name, info_provider, cache_dir, output_dir):
self.generator_name = generator_name
self.info_provider = info_provider
@@ -150,13 +166,19 @@ class CodeGeneratorBase(object):
IdlType.set_dictionaries(interfaces_info['dictionaries'])
IdlType.set_enums(self.info_provider.enumerations)
IdlType.set_callback_functions(self.info_provider.callback_functions)
- IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces'])
- IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces'])
+ IdlType.set_implemented_as_interfaces(
+ interfaces_info['implemented_as_interfaces'])
+ IdlType.set_garbage_collected_types(
+ interfaces_info['garbage_collected_interfaces'])
IdlType.set_garbage_collected_types(interfaces_info['dictionaries'])
set_component_dirs(interfaces_info['component_dirs'])
- def render_templates(self, include_paths, header_template, cpp_template,
- context, component=None):
+ def render_templates(self,
+ include_paths,
+ header_template,
+ cpp_template,
+ context,
+ component=None):
context['code_generator'] = self.generator_name
# Add includes for any dependencies
@@ -167,8 +189,10 @@ class CodeGeneratorBase(object):
includes.add(include_path)
cpp_includes = set(context.get('cpp_includes', []))
- context['cpp_includes'] = normalize_and_sort_includes(cpp_includes | includes)
- context['header_includes'] = normalize_and_sort_includes(context['header_includes'])
+ context['cpp_includes'] = normalize_and_sort_includes(cpp_includes
+ | includes)
+ context['header_includes'] = normalize_and_sort_includes(
+ context['header_includes'])
header_text = render_template(header_template, context)
cpp_text = render_template(cpp_template, context)
@@ -194,14 +218,16 @@ def main(argv):
cache_dir = argv[1]
dummy_filename = argv[2]
except IndexError:
- print 'Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0]
+ print('Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0])
return 1
# Cache templates
jinja_env = initialize_jinja_env(cache_dir)
- template_filenames = [filename for filename in os.listdir(TEMPLATES_DIR)
- # Skip .svn, directories, etc.
- if filename.endswith(('.tmpl', '.txt'))]
+ template_filenames = [
+ filename for filename in os.listdir(TEMPLATES_DIR)
+ # Skip .svn, directories, etc.
+ if filename.endswith(('.tmpl', '.txt'))
+ ]
for template_filename in template_filenames:
jinja_env.get_template(template_filename)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py b/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
index 95564bab6e8..f296d486a3c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
@@ -27,7 +27,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pylint: disable=import-error,print-statement,relative-import
-
"""Generate Blink V8 bindings (.h and .cpp files).
If run itself, caches Jinja templates (and creates dummy file for build,
@@ -61,14 +60,15 @@ import v8_union
from v8_utilities import build_basename, cpp_name
from utilities import idl_filename_to_component, is_testing_target, shorten_union_name, to_header_guard, to_snake_case
-
# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
+
def depending_union_type(idl_type):
"""Returns the union type name if the given idl_type depends on a
union type.
"""
+
def find_base_type(current_type):
if current_type.is_array_or_sequence_type:
return find_base_type(current_type.element_type)
@@ -79,6 +79,7 @@ def depending_union_type(idl_type):
if current_type.is_nullable:
return find_base_type(current_type.inner_type)
return current_type
+
base_type = find_base_type(idl_type)
if base_type.is_union_type:
return base_type
@@ -94,7 +95,7 @@ class TypedefResolver(Visitor):
def resolve(self, definitions, definition_name):
"""Traverse definitions and resolves typedefs with the actual types."""
self.typedefs = {}
- for name, typedef in self.info_provider.typedefs.iteritems():
+ for name, typedef in self.info_provider.typedefs.items():
self.typedefs[name] = typedef.idl_type
self.additional_header_includes = set()
definitions.accept(self)
@@ -122,7 +123,8 @@ class TypedefResolver(Visitor):
union_type = depending_union_type(resolved_idl_type)
if union_type:
self.additional_header_includes.add(
- self.info_provider.include_path_for_union_types(union_type))
+ self.info_provider.include_path_for_union_types(
+ union_type))
# Need to re-assign the attribute, not just mutate idl_type, since
# type(idl_type) may change.
setattr(typed_object, attribute_name, resolved_idl_type)
@@ -135,7 +137,8 @@ class CodeGeneratorV8Base(CodeGeneratorBase):
"""Base class for v8 bindings generator and IDL dictionary impl generator"""
def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir)
+ CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
+ cache_dir, output_dir)
self.typedef_resolver = TypedefResolver(info_provider)
def generate_code(self, definitions, definition_name):
@@ -158,13 +161,16 @@ class CodeGeneratorV8Base(CodeGeneratorBase):
class CodeGeneratorV8(CodeGeneratorV8Base):
def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir)
+ CodeGeneratorV8Base.__init__(self, info_provider, cache_dir,
+ output_dir)
def output_paths(self, definition_name):
- header_path = posixpath.join(self.output_dir, self.get_output_filename(
- definition_name, '.h', prefix='v8_'))
- cpp_path = posixpath.join(self.output_dir, self.get_output_filename(
- definition_name, '.cc', prefix='v8_'))
+ header_path = posixpath.join(
+ self.output_dir,
+ self.get_output_filename(definition_name, '.h', prefix='v8_'))
+ cpp_path = posixpath.join(
+ self.output_dir,
+ self.get_output_filename(definition_name, '.cc', prefix='v8_'))
return header_path, cpp_path
def generate_code_internal(self, definitions, definition_name):
@@ -196,31 +202,39 @@ class CodeGeneratorV8(CodeGeneratorV8Base):
interface_name += 'Partial'
assert component == 'core'
component = 'modules'
- include_paths = interface_info.get('dependencies_other_component_include_paths')
+ include_paths = interface_info.get(
+ 'dependencies_other_component_include_paths')
else:
header_template_filename = 'interface.h.tmpl'
cpp_template_filename = 'interface.cc.tmpl'
interface_context = v8_interface.interface_context
component_info = self.info_provider.component_info
- template_context = interface_context(interface, definitions.interfaces, component_info)
- includes.update(interface_info.get('cpp_includes', {}).get(component, set()))
+ template_context = interface_context(interface, definitions.interfaces,
+ component_info)
+ includes.update(
+ interface_info.get('cpp_includes', {}).get(component, set()))
if not interface.is_partial and not is_testing_target(full_path):
- template_context['header_includes'].add(self.info_provider.include_path_for_export)
- template_context['exported'] = self.info_provider.specifier_for_export
+ template_context['header_includes'].add(
+ self.info_provider.include_path_for_export)
+ template_context['exported'] = \
+ self.info_provider.specifier_for_export
# Add the include for interface itself
if IdlType(interface_name).is_typed_array:
- template_context['header_includes'].add('core/typed_arrays/dom_typed_array.h')
+ template_context['header_includes'].add(
+ 'core/typed_arrays/dom_typed_array.h')
elif interface.is_callback:
pass
else:
- template_context['header_includes'].add(interface_info['include_path'])
+ template_context['header_includes'].add(
+ interface_info['include_path'])
template_context['header_includes'].update(
interface_info.get('additional_header_includes', []))
header_path, cpp_path = self.output_paths(interface_name)
this_include_header_path = self.normalize_this_header_path(header_path)
template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(this_include_header_path)
+ template_context['header_guard'] = to_header_guard(
+ this_include_header_path)
header_template = self.jinja_env.get_template(header_template_filename)
cpp_template = self.jinja_env.get_template(cpp_template_filename)
header_text, cpp_text = self.render_templates(
@@ -245,12 +259,15 @@ class CodeGeneratorV8(CodeGeneratorV8Base):
# Add the include for interface itself
template_context['header_includes'].add(interface_info['include_path'])
if not is_testing_target(interface_info.get('full_path')):
- template_context['header_includes'].add(self.info_provider.include_path_for_export)
- template_context['exported'] = self.info_provider.specifier_for_export
+ template_context['header_includes'].add(
+ self.info_provider.include_path_for_export)
+ template_context['exported'] = \
+ self.info_provider.specifier_for_export
header_path, cpp_path = self.output_paths(dictionary_name)
this_include_header_path = self.normalize_this_header_path(header_path)
template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(this_include_header_path)
+ template_context['header_guard'] = to_header_guard(
+ this_include_header_path)
header_text, cpp_text = self.render_templates(
include_paths, header_template, cpp_template, template_context)
return (
@@ -261,15 +278,16 @@ class CodeGeneratorV8(CodeGeneratorV8Base):
class CodeGeneratorDictionaryImpl(CodeGeneratorV8Base):
def __init__(self, info_provider, cache_dir, output_dir):
- CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir)
+ CodeGeneratorV8Base.__init__(self, info_provider, cache_dir,
+ output_dir)
def output_paths(self, definition_name, interface_info):
output_dir = posixpath.join(self.output_dir,
interface_info['relative_dir'])
- header_path = posixpath.join(output_dir,
- self.get_output_filename(definition_name, '.h'))
- cpp_path = posixpath.join(output_dir,
- self.get_output_filename(definition_name, '.cc'))
+ header_path = posixpath.join(
+ output_dir, self.get_output_filename(definition_name, '.h'))
+ cpp_path = posixpath.join(
+ output_dir, self.get_output_filename(definition_name, '.cc'))
return header_path, cpp_path
def generate_code_internal(self, definitions, definition_name):
@@ -284,14 +302,18 @@ class CodeGeneratorDictionaryImpl(CodeGeneratorV8Base):
dictionary, interfaces_info)
include_paths = interface_info.get('dependencies_include_paths')
if not is_testing_target(interface_info.get('full_path')):
- template_context['exported'] = self.info_provider.specifier_for_export
- template_context['header_includes'].add(self.info_provider.include_path_for_export)
+ template_context['exported'] = \
+ self.info_provider.specifier_for_export
+ template_context['header_includes'].add(
+ self.info_provider.include_path_for_export)
template_context['header_includes'].update(
interface_info.get('additional_header_includes', []))
- header_path, cpp_path = self.output_paths(definition_name, interface_info)
+ header_path, cpp_path = self.output_paths(definition_name,
+ interface_info)
this_include_header_path = self.normalize_this_header_path(header_path)
template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(this_include_header_path)
+ template_context['header_guard'] = to_header_guard(
+ this_include_header_path)
header_text, cpp_text = self.render_templates(
include_paths, header_template, cpp_template, template_context)
return (
@@ -306,15 +328,17 @@ class CodeGeneratorUnionType(CodeGeneratorBase):
CodeGeneratorDictionaryImpl. It assumes that all union types are already
collected. It doesn't process idl files directly.
"""
+
def __init__(self, info_provider, cache_dir, output_dir, target_component):
- CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir)
+ CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
+ cache_dir, output_dir)
self.target_component = target_component
# The code below duplicates parts of TypedefResolver. We do not use it
# directly because IdlUnionType is not a type defined in
# idl_definitions.py. What we do instead is to resolve typedefs in
# _generate_container_code() whenever a new union file is generated.
self.typedefs = {}
- for name, typedef in self.info_provider.typedefs.iteritems():
+ for name, typedef in self.info_provider.typedefs.items():
self.typedefs[name] = typedef.idl_type
def _generate_container_code(self, union_type):
@@ -322,7 +346,8 @@ class CodeGeneratorUnionType(CodeGeneratorBase):
union_type = union_type.resolve_typedefs(self.typedefs)
header_template = self.jinja_env.get_template('union_container.h.tmpl')
cpp_template = self.jinja_env.get_template('union_container.cc.tmpl')
- template_context = v8_union.container_context(union_type, self.info_provider)
+ template_context = v8_union.container_context(union_type,
+ self.info_provider)
template_context['header_includes'].append(
self.info_provider.include_path_for_export)
template_context['exported'] = self.info_provider.specifier_for_export
@@ -331,7 +356,8 @@ class CodeGeneratorUnionType(CodeGeneratorBase):
cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
this_include_header_path = self.normalize_this_header_path(header_path)
template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(this_include_header_path)
+ template_context['header_guard'] = to_header_guard(
+ this_include_header_path)
header_text, cpp_text = self.render_templates(
[], header_template, cpp_template, template_context)
return (
@@ -368,18 +394,22 @@ class CodeGeneratorUnionType(CodeGeneratorBase):
class CodeGeneratorCallbackFunction(CodeGeneratorBase):
def __init__(self, info_provider, cache_dir, output_dir, target_component):
- CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir)
+ CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
+ cache_dir, output_dir)
self.target_component = target_component
self.typedef_resolver = TypedefResolver(info_provider)
def generate_code_internal(self, callback_function, path):
- self.typedef_resolver.resolve(callback_function, callback_function.name)
- header_template = self.jinja_env.get_template('callback_function.h.tmpl')
+ self.typedef_resolver.resolve(callback_function,
+ callback_function.name)
+ header_template = self.jinja_env.get_template(
+ 'callback_function.h.tmpl')
cpp_template = self.jinja_env.get_template('callback_function.cc.tmpl')
template_context = v8_callback_function.callback_function_context(
callback_function)
if not is_testing_target(path):
- template_context['exported'] = self.info_provider.specifier_for_export
+ template_context['exported'] = \
+ self.info_provider.specifier_for_export
template_context['header_includes'].append(
self.info_provider.include_path_for_export)
@@ -388,14 +418,16 @@ class CodeGeneratorCallbackFunction(CodeGeneratorBase):
for argument in callback_function.arguments:
if argument.idl_type.is_union_type:
template_context['header_includes'].append(
- self.info_provider.include_path_for_union_types(argument.idl_type))
+ self.info_provider.include_path_for_union_types(
+ argument.idl_type))
snake_base_name = to_snake_case('V8%s' % callback_function.name)
header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
this_include_header_path = self.normalize_this_header_path(header_path)
template_context['this_include_header_path'] = this_include_header_path
- template_context['header_guard'] = to_header_guard(this_include_header_path)
+ template_context['header_guard'] = to_header_guard(
+ this_include_header_path)
header_text, cpp_text = self.render_templates(
[], header_template, cpp_template, template_context)
return (
@@ -409,12 +441,13 @@ class CodeGeneratorCallbackFunction(CodeGeneratorBase):
if not callback_functions:
return ()
outputs = set()
- for callback_function_dict in callback_functions.itervalues():
+ for callback_function_dict in callback_functions.values():
if callback_function_dict['component_dir'] != self.target_component:
continue
callback_function = callback_function_dict['callback_function']
if 'Custom' in callback_function.extended_attributes:
continue
path = callback_function_dict['full_path']
- outputs.update(self.generate_code_internal(callback_function, path))
+ outputs.update(
+ self.generate_code_internal(callback_function, path))
return outputs
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py b/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
index c6922e536fc..082a545fc51 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
@@ -1,7 +1,6 @@
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""
Collects Web IDL definitions in IDL files into a Python object per Blink
component.
@@ -16,18 +15,21 @@ import blink_idl_parser
import utilities
import web_idl
-
_VALID_COMPONENTS = ('core', 'modules')
def parse_options():
parser = optparse.OptionParser()
- parser.add_option('--idl-list-file', type='string',
- help="a file path which lists IDL file paths to process")
- parser.add_option('--component', type='choice', choices=_VALID_COMPONENTS,
- help="specify a component name")
- parser.add_option('--output', type='string',
- help="the output file path")
+ parser.add_option(
+ '--idl-list-file',
+ type='string',
+ help="a file path which lists IDL file paths to process")
+ parser.add_option(
+ '--component',
+ type='choice',
+ choices=_VALID_COMPONENTS,
+ help="specify a component name")
+ parser.add_option('--output', type='string', help="the output file path")
options, args = parser.parse_args()
if options.idl_list_file is None:
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py b/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
index 78d74f825be..7fa1c022a15 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
@@ -3,7 +3,6 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Compute global objects.
Global objects are defined by interfaces with [Global] on
@@ -30,13 +29,16 @@ def parse_options():
usage = 'Usage: %prog [options] [GlobalObjects.pickle]'
parser = optparse.OptionParser(usage=usage)
parser.add_option('--idl-files-list', help='file listing IDL files')
- parser.add_option('--global-objects-component-files', action='append',
- help='optionally preceeded input pickle filename.')
+ parser.add_option(
+ '--global-objects-component-files',
+ action='append',
+ help='optionally preceeded input pickle filename.')
options, args = parser.parse_args()
if options.idl_files_list is None:
- parser.error('Must specify a file listing IDL files using --idl-files-list.')
+ parser.error(
+ 'Must specify a file listing IDL files using --idl-files-list.')
if options.global_objects_component_files is None:
options.global_objects_component_files = []
if len(args) != 1:
@@ -46,7 +48,7 @@ def parse_options():
def dict_union(dicts):
- return dict((k, v) for d in dicts for k, v in d.iteritems())
+ return dict((k, v) for d in dicts for k, v in d.items())
def idl_file_to_global_names(idl_filename):
@@ -58,22 +60,25 @@ def idl_file_to_global_names(idl_filename):
"""
full_path = os.path.realpath(idl_filename)
idl_file_contents = get_file_contents(full_path)
- extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
+ extended_attributes = get_interface_extended_attributes_from_idl(
+ idl_file_contents)
interface_name = get_first_interface_name_from_idl(idl_file_contents)
if 'Global' not in extended_attributes:
return
global_value = extended_attributes['Global']
if not global_value:
- raise ValueError('[Global] must take an indentifier or an identifier list.\n' +
- full_path)
+ raise ValueError(
+ '[Global] must take an indentifier or an identifier list.\n' +
+ full_path)
return map(str.strip, global_value.strip('()').split(','))
def idl_files_to_interface_name_global_names(idl_files):
"""Yields pairs (interface_name, global_names) found in IDL files."""
for idl_filename in idl_files:
- interface_name = get_first_interface_name_from_idl(get_file_contents(idl_filename))
+ interface_name = get_first_interface_name_from_idl(
+ get_file_contents(idl_filename))
global_names = idl_file_to_global_names(idl_filename)
if global_names:
yield interface_name, global_names
@@ -81,19 +86,20 @@ def idl_files_to_interface_name_global_names(idl_files):
################################################################################
+
def main():
options, args = parse_options()
output_global_objects_filename = args.pop()
interface_name_global_names = dict_union(
existing_interface_name_global_names
- for existing_interface_name_global_names
- in read_pickle_files(options.global_objects_component_files))
+ for existing_interface_name_global_names in read_pickle_files(
+ options.global_objects_component_files))
# File paths of input IDL files are passed in a file, which is generated at
# GN time. It is OK because the target IDL files themselves are static.
idl_files = read_file_to_list(options.idl_files_list)
interface_name_global_names.update(
- idl_files_to_interface_name_global_names(idl_files))
+ idl_files_to_interface_name_global_names(idl_files))
write_pickle_file(output_global_objects_filename,
interface_name_global_names)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py b/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
index 4930013a526..01c23ba15f7 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
@@ -27,7 +27,6 @@
# 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.
-
"""Compute global interface information for individual IDL files.
Auxiliary module for compute_interfaces_info_overall, which consolidates
@@ -58,7 +57,6 @@ from utilities import to_snake_case
from utilities import read_pickle_file
from utilities import write_pickle_file
-
module_path = os.path.dirname(__file__)
source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
gen_path = os.path.join('gen', 'blink')
@@ -74,15 +72,21 @@ def parse_options():
parser = optparse.OptionParser(usage=usage)
parser.add_option('--cache-directory', help='cache directory')
parser.add_option('--idl-files-list', help='file listing IDL files')
- parser.add_option('--interfaces-info-file', help='interface info pickle file')
- parser.add_option('--component-info-file', help='component wide info pickle file')
- parser.add_option('--runtime-enabled-features-file', help='runtime-enabled features pickle file')
+ parser.add_option(
+ '--interfaces-info-file', help='interface info pickle file')
+ parser.add_option(
+ '--component-info-file', help='component wide info pickle file')
+ parser.add_option(
+ '--runtime-enabled-features-file',
+ help='runtime-enabled features pickle file')
options, args = parser.parse_args()
if options.interfaces_info_file is None:
- parser.error('Must specify an output file using --interfaces-info-file.')
+ parser.error(
+ 'Must specify an output file using --interfaces-info-file.')
if options.idl_files_list is None:
- parser.error('Must specify a file listing IDL files using --idl-files-list.')
+ parser.error(
+ 'Must specify a file listing IDL files using --idl-files-list.')
return options, args
@@ -90,6 +94,7 @@ def parse_options():
# Computations
################################################################################
+
def relative_dir_posix(idl_filename, base_path):
"""Returns relative path to the directory of idl_file in POSIX format."""
relative_path_local = os.path.relpath(idl_filename, base_path)
@@ -109,7 +114,8 @@ def include_path(idl_filename, implemented_as=None):
relative_dir = relative_dir_posix(idl_filename, source_path)
# IDL file basename is used even if only a partial interface file
- output_file_basename = implemented_as or idl_filename_to_basename(idl_filename)
+ output_file_basename = implemented_as or idl_filename_to_basename(
+ idl_filename)
output_file_basename = to_snake_case(output_file_basename)
return posixpath.join(relative_dir, output_file_basename + '.h')
@@ -133,9 +139,9 @@ def get_includes_from_definitions(definitions, definition_name):
def get_put_forward_interfaces_from_definition(definition):
- return sorted(set(attribute.idl_type.base_type
- for attribute in definition.attributes
- if 'PutForwards' in attribute.extended_attributes))
+ return sorted(
+ set(attribute.idl_type.base_type for attribute in definition.attributes
+ if 'PutForwards' in attribute.extended_attributes))
def get_unforgeable_attributes_from_definition(definition):
@@ -145,6 +151,7 @@ def get_unforgeable_attributes_from_definition(definition):
def collect_union_types_from_definitions(definitions):
"""Traverse definitions and collect all union types."""
+
class UnionTypeCollector(Visitor):
def collect(self, definitions):
self._union_types = set()
@@ -165,13 +172,14 @@ def collect_union_types_from_definitions(definitions):
class InterfaceInfoCollector(object):
"""A class that collects interface information from idl files."""
+
def __init__(self, cache_directory=None):
- self.reader = IdlReader(interfaces_info=None, outputdir=cache_directory)
+ self.reader = IdlReader(
+ interfaces_info=None, outputdir=cache_directory)
self.interfaces_info = {}
self.partial_interface_files = defaultdict(lambda: {
'full_paths': [],
- 'include_paths': [],
- })
+ 'include_paths': [], })
self.enumerations = {}
self.union_types = set()
self.typedefs = {}
@@ -196,6 +204,7 @@ class InterfaceInfoCollector(object):
def collect_info(self, idl_filename):
"""Reads an idl file and collects information which is required by the
binding code generation."""
+
def collect_unforgeable_attributes(definition, idl_filename):
"""Collects [Unforgeable] attributes so that we can define them on
sub-interfaces later. The resulting structure is as follows.
@@ -205,17 +214,21 @@ class InterfaceInfoCollector(object):
}
"""
interface_info = {}
- unforgeable_attributes = get_unforgeable_attributes_from_definition(definition)
+ unforgeable_attributes = get_unforgeable_attributes_from_definition(
+ definition)
if not unforgeable_attributes:
return interface_info
if definition.is_partial:
- interface_basename = idl_filename_to_interface_name(idl_filename)
+ interface_basename = idl_filename_to_interface_name(
+ idl_filename)
# TODO(yukishiino): [PartialInterfaceImplementedAs] is treated
# in interface_dependency_resolver.transfer_extended_attributes.
# Come up with a better way to keep them consistent.
for attr in unforgeable_attributes:
- attr.extended_attributes['PartialInterfaceImplementedAs'] = definition.extended_attributes.get('ImplementedAs', interface_basename)
+ attr.extended_attributes[
+ 'PartialInterfaceImplementedAs'] = definition.extended_attributes.get(
+ 'ImplementedAs', interface_basename)
interface_info['unforgeable_attributes'] = unforgeable_attributes
return interface_info
@@ -224,7 +237,8 @@ class InterfaceInfoCollector(object):
this_union_types = collect_union_types_from_definitions(definitions)
self.union_types.update(this_union_types)
self.typedefs.update(definitions.typedefs)
- for callback_function_name, callback_function in definitions.callback_functions.iteritems():
+ for callback_function_name, callback_function in \
+ definitions.callback_functions.items():
# Set 'component_dir' to specify a directory that callback function files belong to
self.callback_functions[callback_function_name] = {
'callback_function': callback_function,
@@ -239,10 +253,12 @@ class InterfaceInfoCollector(object):
self.enumerations.update(definitions.enumerations)
if definitions.interfaces:
- definition = next(definitions.interfaces.itervalues())
+ definition = next(iter(definitions.interfaces.values()))
interface_info = {
- 'is_callback_interface': definition.is_callback,
- 'is_dictionary': False,
+ 'is_callback_interface':
+ definition.is_callback,
+ 'is_dictionary':
+ False,
# Interfaces that are referenced (used as types) and that we
# introspect during code generation (beyond interface-level
# data ([ImplementedAs], is_callback_interface, ancestors, and
@@ -250,10 +266,11 @@ class InterfaceInfoCollector(object):
# These cause rebuilds of referrers, due to the dependency,
# so these should be minimized; currently only targets of
# [PutForwards].
- 'referenced_interfaces': get_put_forward_interfaces_from_definition(definition),
+ 'referenced_interfaces':
+ get_put_forward_interfaces_from_definition(definition),
}
elif definitions.dictionaries:
- definition = next(definitions.dictionaries.itervalues())
+ definition = next(iter(definitions.dictionaries.values()))
interface_info = {
'is_callback_interface': False,
'is_dictionary': True,
@@ -267,8 +284,9 @@ class InterfaceInfoCollector(object):
# Remember [Unforgeable] attributes.
if definitions.interfaces:
- merge_dict_recursively(self.interfaces_info[definition.name],
- collect_unforgeable_attributes(definition, idl_filename))
+ merge_dict_recursively(
+ self.interfaces_info[definition.name],
+ collect_unforgeable_attributes(definition, idl_filename))
component = idl_filename_to_component(idl_filename)
extended_attributes = definition.extended_attributes
@@ -284,7 +302,8 @@ class InterfaceInfoCollector(object):
partial_include_paths = []
if this_include_path:
partial_include_paths.append(this_include_path)
- self.add_paths_to_partials_dict(definition.name, full_path, partial_include_paths)
+ self.add_paths_to_partials_dict(definition.name, full_path,
+ partial_include_paths)
# Collects C++ header paths which should be included from generated
# .cpp files. The resulting structure is as follows.
# interfaces_info[interface_name] = {
@@ -297,7 +316,9 @@ class InterfaceInfoCollector(object):
if this_include_path:
merge_dict_recursively(
self.interfaces_info[definition.name],
- {'cpp_includes': {component: set([this_include_path])}})
+ {'cpp_includes': {
+ component: set([this_include_path])
+ }})
return
# 'includes' statements can be included in either the file for the
@@ -307,20 +328,31 @@ class InterfaceInfoCollector(object):
definitions, definition.name)
interface_info.update({
- 'extended_attributes': extended_attributes,
- 'full_path': full_path,
- 'union_types': this_union_types,
- 'implemented_as': implemented_as,
- 'included_by_interfaces': includes_interfaces,
- 'including_mixins': includes_mixins,
- 'include_path': this_include_path,
- # FIXME: temporary private field, while removing old treatement of
- # 'implements': http://crbug.com/360435
- 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
- 'parent': definition.parent,
- 'relative_dir': relative_dir_posix(idl_filename, source_path),
+ 'extended_attributes':
+ extended_attributes,
+ 'full_path':
+ full_path,
+ 'union_types':
+ this_union_types,
+ 'implemented_as':
+ implemented_as,
+ 'included_by_interfaces':
+ includes_interfaces,
+ 'including_mixins':
+ includes_mixins,
+ 'include_path':
+ this_include_path,
+ # FIXME: temporary private field, while removing old
+ # treatement of 'implements': http://crbug.com/360435
+ 'is_legacy_treat_as_partial_interface':
+ 'LegacyTreatAsPartialInterface' in extended_attributes,
+ 'parent':
+ definition.parent,
+ 'relative_dir':
+ relative_dir_posix(idl_filename, source_path),
})
- merge_dict_recursively(self.interfaces_info[definition.name], interface_info)
+ merge_dict_recursively(self.interfaces_info[definition.name],
+ interface_info)
def get_info_as_dict(self):
"""Returns info packaged as a dict."""
@@ -334,17 +366,23 @@ class InterfaceInfoCollector(object):
def get_component_info_as_dict(self, runtime_enabled_features):
"""Returns component wide information as a dict."""
return {
- 'callback_functions': self.callback_functions,
- 'enumerations': dict((enum.name, enum.values)
- for enum in self.enumerations.values()),
- 'runtime_enabled_features': runtime_enabled_features,
- 'typedefs': self.typedefs,
- 'union_types': self.union_types,
+ 'callback_functions':
+ self.callback_functions,
+ 'enumerations':
+ dict((enum.name, enum.values)
+ for enum in self.enumerations.values()),
+ 'runtime_enabled_features':
+ runtime_enabled_features,
+ 'typedefs':
+ self.typedefs,
+ 'union_types':
+ self.union_types,
}
################################################################################
+
def main():
options, _ = parse_options()
@@ -360,9 +398,12 @@ def main():
write_pickle_file(options.interfaces_info_file,
info_collector.get_info_as_dict())
- runtime_enabled_features = read_pickle_file(options.runtime_enabled_features_file)
- write_pickle_file(options.component_info_file,
- info_collector.get_component_info_as_dict(runtime_enabled_features))
+ runtime_enabled_features = read_pickle_file(
+ options.runtime_enabled_features_file)
+ write_pickle_file(
+ options.component_info_file,
+ info_collector.get_component_info_as_dict(runtime_enabled_features))
+
if __name__ == '__main__':
sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py b/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py
index a3e0484a1f8..235cf0f914a 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py
@@ -27,7 +27,6 @@
# 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.
-
"""Compute global interface information, including public information, dependencies, and inheritance.
Computed data is stored in a global variable, |interfaces_info|, and written as
@@ -104,10 +103,11 @@ interfaces_info = {}
# Auxiliary variables (not visible to future build steps)
partial_interface_files = defaultdict(lambda: {
'full_paths': [],
- 'include_paths': [],
-})
+ 'include_paths': [], })
parent_interfaces = {}
-inherited_extended_attributes_by_interface = {} # interface name -> extended attributes
+
+# interface name -> extended attributes
+inherited_extended_attributes_by_interface = {}
class IdlInterfaceFileNotFoundError(Exception):
@@ -127,12 +127,12 @@ def dict_of_dicts_of_lists_update_or_append(existing, other):
Needed for merging partial_interface_files across components.
"""
- for key, value in other.iteritems():
+ for key, value in other.items():
if key not in existing:
existing[key] = value
continue
existing_value = existing[key]
- for inner_key, inner_value in value.iteritems():
+ for inner_key, inner_value in value.items():
existing_value[inner_key].extend(inner_value)
@@ -140,25 +140,33 @@ def dict_of_dicts_of_lists_update_or_append(existing, other):
# Computations
################################################################################
+
def compute_inheritance_info(interface_name):
- """Compute inheritance information, namely ancestors and inherited extended attributes."""
+ """Compute inheritance information, namely ancestors and inherited
+ extended attributes.
+ """
+
def generate_ancestors(interface_name):
while interface_name in parent_interfaces:
interface_name = parent_interfaces[interface_name]
yield interface_name
ancestors = list(generate_ancestors(interface_name))
- inherited_extended_attributes = inherited_extended_attributes_by_interface[interface_name]
+ inherited_extended_attributes = \
+ inherited_extended_attributes_by_interface[interface_name]
for ancestor in ancestors:
# Ancestors may not be present, notably if an ancestor is a generated
# IDL file and we are running this script from run_bindings_tests.py,
# where we don't generate these files.
- ancestor_extended_attributes = inherited_extended_attributes_by_interface.get(ancestor, {})
+ ancestor_extended_attributes = \
+ inherited_extended_attributes_by_interface.get(ancestor, {})
inherited_extended_attributes.update(ancestor_extended_attributes)
interfaces_info[interface_name].update({
- 'ancestors': ancestors,
- 'inherited_extended_attributes': inherited_extended_attributes,
+ 'ancestors':
+ ancestors,
+ 'inherited_extended_attributes':
+ inherited_extended_attributes,
})
@@ -170,8 +178,9 @@ def compute_global_type_info():
garbage_collected_interfaces = set()
callback_interfaces = set()
- for interface_name, interface_info in interfaces_info.iteritems():
- component_dirs[interface_name] = idl_filename_to_component(interface_info['full_path'])
+ for interface_name, interface_info in interfaces_info.items():
+ component_dirs[interface_name] = idl_filename_to_component(
+ interface_info['full_path'])
if interface_info['ancestors']:
ancestors[interface_name] = interface_info['ancestors']
@@ -180,16 +189,19 @@ def compute_global_type_info():
if interface_info['is_dictionary']:
dictionaries[interface_name] = interface_info['is_dictionary']
if interface_info['implemented_as']:
- implemented_as_interfaces[interface_name] = interface_info['implemented_as']
+ implemented_as_interfaces[interface_name] = \
+ interface_info['implemented_as']
- inherited_extended_attributes = interface_info['inherited_extended_attributes']
+ inherited_extended_attributes = \
+ interface_info['inherited_extended_attributes']
garbage_collected_interfaces.add(interface_name)
interfaces_info['ancestors'] = ancestors
interfaces_info['callback_interfaces'] = callback_interfaces
interfaces_info['dictionaries'] = dictionaries
interfaces_info['implemented_as_interfaces'] = implemented_as_interfaces
- interfaces_info['garbage_collected_interfaces'] = garbage_collected_interfaces
+ interfaces_info['garbage_collected_interfaces'] = \
+ garbage_collected_interfaces
interfaces_info['component_dirs'] = component_dirs
@@ -205,15 +217,14 @@ def compute_interfaces_info_overall(info_individuals):
# partial interfaces are used to *extend* interfaces.
# We thus need to update or append if already present
dict_of_dicts_of_lists_update_or_append(
- partial_interface_files, info['partial_interface_files'])
+ partial_interface_files, info['partial_interface_files'])
# Record inheritance information individually
- for interface_name, interface_info in interfaces_info.iteritems():
+ for interface_name, interface_info in interfaces_info.items():
extended_attributes = interface_info['extended_attributes']
inherited_extended_attributes_by_interface[interface_name] = dict(
- (key, value)
- for key, value in extended_attributes.iteritems()
- if key in INHERITED_EXTENDED_ATTRIBUTES)
+ (key, value) for key, value in extended_attributes.items()
+ if key in INHERITED_EXTENDED_ATTRIBUTES)
parent = interface_info['parent']
if parent:
parent_interfaces[interface_name] = parent
@@ -230,26 +241,32 @@ def compute_interfaces_info_overall(info_individuals):
# 'includes').
# Note that moving an 'includes' statement between files does not change the
# info itself (or hence cause a rebuild)!
- for mixin_name, interface_info in interfaces_info.iteritems():
+ for mixin_name, interface_info in interfaces_info.items():
for interface_name in interface_info['included_by_interfaces']:
- interfaces_info[interface_name]['including_mixins'].append(mixin_name)
+ interfaces_info[interface_name]['including_mixins'].append(
+ mixin_name)
del interface_info['included_by_interfaces']
# An IDL file's dependencies are partial interface files that extend it,
# and files for other interfaces that this interfaces include.
- for interface_name, interface_info in interfaces_info.iteritems():
+ for interface_name, interface_info in interfaces_info.items():
partial_interface_paths = partial_interface_files[interface_name]
partial_interfaces_full_paths = partial_interface_paths['full_paths']
# Partial interface definitions each need an include, as they are
# implemented in separate classes from the main interface.
- partial_interfaces_include_paths = partial_interface_paths['include_paths']
+ partial_interfaces_include_paths = \
+ partial_interface_paths['include_paths']
mixins = interface_info['including_mixins']
try:
mixins_info = [interfaces_info[mixin] for mixin in mixins]
except KeyError as key_name:
- raise IdlInterfaceFileNotFoundError('Could not find the IDL file where the following mixin is defined: %s' % key_name)
- mixins_full_paths = [mixin_info['full_path'] for mixin_info in mixins_info]
+ raise IdlInterfaceFileNotFoundError(
+ 'Could not find the IDL file where the following mixin is defined: %s'
+ % key_name)
+ mixins_full_paths = [
+ mixin_info['full_path'] for mixin_info in mixins_info
+ ]
# Mixins don't need include files, as this is handled in the Blink
# implementation (they are implemented on |impl| itself, hence header
# declaration is included in the interface class).
@@ -258,7 +275,8 @@ def compute_interfaces_info_overall(info_individuals):
# https://crbug.com/360435
mixins_include_paths = [
mixin_info['include_path'] for mixin_info in mixins_info
- if mixin_info['is_legacy_treat_as_partial_interface']]
+ if mixin_info['is_legacy_treat_as_partial_interface']
+ ]
dependencies_full_paths = mixins_full_paths
dependencies_include_paths = mixins_include_paths
@@ -274,23 +292,26 @@ def compute_interfaces_info_overall(info_individuals):
dependencies_other_component_full_paths.append(full_path)
for include_path in partial_interfaces_include_paths:
- partial_interface_component = idl_filename_to_component(include_path)
+ partial_interface_component = idl_filename_to_component(
+ include_path)
if component == partial_interface_component:
dependencies_include_paths.append(include_path)
else:
dependencies_other_component_include_paths.append(include_path)
interface_info.update({
- 'dependencies_full_paths': dependencies_full_paths,
- 'dependencies_include_paths': dependencies_include_paths,
+ 'dependencies_full_paths':
+ dependencies_full_paths,
+ 'dependencies_include_paths':
+ dependencies_include_paths,
'dependencies_other_component_full_paths':
- dependencies_other_component_full_paths,
+ dependencies_other_component_full_paths,
'dependencies_other_component_include_paths':
- dependencies_other_component_include_paths,
+ dependencies_other_component_include_paths,
})
# Clean up temporary private information
- for interface_info in interfaces_info.itervalues():
+ for interface_info in interfaces_info.values():
del interface_info['extended_attributes']
del interface_info['union_types']
del interface_info['is_legacy_treat_as_partial_interface']
@@ -302,6 +323,7 @@ def compute_interfaces_info_overall(info_individuals):
################################################################################
+
def main():
_, args = parse_options()
# args = Input1, Input2, ..., Output
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
index 71bfb0383b4..51c66c38c5e 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
@@ -1,7 +1,6 @@
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""
Runs the bindings code generator for the given tasks.
"""
@@ -9,22 +8,40 @@ Runs the bindings code generator for the given tasks.
import optparse
import sys
-import bind_gen
import web_idl
+import bind_gen
def parse_options():
parser = optparse.OptionParser(usage="%prog [options] TASK...")
- parser.add_option('--web_idl_database', type='string',
- help="filepath of the input database")
- parser.add_option('--output_dir_core', type='string',
- help="outout directory for 'core' component")
- parser.add_option('--output_dir_modules', type='string',
- help="outout directory for 'modules' component")
+ parser.add_option(
+ "--web_idl_database",
+ type="string",
+ help="filepath of the input database")
+ parser.add_option(
+ "--root_src_dir",
+ type="string",
+ help='root directory of chromium project, i.e. "//"')
+ parser.add_option(
+ "--root_gen_dir",
+ type="string",
+ help='root directory of generated code files, i.e. '
+ '"//out/Default/gen"')
+ parser.add_option(
+ "--output_core_reldir",
+ type="string",
+ help='output directory for "core" component relative to '
+ 'root_gen_dir')
+ parser.add_option(
+ "--output_modules_reldir",
+ type="string",
+ help='output directory for "modules" component relative '
+ 'to root_gen_dir')
options, args = parser.parse_args()
- required_option_names = (
- 'web_idl_database', 'output_dir_core', 'output_dir_modules')
+ required_option_names = ("web_idl_database", "root_src_dir",
+ "root_gen_dir", "output_core_reldir",
+ "output_modules_reldir")
for opt_name in required_option_names:
if getattr(options, opt_name) is None:
parser.error("--{} is a required option.".format(opt_name))
@@ -40,24 +57,29 @@ def main():
dispatch_table = {
'dictionary': bind_gen.generate_dictionaries,
+ 'enumeration': bind_gen.generate_enumerations,
'interface': bind_gen.generate_interfaces,
+ 'union': bind_gen.generate_unions,
}
for task in tasks:
if task not in dispatch_table:
sys.exit("Unknown task: {}".format(task))
- web_idl_database = web_idl.Database.read_from_file(options.web_idl_database)
- output_dirs = {
- web_idl.Component('core'): options.output_dir_core,
- web_idl.Component('modules'): options.output_dir_modules,
+ web_idl_database = web_idl.Database.read_from_file(
+ options.web_idl_database)
+ component_reldirs = {
+ web_idl.Component('core'): options.output_core_reldir,
+ web_idl.Component('modules'): options.output_modules_reldir,
}
- bind_gen.init(output_dirs)
+ bind_gen.init(
+ root_src_dir=options.root_src_dir,
+ root_gen_dir=options.root_gen_dir,
+ component_reldirs=component_reldirs)
for task in tasks:
- dispatch_table[task](web_idl_database=web_idl_database,
- output_dirs=output_dirs)
+ dispatch_table[task](web_idl_database=web_idl_database)
if __name__ == '__main__':
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
index c4edf6a2c2a..e2b7256dbb0 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
@@ -10,7 +10,6 @@
../../../../mako/mako/ext/__init__.py
../../../../mako/mako/filters.py
../../../../mako/mako/lexer.py
-../../../../mako/mako/lookup.py
../../../../mako/mako/parsetree.py
../../../../mako/mako/pygen.py
../../../../mako/mako/pyparser.py
@@ -31,18 +30,21 @@
../../build/scripts/blinkbuild/name_style_converter.py
bind_gen/__init__.py
bind_gen/blink_v8_bridge.py
-bind_gen/clang_format.py
bind_gen/code_node.py
+bind_gen/code_node_cxx.py
bind_gen/codegen_accumulator.py
bind_gen/codegen_context.py
bind_gen/codegen_expr.py
bind_gen/codegen_format.py
bind_gen/codegen_utils.py
bind_gen/dictionary.py
+bind_gen/enumeration.py
bind_gen/interface.py
bind_gen/mako_renderer.py
bind_gen/name_style.py
bind_gen/path_manager.py
+bind_gen/style_format.py
+bind_gen/union.py
generate_bindings.py
web_idl/__init__.py
web_idl/argument.py
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py
index 62cee43cf39..32120e11e65 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py
@@ -27,7 +27,6 @@
# 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.
-
"""Generate event interfaces .json5 file (EventInterfaces.json5).
The event interfaces .json5 file contains a list of all Event interfaces, i.e.,
@@ -54,21 +53,29 @@ EXPORTED_EXTENDED_ATTRIBUTES = (
'RuntimeEnabled',
)
module_path = os.path.dirname(os.path.realpath(__file__))
-REPO_ROOT_DIR = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir,
- os.pardir, os.pardir, os.pardir))
+REPO_ROOT_DIR = os.path.normpath(
+ os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir,
+ os.pardir))
def parse_options():
parser = OptionParser()
- parser.add_option('--event-idl-files-list', help='file listing event IDL files')
+ parser.add_option(
+ '--event-idl-files-list', help='file listing event IDL files')
parser.add_option('--event-interfaces-file', help='output file')
- parser.add_option('--suffix', help='specify a suffix to the namespace, i.e., "Modules". Default is None.')
+ parser.add_option(
+ '--suffix',
+ help=
+ 'specify a suffix to the namespace, i.e., "Modules". Default is None.')
options, args = parser.parse_args()
if options.event_idl_files_list is None:
- parser.error('Must specify a file listing event IDL files using --event-idl-files-list.')
+ parser.error(
+ 'Must specify a file listing event IDL files using --event-idl-files-list.'
+ )
if options.event_interfaces_file is None:
- parser.error('Must specify an output file using --event-interfaces-file.')
+ parser.error(
+ 'Must specify an output file using --event-interfaces-file.')
if args:
parser.error('No arguments allowed, but %d given.' % len(args))
return options
@@ -76,35 +83,30 @@ def parse_options():
def write_event_interfaces_file(event_idl_files, destination_filename, suffix):
def interface_line(full_path):
- relative_dir_local = os.path.dirname(os.path.relpath(full_path, REPO_ROOT_DIR))
+ relative_dir_local = os.path.dirname(
+ os.path.relpath(full_path, REPO_ROOT_DIR))
relative_dir_posix = relative_dir_local.replace(os.sep, posixpath.sep)
idl_file_contents = get_file_contents(full_path)
interface_name = get_first_interface_name_from_idl(idl_file_contents)
- extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
- extended_attributes_list = [
- (name, extended_attributes[name])
- for name in EXPORTED_EXTENDED_ATTRIBUTES
- if name in extended_attributes]
+ extended_attributes = get_interface_extended_attributes_from_idl(
+ idl_file_contents)
+ extended_attributes_list = [(name, extended_attributes[name])
+ for name in EXPORTED_EXTENDED_ATTRIBUTES
+ if name in extended_attributes]
return (relative_dir_posix, interface_name, extended_attributes_list)
- lines = [
- '{',
- 'metadata: {',
- ' namespace: "event_interface_names",'
- ]
+ lines = ['{', 'metadata: {', ' namespace: "event_interface_names",']
if suffix:
lines.append(' suffix: "' + suffix + '",')
lines.append(' export: "%s_EXPORT",' % suffix.upper())
else:
lines.append(' export: "CORE_EXPORT",')
- lines.extend([
- '},',
- 'data: ['
- ])
- interface_lines = [interface_line(event_idl_file)
- for event_idl_file in event_idl_files]
+ lines.extend(['},', 'data: ['])
+ interface_lines = [
+ interface_line(event_idl_file) for event_idl_file in event_idl_files
+ ]
interface_lines.sort()
for relative_dir, name, attributes in interface_lines:
lines.extend([
@@ -117,20 +119,17 @@ def write_event_interfaces_file(event_idl_files, destination_filename, suffix):
value += 'Enabled'
lines.append(' %s: "%s",' % (param, value))
lines.append(' },')
- lines.extend([
- ']',
- '}'
- ])
+ lines.extend([']', '}'])
write_file('\n'.join(lines), destination_filename)
################################################################################
+
def main():
options = parse_options()
event_idl_files = read_file_to_list(options.event_idl_files_list)
- write_event_interfaces_file(event_idl_files,
- options.event_interfaces_file,
+ write_event_interfaces_file(event_idl_files, options.event_interfaces_file,
options.suffix)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
index 57b677409ba..987f737caf2 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
@@ -3,7 +3,6 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Generates interface properties on global objects.
Concretely these are implemented as "constructor attributes", meaning
@@ -41,22 +40,26 @@ from v8_utilities import EXPOSED_EXECUTION_CONTEXT_METHOD
interface_name_to_global_names = {}
global_name_to_constructors = defaultdict(list)
-
HEADER_FORMAT = """// Stub header file for {{idl_basename}}
-// Required because the IDL compiler assumes that a corresponding header file
-// exists for each IDL file.
+// Required because the IDL compiler assumes that a corresponding header
+// file exists for each IDL file.
"""
+
def parse_options():
parser = optparse.OptionParser()
parser.add_option('--idl-files-list', help='file listing IDL files')
- parser.add_option('--global-objects-file', help='pickle file of global objects')
+ parser.add_option(
+ '--global-objects-file', help='pickle file of global objects')
options, args = parser.parse_args()
if options.idl_files_list is None:
- parser.error('Must specify a file listing IDL files using --idl-files-list.')
+ parser.error(
+ 'Must specify a file listing IDL files using --idl-files-list.')
if options.global_objects_file is None:
- parser.error('Must specify a pickle file of global objects using --global-objects-file.')
+ parser.error(
+ 'Must specify a pickle file of global objects using --global-objects-file.'
+ )
return options, args
@@ -75,16 +78,17 @@ def interface_name_to_constructors(interface_name):
def record_global_constructors(idl_filename):
full_path = os.path.realpath(idl_filename)
idl_file_contents = get_file_contents(full_path)
- extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
+ extended_attributes = get_interface_extended_attributes_from_idl(
+ idl_file_contents)
interface_name = get_first_interface_name_from_idl(idl_file_contents)
# An interface property is produced for every non-callback interface
# that does not have [NoInterfaceObject].
# http://heycam.github.io/webidl/#es-interfaces
- if (not should_generate_impl_file_from_idl(idl_file_contents) or
- is_non_legacy_callback_interface_from_idl(idl_file_contents) or
- is_interface_mixin_from_idl(idl_file_contents) or
- 'NoInterfaceObject' in extended_attributes):
+ if (not should_generate_impl_file_from_idl(idl_file_contents)
+ or is_non_legacy_callback_interface_from_idl(idl_file_contents)
+ or is_interface_mixin_from_idl(idl_file_contents)
+ or 'NoInterfaceObject' in extended_attributes):
return
exposed_arguments = get_interface_exposed_arguments(idl_file_contents)
@@ -92,31 +96,40 @@ def record_global_constructors(idl_filename):
# Exposed(Arguments) case
for argument in exposed_arguments:
if 'RuntimeEnabled' in extended_attributes:
- raise ValueError('RuntimeEnabled should not be used with Exposed(Arguments)')
+ raise ValueError(
+ 'RuntimeEnabled should not be used with Exposed(Arguments)'
+ )
attributes = extended_attributes.copy()
attributes['RuntimeEnabled'] = argument['runtime_enabled']
- new_constructors_list = generate_global_constructors_list(interface_name, attributes)
- global_name_to_constructors[argument['exposed']].extend(new_constructors_list)
+ new_constructors_list = generate_global_constructors_list(
+ interface_name, attributes)
+ global_name_to_constructors[argument['exposed']].extend(
+ new_constructors_list)
else:
# Exposed=env or Exposed=(env1,...) case
exposed_value = extended_attributes.get('Exposed', 'Window')
- exposed_global_names = map(str.strip, exposed_value.strip('()').split(','))
- new_constructors_list = generate_global_constructors_list(interface_name, extended_attributes)
+ exposed_global_names = map(str.strip,
+ exposed_value.strip('()').split(','))
+ new_constructors_list = generate_global_constructors_list(
+ interface_name, extended_attributes)
for name in exposed_global_names:
global_name_to_constructors[name].extend(new_constructors_list)
def generate_global_constructors_list(interface_name, extended_attributes):
extended_attributes_list = [
- name + (('=' + extended_attributes[name]) if extended_attributes[name] else '')
- for name in 'RuntimeEnabled', 'ContextEnabled', 'SecureContext'
- if name in extended_attributes]
+ name + (('=' + extended_attributes[name])
+ if extended_attributes[name] else '')
+ for name in ['RuntimeEnabled', 'ContextEnabled', 'SecureContext']
+ if name in extended_attributes
+ ]
if extended_attributes_list:
extended_string = '[%s] ' % ', '.join(extended_attributes_list)
else:
extended_string = ''
- attribute_string = 'attribute {interface_name}Constructor {interface_name}'.format(interface_name=interface_name)
+ attribute_string = 'attribute {interface_name}Constructor {interface_name}'.format(
+ interface_name=interface_name)
attributes_list = [extended_string + attribute_string]
# In addition to the usual interface property, for every [NamedConstructor]
@@ -129,30 +142,36 @@ def generate_global_constructors_list(interface_name, extended_attributes):
constructor_name = re.sub(r'\(.*', '', named_constructor)
# Note the reduplicated 'ConstructorConstructor'
# FIXME: rename to NamedConstructor
- attribute_string = 'attribute %sConstructorConstructor %s' % (interface_name, constructor_name)
+ attribute_string = 'attribute %sConstructorConstructor %s' % (
+ interface_name, constructor_name)
attributes_list.append(extended_string + attribute_string)
return attributes_list
-def write_global_constructors_partial_interface(interface_name, idl_filename, constructor_attributes_list):
+def write_global_constructors_partial_interface(interface_name, idl_filename,
+ constructor_attributes_list):
idl_basename = os.path.basename(idl_filename)
basename = os.path.splitext(idl_basename)[0]
# FIXME: replace this with a simple Jinja template
- lines = (['[\n',
- ' ImplementedAs=%s\n' % basename,
- '] partial interface %s {\n' % interface_name] +
- [' %s;\n' % constructor_attribute
- # FIXME: sort by interface name (not first by extended attributes)
- for constructor_attribute in sorted(constructor_attributes_list)] +
- ['};\n'])
+ lines = ([
+ '[\n',
+ ' ImplementedAs=%s\n' % basename,
+ '] partial interface %s {\n' % interface_name
+ ] + [
+ ' %s;\n' % constructor_attribute
+ # FIXME: sort by interface name (not first by extended attributes)
+ for constructor_attribute in sorted(constructor_attributes_list)
+ ] + ['};\n'])
write_file(''.join(lines), idl_filename)
header_filename = os.path.splitext(idl_filename)[0] + '.h'
- write_file(HEADER_FORMAT.format(idl_basename=idl_basename), header_filename)
+ write_file(
+ HEADER_FORMAT.format(idl_basename=idl_basename), header_filename)
################################################################################
+
def main():
options, args = parse_options()
@@ -167,7 +186,8 @@ def main():
interface_name_idl_filename = [(args[i], args[i + 1])
for i in range(0, len(args), 2)]
- interface_name_to_global_names.update(read_pickle_file(options.global_objects_file))
+ interface_name_to_global_names.update(
+ read_pickle_file(options.global_objects_file))
for idl_filename in idl_files:
record_global_constructors(idl_filename)
@@ -176,7 +196,8 @@ def main():
known_global_names = EXPOSED_EXECUTION_CONTEXT_METHOD.keys()
exposed_global_names = frozenset(global_name_to_constructors)
if not exposed_global_names.issubset(known_global_names):
- unknown_global_names = exposed_global_names.difference(known_global_names)
+ unknown_global_names = exposed_global_names.difference(
+ known_global_names)
raise ValueError('The following global names were used in '
'[Exposed=xxx] but do not match any global names: %s'
% list(unknown_global_names))
@@ -185,8 +206,8 @@ def main():
# global interface.
for interface_name, idl_filename in interface_name_idl_filename:
constructors = interface_name_to_constructors(interface_name)
- write_global_constructors_partial_interface(
- interface_name, idl_filename, constructors)
+ write_global_constructors_partial_interface(interface_name,
+ idl_filename, constructors)
if __name__ == '__main__':
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
new file mode 100644
index 00000000000..a247e0032ac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
@@ -0,0 +1,137 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Generate of table of APIs and their attributes based on the WebIDL database.
+
+The columns of the table are as follows:
+
+ * interface : Name of interface.
+ * name : Member name. Will be empty for interfaces.
+ * entity_type : One of 'interface', 'namespace', 'const', 'attribute',
+ 'operation', 'constructor', 'stringifier', 'iterable',
+ 'maplike', 'setlike', 'dictionary'
+ * idl_type : Type of the object. For function-like entries, this is the
+ type of the return value. Note that the type is stripped
+ of nullable unions.
+ * syntactic_form : Human readable idl_type.
+ * use_counter : If usage is being measured, this is the UseCounter.
+ * secure_context : 'True' if the [SecureContext] extended attribute is
+ present. Empty otherwise.
+ * high_entropy : 'True' if the [HighEntropy] extended attribute is present.
+ Empty otherwise.
+"""
+
+import optparse
+from io import BytesIO
+from csv import DictWriter
+
+from utilities import write_file
+from v8_utilities import capitalize
+import web_idl
+
+
+def parse_options():
+ parser = optparse.OptionParser(usage="%prog [options]")
+ parser.add_option(
+ "--web_idl_database",
+ type="string",
+ help="filepath of the input database")
+ parser.add_option(
+ "--output", type="string", help="filepath of output file")
+ options, args = parser.parse_args()
+
+ required_option_names = ("web_idl_database", "output")
+ for opt_name in required_option_names:
+ if getattr(options, opt_name) is None:
+ parser.error("--{} is a required option.".format(opt_name))
+
+ return options, args
+
+
+def get_idl_type_name(idl_type):
+ assert isinstance(idl_type, web_idl.IdlType)
+ unwrapped_type = idl_type.unwrap()
+ return unwrapped_type.type_name, unwrapped_type.syntactic_form
+
+
+def true_or_nothing(v):
+ return 'True' if v else ''
+
+
+def record(csv_writer, entity):
+ interface = ''
+ name = ''
+ entity_type = ''
+ use_counter = ''
+ secure_context = ''
+ high_entropy = ''
+ idl_type = ''
+ syntactic_form = ''
+
+ secure_context = ('SecureContext' in entity.extended_attributes)
+ high_entropy = ('HighEntropy' in entity.extended_attributes)
+
+ if 'Measure' in entity.extended_attributes:
+ use_counter = capitalize(entity.identifier)
+ if not isinstance(entity, web_idl.Interface):
+ use_counter = (
+ capitalize(entity.owner.identifier) + '_' + use_counter)
+ elif 'MeasureAs' in entity.extended_attributes:
+ use_counter = entity.extended_attributes.value_of('MeasureAs')
+
+ if isinstance(entity, web_idl.Interface):
+ interface = entity.identifier
+ name = ''
+ entity_type = 'interface'
+ else:
+ interface = entity.owner.identifier
+ name = entity.identifier
+
+ if isinstance(entity, web_idl.Attribute):
+ entity_type = 'attribute'
+ idl_type, syntactic_form = get_idl_type_name(entity.idl_type)
+ elif isinstance(entity, web_idl.Operation):
+ entity_type = 'operation'
+ idl_type, syntactic_form = get_idl_type_name(entity.return_type)
+ elif isinstance(entity, web_idl.Constant):
+ entity_type = 'constant'
+ idl_type, syntactic_form = get_idl_type_name(entity.idl_type)
+ else:
+ assert False, "Unexpected IDL construct"
+ csv_writer.writerow({
+ 'interface': interface,
+ 'name': name,
+ 'entity_type': entity_type,
+ 'idl_type': idl_type,
+ 'syntactic_form': syntactic_form,
+ 'use_counter': use_counter,
+ 'secure_context': true_or_nothing(secure_context),
+ 'high_entropy': true_or_nothing(high_entropy)
+ })
+
+
+def main():
+ options, _ = parse_options()
+ with BytesIO() as out_buffer:
+ csv_writer = DictWriter(
+ out_buffer,
+ fieldnames=[
+ 'interface', 'name', 'entity_type', 'idl_type',
+ 'syntactic_form', 'use_counter', 'secure_context',
+ 'high_entropy'
+ ])
+ csv_writer.writeheader()
+
+ web_idl_database = web_idl.Database.read_from_file(
+ options.web_idl_database)
+ for interface in web_idl_database.interfaces:
+ record(csv_writer, interface)
+ for entity in (interface.attributes + interface.operations +
+ interface.constants):
+ record(csv_writer, entity)
+ write_file(out_buffer.getvalue(), options.output)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps b/chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
new file mode 100644
index 00000000000..1d9e7f3b75a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
@@ -0,0 +1,51 @@
+# Generated by running:
+# build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
+../../../../pyjson5/src/json5/__init__.py
+../../../../pyjson5/src/json5/arg_parser.py
+../../../../pyjson5/src/json5/host.py
+../../../../pyjson5/src/json5/lib.py
+../../../../pyjson5/src/json5/parser.py
+../../../../pyjson5/src/json5/tool.py
+../../../../pyjson5/src/json5/version.py
+../../build/scripts/blinkbuild/__init__.py
+../../build/scripts/blinkbuild/name_style_converter.py
+generate_high_entropy_list.py
+idl_definitions.py
+idl_types.py
+utilities.py
+v8_globals.py
+v8_utilities.py
+web_idl/__init__.py
+web_idl/argument.py
+web_idl/ast_group.py
+web_idl/attribute.py
+web_idl/callback_function.py
+web_idl/callback_interface.py
+web_idl/code_generator_info.py
+web_idl/composition_parts.py
+web_idl/constant.py
+web_idl/constructor.py
+web_idl/database.py
+web_idl/database_builder.py
+web_idl/dictionary.py
+web_idl/enumeration.py
+web_idl/exposure.py
+web_idl/extended_attribute.py
+web_idl/file_io.py
+web_idl/function_like.py
+web_idl/idl_compiler.py
+web_idl/idl_type.py
+web_idl/includes.py
+web_idl/interface.py
+web_idl/ir_builder.py
+web_idl/ir_map.py
+web_idl/literal_constant.py
+web_idl/make_copy.py
+web_idl/namespace.py
+web_idl/operation.py
+web_idl/reference.py
+web_idl/runtime_enabled_features.py
+web_idl/typedef.py
+web_idl/union.py
+web_idl/user_defined_type.py
+web_idl/validator.py
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
index 0e44fe91b66..fca4d565c96 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
@@ -2,11 +2,14 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
-"""Generate initPartialInterfacesInModules(), which registers partial interfaces in modules to core interfaces."""
+"""Generate initPartialInterfacesInModules(), which registers partial
+interfaces in modules to core interfaces.
+"""
# pylint: disable=relative-import
+from __future__ import print_function
+
from optparse import OptionParser
import os
import posixpath
@@ -19,7 +22,6 @@ from utilities import should_generate_impl_file_from_idl
from utilities import write_file
from v8_utilities import build_basename
-
_COPYRIGHT = """// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -41,15 +43,18 @@ void InitPartialInterfacesInModules() {
def parse_options():
usage = 'Usage: %prog [options]'
parser = OptionParser(usage=usage)
- parser.add_option('--idl-files-list',
- help='a text file containing the IDL file paths, so the command line doesn\'t exceed OS length limits.')
+ parser.add_option(
+ '--idl-files-list',
+ help='a text file containing the IDL file paths, so the command '
+ 'line doesn\'t exceed OS length limits.')
parser.add_option('--output')
options, args = parser.parse_args()
if options.output is None:
parser.error('Must specify output file using --output.')
if options.idl_files_list is None:
- parser.error('Must specify a list of IDL files using --idl-files-list.')
+ parser.error(
+ 'Must specify a list of IDL files using --idl-files-list.')
return options
@@ -59,10 +64,10 @@ def extract_meta_data(file_paths):
for file_path in file_paths:
if not file_path.endswith('.idl'):
- print 'WARNING: non-IDL file passed: "%s"' % file_path
+ print('WARNING: non-IDL file passed: "%s"' % file_path)
continue
if not os.path.exists(file_path):
- print 'WARNING: file not found: "%s"' % file_path
+ print('WARNING: file not found: "%s"' % file_path)
continue
idl_file_contents = get_file_contents(file_path)
@@ -86,20 +91,22 @@ def main():
idl_file_names = read_idl_files_list_from_file(options.idl_files_list)
meta_data_list = extract_meta_data(idl_file_names)
- interface_names = ['V8%sPartial' % meta_data['basename']
- for meta_data in meta_data_list]
+ interface_names = [
+ 'V8%sPartial' % meta_data['basename'] for meta_data in meta_data_list
+ ]
interface_names.sort()
- includes = ['#include "third_party/blink/renderer/bindings/modules/v8/%s.h"' %
- build_basename(interface_name)
- for interface_name in interface_names]
- initialize_calls = [' %s::Initialize();' % interface_name
- for interface_name in interface_names]
-
- content = _INIT_PARTIAL_INTERFACE % (
- _COPYRIGHT,
- '\n'.join(includes),
- '\n'.join(initialize_calls))
+ includes = [
+ '#include "third_party/blink/renderer/bindings/modules/v8/%s.h"' %
+ build_basename(interface_name) for interface_name in interface_names
+ ]
+ initialize_calls = [
+ ' %s::Initialize();' % interface_name
+ for interface_name in interface_names
+ ]
+
+ content = _INIT_PARTIAL_INTERFACE % (_COPYRIGHT, '\n'.join(includes),
+ '\n'.join(initialize_calls))
write_file(content, options.output)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
index 0ec3953411b..c2b40844ad1 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
@@ -25,9 +25,9 @@ from v8_utilities import (binding_header_filename, v8_class_name,
# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
-
-OriginTrialInterfaceInfo = namedtuple('OriginTrialInterfaceInfo', [
- 'name', 'v8_class', 'v8_class_or_partial', 'is_global'])
+OriginTrialInterfaceInfo = namedtuple(
+ 'OriginTrialInterfaceInfo',
+ ['name', 'v8_class', 'v8_class_or_partial', 'is_global'])
def get_install_functions(interfaces, feature_names):
@@ -38,15 +38,14 @@ def get_install_functions(interfaces, feature_names):
feature_names is a list of strings, containing names of features which can
be installed on those interfaces.
"""
- return [
- {'condition': 'RuntimeEnabledFeatures::%sEnabled' % feature_name,
- 'name': feature_name,
- 'install_method': 'Install%s' % feature_name,
- 'interface_is_global': interface_info.is_global,
- 'v8_class': interface_info.v8_class,
- 'v8_class_or_partial': interface_info.v8_class_or_partial}
- for feature_name in feature_names
- for interface_info in interfaces]
+ return [{
+ 'condition': 'RuntimeEnabledFeatures::%sEnabled' % feature_name,
+ 'name': feature_name,
+ 'install_method': 'Install%s' % feature_name,
+ 'interface_is_global': interface_info.is_global,
+ 'v8_class': interface_info.v8_class,
+ 'v8_class_or_partial': interface_info.v8_class_or_partial
+ } for feature_name in feature_names for interface_info in interfaces]
def get_origin_trial_feature_names_from_interface(interface, runtime_features):
@@ -78,7 +77,8 @@ def interface_is_global(interface):
return 'Global' in interface.extended_attributes
-def origin_trial_features_info(info_provider, reader, idl_filenames, target_component):
+def origin_trial_features_info(info_provider, reader, idl_filenames,
+ target_component):
"""Read a set of IDL files and compile the mapping between interfaces and
the conditional features defined on them.
@@ -95,10 +95,13 @@ def origin_trial_features_info(info_provider, reader, idl_filenames, target_comp
for idl_filename in idl_filenames:
interface, includes = read_idl_file(reader, idl_filename)
- feature_names = get_origin_trial_feature_names_from_interface(interface, runtime_features)
+ feature_names = get_origin_trial_feature_names_from_interface(
+ interface, runtime_features)
# If this interface is a mixin, we don't generate V8 bindings code for
# it.
+ # TODO(crbug.com/1061995): This incorrectly ignores includes in the
+ # mixin idl like "SomeInterface includes MixinInterface".
if interface.is_mixin:
continue
@@ -109,7 +112,8 @@ def origin_trial_features_info(info_provider, reader, idl_filenames, target_comp
mixin, _ = read_idl_file(
reader,
info_provider.interfaces_info[include.mixin].get('full_path'))
- feature_names |= get_origin_trial_feature_names_from_interface(mixin, runtime_features)
+ feature_names |= get_origin_trial_feature_names_from_interface(
+ mixin, runtime_features)
feature_names = list(feature_names)
if feature_names:
@@ -118,28 +122,29 @@ def origin_trial_features_info(info_provider, reader, idl_filenames, target_comp
# For partial interfaces, we need to generate different
# |include_files| if the parent interface is in a different
# component.
- parent_interface_info = info_provider.interfaces_info[interface.name]
+ parent_interface_info = \
+ info_provider.interfaces_info[interface.name]
parent_interface, _ = read_idl_file(
reader, parent_interface_info.get('full_path'))
is_global = is_global or interface_is_global(parent_interface)
parent_component = idl_filename_to_component(
parent_interface_info.get('full_path'))
if interface.is_partial and target_component != parent_component:
- include_files.add('bindings/%s/v8/%s' %
- (parent_component, binding_header_filename(interface.name)))
- include_files.add('bindings/%s/v8/%s' %
- (target_component, binding_header_filename(interface.name + 'Partial')))
+ include_files.add('bindings/%s/v8/%s' % (
+ parent_component, binding_header_filename(interface.name)))
+ include_files.add(
+ 'bindings/%s/v8/%s' %
+ (target_component,
+ binding_header_filename(interface.name + 'Partial')))
else:
- include_files.add('bindings/%s/v8/%s' %
- (target_component, binding_header_filename(interface.name)))
+ include_files.add('bindings/%s/v8/%s' % (
+ target_component, binding_header_filename(interface.name)))
# If this is a partial interface in the same component as
# its parent, then treat it as a non-partial interface.
interface.is_partial = False
- interface_info = OriginTrialInterfaceInfo(interface.name,
- v8_class_name(interface),
- v8_class_name_or_partial(
- interface),
- is_global)
+ interface_info = OriginTrialInterfaceInfo(
+ interface.name, v8_class_name(interface),
+ v8_class_name_or_partial(interface), is_global)
for feature_name in feature_names:
features_for_type[interface_info].add(feature_name)
types_for_feature[feature_name].add(interface_info)
@@ -171,21 +176,28 @@ def origin_trial_features_context(generator_name, feature_info):
# For each interface, collect a list of bindings installation functions to
# call, organized by conditional feature.
- context['installers_by_interface'] = [
- {'name': interface_info.name,
- 'is_global': interface_info.is_global,
- 'v8_class': interface_info.v8_class,
- 'installers': get_install_functions([interface_info], feature_names)}
- for interface_info, feature_names in features_for_type.items()]
+ context['installers_by_interface'] = [{
+ 'name':
+ interface_info.name,
+ 'is_global':
+ interface_info.is_global,
+ 'v8_class':
+ interface_info.v8_class,
+ 'installers':
+ get_install_functions([interface_info], feature_names)
+ } for interface_info, feature_names in features_for_type.items()]
context['installers_by_interface'].sort(key=lambda x: x['name'])
# For each conditional feature, collect a list of bindings installation
# functions to call, organized by interface.
- context['installers_by_feature'] = [
- {'name': feature_name,
- 'name_constant': 'OriginTrialFeature::k%s' % feature_name,
- 'installers': get_install_functions(interfaces, [feature_name])}
- for feature_name, interfaces in types_for_feature.items()]
+ context['installers_by_feature'] = [{
+ 'name':
+ feature_name,
+ 'name_constant':
+ 'OriginTrialFeature::k%s' % feature_name,
+ 'installers':
+ get_install_functions(interfaces, [feature_name])
+ } for feature_name, interfaces in types_for_feature.items()]
context['installers_by_feature'].sort(key=lambda x: x['name'])
return context
@@ -193,14 +205,16 @@ def origin_trial_features_context(generator_name, feature_info):
def parse_options():
parser = optparse.OptionParser()
- parser.add_option('--cache-directory',
- help='cache directory, defaults to output directory')
+ parser.add_option(
+ '--cache-directory',
+ help='cache directory, defaults to output directory')
parser.add_option('--output-directory')
parser.add_option('--info-dir')
- parser.add_option('--target-component',
- type='choice',
- choices=['core', 'modules'],
- help='target component to generate code')
+ parser.add_option(
+ '--target-component',
+ type='choice',
+ choices=['core', 'modules'],
+ help='target component to generate code')
parser.add_option('--idl-files-list')
options, _ = parser.parse_args()
@@ -215,23 +229,25 @@ def generate_origin_trial_features(info_provider, options, idl_filenames):
# Extract the bidirectional mapping of conditional features <-> interfaces
# from the global info provider and the supplied list of IDL files.
- feature_info = origin_trial_features_info(info_provider,
- reader, idl_filenames,
- options.target_component)
+ feature_info = origin_trial_features_info(
+ info_provider, reader, idl_filenames, options.target_component)
# Convert that mapping into the context required for the Jinja2 templates.
- template_context = origin_trial_features_context(
- MODULE_PYNAME, feature_info)
+ template_context = origin_trial_features_context(MODULE_PYNAME,
+ feature_info)
file_basename = 'origin_trial_features_for_%s' % options.target_component
# Generate and write out the header file
- header_text = render_template(jinja_env.get_template(file_basename + '.h.tmpl'), template_context)
- header_path = posixpath.join(options.output_directory, file_basename + '.h')
+ header_text = render_template(
+ jinja_env.get_template(file_basename + '.h.tmpl'), template_context)
+ header_path = posixpath.join(options.output_directory,
+ file_basename + '.h')
write_file(header_text, header_path)
# Generate and write out the implementation file
- cpp_text = render_template(jinja_env.get_template(file_basename + '.cc.tmpl'), template_context)
+ cpp_text = render_template(
+ jinja_env.get_template(file_basename + '.cc.tmpl'), template_context)
cpp_path = posixpath.join(options.output_directory, file_basename + '.cc')
write_file(cpp_text, cpp_path)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
index 3fc8a81a152..4f23b299d0d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
@@ -17,14 +17,14 @@ import v8_interface
import v8_types
import v8_utilities
-
INCLUDES = frozenset([
'third_party/blink/renderer/bindings/core/v8/generated_code_helper.h',
'third_party/blink/renderer/bindings/core/v8/v8_html_document.h',
'third_party/blink/renderer/bindings/core/v8/v8_initializer.h',
'third_party/blink/renderer/bindings/core/v8/v8_window.h',
'third_party/blink/renderer/platform/bindings/v8_object_constructor.h',
- 'v8/include/v8.h'])
+ 'v8/include/v8.h'
+])
TEMPLATE_FILE = 'external_reference_table.cc.tmpl'
@@ -39,22 +39,27 @@ SNAPSHOTTED_INTERFACES = frozenset([
def parse_args():
parser = argparse.ArgumentParser()
- parser.add_argument('--idl-files-list', type=str, required=True,
- help='file listing IDL files')
- parser.add_argument('--output', type=str, required=True,
- help='output file path')
- parser.add_argument('--info-dir', type=str, required=True,
- help='directory contains component info')
- parser.add_argument('--cache-dir', type=str, required=True,
- help='cache directory')
- parser.add_argument('--target-component', type=str, required=True,
- help='target component')
+ parser.add_argument(
+ '--idl-files-list',
+ type=str,
+ required=True,
+ help='file listing IDL files')
+ parser.add_argument(
+ '--output', type=str, required=True, help='output file path')
+ parser.add_argument(
+ '--info-dir',
+ type=str,
+ required=True,
+ help='directory contains component info')
+ parser.add_argument(
+ '--cache-dir', type=str, required=True, help='cache directory')
+ parser.add_argument(
+ '--target-component', type=str, required=True, help='target component')
return parser.parse_known_args()
# This class creates a Jinja template context about an interface.
class InterfaceTemplateContextBuilder(object):
-
def __init__(self, opts, info_provider):
self._opts = opts
self._info_provider = info_provider
@@ -64,12 +69,14 @@ class InterfaceTemplateContextBuilder(object):
assert component in ['core', 'modules']
- name = '%s%s' % (v8_utilities.cpp_name(interface), 'Partial' if interface.is_partial else '')
+ name = '%s%s' % (v8_utilities.cpp_name(interface),
+ 'Partial' if interface.is_partial else '')
# Constructors
has_constructor_callback = False
if not interface.is_partial:
- constructors = any(constructor.name == 'Constructor' for constructor in interface.constructors)
+ constructors = any(constructor.name == 'Constructor'
+ for constructor in interface.constructors)
custom_constructors = interface.custom_constructors
html_constructor = 'HTMLConstructor' in interface.extended_attributes
has_constructor_callback = constructors or custom_constructors or html_constructor
@@ -86,9 +93,13 @@ class InterfaceTemplateContextBuilder(object):
named_property_getter = None
component_info = self._info_provider.component_info
if interface.name in SNAPSHOTTED_INTERFACES:
- attributes = [v8_attributes.attribute_context(interface, attribute, interfaces, component_info)
- for attribute in interface.attributes]
- methods = v8_interface.methods_context(interface, component_info)['methods']
+ attributes = [
+ v8_attributes.attribute_context(interface, attribute,
+ interfaces, component_info)
+ for attribute in interface.attributes
+ ]
+ methods = v8_interface.methods_context(interface,
+ component_info)['methods']
is_global = 'Global' in interface.extended_attributes
named_property_getter = v8_interface.property_getter(
@@ -97,37 +108,68 @@ class InterfaceTemplateContextBuilder(object):
interface.indexed_property_getter, ['index'])
if not interface.is_partial:
- has_security_check = ('CheckSecurity' in interface.extended_attributes and
- interface.name != 'EventTarget')
- has_cross_origin_named_getter = (any(method['is_cross_origin'] for method in methods) or
- any(attribute['has_cross_origin_getter'] for attribute in attributes))
- has_cross_origin_named_setter = any(attribute['has_cross_origin_setter'] for attribute in attributes)
- has_cross_origin_indexed_getter = indexed_property_getter and indexed_property_getter['is_cross_origin']
- has_cross_origin_named_enum = has_cross_origin_named_getter or has_cross_origin_named_setter
- if named_property_getter and named_property_getter['is_cross_origin']:
+ has_security_check = (
+ 'CheckSecurity' in interface.extended_attributes
+ and interface.name != 'EventTarget')
+ has_cross_origin_named_getter = (
+ any(method['is_cross_origin'] for method in methods)
+ or any(attribute['has_cross_origin_getter']
+ for attribute in attributes))
+ has_cross_origin_named_setter = any(
+ attribute['has_cross_origin_setter']
+ for attribute in attributes)
+ has_cross_origin_indexed_getter = (
+ indexed_property_getter
+ and indexed_property_getter['is_cross_origin'])
+ has_cross_origin_named_enum = has_cross_origin_named_getter \
+ or has_cross_origin_named_setter
+ if (named_property_getter
+ and named_property_getter['is_cross_origin']):
has_cross_origin_named_getter = True
return {
- 'attributes': attributes,
- 'component': component,
- 'has_constructor_callback': has_constructor_callback,
- '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_enum,
- 'has_cross_origin_indexed_getter': has_cross_origin_indexed_getter,
- 'has_security_check': has_security_check,
- 'indexed_property_getter': indexed_property_getter,
- 'indexed_property_setter': v8_interface.property_setter(interface.indexed_property_setter, interface),
- 'indexed_property_deleter': v8_interface.property_deleter(interface.indexed_property_deleter),
- 'internal_namespace': v8_interface.internal_namespace(interface),
- 'is_partial': interface.is_partial,
- 'methods': methods,
- 'name': name,
- 'named_constructor': v8_interface.named_constructor_context(interface),
- 'named_property_getter': named_property_getter,
- 'named_property_setter': v8_interface.property_setter(interface.named_property_setter, interface),
- 'named_property_deleter': v8_interface.property_deleter(interface.named_property_deleter),
- 'v8_class': v8_utilities.v8_class_name_or_partial(interface),
+ 'attributes':
+ attributes,
+ 'component':
+ component,
+ 'has_constructor_callback':
+ has_constructor_callback,
+ '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_enum,
+ 'has_cross_origin_indexed_getter':
+ has_cross_origin_indexed_getter,
+ 'has_security_check':
+ has_security_check,
+ 'indexed_property_getter':
+ indexed_property_getter,
+ 'indexed_property_setter':
+ v8_interface.property_setter(interface.indexed_property_setter,
+ interface),
+ 'indexed_property_deleter':
+ v8_interface.property_deleter(interface.indexed_property_deleter),
+ 'internal_namespace':
+ v8_interface.internal_namespace(interface),
+ 'is_partial':
+ interface.is_partial,
+ 'methods':
+ methods,
+ 'name':
+ name,
+ 'named_constructor':
+ v8_interface.named_constructor_context(interface),
+ 'named_property_getter':
+ named_property_getter,
+ 'named_property_setter':
+ v8_interface.property_setter(interface.named_property_setter,
+ interface),
+ 'named_property_deleter':
+ v8_interface.property_deleter(interface.named_property_deleter),
+ 'v8_class':
+ v8_utilities.v8_class_name_or_partial(interface),
}
@@ -136,11 +178,11 @@ class ExternalReferenceTableGenerator(object):
def __init__(self, opts, info_provider):
self._opts = opts
self._info_provider = info_provider
- self._reader = IdlReader(
- info_provider.interfaces_info, opts.cache_dir)
+ self._reader = IdlReader(info_provider.interfaces_info, opts.cache_dir)
self._interface_contexts = {}
self._include_files = set(INCLUDES)
- v8_types.set_component_dirs(info_provider.interfaces_info['component_dirs'])
+ v8_types.set_component_dirs(
+ info_provider.interfaces_info['component_dirs'])
# Creates a Jinja context from an IDL file.
def process_idl_file(self, idl_filename):
@@ -162,19 +204,25 @@ class ExternalReferenceTableGenerator(object):
# Non legacy callback interface does not provide V8 callbacks.
if interface.is_callback:
return len(interface.constants) > 0
- if v8_utilities.runtime_enabled_feature_name(interface, runtime_features):
+ if v8_utilities.runtime_enabled_feature_name(
+ interface, runtime_features):
return False
if 'Exposed' not in interface.extended_attributes:
return True
- return any(exposure.exposed == 'Window' and exposure.runtime_enabled is None
- for exposure in interface.extended_attributes['Exposed'])
+ return any(
+ exposure.exposed == 'Window'
+ and exposure.runtime_enabled is None
+ for exposure in interface.extended_attributes['Exposed'])
if not has_impl(interface):
return
- context_builder = InterfaceTemplateContextBuilder(self._opts, self._info_provider)
- context = context_builder.create_interface_context(interface, component, interfaces)
- name = '%s%s' % (interface.name, 'Partial' if interface.is_partial else '')
+ context_builder = InterfaceTemplateContextBuilder(
+ self._opts, self._info_provider)
+ context = context_builder.create_interface_context(
+ interface, component, interfaces)
+ name = '%s%s' % (interface.name,
+ 'Partial' if interface.is_partial else '')
self._interface_contexts[name] = context
# Do not include unnecessary header files.
@@ -213,8 +261,8 @@ class ExternalReferenceTableGenerator(object):
def main():
opts, _ = parse_args()
# TODO(peria): get rid of |info_provider|
- info_provider = create_component_info_provider(
- opts.info_dir, opts.target_component)
+ info_provider = create_component_info_provider(opts.info_dir,
+ opts.target_component)
generator = ExternalReferenceTableGenerator(opts, info_provider)
idl_files = utilities.read_idl_files_list_from_file(opts.idl_files_list)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py
index d4f4f54ecd4..94ba1bd4750 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_compiler.py
@@ -26,7 +26,6 @@
# 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.
-
"""Compile an .idl file to Blink V8 bindings (.h and .cpp files).
Design doc: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/IDLCompiler.md
@@ -49,22 +48,23 @@ from utilities import write_file
def parse_options():
parser = OptionParser()
- parser.add_option('--cache-directory',
- help='cache directory, defaults to output directory')
- parser.add_option('--generate-impl',
- action='store_true', default=False)
- parser.add_option('--read-idl-list-from-file',
- action='store_true', default=False)
+ parser.add_option(
+ '--cache-directory',
+ help='cache directory, defaults to output directory')
+ parser.add_option('--generate-impl', action='store_true', default=False)
+ parser.add_option(
+ '--read-idl-list-from-file', action='store_true', default=False)
parser.add_option('--output-directory')
parser.add_option('--impl-output-directory')
parser.add_option('--info-dir')
# FIXME: We should always explicitly specify --target-component and
# remove the default behavior.
- parser.add_option('--target-component',
- type='choice',
- choices=['core', 'modules'],
- help='target component to generate code, defaults to '
- 'component of input idl file')
+ parser.add_option(
+ '--target-component',
+ type='choice',
+ choices=['core', 'modules'],
+ help='target component to generate code, defaults to '
+ 'component of input idl file')
# ensure output comes last, so command line easy to parse via regexes
parser.disable_interspersed_args()
@@ -72,7 +72,9 @@ def parse_options():
if options.output_directory is None:
parser.error('Must specify output directory using --output-directory.')
if len(args) != 1:
- parser.error('Must specify exactly 1 input file as argument, but %d given.' % len(args))
+ parser.error(
+ 'Must specify exactly 1 input file as argument, but %d given.' %
+ len(args))
idl_filename = os.path.realpath(args[0])
return options, idl_filename
@@ -83,8 +85,11 @@ class IdlCompiler(object):
"""
__metaclass__ = abc.ABCMeta
- def __init__(self, output_directory, cache_directory=None,
- code_generator_class=None, info_provider=None,
+ def __init__(self,
+ output_directory,
+ cache_directory=None,
+ code_generator_class=None,
+ info_provider=None,
target_component=None):
"""
Args:
@@ -99,9 +104,8 @@ class IdlCompiler(object):
self.output_directory = output_directory
self.target_component = target_component
self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
- self.code_generator = code_generator_class(self.info_provider,
- self.cache_directory,
- self.output_directory)
+ self.code_generator = code_generator_class(
+ self.info_provider, self.cache_directory, self.output_directory)
def compile_and_write(self, idl_filename):
definitions = self.reader.read_idl_definitions(idl_filename)
@@ -149,11 +153,9 @@ def generate_dictionary_impl(code_generator_class, info_provider, options,
def generate_union_type_containers(code_generator_class, info_provider,
options):
- generator = code_generator_class(
- info_provider,
- options.cache_directory,
- options.output_directory,
- options.target_component)
+ generator = code_generator_class(info_provider, options.cache_directory,
+ options.output_directory,
+ options.target_component)
output_code_list = generator.generate_code()
for output_path, output_code in output_code_list:
write_file(output_code, output_path)
@@ -161,11 +163,9 @@ def generate_union_type_containers(code_generator_class, info_provider,
def generate_callback_function_impl(code_generator_class, info_provider,
options):
- generator = code_generator_class(
- info_provider,
- options.cache_directory,
- options.output_directory,
- options.target_component)
+ generator = code_generator_class(info_provider, options.cache_directory,
+ options.output_directory,
+ options.target_component)
output_code_list = generator.generate_code()
for output_path, output_code in output_code_list:
write_file(output_code, output_path)
@@ -173,8 +173,8 @@ def generate_callback_function_impl(code_generator_class, info_provider,
def main():
options, input_filename = parse_options()
- info_provider = create_component_info_provider(
- options.info_dir, options.target_component)
+ info_provider = create_component_info_provider(options.info_dir,
+ options.target_component)
if options.generate_impl or options.read_idl_list_from_file:
# |input_filename| should be a file which contains a list of IDL
# dictionary paths.
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
index 27c6b032902..11f6846eef2 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
@@ -27,7 +27,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pylint: disable=relative-import
-
"""Blink IDL Intermediate Representation (IR) classes.
Classes are primarily constructors, which build an IdlDefinitions object
@@ -73,11 +72,11 @@ from idl_types import IdlUnionType
SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
-
################################################################################
# TypedObject
################################################################################
+
class TypedObject(object):
"""Object with a type, such as an Attribute or Operation (return value).
@@ -85,13 +84,14 @@ class TypedObject(object):
by the TypedefResolver before passing data to the code generator.
"""
__metaclass__ = abc.ABCMeta
- idl_type_attributes = ('idl_type',)
+ idl_type_attributes = ('idl_type', )
################################################################################
# Definitions (main container class)
################################################################################
+
class IdlDefinitions(object):
def __init__(self, node):
"""Args: node: AST root node, class == 'File'"""
@@ -123,7 +123,8 @@ class IdlDefinitions(object):
self.enumerations[enumeration.name] = enumeration
elif child_class == 'Callback':
callback_function = IdlCallbackFunction(child)
- self.callback_functions[callback_function.name] = callback_function
+ self.callback_functions[callback_function.
+ name] = callback_function
elif child_class == 'Includes':
self.includes.append(IdlIncludes(child))
elif child_class == 'Dictionary':
@@ -136,22 +137,22 @@ class IdlDefinitions(object):
def accept(self, visitor):
visitor.visit_definitions(self)
- for interface in self.interfaces.itervalues():
+ for interface in self.interfaces.values():
interface.accept(visitor)
- for callback_function in self.callback_functions.itervalues():
+ for callback_function in self.callback_functions.values():
callback_function.accept(visitor)
- for dictionary in self.dictionaries.itervalues():
+ for dictionary in self.dictionaries.values():
dictionary.accept(visitor)
- for enumeration in self.enumerations.itervalues():
+ for enumeration in self.enumerations.values():
enumeration.accept(visitor)
for include in self.includes:
include.accept(visitor)
- for typedef in self.typedefs.itervalues():
+ for typedef in self.typedefs.values():
typedef.accept(visitor)
def update(self, other):
"""Update with additional IdlDefinitions."""
- for interface_name, new_interface in other.interfaces.iteritems():
+ for interface_name, new_interface in other.interfaces.items():
if not new_interface.is_partial:
# Add as new interface
self.interfaces[interface_name] = new_interface
@@ -162,8 +163,8 @@ class IdlDefinitions(object):
self.interfaces[interface_name].merge(new_interface)
except KeyError:
raise Exception('Tried to merge partial interface for {0}, '
- 'but no existing interface by that name'
- .format(interface_name))
+ 'but no existing interface by that name'.
+ format(interface_name))
# Merge callbacks and enumerations
self.enumerations.update(other.enumerations)
@@ -174,6 +175,7 @@ class IdlDefinitions(object):
# Callback Functions
################################################################################
+
class IdlCallbackFunction(TypedObject):
def __init__(self, node):
children = node.GetChildren()
@@ -185,12 +187,14 @@ class IdlCallbackFunction(TypedObject):
if num_children == 3:
ext_attributes_node = children[2]
self.extended_attributes = (
- ext_attributes_node_to_extended_attributes(ext_attributes_node))
+ ext_attributes_node_to_extended_attributes(ext_attributes_node)
+ )
else:
self.extended_attributes = {}
arguments_node_class = arguments_node.GetClass()
if arguments_node_class != 'Arguments':
- raise ValueError('Expected Arguments node, got %s' % arguments_node_class)
+ raise ValueError(
+ 'Expected Arguments node, got %s' % arguments_node_class)
self.name = node.GetName()
self.idl_type = type_node_to_type(type_node)
@@ -206,6 +210,7 @@ class IdlCallbackFunction(TypedObject):
# Dictionary
################################################################################
+
class IdlDictionary(object):
def __init__(self, node):
self.extended_attributes = {}
@@ -258,6 +263,7 @@ class IdlDictionaryMember(TypedObject):
# Enumerations
################################################################################
+
class IdlEnum(object):
def __init__(self, node):
self.name = node.GetName()
@@ -273,8 +279,9 @@ class IdlEnum(object):
# Typedefs
################################################################################
+
class IdlTypedef(object):
- idl_type_attributes = ('idl_type',)
+ idl_type_attributes = ('idl_type', )
def __init__(self, node):
self.name = node.GetName()
@@ -288,6 +295,7 @@ class IdlTypedef(object):
# Interfaces
################################################################################
+
class IdlInterface(object):
def __init__(self, node):
self.attributes = []
@@ -315,6 +323,14 @@ class IdlInterface(object):
has_indexed_property_getter = False
has_integer_typed_length = False
+ # These are used to support both constructor operations and old style
+ # [Constructor] extended attributes. Ideally we should do refactoring
+ # for constructor code generation but we will use a new code generator
+ # soon so this kind of workaround should be fine.
+ constructor_operations = []
+ custom_constructor_operations = []
+ constructor_operations_extended_attributes = {}
+
def is_blacklisted_attribute_type(idl_type):
return idl_type.is_callback_function or \
idl_type.is_dictionary or \
@@ -327,14 +343,17 @@ class IdlInterface(object):
if child_class == 'Attribute':
attr = IdlAttribute(child)
if is_blacklisted_attribute_type(attr.idl_type):
- raise ValueError('Type "%s" cannot be used as an attribute.' % attr.idl_type)
+ raise ValueError(
+ 'Type "%s" cannot be used as an attribute.' %
+ attr.idl_type)
if attr.idl_type.is_integer_type and attr.name == 'length':
has_integer_typed_length = True
self.attributes.append(attr)
elif child_class == 'Const':
self.constants.append(IdlConstant(child))
elif child_class == 'ExtAttributes':
- extended_attributes = ext_attributes_node_to_extended_attributes(child)
+ extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
self.constructors, self.custom_constructors = (
extended_attributes_to_constructors(extended_attributes))
clear_constructor_attributes(extended_attributes)
@@ -347,6 +366,20 @@ class IdlInterface(object):
elif str(op.arguments[0].idl_type) == 'DOMString':
self.has_named_property_getter = True
self.operations.append(op)
+ elif child_class == 'Constructor':
+ operation = constructor_operation_from_node(child)
+ if operation.is_custom:
+ custom_constructor_operations.append(operation.constructor)
+ else:
+ # Check extended attributes consistency when we previously
+ # handle constructor operations.
+ if constructor_operations:
+ check_constructor_operations_extended_attributes(
+ constructor_operations_extended_attributes,
+ operation.extended_attributes)
+ constructor_operations.append(operation.constructor)
+ constructor_operations_extended_attributes.update(
+ operation.extended_attributes)
elif child_class == 'Inherit':
self.parent = child.GetName()
elif child_class == 'Stringifier':
@@ -362,7 +395,9 @@ class IdlInterface(object):
raise ValueError('Unrecognized node class: %s' % child_class)
if len(filter(None, [self.iterable, self.maplike, self.setlike])) > 1:
- raise ValueError('Interface can only have one of iterable<>, maplike<> and setlike<>.')
+ raise ValueError(
+ 'Interface can only have one of iterable<>, maplike<> and setlike<>.'
+ )
# TODO(rakuco): This validation logic should be in v8_interface according to bashi@.
# At the moment, doing so does not work because several IDL files are partial Window
@@ -370,19 +405,39 @@ class IdlInterface(object):
# to prevent these partial interfaces from resetting has_named_property to False.
if 'LegacyUnenumerableNamedProperties' in self.extended_attributes and \
not self.has_named_property_getter:
- raise ValueError('[LegacyUnenumerableNamedProperties] can be used only in interfaces '
- 'that support named properties.')
+ raise ValueError(
+ '[LegacyUnenumerableNamedProperties] can be used only in interfaces '
+ 'that support named properties.')
if has_integer_typed_length and has_indexed_property_getter:
self.has_indexed_elements = True
else:
if self.iterable is not None and self.iterable.key_type is None:
- raise ValueError('Value iterators (iterable<V>) must be accompanied by an indexed '
- 'property getter and an integer-typed length attribute.')
+ raise ValueError(
+ 'Value iterators (iterable<V>) must be accompanied by an indexed '
+ 'property getter and an integer-typed length attribute.')
if 'Unforgeable' in self.extended_attributes:
raise ValueError('[Unforgeable] cannot appear on interfaces.')
+ if constructor_operations or custom_constructor_operations:
+ if self.constructors or self.custom_constructors:
+ raise ValueError('Detected mixed [Constructor] and consructor '
+ 'operations. Do not use both in a single '
+ 'interface.')
+ extended_attributes = (
+ convert_constructor_operations_extended_attributes(
+ constructor_operations_extended_attributes))
+ if any(name in extended_attributes.keys()
+ for name in self.extended_attributes.keys()):
+ raise ValueError('Detected mixed extended attributes for '
+ 'both [Constructor] and constructor '
+ 'operations. Do not use both in a single '
+ 'interface')
+ self.constructors = constructor_operations
+ self.custom_constructors = custom_constructor_operations
+ self.extended_attributes.update(extended_attributes)
+
def accept(self, visitor):
visitor.visit_interface(self)
for attribute in self.attributes:
@@ -423,9 +478,11 @@ class IdlInterface(object):
# Attributes
################################################################################
+
class IdlAttribute(TypedObject):
def __init__(self, node=None):
- self.is_read_only = bool(node.GetProperty('READONLY')) if node else False
+ self.is_read_only = bool(
+ node.GetProperty('READONLY')) if node else False
self.is_static = bool(node.GetProperty('STATIC')) if node else False
self.name = node.GetName() if node else None
self.idl_type = None
@@ -441,12 +498,15 @@ class IdlAttribute(TypedObject):
if child_class == 'Type':
self.idl_type = type_node_to_type(child)
elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
+ self.extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
else:
- raise ValueError('Unrecognized node class: %s' % child_class)
+ raise ValueError(
+ 'Unrecognized node class: %s' % child_class)
if 'Unforgeable' in self.extended_attributes and self.is_static:
- raise ValueError('[Unforgeable] cannot appear on static attributes.')
+ raise ValueError(
+ '[Unforgeable] cannot appear on static attributes.')
def accept(self, visitor):
visitor.visit_attribute(self)
@@ -456,6 +516,7 @@ class IdlAttribute(TypedObject):
# Constants
################################################################################
+
class IdlConstant(TypedObject):
def __init__(self, node):
children = node.GetChildren()
@@ -479,7 +540,8 @@ class IdlConstant(TypedObject):
if num_children == 3:
ext_attributes_node = children[2]
- self.extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node)
+ self.extended_attributes = ext_attributes_node_to_extended_attributes(
+ ext_attributes_node)
else:
self.extended_attributes = {}
@@ -491,6 +553,7 @@ class IdlConstant(TypedObject):
# Literals
################################################################################
+
class IdlLiteral(object):
def __init__(self, idl_type, value):
self.idl_type = idl_type
@@ -548,6 +611,7 @@ def default_node_to_idl_literal(node):
# Operations
################################################################################
+
class IdlOperation(TypedObject):
def __init__(self, node=None):
self.arguments = []
@@ -579,12 +643,14 @@ class IdlOperation(TypedObject):
elif child_class == 'Type':
self.idl_type = type_node_to_type(child)
elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
+ self.extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
else:
raise ValueError('Unrecognized node class: %s' % child_class)
if 'Unforgeable' in self.extended_attributes and self.is_static:
- raise ValueError('[Unforgeable] cannot appear on static operations.')
+ raise ValueError(
+ '[Unforgeable] cannot appear on static operations.')
@classmethod
def constructor_from_arguments_node(cls, name, arguments_node):
@@ -604,6 +670,7 @@ class IdlOperation(TypedObject):
# Arguments
################################################################################
+
class IdlArgument(TypedObject):
def __init__(self, node=None):
self.extended_attributes = {}
@@ -624,11 +691,14 @@ class IdlArgument(TypedObject):
if child_class == 'Type':
self.idl_type = type_node_to_type(child)
elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
+ self.extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
elif child_class == 'Argument':
child_name = child.GetName()
if child_name != '...':
- raise ValueError('Unrecognized Argument node; expected "...", got "%s"' % child_name)
+ raise ValueError(
+ 'Unrecognized Argument node; expected "...", got "%s"'
+ % child_name)
self.is_variadic = bool(child.GetProperty('ELLIPSIS'))
elif child_class == 'Default':
self.default_value = default_node_to_idl_literal(child)
@@ -653,6 +723,7 @@ def arguments_node_to_arguments(node):
# Stringifiers
################################################################################
+
class IdlStringifier(object):
def __init__(self, node):
self.attribute = None
@@ -668,7 +739,8 @@ class IdlStringifier(object):
if operation.name:
self.operation = operation
elif child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
+ self.extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
else:
raise ValueError('Unrecognized node class: %s' % child_class)
@@ -683,6 +755,7 @@ class IdlStringifier(object):
# Iterable, Maplike, Setlike
################################################################################
+
class IdlIterableOrMaplikeOrSetlike(TypedObject):
def __init__(self, node):
self.extended_attributes = {}
@@ -691,7 +764,8 @@ class IdlIterableOrMaplikeOrSetlike(TypedObject):
for child in node.GetChildren():
child_class = child.GetClass()
if child_class == 'ExtAttributes':
- self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
+ self.extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
elif child_class == 'Type':
self.type_children.append(child)
else:
@@ -711,7 +785,8 @@ class IdlIterable(IdlIterableOrMaplikeOrSetlike):
self.key_type = type_node_to_type(self.type_children[0])
self.value_type = type_node_to_type(self.type_children[1])
else:
- raise ValueError('Unexpected number of type children: %d' % len(self.type_children))
+ raise ValueError('Unexpected number of type children: %d' % len(
+ self.type_children))
del self.type_children
def accept(self, visitor):
@@ -730,7 +805,8 @@ class IdlMaplike(IdlIterableOrMaplikeOrSetlike):
self.key_type = type_node_to_type(self.type_children[0])
self.value_type = type_node_to_type(self.type_children[1])
else:
- raise ValueError('Unexpected number of children: %d' % len(self.type_children))
+ raise ValueError(
+ 'Unexpected number of children: %d' % len(self.type_children))
del self.type_children
def accept(self, visitor):
@@ -738,7 +814,7 @@ class IdlMaplike(IdlIterableOrMaplikeOrSetlike):
class IdlSetlike(IdlIterableOrMaplikeOrSetlike):
- idl_type_attributes = ('value_type',)
+ idl_type_attributes = ('value_type', )
def __init__(self, node):
super(IdlSetlike, self).__init__(node)
@@ -748,7 +824,8 @@ class IdlSetlike(IdlIterableOrMaplikeOrSetlike):
if len(self.type_children) == 1:
self.value_type = type_node_to_type(self.type_children[0])
else:
- raise ValueError('Unexpected number of children: %d' % len(self.type_children))
+ raise ValueError(
+ 'Unexpected number of children: %d' % len(self.type_children))
del self.type_children
def accept(self, visitor):
@@ -759,6 +836,7 @@ class IdlSetlike(IdlIterableOrMaplikeOrSetlike):
# Includes statements
################################################################################
+
class IdlIncludes(object):
def __init__(self, node):
self.interface = node.GetName()
@@ -772,12 +850,14 @@ class IdlIncludes(object):
# Extended attributes
################################################################################
+
class Exposure:
"""An Exposure holds one Exposed or RuntimeEnabled condition.
Each exposure has two properties: exposed and runtime_enabled.
Exposure(e, r) corresponds to [Exposed(e r)]. Exposure(e) corresponds to
[Exposed=e].
"""
+
def __init__(self, exposed, runtime_enabled=None):
self.exposed = exposed
self.runtime_enabled = runtime_enabled
@@ -801,8 +881,7 @@ def ext_attributes_node_to_extended_attributes(node):
# overloading, and thus are stored in temporary lists.
# However, Named Constructors cannot be overloaded, and thus do not have
# a list.
- # FIXME: move Constructor logic into separate function, instead of modifying
- # extended attributes in-place.
+ # TODO(bashi): Remove |constructors| and |custom_constructors|.
constructors = []
custom_constructors = []
extended_attributes = {}
@@ -812,7 +891,9 @@ def ext_attributes_node_to_extended_attributes(node):
if not children:
return None
if len(children) > 1:
- raise ValueError('ExtAttributes node with %s children, expected at most 1' % len(children))
+ raise ValueError(
+ 'ExtAttributes node with %s children, expected at most 1' %
+ len(children))
return children[0]
extended_attribute_node_list = node.GetChildren()
@@ -821,25 +902,29 @@ def ext_attributes_node_to_extended_attributes(node):
child = child_node(extended_attribute_node)
child_class = child and child.GetClass()
if name == 'Constructor':
- if child_class and child_class != 'Arguments':
- raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class)
- constructors.append(child)
+ raise ValueError('[Constructor] is deprecated. Use constructor '
+ 'operations')
elif name == 'CustomConstructor':
- if child_class and child_class != 'Arguments':
- raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class)
- custom_constructors.append(child)
+ raise ValueError('[CustomConstructor] is deprecated. Use '
+ 'constructor operations with [Custom]')
elif name == 'NamedConstructor':
if child_class and child_class != 'Call':
- raise ValueError('[NamedConstructor] only supports Call as child, but has child of class: %s' % child_class)
+ raise ValueError(
+ '[NamedConstructor] only supports Call as child, but has child of class: %s'
+ % child_class)
extended_attributes[name] = child
elif name == 'Exposed':
if child_class and child_class != 'Arguments':
- raise ValueError('[Exposed] only supports Arguments as child, but has child of class: %s' % child_class)
+ raise ValueError(
+ '[Exposed] only supports Arguments as child, but has child of class: %s'
+ % child_class)
exposures = []
if child_class == 'Arguments':
- exposures = [Exposure(exposed=str(arg.idl_type),
- runtime_enabled=arg.name)
- for arg in arguments_node_to_arguments(child)]
+ exposures = [
+ Exposure(
+ exposed=str(arg.idl_type), runtime_enabled=arg.name)
+ for arg in arguments_node_to_arguments(child)
+ ]
else:
value = extended_attribute_node.GetProperty('VALUE')
if type(value) is str:
@@ -848,7 +933,8 @@ def ext_attributes_node_to_extended_attributes(node):
exposures = [Exposure(exposed=v) for v in value]
extended_attributes[name] = exposures
elif child:
- raise ValueError('ExtAttributes node with unexpected children: %s' % name)
+ raise ValueError(
+ 'ExtAttributes node with unexpected children: %s' % name)
else:
value = extended_attribute_node.GetProperty('VALUE')
extended_attributes[name] = value
@@ -869,15 +955,21 @@ def extended_attributes_to_constructors(extended_attributes):
Auxiliary function for IdlInterface.__init__.
"""
+ # TODO(bashi): Remove 'Constructors' and 'CustomConstructors'.
+
constructor_list = extended_attributes.get('Constructors', [])
constructors = [
- IdlOperation.constructor_from_arguments_node('Constructor', arguments_node)
- for arguments_node in constructor_list]
+ IdlOperation.constructor_from_arguments_node('Constructor',
+ arguments_node)
+ for arguments_node in constructor_list
+ ]
custom_constructor_list = extended_attributes.get('CustomConstructors', [])
custom_constructors = [
- IdlOperation.constructor_from_arguments_node('CustomConstructor', arguments_node)
- for arguments_node in custom_constructor_list]
+ IdlOperation.constructor_from_arguments_node('CustomConstructor',
+ arguments_node)
+ for arguments_node in custom_constructor_list
+ ]
if 'NamedConstructor' in extended_attributes:
# FIXME: support overloaded named constructors, and make homogeneous
@@ -886,15 +978,102 @@ def extended_attributes_to_constructors(extended_attributes):
extended_attributes['NamedConstructor'] = call_node.GetName()
children = call_node.GetChildren()
if len(children) != 1:
- raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
+ raise ValueError('NamedConstructor node expects 1 child, got %s.' %
+ len(children))
arguments_node = children[0]
- named_constructor = IdlOperation.constructor_from_arguments_node('NamedConstructor', arguments_node)
+ named_constructor = IdlOperation.constructor_from_arguments_node(
+ 'NamedConstructor', arguments_node)
# FIXME: should return named_constructor separately; appended for Perl
constructors.append(named_constructor)
return constructors, custom_constructors
+class ConstructorOperation(object):
+ """Represents a constructor operation. This is a tentative object used to
+ create constructors in IdlInterface.
+ """
+
+ def __init__(self, constructor, extended_attributes, is_custom):
+ self.constructor = constructor
+ self.extended_attributes = extended_attributes
+ self.is_custom = is_custom
+
+
+def constructor_operation_from_node(node):
+ """Creates a ConstructorOperation from the given |node|.
+ """
+
+ arguments_node = None
+ extended_attributes = {}
+
+ for child in node.GetChildren():
+ child_class = child.GetClass()
+ if child_class == 'Arguments':
+ arguments_node = child
+ elif child_class == 'ExtAttributes':
+ extended_attributes = ext_attributes_node_to_extended_attributes(
+ child)
+ else:
+ raise ValueError('Unrecognized node class: %s' % child_class)
+
+ if not arguments_node:
+ raise ValueError('Expected Arguments node for constructor operation')
+
+ if 'Custom' in extended_attributes:
+ if extended_attributes['Custom']:
+ raise ValueError('[Custom] should not have a value on constructor '
+ 'operations')
+ del extended_attributes['Custom']
+ constructor = IdlOperation.constructor_from_arguments_node(
+ 'CustomConstructor', arguments_node)
+ return ConstructorOperation(
+ constructor, extended_attributes, is_custom=True)
+ else:
+ constructor = IdlOperation.constructor_from_arguments_node(
+ 'Constructor', arguments_node)
+ return ConstructorOperation(
+ constructor, extended_attributes, is_custom=False)
+
+
+def check_constructor_operations_extended_attributes(current_attrs, new_attrs):
+ """Raises a ValueError if two extended attribute lists have different values
+ of constructor related attributes.
+ """
+
+ attrs_to_check = ['CallWith', 'RaisesException']
+ for attr in attrs_to_check:
+ if current_attrs.get(attr) != new_attrs.get(attr):
+ raise ValueError('[{}] should have the same value on all '
+ 'constructor operations'.format(attr))
+
+
+def convert_constructor_operations_extended_attributes(extended_attributes):
+ """Converts extended attributes specified on constructor operations to
+ extended attributes for an interface definition (e.g. [ConstructorCallWith])
+ """
+
+ converted = {}
+ for name, value in extended_attributes.items():
+ if name == "CallWith":
+ converted["ConstructorCallWith"] = value
+ elif name == "RaisesException":
+ if value:
+ raise ValueError(
+ '[RaisesException] should not have a value on '
+ 'constructor operations')
+ converted["RaisesException"] = 'Constructor'
+ elif name == "MeasureAs":
+ converted["MeasureAs"] = value
+ elif name == "Measure":
+ converted["Measure"] = None
+ else:
+ raise ValueError(
+ '[{}] is not supported on constructor operations'.format(name))
+
+ return converted
+
+
def clear_constructor_attributes(extended_attributes):
# Deletes Constructor*s* (plural), sets Constructor (singular)
if 'Constructors' in extended_attributes:
@@ -909,14 +1088,17 @@ def clear_constructor_attributes(extended_attributes):
# Types
################################################################################
+
def type_node_to_type(node):
children = node.GetChildren()
if len(children) != 1 and len(children) != 2:
- raise ValueError('Type node expects 1 or 2 child(ren), got %d.' % len(children))
+ raise ValueError(
+ 'Type node expects 1 or 2 child(ren), got %d.' % len(children))
base_type = type_node_inner_to_type(children[0])
if len(children) == 2:
- extended_attributes = ext_attributes_node_to_extended_attributes(children[1])
+ extended_attributes = ext_attributes_node_to_extended_attributes(
+ children[1])
base_type = IdlAnnotatedType(base_type, extended_attributes)
if node.GetProperty('NULLABLE'):
@@ -950,21 +1132,25 @@ def type_node_inner_to_type(node):
def record_node_to_type(node):
children = node.GetChildren()
if len(children) != 2:
- raise ValueError('record<K,V> node expects exactly 2 children, got %d' % (len(children)))
+ raise ValueError('record<K,V> node expects exactly 2 children, got %d'
+ % (len(children)))
key_child = children[0]
value_child = children[1]
if key_child.GetClass() != 'StringType':
raise ValueError('Keys in record<K,V> nodes must be string types.')
if value_child.GetClass() != 'Type':
- raise ValueError('Unrecognized node class for record<K,V> value: %s' % value_child.GetClass())
- return IdlRecordType(IdlType(key_child.GetName()), type_node_to_type(value_child))
+ raise ValueError('Unrecognized node class for record<K,V> value: %s' %
+ value_child.GetClass())
+ return IdlRecordType(
+ IdlType(key_child.GetName()), type_node_to_type(value_child))
def sequence_node_to_type(node):
children = node.GetChildren()
class_name = node.GetClass()
if len(children) != 1:
- raise ValueError('%s node expects exactly 1 child, got %s' % (class_name, len(children)))
+ raise ValueError('%s node expects exactly 1 child, got %s' %
+ (class_name, len(children)))
sequence_child = children[0]
sequence_child_class = sequence_child.GetClass()
if sequence_child_class != 'Type':
@@ -984,7 +1170,8 @@ def sequence_node_to_type(node):
def typedef_node_to_type(node):
children = node.GetChildren()
if len(children) != 1:
- raise ValueError('Typedef node with %s children, expected 1' % len(children))
+ raise ValueError(
+ 'Typedef node with %s children, expected 1' % len(children))
child = children[0]
child_class = child.GetClass()
if child_class != 'Type':
@@ -993,8 +1180,10 @@ def typedef_node_to_type(node):
def union_type_node_to_idl_union_type(node):
- member_types = [type_node_to_type(member_type_node)
- for member_type_node in node.GetChildren()]
+ member_types = [
+ type_node_to_type(member_type_node)
+ for member_type_node in node.GetChildren()
+ ]
return IdlUnionType(member_types)
@@ -1002,6 +1191,7 @@ def union_type_node_to_idl_union_type(node):
# Visitor
################################################################################
+
class Visitor(object):
"""Abstract visitor class for IDL definitions traverse."""
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py
index 78dd7320744..e2a91843a9a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions_test.py
@@ -3,7 +3,6 @@
# found in the LICENSE file.
# pylint: disable=import-error,print-statement,relative-import
-
"""Unit tests for idl_definitions.py."""
import unittest
@@ -12,7 +11,6 @@ from idl_definitions import IdlAttribute
class IdlAttributeTest(unittest.TestCase):
-
def test_no_params(self):
try:
IdlAttribute()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py
index 3b0895ed5b5..8d72865a6ca 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_reader.py
@@ -25,7 +25,6 @@
# 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.
-
"""Read an IDL file or complete IDL interface, producing an IdlDefinitions object.
Design doc:
@@ -56,28 +55,28 @@ def validate_blink_idl_definitions(idl_filename, idl_file_basename,
definitions. There is no filename convention in this case.
- Otherwise, an IDL file is invalid.
"""
- targets = (definitions.interfaces.values() +
- definitions.dictionaries.values())
+ targets = (
+ definitions.interfaces.values() + definitions.dictionaries.values())
number_of_targets = len(targets)
if number_of_targets > 1:
raise Exception(
- 'Expected exactly 1 definition in file {0}, but found {1}'
- .format(idl_filename, number_of_targets))
+ 'Expected exactly 1 definition in file {0}, but found {1}'.format(
+ idl_filename, number_of_targets))
if number_of_targets == 0:
- number_of_definitions = (
- len(definitions.enumerations) + len(definitions.typedefs) +
- len(definitions.callback_functions))
+ number_of_definitions = (len(definitions.enumerations) + len(
+ definitions.typedefs) + len(definitions.callback_functions))
if number_of_definitions == 0:
- raise Exception(
- 'No definition found in %s' % idl_filename)
+ raise Exception('No definition found in %s. (Missing semicolon?)' %
+ idl_filename)
return
target = targets[0]
if target.is_partial:
return
- if target.name != idl_file_basename and to_snake_case(target.name) != idl_file_basename:
+ if (target.name != idl_file_basename
+ and to_snake_case(target.name) != idl_file_basename):
raise Exception(
- 'Definition name "{0}" disagrees with IDL file basename "{1}".'
- .format(target.name, idl_file_basename))
+ 'Definition name "{0}" disagrees with IDL file basename "{1}".'.
+ format(target.name, idl_file_basename))
class IdlReader(object):
@@ -86,7 +85,8 @@ class IdlReader(object):
self.interfaces_info = interfaces_info
if interfaces_info:
- self.interface_dependency_resolver = InterfaceDependencyResolver(interfaces_info, self)
+ self.interface_dependency_resolver = InterfaceDependencyResolver(
+ interfaces_info, self)
else:
self.interface_dependency_resolver = None
@@ -105,7 +105,8 @@ class IdlReader(object):
if not definitions.interfaces:
return {component: definitions}
- return self.interface_dependency_resolver.resolve_dependencies(definitions, component)
+ return self.interface_dependency_resolver.resolve_dependencies(
+ definitions, component)
def read_idl_file(self, idl_filename):
"""Returns an IdlDefinitions object for an IDL file, without any dependencies.
@@ -119,15 +120,16 @@ class IdlReader(object):
idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
definitions = IdlDefinitions(ast)
- validate_blink_idl_definitions(
- idl_filename, idl_file_basename, definitions)
+ validate_blink_idl_definitions(idl_filename, idl_file_basename,
+ definitions)
# Validate extended attributes
if not self.extended_attribute_validator:
return definitions
try:
- self.extended_attribute_validator.validate_extended_attributes(definitions)
+ self.extended_attribute_validator.validate_extended_attributes(
+ definitions)
except IDLInvalidExtendedAttributeError as error:
raise IDLInvalidExtendedAttributeError("""
IDL ATTRIBUTE ERROR in file:
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
index acb20cf69e0..cd4f0c3513b 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
@@ -18,7 +18,6 @@ IdlTypes are picklable because we store them in interfaces_info.
from collections import defaultdict
-
################################################################################
# IDL types
################################################################################
@@ -35,24 +34,26 @@ INTEGER_TYPES = frozenset([
'long long',
'unsigned long long',
])
-NUMERIC_TYPES = (INTEGER_TYPES | frozenset([
- # http://www.w3.org/TR/WebIDL/#dfn-numeric-type
- 'float',
- 'unrestricted float',
- 'double',
- 'unrestricted double',
-]))
+NUMERIC_TYPES = (
+ INTEGER_TYPES | frozenset([
+ # http://www.w3.org/TR/WebIDL/#dfn-numeric-type
+ 'float',
+ 'unrestricted float',
+ 'double',
+ 'unrestricted double',
+ ]))
# http://www.w3.org/TR/WebIDL/#dfn-primitive-type
PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES)
-BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([
- # Built-in, non-composite, non-object data types
- # http://heycam.github.io/webidl/#idl-types
- 'DOMString',
- 'ByteString',
- 'USVString',
- # http://heycam.github.io/webidl/#idl-types
- 'void',
-]))
+BASIC_TYPES = (
+ PRIMITIVE_TYPES | frozenset([
+ # Built-in, non-composite, non-object data types
+ # http://heycam.github.io/webidl/#idl-types
+ 'DOMString',
+ 'ByteString',
+ 'USVString',
+ # http://heycam.github.io/webidl/#idl-types
+ 'void',
+ ]))
TYPE_NAMES = {
# http://heycam.github.io/webidl/#dfn-type-name
'any': 'Any',
@@ -84,8 +85,10 @@ STRING_TYPES = frozenset([
])
EXTENDED_ATTRIBUTES_APPLICABLE_TO_TYPES = frozenset([
+ 'AllowShared',
'Clamp',
'EnforceRange',
+ 'StringContext',
'TreatNullAs',
])
@@ -95,9 +98,10 @@ EXTENDED_ATTRIBUTES_APPLICABLE_TO_TYPES = frozenset([
ancestors = defaultdict(list) # interface_name -> ancestors
+
def inherits_interface(interface_name, ancestor_name):
- return (interface_name == ancestor_name or
- ancestor_name in ancestors[interface_name])
+ return (interface_name == ancestor_name
+ or ancestor_name in ancestors[interface_name])
def set_ancestors(new_ancestors):
@@ -105,11 +109,12 @@ def set_ancestors(new_ancestors):
class IdlTypeBase(object):
- """Base class for IdlType, IdlUnionType, IdlArrayOrSequenceType and IdlNullableType."""
+ """Base class for IdlType, IdlUnionType, IdlArrayOrSequenceType
+ and IdlNullableType.
+ """
def __str__(self):
- raise NotImplementedError(
- '__str__() should be defined in subclasses')
+ raise NotImplementedError('__str__() should be defined in subclasses')
def __getattr__(self, name):
# Default undefined attributes to None (analogous to Jinja variables).
@@ -131,6 +136,7 @@ class IdlTypeBase(object):
# IdlType
################################################################################
+
class IdlType(IdlTypeBase):
# FIXME: incorporate Nullable, etc.
# to support types like short?[] vs. short[]?, instead of treating these
@@ -184,8 +190,8 @@ class IdlType(IdlTypeBase):
@property
def is_enum(self):
- # FIXME: add an IdlEnumType class and a resolve_enums step at end of
- # IdlDefinitions constructor
+ # FIXME: add an IdlEnumType class and a resolve_enums step
+ # at end of IdlDefinitions constructor
return self.name in IdlType.enums
@property
@@ -218,13 +224,10 @@ class IdlType(IdlTypeBase):
# http://www.w3.org/TR/WebIDL/#idl-types
# http://www.w3.org/TR/WebIDL/#idl-interface
# In C++ these are RefPtr types.
- return not(self.is_basic_type or
- self.is_callback_function or
- self.is_dictionary or
- self.is_enum or
- self.name == 'Any' or
- self.name == 'Object' or
- self.name == 'Promise') # Promise will be basic in future
+ return not (self.is_basic_type or self.is_callback_function
+ or self.is_dictionary or self.is_enum or self.name == 'Any'
+ or self.name == 'Object' or self.name == 'Promise'
+ ) # Promise will be basic in future
@property
def is_string_type(self):
@@ -256,15 +259,22 @@ class IdlType(IdlTypeBase):
cls.enums.update(new_enums)
def resolve_typedefs(self, typedefs):
- # This function either returns |self| or a different object.
- # FIXME: Rename typedefs_resolved().
- return typedefs.get(self.base_type, self)
+ base_type = self.base_type
+ if base_type in typedefs:
+ resolved_type = typedefs[base_type]
+ if resolved_type.base_type in typedefs:
+ raise ValueError("We can't typedef a typedef'ed type.")
+ # For the case that the resolved type contains other typedef'ed
+ # type(s).
+ return resolved_type.resolve_typedefs(typedefs)
+ return self
################################################################################
# IdlUnionType
################################################################################
+
class IdlUnionType(IdlTypeBase):
# http://heycam.github.io/webidl/#idl-union
# IdlUnionType has __hash__() and __eq__() methods because they are stored
@@ -274,7 +284,8 @@ class IdlUnionType(IdlTypeBase):
self.member_types = member_types
def __str__(self):
- return '(' + ' or '.join(str(member_type) for member_type in self.member_types) + ')'
+ return '(' + ' or '.join(
+ str(member_type) for member_type in self.member_types) + ')'
def __hash__(self):
return hash(self.name)
@@ -296,14 +307,16 @@ class IdlUnionType(IdlTypeBase):
https://heycam.github.io/webidl/#dfn-flattened-union-member-types
"""
- # We cannot use a set directly because each member is an IdlTypeBase-derived class, and
- # comparing two objects of the same type is not the same as comparing their names. In
- # other words:
+ # We cannot use a set directly because each member is an
+ # IdlTypeBase-derived class, and comparing two objects of the
+ # same type is not the same as comparing their names.
+ # In other words:
# x = IdlType('ByteString')
# y = IdlType('ByteString')
# x == y # False
# x.name == y.name # True
- # |flattened_members|'s keys are type names, the values are type |objects.
+ # |flattened_members|'s keys are type names, the values are type
+ # |objects|.
# We assume we can use two IDL objects of the same type interchangeably.
flattened_members = {}
for member in self.member_types:
@@ -344,8 +357,8 @@ class IdlUnionType(IdlTypeBase):
@property
def string_member_type(self):
return self.single_matching_member_type(
- lambda member_type: (member_type.is_string_type or
- member_type.is_enum))
+ lambda member_type: (member_type.is_string_type or member_type.is_enum)
+ )
@property
def numeric_member_type(self):
@@ -383,7 +396,8 @@ class IdlUnionType(IdlTypeBase):
def resolve_typedefs(self, typedefs):
self.member_types = [
member_type.resolve_typedefs(typedefs)
- for member_type in self.member_types]
+ for member_type in self.member_types
+ ]
return self
def idl_types(self):
@@ -397,6 +411,7 @@ class IdlUnionType(IdlTypeBase):
# IdlArrayOrSequenceType, IdlSequenceType, IdlFrozenArrayType
################################################################################
+
# TODO(bashi): Rename this like "IdlArrayTypeBase" or something.
class IdlArrayOrSequenceType(IdlTypeBase):
"""Base class for array-like types."""
@@ -479,6 +494,7 @@ class IdlFrozenArrayType(IdlArrayOrSequenceType):
# IdlRecordType
################################################################################
+
class IdlRecordType(IdlTypeBase):
def __init__(self, key_type, value_type):
super(IdlRecordType, self).__init__()
@@ -523,6 +539,7 @@ class IdlRecordType(IdlTypeBase):
# IdlNullableType
################################################################################
+
# https://heycam.github.io/webidl/#idl-nullable-type
class IdlNullableType(IdlTypeBase):
def __init__(self, inner_type):
@@ -599,9 +616,11 @@ class IdlNullableType(IdlTypeBase):
# IdlAnnotatedType
################################################################################
+
class IdlAnnotatedType(IdlTypeBase):
"""IdlAnnoatedType represents an IDL type with extended attributes.
- [Clamp], [EnforceRange], and [TreatNullAs] are applicable to types.
+ [Clamp], [EnforceRange], [StringContext], and [TreatNullAs] are applicable
+ to types.
https://heycam.github.io/webidl/#idl-annotated-types
"""
@@ -612,11 +631,18 @@ class IdlAnnotatedType(IdlTypeBase):
if any(key not in EXTENDED_ATTRIBUTES_APPLICABLE_TO_TYPES
for key in extended_attributes):
- raise ValueError('Extended attributes not applicable to types: %s' % self)
+ raise ValueError(
+ 'Extended attributes not applicable to types: %s' % self)
+
+ if ('StringContext' in extended_attributes
+ and inner_type.base_type not in ['DOMString', 'USVString']):
+ raise ValueError(
+ 'StringContext is only applicable to string types.')
def __str__(self):
- annotation = ', '.join((key + ('' if val is None else '=' + val))
- for key, val in self.extended_attributes.iteritems())
+ annotation = ', '.join(
+ (key + ('' if val is None else '=' + val))
+ for key, val in self.extended_attributes.items())
return '[%s] %s' % (annotation, str(self.inner_type))
def __getattr__(self, name):
@@ -637,9 +663,14 @@ class IdlAnnotatedType(IdlTypeBase):
return True
@property
+ def has_string_context(self):
+ return 'StringContext' in self.extended_attributes
+
+ @property
def name(self):
- annotation = ''.join((key + ('' if val is None else val))
- for key, val in sorted(self.extended_attributes.iteritems()))
+ annotation = ''.join(
+ (key + ('' if val is None else val))
+ for key, val in sorted(self.extended_attributes.items()))
return self.inner_type.name + annotation
def resolve_typedefs(self, typedefs):
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py
index 2948ca9922f..519fbcf84e8 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_types_test.py
@@ -3,7 +3,6 @@
# found in the LICENSE file.
# pylint: disable=import-error,print-statement,relative-import
-
"""Unit tests for idl_types.py."""
import unittest
@@ -16,7 +15,6 @@ from idl_types import IdlUnionType
class IdlTypeTest(unittest.TestCase):
-
def test_is_void(self):
idl_type = IdlType('void')
self.assertTrue(idl_type.is_void)
@@ -25,7 +23,6 @@ class IdlTypeTest(unittest.TestCase):
class IdlRecordTypeTest(unittest.TestCase):
-
def test_idl_types(self):
idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
idl_types = list(idl_type.idl_types())
@@ -33,21 +30,28 @@ class IdlRecordTypeTest(unittest.TestCase):
self.assertIs(idl_types[0], idl_type)
self.assertEqual(idl_types[1].name, 'USVString')
self.assertEqual(idl_types[2].name, 'Long')
- self.assertListEqual(list(idl_type.idl_types()),
- [idl_type, idl_type.key_type, idl_type.value_type])
+ self.assertListEqual(
+ list(idl_type.idl_types()),
+ [idl_type, idl_type.key_type, idl_type.value_type])
- idl_type = IdlRecordType(IdlType('DOMString'), IdlSequenceType(IdlType('unrestricted float')))
+ idl_type = IdlRecordType(
+ IdlType('DOMString'), IdlSequenceType(
+ IdlType('unrestricted float')))
idl_types = list(idl_type.idl_types())
self.assertEqual(len(idl_types), 4)
self.assertIs(idl_types[0], idl_type)
self.assertEqual(idl_types[1].name, 'String')
self.assertEqual(idl_types[2].name, 'UnrestrictedFloatSequence')
self.assertEqual(idl_types[3].name, 'UnrestrictedFloat')
- self.assertListEqual(list(idl_type.idl_types()),
- [idl_type, idl_type.key_type, idl_type.value_type, idl_type.value_type.element_type])
-
- idl_type = IdlRecordType(IdlType('ByteString'),
- IdlRecordType(IdlType('DOMString'), IdlType('octet')))
+ self.assertListEqual(
+ list(idl_type.idl_types()), [
+ idl_type, idl_type.key_type, idl_type.value_type,
+ idl_type.value_type.element_type
+ ])
+
+ idl_type = IdlRecordType(
+ IdlType('ByteString'),
+ IdlRecordType(IdlType('DOMString'), IdlType('octet')))
idl_types = list(idl_type.idl_types())
self.assertEqual(len(idl_types), 5)
self.assertIs(idl_types[0], idl_type)
@@ -55,38 +59,48 @@ class IdlRecordTypeTest(unittest.TestCase):
self.assertEqual(idl_types[2].name, 'StringOctetRecord')
self.assertEqual(idl_types[3].name, 'String')
self.assertEqual(idl_types[4].name, 'Octet')
- self.assertListEqual(list(idl_type.idl_types()),
- [idl_type, idl_type.key_type, idl_type.value_type, idl_type.value_type.key_type,
- idl_type.value_type.value_type])
+ self.assertListEqual(
+ list(idl_type.idl_types()), [
+ idl_type, idl_type.key_type, idl_type.value_type,
+ idl_type.value_type.key_type, idl_type.value_type.value_type
+ ])
def test_is_record(self):
idl_type = IdlType('USVString')
self.assertFalse(idl_type.is_record_type)
- idl_type = IdlSequenceType(IdlRecordType(IdlType('DOMString'), IdlType('byte')))
+ idl_type = IdlSequenceType(
+ IdlRecordType(IdlType('DOMString'), IdlType('byte')))
self.assertFalse(idl_type.is_record_type)
idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
self.assertTrue(idl_type.is_record_type)
- idl_type = IdlRecordType(IdlType('USVString'), IdlSequenceType(IdlType('boolean')))
+ idl_type = IdlRecordType(
+ IdlType('USVString'), IdlSequenceType(IdlType('boolean')))
self.assertTrue(idl_type.is_record_type)
def test_name(self):
idl_type = IdlRecordType(IdlType('ByteString'), IdlType('octet'))
self.assertEqual(idl_type.name, 'ByteStringOctetRecord')
- idl_type = IdlRecordType(IdlType('USVString'), IdlSequenceType(IdlType('double')))
+ idl_type = IdlRecordType(
+ IdlType('USVString'), IdlSequenceType(IdlType('double')))
self.assertEqual(idl_type.name, 'USVStringDoubleSequenceRecord')
- idl_type = IdlRecordType(IdlType('DOMString'),
- IdlRecordType(IdlType('ByteString'),
- IdlSequenceType(IdlType('unsigned short'))))
- self.assertEqual(idl_type.name, 'StringByteStringUnsignedShortSequenceRecordRecord')
+ idl_type = IdlRecordType(
+ IdlType('DOMString'),
+ IdlRecordType(
+ IdlType('ByteString'),
+ IdlSequenceType(IdlType('unsigned short'))))
+ self.assertEqual(idl_type.name,
+ 'StringByteStringUnsignedShortSequenceRecordRecord')
class IdlUnionTypeTest(unittest.TestCase):
-
def test_flattened_member_types(self):
- # We are only testing the algorithm here, so we do create some ambiguous union types.
+ # We are only testing the algorithm here, so we do create some
+ # ambiguous union types.
def compare_flattened_members(actual, expected):
- """Compare a set of IDL types by name, as the objects are different"""
+ """Compare a set of IDL types by name, as the objects
+ are different
+ """
actual_names = set([member.name for member in actual])
expected_names = set([member.name for member in expected])
self.assertEqual(actual_names, expected_names)
@@ -96,46 +110,80 @@ class IdlUnionTypeTest(unittest.TestCase):
idl_type.flattened_member_types,
set([IdlType('long'), IdlType('SomeInterface')]))
- idl_type = IdlUnionType([IdlUnionType([IdlType('ByteString'), IdlType('float')]),
- IdlType('boolean')])
+ idl_type = IdlUnionType([
+ IdlUnionType([IdlType('ByteString'),
+ IdlType('float')]),
+ IdlType('boolean')
+ ])
compare_flattened_members(
idl_type.flattened_member_types,
- set([IdlType('float'), IdlType('boolean'), IdlType('ByteString')]))
-
- idl_type = IdlUnionType([IdlUnionType([IdlType('ByteString'), IdlType('DOMString')]),
- IdlType('DOMString')])
+ set([IdlType('float'),
+ IdlType('boolean'),
+ IdlType('ByteString')]))
+
+ idl_type = IdlUnionType([
+ IdlUnionType([IdlType('ByteString'),
+ IdlType('DOMString')]),
+ IdlType('DOMString')
+ ])
compare_flattened_members(
idl_type.flattened_member_types,
- set([IdlType('DOMString'), IdlType('ByteString')]))
+ set([IdlType('DOMString'),
+ IdlType('ByteString')]))
idl_type = IdlUnionType(
- [IdlNullableType(IdlType('ByteString')), IdlType('byte')])
+ [IdlNullableType(IdlType('ByteString')),
+ IdlType('byte')])
compare_flattened_members(
idl_type.flattened_member_types,
set([IdlType('ByteString'), IdlType('byte')]))
- idl_type = IdlUnionType(
- [IdlNullableType(IdlType('ByteString')), IdlType('byte'),
- IdlUnionType([IdlType('ByteString'), IdlType('float')])])
+ idl_type = IdlUnionType([
+ IdlNullableType(IdlType('ByteString')),
+ IdlType('byte'),
+ IdlUnionType([IdlType('ByteString'),
+ IdlType('float')])
+ ])
self.assertEqual(len(idl_type.flattened_member_types), 3)
compare_flattened_members(
idl_type.flattened_member_types,
- set([IdlType('ByteString'), IdlType('byte'), IdlType('float')]))
-
- # From the example in the spec: "the flattened member types of the union type (Node or (sequence<long> or Event) or
- # (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>) are the six types Node, sequence<long>,
- # Event, XMLHttpRequest, DOMString and sequence<(sequence<double> or NodeList)>"
- idl_type = IdlUnionType(
- [IdlType('Node'),
- IdlUnionType([IdlSequenceType(IdlType('long')), IdlType('Event')]),
- IdlNullableType(IdlUnionType([IdlType('XMLHttpRequest'), IdlType('DOMString')])),
- IdlSequenceType(IdlUnionType([IdlSequenceType(IdlType('double')), IdlType('NodeList')]))])
+ set([IdlType('ByteString'),
+ IdlType('byte'),
+ IdlType('float')]))
+
+ # From the example in the spec: "the flattened member types of the
+ # union type (Node or (sequence<long> or Event) or
+ # (XMLHttpRequest or DOMString)? or
+ # sequence<(sequence<double> or NodeList)>) are the six types Node,
+ # sequence<long>, Event, XMLHttpRequest, DOMString and
+ # sequence<(sequence<double> or NodeList)>"
+ idl_type = IdlUnionType([
+ IdlType('Node'),
+ IdlUnionType([IdlSequenceType(IdlType('long')),
+ IdlType('Event')]),
+ IdlNullableType(
+ IdlUnionType([IdlType('XMLHttpRequest'),
+ IdlType('DOMString')])),
+ IdlSequenceType(
+ IdlUnionType(
+ [IdlSequenceType(IdlType('double')),
+ IdlType('NodeList')]))
+ ])
self.assertEqual(len(idl_type.flattened_member_types), 6)
compare_flattened_members(
idl_type.flattened_member_types,
- set([IdlType('Node'), IdlSequenceType(IdlType('long')), IdlType('Event'),
- IdlType('XMLHttpRequest'), IdlType('DOMString'),
- IdlSequenceType(IdlUnionType([IdlSequenceType(IdlType('double')), IdlType('NodeList')]))]))
+ set([
+ IdlType('Node'),
+ IdlSequenceType(IdlType('long')),
+ IdlType('Event'),
+ IdlType('XMLHttpRequest'),
+ IdlType('DOMString'),
+ IdlSequenceType(
+ IdlUnionType([
+ IdlSequenceType(IdlType('double')),
+ IdlType('NodeList')
+ ]))
+ ]))
def test_resolve_typedefs(self):
# This is a simplification of the typedef mechanism to avoid having to
@@ -147,13 +195,17 @@ class IdlUnionTypeTest(unittest.TestCase):
}
# (long long or MyBooleanType)
- union = IdlUnionType([IdlType('long long'), IdlType('MyBooleanType')]).resolve_typedefs(typedefs)
+ union = IdlUnionType(
+ [IdlType('long long'),
+ IdlType('MyBooleanType')]).resolve_typedefs(typedefs)
self.assertEqual(union.name, 'LongLongOrBoolean')
self.assertEqual(union.member_types[0].name, 'LongLong')
self.assertEqual(union.member_types[1].name, 'Boolean')
# (Foo or SomeInterfaceT)
- union = IdlUnionType([IdlType('Foo'), IdlType('SomeInterfaceT')]).resolve_typedefs(typedefs)
+ union = IdlUnionType(
+ [IdlType('Foo'),
+ IdlType('SomeInterfaceT')]).resolve_typedefs(typedefs)
self.assertEqual(union.name, 'UnsignedShortOrMyInterface')
self.assertEqual(union.member_types[0].name, 'UnsignedShort')
self.assertEqual(union.member_types[1].name, 'MyInterface')
@@ -161,16 +213,19 @@ class IdlUnionTypeTest(unittest.TestCase):
# (Foo or sequence<(MyBooleanType or double)>)
union = IdlUnionType([
IdlType('Foo'),
- IdlSequenceType(IdlUnionType([IdlType('MyBooleanType'),
- IdlType('double')]))]).resolve_typedefs(typedefs)
+ IdlSequenceType(
+ IdlUnionType([IdlType('MyBooleanType'),
+ IdlType('double')]))
+ ]).resolve_typedefs(typedefs)
self.assertEqual(union.name, 'UnsignedShortOrBooleanOrDoubleSequence')
self.assertEqual(union.member_types[0].name, 'UnsignedShort')
self.assertEqual(union.member_types[1].name, 'BooleanOrDoubleSequence')
- self.assertEqual(union.member_types[1].element_type.name, 'BooleanOrDouble')
- self.assertEqual(union.member_types[1].element_type.member_types[0].name,
- 'Boolean')
- self.assertEqual(union.member_types[1].element_type.member_types[1].name,
- 'Double')
+ self.assertEqual(union.member_types[1].element_type.name,
+ 'BooleanOrDouble')
+ self.assertEqual(
+ union.member_types[1].element_type.member_types[0].name, 'Boolean')
+ self.assertEqual(
+ union.member_types[1].element_type.member_types[1].name, 'Double')
self.assertEqual(2, len(union.flattened_member_types))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
index 85de1cc1d83..64e84ef7da1 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
@@ -25,13 +25,11 @@
# 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.
-
"""Validate extended attributes.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Extended-attribute-validation
"""
-
import os.path
import re
@@ -42,6 +40,7 @@ EXTENDED_ATTRIBUTES_RELATIVE_PATH = os.path.join('bindings',
EXTENDED_ATTRIBUTES_FILENAME = os.path.join(source_path,
EXTENDED_ATTRIBUTES_RELATIVE_PATH)
+
class IDLInvalidExtendedAttributeError(Exception):
pass
@@ -52,7 +51,7 @@ class IDLExtendedAttributeValidator(object):
def validate_extended_attributes(self, definitions):
# FIXME: this should be done when parsing the file, rather than after.
- for interface in definitions.interfaces.itervalues():
+ for interface in definitions.interfaces.values():
self.validate_extended_attributes_node(interface)
for attribute in interface.attributes:
self.validate_extended_attributes_node(attribute)
@@ -60,18 +59,17 @@ class IDLExtendedAttributeValidator(object):
self.validate_extended_attributes_node(operation)
for argument in operation.arguments:
self.validate_extended_attributes_node(argument)
- for dictionary in definitions.dictionaries.itervalues():
+ for dictionary in definitions.dictionaries.values():
self.validate_extended_attributes_node(dictionary)
for member in dictionary.members:
self.validate_extended_attributes_node(member)
- for callback_function in definitions.callback_functions.itervalues():
+ for callback_function in definitions.callback_functions.values():
self.validate_extended_attributes_node(callback_function)
for argument in callback_function.arguments:
self.validate_extended_attributes_node(argument)
-
def validate_extended_attributes_node(self, node):
- for name, values_string in node.extended_attributes.iteritems():
+ for name, values_string in node.extended_attributes.items():
self.validate_name_values_string(name, values_string)
def validate_name_values_string(self, name, values_string):
@@ -106,7 +104,9 @@ def read_extended_attributes_file():
if not line or line.startswith('#'):
continue
name, _, values_string = map(str.strip, line.partition('='))
- value_list = [value.strip() for value in values_string.split('|')]
+ value_list = [
+ value.strip() for value in values_string.split('|')
+ ]
yield name, value_list
valid_extended_attributes = {}
@@ -114,6 +114,6 @@ def read_extended_attributes_file():
if not value_list:
valid_extended_attributes[name] = set([None])
continue
- valid_extended_attributes[name] = set([value if value else None
- for value in value_list])
+ valid_extended_attributes[name] = set(
+ [value if value else None for value in value_list])
return valid_extended_attributes
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
index ebd88a668ec..030ca1c9f9c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
@@ -25,7 +25,6 @@
# 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
@@ -102,7 +101,7 @@ class InterfaceDependencyResolver(object):
'this definition: %s, because this should '
'have a dictionary.' % definitions.idl_name)
- target_interface = next(definitions.interfaces.itervalues())
+ target_interface = next(iter(definitions.interfaces.values()))
interface_name = target_interface.name
interface_info = self.interfaces_info[interface_name]
@@ -111,34 +110,36 @@ class InterfaceDependencyResolver(object):
interface_info['inherited_extended_attributes'])
resolved_definitions = merge_interface_dependencies(
- definitions,
- component,
- target_interface,
+ 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)
+ inherit_unforgeable_attributes(resolved_definitions,
+ self.interfaces_info)
- for referenced_interface_name in interface_info['referenced_interfaces']:
+ 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):
+ 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,
+ 'in %s' % (definitions.idl_name, component,
referenced_interface_name,
referenced_component))
- resolved_definitions[component].update(referenced_definitions[component])
+ resolved_definitions[component].update(
+ referenced_definitions[component])
return resolved_definitions
-def merge_interface_dependencies(definitions, component, target_interface, dependency_idl_filenames, reader):
+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:
@@ -158,9 +159,11 @@ def merge_interface_dependencies(definitions, component, target_interface, depen
# 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_component = idl_filename_to_component(
+ dependency_idl_filename)
- dependency_interface = next(dependency_definitions.interfaces.itervalues())
+ dependency_interface = next(
+ iter(dependency_definitions.interfaces.values()))
transfer_extended_attributes(dependency_interface,
dependency_idl_filename)
@@ -176,12 +179,13 @@ def merge_interface_dependencies(definitions, component, target_interface, depen
# 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 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
@@ -189,12 +193,16 @@ def merge_interface_dependencies(definitions, component, target_interface, depen
# 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)
+ 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]
+ 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.
@@ -208,7 +216,8 @@ def merge_interface_dependencies(definitions, component, target_interface, depen
# 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.extended_attributes.pop(
+ 'ImplementedAs', None)
dependency_interface.original_interface = target_interface
target_interface.partial_interfaces.append(dependency_interface)
resolved_definitions[dependency_component] = dependency_definitions
@@ -221,20 +230,21 @@ def merge_interface_dependencies(definitions, component, target_interface, depen
# - 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))
-
- resolved_definitions[component].update(dependency_definitions) # merges partial interfaces
+ 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).
@@ -243,7 +253,8 @@ def merge_interface_dependencies(definitions, component, target_interface, depen
return resolved_definitions
-def transfer_extended_attributes(dependency_interface, dependency_idl_filename):
+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
@@ -263,7 +274,8 @@ def transfer_extended_attributes(dependency_interface, dependency_idl_filename):
if key not in dependency_interface.extended_attributes:
continue
- merged_extended_attributes[key] = dependency_interface.extended_attributes[key]
+ 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
@@ -307,11 +319,14 @@ def transfer_extended_attributes(dependency_interface, dependency_idl_filename):
attributes[key] = value
for attribute in dependency_interface.attributes:
- update_attributes(attribute.extended_attributes, merged_extended_attributes)
+ update_attributes(attribute.extended_attributes,
+ merged_extended_attributes)
for constant in dependency_interface.constants:
- update_attributes(constant.extended_attributes, merged_extended_attributes)
+ update_attributes(constant.extended_attributes,
+ merged_extended_attributes)
for operation in dependency_interface.operations:
- update_attributes(operation.extended_attributes, merged_extended_attributes)
+ update_attributes(operation.extended_attributes,
+ merged_extended_attributes)
def inherit_unforgeable_attributes(resolved_definitions, interfaces_info):
@@ -322,35 +337,47 @@ def inherit_unforgeable_attributes(resolved_definitions, interfaces_info):
'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)
+ 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', [])]
+ 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, {}))
+ cpp_includes.update(
+ interface.get('cpp_includes', {}).get(component, {}))
return unforgeable_attributes, referenced_interfaces, cpp_includes
- for component, definitions in resolved_definitions.iteritems():
- for interface_name, interface in definitions.interfaces.iteritems():
+ 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)
+ 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))
+ 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}})
+ {'cpp_includes': {
+ component: cpp_includes
+ }})
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py b/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py
index 351ca8e40ed..309de695493 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py
@@ -182,11 +182,12 @@ def method_overloads_by_name(methods):
"""Returns generator of overloaded methods by name: [name, [method]]"""
# Filter to only methods that are actually overloaded
method_counts = Counter(method['name'] for method in methods)
- overloaded_method_names = set(name
- for name, count in method_counts.iteritems()
- if count > 1)
- overloaded_methods = [method for method in methods
- if method['name'] in overloaded_method_names]
+ overloaded_method_names = set(
+ name for name, count in method_counts.items() if count > 1)
+ overloaded_methods = [
+ method for method in methods
+ if method['name'] in overloaded_method_names
+ ]
# Group by name (generally will be defined together, but not necessarily)
return sort_and_groupby(overloaded_methods, itemgetter('name'))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py b/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py
index 44ccd2095b1..3a94c06e615 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/overload_set_algorithm_test.py
@@ -3,12 +3,14 @@
# found in the LICENSE file.
# pylint: disable=import-error,print-statement,relative-import,protected-access
-
"""Unit tests for overload_set_algorithm.py."""
import unittest
from overload_set_algorithm import effective_overload_set
+# disabling yapf formating for complex data, see
+# https://github.com/google/yapf#why-does-yapf-destroy-my-awesome-formatting
+# yapf: disable
class EffectiveOverloadSetTest(unittest.TestCase):
def test_example_in_comments(self):
@@ -334,3 +336,4 @@ class EffectiveOverloadSetTest(unittest.TestCase):
())]
self.assertEqual(effective_overload_set(operation_list), overload_set)
+# yapf: enable
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni b/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni
index 00a0b2a5ce5..9f1b79be3e6 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni
+++ b/chromium/third_party/blink/renderer/bindings/scripts/scripts.gni
@@ -125,9 +125,7 @@ template("generate_event_interfaces") {
output_file =
"$root_gen_dir/third_party/blink/renderer/" + invoker.output_file
- outputs = [
- output_file,
- ]
+ outputs = [ output_file ]
script = "//third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py"
args = [
@@ -161,7 +159,9 @@ template("idl_compiler") {
# "import site" to speed up startup. Figure out if we need this and do
# something similar (not really expressible in GN now).
_script = "//third_party/blink/renderer/bindings/scripts/idl_compiler.py"
- _inputs = idl_lexer_parser_files + idl_compiler_files # to be explicit (covered by parsetab)
+ _inputs =
+ idl_lexer_parser_files + idl_compiler_files # to be explicit (covered by
+ # parsetab)
_inputs += [
"$bindings_scripts_output_dir/lextab.py",
"$bindings_scripts_output_dir/parsetab.pickle",
@@ -250,7 +250,9 @@ template("idl_impl") {
idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
write_file(idl_files_list, rebase_path(invoker.dict_idls, root_build_dir))
- inputs = idl_lexer_parser_files + idl_compiler_files # to be explicit (covered by parsetab)
+ inputs =
+ idl_lexer_parser_files + idl_compiler_files # to be explicit (covered
+ # by parsetab)
inputs += [
"$bindings_scripts_output_dir/lextab.py",
"$bindings_scripts_output_dir/parsetab.pickle",
@@ -342,9 +344,7 @@ template("compute_global_objects") {
idl_files_list,
] + invoker.sources_generated + invoker.sources
- outputs = [
- invoker.output_file,
- ]
+ outputs = [ invoker.output_file ]
args = [
"--idl-files-list",
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/utilities.py b/chromium/third_party/blink/renderer/bindings/scripts/utilities.py
index ebca696912d..1dc06544585 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/utilities.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -1,24 +1,25 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Utility functions (file reading, simple IDL parsing by regexes) for IDL build.
Design doc: http://www.chromium.org/developers/design-documents/idl-build
"""
import os
-import cPickle as pickle
import re
import shlex
-import string
import subprocess
import sys
-sys.path.append(os.path.join(os.path.dirname(__file__),
- '..', '..', 'build', 'scripts'))
-from blinkbuild.name_style_converter import NameStyleConverter
+if sys.version_info.major == 2:
+ import cPickle as pickle
+else:
+ import pickle
+sys.path.append(
+ os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
+from blinkbuild.name_style_converter import NameStyleConverter
KNOWN_COMPONENTS = frozenset(['core', 'modules'])
KNOWN_COMPONENTS_WITH_TESTING = frozenset(['core', 'modules', 'testing'])
@@ -29,7 +30,8 @@ def idl_filename_to_basename(idl_filename):
return os.path.splitext(os.path.basename(idl_filename))[0]
-def idl_filename_to_component_with_known_components(idl_filename, known_components):
+def idl_filename_to_component_with_known_components(idl_filename,
+ known_components):
path = os.path.dirname(os.path.realpath(idl_filename))
while path:
dirname, basename = os.path.split(path)
@@ -42,11 +44,13 @@ def idl_filename_to_component_with_known_components(idl_filename, known_componen
def idl_filename_to_component(idl_filename):
- return idl_filename_to_component_with_known_components(idl_filename, KNOWN_COMPONENTS)
+ return idl_filename_to_component_with_known_components(
+ idl_filename, KNOWN_COMPONENTS)
def is_testing_target(idl_filename):
- component = idl_filename_to_component_with_known_components(idl_filename, KNOWN_COMPONENTS_WITH_TESTING)
+ component = idl_filename_to_component_with_known_components(
+ idl_filename, KNOWN_COMPONENTS_WITH_TESTING)
return component == 'testing'
@@ -69,6 +73,7 @@ class ComponentInfoProvider(object):
"""Base class of information provider which provides component-specific
information.
"""
+
def __init__(self):
pass
@@ -176,11 +181,14 @@ class ComponentInfoProviderModules(ComponentInfoProvider):
def union_types(self):
# Remove duplicate union types from component_info_modules to avoid
# generating multiple container generation.
- return self._component_info_modules['union_types'] - self._component_info_core['union_types']
+ return (self._component_info_modules['union_types'] -
+ self._component_info_core['union_types'])
def include_path_for_union_types(self, union_type):
- core_union_type_names = [core_union_type.name for core_union_type
- in self._component_info_core['union_types']]
+ core_union_type_names = [
+ core_union_type.name
+ for core_union_type in self._component_info_core['union_types']
+ ]
name = shorten_union_name(union_type)
if union_type.name in core_union_type_names:
return 'bindings/core/v8/%s.h' % to_snake_case(name)
@@ -201,7 +209,8 @@ class ComponentInfoProviderModules(ComponentInfoProvider):
def load_interfaces_info_overall_pickle(info_dir):
- with open(os.path.join(info_dir, 'interfaces_info.pickle')) as interface_info_file:
+ with open(os.path.join(info_dir,
+ 'interfaces_info.pickle')) as interface_info_file:
return pickle.load(interface_info_file)
@@ -210,7 +219,7 @@ def merge_dict_recursively(target, diff):
|target| will be updated with |diff|. Part of |diff| may be re-used in
|target|.
"""
- for key, value in diff.iteritems():
+ for key, value in diff.items():
if key not in target:
target[key] = value
elif type(value) == dict:
@@ -227,19 +236,26 @@ def merge_dict_recursively(target, diff):
def create_component_info_provider_core(info_dir):
interfaces_info = load_interfaces_info_overall_pickle(info_dir)
- with open(os.path.join(info_dir, 'core', 'component_info_core.pickle')) as component_info_file:
+ with open(
+ os.path.join(info_dir, 'core',
+ 'component_info_core.pickle')) as component_info_file:
component_info = pickle.load(component_info_file)
return ComponentInfoProviderCore(interfaces_info, component_info)
def create_component_info_provider_modules(info_dir):
interfaces_info = load_interfaces_info_overall_pickle(info_dir)
- with open(os.path.join(info_dir, 'core', 'component_info_core.pickle')) as component_info_file:
+ with open(
+ os.path.join(info_dir, 'core',
+ 'component_info_core.pickle')) as component_info_file:
component_info_core = pickle.load(component_info_file)
- with open(os.path.join(info_dir, 'modules', 'component_info_modules.pickle')) as component_info_file:
+ with open(
+ os.path.join(
+ info_dir, 'modules',
+ 'component_info_modules.pickle')) as component_info_file:
component_info_modules = pickle.load(component_info_file)
- return ComponentInfoProviderModules(
- interfaces_info, component_info_core, component_info_modules)
+ return ComponentInfoProviderModules(interfaces_info, component_info_core,
+ component_info_modules)
def create_component_info_provider(info_dir, component):
@@ -255,6 +271,7 @@ def create_component_info_provider(info_dir, component):
# Basic file reading/writing
################################################################################
+
def get_file_contents(filename):
with open(filename) as f:
return f.read()
@@ -270,7 +287,11 @@ def resolve_cygpath(cygdrive_names):
if not cygdrive_names:
return []
cmd = ['cygpath', '-f', '-', '-wa']
- process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ process = subprocess.Popen(
+ cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
idl_file_names = []
for file_name in cygdrive_names:
process.stdin.write('%s\n' % file_name)
@@ -285,10 +306,14 @@ def read_idl_files_list_from_file(filename):
"""Similar to read_file_to_list, but also resolves cygpath."""
with open(filename) as input_file:
file_names = sorted(shlex.split(input_file))
- idl_file_names = [file_name for file_name in file_names
- if not file_name.startswith('/cygdrive')]
- cygdrive_names = [file_name for file_name in file_names
- if file_name.startswith('/cygdrive')]
+ idl_file_names = [
+ file_name for file_name in file_names
+ if not file_name.startswith('/cygdrive')
+ ]
+ cygdrive_names = [
+ file_name for file_name in file_names
+ if file_name.startswith('/cygdrive')
+ ]
idl_file_names.extend(resolve_cygpath(cygdrive_names))
return idl_file_names
@@ -299,7 +324,7 @@ def read_pickle_files(pickle_filenames):
def read_pickle_file(pickle_filename):
- with open(pickle_filename) as pickle_file:
+ with open(pickle_filename, 'rb') as pickle_file:
return pickle.load(pickle_file)
@@ -311,12 +336,12 @@ def write_file(new_text, destination_filename):
return
destination_dirname = os.path.dirname(destination_filename)
- if not os.path.exists(destination_dirname):
+ if destination_dirname and not os.path.exists(destination_dirname):
os.makedirs(destination_dirname)
# Write file in binary so that when run on Windows, line endings are not
# converted
with open(destination_filename, 'wb') as destination_file:
- destination_file.write(new_text)
+ destination_file.write(new_text.encode('utf-8'))
def write_pickle_file(pickle_filename, data):
@@ -329,7 +354,7 @@ def write_pickle_file(pickle_filename, data):
except Exception:
# If trouble unpickling, overwrite
pass
- with open(pickle_filename, 'w') as pickle_file:
+ with open(pickle_filename, 'wb') as pickle_file:
pickle.dump(data, pickle_file)
@@ -342,6 +367,7 @@ def write_pickle_file(pickle_filename, data):
# Leading and trailing context (e.g. following '{') used to avoid false matches.
################################################################################
+
def is_non_legacy_callback_interface_from_idl(file_contents):
"""Returns True if the specified IDL is a non-legacy callback interface."""
match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents)
@@ -378,20 +404,24 @@ def match_interface_extended_attributes_and_name_from_idl(file_contents):
r'(\w+)\s*'
r'(:\s*\w+\s*)?'
r'{',
- file_contents, flags=re.DOTALL)
+ file_contents,
+ flags=re.DOTALL)
return match
def get_interface_extended_attributes_from_idl(file_contents):
- match = match_interface_extended_attributes_and_name_from_idl(file_contents)
+ match = match_interface_extended_attributes_and_name_from_idl(
+ file_contents)
if not match or not match.group(1):
return {}
extended_attributes_string = match.group(1).strip()
- parts = [extended_attribute.strip()
- for extended_attribute in re.split(',', extended_attributes_string)
- # Discard empty parts, which may exist due to trailing comma
- if extended_attribute.strip()]
+ parts = [
+ extended_attribute.strip()
+ for extended_attribute in re.split(',', extended_attributes_string)
+ # Discard empty parts, which may exist due to trailing comma
+ if extended_attribute.strip()
+ ]
# Joins |parts| with commas as far as the parences are not balanced,
# and then converts a (joined) term to a dict entry.
@@ -406,14 +436,15 @@ def get_interface_extended_attributes_from_idl(file_contents):
if parences < 0 or square_brackets < 0:
raise ValueError('You have more close braces than open braces.')
if parences == 0 and square_brackets == 0:
- name, _, value = map(string.strip, concatenated.partition('='))
+ name, _, value = map(str.strip, concatenated.partition('='))
extended_attributes[name] = value
concatenated = None
return extended_attributes
def get_interface_exposed_arguments(file_contents):
- match = match_interface_extended_attributes_and_name_from_idl(file_contents)
+ match = match_interface_extended_attributes_and_name_from_idl(
+ file_contents)
if not match or not match.group(1):
return None
@@ -422,15 +453,19 @@ def get_interface_exposed_arguments(file_contents):
if not match:
return None
arguments = []
- for argument in map(string.strip, match.group(1).split(',')):
+ for argument in map(str.strip, match.group(1).split(',')):
exposed, runtime_enabled = argument.split()
- arguments.append({'exposed': exposed, 'runtime_enabled': runtime_enabled})
+ arguments.append({
+ 'exposed': exposed,
+ 'runtime_enabled': runtime_enabled
+ })
return arguments
def get_first_interface_name_from_idl(file_contents):
- match = match_interface_extended_attributes_and_name_from_idl(file_contents)
+ match = match_interface_extended_attributes_and_name_from_idl(
+ file_contents)
if match:
return match.group(3)
return None
@@ -442,21 +477,28 @@ def get_first_interface_name_from_idl(file_contents):
def shorten_union_name(union_type):
aliases = {
# modules/canvas2d/CanvasRenderingContext2D.idl
- 'CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas': 'CanvasImageSource',
+ 'CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas':
+ 'CanvasImageSource',
# modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
# Due to html_canvas_element_module_support_webgl2_compute.idl and html_canvas_element_module.idl are exclusive in modules_idl_files.gni, they have same shorten name.
- 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext': 'RenderingContext',
+ 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext':
+ 'RenderingContext',
# modules/canvas/htmlcanvas/html_canvas_element_module.idl
- 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext': 'RenderingContext',
+ 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrGPUCanvasContext':
+ 'RenderingContext',
# core/frame/window_or_worker_global_scope.idl
- 'HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas': 'ImageBitmapSource',
+ 'HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas':
+ 'ImageBitmapSource',
# bindings/tests/idls/core/TestTypedefs.idl
- 'NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord': 'NestedUnionType',
+ 'NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord':
+ 'NestedUnionType',
# modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl.
# Due to offscreen_canvas_module_support_webgl2_compute.idl and offscreen_canvas_module.idl are exclusive in modules_idl_files.gni, they have same shorten name.
- 'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContext': 'OffscreenRenderingContext',
+ 'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContext':
+ 'OffscreenRenderingContext',
# modules/canvas/offscreencanvas/offscreen_canvas_module.idl
- 'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContext': 'OffscreenRenderingContext',
+ 'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContext':
+ 'OffscreenRenderingContext',
}
idl_type = union_type
@@ -563,7 +605,8 @@ def format_blink_cpp_source_code(text):
if was_open_brace:
# No empty line just after an open brace.
pass
- elif match and match.group('first') == '}' and 'namespace' not in line:
+ elif (match and match.group('first') == '}'
+ and 'namespace' not in line):
# No empty line just before a closing brace.
pass
else:
@@ -578,7 +621,8 @@ def format_blink_cpp_source_code(text):
match = re_last_brace.search(line)
else:
match = None
- was_open_brace = (match and match.group('last') == '{' and 'namespace' not in line)
+ was_open_brace = (match and match.group('last') == '{'
+ and 'namespace' not in line)
# Let |'\n'.join| emit the last newline.
if output:
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
index e58cc6148f5..26fbd984024 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
@@ -27,7 +27,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pylint: disable=relative-import
-
"""Generate template values for attributes.
Extends IdlType with property |constructor_type_name|.
@@ -38,17 +37,23 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(__file__),
- '..', '..', 'build', 'scripts'))
+sys.path.append(
+ os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
from blinkbuild.name_style_converter import NameStyleConverter
import idl_types
from idl_types import inherits_interface
from v8_globals import includes
import v8_types
import v8_utilities
-from v8_utilities import (cpp_name_or_partial, capitalize, cpp_name, has_extended_attribute,
- has_extended_attribute_value, scoped_name, strip_suffix,
- uncapitalize, extended_attribute_value_as_list, is_unforgeable)
+from v8_utilities import capitalize
+from v8_utilities import cpp_encoded_property_name
+from v8_utilities import cpp_name
+from v8_utilities import extended_attribute_value_as_list
+from v8_utilities import has_extended_attribute_value
+from v8_utilities import is_unforgeable
+from v8_utilities import scoped_name
+from v8_utilities import strip_suffix
+from v8_utilities import uncapitalize
from blinkbuild.name_style_converter import NameStyleConverter
@@ -73,14 +78,14 @@ def attribute_context(interface, attribute, interfaces, component_info):
idl_type.add_includes_for_type(extended_attributes)
if idl_type.enum_values:
includes.add('core/inspector/console_message.h')
+ includes.add('platform/heap/heap.h')
# [CheckSecurity]
is_cross_origin = 'CrossOrigin' in extended_attributes
- is_check_security_for_receiver = (
- has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and
- is_cross_origin)
- is_check_security_for_return_value = (
- has_extended_attribute_value(attribute, 'CheckSecurity', 'ReturnValue'))
+ is_check_security_for_receiver = (has_extended_attribute_value(
+ interface, 'CheckSecurity', 'Receiver') and is_cross_origin)
+ is_check_security_for_return_value = (has_extended_attribute_value(
+ attribute, 'CheckSecurity', 'ReturnValue'))
if is_check_security_for_receiver or is_check_security_for_return_value:
includes.add('bindings/core/v8/binding_security.h')
if is_check_security_for_return_value:
@@ -93,7 +98,8 @@ def attribute_context(interface, attribute, interfaces, component_info):
# TODO(yukishiino): Constructors are much like methods although constructors
# are not methods. Constructors must be data-type properties, and we can
# support them as a kind of methods.
- constructor_type = idl_type.constructor_type_name if is_constructor_attribute(attribute) else None
+ constructor_type = idl_type.constructor_type_name if is_constructor_attribute(
+ attribute) else None
# [CEReactions]
is_ce_reactions = 'CEReactions' in extended_attributes
if is_ce_reactions:
@@ -111,11 +117,17 @@ def attribute_context(interface, attribute, interfaces, component_info):
includes.add('core/html/custom/v0_custom_element_processing_stack.h')
# [PerWorldBindings]
if 'PerWorldBindings' in extended_attributes:
- assert idl_type.is_wrapper_type or 'LogActivity' in extended_attributes, '[PerWorldBindings] should only be used with wrapper types: %s.%s' % (interface.name, attribute.name)
+ assert idl_type.is_wrapper_type or 'LogActivity' in \
+ extended_attributes, \
+ '[PerWorldBindings] should only be used with wrapper types: %s.%s' % \
+ (interface.name, attribute.name)
# [SaveSameObject]
- is_save_same_object = (
- 'SameObject' in attribute.extended_attributes and
- 'SaveSameObject' in attribute.extended_attributes)
+ is_save_same_object = ('SameObject' in attribute.extended_attributes and
+ 'SaveSameObject' in attribute.extended_attributes)
+
+ # [StringContext]
+ if idl_type.has_string_context:
+ includes.add('bindings/core/v8/generated_code_helper.h')
# [CachedAccessor]
is_cached_accessor = 'CachedAccessor' in extended_attributes
@@ -124,40 +136,29 @@ def attribute_context(interface, attribute, interfaces, component_info):
is_lenient_setter = 'LenientSetter' in extended_attributes
# [CachedAttribute]
- cached_attribute_validation_method = extended_attributes.get('CachedAttribute')
+ cached_attribute_validation_method = extended_attributes.get(
+ 'CachedAttribute')
keep_alive_for_gc = is_keep_alive_for_gc(interface, attribute)
- does_generate_getter = (
- not has_custom_getter(attribute) and
- not constructor_type
- )
+ does_generate_getter = (not has_custom_getter(attribute)
+ and not constructor_type)
does_generate_setter = (
- has_setter(interface, attribute) and
- not (has_custom_setter(attribute) or is_lenient_setter)
- )
-
- use_private_property_in_getter = (
- does_generate_getter and (
- cached_attribute_validation_method or
- is_save_same_object or
- keep_alive_for_gc
- )
- )
- use_private_property_in_setter = (
- does_generate_setter and
- cached_attribute_validation_method
- )
+ has_setter(interface, attribute)
+ and not (has_custom_setter(attribute) or is_lenient_setter))
+
+ use_private_property_in_getter = (does_generate_getter
+ and (cached_attribute_validation_method
+ or is_save_same_object
+ or keep_alive_for_gc))
+ use_private_property_in_setter = (does_generate_setter
+ and cached_attribute_validation_method)
private_property_is_shared_between_getter_and_setter = (
- use_private_property_in_getter and
- use_private_property_in_setter
- )
-
- does_use_private_property = (
- use_private_property_in_getter or
- use_private_property_in_setter or
- is_cached_accessor
- )
+ use_private_property_in_getter and use_private_property_in_setter)
+
+ does_use_private_property = (use_private_property_in_getter
+ or use_private_property_in_setter
+ or is_cached_accessor)
if does_use_private_property:
includes.add('platform/bindings/v8_private_property.h')
@@ -178,29 +179,50 @@ def attribute_context(interface, attribute, interfaces, component_info):
runtime_features = component_info['runtime_enabled_features']
+ internal_name = cpp_encoded_property_name(attribute)
+
+ cpp_type = idl_type.cpp_type
+ if idl_type.is_explicit_nullable:
+ cpp_type = v8_types.cpp_template_type('base::Optional', cpp_type)
+
context = {
- 'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'), # [ActivityLogging]
- 'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'), # [ActivityLogging]
- 'activity_logging_world_check': v8_utilities.activity_logging_world_check(attribute), # [ActivityLogging]
- 'cached_accessor_name': '%s%sCachedAccessor' % (interface.name, attribute.name.capitalize()),
- 'cached_attribute_validation_method': cached_attribute_validation_method,
- 'camel_case_name': NameStyleConverter(attribute.name).to_upper_camel_case(),
- 'constructor_type': constructor_type,
- 'context_enabled_feature_name': v8_utilities.context_enabled_feature_name(attribute),
+ # [ActivityLogging]
+ 'activity_logging_world_list_for_getter':
+ v8_utilities.activity_logging_world_list(attribute, 'Getter'),
+ # [ActivityLogging]
+ 'activity_logging_world_list_for_setter':
+ v8_utilities.activity_logging_world_list(attribute, 'Setter'),
+ # [ActivityLogging]
+ 'activity_logging_world_check':
+ v8_utilities.activity_logging_world_check(attribute),
+ 'cached_accessor_name':
+ '%s%sCachedAccessor' % (interface.name, attribute.name.capitalize()),
+ 'cached_attribute_validation_method':
+ cached_attribute_validation_method,
+ 'camel_case_name':
+ NameStyleConverter(internal_name).to_upper_camel_case(),
+ 'constructor_type':
+ constructor_type,
+ 'context_enabled_feature_name':
+ v8_utilities.context_enabled_feature_name(attribute),
'cpp_name': cpp_name(attribute),
- 'cpp_type': idl_type.cpp_type,
+ 'cpp_type': cpp_type,
'cpp_type_initializer': idl_type.cpp_type_initializer,
'deprecate_as': deprecate_as,
'does_generate_getter': does_generate_getter,
'does_generate_setter': does_generate_setter,
'enum_type': idl_type.enum_type,
'enum_values': idl_type.enum_values,
- 'exposed_test': v8_utilities.exposed(attribute, interface), # [Exposed]
- 'getter_has_no_side_effect': has_extended_attribute_value(attribute, 'Affects', 'Nothing'),
+ # [Exposed]
+ 'exposed_test':
+ v8_utilities.exposed(attribute, interface),
+ 'getter_has_no_side_effect':
+ has_extended_attribute_value(attribute, 'Affects', 'Nothing'),
'has_cross_origin_getter':
has_extended_attribute_value(attribute, 'CrossOrigin', None) or
has_extended_attribute_value(attribute, 'CrossOrigin', 'Getter'),
- 'has_cross_origin_setter': has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'),
+ 'has_cross_origin_setter':
+ has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'),
'has_custom_getter': has_custom_getter(attribute),
'has_custom_setter': has_custom_setter(attribute),
'has_promise_type': idl_type.name == 'Promise',
@@ -208,11 +230,14 @@ def attribute_context(interface, attribute, interfaces, component_info):
'high_entropy': high_entropy,
'idl_type': str(idl_type),
'is_cached_accessor': is_cached_accessor,
- 'is_call_with_execution_context': has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'),
- 'is_call_with_script_state': has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'),
+ 'is_call_with_execution_context':
+ has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'),
+ 'is_call_with_script_state':
+ has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'),
'is_ce_reactions': is_ce_reactions,
'is_check_security_for_receiver': is_check_security_for_receiver,
- 'is_check_security_for_return_value': is_check_security_for_return_value,
+ 'is_check_security_for_return_value':
+ is_check_security_for_return_value,
'is_custom_element_callbacks': is_custom_element_callbacks,
# TODO(yukishiino): Make all DOM attributes accessor-type properties.
'is_data_type_property': is_data_type_property(interface, attribute),
@@ -242,9 +267,11 @@ def attribute_context(interface, attribute, interfaces, component_info):
'on_instance': v8_utilities.on_instance(interface, attribute),
'on_interface': v8_utilities.on_interface(interface, attribute),
'on_prototype': v8_utilities.on_prototype(interface, attribute),
+ # [RuntimeEnabled] for origin trial
'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(attribute, runtime_features), # [RuntimeEnabled] for origin trial
- 'private_property_is_shared_between_getter_and_setter': private_property_is_shared_between_getter_and_setter,
+ v8_utilities.origin_trial_feature_name(attribute, runtime_features),
+ 'private_property_is_shared_between_getter_and_setter':
+ private_property_is_shared_between_getter_and_setter,
'property_attributes': property_attributes(interface, attribute),
'reflect_empty': cpp_content_attribute_value_name(
interface, extended_attributes.get('ReflectEmpty')),
@@ -253,9 +280,11 @@ def attribute_context(interface, attribute, interfaces, component_info):
'reflect_missing': cpp_content_attribute_value_name(
interface, extended_attributes.get('ReflectMissing')),
'reflect_only': reflect_only,
+ # [RuntimeEnabled] if not in origin trial
'runtime_enabled_feature_name':
- v8_utilities.runtime_enabled_feature_name(attribute, runtime_features), # [RuntimeEnabled] if not in origin trial
- 'secure_context_test': v8_utilities.secure_context(attribute, interface), # [SecureContext]
+ v8_utilities.runtime_enabled_feature_name(attribute, runtime_features),
+ # [SecureContext]
+ 'secure_context_test': v8_utilities.secure_context(attribute, interface),
'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
'world_suffixes': (
['', 'ForMainWorld']
@@ -275,28 +304,38 @@ def attribute_context(interface, attribute, interfaces, component_info):
# for them here.
if is_cross_origin:
if context['has_cross_origin_setter'] and context['has_custom_setter']:
- raise Exception('[CrossOrigin] and [Custom] are incompatible on the same setter: %s.%s', interface.name, attribute.name)
+ raise Exception(
+ '[CrossOrigin] and [Custom] are incompatible on the same setter: %s.%s',
+ interface.name, attribute.name)
if context['is_per_world_bindings']:
- raise Exception('[CrossOrigin] and [PerWorldBindings] are incompatible: %s.%s', interface.name, attribute.name)
+ raise Exception(
+ '[CrossOrigin] and [PerWorldBindings] are incompatible: %s.%s',
+ interface.name, attribute.name)
if context['constructor_type']:
- raise Exception('[CrossOrigin] cannot be used for constructors: %s.%s', interface.name, attribute.name)
+ raise Exception(
+ '[CrossOrigin] cannot be used for constructors: %s.%s',
+ interface.name, attribute.name)
return context
def runtime_call_stats_context(interface, attribute, context):
includes.add('platform/bindings/runtime_call_stats.h')
- generic_counter_name = 'Blink_' + v8_utilities.cpp_name(interface) + '_' + attribute.name
- (counter, extended_attribute_defined) = v8_utilities.rcs_counter_name(attribute, generic_counter_name)
+ generic_counter_name = (
+ 'Blink_' + v8_utilities.cpp_name(interface) + '_' + attribute.name)
+ (counter, extended_attribute_defined) = v8_utilities.rcs_counter_name(
+ attribute, generic_counter_name)
runtime_call_stats = {
- 'extended_attribute_defined': extended_attribute_defined,
- 'getter_counter': '%s_Getter' % counter,
- 'setter_counter': '%s_Setter' % counter,
- 'constructor_getter_callback_counter': '%s_ConstructorGetterCallback' % generic_counter_name,
+ 'extended_attribute_defined':
+ extended_attribute_defined,
+ 'getter_counter':
+ '%s_Getter' % counter,
+ 'setter_counter':
+ '%s_Setter' % counter,
+ 'constructor_getter_callback_counter':
+ '%s_ConstructorGetterCallback' % generic_counter_name,
}
- context.update({
- 'runtime_call_stats': runtime_call_stats
- })
+ context.update({'runtime_call_stats': runtime_call_stats})
def is_origin_trial_enabled(attribute):
@@ -308,46 +347,51 @@ def is_secure_context(attribute):
def filter_accessors(attributes):
- return [attribute for attribute in attributes if
- not (attribute['exposed_test'] or
- is_secure_context(attribute) or
- attribute['context_enabled_feature_name'] or
- is_origin_trial_enabled(attribute) or
- attribute['runtime_enabled_feature_name']) and
- not attribute['is_data_type_property']]
+ return [
+ attribute for attribute in attributes
+ if not (attribute['exposed_test'] or is_secure_context(attribute)
+ or attribute['context_enabled_feature_name']
+ or is_origin_trial_enabled(attribute)
+ or attribute['runtime_enabled_feature_name'])
+ and not attribute['is_data_type_property']
+ ]
def is_data_attribute(attribute):
- return (not (attribute['exposed_test'] or
- is_secure_context(attribute) or
- attribute['context_enabled_feature_name'] or
- is_origin_trial_enabled(attribute) or
- attribute['runtime_enabled_feature_name']) and
- attribute['is_data_type_property'])
+ return (not (attribute['exposed_test'] or is_secure_context(attribute)
+ or attribute['context_enabled_feature_name']
+ or is_origin_trial_enabled(attribute)
+ or attribute['runtime_enabled_feature_name'])
+ and attribute['is_data_type_property'])
def filter_data_attributes(attributes):
- return [attribute for attribute in attributes if is_data_attribute(attribute)]
+ return [
+ attribute for attribute in attributes if is_data_attribute(attribute)
+ ]
def filter_runtime_enabled(attributes):
- return [attribute for attribute in attributes if
- not (attribute['exposed_test'] or
- is_secure_context(attribute)) and
- attribute['runtime_enabled_feature_name']]
+ return [
+ attribute for attribute in attributes
+ if not (attribute['exposed_test'] or is_secure_context(attribute))
+ and attribute['runtime_enabled_feature_name']
+ ]
def filter_conditionally_enabled(attributes):
- return [attribute for attribute in attributes if
- attribute['exposed_test'] or
- (is_secure_context(attribute) and
- not is_origin_trial_enabled(attribute))]
+ return [
+ attribute for attribute in attributes
+ if attribute['exposed_test'] or (is_secure_context(
+ attribute) and not is_origin_trial_enabled(attribute))
+ ]
################################################################################
# Getter
################################################################################
+
def getter_context(interface, attribute, context):
idl_type = attribute.idl_type
base_idl_type = idl_type.base_type
@@ -360,51 +404,68 @@ def getter_context(interface, attribute, context):
# exceptions), we need to use a local variable.
# FIXME: check if compilers are smart enough to inline this, and if so,
# always use a local variable (for readability and CG simplicity).
- if (idl_type.is_explicit_nullable or
- base_idl_type == 'EventHandler' or
- 'CachedAttribute' in extended_attributes or
- 'ReflectOnly' in extended_attributes or
- context['is_keep_alive_for_gc'] or
- context['is_getter_raises_exception']):
+ if (idl_type.is_explicit_nullable or base_idl_type == 'EventHandler'
+ or 'CachedAttribute' in extended_attributes
+ or 'ReflectOnly' in extended_attributes
+ or context['is_keep_alive_for_gc']
+ or context['is_getter_raises_exception']):
context['cpp_value_original'] = cpp_value
cpp_value = 'cpp_value'
def v8_set_return_value_statement(for_main_world=False):
- if context['is_keep_alive_for_gc'] or 'CachedAttribute' in extended_attributes:
+ if (context['is_keep_alive_for_gc']
+ or 'CachedAttribute' in extended_attributes):
return 'V8SetReturnValue(info, v8_value)'
+ if idl_type.is_explicit_nullable:
+ cpp_return_value = 'cpp_value.value()'
+ if idl_type.is_frozen_array:
+ cpp_return_value = 'FreezeV8Object(ToV8(cpp_value.value(), info.Holder(), info.GetIsolate()), info.GetIsolate())'
+ return 'V8SetReturnValue(info, {})'.format(cpp_return_value)
return idl_type.v8_set_return_value(
- cpp_value, extended_attributes=extended_attributes, script_wrappable='impl',
- for_main_world=for_main_world, is_static=attribute.is_static)
+ cpp_value,
+ extended_attributes=extended_attributes,
+ script_wrappable='impl',
+ for_main_world=for_main_world,
+ is_static=attribute.is_static)
cpp_value_to_script_wrappable = cpp_value
if idl_type.is_array_buffer_view_or_typed_array:
cpp_value_to_script_wrappable += '.View()'
context.update({
- 'cpp_value': cpp_value,
- 'cpp_value_to_script_wrappable': cpp_value_to_script_wrappable,
- 'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
- cpp_value=cpp_value, creation_context='holder',
+ 'cpp_value':
+ cpp_value,
+ 'cpp_value_to_script_wrappable':
+ cpp_value_to_script_wrappable,
+ 'cpp_value_to_v8_value':
+ idl_type.cpp_value_to_v8_value(
+ cpp_value=cpp_value,
+ creation_context='holder',
extended_attributes=extended_attributes),
- 'v8_set_return_value_for_main_world': v8_set_return_value_statement(for_main_world=True),
- 'v8_set_return_value': v8_set_return_value_statement(),
+ 'v8_set_return_value_for_main_world':
+ v8_set_return_value_statement(for_main_world=True),
+ 'v8_set_return_value':
+ v8_set_return_value_statement(),
})
+
def getter_expression(interface, attribute, context):
- arguments = []
- this_getter_base_name = getter_base_name(interface, attribute, arguments)
+ extra_arguments = []
+ this_getter_base_name = getter_base_name(interface, attribute,
+ extra_arguments)
getter_name = scoped_name(interface, attribute, this_getter_base_name)
- arguments.extend(v8_utilities.call_with_arguments(
- attribute.extended_attributes.get('CallWith')))
+ arguments = []
+ arguments.extend(
+ v8_utilities.call_with_arguments(
+ attribute.extended_attributes.get('CallWith')))
# Members of IDL partial interface definitions are implemented in C++ as
# static member functions, which for instance members (non-static members)
# take *impl as their first argument
- if ('PartialInterfaceImplementedAs' in attribute.extended_attributes and
- not attribute.is_static):
+ if ('PartialInterfaceImplementedAs' in attribute.extended_attributes
+ and not attribute.is_static):
arguments.append('*impl')
- if attribute.idl_type.is_explicit_nullable:
- arguments.append('is_null')
+ arguments.extend(extra_arguments)
if context['is_getter_raises_exception']:
arguments.append('exception_state')
if attribute.idl_type.use_output_parameter_for_result:
@@ -413,8 +474,8 @@ def getter_expression(interface, attribute, context):
expression = '%s(%s)' % (getter_name, ', '.join(arguments))
# Needed to handle getter expressions returning Type& as the
# use site for |expression| expects Type*.
- if (attribute.idl_type.is_interface_type and len(arguments) == 0 and
- not attribute.idl_type.is_array_buffer_view_or_typed_array):
+ if (attribute.idl_type.is_interface_type and len(arguments) == 0
+ and not attribute.idl_type.is_array_buffer_view_or_typed_array):
return 'WTF::GetPtr(%s)' % expression
return expression
@@ -435,7 +496,8 @@ def getter_base_name(interface, attribute, arguments):
return name if 'ImplementedAs' in extended_attributes \
else uncapitalize(name)
- content_attribute_name = extended_attributes['Reflect'] or attribute.name.lower()
+ content_attribute_name = (extended_attributes['Reflect']
+ or attribute.name.lower())
if content_attribute_name in ['class', 'id', 'name']:
# Special-case for performance optimization.
return 'Get%sAttribute' % content_attribute_name.capitalize()
@@ -459,28 +521,31 @@ def is_keep_alive_for_gc(interface, attribute):
extended_attributes = attribute.extended_attributes
if attribute.is_static:
return False
+ if idl_type.is_array_buffer_or_view:
+ return False
return (
# For readonly attributes, for performance reasons we keep the attribute
# wrapper alive while the owner wrapper is alive, because the attribute
# never changes.
- (attribute.is_read_only and
- idl_type.is_wrapper_type and
- # There are some exceptions, however:
- not(
- # Node lifetime is managed by object grouping.
- inherits_interface(interface.name, 'Node') or
- inherits_interface(base_idl_type, 'Node') or
- # A self-reference is unnecessary.
- attribute.name == 'self' or
- # FIXME: Remove these hard-coded hacks.
- base_idl_type in ['EventTarget', 'Window'] or
- base_idl_type.startswith(('HTML', 'SVG')))))
+ (
+ attribute.is_read_only and idl_type.is_wrapper_type and
+ # There are some exceptions, however:
+ not (
+ # Node lifetime is managed by object grouping.
+ inherits_interface(interface.name, 'Node')
+ or inherits_interface(base_idl_type, 'Node') or
+ # A self-reference is unnecessary.
+ attribute.name == 'self' or
+ # FIXME: Remove these hard-coded hacks.
+ base_idl_type in ['EventTarget', 'Window']
+ or base_idl_type.startswith(('HTML', 'SVG')))))
################################################################################
# Setter
################################################################################
+
def setter_context(interface, attribute, interfaces, context):
if 'PutForwards' in attribute.extended_attributes:
# Make sure the target interface and attribute exist.
@@ -488,8 +553,7 @@ def setter_context(interface, attribute, interfaces, context):
target_attribute_name = attribute.extended_attributes['PutForwards']
interface = interfaces[target_interface_name]
try:
- next(candidate
- for candidate in interface.attributes
+ next(candidate for candidate in interface.attributes
if candidate.name == target_attribute_name)
except StopIteration:
raise Exception('[PutForward] target not found:\n'
@@ -504,8 +568,8 @@ def setter_context(interface, attribute, interfaces, context):
# exception.
context['cpp_setter'] = (
'if (info.Holder()->CreateDataProperty(' +
- 'info.GetIsolate()->GetCurrentContext(), property_name, v8_value).IsNothing())' +
- '\n return')
+ 'info.GetIsolate()->GetCurrentContext(), ' +
+ 'property_name, v8_value).IsNothing())' + '\n return')
return
extended_attributes = attribute.extended_attributes
@@ -513,8 +577,8 @@ def setter_context(interface, attribute, interfaces, context):
# [RaisesException], [RaisesException=Setter]
is_setter_raises_exception = (
- 'RaisesException' in extended_attributes and
- extended_attributes['RaisesException'] in [None, 'Setter'])
+ 'RaisesException' in extended_attributes
+ and extended_attributes['RaisesException'] in [None, 'Setter'])
has_type_checking_interface = idl_type.is_wrapper_type
@@ -524,27 +588,36 @@ def setter_context(interface, attribute, interfaces, context):
# [CEReactions, Reflect, RuntimeEnabled],
# * the type is boolean, DOMString, or DOMString?, and
# * the interface inherits from 'Element'.
- if ('Reflect' in extended_attributes and
- 'CEReactions' in extended_attributes and
- str(idl_type) in ('boolean', 'DOMString', 'DOMString?') and
- inherits_interface(interface.name, 'Element')):
- if (len(extended_attributes) == 2 or
- (len(extended_attributes) == 3 and 'RuntimeEnabled' in extended_attributes)):
+ if ('Reflect' in extended_attributes
+ and 'CEReactions' in extended_attributes
+ and str(idl_type) in ('boolean', 'DOMString', 'DOMString?')
+ and inherits_interface(interface.name, 'Element')):
+ if (len(extended_attributes) == 2
+ or (len(extended_attributes) == 3
+ and 'RuntimeEnabled' in extended_attributes)):
use_common_reflection_setter = True
context.update({
'has_setter_exception_state':
- is_setter_raises_exception or has_type_checking_interface or
- idl_type.v8_conversion_needs_exception_state,
- 'has_type_checking_interface': has_type_checking_interface,
- 'is_setter_call_with_execution_context': has_extended_attribute_value(
- attribute, 'SetterCallWith', 'ExecutionContext'),
- 'is_setter_call_with_script_state': has_extended_attribute_value(
- attribute, 'SetterCallWith', 'ScriptState'),
- 'is_setter_raises_exception': is_setter_raises_exception,
- 'use_common_reflection_setter': use_common_reflection_setter,
- 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
- extended_attributes, 'v8_value', 'cpp_value',
+ is_setter_raises_exception or has_type_checking_interface
+ or idl_type.v8_conversion_needs_exception_state,
+ 'has_type_checking_interface':
+ has_type_checking_interface,
+ 'is_setter_call_with_execution_context':
+ has_extended_attribute_value(attribute, 'SetterCallWith',
+ 'ExecutionContext'),
+ 'is_setter_call_with_script_state':
+ has_extended_attribute_value(attribute, 'SetterCallWith',
+ 'ScriptState'),
+ 'is_setter_raises_exception':
+ is_setter_raises_exception,
+ 'use_common_reflection_setter':
+ use_common_reflection_setter,
+ 'v8_value_to_local_cpp_value':
+ idl_type.v8_value_to_local_cpp_value(
+ extended_attributes,
+ 'v8_value',
+ 'cpp_value',
code_generation_target='attribute_set'),
})
@@ -555,18 +628,21 @@ def setter_context(interface, attribute, interfaces, context):
def setter_expression(interface, attribute, context):
extended_attributes = attribute.extended_attributes
arguments = v8_utilities.call_with_arguments(
- extended_attributes.get('SetterCallWith') or
- extended_attributes.get('CallWith'))
+ extended_attributes.get('SetterCallWith')
+ or extended_attributes.get('CallWith'))
- this_setter_base_name = setter_base_name(interface, attribute, arguments)
+ extra_arguments = []
+ this_setter_base_name = setter_base_name(interface, attribute,
+ extra_arguments)
setter_name = scoped_name(interface, attribute, this_setter_base_name)
# Members of IDL partial interface definitions are implemented in C++ as
# static member functions, which for instance members (non-static members)
# take *impl as their first argument
- if ('PartialInterfaceImplementedAs' in extended_attributes and
- not attribute.is_static):
+ if ('PartialInterfaceImplementedAs' in extended_attributes
+ and not attribute.is_static):
arguments.append('*impl')
+ arguments.extend(extra_arguments)
idl_type = attribute.idl_type
if idl_type.base_type == 'EventHandler':
handler_type = 'kEventHandler'
@@ -574,25 +650,21 @@ def setter_expression(interface, attribute, context):
handler_type = 'kOnErrorEventHandler'
elif attribute.name == 'onbeforeunload':
handler_type = 'kOnBeforeUnloadEventHandler'
- arguments.append(
- 'JSEventHandler::CreateOrNull(' +
- 'v8_value, ' +
- 'JSEventHandler::HandlerType::' + handler_type +
- ')')
- elif idl_type.base_type == 'SerializedScriptValue':
- arguments.append('std::move(cpp_value)')
+ arguments.append('JSEventHandler::CreateOrNull(' + 'v8_value, ' +
+ 'JSEventHandler::HandlerType::' + handler_type + ')')
else:
arguments.append('cpp_value')
- if idl_type.is_explicit_nullable:
- arguments.append('is_null')
if context['is_setter_raises_exception']:
arguments.append('exception_state')
if context['use_common_reflection_setter']:
attr_name = scoped_content_attribute_name(interface, attribute)
if idl_type.base_type == 'boolean':
setter_name = 'V8SetReflectedBooleanAttribute'
- arguments = ['info', '"%s"' % interface.name,
- '"%s"' % attribute.name, attr_name]
+ arguments = [
+ 'info',
+ '"%s"' % interface.name,
+ '"%s"' % attribute.name, attr_name
+ ]
elif idl_type.base_type == 'DOMString':
if idl_type.is_nullable:
setter_name = 'V8SetReflectedNullableDOMStringAttribute'
@@ -626,8 +698,10 @@ def setter_base_name(interface, attribute, arguments):
def scoped_content_attribute_name(interface, attribute):
- content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower()
- symbol_name = 'k' + NameStyleConverter(content_attribute_name).to_upper_camel_case()
+ content_attribute_name = (attribute.extended_attributes['Reflect']
+ or attribute.name.lower())
+ symbol_name = 'k' + NameStyleConverter(
+ content_attribute_name).to_upper_camel_case()
if interface.name.startswith('SVG'):
namespace = 'svg_names'
includes.add('core/svg_names.h')
@@ -650,25 +724,26 @@ def cpp_content_attribute_value_name(interface, value):
# Attribute configuration
################################################################################
+
# Property descriptor's {writable: boolean}
def is_writable(attribute):
- return (not attribute.is_read_only or
- any(keyword in attribute.extended_attributes for keyword in [
- 'PutForwards', 'Replaceable', 'LenientSetter']))
+ return (not attribute.is_read_only or any(
+ keyword in attribute.extended_attributes
+ for keyword in ['PutForwards', 'Replaceable', 'LenientSetter']))
def is_data_type_property(interface, attribute):
if 'CachedAccessor' in attribute.extended_attributes:
return False
- return (is_constructor_attribute(attribute) or
- 'CrossOrigin' in attribute.extended_attributes)
+ return (is_constructor_attribute(attribute)
+ or 'CrossOrigin' in attribute.extended_attributes)
# [PutForwards], [Replaceable], [LenientSetter]
def has_setter(interface, attribute):
- if (is_data_type_property(interface, attribute) and
- (is_constructor_attribute(attribute) or
- 'Replaceable' in attribute.extended_attributes)):
+ if (is_data_type_property(interface, attribute)
+ and (is_constructor_attribute(attribute)
+ or 'Replaceable' in attribute.extended_attributes)):
return False
return is_writable(attribute)
@@ -678,8 +753,8 @@ def has_setter(interface, attribute):
def property_attributes(interface, attribute):
extended_attributes = attribute.extended_attributes
property_attributes_list = []
- if ('NotEnumerable' in extended_attributes or
- is_constructor_attribute(attribute)):
+ if ('NotEnumerable' in extended_attributes
+ or is_constructor_attribute(attribute)):
property_attributes_list.append('v8::DontEnum')
if is_unforgeable(attribute):
property_attributes_list.append('v8::DontDelete')
@@ -691,16 +766,15 @@ def property_attributes(interface, attribute):
# [Custom], [Custom=Getter]
def has_custom_getter(attribute):
extended_attributes = attribute.extended_attributes
- return ('Custom' in extended_attributes and
- extended_attributes['Custom'] in [None, 'Getter'])
+ return ('Custom' in extended_attributes
+ and extended_attributes['Custom'] in [None, 'Getter'])
# [Custom], [Custom=Setter]
def has_custom_setter(attribute):
extended_attributes = attribute.extended_attributes
- return (not attribute.is_read_only and
- 'Custom' in extended_attributes and
- extended_attributes['Custom'] in [None, 'Setter'])
+ return (not attribute.is_read_only and 'Custom' in extended_attributes
+ and extended_attributes['Custom'] in [None, 'Setter'])
################################################################################
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
index bdd5965ca9d..76de914834a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
@@ -1,7 +1,6 @@
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Generate template values for a callback function.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
@@ -43,15 +42,24 @@ def callback_function_context(callback_function):
# the moment, the two are being defined because their values may change
# in the future (e.g. if we support [ImplementedAs=] in callback
# functions).
- 'callback_function_name': callback_function.name,
- 'cpp_class': 'V8%s' % callback_function.name,
- 'cpp_includes': sorted(includes),
- 'forward_declarations': sorted(forward_declarations(callback_function)),
- 'header_includes': sorted(CALLBACK_FUNCTION_H_INCLUDES),
- 'idl_type': idl_type_str,
- 'is_treat_non_object_as_null': 'TreatNonObjectAsNull' in callback_function.extended_attributes,
- 'native_value_traits_tag': v8_types.idl_type_to_native_value_traits_tag(idl_type),
- 'return_cpp_type': idl_type.cpp_type,
+ 'callback_function_name':
+ callback_function.name,
+ 'cpp_class':
+ 'V8%s' % callback_function.name,
+ 'cpp_includes':
+ sorted(includes),
+ 'forward_declarations':
+ sorted(forward_declarations(callback_function)),
+ 'header_includes':
+ sorted(CALLBACK_FUNCTION_H_INCLUDES),
+ 'idl_type':
+ idl_type_str,
+ 'is_treat_non_object_as_null':
+ 'TreatNonObjectAsNull' in callback_function.extended_attributes,
+ 'native_value_traits_tag':
+ v8_types.idl_type_to_native_value_traits_tag(idl_type),
+ 'return_cpp_type':
+ idl_type.cpp_type,
}
context.update(arguments_context(callback_function.arguments))
@@ -78,14 +86,21 @@ def arguments_context(arguments):
def argument_context(argument):
idl_type = argument.idl_type
return {
- 'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
- argument.name, isolate='GetIsolate()',
+ 'cpp_value_to_v8_value':
+ idl_type.cpp_value_to_v8_value(
+ argument.name,
+ isolate='GetIsolate()',
creation_context='argument_creation_context'),
- 'enum_type': idl_type.enum_type,
- 'enum_values': idl_type.enum_values,
- 'is_variadic': argument.is_variadic,
- 'name': argument.name,
- 'v8_name': 'v8_%s' % argument.name,
+ 'enum_type':
+ idl_type.enum_type,
+ 'enum_values':
+ idl_type.enum_values,
+ 'is_variadic':
+ argument.is_variadic,
+ 'name':
+ argument.name,
+ 'v8_name':
+ 'v8_%s' % argument.name,
}
def argument_cpp_type(argument):
@@ -98,7 +113,9 @@ def arguments_context(arguments):
else:
return cpp_type
- argument_declarations = ['bindings::V8ValueOrScriptWrappableAdapter callback_this_value']
+ argument_declarations = [
+ 'bindings::V8ValueOrScriptWrappableAdapter callback_this_value'
+ ]
argument_declarations.extend(
'%s %s' % (argument_cpp_type(argument), argument.name)
for argument in arguments)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
index e4580fd9319..973a1edde51 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
@@ -25,7 +25,6 @@
# 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.
-
"""Generate template values for a callback interface.
Extends IdlTypeBase with property |callback_cpp_type|.
@@ -69,10 +68,12 @@ def _cpp_type(idl_type):
# Callbacks use raw pointers, so raw_type=True
raw_cpp_type = idl_type.cpp_type_args(raw_type=True)
# Pass containers and dictionaries to callback method by const reference rather than by value
- if raw_cpp_type.startswith(('Vector', 'HeapVector')) or idl_type.is_dictionary:
+ if (raw_cpp_type.startswith(('Vector', 'HeapVector'))
+ or idl_type.is_dictionary):
return 'const %s&' % raw_cpp_type
return raw_cpp_type
+
IdlTypeBase.callback_cpp_type = property(_cpp_type)
@@ -90,9 +91,8 @@ def callback_interface_context(callback_interface, _, component_info):
# https://heycam.github.io/webidl/#dfn-single-operation-callback-interface
is_single_operation = True
- if (callback_interface.parent or
- len(callback_interface.attributes) > 0 or
- len(callback_interface.operations) == 0):
+ if (callback_interface.parent or len(callback_interface.attributes) > 0
+ or len(callback_interface.operations) == 0):
is_single_operation = False
else:
operations = callback_interface.operations
@@ -103,18 +103,30 @@ def callback_interface_context(callback_interface, _, component_info):
break
return {
- 'constants': [constant_context(constant, callback_interface, component_info)
- for constant in callback_interface.constants],
- 'cpp_class': callback_interface.name,
- 'do_not_check_constants': 'DoNotCheckConstants' in callback_interface.extended_attributes,
- 'forward_declarations': sorted(forward_declarations(callback_interface)),
- 'header_includes': header_includes,
- 'interface_name': callback_interface.name,
- 'is_legacy_callback_interface': is_legacy_callback_interface,
- 'is_single_operation_callback_interface': is_single_operation,
- 'methods': [method_context(operation)
- for operation in callback_interface.operations],
- 'v8_class': v8_utilities.v8_class_name(callback_interface),
+ 'constants': [
+ constant_context(constant, callback_interface, component_info)
+ for constant in callback_interface.constants
+ ],
+ 'cpp_class':
+ callback_interface.name,
+ 'do_not_check_constants':
+ 'DoNotCheckConstants' in callback_interface.extended_attributes,
+ 'forward_declarations':
+ sorted(forward_declarations(callback_interface)),
+ 'header_includes':
+ header_includes,
+ 'interface_name':
+ callback_interface.name,
+ 'is_legacy_callback_interface':
+ is_legacy_callback_interface,
+ 'is_single_operation_callback_interface':
+ is_single_operation,
+ 'methods': [
+ method_context(operation)
+ for operation in callback_interface.operations
+ ],
+ 'v8_class':
+ v8_utilities.v8_class_name(callback_interface),
}
@@ -150,10 +162,14 @@ def method_context(operation):
add_includes_for_operation(operation)
context = {
- 'cpp_type': idl_type.callback_cpp_type,
- 'idl_type': idl_type_str,
- 'name': operation.name,
- 'native_value_traits_tag': v8_types.idl_type_to_native_value_traits_tag(idl_type),
+ 'cpp_type':
+ idl_type.callback_cpp_type,
+ 'idl_type':
+ idl_type_str,
+ 'name':
+ operation.name,
+ 'native_value_traits_tag':
+ v8_types.idl_type_to_native_value_traits_tag(idl_type),
}
context.update(arguments_context(operation.arguments))
return context
@@ -162,18 +178,24 @@ def method_context(operation):
def arguments_context(arguments):
def argument_context(argument):
return {
- 'cpp_value_to_v8_value': argument.idl_type.cpp_value_to_v8_value(
- argument.name, isolate='GetIsolate()',
+ 'cpp_value_to_v8_value':
+ argument.idl_type.cpp_value_to_v8_value(
+ argument.name,
+ isolate='GetIsolate()',
creation_context='argument_creation_context'),
- 'name': argument.name,
- 'v8_name': 'v8_' + argument.name,
+ 'name':
+ argument.name,
+ 'v8_name':
+ 'v8_' + argument.name,
}
- argument_declarations = ['bindings::V8ValueOrScriptWrappableAdapter callback_this_value']
+ argument_declarations = [
+ 'bindings::V8ValueOrScriptWrappableAdapter callback_this_value'
+ ]
argument_declarations.extend(
'%s %s' % (argument.idl_type.callback_cpp_type, argument.name)
for argument in arguments)
- return {
+ return {
'argument_declarations': argument_declarations,
'arguments': [argument_context(argument) for argument in arguments],
}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
index 5beb8a3a1ac..c799496ec88 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
@@ -1,21 +1,21 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Generate template contexts of dictionaries for both v8 bindings and
implementation classes that are used by blink's core/modules.
"""
-import operator
+from blinkbuild.name_style_converter import NameStyleConverter
from idl_types import IdlType
from utilities import to_snake_case
from v8_globals import includes
+from v8_utilities import has_extended_attribute_value
+import operator
import v8_types
import v8_utilities
-from v8_utilities import has_extended_attribute_value
-
DICTIONARY_H_INCLUDES = frozenset([
+ 'base/containers/span.h',
'bindings/core/v8/native_value_traits.h',
'bindings/core/v8/to_v8_for_core.h',
'bindings/core/v8/v8_binding_for_core.h',
@@ -30,24 +30,24 @@ DICTIONARY_CPP_INCLUDES = frozenset([
def getter_name_for_dictionary_member(member):
name = v8_utilities.cpp_name(member)
- return name
+ return NameStyleConverter(name).to_lower_camel_case()
def setter_name_for_dictionary_member(member):
- name = v8_utilities.cpp_name(member)
- return 'set%s' % v8_utilities.capitalize(name)
+ name = 'set_{}'.format(v8_utilities.cpp_name(member))
+ return NameStyleConverter(name).to_lower_camel_case()
def null_setter_name_for_dictionary_member(member):
if member.idl_type.is_nullable:
- name = v8_utilities.cpp_name(member)
- return 'set%sToNull' % v8_utilities.capitalize(name)
+ name = 'set_{}_to_null'.format(v8_utilities.cpp_name(member))
+ return NameStyleConverter(name).to_lower_camel_case()
return None
def has_method_name_for_dictionary_member(member):
- name = v8_utilities.cpp_name(member)
- return 'has%s' % v8_utilities.capitalize(name)
+ name = NameStyleConverter('has_' + v8_utilities.cpp_name(member))
+ return name.to_lower_camel_case()
def unwrap_nullable_if_needed(idl_type):
@@ -58,6 +58,7 @@ def unwrap_nullable_if_needed(idl_type):
# Context for V8 bindings
+
def dictionary_context(dictionary, interfaces_info, component_info):
includes.clear()
includes.update(DICTIONARY_CPP_INCLUDES)
@@ -66,9 +67,11 @@ def dictionary_context(dictionary, interfaces_info, component_info):
raise Exception(
'Dictionary cannot be RuntimeEnabled: %s' % dictionary.name)
- members = [member_context(dictionary, member, component_info)
- for member in sorted(dictionary.members,
- key=operator.attrgetter('name'))]
+ members = [
+ member_context(dictionary, member, component_info)
+ for member in sorted(
+ dictionary.members, key=operator.attrgetter('name'))
+ ]
for member in members:
if member['runtime_enabled_feature_name']:
@@ -85,15 +88,22 @@ def dictionary_context(dictionary, interfaces_info, component_info):
cpp_class = v8_utilities.cpp_name(dictionary)
context = {
- 'cpp_class': cpp_class,
- 'has_origin_trial_members': has_origin_trial_members,
- 'header_includes': set(DICTIONARY_H_INCLUDES),
- 'members': members,
- 'required_member_names': sorted([member.name
- for member in dictionary.members
- if member.is_required]),
- 'use_permissive_dictionary_conversion': 'PermissiveDictionaryConversion' in dictionary.extended_attributes,
- 'v8_class': v8_types.v8_type(cpp_class),
+ 'cpp_class':
+ cpp_class,
+ 'has_origin_trial_members':
+ has_origin_trial_members,
+ 'header_includes':
+ set(DICTIONARY_H_INCLUDES),
+ 'members':
+ members,
+ 'required_member_names':
+ sorted([
+ member.name for member in dictionary.members if member.is_required
+ ]),
+ 'use_permissive_dictionary_conversion':
+ 'PermissiveDictionaryConversion' in dictionary.extended_attributes,
+ 'v8_class':
+ v8_types.v8_type(cpp_class),
}
if dictionary.parent:
IdlType(dictionary.parent).add_includes_for_type()
@@ -126,8 +136,8 @@ def member_context(_, member, component_info):
# states for some types for memory usage and performance.
# For types whose |has_explicit_presence| is True, we provide explicit
# states of presence.
- has_explicit_presence = (
- idl_type.is_nullable and idl_type.inner_type.is_interface_type)
+ has_explicit_presence = (idl_type.is_nullable
+ and idl_type.inner_type.is_interface_type)
def default_values():
if not member.default_value:
@@ -138,7 +148,8 @@ def member_context(_, member, component_info):
cpp_default_value = unwrapped_idl_type.literal_cpp_value(
member.default_value)
v8_default_value = unwrapped_idl_type.cpp_value_to_v8_value(
- cpp_value=cpp_default_value, isolate='isolate',
+ cpp_value=cpp_default_value,
+ isolate='isolate',
creation_context='creationContext')
return cpp_default_value, v8_default_value
@@ -148,48 +159,78 @@ def member_context(_, member, component_info):
v8_value = snake_case_name + "_value"
has_value_or_default = snake_case_name + "_has_value_or_default"
getter_name = getter_name_for_dictionary_member(member)
- is_deprecated_dictionary = unwrapped_idl_type.name == 'Dictionary'
runtime_features = component_info['runtime_enabled_features']
return {
- 'cpp_default_value': cpp_default_value,
- 'cpp_type': unwrapped_idl_type.cpp_type,
- 'cpp_value': cpp_value,
- 'cpp_value_to_v8_value': unwrapped_idl_type.cpp_value_to_v8_value(
- cpp_value='impl->%s()' % getter_name, isolate='isolate',
+ 'cpp_default_value':
+ cpp_default_value,
+ 'cpp_type':
+ unwrapped_idl_type.cpp_type,
+ 'cpp_value':
+ cpp_value,
+ 'cpp_value_to_v8_value':
+ unwrapped_idl_type.cpp_value_to_v8_value(
+ cpp_value='impl->%s()' % getter_name,
+ isolate='isolate',
creation_context='creationContext',
extended_attributes=extended_attributes),
- 'deprecate_as': v8_utilities.deprecate_as(member),
- 'enum_type': idl_type.enum_type,
- 'enum_values': idl_type.enum_values,
- 'getter_name': getter_name,
- 'has_explicit_presence': has_explicit_presence,
- 'has_method_name': has_method_name_for_dictionary_member(member),
- 'idl_type': idl_type.base_type,
- 'is_callback_function_type': idl_type.is_callback_function,
- 'is_interface_type': idl_type.is_interface_type and not is_deprecated_dictionary,
- 'is_nullable': idl_type.is_nullable,
- 'is_object': unwrapped_idl_type.name == 'Object' or is_deprecated_dictionary,
- 'is_string_type': idl_type.preprocessed_type.is_string_type,
- 'is_required': member.is_required,
- 'name': member.name,
+ 'deprecate_as':
+ v8_utilities.deprecate_as(member),
+ 'enum_type':
+ idl_type.enum_type,
+ 'enum_values':
+ idl_type.enum_values,
+ 'getter_name':
+ getter_name,
+ 'has_explicit_presence':
+ has_explicit_presence,
+ 'has_method_name':
+ has_method_name_for_dictionary_member(member),
+ 'idl_type':
+ idl_type.base_type,
+ 'is_callback_function_type':
+ idl_type.is_callback_function,
+ 'is_interface_type':
+ idl_type.is_interface_type,
+ 'is_nullable':
+ idl_type.is_nullable,
+ 'is_object':
+ unwrapped_idl_type.name == 'Object',
+ 'is_string_type':
+ idl_type.preprocessed_type.is_string_type,
+ 'is_required':
+ member.is_required,
+ 'name':
+ member.name,
+ # [RuntimeEnabled] for origin trial
'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(member, runtime_features), # [RuntimeEnabled] for origin trial
+ v8_utilities.origin_trial_feature_name(member, runtime_features),
+ # [RuntimeEnabled] if not in origin trial
'runtime_enabled_feature_name':
- v8_utilities.runtime_enabled_feature_name(member, runtime_features), # [RuntimeEnabled] if not in origin trial
- 'setter_name': setter_name_for_dictionary_member(member),
- 'has_value_or_default': has_value_or_default,
- 'null_setter_name': null_setter_name_for_dictionary_member(member),
- 'v8_default_value': v8_default_value,
- 'v8_value': v8_value,
- 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
- extended_attributes, v8_value, cpp_value, isolate='isolate',
+ v8_utilities.runtime_enabled_feature_name(member, runtime_features),
+ 'setter_name':
+ setter_name_for_dictionary_member(member),
+ 'has_value_or_default':
+ has_value_or_default,
+ 'null_setter_name':
+ null_setter_name_for_dictionary_member(member),
+ 'v8_default_value':
+ v8_default_value,
+ 'v8_value':
+ v8_value,
+ 'v8_value_to_local_cpp_value':
+ idl_type.v8_value_to_local_cpp_value(
+ extended_attributes,
+ v8_value,
+ cpp_value,
+ isolate='isolate',
use_exception_state=True),
}
# Context for implementation classes
+
def dictionary_impl_context(dictionary, interfaces_info):
def remove_duplicate_members(members):
# When [ImplementedAs] is used, cpp_name can conflict. For example,
@@ -202,14 +243,17 @@ def dictionary_impl_context(dictionary, interfaces_info):
if duplicated_member and duplicated_member != member:
raise Exception('Member name conflict: %s' % cpp_name)
members_dict[cpp_name] = member
- return sorted(members_dict.values(), key=lambda member: member['cpp_name'])
+ return sorted(
+ members_dict.values(), key=lambda member: member['cpp_name'])
includes.clear()
header_forward_decls = set()
header_includes = set(['platform/heap/handle.h'])
- members = [member_impl_context(member, interfaces_info,
- header_includes, header_forward_decls)
- for member in dictionary.members]
+ members = [
+ member_impl_context(member, interfaces_info, header_includes,
+ header_forward_decls)
+ for member in dictionary.members
+ ]
members = remove_duplicate_members(members)
context = {
'header_forward_decls': header_forward_decls,
@@ -218,8 +262,9 @@ def dictionary_impl_context(dictionary, interfaces_info):
'members': members,
}
if dictionary.parent:
- context['parent_cpp_class'] = v8_utilities.cpp_name_from_interfaces_info(
- dictionary.parent, interfaces_info)
+ context['parent_cpp_class'] = \
+ v8_utilities.cpp_name_from_interfaces_info(dictionary.parent,
+ interfaces_info)
parent_interface_info = interfaces_info.get(dictionary.parent)
if parent_interface_info:
context['header_includes'].add(
@@ -241,8 +286,8 @@ def member_impl_context(member, interfaces_info, header_includes,
# states for some types for memory usage and performance.
# For types whose |has_explicit_presence| is True, we provide explicit
# states of presence.
- has_explicit_presence = (
- member.idl_type.is_nullable and member.idl_type.inner_type.is_interface_type)
+ has_explicit_presence = (member.idl_type.is_nullable
+ and member.idl_type.inner_type.is_interface_type)
nullable_indicator_name = None
if not idl_type.cpp_type_has_null_value or has_explicit_presence:
@@ -256,50 +301,66 @@ def member_impl_context(member, interfaces_info, header_includes,
if idl_type.name == 'Any':
return '!({0}_.IsEmpty() || {0}_.IsUndefined())'.format(cpp_name)
if idl_type.name == 'Object':
- return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(cpp_name)
- if idl_type.name == 'Dictionary':
- return '!%s_.IsUndefinedOrNull()' % cpp_name
- return '%s_' % cpp_name
+ return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(
+ cpp_name)
+ return '!!%s_' % cpp_name
cpp_default_value = None
if member.default_value:
if not member.default_value.is_null or has_explicit_presence:
- cpp_default_value = idl_type.literal_cpp_value(member.default_value)
+ cpp_default_value = idl_type.literal_cpp_value(
+ member.default_value)
forward_decl_name = idl_type.impl_forward_declaration_name
if forward_decl_name:
includes.update(idl_type.impl_includes_for_type(interfaces_info))
header_forward_decls.add(forward_decl_name)
else:
- header_includes.update(idl_type.impl_includes_for_type(interfaces_info))
+ header_includes.update(
+ idl_type.impl_includes_for_type(interfaces_info))
setter_value = 'value'
- if idl_type.is_array_buffer_view_or_typed_array:
- setter_value += '.View()'
-
non_null_type = idl_type.inner_type if idl_type.is_nullable else idl_type
- setter_inline = 'inline ' if (
- non_null_type.is_basic_type or
- non_null_type.is_enum or
- non_null_type.is_wrapper_type) else ''
+ setter_inline = 'inline ' if (non_null_type.is_basic_type
+ or non_null_type.is_enum
+ or non_null_type.is_wrapper_type) else ''
extended_attributes = member.extended_attributes
return {
- 'cpp_default_value': cpp_default_value,
- 'cpp_name': cpp_name,
- 'has_explicit_presence': has_explicit_presence,
- 'getter_expression': cpp_name + '_',
- 'getter_name': getter_name_for_dictionary_member(member),
- 'has_method_expression': has_method_expression(),
- 'has_method_name': has_method_name_for_dictionary_member(member),
- 'is_nullable': idl_type.is_nullable,
- 'is_traceable': idl_type.is_traceable,
- 'member_cpp_type': idl_type.cpp_type_args(used_in_cpp_sequence=True, extended_attributes=extended_attributes),
- 'null_setter_name': null_setter_name_for_dictionary_member(member),
- 'nullable_indicator_name': nullable_indicator_name,
- 'rvalue_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True, extended_attributes=extended_attributes),
- 'setter_inline': setter_inline,
- 'setter_name': setter_name_for_dictionary_member(member),
- 'setter_value': setter_value,
+ 'cpp_default_value':
+ cpp_default_value,
+ 'cpp_name':
+ cpp_name,
+ 'has_explicit_presence':
+ has_explicit_presence,
+ 'getter_expression':
+ cpp_name + '_',
+ 'getter_name':
+ getter_name_for_dictionary_member(member),
+ 'has_method_expression':
+ has_method_expression(),
+ 'has_method_name':
+ has_method_name_for_dictionary_member(member),
+ 'is_nullable':
+ idl_type.is_nullable,
+ 'is_traceable':
+ idl_type.is_traceable,
+ 'member_cpp_type':
+ idl_type.cpp_type_args(
+ used_in_cpp_sequence=True,
+ extended_attributes=extended_attributes),
+ 'null_setter_name':
+ null_setter_name_for_dictionary_member(member),
+ 'nullable_indicator_name':
+ nullable_indicator_name,
+ 'rvalue_cpp_type':
+ idl_type.cpp_type_args(
+ used_as_rvalue_type=True, extended_attributes=extended_attributes),
+ 'setter_inline':
+ setter_inline,
+ 'setter_name':
+ setter_name_for_dictionary_member(member),
+ 'setter_value':
+ setter_value,
}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py
index 55ed25722ed..49fb86151e3 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_globals.py
@@ -25,7 +25,6 @@
# 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.
-
"""Module to share global variables (includes and interfaces) across modules."""
includes = set()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
index 39ab8717569..02f604dee9d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pylint: disable=relative-import
-
"""Generate template values for an interface.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
@@ -37,8 +36,8 @@ import os
import sys
from operator import or_
-sys.path.append(os.path.join(os.path.dirname(__file__),
- '..', '..', 'build', 'scripts'))
+sys.path.append(
+ os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
from blinkbuild.name_style_converter import NameStyleConverter
from idl_definitions import IdlAttribute, IdlOperation, IdlArgument
from idl_types import IdlType, inherits_interface
@@ -50,11 +49,9 @@ from v8_globals import includes
import v8_methods
import v8_types
import v8_utilities
-from v8_utilities import (binding_header_filename, context_enabled_feature_name,
- cpp_name_or_partial, cpp_name,
- has_extended_attribute_value,
- runtime_enabled_feature_name)
-
+from v8_utilities import (
+ binding_header_filename, context_enabled_feature_name, cpp_name_or_partial,
+ cpp_name, has_extended_attribute_value, runtime_enabled_feature_name)
INTERFACE_H_INCLUDES = frozenset([
'bindings/core/v8/generated_code_helper.h',
@@ -68,6 +65,7 @@ INTERFACE_H_INCLUDES = frozenset([
])
INTERFACE_CPP_INCLUDES = frozenset([
'base/memory/scoped_refptr.h',
+ 'bindings/core/v8/native_value_traits_impl.h',
'bindings/core/v8/v8_dom_configuration.h',
'core/execution_context/execution_context.h',
'platform/scheduler/public/cooperative_scheduling_manager.h',
@@ -79,34 +77,42 @@ INTERFACE_CPP_INCLUDES = frozenset([
def filter_has_constant_configuration(constants):
- return [constant for constant in constants if
- not constant['measure_as'] and
- not constant['deprecate_as'] and
- not constant['runtime_enabled_feature_name'] and
- not constant['origin_trial_feature_name']]
+ return [
+ constant for constant in constants
+ if not constant['measure_as'] and not constant['deprecate_as']
+ and not constant['runtime_enabled_feature_name']
+ and not constant['origin_trial_feature_name']
+ ]
def filter_has_special_getter(constants):
- return [constant for constant in constants if
- constant['measure_as'] or
- constant['deprecate_as']]
+ return [
+ constant for constant in constants
+ if constant['measure_as'] or constant['deprecate_as']
+ ]
def filter_runtime_enabled(constants):
- return [constant for constant in constants if
- constant['runtime_enabled_feature_name']]
+ return [
+ constant for constant in constants
+ if constant['runtime_enabled_feature_name']
+ ]
def filter_origin_trial_enabled(constants):
- return [constant for constant in constants if
- constant['origin_trial_feature_name']]
+ return [
+ constant for constant in constants
+ if constant['origin_trial_feature_name']
+ ]
def constant_filters():
- return {'has_constant_configuration': filter_has_constant_configuration,
- 'has_special_getter': filter_has_special_getter,
- 'runtime_enabled_constants': filter_runtime_enabled,
- 'origin_trial_enabled_constants': filter_origin_trial_enabled}
+ return {
+ 'has_constant_configuration': filter_has_constant_configuration,
+ 'has_special_getter': filter_has_special_getter,
+ 'runtime_enabled_constants': filter_runtime_enabled,
+ 'origin_trial_enabled_constants': filter_origin_trial_enabled
+ }
def origin_trial_features(interface, constants, attributes, methods):
@@ -128,26 +134,40 @@ def origin_trial_features(interface, constants, attributes, methods):
# Collect all members visible on this interface with a defined origin trial
origin_trial_constants = member_filter(constants)
origin_trial_attributes = member_filter(attributes)
- origin_trial_methods = member_filter([method for method in methods
- if v8_methods.method_is_visible(method, interface.is_partial) and
- not v8_methods.custom_registration(method)])
+ origin_trial_methods = member_filter([
+ method for method in methods
+ if v8_methods.method_is_visible(method, interface.is_partial)
+ and not v8_methods.custom_registration(method)
+ ])
- feature_names = set([member[KEY] for member in origin_trial_constants + origin_trial_attributes + origin_trial_methods])
+ feature_names = set([
+ member[KEY] for member in origin_trial_constants +
+ origin_trial_attributes + origin_trial_methods
+ ])
# Construct the list of dictionaries. 'needs_instance' will be true if any
# member for the feature has 'on_instance' defined as true.
- features = [{'name': name,
- 'constants': member_filter_by_name(origin_trial_constants, name),
- 'attributes': member_filter_by_name(origin_trial_attributes, name),
- 'methods': member_filter_by_name(origin_trial_methods, name)}
- for name in feature_names]
+ features = [{
+ 'name':
+ name,
+ 'constants':
+ member_filter_by_name(origin_trial_constants, name),
+ 'attributes':
+ member_filter_by_name(origin_trial_attributes, name),
+ 'methods':
+ member_filter_by_name(origin_trial_methods, name)
+ } for name in feature_names]
for feature in features:
- members = feature['constants'] + feature['attributes'] + feature['methods']
- feature['needs_instance'] = any(member.get('on_instance', False) for member in members)
+ members = feature['constants'] + feature['attributes'] + feature[
+ 'methods']
+ feature['needs_instance'] = any(
+ member.get('on_instance', False) for member in members)
# TODO(chasej): Need to handle method overloads? e.g.
# (method['overloads']['secure_context_test_all'] if 'overloads' in method else method['secure_context_test'])
- feature['needs_secure_context'] = any(member.get('secure_context_test', False) for member in members)
- feature['needs_context'] = feature['needs_secure_context'] or any(member.get('exposed_test', False) for member in members)
+ feature['needs_secure_context'] = any(
+ member.get('secure_context_test', False) for member in members)
+ feature['needs_context'] = feature['needs_secure_context'] or any(
+ member.get('exposed_test', False) for member in members)
if features:
includes.add('platform/bindings/script_state.h')
@@ -166,7 +186,10 @@ def context_enabled_features(attributes):
KEY = 'context_enabled_feature_name' # pylint: disable=invalid-name
def member_filter(members):
- return sorted([member for member in members if member.get(KEY) and not member.get('exposed_test')])
+ return sorted([
+ member for member in members
+ if member.get(KEY) and not member.get('exposed_test')
+ ])
def member_filter_by_name(members, name):
return [member for member in members if member[KEY] == name]
@@ -174,10 +197,14 @@ def context_enabled_features(attributes):
# Collect all members visible on this interface with a defined origin trial
context_enabled_attributes = member_filter(attributes)
feature_names = set([member[KEY] for member in context_enabled_attributes])
- features = [{'name': name,
- 'attributes': member_filter_by_name(context_enabled_attributes, name),
- 'needs_instance': False}
- for name in feature_names]
+ features = [{
+ 'name':
+ name,
+ 'attributes':
+ member_filter_by_name(context_enabled_attributes, name),
+ 'needs_instance':
+ False
+ } for name in feature_names]
if features:
includes.add('platform/bindings/script_state.h')
return features
@@ -186,13 +213,20 @@ def context_enabled_features(attributes):
def runtime_call_stats_context(interface):
counter_prefix = 'Blink_' + v8_utilities.cpp_name(interface) + '_'
return {
- 'constructor_counter': counter_prefix + 'Constructor',
- 'cross_origin_named_getter_counter': counter_prefix + 'CrossOriginNamedGetter',
- 'cross_origin_named_setter_counter': counter_prefix + 'CrossOriginNamedSetter',
- 'indexed_property_getter_counter': counter_prefix + 'IndexedPropertyGetter',
- 'named_property_getter_counter': counter_prefix + 'NamedPropertyGetter',
- 'named_property_query_counter': counter_prefix + 'NamedPropertyQuery',
- 'named_property_setter_counter': counter_prefix + 'NamedPropertySetter',
+ 'constructor_counter':
+ counter_prefix + 'Constructor',
+ 'cross_origin_named_getter_counter':
+ counter_prefix + 'CrossOriginNamedGetter',
+ 'cross_origin_named_setter_counter':
+ counter_prefix + 'CrossOriginNamedSetter',
+ 'indexed_property_getter_counter':
+ counter_prefix + 'IndexedPropertyGetter',
+ 'named_property_getter_counter':
+ counter_prefix + 'NamedPropertyGetter',
+ 'named_property_query_counter':
+ counter_prefix + 'NamedPropertyQuery',
+ 'named_property_setter_counter':
+ counter_prefix + 'NamedPropertySetter',
}
@@ -220,11 +254,13 @@ def interface_context(interface, interfaces, component_info):
parent_interface = None
is_event_target = False
# partial interface needs the definition of its original interface.
- includes.add('bindings/core/v8/%s' % binding_header_filename(interface.name))
+ includes.add(
+ 'bindings/core/v8/%s' % binding_header_filename(interface.name))
else:
parent_interface = interface.parent
if parent_interface:
- header_includes.update(v8_types.includes_for_interface(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
@@ -235,19 +271,18 @@ def interface_context(interface, interfaces, component_info):
includes.update(('bindings/core/v8/v8_array_buffer.h',
'bindings/core/v8/v8_shared_array_buffer.h'))
if interface.name == 'ArrayBufferView':
- includes.update((
- 'bindings/core/v8/v8_int8_array.h',
- 'bindings/core/v8/v8_int16_array.h',
- 'bindings/core/v8/v8_int32_array.h',
- 'bindings/core/v8/v8_uint8_array.h',
- 'bindings/core/v8/v8_uint8_clamped_array.h',
- 'bindings/core/v8/v8_uint16_array.h',
- 'bindings/core/v8/v8_uint32_array.h',
- 'bindings/core/v8/v8_big_int_64_array.h',
- 'bindings/core/v8/v8_big_uint_64_array.h',
- 'bindings/core/v8/v8_float32_array.h',
- 'bindings/core/v8/v8_float64_array.h',
- 'bindings/core/v8/v8_data_view.h'))
+ includes.update(('bindings/core/v8/v8_int8_array.h',
+ 'bindings/core/v8/v8_int16_array.h',
+ 'bindings/core/v8/v8_int32_array.h',
+ 'bindings/core/v8/v8_uint8_array.h',
+ 'bindings/core/v8/v8_uint8_clamped_array.h',
+ 'bindings/core/v8/v8_uint16_array.h',
+ 'bindings/core/v8/v8_uint32_array.h',
+ 'bindings/core/v8/v8_big_int_64_array.h',
+ 'bindings/core/v8/v8_big_uint_64_array.h',
+ 'bindings/core/v8/v8_float32_array.h',
+ 'bindings/core/v8/v8_float64_array.h',
+ 'bindings/core/v8/v8_data_view.h'))
# [ActiveScriptWrappable]
active_scriptwrappable = 'ActiveScriptWrappable' in extended_attributes
@@ -266,12 +301,14 @@ def interface_context(interface, interfaces, component_info):
# 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')
+ wrapper_class_id = ('kNodeClassId' if inherits_interface(
+ interface.name, 'Node') else 'kObjectClassId')
# [LegacyUnenumerableNamedProperties]
# pylint: disable=C0103
- has_legacy_unenumerable_named_properties = (interface.has_named_property_getter and
- 'LegacyUnenumerableNamedProperties' in extended_attributes)
+ 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)
@@ -280,55 +317,93 @@ def interface_context(interface, interfaces, component_info):
# TODO(peria): Generate the target list from 'Window' and 'HTMLDocument'.
needs_runtime_enabled_installer = v8_class_name in [
- 'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget']
+ 'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget'
+ ]
runtime_features = component_info['runtime_enabled_features']
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,
+ '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,
- 'internal_namespace': internal_namespace(interface),
- '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,
- 'measure_as': v8_utilities.measure_as(interface, None), # [MeasureAs]
- 'needs_runtime_enabled_installer': needs_runtime_enabled_installer,
- 'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(interface, runtime_features),
- '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, runtime_features), # [RuntimeEnabled]
- 'snake_case_v8_class': NameStyleConverter(v8_class_name).to_snake_case(),
- 'v8_class': v8_class_name,
- 'v8_class_or_partial': v8_class_name_or_partial,
- 'wrapper_class_id': wrapper_class_id,
+ 'has_access_check_callbacks': (is_check_security
+ and interface.name != 'EventTarget'),
+ # [Custom=LegacyCallAsFunction]
+ 'has_custom_legacy_call_as_function':
+ has_extended_attribute_value(interface, '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,
+ 'internal_namespace':
+ internal_namespace(interface),
+ '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,
+ # [MeasureAs]
+ 'measure_as':
+ v8_utilities.measure_as(interface, None),
+ 'needs_runtime_enabled_installer':
+ needs_runtime_enabled_installer,
+ 'origin_trial_feature_name':
+ v8_utilities.origin_trial_feature_name(interface, runtime_features),
+ 'parent_interface':
+ parent_interface,
+ 'pass_cpp_type':
+ cpp_name(interface) + '*',
+ 'runtime_call_stats':
+ runtime_call_stats_context(interface),
+ # [RuntimeEnabled]
+ 'runtime_enabled_feature_name':
+ runtime_enabled_feature_name(interface, runtime_features),
+ 'snake_case_v8_class':
+ NameStyleConverter(v8_class_name).to_snake_case(),
+ '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']
+ 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)
+ context['constructor_overloads'] = overloads_context(
+ interface, constructors)
# [CustomConstructor]
custom_constructors = [{ # Only needed for computing interface length
@@ -340,8 +415,9 @@ def interface_context(interface, interfaces, component_info):
has_html_constructor = 'HTMLConstructor' in extended_attributes
# https://html.spec.whatwg.org/C/#html-element-constructors
if has_html_constructor:
- if ('Constructor' in extended_attributes or
- 'NoInterfaceObject' in extended_attributes or interface.is_mixin):
+ if ('Constructor' in extended_attributes
+ or 'NoInterfaceObject' in extended_attributes
+ or interface.is_mixin):
raise Exception('[HTMLConstructor] cannot be specified with '
'[Constructor] or [NoInterfaceObject], or on '
'a mixin : %s' % interface.name)
@@ -363,21 +439,27 @@ def interface_context(interface, interfaces, component_info):
includes.add('core/frame/local_dom_window.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)
+ raise Exception(
+ '[Measure] or [MeasureAs] specified for interface without a constructor: '
+ '%s' % interface.name)
# [ConstructorCallWith=Document]
- if has_extended_attribute_value(interface, '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, runtime_features)))
+ unscopables.append((attribute.name,
+ runtime_enabled_feature_name(
+ attribute, runtime_features)))
for method in interface.operations:
if 'Unscopable' in method.extended_attributes:
- unscopables.append((method.name, runtime_enabled_feature_name(method, runtime_features)))
+ unscopables.append((method.name,
+ runtime_enabled_feature_name(
+ method, runtime_features)))
# [CEReactions]
setter_or_deleters = (
@@ -386,49 +468,77 @@ def interface_context(interface, interfaces, component_info):
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)
+ 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/ce_reactions_scope.h')
context.update({
- 'constructors': constructors,
- 'has_custom_constructor': bool(custom_constructors),
- 'has_html_constructor': has_html_constructor,
+ '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),
+ interface_length(constructors + custom_constructors),
+ # [RaisesException=Constructor]
+ 'is_constructor_raises_exception':
+ extended_attributes.get('RaisesException') == 'Constructor',
+ 'named_constructor':
+ named_constructor,
+ 'unscopables':
+ sorted(unscopables),
})
# Constants
context.update({
- 'constants': [constant_context(constant, interface, component_info) for constant in interface.constants],
- 'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes,
+ 'constants': [
+ constant_context(constant, interface, component_info)
+ for constant in interface.constants
+ ],
+ 'do_not_check_constants':
+ 'DoNotCheckConstants' in extended_attributes,
})
# Attributes
attributes = attributes_context(interface, interfaces, component_info)
context.update({
- 'attributes': attributes,
+ 'attributes':
+ attributes,
# Elements in attributes are broken in following members.
- 'accessors': v8_attributes.filter_accessors(attributes),
- 'data_attributes': v8_attributes.filter_data_attributes(attributes),
- 'runtime_enabled_attributes': v8_attributes.filter_runtime_enabled(attributes),
+ 'accessors':
+ v8_attributes.filter_accessors(attributes),
+ 'data_attributes':
+ v8_attributes.filter_data_attributes(attributes),
+ 'runtime_enabled_attributes':
+ v8_attributes.filter_runtime_enabled(attributes),
})
# Conditionally enabled attributes
- conditionally_enabled_attributes = v8_attributes.filter_conditionally_enabled(attributes)
- conditional_attributes = [attr for attr in conditionally_enabled_attributes if not attr['constructor_type']]
- conditional_interface_objects = [attr for attr in conditionally_enabled_attributes if attr['constructor_type']]
+ conditionally_enabled_attributes = v8_attributes.filter_conditionally_enabled(
+ attributes)
+ conditional_attributes = [
+ attr for attr in conditionally_enabled_attributes
+ if not attr['constructor_type']
+ ]
+ conditional_interface_objects = [
+ attr for attr in conditionally_enabled_attributes
+ if attr['constructor_type']
+ ]
has_conditional_secure_attributes = any( # pylint: disable=invalid-name
- v8_attributes.is_secure_context(attr) for attr in conditionally_enabled_attributes)
+ v8_attributes.is_secure_context(attr)
+ for attr in conditionally_enabled_attributes)
context.update({
- 'conditional_attributes': conditional_attributes,
- 'conditional_interface_objects': conditional_interface_objects,
- 'has_conditional_secure_attributes': has_conditional_secure_attributes,
+ 'conditional_attributes':
+ conditional_attributes,
+ 'conditional_interface_objects':
+ conditional_interface_objects,
+ 'has_conditional_secure_attributes':
+ has_conditional_secure_attributes,
})
# Methods
@@ -436,22 +546,24 @@ def interface_context(interface, interfaces, component_info):
methods = context['methods']
# Conditionally enabled methods
- conditional_methods = v8_methods.filter_conditionally_enabled(methods, interface.is_partial)
+ conditional_methods = v8_methods.filter_conditionally_enabled(
+ methods, interface.is_partial)
has_conditional_secure_methods = any( # pylint: disable=invalid-name
v8_methods.is_secure_context(method) for method in conditional_methods)
context.update({
'has_conditional_secure_methods':
- has_conditional_secure_methods,
- 'conditional_methods': conditional_methods,
+ has_conditional_secure_methods,
+ 'conditional_methods':
+ conditional_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')
+ 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,
@@ -464,27 +576,38 @@ def interface_context(interface, interfaces, component_info):
v8_class_name_or_partial + '::InstallConditionalFeatures')
context.update({
- 'install_conditional_features_func': install_conditional_features_func,
+ 'install_conditional_features_func':
+ install_conditional_features_func,
})
context.update({
- '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),
+ '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'],
+ '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'])),
+ sorted(
+ origin_trial_features(interface, context['constants'],
+ context['attributes'], context['methods']) +
+ context_enabled_features(context['attributes'])),
})
if context['optional_features']:
includes.add('platform/bindings/v8_per_context_data.h')
@@ -510,17 +633,23 @@ def interface_context(interface, interfaces, component_info):
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']:
+ 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']:
+ 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,
+ '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
@@ -538,15 +667,19 @@ def attributes_context(interface, interfaces, component_info):
A list of attribute contexts
"""
- attributes = [v8_attributes.attribute_context(interface, attribute, interfaces, component_info)
- for attribute in interface.attributes]
+ attributes = [
+ v8_attributes.attribute_context(interface, attribute, interfaces,
+ component_info)
+ for attribute in interface.attributes
+ ]
- has_conditional_attributes = any(attribute['exposed_test'] for attribute in attributes)
+ has_conditional_attributes = any(
+ attribute['exposed_test'] for attribute in attributes)
if has_conditional_attributes and interface.is_partial:
raise Exception(
'Conditional attributes between partial interfaces in modules '
- 'and the original interfaces(%s) in core are not allowed.'
- % interface.name)
+ 'and the original interfaces(%s) in core are not allowed.' %
+ interface.name)
# See also comment in methods_context.
if not interface.is_partial and (interface.maplike or interface.setlike):
@@ -559,8 +692,9 @@ def attributes_context(interface, interfaces, component_info):
size_attribute.idl_type = IdlType('unsigned long')
size_attribute.is_read_only = True
size_attribute.extended_attributes['NotEnumerable'] = None
- attributes.append(v8_attributes.attribute_context(
- interface, size_attribute, interfaces, component_info))
+ attributes.append(
+ v8_attributes.attribute_context(interface, size_attribute,
+ interfaces, component_info))
return attributes
@@ -583,21 +717,32 @@ def methods_context(interface, component_info):
methods = []
if interface.original_interface:
- methods.extend([v8_methods.method_context(interface, operation, component_info, is_visible=False)
- for operation in interface.original_interface.operations
- if operation.name])
- methods.extend([v8_methods.method_context(interface, method, component_info)
- for method in interface.operations
- if method.name]) # Skip anonymous special operations (methods)
+ methods.extend([
+ v8_methods.method_context(
+ interface, operation, component_info, is_visible=False)
+ for operation in interface.original_interface.operations
+ if operation.name
+ ])
+ methods.extend([
+ v8_methods.method_context(interface, method, component_info)
+ for method in interface.operations if method.name
+ ]) # Skip anonymous special operations (methods)
if interface.partial_interfaces:
- assert len(interface.partial_interfaces) == len(set(interface.partial_interfaces))
+ assert len(interface.partial_interfaces) == len(
+ set(interface.partial_interfaces))
for partial_interface in interface.partial_interfaces:
- methods.extend([v8_methods.method_context(interface, operation, component_info, is_visible=False)
- for operation in partial_interface.operations
- if operation.name])
+ methods.extend([
+ v8_methods.method_context(
+ interface, operation, component_info, is_visible=False)
+ for operation in partial_interface.operations if operation.name
+ ])
compute_method_overloads_context(interface, methods)
- def generated_method(return_type, name, arguments=None, extended_attributes=None, implemented_as=None):
+ def generated_method(return_type,
+ name,
+ arguments=None,
+ extended_attributes=None,
+ implemented_as=None):
operation = IdlOperation()
operation.idl_type = return_type
operation.name = name
@@ -610,7 +755,10 @@ def methods_context(interface, component_info):
operation.extended_attributes['ImplementedAs'] = implemented_as
return v8_methods.method_context(interface, operation, component_info)
- def generated_argument(idl_type, name, is_optional=False, extended_attributes=None):
+ def generated_argument(idl_type,
+ name,
+ is_optional=False,
+ extended_attributes=None):
argument = IdlArgument()
argument.idl_type = idl_type
argument.name = name
@@ -630,23 +778,30 @@ def methods_context(interface, component_info):
# need to support iterator overloads between interface and
# partial interface definitions.
# http://heycam.github.io/webidl/#idl-overloading
- if (not interface.is_partial and (
- interface.iterable or interface.maplike or interface.setlike or
- interface.has_indexed_elements)):
+ if (not interface.is_partial
+ and (interface.iterable or interface.maplike or interface.setlike
+ or interface.has_indexed_elements)):
used_extended_attributes = {}
if interface.iterable:
- used_extended_attributes.update(interface.iterable.extended_attributes)
+ used_extended_attributes.update(
+ interface.iterable.extended_attributes)
elif interface.maplike:
- used_extended_attributes.update(interface.maplike.extended_attributes)
+ used_extended_attributes.update(
+ interface.maplike.extended_attributes)
elif interface.setlike:
- used_extended_attributes.update(interface.setlike.extended_attributes)
+ used_extended_attributes.update(
+ interface.setlike.extended_attributes)
if 'RaisesException' in used_extended_attributes:
- raise ValueError('[RaisesException] is implied for iterable<>/maplike<>/setlike<>')
+ raise ValueError(
+ '[RaisesException] is implied for iterable<>/maplike<>/setlike<>'
+ )
if 'CallWith' in used_extended_attributes:
- raise ValueError('[CallWith=ScriptState] is implied for iterable<>/maplike<>/setlike<>')
+ raise ValueError(
+ '[CallWith=ScriptState] is implied for iterable<>/maplike<>/setlike<>'
+ )
used_extended_attributes.update({
'RaisesException': None,
@@ -666,7 +821,8 @@ def methods_context(interface, component_info):
implemented_as=implemented_as)
if not interface.has_indexed_elements:
- iterator_method = generated_iterator_method('iterator', implemented_as='GetIterator')
+ iterator_method = generated_iterator_method(
+ 'iterator', implemented_as='GetIterator')
if interface.iterable or interface.maplike or interface.setlike:
non_overridable_methods = []
@@ -681,68 +837,101 @@ def methods_context(interface, component_info):
if not is_value_iterator:
if not interface.setlike:
iterator_method_alias = 'entries'
- entries_or_values_method = generated_iterator_method('values')
+ entries_or_values_method = generated_iterator_method(
+ 'values')
else:
iterator_method_alias = 'values'
- entries_or_values_method = generated_iterator_method('entries')
+ entries_or_values_method = generated_iterator_method(
+ 'entries')
non_overridable_methods.extend([
generated_iterator_method('keys'),
entries_or_values_method,
# void forEach(ForEachIteratorCallback callback, [DefaultValue=Undefined] optional any thisArg)
- generated_method(IdlType('void'), 'forEach',
- arguments=[generated_argument(IdlType('ForEachIteratorCallback'), 'callback'),
- generated_argument(IdlType('any'), 'thisArg',
- is_optional=True,
- extended_attributes={'DefaultValue': 'Undefined'})],
- extended_attributes=forEach_extended_attributes),
+ generated_method(
+ IdlType('void'),
+ 'forEach',
+ arguments=[
+ generated_argument(
+ IdlType('ForEachIteratorCallback'),
+ 'callback'),
+ generated_argument(
+ IdlType('any'),
+ 'thisArg',
+ is_optional=True,
+ extended_attributes={
+ 'DefaultValue': 'Undefined'
+ })
+ ],
+ extended_attributes=forEach_extended_attributes),
])
if interface.maplike:
- key_argument = generated_argument(interface.maplike.key_type, 'key')
- value_argument = generated_argument(interface.maplike.value_type, 'value')
+ key_argument = generated_argument(interface.maplike.key_type,
+ 'key')
+ value_argument = generated_argument(
+ interface.maplike.value_type, 'value')
non_overridable_methods.extend([
- generated_method(IdlType('boolean'), 'has',
- arguments=[key_argument],
- extended_attributes=used_extended_attributes),
- generated_method(IdlType('any'), 'get',
- arguments=[key_argument],
- extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('boolean'),
+ 'has',
+ arguments=[key_argument],
+ extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('any'),
+ 'get',
+ arguments=[key_argument],
+ extended_attributes=used_extended_attributes),
])
if not interface.maplike.is_read_only:
overridable_methods.extend([
- generated_method(IdlType('void'), 'clear',
- extended_attributes=used_extended_attributes),
- generated_method(IdlType('boolean'), 'delete',
- arguments=[key_argument],
- extended_attributes=used_extended_attributes),
- generated_method(IdlType(interface.name), 'set',
- arguments=[key_argument, value_argument],
- extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('void'),
+ 'clear',
+ extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('boolean'),
+ 'delete',
+ arguments=[key_argument],
+ extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType(interface.name),
+ 'set',
+ arguments=[key_argument, value_argument],
+ extended_attributes=used_extended_attributes),
])
if interface.setlike:
- value_argument = generated_argument(interface.setlike.value_type, 'value')
+ value_argument = generated_argument(
+ interface.setlike.value_type, 'value')
non_overridable_methods.extend([
- generated_method(IdlType('boolean'), 'has',
- arguments=[value_argument],
- extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('boolean'),
+ 'has',
+ arguments=[value_argument],
+ extended_attributes=used_extended_attributes),
])
if not interface.setlike.is_read_only:
overridable_methods.extend([
- generated_method(IdlType(interface.name), 'add',
- arguments=[value_argument],
- extended_attributes=used_extended_attributes),
- generated_method(IdlType('void'), 'clear',
- extended_attributes=used_extended_attributes),
- generated_method(IdlType('boolean'), 'delete',
- arguments=[value_argument],
- extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType(interface.name),
+ 'add',
+ arguments=[value_argument],
+ extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('void'),
+ 'clear',
+ extended_attributes=used_extended_attributes),
+ generated_method(
+ IdlType('boolean'),
+ 'delete',
+ arguments=[value_argument],
+ extended_attributes=used_extended_attributes),
])
methods_by_name = {}
@@ -776,11 +965,12 @@ def methods_context(interface, component_info):
implemented_as = stringifier.operation.name
else:
implemented_as = 'toString'
- methods.append(generated_method(
- return_type=IdlType('DOMString'),
- name='toString',
- extended_attributes=stringifier_ext_attrs,
- implemented_as=implemented_as))
+ methods.append(
+ generated_method(
+ return_type=IdlType('DOMString'),
+ name='toString',
+ extended_attributes=stringifier_ext_attrs,
+ implemented_as=implemented_as))
for method in methods:
# The value of the Function object’s “length” property is a Number
@@ -794,7 +984,8 @@ def methods_context(interface, component_info):
# enabled overloads are actually enabled, so length may be incorrect.
# E.g., [RuntimeEnabled=Foo] void f(); void f(long x);
# should have length 1 if Foo is not enabled, but length 0 if it is.
- method['length'] = (method['overloads']['length'] if 'overloads' in method else
+ method['length'] = (method['overloads']['length']
+ if 'overloads' in method else
method['number_of_required_arguments'])
return {
@@ -822,22 +1013,36 @@ def constant_context(constant, interface, component_info):
runtime_features = component_info['runtime_enabled_features']
return {
- 'camel_case_name': NameStyleConverter(constant.name).to_upper_camel_case(),
- 'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'),
- 'cpp_type': constant.idl_type.cpp_type,
- 'deprecate_as': v8_utilities.deprecate_as(constant), # [DeprecateAs]
- 'idl_type': constant.idl_type.name,
- 'measure_as': v8_utilities.measure_as(constant, interface), # [MeasureAs]
- 'high_entropy': v8_utilities.high_entropy(constant), # [HighEntropy]
- 'name': constant.name,
- 'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(constant,
- runtime_features), # [RuntimeEnabled] for origin trial
+ 'camel_case_name':
+ NameStyleConverter(constant.name).to_upper_camel_case(),
+ 'cpp_class':
+ extended_attributes.get('PartialInterfaceImplementedAs'),
+ 'cpp_type':
+ constant.idl_type.cpp_type,
+ 'deprecate_as':
+ v8_utilities.deprecate_as(constant), # [DeprecateAs]
+ 'idl_type':
+ constant.idl_type.name,
+ 'measure_as':
+ v8_utilities.measure_as(constant, interface), # [MeasureAs]
+ 'high_entropy':
+ v8_utilities.high_entropy(constant), # [HighEntropy]
+ 'name':
+ constant.name,
+ # [RuntimeEnabled] for origin trial
+ 'origin_trial_feature_name':
+ v8_utilities.origin_trial_feature_name(constant, runtime_features),
# FIXME: use 'reflected_name' as correct 'name'
- 'rcs_counter': 'Blink_' + v8_utilities.cpp_name(interface) + '_' + constant.name + '_ConstantGetter',
- 'reflected_name': extended_attributes.get('Reflect', reflected_name(constant.name)),
- 'runtime_enabled_feature_name': runtime_enabled_feature_name(constant,
- runtime_features), # [RuntimeEnabled] if not in origin trial
- 'value': constant.value,
+ 'rcs_counter':
+ 'Blink_' + v8_utilities.cpp_name(interface) + '_' + constant.name +
+ '_ConstantGetter',
+ 'reflected_name':
+ extended_attributes.get('Reflect', reflected_name(constant.name)),
+ # [RuntimeEnabled] if not in origin trial
+ 'runtime_enabled_feature_name':
+ runtime_enabled_feature_name(constant, runtime_features),
+ 'value':
+ constant.value,
}
@@ -845,6 +1050,7 @@ def constant_context(constant, interface, component_info):
# Overloads
################################################################################
+
def compute_method_overloads_context(interface, methods):
# Regular methods
compute_method_overloads_context_by_type(
@@ -870,7 +1076,8 @@ def compute_method_overloads_context_by_type(interface, methods):
# package necessary information into |method.overloads| for that method.
overloads[-1]['overloads'] = overloads_context(interface, overloads)
overloads[-1]['overloads']['name'] = name
- overloads[-1]['overloads']['camel_case_name'] = NameStyleConverter(name).to_upper_camel_case()
+ overloads[-1]['overloads']['camel_case_name'] = NameStyleConverter(
+ name).to_upper_camel_case()
def overloads_context(interface, overloads):
@@ -887,8 +1094,10 @@ def overloads_context(interface, overloads):
# TODO(iclelland): Allow origin trials on method overloads
# (crbug.com/621641)
if any(method.get('origin_trial_feature_name') for method in overloads):
- raise Exception('[RuntimeEnabled] for origin trial cannot be specified on '
- 'overloaded methods: %s.%s' % (interface.name, overloads[0]['name']))
+ raise Exception(
+ '[RuntimeEnabled] for origin trial cannot be specified on '
+ 'overloaded methods: %s.%s' % (interface.name,
+ overloads[0]['name']))
effective_overloads_by_length = effective_overload_set_by_length(overloads)
lengths = [length for length, _ in effective_overloads_by_length]
@@ -907,7 +1116,8 @@ def overloads_context(interface, overloads):
# runtime enabled, in which case we need to have a runtime determined
# Function.length.
shortest_overloads = effective_overloads_by_length[0][1]
- if (all(method.get('runtime_enabled_feature_name')
+ if (all(
+ method.get('runtime_enabled_feature_name')
for method, _, _ in shortest_overloads)):
# Generate a list of (length, runtime_enabled_feature_names) tuples.
runtime_determined_lengths = []
@@ -921,19 +1131,21 @@ def overloads_context(interface, overloads):
break
runtime_determined_lengths.append(
(length, sorted(runtime_enabled_feature_names)))
- function_length = ('%s::%sMethodLength()'
- % (internal_namespace(interface), camel_case_name))
+ function_length = ('%s::%sMethodLength()' % (
+ internal_namespace(interface), camel_case_name))
# Check if all overloads with the longest required arguments list are
# runtime enabled, in which case we need to have a runtime determined
# maximum distinguishing argument index.
longest_overloads = effective_overloads_by_length[-1][1]
- if (not common_value(overloads, 'runtime_enabled_feature_name') and
- all(method.get('runtime_enabled_feature_name')
+ if (not common_value(overloads, 'runtime_enabled_feature_name')
+ and all(
+ method.get('runtime_enabled_feature_name')
for method, _, _ in longest_overloads)):
# Generate a list of (length, runtime_enabled_feature_name) tuples.
runtime_determined_maxargs = []
- for length, effective_overloads in reversed(effective_overloads_by_length):
+ for length, effective_overloads in reversed(
+ effective_overloads_by_length):
runtime_enabled_feature_names = set(
method['runtime_enabled_feature_name']
for method, _, _ in effective_overloads
@@ -944,15 +1156,17 @@ def overloads_context(interface, overloads):
break
runtime_determined_maxargs.append(
(length, sorted(runtime_enabled_feature_names)))
- maxarg = ('%s::%sMethodMaxArg()' %
- (internal_namespace(interface), camel_case_name))
+ maxarg = ('%s::%sMethodMaxArg()' % (internal_namespace(interface),
+ camel_case_name))
# Check and fail if overloads disagree about whether the return type
# is a Promise or not.
- promise_overload_count = sum(1 for method in overloads if method.get('returns_promise'))
+ promise_overload_count = sum(
+ 1 for method in overloads if method.get('returns_promise'))
if promise_overload_count not in (0, len(overloads)):
- raise ValueError('Overloads of %s have conflicting Promise/non-Promise types'
- % (name))
+ raise ValueError(
+ 'Overloads of %s have conflicting Promise/non-Promise types' %
+ (name))
has_overload_visible = False
has_overload_not_visible = False
@@ -969,30 +1183,45 @@ def overloads_context(interface, overloads):
has_partial_overloads = has_overload_visible and has_overload_not_visible
return {
- 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [DeprecateAs]
- 'exposed_test_all': common_value(overloads, 'exposed_test'), # [Exposed]
- 'length': function_length,
- 'length_tests_methods': length_tests_methods(effective_overloads_by_length),
+ 'deprecate_all_as':
+ common_value(overloads, 'deprecate_as'), # [DeprecateAs]
+ 'exposed_test_all':
+ common_value(overloads, 'exposed_test'), # [Exposed]
+ 'length':
+ function_length,
+ 'length_tests_methods':
+ length_tests_methods(effective_overloads_by_length),
# 1. Let maxarg be the length of the longest type list of the
# entries in S.
- 'maxarg': maxarg,
- 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs]
- 'returns_promise_all': promise_overload_count > 0,
- 'runtime_determined_lengths': runtime_determined_lengths,
- 'runtime_determined_maxargs': runtime_determined_maxargs,
- 'runtime_enabled_all': common_value(overloads, 'runtime_enabled_feature_name'), # [RuntimeEnabled]
- 'secure_context_test_all': common_value(overloads, 'secure_context_test'), # [SecureContext]
- 'valid_arities': (lengths
- # Only need to report valid arities if there is a gap in the
- # sequence of possible lengths, otherwise invalid length means
- # "not enough arguments".
- if lengths[-1] - lengths[0] != len(lengths) - 1 else None),
- 'visible': has_overload_visible,
- 'has_partial_overloads': has_partial_overloads,
+ 'maxarg':
+ maxarg,
+ 'measure_all_as':
+ common_value(overloads, 'measure_as'), # [MeasureAs]
+ 'returns_promise_all':
+ promise_overload_count > 0,
+ 'runtime_determined_lengths':
+ runtime_determined_lengths,
+ 'runtime_determined_maxargs':
+ runtime_determined_maxargs,
+ # [RuntimeEnabled]
+ 'runtime_enabled_all':
+ common_value(overloads, 'runtime_enabled_feature_name'),
+ # [SecureContext]
+ 'secure_context_test_all':
+ common_value(overloads, 'secure_context_test'),
+ 'valid_arities': (
+ lengths
+ # Only need to report valid arities if there is a gap in the
+ # sequence of possible lengths, otherwise invalid length means
+ # "not enough arguments".
+ if lengths[-1] - lengths[0] != len(lengths) - 1 else None),
+ 'visible':
+ has_overload_visible,
+ 'has_partial_overloads':
+ has_partial_overloads,
}
-
def distinguishing_argument_index(entries):
"""Returns the distinguishing argument index for a sequence of entries.
@@ -1017,9 +1246,10 @@ def distinguishing_argument_index(entries):
return idl_type.inner_type.name
return idl_type.name
- type_lists = [tuple(typename_without_nullable(idl_type)
- for idl_type in entry[1])
- for entry in entries]
+ type_lists = [
+ tuple(typename_without_nullable(idl_type) for idl_type in entry[1])
+ for entry in entries
+ ]
type_list_length = len(type_lists[0])
# Only applicable for entries that “[have] a given type list length”
assert all(len(type_list) == type_list_length for type_list in type_lists)
@@ -1039,8 +1269,8 @@ def distinguishing_argument_index(entries):
# “In addition, for each index j, where j is less than the
# distinguishing argument index for a given type list length, the types
# at index j in all of the entries’ type lists must be the same”
- index = next(i for i, types in enumerate(types_by_index)
- if len(types) > 1)
+ index = next(
+ i for i, types in enumerate(types_by_index) if len(types) > 1)
except StopIteration:
raise ValueError('No distinguishing index found for %s, length %s:\n'
'All entries have the same type list:\n'
@@ -1055,15 +1285,16 @@ def distinguishing_argument_index(entries):
raise ValueError(
'Invalid optionality lists for %s, length %s:\n'
'Optionality lists differ below distinguishing argument index %s:\n'
- '%s'
- % (name, type_list_length, index, set(initial_optionality_lists)))
+ '%s' % (name, type_list_length, index,
+ set(initial_optionality_lists)))
# Check distinguishability
# http://heycam.github.io/webidl/#dfn-distinguishable
# Use names to check for distinct types, since objects are distinct
# FIXME: check distinguishability more precisely, for validation
- distinguishing_argument_type_names = [type_list[index]
- for type_list in type_lists]
+ distinguishing_argument_type_names = [
+ type_list[index] for type_list in type_lists
+ ]
if (len(set(distinguishing_argument_type_names)) !=
len(distinguishing_argument_type_names)):
raise ValueError('Types in distinguishing argument are not distinct:\n'
@@ -1100,8 +1331,9 @@ def resolution_tests_methods(effective_overloads):
Returns:
[(test, method)]
"""
- methods = [effective_overload[0]
- for effective_overload in effective_overloads]
+ methods = [
+ effective_overload[0] for effective_overload in effective_overloads
+ ]
if len(methods) == 1:
# If only one method with a given length, no test needed
yield 'true', methods[0]
@@ -1251,9 +1483,8 @@ def resolution_tests_methods(effective_overloads):
# ...
try:
method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_callback_interface or
- idl_type.is_dictionary or idl_type.name == 'Dictionary' or
- idl_type.is_record_type)
+ if idl_type.is_callback_interface
+ or idl_type.is_dictionary or idl_type.is_record_type)
test = '%s->IsObject()' % cpp_value
yield test, method
except StopIteration:
@@ -1288,9 +1519,10 @@ def resolution_tests_methods(effective_overloads):
# • a string type
# ...
try:
- method = next(method for idl_type, method in idl_types_methods
- if idl_type.is_string_type or idl_type.is_enum
- or (idl_type.is_union_type and idl_type.string_member_type))
+ method = next(
+ method for idl_type, method in idl_types_methods
+ if idl_type.is_string_type or idl_type.is_enum or (
+ idl_type.is_union_type and idl_type.string_member_type))
yield 'true', method
except StopIteration:
pass
@@ -1322,6 +1554,7 @@ def resolution_tests_methods(effective_overloads):
# Utility functions
################################################################################
+
def common(dicts, f):
"""Returns common result of f across an iterable of dicts, or None.
@@ -1361,6 +1594,7 @@ def internal_namespace(interface):
# Constructors
################################################################################
+
# [Constructor]
def constructor_context(interface, constructor):
# [RaisesException=Constructor]
@@ -1369,39 +1603,46 @@ def constructor_context(interface, constructor):
argument_contexts = [
v8_methods.argument_context(interface, constructor, argument, index)
- for index, argument in enumerate(constructor.arguments)]
+ for index, argument in enumerate(constructor.arguments)
+ ]
return {
- 'arguments': argument_contexts,
- 'cpp_type': cpp_name(interface) + '*',
- 'cpp_value': v8_methods.cpp_value(
- interface, constructor, len(constructor.arguments)),
+ 'arguments':
+ argument_contexts,
+ 'cpp_type':
+ cpp_name(interface) + '*',
+ 'cpp_value':
+ v8_methods.cpp_value(interface, constructor,
+ len(constructor.arguments)),
'has_exception_state':
- is_constructor_raises_exception or
- any(argument for argument in constructor.arguments
- if argument.idl_type.name == 'SerializedScriptValue' or
- argument.idl_type.v8_conversion_needs_exception_state),
+ is_constructor_raises_exception
+ or any(argument for argument in constructor.arguments
+ if argument.idl_type.v8_conversion_needs_exception_state),
'has_optional_argument_without_default_value':
- any(True for argument_context in argument_contexts
- if argument_context['is_optional_without_default_value']),
+ any(True for argument_context in argument_contexts
+ if argument_context['is_optional_without_default_value']),
'is_call_with_document':
- # [ConstructorCallWith=Document]
- has_extended_attribute_value(interface,
- 'ConstructorCallWith', 'Document'),
+ # [ConstructorCallWith=Document]
+ has_extended_attribute_value(interface, 'ConstructorCallWith',
+ 'Document'),
'is_call_with_execution_context':
- # [ConstructorCallWith=ExecutionContext]
- has_extended_attribute_value(interface,
- 'ConstructorCallWith', 'ExecutionContext'),
+ # [ConstructorCallWith=ExecutionContext]
+ has_extended_attribute_value(interface, 'ConstructorCallWith',
+ 'ExecutionContext'),
'is_call_with_script_state':
- # [ConstructorCallWith=ScriptState]
- has_extended_attribute_value(
- interface, 'ConstructorCallWith', 'ScriptState'),
- 'is_constructor': True,
- 'is_named_constructor': False,
- 'is_raises_exception': is_constructor_raises_exception,
+ # [ConstructorCallWith=ScriptState]
+ has_extended_attribute_value(interface, 'ConstructorCallWith',
+ 'ScriptState'),
+ 'is_constructor':
+ True,
+ 'is_named_constructor':
+ False,
+ 'is_raises_exception':
+ is_constructor_raises_exception,
'number_of_required_arguments':
- number_of_required_arguments(constructor),
- 'rcs_counter': 'Blink_' + v8_utilities.cpp_name(interface) + '_ConstructorCallback'
+ number_of_required_arguments(constructor),
+ 'rcs_counter':
+ 'Blink_' + v8_utilities.cpp_name(interface) + '_ConstructorCallback'
}
@@ -1424,8 +1665,10 @@ def named_constructor_context(interface):
def number_of_required_arguments(constructor):
- return len([argument for argument in constructor.arguments
- if not (argument.is_optional or argument.is_variadic)])
+ return len([
+ argument for argument in constructor.arguments
+ if not (argument.is_optional or argument.is_variadic)
+ ])
def interface_length(constructors):
@@ -1441,6 +1684,7 @@ def interface_length(constructors):
# http://heycam.github.io/webidl/#idl-special-operations
################################################################################
+
def property_getter(getter, cpp_arguments):
if not getter:
return None
@@ -1455,10 +1699,12 @@ def property_getter(getter, cpp_arguments):
return ''
extended_attributes = getter.extended_attributes
- has_no_side_effect = v8_utilities.has_extended_attribute_value(getter, 'Affects', 'Nothing')
+ has_no_side_effect = v8_utilities.has_extended_attribute_value(
+ getter, 'Affects', 'Nothing')
idl_type = getter.idl_type
idl_type.add_includes_for_type(extended_attributes)
- is_call_with_script_state = v8_utilities.has_extended_attribute_value(getter, 'CallWith', 'ScriptState')
+ is_call_with_script_state = v8_utilities.has_extended_attribute_value(
+ getter, 'CallWith', 'ScriptState')
is_raises_exception = 'RaisesException' in extended_attributes
use_output_parameter_for_result = idl_type.use_output_parameter_for_result
@@ -1475,27 +1721,41 @@ def property_getter(getter, cpp_arguments):
cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
return {
- 'cpp_type': idl_type.cpp_type,
- 'cpp_value': cpp_value,
- 'has_no_side_effect': has_no_side_effect,
- 'is_call_with_script_state': is_call_with_script_state,
- 'is_cross_origin': 'CrossOrigin' in extended_attributes,
+ 'cpp_type':
+ idl_type.cpp_type,
+ 'cpp_value':
+ cpp_value,
+ 'has_no_side_effect':
+ has_no_side_effect,
+ 'is_call_with_script_state':
+ is_call_with_script_state,
+ 'is_cross_origin':
+ 'CrossOrigin' in extended_attributes,
'is_custom':
- 'Custom' in extended_attributes and
- (not extended_attributes['Custom'] or
- has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')),
- 'is_custom_property_enumerator': has_extended_attribute_value(
- getter, 'Custom', 'PropertyEnumerator'),
- 'is_custom_property_query': has_extended_attribute_value(
- getter, 'Custom', 'PropertyQuery'),
+ 'Custom' in extended_attributes and
+ (not extended_attributes['Custom']
+ or has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')),
+ 'is_custom_property_enumerator':
+ has_extended_attribute_value(getter, 'Custom', 'PropertyEnumerator'),
+ 'is_custom_property_query':
+ has_extended_attribute_value(getter, 'Custom', 'PropertyQuery'),
# TODO(rakuco): [NotEnumerable] does not make sense here and is only
# used in non-standard IDL operations. We need to get rid of them.
- 'is_enumerable': 'NotEnumerable' not in extended_attributes,
- 'is_null_expression': is_null_expression(idl_type),
- 'is_raises_exception': is_raises_exception,
- 'name': cpp_name(getter),
- 'use_output_parameter_for_result': use_output_parameter_for_result,
- 'v8_set_return_value': idl_type.v8_set_return_value('result', extended_attributes=extended_attributes, script_wrappable='impl'),
+ 'is_enumerable':
+ 'NotEnumerable' not in extended_attributes,
+ 'is_null_expression':
+ is_null_expression(idl_type),
+ 'is_raises_exception':
+ is_raises_exception,
+ 'name':
+ cpp_name(getter),
+ 'use_output_parameter_for_result':
+ use_output_parameter_for_result,
+ 'v8_set_return_value':
+ idl_type.v8_set_return_value(
+ 'result',
+ extended_attributes=extended_attributes,
+ script_wrappable='impl'),
}
@@ -1506,25 +1766,35 @@ def property_setter(setter, interface):
extended_attributes = setter.extended_attributes
idl_type = setter.arguments[1].idl_type
idl_type.add_includes_for_type(extended_attributes)
- is_call_with_script_state = v8_utilities.has_extended_attribute_value(setter, 'CallWith', 'ScriptState')
+ is_call_with_script_state = v8_utilities.has_extended_attribute_value(
+ setter, 'CallWith', 'ScriptState')
is_raises_exception = 'RaisesException' in extended_attributes
is_ce_reactions = 'CEReactions' in extended_attributes
has_type_checking_interface = idl_type.is_wrapper_type
return {
- 'has_exception_state': (is_raises_exception or
- idl_type.v8_conversion_needs_exception_state),
- 'has_type_checking_interface': has_type_checking_interface,
- 'idl_type': idl_type.base_type,
- 'is_call_with_script_state': is_call_with_script_state,
- 'is_ce_reactions': is_ce_reactions,
- 'is_custom': 'Custom' in extended_attributes,
- 'is_nullable': idl_type.is_nullable,
- 'is_raises_exception': is_raises_exception,
- 'name': cpp_name(setter),
- 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
- extended_attributes, 'v8_value', 'property_value'),
+ 'has_exception_state':
+ (is_raises_exception or idl_type.v8_conversion_needs_exception_state),
+ 'has_type_checking_interface':
+ has_type_checking_interface,
+ 'idl_type':
+ idl_type.base_type,
+ 'is_call_with_script_state':
+ is_call_with_script_state,
+ 'is_ce_reactions':
+ is_ce_reactions,
+ 'is_custom':
+ 'Custom' in extended_attributes,
+ 'is_nullable':
+ idl_type.is_nullable,
+ 'is_raises_exception':
+ is_raises_exception,
+ 'name':
+ cpp_name(setter),
+ 'v8_value_to_local_cpp_value':
+ idl_type.v8_value_to_local_cpp_value(extended_attributes, 'v8_value',
+ 'property_value'),
}
@@ -1533,7 +1803,8 @@ def property_deleter(deleter):
return None
extended_attributes = deleter.extended_attributes
- is_call_with_script_state = v8_utilities.has_extended_attribute_value(deleter, 'CallWith', 'ScriptState')
+ is_call_with_script_state = v8_utilities.has_extended_attribute_value(
+ deleter, 'CallWith', 'ScriptState')
is_ce_reactions = 'CEReactions' in extended_attributes
return {
'is_call_with_script_state': is_call_with_script_state,
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
index 07fcc8d0f8e..22f9a93432c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
@@ -25,7 +25,6 @@
# 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.
-
"""Generate template values for methods.
Extends IdlArgument with property |default_cpp_value|.
@@ -37,8 +36,8 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(__file__),
- '..', '..', 'build', 'scripts'))
+sys.path.append(
+ os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'scripts'))
from blinkbuild.name_style_converter import NameStyleConverter
from idl_definitions import IdlArgument, IdlOperation
from idl_types import IdlTypeBase, IdlUnionType, inherits_interface
@@ -50,7 +49,9 @@ from v8_utilities import (has_extended_attribute_value, is_unforgeable)
def method_is_visible(method, interface_is_partial):
if 'overloads' in method:
- return method['overloads']['visible'] and not (method['overloads']['has_partial_overloads'] and interface_is_partial)
+ return method['overloads']['visible'] and not (
+ method['overloads']['has_partial_overloads']
+ and interface_is_partial)
return method['visible'] and 'overload_index' not in method
@@ -59,19 +60,23 @@ def is_origin_trial_enabled(method):
def is_secure_context(method):
- return bool(method['overloads']['secure_context_test_all'] if 'overloads' in method else method['secure_context_test'])
+ return bool(method['overloads']['secure_context_test_all'] if 'overloads'
+ in method else method['secure_context_test'])
def is_conditionally_enabled(method):
- exposed = method['overloads']['exposed_test_all'] if 'overloads' in method else method['exposed_test']
+ exposed = method['overloads']['exposed_test_all'] \
+ if 'overloads' in method else method['exposed_test']
return exposed or is_secure_context(method)
def filter_conditionally_enabled(methods, interface_is_partial):
- return [method for method in methods if (
- method_is_visible(method, interface_is_partial) and
- is_conditionally_enabled(method) and
- not is_origin_trial_enabled(method))]
+ return [
+ method for method in methods
+ if (method_is_visible(method, interface_is_partial)
+ and is_conditionally_enabled(method)
+ and not is_origin_trial_enabled(method))
+ ]
def custom_registration(method):
@@ -81,48 +86,65 @@ def custom_registration(method):
if method['is_cross_origin']:
return True
if 'overloads' in method:
- return (method['overloads']['runtime_determined_lengths'] or
- (method['overloads']['runtime_enabled_all'] and not is_conditionally_enabled(method)))
- return method['runtime_enabled_feature_name'] and not is_conditionally_enabled(method)
+ return (method['overloads']['runtime_determined_lengths']
+ or (method['overloads']['runtime_enabled_all']
+ and not is_conditionally_enabled(method)))
+ return method[
+ 'runtime_enabled_feature_name'] and not is_conditionally_enabled(
+ method)
def filter_custom_registration(methods, interface_is_partial):
- return [method for method in methods if (
- method_is_visible(method, interface_is_partial) and custom_registration(method))]
+ return [
+ method for method in methods
+ if (method_is_visible(method, interface_is_partial)
+ and custom_registration(method))
+ ]
def filter_method_configuration(methods, interface_is_partial):
- return [method for method in methods if
- method_is_visible(method, interface_is_partial) and
- not is_origin_trial_enabled(method) and
- not is_conditionally_enabled(method) and
- not custom_registration(method)]
+ return [
+ method for method in methods
+ if method_is_visible(method, interface_is_partial)
+ and not is_origin_trial_enabled(method)
+ and not is_conditionally_enabled(method)
+ and not custom_registration(method)
+ ]
def method_filters():
- return {'custom_registration': filter_custom_registration,
- 'has_method_configuration': filter_method_configuration}
+ return {
+ 'custom_registration': filter_custom_registration,
+ 'has_method_configuration': filter_method_configuration
+ }
def use_local_result(method):
extended_attributes = method.extended_attributes
idl_type = method.idl_type
- return (has_extended_attribute_value(method, 'CallWith', 'ScriptState') or
- 'NewObject' in extended_attributes or
- 'RaisesException' in extended_attributes or
- idl_type.is_union_type or
- idl_type.is_dictionary or
- idl_type.is_explicit_nullable)
+ return (has_extended_attribute_value(method, 'CallWith', 'ScriptState')
+ or 'NewObject' in extended_attributes
+ or 'RaisesException' in extended_attributes
+ or idl_type.is_union_type or idl_type.is_dictionary
+ or idl_type.is_explicit_nullable)
def runtime_call_stats_context(interface, method):
includes.add('platform/bindings/runtime_call_stats.h')
- generic_counter_name = 'Blink_' + v8_utilities.cpp_name(interface) + '_' + method.name
- (method_counter, extended_attribute_defined) = v8_utilities.rcs_counter_name(method, generic_counter_name)
+ generic_counter_name = (
+ 'Blink_' + v8_utilities.cpp_name(interface) + '_' + method.name)
+ (method_counter, extended_attribute_defined) = \
+ v8_utilities.rcs_counter_name(method, generic_counter_name)
+ trace_event_name = interface.name + '.' + method.name
return {
- 'extended_attribute_defined': extended_attribute_defined,
- 'method_counter': method_counter,
- 'origin_safe_method_getter_counter': generic_counter_name + '_OriginSafeMethodGetter'
+ 'extended_attribute_defined':
+ extended_attribute_defined,
+ 'method_counter':
+ method_counter,
+ 'origin_safe_method_getter_counter':
+ generic_counter_name + '_OriginSafeMethodGetter',
+ 'trace_event_name':
+ trace_event_name,
}
@@ -138,18 +160,19 @@ def method_context(interface, method, component_info, is_visible=True):
this_cpp_value = cpp_value(interface, method, len(arguments))
- is_call_with_script_state = has_extended_attribute_value(method, 'CallWith', 'ScriptState')
- is_call_with_this_value = has_extended_attribute_value(method, 'CallWith', 'ThisValue')
+ is_call_with_script_state = has_extended_attribute_value(
+ method, 'CallWith', 'ScriptState')
+ is_call_with_this_value = has_extended_attribute_value(
+ method, 'CallWith', 'ThisValue')
if is_call_with_script_state or is_call_with_this_value:
includes.add('platform/bindings/script_state.h')
# [CheckSecurity]
is_cross_origin = 'CrossOrigin' in extended_attributes
- is_check_security_for_receiver = (
- has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and
- not is_cross_origin)
- is_check_security_for_return_value = (
- has_extended_attribute_value(method, 'CheckSecurity', 'ReturnValue'))
+ is_check_security_for_receiver = (has_extended_attribute_value(
+ interface, 'CheckSecurity', 'Receiver') and not is_cross_origin)
+ is_check_security_for_return_value = (has_extended_attribute_value(
+ method, 'CheckSecurity', 'ReturnValue'))
if is_check_security_for_receiver or is_check_security_for_return_value:
includes.add('bindings/core/v8/binding_security.h')
if is_check_security_for_return_value:
@@ -164,8 +187,6 @@ def method_context(interface, method, component_info, is_visible=True):
includes.add('core/html/custom/v0_custom_element_processing_stack.h')
is_raises_exception = 'RaisesException' in extended_attributes
- is_custom_call_prologue = has_extended_attribute_value(method, 'Custom', 'CallPrologue')
- is_custom_call_epilogue = has_extended_attribute_value(method, 'Custom', 'CallEpilogue')
if 'LenientThis' in extended_attributes:
raise Exception('[LenientThis] is not supported for operations.')
@@ -180,89 +201,142 @@ def method_context(interface, method, component_info, is_visible=True):
includes.add('platform/bindings/v8_per_context_data.h')
argument_contexts = [
- argument_context(interface, method, argument, index, is_visible=is_visible)
- for index, argument in enumerate(arguments)]
+ argument_context(
+ interface, method, argument, index, is_visible=is_visible)
+ for index, argument in enumerate(arguments)
+ ]
runtime_features = component_info['runtime_enabled_features']
return {
- 'activity_logging_world_list': v8_utilities.activity_logging_world_list(method), # [ActivityLogging]
- 'arguments': argument_contexts,
- 'camel_case_name': NameStyleConverter(name).to_upper_camel_case(),
- 'cpp_type': (v8_types.cpp_template_type('base::Optional', idl_type.cpp_type)
- if idl_type.is_explicit_nullable
- else v8_types.cpp_type(idl_type, extended_attributes=extended_attributes)),
- 'cpp_value': this_cpp_value,
- 'cpp_type_initializer': idl_type.cpp_type_initializer,
- 'high_entropy': v8_utilities.high_entropy(method), # [HighEntropy]
- 'deprecate_as': v8_utilities.deprecate_as(method), # [DeprecateAs]
- 'do_not_test_new_object': 'DoNotTestNewObject' in extended_attributes,
- 'exposed_test': v8_utilities.exposed(method, interface), # [Exposed]
+ 'activity_logging_world_list':
+ v8_utilities.activity_logging_world_list(method), # [ActivityLogging]
+ 'arguments':
+ argument_contexts,
+ 'camel_case_name':
+ NameStyleConverter(name).to_upper_camel_case(),
+ 'cpp_type':
+ (v8_types.cpp_template_type('base::Optional', idl_type.cpp_type)
+ if idl_type.is_explicit_nullable else v8_types.cpp_type(
+ idl_type, extended_attributes=extended_attributes)),
+ 'cpp_value':
+ this_cpp_value,
+ 'cpp_type_initializer':
+ idl_type.cpp_type_initializer,
+ 'high_entropy':
+ v8_utilities.high_entropy(method), # [HighEntropy]
+ 'deprecate_as':
+ v8_utilities.deprecate_as(method), # [DeprecateAs]
+ 'do_not_test_new_object':
+ 'DoNotTestNewObject' in extended_attributes,
+ 'exposed_test':
+ v8_utilities.exposed(method, interface), # [Exposed]
'has_exception_state':
- is_raises_exception or
- is_check_security_for_receiver or
- any(argument for argument in arguments
- if (argument.idl_type.name == 'SerializedScriptValue' or
- argument_conversion_needs_exception_state(method, argument))),
+ is_raises_exception or is_check_security_for_receiver or any(
+ argument for argument in arguments
+ if argument_conversion_needs_exception_state(method, argument)),
'has_optional_argument_without_default_value':
- any(True for argument_context in argument_contexts
- if argument_context['is_optional_without_default_value']),
- 'idl_type': idl_type.base_type,
- 'is_call_with_execution_context': has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'),
- 'is_call_with_script_state': is_call_with_script_state,
- 'is_call_with_this_value': is_call_with_this_value,
- 'is_ce_reactions': is_ce_reactions,
- 'is_check_security_for_receiver': is_check_security_for_receiver,
- 'is_check_security_for_return_value': is_check_security_for_return_value,
- 'is_cross_origin': 'CrossOrigin' in extended_attributes,
- 'is_custom': 'Custom' in extended_attributes and
- not (is_custom_call_prologue or is_custom_call_epilogue),
- 'is_custom_call_prologue': is_custom_call_prologue,
- 'is_custom_call_epilogue': is_custom_call_epilogue,
- 'is_custom_element_callbacks': is_custom_element_callbacks,
- 'is_explicit_nullable': idl_type.is_explicit_nullable,
- 'is_new_object': 'NewObject' in extended_attributes,
+ any(True for argument_context in argument_contexts
+ if argument_context['is_optional_without_default_value']),
+ 'idl_type':
+ idl_type.base_type,
+ 'is_call_with_execution_context':
+ has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'),
+ 'is_call_with_script_state':
+ is_call_with_script_state,
+ 'is_call_with_this_value':
+ is_call_with_this_value,
+ 'is_ce_reactions':
+ is_ce_reactions,
+ 'is_check_security_for_receiver':
+ is_check_security_for_receiver,
+ 'is_check_security_for_return_value':
+ is_check_security_for_return_value,
+ 'is_cross_origin':
+ 'CrossOrigin' in extended_attributes,
+ 'is_custom':
+ 'Custom' in extended_attributes,
+ 'is_custom_element_callbacks':
+ is_custom_element_callbacks,
+ 'is_explicit_nullable':
+ idl_type.is_explicit_nullable,
+ 'is_new_object':
+ 'NewObject' in extended_attributes,
'is_partial_interface_member':
- 'PartialInterfaceImplementedAs' in extended_attributes,
- 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
- 'is_raises_exception': is_raises_exception,
- 'is_static': is_static,
- 'is_unforgeable': is_unforgeable(method),
- 'is_variadic': arguments and arguments[-1].is_variadic,
- 'measure_as': v8_utilities.measure_as(method, interface), # [MeasureAs]
- 'name': name,
- 'number_of_arguments': len(arguments),
- 'number_of_required_arguments': len([
+ 'PartialInterfaceImplementedAs' in extended_attributes,
+ 'is_per_world_bindings':
+ 'PerWorldBindings' in extended_attributes,
+ 'is_raises_exception':
+ is_raises_exception,
+ 'is_static':
+ is_static,
+ 'is_unforgeable':
+ is_unforgeable(method),
+ 'is_variadic':
+ arguments and arguments[-1].is_variadic,
+ 'measure_as':
+ v8_utilities.measure_as(method, interface), # [MeasureAs]
+ 'name':
+ name,
+ 'number_of_arguments':
+ len(arguments),
+ 'number_of_required_arguments':
+ len([
argument for argument in arguments
- if not (argument.is_optional or argument.is_variadic)]),
- 'number_of_required_or_variadic_arguments': len([
- argument for argument in arguments
- if not argument.is_optional]),
- 'on_instance': v8_utilities.on_instance(interface, method),
- 'on_interface': v8_utilities.on_interface(interface, method),
- 'on_prototype': v8_utilities.on_prototype(interface, method),
+ if not (argument.is_optional or argument.is_variadic)
+ ]),
+ 'number_of_required_or_variadic_arguments':
+ len([argument for argument in arguments if not argument.is_optional]),
+ 'on_instance':
+ v8_utilities.on_instance(interface, method),
+ 'on_interface':
+ v8_utilities.on_interface(interface, method),
+ 'on_prototype':
+ v8_utilities.on_prototype(interface, method),
+ # [RuntimeEnabled] for origin trial
'origin_trial_feature_name':
- v8_utilities.origin_trial_feature_name(method, runtime_features), # [RuntimeEnabled] for origin trial
- 'property_attributes': property_attributes(interface, method),
- 'returns_promise': method.returns_promise,
- 'runtime_call_stats': runtime_call_stats_context(interface, method),
+ v8_utilities.origin_trial_feature_name(method, runtime_features),
+ 'property_attributes':
+ property_attributes(interface, method),
+ 'returns_promise':
+ method.returns_promise,
+ 'runtime_call_stats':
+ runtime_call_stats_context(interface, method),
+ # [RuntimeEnabled] if not in origin trial
'runtime_enabled_feature_name':
- v8_utilities.runtime_enabled_feature_name(method, runtime_features), # [RuntimeEnabled] if not in origin trial
- 'secure_context_test': v8_utilities.secure_context(method, interface), # [SecureContext]
- 'side_effect_type': side_effect_type, # [Affects]
- 'snake_case_name': NameStyleConverter(name).to_snake_case(),
- 'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
- 'use_local_result': use_local_result(method),
- 'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
- 'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True),
- 'visible': is_visible,
- 'world_suffixes': ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else [''], # [PerWorldBindings],
+ v8_utilities.runtime_enabled_feature_name(method, runtime_features),
+ # [SecureContext]
+ 'secure_context_test':
+ v8_utilities.secure_context(method, interface),
+ # [Affects]
+ 'side_effect_type':
+ side_effect_type,
+ 'snake_case_name':
+ NameStyleConverter(name).to_snake_case(),
+ 'use_output_parameter_for_result':
+ idl_type.use_output_parameter_for_result,
+ 'use_local_result':
+ use_local_result(method),
+ 'v8_set_return_value':
+ v8_set_return_value(interface.name, method, this_cpp_value),
+ 'v8_set_return_value_for_main_world':
+ v8_set_return_value(
+ interface.name, method, this_cpp_value, for_main_world=True),
+ 'visible':
+ is_visible,
+ 'world_suffixes':
+ ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else
+ [''], # [PerWorldBindings],
}
def argument_context(interface, method, argument, index, is_visible=True):
extended_attributes = argument.extended_attributes
idl_type = argument.idl_type
+ if idl_type.has_string_context:
+ includes.add(
+ 'third_party/blink/renderer/bindings/core/v8/generated_code_helper.h'
+ )
if is_visible:
idl_type.add_includes_for_type(extended_attributes)
this_cpp_value = cpp_value(interface, method, index)
@@ -271,52 +345,77 @@ def argument_context(interface, method, argument, index, is_visible=True):
has_type_checking_interface = idl_type.is_wrapper_type
set_default_value = argument.set_default_value
- this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes,
- raw_type=True,
- used_as_variadic_argument=argument.is_variadic)
+ this_cpp_type = idl_type.cpp_type_args(
+ extended_attributes=extended_attributes,
+ raw_type=True,
+ used_as_variadic_argument=argument.is_variadic)
snake_case_name = NameStyleConverter(argument.name).to_snake_case()
context = {
- 'cpp_type': (
- v8_types.cpp_template_type('base::Optional', this_cpp_type)
- if idl_type.is_explicit_nullable and not argument.is_variadic
- else this_cpp_type),
- 'cpp_value': this_cpp_value,
+ 'cpp_type': (v8_types.cpp_template_type(
+ 'base::Optional', this_cpp_type) if idl_type.is_explicit_nullable
+ and not argument.is_variadic else this_cpp_type),
+ 'cpp_value':
+ this_cpp_value,
# FIXME: check that the default value's type is compatible with the argument's
- 'enum_type': idl_type.enum_type,
- 'enum_values': idl_type.enum_values,
- 'handle': '%s_handle' % snake_case_name,
+ 'enum_type':
+ idl_type.enum_type,
+ 'enum_values':
+ idl_type.enum_values,
+ 'handle':
+ '%s_handle' % snake_case_name,
# TODO(peria): remove once [DefaultValue] removed and just use
# argument.default_value. https://crbug.com/924419
- 'has_default': 'DefaultValue' in extended_attributes or set_default_value,
- 'has_type_checking_interface': has_type_checking_interface,
+ 'has_default':
+ 'DefaultValue' in extended_attributes or set_default_value,
+ 'has_type_checking_interface':
+ has_type_checking_interface,
# Dictionary is special-cased, but arrays and sequences shouldn't be
- 'idl_type': idl_type.base_type,
- 'idl_type_object': idl_type,
- 'index': index,
- 'is_callback_function': idl_type.is_callback_function,
- 'is_callback_interface': idl_type.is_callback_interface,
+ 'idl_type':
+ idl_type.base_type,
+ 'idl_type_object':
+ idl_type,
+ 'index':
+ index,
+ 'is_callback_function':
+ idl_type.is_callback_function,
+ 'is_callback_interface':
+ idl_type.is_callback_interface,
# FIXME: Remove generic 'Dictionary' special-casing
- 'is_dictionary': idl_type.is_dictionary or idl_type.base_type == 'Dictionary',
- 'is_explicit_nullable': idl_type.is_explicit_nullable,
- 'is_nullable': idl_type.is_nullable,
- 'is_optional': argument.is_optional,
- 'is_variadic': argument.is_variadic,
- 'is_variadic_wrapper_type': is_variadic_wrapper_type,
- 'is_wrapper_type': idl_type.is_wrapper_type,
- 'local_cpp_variable': snake_case_name,
- 'name': argument.name,
- 'set_default_value': set_default_value,
- 'use_permissive_dictionary_conversion': 'PermissiveDictionaryConversion' in extended_attributes,
- 'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
- 'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True),
- 'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(interface.name, method, argument, index),
+ 'is_dictionary':
+ idl_type.is_dictionary,
+ 'is_explicit_nullable':
+ idl_type.is_explicit_nullable,
+ 'is_nullable':
+ idl_type.is_nullable,
+ 'is_optional':
+ argument.is_optional,
+ 'is_variadic':
+ argument.is_variadic,
+ 'is_variadic_wrapper_type':
+ is_variadic_wrapper_type,
+ 'is_wrapper_type':
+ idl_type.is_wrapper_type,
+ 'local_cpp_variable':
+ snake_case_name,
+ 'name':
+ argument.name,
+ 'set_default_value':
+ set_default_value,
+ 'use_permissive_dictionary_conversion':
+ 'PermissiveDictionaryConversion' in extended_attributes,
+ 'v8_set_return_value':
+ v8_set_return_value(interface.name, method, this_cpp_value),
+ 'v8_set_return_value_for_main_world':
+ v8_set_return_value(
+ interface.name, method, this_cpp_value, for_main_world=True),
+ 'v8_value_to_local_cpp_value':
+ v8_value_to_local_cpp_value(interface.name, method, argument, index),
}
context.update({
'is_optional_without_default_value':
- context['is_optional'] and
- not context['has_default'] and
- not context['is_dictionary'] and
- not context['is_callback_interface'],
+ context['is_optional'] and not context['has_default']
+ and not context['is_dictionary']
+ and not context['is_callback_interface'],
})
return context
@@ -325,13 +424,15 @@ def argument_context(interface, method, argument, index, is_visible=True):
# Value handling
################################################################################
+
def cpp_value(interface, method, number_of_arguments):
# Truncate omitted optional arguments
arguments = method.arguments[:number_of_arguments]
cpp_arguments = []
if method.is_constructor:
- call_with_values = interface.extended_attributes.get('ConstructorCallWith')
+ call_with_values = interface.extended_attributes.get(
+ 'ConstructorCallWith')
else:
call_with_values = method.extended_attributes.get('CallWith')
cpp_arguments.extend(v8_utilities.call_with_arguments(call_with_values))
@@ -339,20 +440,12 @@ def cpp_value(interface, method, number_of_arguments):
# Members of IDL partial interface definitions are implemented in C++ as
# static member functions, which for instance members (non-static members)
# take *impl as their first argument
- if ('PartialInterfaceImplementedAs' in method.extended_attributes and
- not method.is_static):
+ if ('PartialInterfaceImplementedAs' in method.extended_attributes
+ and not method.is_static):
cpp_arguments.append('*impl')
for argument in arguments:
variable_name = NameStyleConverter(argument.name).to_snake_case()
- if argument.idl_type.base_type == 'SerializedScriptValue':
- cpp_arguments.append('std::move(%s)' % variable_name)
- else:
- cpp_arguments.append(variable_name)
-
- if ('RaisesException' in method.extended_attributes or
- (method.is_constructor and
- has_extended_attribute_value(interface, 'RaisesException', 'Constructor'))):
- cpp_arguments.append('exception_state')
+ cpp_arguments.append(variable_name)
# If a method returns an IDL dictionary or union type, the return value is
# passed as an argument to impl classes.
@@ -360,6 +453,11 @@ def cpp_value(interface, method, number_of_arguments):
if idl_type and idl_type.use_output_parameter_for_result:
cpp_arguments.append('result')
+ if ('RaisesException' in method.extended_attributes
+ or (method.is_constructor and has_extended_attribute_value(
+ interface, 'RaisesException', 'Constructor'))):
+ cpp_arguments.append('exception_state')
+
if method.name == 'Constructor':
base_name = 'Create'
elif method.name == 'NamedConstructor':
@@ -371,7 +469,10 @@ def cpp_value(interface, method, number_of_arguments):
return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
-def v8_set_return_value(interface_name, method, cpp_value, for_main_world=False):
+def v8_set_return_value(interface_name,
+ method,
+ cpp_value,
+ for_main_world=False):
idl_type = method.idl_type
extended_attributes = method.extended_attributes
if not idl_type or idl_type.name == 'void':
@@ -386,75 +487,61 @@ def v8_set_return_value(interface_name, method, cpp_value, for_main_world=False)
else:
cpp_value = 'result'
- script_wrappable = 'impl' if inherits_interface(interface_name, 'Node') else ''
- return idl_type.v8_set_return_value(cpp_value, extended_attributes, script_wrappable=script_wrappable, for_main_world=for_main_world, is_static=method.is_static)
+ script_wrappable = 'impl' if inherits_interface(interface_name,
+ 'Node') else ''
+ return idl_type.v8_set_return_value(
+ cpp_value,
+ extended_attributes,
+ script_wrappable=script_wrappable,
+ for_main_world=for_main_world,
+ is_static=method.is_static)
-def v8_value_to_local_cpp_variadic_value(argument, index):
+def v8_value_to_local_cpp_variadic_value(argument,
+ index,
+ for_constructor_callback=False):
assert argument.is_variadic
- idl_type = v8_types.native_value_traits_type_name(argument.idl_type,
- argument.extended_attributes, True)
-
+ idl_type = v8_types.native_value_traits_type_name(
+ argument.idl_type, argument.extended_attributes, True)
+ execution_context_if_needed = ''
+ if argument.idl_type.has_string_context:
+ execution_context_if_needed = ', bindings::ExecutionContextFromV8Wrappable(impl)'
+ if for_constructor_callback:
+ execution_context_if_needed = ', CurrentExecutionContext(info.GetIsolate())'
+ assign_expression = 'ToImplArguments<%s>(info, %s, exception_state%s)' % (
+ idl_type, index, execution_context_if_needed)
return {
- 'assign_expression': 'ToImplArguments<%s>(info, %s, exception_state)' % (idl_type, index),
+ 'assign_expression': assign_expression,
'check_expression': 'exception_state.HadException()',
'cpp_name': NameStyleConverter(argument.name).to_snake_case(),
'declare_variable': False,
}
-def v8_value_to_local_cpp_ssv_value(extended_attributes, idl_type, v8_value, variable_name, for_storage):
- this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True)
-
- storage_policy = 'kForStorage' if for_storage else 'kNotForStorage'
- arguments = ', '.join([
- 'info.GetIsolate()',
- v8_value,
- '{ssv}::SerializeOptions({ssv}::{storage_policy})',
- 'exception_state'
- ])
- cpp_expression_format = 'NativeValueTraits<{ssv}>::NativeValue(%s)' % arguments
- this_cpp_value = cpp_expression_format.format(
- ssv='SerializedScriptValue',
- storage_policy=storage_policy
- )
-
- return {
- 'assign_expression': this_cpp_value,
- 'check_expression': 'exception_state.HadException()',
- 'cpp_type': this_cpp_type,
- 'cpp_name': variable_name,
- 'declare_variable': False,
- }
-
-
def v8_value_to_local_cpp_value(interface_name, method, argument, index):
extended_attributes = argument.extended_attributes
idl_type = argument.idl_type
name = NameStyleConverter(argument.name).to_snake_case()
v8_value = 'info[{index}]'.format(index=index)
-
- # History.pushState and History.replaceState are explicitly specified as
- # serializing the value for storage. The default is to not serialize for
- # storage. See https://html.spec.whatwg.org/C/#dom-history-pushstate
- if idl_type.name == 'SerializedScriptValue':
- for_storage = (interface_name == 'History' and
- method.name in ('pushState', 'replaceState'))
- return v8_value_to_local_cpp_ssv_value(extended_attributes, idl_type,
- v8_value, name,
- for_storage=for_storage)
+ for_constructor_callback = method.name == 'Constructor'
if argument.is_variadic:
- return v8_value_to_local_cpp_variadic_value(argument, index)
- return idl_type.v8_value_to_local_cpp_value(extended_attributes, v8_value,
- name, declare_variable=False,
- use_exception_state=method.returns_promise)
+ return v8_value_to_local_cpp_variadic_value(
+ argument, index, for_constructor_callback=for_constructor_callback)
+ return idl_type.v8_value_to_local_cpp_value(
+ extended_attributes,
+ v8_value,
+ name,
+ declare_variable=False,
+ use_exception_state=method.returns_promise,
+ for_constructor_callback=for_constructor_callback)
################################################################################
# Auxiliary functions
################################################################################
+
# [NotEnumerable], [Unforgeable]
def property_attributes(interface, method):
extended_attributes = method.extended_attributes
@@ -481,7 +568,8 @@ def argument_set_default_value(argument):
raise Exception('invalid default value for dictionary type')
if idl_type.is_array_or_sequence_type:
if default_value.value != '[]':
- raise Exception('invalid default value for sequence type: %s' % default_value.value)
+ raise Exception('invalid default value for sequence type: %s' %
+ default_value.value)
# Nothing to do when we set an empty sequence as default value, but we
# need to return non-empty value so that we don't generate method calls
# without this argument.
@@ -489,11 +577,14 @@ def argument_set_default_value(argument):
if idl_type.is_union_type:
if argument.default_value.is_null:
if not idl_type.includes_nullable_type:
- raise Exception('invalid default value for union type: null for %s'
- % idl_type.name)
+ raise Exception(
+ 'invalid default value for union type: null for %s' %
+ idl_type.name)
# Union container objects are "null" initially.
return '/* null default value */'
- if isinstance(default_value.value, basestring):
+ if default_value.value == "{}":
+ member_type = idl_type.dictionary_member_type
+ elif isinstance(default_value.value, basestring):
member_type = idl_type.string_member_type
elif isinstance(default_value.value, (int, float)):
member_type = idl_type.numeric_member_type
@@ -502,27 +593,28 @@ def argument_set_default_value(argument):
else:
member_type = None
if member_type is None:
- raise Exception('invalid default value for union type: %r for %s'
- % (default_value.value, idl_type.name))
+ raise Exception('invalid default value for union type: %r for %s' %
+ (default_value.value, idl_type.name))
member_type_name = (member_type.inner_type.name
- if member_type.is_nullable else
- member_type.name)
+ if member_type.is_nullable else member_type.name)
return '%s.Set%s(%s)' % (variable_name, member_type_name,
member_type.literal_cpp_value(default_value))
return '%s = %s' % (variable_name,
idl_type.literal_cpp_value(default_value))
+
IdlArgument.set_default_value = property(argument_set_default_value)
def method_returns_promise(method):
return method.idl_type and method.idl_type.name == 'Promise'
+
IdlOperation.returns_promise = property(method_returns_promise)
def argument_conversion_needs_exception_state(method, argument):
idl_type = argument.idl_type
- return (idl_type.v8_conversion_needs_exception_state or
- argument.is_variadic or
- (method.returns_promise and idl_type.is_string_type))
+ return (idl_type.v8_conversion_needs_exception_state
+ or argument.is_variadic
+ or (method.returns_promise and idl_type.is_string_type))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
index 5b7aae6f0fd..a2007d860b9 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
@@ -27,7 +27,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pylint: disable=relative-import
-
"""Functions for type handling and type conversion (Blink/C++ <-> V8/JS).
Extends IdlType and IdlUnionType with V8-specific properties, methods, and
@@ -41,6 +40,7 @@ Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
import posixpath
+from idl_types import IdlAnnotatedType
from idl_types import IdlArrayOrSequenceType
from idl_types import IdlNullableType
from idl_types import IdlRecordType
@@ -52,16 +52,13 @@ import v8_attributes # for IdlType.constructor_type_name
from v8_globals import includes
from v8_utilities import binding_header_filename, extended_attribute_value_contains
-
################################################################################
# V8-specific handling of IDL types
################################################################################
NON_WRAPPER_TYPES = frozenset([
- 'Dictionary',
'EventHandler',
'NodeFilter',
- 'SerializedScriptValue',
])
TYPED_ARRAY_TYPES = frozenset([
'Float32Array',
@@ -76,15 +73,15 @@ TYPED_ARRAY_TYPES = frozenset([
'BigInt64Array',
'BigUint64Array',
])
-ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES = TYPED_ARRAY_TYPES.union(frozenset([
- 'ArrayBufferView'
-]))
-ARRAY_BUFFER_AND_VIEW_TYPES = TYPED_ARRAY_TYPES.union(frozenset([
- 'ArrayBuffer',
- 'ArrayBufferView',
- 'DataView',
- 'SharedArrayBuffer',
-]))
+ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES = TYPED_ARRAY_TYPES.union(
+ frozenset(['ArrayBufferView']))
+ARRAY_BUFFER_AND_VIEW_TYPES = TYPED_ARRAY_TYPES.union(
+ frozenset([
+ 'ArrayBuffer',
+ 'ArrayBufferView',
+ 'DataView',
+ 'SharedArrayBuffer',
+ ]))
# We have an unfortunate hack that treats types whose name ends with
# 'Constructor' as aliases to IDL interface object. This white list is used to
# disable the hack.
@@ -105,10 +102,8 @@ IdlType.is_typed_array = property(
lambda self: self.base_type in TYPED_ARRAY_TYPES)
IdlType.is_wrapper_type = property(
- lambda self: (self.is_interface_type and
- not self.is_callback_interface and
- self.base_type not in NON_WRAPPER_TYPES))
-
+ lambda self: (self.is_interface_type and not self.is_callback_interface and self.base_type not in NON_WRAPPER_TYPES)
+)
################################################################################
# C++ types
@@ -129,13 +124,13 @@ CPP_INTEGER_CONVERSION_RULES = {
'unsigned long long': 'uint64_t',
}
CPP_SPECIAL_CONVERSION_RULES = {
- 'Dictionary': 'Dictionary',
'EventHandler': 'EventListener*',
'Promise': 'ScriptPromise',
'ScriptValue': 'ScriptValue',
# FIXME: Eliminate custom bindings for XPathNSResolver http://crbug.com/345529
'XPathNSResolver': 'XPathNSResolver*',
'boolean': 'bool',
+ 'object': 'ScriptValue',
'unrestricted double': 'double',
'unrestricted float': 'float',
}
@@ -154,11 +149,18 @@ def string_resource_mode(idl_type):
treat_null_as = idl_type.extended_attributes.get('TreatNullAs')
if treat_null_as == 'EmptyString':
return 'kTreatNullAsEmptyString'
- raise ValueError('Unknown value for [TreatNullAs]: %s' % treat_null_as)
+ elif treat_null_as:
+ raise ValueError(
+ 'Unknown value for [TreatNullAs]: %s' % treat_null_as)
return ''
-def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_type=False, used_as_variadic_argument=False, used_in_cpp_sequence=False):
+def cpp_type(idl_type,
+ extended_attributes=None,
+ raw_type=False,
+ used_as_rvalue_type=False,
+ used_as_variadic_argument=False,
+ used_in_cpp_sequence=False):
"""Returns C++ type corresponding to IDL type.
|idl_type| argument is of type IdlType, while return value is a string
@@ -198,9 +200,12 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
# integrated null state that can be distinguished from a present but
# empty dictionary. It's unclear whether this will ever come up in
# real spec WebIDL.
- raise NotImplementedError('Sequences of nullable dictionary, sequence or record types are not yet supported.')
+ raise NotImplementedError(
+ 'Sequences of nullable dictionary, sequence or record types are not yet supported.'
+ )
return 'base::Optional<%s>' % inner_type.cpp_type_args(
- extended_attributes, raw_type, used_as_rvalue_type, used_as_variadic_argument, used_in_cpp_sequence)
+ extended_attributes, raw_type, used_as_rvalue_type,
+ used_as_variadic_argument, used_in_cpp_sequence)
# Array or sequence types
if used_as_variadic_argument:
@@ -208,18 +213,23 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
else:
native_array_element_type = idl_type.native_array_element_type
if native_array_element_type:
- vector_type = cpp_ptr_type('Vector', 'HeapVector', native_array_element_type.is_traceable)
- vector_template_type = cpp_template_type(vector_type, native_array_element_type.cpp_type_args(used_in_cpp_sequence=True))
+ vector_type = cpp_ptr_type('Vector', 'HeapVector',
+ native_array_element_type.is_traceable)
+ vector_template_type = cpp_template_type(
+ vector_type,
+ native_array_element_type.cpp_type_args(used_in_cpp_sequence=True))
if used_as_rvalue_type:
return 'const %s&' % vector_template_type
return vector_template_type
# Record types.
if idl_type.is_record_type:
- vector_type = cpp_ptr_type('Vector', 'HeapVector', idl_type.value_type.is_traceable)
- value_type = idl_type.value_type.cpp_type_args(used_in_cpp_sequence=True)
- vector_template_type = cpp_template_type(vector_type,
- 'std::pair<String, %s>' % value_type)
+ vector_type = cpp_ptr_type('Vector', 'HeapVector',
+ idl_type.value_type.is_traceable)
+ value_type = idl_type.value_type.cpp_type_args(
+ used_in_cpp_sequence=True)
+ vector_template_type = cpp_template_type(
+ vector_type, 'std::pair<String, %s>' % value_type)
if used_as_rvalue_type:
return 'const %s&' % vector_template_type
return vector_template_type
@@ -234,9 +244,9 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
if base_idl_type in CPP_SPECIAL_CONVERSION_RULES:
return CPP_SPECIAL_CONVERSION_RULES[base_idl_type]
- if base_idl_type == 'SerializedScriptValue':
- return 'scoped_refptr<%s>' % base_idl_type
if idl_type.is_string_type:
+ if idl_type.has_string_context:
+ return 'String'
if not raw_type:
return 'const String&' if used_as_rvalue_type else 'String'
return 'V8StringResource<%s>' % string_resource_mode(idl_type)
@@ -244,13 +254,12 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
if base_idl_type == 'ArrayBufferView' and 'FlexibleArrayBufferView' in extended_attributes:
return 'FlexibleArrayBufferView'
if base_idl_type in TYPED_ARRAY_TYPES and 'FlexibleArrayBufferView' in extended_attributes:
- return 'Flexible' + base_idl_type + 'View'
- if base_idl_type in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
- if not used_in_cpp_sequence:
- if 'AllowShared' in extended_attributes:
- return cpp_template_type('MaybeShared', idl_type.implemented_as)
- else:
- return cpp_template_type('NotShared', idl_type.implemented_as)
+ return 'Flexible' + base_idl_type
+ if base_idl_type in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES or base_idl_type == 'DataView':
+ if 'AllowShared' in extended_attributes:
+ return cpp_template_type('MaybeShared', idl_type.implemented_as)
+ else:
+ return cpp_template_type('NotShared', idl_type.implemented_as)
if idl_type.is_interface_type or idl_type.is_dictionary:
implemented_as_class = idl_type.implemented_as
if raw_type or not used_in_cpp_sequence:
@@ -267,8 +276,9 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
if idl_type.is_nullable:
return idl_type.inner_type.name
return idl_type.name
- idl_type_name = 'Or'.join(member_cpp_name(member)
- for member in idl_type.member_types)
+
+ idl_type_name = 'Or'.join(
+ member_cpp_name(member) for member in idl_type.member_types)
return 'const %s&' % idl_type_name if used_as_rvalue_type else idl_type_name
if idl_type.is_callback_function:
v8_type_name = 'V8' + base_idl_type
@@ -295,15 +305,16 @@ def cpp_type_initializer(idl_type):
if idl_type.native_array_element_type:
return ''
+ if idl_type.is_explicit_nullable:
+ return ''
if idl_type.is_numeric_type:
return ' = 0'
if base_idl_type == 'boolean':
return ' = false'
- if (base_idl_type in NON_WRAPPER_TYPES or
- base_idl_type in CPP_SPECIAL_CONVERSION_RULES or
- base_idl_type == 'any' or
- idl_type.is_string_type or
- idl_type.is_enum):
+ if (base_idl_type in NON_WRAPPER_TYPES
+ or base_idl_type in CPP_SPECIAL_CONVERSION_RULES
+ or base_idl_type == 'any' or idl_type.is_string_type
+ or idl_type.is_enum):
return ''
return ' = nullptr'
@@ -314,7 +325,6 @@ IdlTypeBase.cpp_type_initializer = property(cpp_type_initializer)
IdlTypeBase.cpp_type_args = cpp_type
IdlUnionType.cpp_type_initializer = ''
-
IdlArrayOrSequenceType.native_array_element_type = property(
lambda self: self.element_type)
@@ -358,9 +368,9 @@ def implemented_as(idl_type):
IdlType.implemented_as = property(implemented_as)
IdlType.set_implemented_as_interfaces = classmethod(
- lambda cls, new_implemented_as_interfaces:
- cls.implemented_as_interfaces.update(new_implemented_as_interfaces))
-
+ lambda cls, new_implemented_as_interfaces: \
+ cls.implemented_as_interfaces.update(new_implemented_as_interfaces)
+)
# [GarbageCollected]
IdlType.garbage_collected_types = set()
@@ -369,8 +379,9 @@ IdlType.is_garbage_collected = property(
lambda self: self.base_type in IdlType.garbage_collected_types)
IdlType.set_garbage_collected_types = classmethod(
- lambda cls, new_garbage_collected_types:
- cls.garbage_collected_types.update(new_garbage_collected_types))
+ lambda cls, new_garbage_collected_types: \
+ cls.garbage_collected_types.update(new_garbage_collected_types)
+)
def is_gc_type(idl_type):
@@ -381,7 +392,9 @@ IdlTypeBase.is_gc_type = property(is_gc_type)
def is_traceable(idl_type):
- return idl_type.is_garbage_collected or idl_type.is_callback_function or idl_type.cpp_type in ('ScriptValue', 'ScriptPromise')
+ return (idl_type.is_garbage_collected or idl_type.is_callback_function
+ or idl_type.cpp_type in ('ScriptValue', 'ScriptPromise'))
+
IdlTypeBase.is_traceable = property(is_traceable)
IdlUnionType.is_traceable = property(lambda self: True)
@@ -392,34 +405,39 @@ IdlRecordType.is_traceable = property(
IdlNullableType.is_traceable = property(
lambda self: self.inner_type.is_traceable)
-
################################################################################
# Includes
################################################################################
INCLUDES_FOR_TYPE = {
- 'object': set(),
- 'ArrayBufferView': set(['bindings/core/v8/v8_array_buffer_view.h',
- 'core/typed_arrays/array_buffer_view_helpers.h',
- 'core/typed_arrays/flexible_array_buffer_view.h']),
- 'Dictionary': set(['bindings/core/v8/dictionary.h']),
- 'EventHandler': set(['bindings/core/v8/js_event_handler.h']),
- 'HTMLCollection': set(['bindings/core/v8/v8_html_collection.h',
- 'core/dom/class_collection.h',
- 'core/dom/tag_collection.h',
- 'core/html/html_collection.h',
- 'core/html/html_table_rows_collection.h',
- 'core/html/forms/html_data_list_options_collection.h',
- 'core/html/forms/html_form_controls_collection.h']),
- 'NodeList': set(['bindings/core/v8/v8_node_list.h',
- 'core/dom/name_node_list.h',
- 'core/dom/node_list.h',
- 'core/dom/static_node_list.h',
- 'core/html/forms/labels_node_list.h']),
- 'Promise': set(['bindings/core/v8/script_promise.h']),
- 'SerializedScriptValue': set(['bindings/core/v8/serialization/serialized_script_value.h',
- 'bindings/core/v8/serialization/serialized_script_value_factory.h']),
- 'ScriptValue': set(['bindings/core/v8/script_value.h']),
+ 'object':
+ set(['bindings/core/v8/script_value.h']),
+ 'ArrayBufferView':
+ set([
+ 'bindings/core/v8/v8_array_buffer_view.h',
+ 'core/typed_arrays/array_buffer_view_helpers.h',
+ 'core/typed_arrays/flexible_array_buffer_view.h'
+ ]),
+ 'EventHandler':
+ set(['bindings/core/v8/js_event_handler.h']),
+ 'HTMLCollection':
+ set([
+ 'bindings/core/v8/v8_html_collection.h', 'core/dom/class_collection.h',
+ 'core/dom/tag_collection.h', 'core/html/html_collection.h',
+ 'core/html/html_table_rows_collection.h',
+ 'core/html/forms/html_data_list_options_collection.h',
+ 'core/html/forms/html_form_controls_collection.h'
+ ]),
+ 'NodeList':
+ set([
+ 'bindings/core/v8/v8_node_list.h', 'core/dom/name_node_list.h',
+ 'core/dom/node_list.h', 'core/dom/static_node_list.h',
+ 'core/html/forms/labels_node_list.h'
+ ]),
+ 'Promise':
+ set(['bindings/core/v8/script_promise.h']),
+ 'ScriptValue':
+ set(['bindings/core/v8/script_value.h']),
}
@@ -433,11 +451,15 @@ def includes_for_type(idl_type, extended_attributes=None):
return INCLUDES_FOR_TYPE[base_idl_type]
if base_idl_type in TYPED_ARRAY_TYPES:
return INCLUDES_FOR_TYPE['ArrayBufferView'].union(
- set(['bindings/%s/v8/%s' % (component_dir[base_idl_type], binding_header_filename(base_idl_type))])
- )
+ set([
+ 'bindings/%s/v8/%s' % (component_dir[base_idl_type],
+ binding_header_filename(base_idl_type))
+ ]))
if idl_type.is_basic_type:
- return set(['bindings/core/v8/idl_types.h',
- 'bindings/core/v8/native_value_traits_impl.h'])
+ return set([
+ 'bindings/core/v8/idl_types.h',
+ 'bindings/core/v8/native_value_traits_impl.h'
+ ])
if base_idl_type.endswith('ConstructorConstructor'):
# FIXME: rename to NamedConstructor
# FIXME: replace with a [NamedConstructorAttribute] extended attribute
@@ -445,41 +467,55 @@ def includes_for_type(idl_type, extended_attributes=None):
# and these do not have header files, as they are part of the generated
# bindings for the interface
return set()
- if (base_idl_type.endswith('Constructor') and
- base_idl_type not in _CALLBACK_CONSTRUCTORS):
+ if (base_idl_type.endswith('Constructor')
+ and base_idl_type not in _CALLBACK_CONSTRUCTORS):
# FIXME: replace with a [ConstructorAttribute] extended attribute
base_idl_type = idl_type.constructor_type_name
if idl_type.is_custom_callback_function:
return set()
if idl_type.is_callback_function:
component = IdlType.callback_functions[base_idl_type]['component_dir']
- return set(['bindings/%s/v8/%s' % (component, binding_header_filename(base_idl_type))])
+ return set([
+ 'bindings/%s/v8/%s' % (component,
+ binding_header_filename(base_idl_type))
+ ])
if base_idl_type not in component_dir:
return set()
- return set(['bindings/%s/v8/%s' % (component_dir[base_idl_type],
- binding_header_filename(base_idl_type))])
+ return set([
+ 'bindings/%s/v8/%s' % (component_dir[base_idl_type],
+ binding_header_filename(base_idl_type))
+ ])
+
IdlType.includes_for_type = includes_for_type
def includes_for_union_type(idl_type, extended_attributes=None):
- return set.union(*[member_type.includes_for_type(extended_attributes)
- for member_type in idl_type.member_types])
+ return set.union(*[
+ member_type.includes_for_type(extended_attributes)
+ for member_type in idl_type.member_types
+ ])
+
IdlUnionType.includes_for_type = includes_for_union_type
def includes_for_array_or_sequence_type(idl_type, extended_attributes=None):
- return set.union(set(['bindings/core/v8/idl_types.h',
- 'bindings/core/v8/native_value_traits_impl.h']),
- idl_type.element_type.includes_for_type(extended_attributes))
+ return set.union(
+ set([
+ 'bindings/core/v8/idl_types.h',
+ 'bindings/core/v8/native_value_traits_impl.h'
+ ]), idl_type.element_type.includes_for_type(extended_attributes))
+
IdlArrayOrSequenceType.includes_for_type = includes_for_array_or_sequence_type
def includes_for_record_type(idl_type, extended_attributes=None):
- return set.union(idl_type.key_type.includes_for_type(extended_attributes),
- idl_type.value_type.includes_for_type(extended_attributes))
+ return set.union(
+ idl_type.key_type.includes_for_type(extended_attributes),
+ idl_type.value_type.includes_for_type(extended_attributes))
+
IdlRecordType.includes_for_type = includes_for_record_type
@@ -487,6 +523,7 @@ IdlRecordType.includes_for_type = includes_for_record_type
def add_includes_for_type(idl_type, extended_attributes=None):
includes.update(idl_type.includes_for_type(extended_attributes))
+
IdlTypeBase.add_includes_for_type = add_includes_for_type
@@ -504,8 +541,8 @@ def impl_includes_for_type(idl_type, interfaces_info):
idl_type = idl_type.preprocessed_type
native_array_element_type = idl_type.native_array_element_type
if native_array_element_type:
- includes_for_type.update(impl_includes_for_type(
- native_array_element_type, interfaces_info))
+ includes_for_type.update(
+ impl_includes_for_type(native_array_element_type, interfaces_info))
includes_for_type.add('platform/wtf/vector.h')
base_idl_type = idl_type.base_type
@@ -513,24 +550,31 @@ def impl_includes_for_type(idl_type, interfaces_info):
includes_for_type.add('platform/wtf/text/wtf_string.h')
if idl_type.is_callback_function:
component = IdlType.callback_functions[base_idl_type]['component_dir']
- return set(['bindings/%s/v8/%s' % (component, binding_header_filename(base_idl_type))])
+ return set([
+ 'bindings/%s/v8/%s' % (component,
+ binding_header_filename(base_idl_type))
+ ])
if base_idl_type in interfaces_info:
interface_info = interfaces_info[base_idl_type]
includes_for_type.add(interface_info['include_path'])
if base_idl_type in INCLUDES_FOR_TYPE:
includes_for_type.update(INCLUDES_FOR_TYPE[base_idl_type])
if idl_type.is_array_buffer_view_or_typed_array:
- return set(['core/typed_arrays/dom_typed_array.h',
- 'core/typed_arrays/array_buffer_view_helpers.h'])
+ return set([
+ 'core/typed_arrays/dom_typed_array.h',
+ 'core/typed_arrays/array_buffer_view_helpers.h'
+ ])
return includes_for_type
def impl_includes_for_type_union(idl_type, interfaces_info):
includes_for_type = set()
for member_type in idl_type.member_types:
- includes_for_type.update(member_type.impl_includes_for_type(interfaces_info))
+ includes_for_type.update(
+ member_type.impl_includes_for_type(interfaces_info))
return includes_for_type
+
IdlTypeBase.impl_includes_for_type = impl_includes_for_type
IdlUnionType.impl_includes_for_type = impl_includes_for_type_union
@@ -549,7 +593,6 @@ def impl_forward_declaration_name(idl_type):
IdlTypeBase.impl_forward_declaration_name = property(
impl_forward_declaration_name)
-
component_dir = {}
@@ -566,49 +609,55 @@ def set_component_dirs(new_component_dirs):
# to introduce any performance regressions.
V8_VALUE_TO_CPP_VALUE = {
# Basic
- 'DOMString': '{v8_value}',
+ 'DOMString':
+ '{v8_value}',
# Interface types
- 'FlexibleArrayBufferView': 'ToFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name}, allocateFlexibleArrayBufferViewStorage({v8_value}))',
- 'Promise': 'ScriptPromise::Cast(ScriptState::Current({isolate}), {v8_value})',
- 'ScriptValue': 'ScriptValue({isolate}, {v8_value})',
- 'Window': 'ToDOMWindow({isolate}, {v8_value})',
- 'XPathNSResolver': 'ToXPathNSResolver(ScriptState::Current({isolate}), {v8_value})',
+ 'FlexibleArrayBufferView':
+ 'ToFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name})',
+ 'Promise':
+ 'ScriptPromise::Cast(ScriptState::Current({isolate}), {v8_value})',
+ 'ScriptValue':
+ 'ScriptValue({isolate}, {v8_value})',
+ 'Window':
+ 'ToDOMWindow({isolate}, {v8_value})',
+ 'XPathNSResolver':
+ 'ToXPathNSResolver(ScriptState::Current({isolate}), {v8_value})',
}
def v8_conversion_needs_exception_state(idl_type):
- return (idl_type.is_numeric_type or
- idl_type.is_enum or
- idl_type.is_dictionary or
- idl_type.is_array_buffer_view_or_typed_array or
- idl_type.name in ('Boolean', 'ByteString', 'Dictionary', 'USVString', 'SerializedScriptValue'))
+ return (idl_type.is_numeric_type or idl_type.is_enum
+ or idl_type.is_dictionary
+ or idl_type.is_array_buffer_view_or_typed_array
+ or idl_type.has_string_context or
+ idl_type.name in ('Boolean', 'ByteString', 'Object', 'USVString'))
+
-IdlType.v8_conversion_needs_exception_state = property(v8_conversion_needs_exception_state)
+IdlType.v8_conversion_needs_exception_state = property(
+ v8_conversion_needs_exception_state)
+IdlAnnotatedType.v8_conversion_needs_exception_state = property(
+ v8_conversion_needs_exception_state)
IdlArrayOrSequenceType.v8_conversion_needs_exception_state = True
IdlRecordType.v8_conversion_needs_exception_state = True
IdlUnionType.v8_conversion_needs_exception_state = True
-
-TRIVIAL_CONVERSIONS = frozenset([
- 'any',
- 'boolean',
- 'Dictionary',
- 'NodeFilter',
- 'XPathNSResolver',
- 'Promise'
-])
+TRIVIAL_CONVERSIONS = frozenset(
+ ['any', 'boolean', 'NodeFilter', 'XPathNSResolver', 'Promise'])
def v8_conversion_is_trivial(idl_type):
# The conversion is a simple expression that returns the converted value and
# cannot raise an exception.
- return (idl_type.base_type in TRIVIAL_CONVERSIONS or
- idl_type.is_wrapper_type)
+ return (idl_type.base_type in TRIVIAL_CONVERSIONS
+ or idl_type.is_wrapper_type)
+
IdlType.v8_conversion_is_trivial = property(v8_conversion_is_trivial)
-def native_value_traits_type_name(idl_type, extended_attributes, in_sequence_or_record=False):
+def native_value_traits_type_name(idl_type,
+ extended_attributes,
+ in_sequence_or_record=False):
idl_type = idl_type.preprocessed_type
if idl_type.is_string_type:
@@ -617,24 +666,25 @@ def native_value_traits_type_name(idl_type, extended_attributes, in_sequence_or_
# attribute and nullable string types.
name = 'IDL%s' % idl_type.name
elif idl_type.is_nullable:
- inner_type = native_value_traits_type_name(idl_type.inner_type, extended_attributes)
- # IDLNullable is only required for sequences and such.
- # The IDL compiler already has special cases for nullable operation
+ inner_type = idl_type.inner_type
+ inner_type_nvt_type = native_value_traits_type_name(
+ inner_type, extended_attributes)
+ # The IDL compiler has special cases to handle some nullable types in operation
# parameters, dictionary fields, etc.
- if in_sequence_or_record:
- name = 'IDLNullable<%s>' % native_value_traits_type_name(idl_type.inner_type,
- extended_attributes)
+ if in_sequence_or_record or inner_type.name == 'Object':
+ name = 'IDLNullable<%s>' % inner_type_nvt_type
else:
- name = inner_type
+ name = inner_type_nvt_type
elif idl_type.native_array_element_type:
- name = 'IDLSequence<%s>' % native_value_traits_type_name(idl_type.native_array_element_type,
- extended_attributes, True)
+ name = 'IDLSequence<%s>' % native_value_traits_type_name(
+ idl_type.native_array_element_type, extended_attributes, True)
elif idl_type.is_record_type:
- name = 'IDLRecord<%s, %s>' % (native_value_traits_type_name(idl_type.key_type,
- extended_attributes),
- native_value_traits_type_name(idl_type.value_type,
- extended_attributes, True))
- elif idl_type.is_basic_type or idl_type.name == 'Promise':
+ name = 'IDLRecord<%s, %s>' % (native_value_traits_type_name(
+ idl_type.key_type, extended_attributes),
+ native_value_traits_type_name(
+ idl_type.value_type,
+ extended_attributes, True))
+ elif idl_type.is_basic_type or idl_type.name in ['Object', 'Promise']:
name = 'IDL%s' % idl_type.name
elif idl_type.implemented_as is not None:
name = idl_type.implemented_as
@@ -643,7 +693,8 @@ def native_value_traits_type_name(idl_type, extended_attributes, in_sequence_or_
return name
-def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name, isolate):
+def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value,
+ variable_name, isolate, for_constructor_callback):
if idl_type.name == 'void':
return ''
@@ -653,45 +704,58 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name
if 'FlexibleArrayBufferView' in extended_attributes:
if base_idl_type not in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
- raise ValueError('Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s' % (idl_type.base_type))
+ raise ValueError(
+ 'Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s'
+ % (idl_type.base_type))
if 'AllowShared' not in extended_attributes:
- raise ValueError('"FlexibleArrayBufferView" extended attribute requires "AllowShared" on %s' % (idl_type.base_type))
+ raise ValueError(
+ '"FlexibleArrayBufferView" extended attribute requires "AllowShared" on %s'
+ % (idl_type.base_type))
base_idl_type = 'FlexibleArrayBufferView'
if 'AllowShared' in extended_attributes and not idl_type.is_array_buffer_view_or_typed_array:
- raise ValueError('Unrecognized base type for extended attribute "AllowShared": %s' % (idl_type.base_type))
+ raise ValueError(
+ 'Unrecognized base type for extended attribute "AllowShared": %s' %
+ (idl_type.base_type))
if idl_type.is_integer_type:
arguments = ', '.join([v8_value, 'exception_state'])
- elif base_idl_type == 'SerializedScriptValue':
- arguments = ', '.join([
- v8_value,
- 'SerializedScriptValue::SerializeOptions(SerializedScriptValue::kNotForStorage)',
- 'exception_state'])
elif idl_type.v8_conversion_needs_exception_state:
arguments = ', '.join([v8_value, 'exception_state'])
else:
arguments = v8_value
- if base_idl_type in V8_VALUE_TO_CPP_VALUE:
+ if idl_type.has_string_context:
+ execution_context = 'bindings::ExecutionContextFromV8Wrappable(impl)'
+ if for_constructor_callback:
+ execution_context = 'CurrentExecutionContext(info.GetIsolate())'
+ cpp_expression_format = 'NativeValueTraits<IDL%s>::NativeValue(%s, %s, exception_state, %s)' % (
+ idl_type.name, isolate, v8_value, execution_context)
+ elif base_idl_type in V8_VALUE_TO_CPP_VALUE:
cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type]
elif idl_type.name == 'ArrayBuffer':
cpp_expression_format = (
'{v8_value}->Is{idl_type}() ? '
- 'V8{idl_type}::ToImpl(v8::Local<v8::{idl_type}>::Cast({v8_value})) : 0')
- elif idl_type.is_array_buffer_view_or_typed_array:
- this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes)
+ 'V8{idl_type}::ToImpl(v8::Local<v8::{idl_type}>::Cast({v8_value})) : 0'
+ )
+ elif idl_type.is_array_buffer_view_or_typed_array or base_idl_type == 'DataView':
+ this_cpp_type = idl_type.cpp_type_args(
+ extended_attributes=extended_attributes)
if 'AllowShared' in extended_attributes:
- cpp_expression_format = ('ToMaybeShared<%s>({isolate}, {v8_value}, exception_state)' % this_cpp_type)
+ cpp_expression_format = (
+ 'ToMaybeShared<%s>({isolate}, {v8_value}, exception_state)' %
+ this_cpp_type)
else:
- cpp_expression_format = ('ToNotShared<%s>({isolate}, {v8_value}, exception_state)' % this_cpp_type)
-
+ cpp_expression_format = (
+ 'ToNotShared<%s>({isolate}, {v8_value}, exception_state)' %
+ this_cpp_type)
elif idl_type.is_union_type:
nullable = 'UnionTypeConversionMode::kNullable' if idl_type.includes_nullable_type \
else 'UnionTypeConversionMode::kNotNullable'
# We need to consider the moving of the null through the union in order
# to generate the correct V8* class name.
- this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes)
+ this_cpp_type = idl_type.cpp_type_args(
+ extended_attributes=extended_attributes)
cpp_expression_format = '%s::ToImpl({isolate}, {v8_value}, {variable_name}, %s, exception_state)' % \
(v8_type(this_cpp_type), nullable)
elif idl_type.use_output_parameter_for_result:
@@ -701,26 +765,47 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name
elif idl_type.v8_conversion_needs_exception_state:
# Effectively, this if branch means everything with v8_conversion_needs_exception_state == True
# except for unions and dictionary interfaces.
- base_idl_type = native_value_traits_type_name(idl_type, extended_attributes)
+ base_idl_type = native_value_traits_type_name(idl_type,
+ extended_attributes)
cpp_expression_format = (
- 'NativeValueTraits<{idl_type}>::NativeValue({isolate}, {arguments})')
+ 'NativeValueTraits<{idl_type}>::NativeValue({isolate}, {arguments})'
+ )
else:
cpp_expression_format = (
'V8{idl_type}::ToImplWithTypeCheck({isolate}, {v8_value})')
- return cpp_expression_format.format(arguments=arguments, idl_type=base_idl_type, v8_value=v8_value, variable_name=variable_name, isolate=isolate)
+ return cpp_expression_format.format(
+ arguments=arguments,
+ idl_type=base_idl_type,
+ v8_value=v8_value,
+ variable_name=variable_name,
+ isolate=isolate)
# FIXME: this function should be refactored, as this takes too many flags.
-def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, declare_variable=True,
- isolate='info.GetIsolate()', bailout_return_value=None, use_exception_state=False,
- code_generation_target=None):
+def v8_value_to_local_cpp_value(idl_type,
+ extended_attributes,
+ v8_value,
+ variable_name,
+ declare_variable=True,
+ isolate='info.GetIsolate()',
+ bailout_return_value=None,
+ use_exception_state=False,
+ code_generation_target=None,
+ for_constructor_callback=False):
"""Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
- this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True)
+ this_cpp_type = idl_type.cpp_type_args(
+ extended_attributes=extended_attributes, raw_type=True)
idl_type = idl_type.preprocessed_type
- cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name, isolate)
+ cpp_value = v8_value_to_cpp_value(
+ idl_type,
+ extended_attributes,
+ v8_value,
+ variable_name,
+ isolate,
+ for_constructor_callback=for_constructor_callback)
# Optional expression that returns a value to be assigned to the local variable.
assign_expression = None
@@ -734,7 +819,9 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl
if 'FlexibleArrayBufferView' in extended_attributes:
if idl_type.base_type not in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
- raise ValueError('Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s' % (idl_type.base_type))
+ raise ValueError(
+ 'Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s'
+ % (idl_type.base_type))
set_expression = cpp_value
elif idl_type.is_string_type or idl_type.v8_conversion_needs_exception_state:
# Types for which conversion can fail and that need error handling.
@@ -756,7 +843,8 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl
check_expression = '!%s.Prepare()' % variable_name
elif not idl_type.v8_conversion_is_trivial and not idl_type.is_callback_function:
return {
- 'error_message': 'no V8 -> C++ conversion for IDL type: %s' % idl_type.name
+ 'error_message':
+ 'no V8 -> C++ conversion for IDL type: %s' % idl_type.name
}
else:
assign_expression = cpp_value
@@ -766,10 +854,12 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl
if (idl_type.is_explicit_nullable
and code_generation_target == 'attribute_set'):
- assign_expression = (
- "is_null "
- "? {cpp_type}() "
- ": {expr}".format(cpp_type=this_cpp_type, expr=assign_expression))
+ this_cpp_type = cpp_template_type('base::Optional', this_cpp_type)
+ expr = '{cpp_type}({expr})'.format(
+ cpp_type=this_cpp_type, expr=assign_expression)
+ assign_expression = ("is_null "
+ "? base::nullopt "
+ ": {expr}".format(expr=expr))
return {
'assign_expression': assign_expression,
@@ -791,25 +881,28 @@ def use_output_parameter_for_result(idl_type):
"""
return idl_type.is_union_type
-IdlTypeBase.use_output_parameter_for_result = property(use_output_parameter_for_result)
+IdlTypeBase.use_output_parameter_for_result = property(
+ use_output_parameter_for_result)
################################################################################
# C++ -> V8
################################################################################
+
def preprocess_idl_type(idl_type):
if idl_type.is_nullable:
return IdlNullableType(idl_type.inner_type.preprocessed_type)
if idl_type.is_enum:
# Enumerations are internally DOMStrings
return IdlType('DOMString')
- if idl_type.base_type in ['any', 'object'] or idl_type.is_custom_callback_function:
+ if idl_type.base_type == 'any' or idl_type.is_custom_callback_function:
return IdlType('ScriptValue')
if idl_type.is_callback_function:
return idl_type
return idl_type
+
IdlTypeBase.preprocessed_type = property(preprocess_idl_type)
@@ -830,8 +923,8 @@ def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes):
# [0, 2^31). When a value isn't in this range, a default value (or 0)
# should be returned instead.
extended_attributes = extended_attributes or {}
- if ('Reflect' in extended_attributes and
- idl_type.base_type in ['unsigned long', 'unsigned short']):
+ if ('Reflect' in extended_attributes
+ and idl_type.base_type in ['unsigned long', 'unsigned short']):
cpp_value = cpp_value.replace('GetUnsignedIntegralAttribute',
'GetIntegralAttribute')
cpp_value = 'std::max(0, static_cast<int>(%s))' % cpp_value
@@ -873,11 +966,10 @@ def v8_conversion_type(idl_type, extended_attributes):
if idl_type.is_nullable:
return 'StringOrNull'
return base_idl_type
- if idl_type.is_basic_type or base_idl_type == 'ScriptValue':
+ if idl_type.is_basic_type:
return base_idl_type
- # Generic dictionary type
- if base_idl_type == 'Dictionary':
- return 'Dictionary'
+ if base_idl_type in ['object', 'ScriptValue']:
+ return 'ScriptValue'
# Data type with potential additional includes
if base_idl_type in V8_SET_RETURN_VALUE: # Special V8SetReturnValue treatment
@@ -886,44 +978,68 @@ def v8_conversion_type(idl_type, extended_attributes):
# Pointer type
return 'DOMWrapper'
-IdlTypeBase.v8_conversion_type = v8_conversion_type
+IdlTypeBase.v8_conversion_type = v8_conversion_type
V8_SET_RETURN_VALUE = {
- 'boolean': 'V8SetReturnValueBool(info, {cpp_value})',
- 'DOMString': 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
- 'ByteString': 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
- 'USVString': 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
- 'StringOrNull': 'V8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
- 'void': '',
+ 'boolean':
+ 'V8SetReturnValueBool(info, {cpp_value})',
+ 'DOMString':
+ 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
+ 'ByteString':
+ 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
+ 'USVString':
+ 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
+ 'StringOrNull':
+ 'V8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
+ 'void':
+ '',
# All the int types below are converted to (u)int32_t in the V8SetReturnValue{Int,Unsigned}() calls.
# The 64-bit int types have already been converted to double when V8_SET_RETURN_VALUE is used, so they are not
# listed here.
- 'int8_t': 'V8SetReturnValueInt(info, {cpp_value})',
- 'int16_t': 'V8SetReturnValueInt(info, {cpp_value})',
- 'int32_t': 'V8SetReturnValueInt(info, {cpp_value})',
- 'uint8_t': 'V8SetReturnValueUnsigned(info, {cpp_value})',
- 'uint16_t': 'V8SetReturnValueUnsigned(info, {cpp_value})',
- 'uint32_t': 'V8SetReturnValueUnsigned(info, {cpp_value})',
+ 'int8_t':
+ 'V8SetReturnValueInt(info, {cpp_value})',
+ 'int16_t':
+ 'V8SetReturnValueInt(info, {cpp_value})',
+ 'int32_t':
+ 'V8SetReturnValueInt(info, {cpp_value})',
+ 'uint8_t':
+ 'V8SetReturnValueUnsigned(info, {cpp_value})',
+ 'uint16_t':
+ 'V8SetReturnValueUnsigned(info, {cpp_value})',
+ 'uint32_t':
+ 'V8SetReturnValueUnsigned(info, {cpp_value})',
# No special V8SetReturnValue* function (set value directly)
- 'float': 'V8SetReturnValue(info, {cpp_value})',
- 'unrestricted float': 'V8SetReturnValue(info, {cpp_value})',
- 'double': 'V8SetReturnValue(info, {cpp_value})',
- 'unrestricted double': 'V8SetReturnValue(info, {cpp_value})',
+ 'float':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'unrestricted float':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'double':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'unrestricted double':
+ 'V8SetReturnValue(info, {cpp_value})',
# No special V8SetReturnValue* function, but instead convert value to V8
# and then use general V8SetReturnValue.
- 'sequence': 'V8SetReturnValue(info, {cpp_value})',
- 'FrozenArray': 'V8SetReturnValue(info, {cpp_value})',
- 'EventHandler': 'V8SetReturnValue(info, {cpp_value})',
- 'NodeFilter': 'V8SetReturnValue(info, {cpp_value})',
- 'ScriptValue': 'V8SetReturnValue(info, {cpp_value})',
- 'SerializedScriptValue': 'V8SetReturnValue(info, {cpp_value})',
+ 'sequence':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'FrozenArray':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'EventHandler':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'NodeFilter':
+ 'V8SetReturnValue(info, {cpp_value})',
+ 'ScriptValue':
+ 'V8SetReturnValue(info, {cpp_value})',
# Records.
- 'Record': 'V8SetReturnValue(info, ToV8({cpp_value}, info.Holder(), info.GetIsolate()))',
+ 'Record':
+ 'V8SetReturnValue(info, ToV8({cpp_value}, info.Holder(), info.GetIsolate()))',
# DOMWrapper
- 'DOMWrapperForMainWorld': 'V8SetReturnValueForMainWorld(info, {cpp_value})',
- 'DOMWrapperFast': 'V8SetReturnValueFast(info, {cpp_value}, {script_wrappable})',
- 'DOMWrapperDefault': 'V8SetReturnValue(info, {cpp_value})',
+ 'DOMWrapperForMainWorld':
+ 'V8SetReturnValueForMainWorld(info, {cpp_value})',
+ 'DOMWrapperFast':
+ 'V8SetReturnValueFast(info, {cpp_value}, {script_wrappable})',
+ 'DOMWrapperDefault':
+ 'V8SetReturnValue(info, {cpp_value})',
# If [CheckSecurity=ReturnValue] is specified, the returned object must be
# wrapped in its own realm, which can be different from the realm of the
# receiver object.
@@ -935,34 +1051,42 @@ V8_SET_RETURN_VALUE = {
# contentWindow(). Note that DOMWindow* has its own realm and there is no
# need to pass |creationContext| in for ToV8(DOMWindow*).
# Window.frameElement is implemented with [Custom].
- 'DOMWrapperAcrossContext': (
- 'V8SetReturnValue(info, ToV8({cpp_value}, ' +
- 'ToV8(impl->contentWindow(), v8::Local<v8::Object>(), ' +
- 'info.GetIsolate()).As<v8::Object>(), info.GetIsolate()))'),
+ 'DOMWrapperAcrossContext':
+ ('V8SetReturnValue(info, ToV8({cpp_value}, ' +
+ 'ToV8(impl->contentWindow(), v8::Local<v8::Object>(), ' +
+ 'info.GetIsolate()).As<v8::Object>(), info.GetIsolate()))'),
# Note that static attributes and operations do not check whether |this| is
# an instance of the interface nor |this|'s creation context is the same as
# the current context. So we must always use the current context as the
# creation context of the DOM wrapper for the return value.
- 'DOMWrapperStatic': 'V8SetReturnValue(info, {cpp_value}, info.GetIsolate()->GetCurrentContext()->Global())',
- # Generic dictionary type
- 'Dictionary': 'V8SetReturnValue(info, {cpp_value})',
- 'DictionaryStatic': '#error not implemented yet',
+ 'DOMWrapperStatic':
+ 'V8SetReturnValue(info, {cpp_value}, info.GetIsolate()->GetCurrentContext()->Global())',
# Nullable dictionaries
- 'NullableDictionary': 'V8SetReturnValue(info, result)',
- 'NullableDictionaryStatic': 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
+ 'NullableDictionary':
+ 'V8SetReturnValue(info, result)',
+ 'NullableDictionaryStatic':
+ 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
# Union types or dictionaries
- 'DictionaryOrUnion': 'V8SetReturnValue(info, result)',
- 'DictionaryOrUnionStatic': 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
+ 'DictionaryOrUnion':
+ 'V8SetReturnValue(info, result)',
+ 'DictionaryOrUnionStatic':
+ 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
}
-def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable='', for_main_world=False, is_static=False):
+def v8_set_return_value(idl_type,
+ cpp_value,
+ extended_attributes=None,
+ script_wrappable='',
+ for_main_world=False,
+ is_static=False):
"""Returns a statement that converts a C++ value to a V8 value and sets it as a return value.
"""
+
def dom_wrapper_conversion_type():
- if ('CheckSecurity' in extended_attributes and
- extended_attribute_value_contains(
+ if ('CheckSecurity' in extended_attributes
+ and extended_attribute_value_contains(
extended_attributes['CheckSecurity'], 'ReturnValue')):
return 'DOMWrapperAcrossContext'
if is_static:
@@ -973,59 +1097,81 @@ def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wr
return 'DOMWrapperForMainWorld'
return 'DOMWrapperFast'
- idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
+ idl_type, cpp_value = preprocess_idl_type_and_value(
+ idl_type, cpp_value, extended_attributes)
this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
# SetReturn-specific overrides
if this_v8_conversion_type in ('EventHandler', 'NodeFilter', 'ScriptValue',
- 'SerializedScriptValue', 'sequence', 'FrozenArray'):
+ 'sequence', 'FrozenArray'):
# Convert value to V8 and then use general V8SetReturnValue
- cpp_value = idl_type.cpp_value_to_v8_value(cpp_value, extended_attributes=extended_attributes)
+ cpp_value = idl_type.cpp_value_to_v8_value(
+ cpp_value, extended_attributes=extended_attributes)
if this_v8_conversion_type == 'DOMWrapper':
this_v8_conversion_type = dom_wrapper_conversion_type()
- if is_static and this_v8_conversion_type in ('Dictionary', 'NullableDictionary', 'DictionaryOrUnion'):
+ if is_static and this_v8_conversion_type in ('NullableDictionary',
+ 'DictionaryOrUnion'):
this_v8_conversion_type += 'Static'
format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type]
- statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable)
+ statement = format_string.format(
+ cpp_value=cpp_value, script_wrappable=script_wrappable)
return statement
IdlTypeBase.v8_set_return_value = v8_set_return_value
-
CPP_VALUE_TO_V8_VALUE = {
# Built-in types
- 'DOMString': 'V8String({isolate}, {cpp_value})',
- 'ByteString': 'V8String({isolate}, {cpp_value})',
- 'USVString': 'V8String({isolate}, {cpp_value})',
- 'boolean': 'v8::Boolean::New({isolate}, {cpp_value})',
+ 'DOMString':
+ 'V8String({isolate}, {cpp_value})',
+ 'ByteString':
+ 'V8String({isolate}, {cpp_value})',
+ 'USVString':
+ 'V8String({isolate}, {cpp_value})',
+ 'boolean':
+ 'v8::Boolean::New({isolate}, {cpp_value})',
# All the int types below are converted to (u)int32_t in the v8::Integer::New*() calls.
# The 64-bit int types have already been converted to double when CPP_VALUE_TO_V8_VALUE is used, so they are not
# listed here.
- 'int8_t': 'v8::Integer::New({isolate}, {cpp_value})',
- 'int16_t': 'v8::Integer::New({isolate}, {cpp_value})',
- 'int32_t': 'v8::Integer::New({isolate}, {cpp_value})',
- 'uint8_t': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
- 'uint16_t': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
- 'uint32_t': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
- 'float': 'v8::Number::New({isolate}, {cpp_value})',
- 'unrestricted float': 'v8::Number::New({isolate}, {cpp_value})',
- 'double': 'v8::Number::New({isolate}, {cpp_value})',
- 'unrestricted double': 'v8::Number::New({isolate}, {cpp_value})',
- 'StringOrNull': ('({cpp_value}.IsNull() ? ' +
- 'v8::Null({isolate}).As<v8::Value>() : ' +
- 'V8String({isolate}, {cpp_value}).As<v8::Value>())'),
+ 'int8_t':
+ 'v8::Integer::New({isolate}, {cpp_value})',
+ 'int16_t':
+ 'v8::Integer::New({isolate}, {cpp_value})',
+ 'int32_t':
+ 'v8::Integer::New({isolate}, {cpp_value})',
+ 'uint8_t':
+ 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
+ 'uint16_t':
+ 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
+ 'uint32_t':
+ 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
+ 'float':
+ 'v8::Number::New({isolate}, {cpp_value})',
+ 'unrestricted float':
+ 'v8::Number::New({isolate}, {cpp_value})',
+ 'double':
+ 'v8::Number::New({isolate}, {cpp_value})',
+ 'unrestricted double':
+ 'v8::Number::New({isolate}, {cpp_value})',
+ 'StringOrNull':
+ ('({cpp_value}.IsNull() ? ' + 'v8::Null({isolate}).As<v8::Value>() : ' +
+ 'V8String({isolate}, {cpp_value}).As<v8::Value>())'),
# Special cases
- 'Dictionary': '{cpp_value}.V8Value()',
- 'EventHandler': 'JSEventHandler::AsV8Value({isolate}, impl, {cpp_value})',
- 'NodeFilter': 'ToV8({cpp_value}, {creation_context}, {isolate})',
- 'Record': 'ToV8({cpp_value}, {creation_context}, {isolate})',
- 'ScriptValue': '{cpp_value}.V8Value()',
- 'SerializedScriptValue': 'V8Deserialize({isolate}, {cpp_value}.get())',
+ 'EventHandler':
+ 'JSEventHandler::AsV8Value({isolate}, impl, {cpp_value})',
+ 'NodeFilter':
+ 'ToV8({cpp_value}, {creation_context}, {isolate})',
+ 'Record':
+ 'ToV8({cpp_value}, {creation_context}, {isolate})',
+ 'ScriptValue':
+ '{cpp_value}.V8Value()',
# General
- 'sequence': 'ToV8({cpp_value}, {creation_context}, {isolate})',
- 'FrozenArray': 'FreezeV8Object(ToV8({cpp_value}, {creation_context}, {isolate}), {isolate})',
- 'DOMWrapper': 'ToV8({cpp_value}, {creation_context}, {isolate})',
+ 'sequence':
+ 'ToV8({cpp_value}, {creation_context}, {isolate})',
+ 'FrozenArray':
+ 'FreezeV8Object(ToV8({cpp_value}, {creation_context}, {isolate}), {isolate})',
+ 'DOMWrapper':
+ 'ToV8({cpp_value}, {creation_context}, {isolate})',
# Passing nullable dictionaries isn't a pattern currently used
# anywhere in the web platform, and more work would be needed in
# the code generator to distinguish between passing null, and
@@ -1036,19 +1182,29 @@ CPP_VALUE_TO_V8_VALUE = {
# nullable dictionary type.
#
# Union types or dictionaries
- 'DictionaryOrUnion': 'ToV8({cpp_value}, {creation_context}, {isolate})',
+ 'DictionaryOrUnion':
+ 'ToV8({cpp_value}, {creation_context}, {isolate})',
}
-def cpp_value_to_v8_value(idl_type, cpp_value, isolate='info.GetIsolate()', creation_context='info.Holder()', extended_attributes=None):
+def cpp_value_to_v8_value(idl_type,
+ cpp_value,
+ isolate='info.GetIsolate()',
+ creation_context='info.Holder()',
+ extended_attributes=None):
"""Returns an expression that converts a C++ value to a V8 value."""
# the isolate parameter is needed for callback interfaces
- idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
+ idl_type, cpp_value = preprocess_idl_type_and_value(
+ idl_type, cpp_value, extended_attributes)
this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type]
- statement = format_string.format(cpp_value=cpp_value, isolate=isolate, creation_context=creation_context)
+ statement = format_string.format(
+ cpp_value=cpp_value,
+ isolate=isolate,
+ creation_context=creation_context)
return statement
+
IdlTypeBase.cpp_value_to_v8_value = cpp_value_to_v8_value
@@ -1096,7 +1252,6 @@ IdlType.literal_cpp_value = literal_cpp_value
IdlUnionType.literal_cpp_value = union_literal_cpp_value
IdlArrayOrSequenceType.literal_cpp_value = array_or_sequence_literal_cpp_value
-
_IDL_TYPE_TO_NATIVE_VALUE_TRAITS_TAG_MAP = {
'DOMString': 'IDLString',
'USVString': 'IDLUSVString',
@@ -1133,15 +1288,13 @@ def cpp_type_has_null_value(idl_type):
# - Interface types and Dictionary types represent null as a null pointer.
# - Union types, as thier container classes can represent null value.
# - 'Object' and 'any' type. We use ScriptValue for object type.
- return (idl_type.is_string_type
- or idl_type.is_enum
- or idl_type.is_interface_type
- or idl_type.is_callback_interface
+ return (idl_type.is_string_type or idl_type.is_enum
+ or idl_type.is_interface_type or idl_type.is_callback_interface
or idl_type.is_callback_function
- or idl_type.is_custom_callback_function
- or idl_type.is_dictionary
- or idl_type.is_union_type
- or idl_type.base_type == 'object' or idl_type.base_type == 'any')
+ or idl_type.is_custom_callback_function or idl_type.is_dictionary
+ or idl_type.is_union_type or idl_type.base_type == 'object'
+ or idl_type.base_type == 'any')
+
IdlTypeBase.cpp_type_has_null_value = property(cpp_type_has_null_value)
@@ -1156,6 +1309,7 @@ def is_explicit_nullable(idl_type):
# we use base::Optional<T> or similar explicit ways to represent a null value.
return idl_type.is_nullable and not idl_type.is_implicit_nullable
+
IdlTypeBase.is_implicit_nullable = property(is_implicit_nullable)
IdlUnionType.is_implicit_nullable = False
IdlTypeBase.is_explicit_nullable = property(is_explicit_nullable)
@@ -1165,6 +1319,7 @@ def includes_nullable_type_union(idl_type):
# http://heycam.github.io/webidl/#dfn-includes-a-nullable-type
return idl_type.number_of_nullable_member_types == 1
+
IdlTypeBase.includes_nullable_type = False
IdlNullableType.includes_nullable_type = True
IdlUnionType.includes_nullable_type = property(includes_nullable_type_union)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
index ffacd12235c..54d50871d5a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
@@ -6,9 +6,9 @@ from utilities import to_snake_case
import v8_types
import v8_utilities
-
UNION_CPP_INCLUDES = frozenset([
'base/stl_util.h',
+ 'bindings/core/v8/native_value_traits_impl.h',
'bindings/core/v8/to_v8_for_core.h',
])
@@ -21,7 +21,6 @@ UNION_H_INCLUDES = frozenset([
'platform/heap/handle.h',
])
-
cpp_includes = set()
header_forward_decls = set()
header_includes = set()
@@ -47,7 +46,8 @@ def container_context(union_type, info_provider):
object_type = None
record_type = None
string_type = None
- for member in sorted(union_type.flattened_member_types, key=lambda m: m.name):
+ for member in sorted(
+ union_type.flattened_member_types, key=lambda m: m.name):
context = member_context(member, info_provider)
members.append(context)
if member.base_type == 'ArrayBuffer':
@@ -66,8 +66,7 @@ def container_context(union_type, info_provider):
if array_or_sequence_type:
raise Exception('%s is ambiguous.' % union_type.name)
array_or_sequence_type = context
- # "Dictionary" is an object, rather than an IDL dictionary.
- elif member.base_type == 'Dictionary':
+ elif member.base_type == 'object':
if object_type or record_type:
raise Exception('%s is ambiguous.' % union_type.name)
object_type = context
@@ -84,14 +83,17 @@ def container_context(union_type, info_provider):
elif member is union_type.string_member_type:
string_type = context
else:
- raise Exception('%s is not supported as an union member.' % member.name)
+ raise Exception(
+ '%s is not supported as an union member.' % member.name)
# Nullable restriction checks
nullable_members = union_type.number_of_nullable_member_types
if nullable_members > 1:
- raise Exception('%s contains more than one nullable members' % union_type.name)
+ raise Exception(
+ '%s contains more than one nullable members' % union_type.name)
if dictionary_type and nullable_members == 1:
- raise Exception('%s has a dictionary and a nullable member' % union_type.name)
+ raise Exception(
+ '%s has a dictionary and a nullable member' % union_type.name)
cpp_class = union_type.cpp_type
return {
@@ -119,8 +121,8 @@ def container_context(union_type, info_provider):
def _update_includes_and_forward_decls(member, info_provider):
interface_info = info_provider.interfaces_info.get(member.name, None)
if interface_info:
- cpp_includes.update(interface_info.get(
- 'dependencies_include_paths', []))
+ cpp_includes.update(
+ interface_info.get('dependencies_include_paths', []))
# We need complete types for IDL dictionaries in union containers.
if member.is_dictionary or member.is_array_buffer_view_or_typed_array:
header_includes.update(member.includes_for_type())
@@ -130,15 +132,18 @@ def _update_includes_and_forward_decls(member, info_provider):
else:
if member.is_record_type:
_update_includes_and_forward_decls(member.key_type, info_provider)
- _update_includes_and_forward_decls(member.value_type, info_provider)
+ _update_includes_and_forward_decls(member.value_type,
+ info_provider)
elif member.is_array_or_sequence_type:
- _update_includes_and_forward_decls(member.element_type, info_provider)
+ _update_includes_and_forward_decls(member.element_type,
+ info_provider)
cpp_includes.add('bindings/core/v8/script_iterator.h')
elif member.is_union_type:
# Reaching this block means we have a union that is inside a
# record or sequence.
header_forward_decls.add(member.name)
- cpp_includes.update([info_provider.include_path_for_union_types(member)])
+ cpp_includes.update(
+ [info_provider.include_path_for_union_types(member)])
cpp_includes.update(member.includes_for_type())
@@ -146,7 +151,8 @@ def member_context(member, info_provider):
_update_includes_and_forward_decls(member, info_provider)
if member.is_nullable:
member = member.inner_type
- type_name = (member.inner_type if member.is_annotated_type else member).name
+ type_name = (member.inner_type
+ if member.is_annotated_type else member).name
# When converting a sequence or frozen array, we need to call the GetMethod(V, @@iterator)
# ES abstract operation and then use the result of that call to create a sequence from an
# iterable. For the purposes of this method, it means we need to pass |script_iterator|
@@ -156,21 +162,37 @@ def member_context(member, info_provider):
else:
v8_value_name = 'v8_value'
return {
- 'cpp_name': to_snake_case(v8_utilities.cpp_name(member)),
- 'cpp_type': member.cpp_type_args(used_in_cpp_sequence=True),
- 'cpp_local_type': member.cpp_type,
- 'cpp_value_to_v8_value': member.cpp_value_to_v8_value(
- cpp_value='impl.GetAs%s()' % type_name, isolate='isolate',
+ 'cpp_name':
+ to_snake_case(v8_utilities.cpp_name(member)),
+ 'cpp_type':
+ member.cpp_type_args(used_in_cpp_sequence=True),
+ 'cpp_local_type':
+ member.cpp_type,
+ 'cpp_value_to_v8_value':
+ member.cpp_value_to_v8_value(
+ cpp_value='impl.GetAs%s()' % type_name,
+ isolate='isolate',
creation_context='creationContext'),
- 'enum_type': member.enum_type,
- 'enum_values': member.enum_values,
- 'is_array_buffer_or_view_type': member.is_array_buffer_or_view,
- 'is_array_buffer_view_or_typed_array': member.is_array_buffer_view_or_typed_array,
- 'is_traceable': member.is_traceable,
- 'rvalue_cpp_type': member.cpp_type_args(used_as_rvalue_type=True),
- 'specific_type_enum': 'k' + member.name,
- 'type_name': type_name,
- 'v8_value_to_local_cpp_value': member.v8_value_to_local_cpp_value(
- {}, v8_value_name, 'cpp_value', isolate='isolate',
- use_exception_state=True)
+ 'enum_type':
+ member.enum_type,
+ 'enum_values':
+ member.enum_values,
+ 'is_array_buffer_or_view_type':
+ member.is_array_buffer_or_view,
+ 'is_array_buffer_view_or_typed_array':
+ member.is_array_buffer_view_or_typed_array,
+ 'is_traceable':
+ member.is_traceable,
+ 'rvalue_cpp_type':
+ member.cpp_type_args(used_as_rvalue_type=True),
+ 'specific_type_enum':
+ 'k' + member.name,
+ 'type_name':
+ type_name,
+ 'v8_value_to_local_cpp_value':
+ member.v8_value_to_local_cpp_value({},
+ v8_value_name,
+ 'cpp_value',
+ isolate='isolate',
+ use_exception_state=True)
}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
index ec31d27da23..d6a53c6538a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
@@ -25,7 +25,6 @@
# 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.
-
"""Functions shared by various parts of the code generator.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
@@ -56,15 +55,15 @@ ACRONYMS = [
'XSLT',
]
-
################################################################################
# Extended attribute parsing
################################################################################
+
def extended_attribute_value_contains(extended_attribute_value, key):
- return (extended_attribute_value == key or
- (isinstance(extended_attribute_value, list) and
- key in extended_attribute_value))
+ return (extended_attribute_value == key
+ or (isinstance(extended_attribute_value, list)
+ and key in extended_attribute_value))
def has_extended_attribute(definition_or_member, extended_attribute_list):
@@ -74,8 +73,8 @@ def has_extended_attribute(definition_or_member, extended_attribute_list):
def has_extended_attribute_value(definition_or_member, name, value):
extended_attributes = definition_or_member.extended_attributes
- return (name in extended_attributes and
- extended_attribute_value_contains(extended_attributes[name], value))
+ return (name in extended_attributes and extended_attribute_value_contains(
+ extended_attributes[name], value))
def extended_attribute_value_as_list(definition_or_member, name):
@@ -92,6 +91,7 @@ def extended_attribute_value_as_list(definition_or_member, name):
# String handling
################################################################################
+
def capitalize(name):
"""Capitalize first letter or initial acronym (used in setter names)."""
for acronym in ACRONYMS:
@@ -126,14 +126,16 @@ def runtime_enabled_function(name):
# C++
################################################################################
+
def scoped_name(interface, definition, base_name):
# partial interfaces are implemented as separate classes, with their members
# implemented as static member functions
- partial_interface_implemented_as = definition.extended_attributes.get('PartialInterfaceImplementedAs')
+ partial_interface_implemented_as = definition.extended_attributes.get(
+ 'PartialInterfaceImplementedAs')
if partial_interface_implemented_as:
return '%s::%s' % (partial_interface_implemented_as, base_name)
- if (definition.is_static or
- definition.name in ('Constructor', 'NamedConstructor')):
+ if (definition.is_static
+ or definition.name in ('Constructor', 'NamedConstructor')):
return '%s::%s' % (cpp_name(interface), base_name)
return 'impl->%s' % base_name
@@ -168,6 +170,7 @@ def binding_header_filename(name):
# Specific extended attributes
################################################################################
+
# [ActivityLogging]
def activity_logging_world_list(member, access_type=''):
"""Returns a set of world suffixes for which a definition member has activity logging, for specified access type.
@@ -198,8 +201,8 @@ def activity_logging_world_check(member):
extended_attributes = member.extended_attributes
if 'LogActivity' not in extended_attributes:
return False
- if ('PerWorldBindings' not in extended_attributes and
- 'LogAllWorlds' not in extended_attributes):
+ if ('PerWorldBindings' not in extended_attributes
+ and 'LogAllWorlds' not in extended_attributes):
return True
return False
@@ -225,16 +228,17 @@ CALL_WITH_VALUES = [
def call_with_arguments(call_with_values):
if not call_with_values:
return []
- return [CALL_WITH_ARGUMENTS[value]
- for value in CALL_WITH_VALUES
- if extended_attribute_value_contains(call_with_values, value)]
+ return [
+ CALL_WITH_ARGUMENTS[value] for value in CALL_WITH_VALUES
+ if extended_attribute_value_contains(call_with_values, value)
+ ]
# [Constructor], [NamedConstructor]
def is_constructor_attribute(member):
# TODO(yukishiino): replace this with [Constructor] and [NamedConstructor] extended attribute
- return (type(member) == IdlAttribute and
- member.idl_type.name.endswith('Constructor'))
+ return (type(member) == IdlAttribute
+ and member.idl_type.name.endswith('Constructor'))
# [DeprecateAs]
@@ -260,7 +264,6 @@ EXPOSED_EXECUTION_CONTEXT_METHOD = {
'Worklet': 'IsWorkletGlobalScope',
}
-
EXPOSED_WORKERS = set([
'DedicatedWorker',
'SharedWorker',
@@ -270,6 +273,7 @@ EXPOSED_WORKERS = set([
class ExposureSet:
"""An ExposureSet is a collection of Exposure instructions."""
+
def __init__(self, exposures=None):
self.exposures = set(exposures) if exposures else set()
@@ -301,9 +305,10 @@ class ExposureSet:
@staticmethod
def _code(exposure):
condition = ('execution_context->%s()' %
- EXPOSED_EXECUTION_CONTEXT_METHOD[exposure.exposed])
+ EXPOSED_EXECUTION_CONTEXT_METHOD[exposure.exposed])
if exposure.runtime_enabled is not None:
- runtime_enabled = (runtime_enabled_function(exposure.runtime_enabled))
+ runtime_enabled = (runtime_enabled_function(
+ exposure.runtime_enabled))
return '({0} && {1})'.format(condition, runtime_enabled)
return condition
@@ -338,7 +343,9 @@ def exposed(member, interface):
# Methods must not be exposed to a broader scope than their interface.
if not exposure_set.issubset(interface_exposure_set):
- raise ValueError('Interface members\' exposure sets must be a subset of the interface\'s.')
+ raise ValueError(
+ 'Interface members\' exposure sets must be a subset of the interface\'s.'
+ )
return exposure_set.code()
@@ -349,9 +356,9 @@ def secure_context(member, interface):
to the current context. Requires that the surrounding code defines an |is_secure_context|
variable prior to this check."""
member_is_secure_context = 'SecureContext' in member.extended_attributes
- interface_is_secure_context = ((member.defined_in is None or
- member.defined_in == interface.name) and
- 'SecureContext' in interface.extended_attributes)
+ interface_is_secure_context = (
+ (member.defined_in is None or member.defined_in == interface.name)
+ and 'SecureContext' in interface.extended_attributes)
if not (member_is_secure_context or interface_is_secure_context):
return None
@@ -361,12 +368,14 @@ def secure_context(member, interface):
if member_is_secure_context:
conditional = member.extended_attributes['SecureContext']
if conditional:
- conditions.append('!{}'.format(runtime_enabled_function(conditional)))
+ conditions.append('!{}'.format(
+ runtime_enabled_function(conditional)))
if interface_is_secure_context:
conditional = interface.extended_attributes['SecureContext']
if conditional:
- conditions.append('!{}'.format(runtime_enabled_function(conditional)))
+ conditions.append('!{}'.format(
+ runtime_enabled_function(conditional)))
return ' || '.join(conditions)
@@ -381,7 +390,8 @@ def cpp_name(definition_or_member):
#
# [1] https://heycam.github.io/webidl/#prod-identifier
if '-' in definition_or_member.name:
- return NameStyleConverter(definition_or_member.name).to_lower_camel_case()
+ return NameStyleConverter(
+ definition_or_member.name).to_lower_camel_case()
return definition_or_member.name
@@ -396,6 +406,25 @@ def cpp_name_or_partial(interface):
return cpp_class_name
+def cpp_encoded_property_name(member):
+ """
+ Returns a property name that the bindings generator can use in generated
+ code internally.
+
+ Note that Web IDL allows '-' (hyphen-minus) and '_' (low line) in
+ identifiers but C++ does not allow or recommend them. This function
+ encodes these characters.
+ """
+ property_name = member.name
+ # We're optimistic about name conflict. It's highly unlikely that these
+ # replacements will cause a conflict.
+ assert "Dec45" not in property_name
+ assert "Dec95" not in property_name
+ property_name = property_name.replace("-", "Dec45")
+ property_name = property_name.replace("_", "Dec95")
+ return property_name
+
+
# [MeasureAs]
def measure_as(definition_or_member, interface):
extended_attributes = definition_or_member.extended_attributes
@@ -408,7 +437,8 @@ def measure_as(definition_or_member, interface):
includes.add('platform/instrumentation/use_counter.h')
measure_as_name = capitalize(definition_or_member.name)
if interface is not None:
- measure_as_name = '%s_%s' % (capitalize(interface.name), measure_as_name)
+ measure_as_name = '%s_%s' % (capitalize(interface.name),
+ measure_as_name)
return lambda suffix: 'V8%s_%s' % (measure_as_name, suffix)
return None
@@ -418,10 +448,11 @@ def high_entropy(definition_or_member):
extended_attributes = definition_or_member.extended_attributes
if 'HighEntropy' in extended_attributes:
includes.add('core/frame/dactyloscoper.h')
- if not ('Measure' in extended_attributes or 'MeasureAs' in extended_attributes):
- raise Exception('%s specified [HighEntropy], but does not include '
- 'either [Measure] or [MeasureAs]'
- % definition_or_member.name)
+ if not ('Measure' in extended_attributes
+ or 'MeasureAs' in extended_attributes):
+ raise Exception(
+ '%s specified [HighEntropy], but does not include '
+ 'either [Measure] or [MeasureAs]' % definition_or_member.name)
return True
return False
@@ -440,7 +471,8 @@ def origin_trial_feature_name(definition_or_member, runtime_features):
"""
extended_attributes = definition_or_member.extended_attributes
feature_name = extended_attributes.get('RuntimeEnabled')
- if feature_name and _is_origin_trial_feature(feature_name, runtime_features):
+ if feature_name and _is_origin_trial_feature(feature_name,
+ runtime_features):
return feature_name
@@ -448,7 +480,8 @@ def origin_trial_function_call(feature_name, execution_context=None):
"""Returns a function call to determine if an origin trial is enabled."""
return 'RuntimeEnabledFeatures::{feature_name}Enabled({context})'.format(
feature_name=feature_name,
- context=execution_context if execution_context else "execution_context")
+ context=execution_context
+ if execution_context else "execution_context")
# [ContextEnabled]
@@ -470,7 +503,8 @@ def rcs_counter_name(member, generic_counter_name):
def runtime_enabled_feature_name(definition_or_member, runtime_features):
extended_attributes = definition_or_member.extended_attributes
feature_name = extended_attributes.get('RuntimeEnabled')
- if feature_name and not _is_origin_trial_feature(feature_name, runtime_features):
+ if feature_name and not _is_origin_trial_feature(feature_name,
+ runtime_features):
includes.add('platform/runtime_enabled_features.h')
return feature_name
@@ -502,8 +536,8 @@ def on_instance(interface, member):
if is_constructor_attribute(member):
return True
- if ('Global' in interface.extended_attributes or
- 'Unforgeable' in member.extended_attributes):
+ if ('Global' in interface.extended_attributes
+ or 'Unforgeable' in member.extended_attributes):
return True
return False
@@ -532,8 +566,8 @@ def on_prototype(interface, member):
if is_constructor_attribute(member):
return False
- if ('Global' in interface.extended_attributes or
- 'Unforgeable' in member.extended_attributes):
+ if ('Global' in interface.extended_attributes
+ or 'Unforgeable' in member.extended_attributes):
return False
return True
@@ -556,16 +590,15 @@ def on_interface(interface, member):
# http://heycam.github.io/webidl/#idl-indexed-properties
################################################################################
+
def indexed_property_getter(interface):
try:
# Find indexed property getter, if present; has form:
# getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1)
return next(
- method
- for method in interface.operations
- if ('getter' in method.specials and
- len(method.arguments) == 1 and
- str(method.arguments[0].idl_type) == 'unsigned long'))
+ method for method in interface.operations
+ if ('getter' in method.specials and len(method.arguments) == 1
+ and str(method.arguments[0].idl_type) == 'unsigned long'))
except StopIteration:
return None
@@ -575,11 +608,9 @@ def indexed_property_setter(interface):
# Find indexed property setter, if present; has form:
# setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE ARG2)
return next(
- method
- for method in interface.operations
- if ('setter' in method.specials and
- len(method.arguments) == 2 and
- str(method.arguments[0].idl_type) == 'unsigned long'))
+ method for method in interface.operations
+ if ('setter' in method.specials and len(method.arguments) == 2
+ and str(method.arguments[0].idl_type) == 'unsigned long'))
except StopIteration:
return None
@@ -589,11 +620,9 @@ def indexed_property_deleter(interface):
# Find indexed property deleter, if present; has form:
# deleter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG)
return next(
- method
- for method in interface.operations
- if ('deleter' in method.specials and
- len(method.arguments) == 1 and
- str(method.arguments[0].idl_type) == 'unsigned long'))
+ method for method in interface.operations
+ if ('deleter' in method.specials and len(method.arguments) == 1
+ and str(method.arguments[0].idl_type) == 'unsigned long'))
except StopIteration:
return None
@@ -603,16 +632,15 @@ def indexed_property_deleter(interface):
# http://heycam.github.io/webidl/#idl-named-properties
################################################################################
+
def named_property_getter(interface):
try:
# Find named property getter, if present; has form:
# getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1)
getter = next(
- method
- for method in interface.operations
- if ('getter' in method.specials and
- len(method.arguments) == 1 and
- str(method.arguments[0].idl_type) == 'DOMString'))
+ method for method in interface.operations
+ if ('getter' in method.specials and len(method.arguments) == 1
+ and str(method.arguments[0].idl_type) == 'DOMString'))
getter.name = getter.name or 'AnonymousNamedGetter'
return getter
except StopIteration:
@@ -624,11 +652,9 @@ def named_property_setter(interface):
# Find named property setter, if present; has form:
# setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2)
return next(
- method
- for method in interface.operations
- if ('setter' in method.specials and
- len(method.arguments) == 2 and
- str(method.arguments[0].idl_type) == 'DOMString'))
+ method for method in interface.operations
+ if ('setter' in method.specials and len(method.arguments) == 2
+ and str(method.arguments[0].idl_type) == 'DOMString'))
except StopIteration:
return None
@@ -638,11 +664,9 @@ def named_property_deleter(interface):
# Find named property deleter, if present; has form:
# deleter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG)
return next(
- method
- for method in interface.operations
- if ('deleter' in method.specials and
- len(method.arguments) == 1 and
- str(method.arguments[0].idl_type) == 'DOMString'))
+ method for method in interface.operations
+ if ('deleter' in method.specials and len(method.arguments) == 1
+ and str(method.arguments[0].idl_type) == 'DOMString'))
except StopIteration:
return None
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/.style.yapf b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/.style.yapf
index 0169b9a6487..2ae9158e446 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/.style.yapf
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/.style.yapf
@@ -1,3 +1,4 @@
[style]
# https://www.chromium.org/blink/coding-style
based_on_style = pep8
+column_limit = 79
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
index 4dacc398b45..387fef30bff 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
@@ -12,8 +12,10 @@ def _setup_sys_path():
expected_path = 'third_party/blink/renderer/bindings/scripts/web_idl/'
this_dir = os.path.dirname(__file__)
- root_dir = os.path.join(this_dir, *(['..'] * expected_path.count('/')))
- sys.path = [
+ root_dir = os.path.abspath(
+ os.path.join(this_dir, *(['..'] * expected_path.count('/'))))
+
+ module_dirs = (
# //third_party/blink/renderer/build/scripts/blinkbuild
os.path.join(root_dir, 'third_party', 'blink', 'renderer', 'build',
'scripts'),
@@ -23,17 +25,23 @@ def _setup_sys_path():
os.path.join(root_dir, 'third_party', 'pyjson5', 'src'),
# //tools/idl_parser
os.path.join(root_dir, 'tools'),
- ] + sys.path
+ )
+ for module_dir in reversed(module_dirs):
+ # Preserve sys.path[0] as is.
+ # https://docs.python.org/3/library/sys.html?highlight=path[0]#sys.path
+ sys.path.insert(1, module_dir)
_setup_sys_path()
-
+from . import file_io
from .ast_group import AstGroup
from .attribute import Attribute
from .callback_function import CallbackFunction
from .callback_interface import CallbackInterface
from .composition_parts import Component
+from .composition_parts import DebugInfo
+from .composition_parts import Identifier
from .constant import Constant
from .constructor import Constructor
from .constructor import ConstructorGroup
@@ -43,10 +51,18 @@ from .dictionary import Dictionary
from .dictionary import DictionaryMember
from .enumeration import Enumeration
from .exposure import Exposure
+from .extended_attribute import ExtendedAttribute
+from .extended_attribute import ExtendedAttributes
from .function_like import FunctionLike
from .function_like import OverloadGroup
from .idl_type import IdlType
+from .interface import IndexedAndNamedProperties
from .interface import Interface
+from .interface import Iterable
+from .interface import LegacyWindowAlias
+from .interface import Maplike
+from .interface import Setlike
+from .interface import Stringifier
from .literal_constant import LiteralConstant
from .namespace import Namespace
from .operation import Operation
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py
index 1d3f9d74fc1..467e1006463 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py
@@ -55,7 +55,7 @@ class Attribute(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo,
ir = make_copy(ir)
WithIdentifier.__init__(self, ir)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_function.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_function.py
index 3536a9e67c6..b82196d6b7b 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_function.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_function.py
@@ -47,7 +47,7 @@ class CallbackFunction(UserDefinedType, FunctionLike, WithExtendedAttributes,
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
FunctionLike.__init__(self, ir)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithComponent.__init__(self, ir, readonly=True)
WithDebugInfo.__init__(self, ir)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_interface.py
index e3792d16520..42249966d1c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/callback_interface.py
@@ -52,17 +52,19 @@ class CallbackInterface(UserDefinedType, WithExtendedAttributes,
self.attributes = []
self.constants = constants
- self.operations = operations
- self.operation_groups = []
self.constructors = []
self.constructor_groups = []
+ self.named_constructors = []
+ self.named_constructor_groups = []
+ self.operations = operations
+ self.operation_groups = []
def __init__(self, ir):
assert isinstance(ir, CallbackInterface.IR)
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithComponent.__init__(self, ir, readonly=True)
WithDebugInfo.__init__(self, ir)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
index 98a491d27b2..9c1d2784440 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
@@ -5,8 +5,11 @@
# The list of attributes that CodeGeneratorInfo supports. CodeGeneratorInfo's
# attributes are auto-generated from this list because they're boilerplated.
_CODE_GENERATOR_INFO_ATTRIBUTES = (
- 'defined_in_mixin',
- 'defined_in_partial',
+ 'blink_headers',
+ 'defined_in_mixin', # [LegacyTreatAsPartialInterface] makes this False
+ 'defined_in_partial', # [LegacyTreatAsPartialInterface] makes this True
+ 'is_active_script_wrappable',
+ 'is_legacy_unenumerable_named_properties',
'property_implemented_as',
'receiver_implemented_as',
)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py
index a999bca7d7e..29add032724 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/composition_parts.py
@@ -2,11 +2,14 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import posixpath
+
from .code_generator_info import CodeGeneratorInfo
from .code_generator_info import CodeGeneratorInfoMutable
from .exposure import Exposure
from .exposure import ExposureMutable
from .extended_attribute import ExtendedAttributes
+from .extended_attribute import ExtendedAttributesMutable
class Identifier(str):
@@ -31,14 +34,18 @@ class WithIdentifier(object):
class WithExtendedAttributes(object):
"""Implements |extended_attributes| as a readonly attribute."""
- def __init__(self, extended_attributes=None):
+ def __init__(self, extended_attributes=None, readonly=False):
if isinstance(extended_attributes, WithExtendedAttributes):
extended_attributes = extended_attributes.extended_attributes
elif extended_attributes is None:
extended_attributes = ExtendedAttributes()
assert isinstance(extended_attributes, ExtendedAttributes)
- self._extended_attributes = extended_attributes
+ if readonly:
+ self._extended_attributes = ExtendedAttributes(extended_attributes)
+ else:
+ self._extended_attributes = ExtendedAttributesMutable(
+ extended_attributes)
@property
def extended_attributes(self):
@@ -133,10 +140,22 @@ class WithComponent(object):
class Location(object):
+ _blink_path_prefix = posixpath.sep + posixpath.join(
+ 'third_party', 'blink', 'renderer', '')
+
def __init__(self, filepath=None, line_number=None, position=None):
assert filepath is None or isinstance(filepath, str)
assert line_number is None or isinstance(line_number, int)
assert position is None or isinstance(position, int)
+
+ # idl_parser produces paths based on the working directory, which may
+ # not be the project root directory, e.g. "../../third_party/blink/...".
+ # Canonicalize the paths heuristically.
+ if filepath is not None:
+ index = filepath.find(self._blink_path_prefix)
+ if index >= 0:
+ filepath = filepath[index + 1:]
+
self._filepath = filepath
self._line_number = line_number
self._position = position # Position number in a file
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constant.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constant.py
index 3a4a85ea710..c54fef0b472 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constant.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constant.py
@@ -50,7 +50,7 @@ class Constant(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo,
ir = make_copy(ir)
WithIdentifier.__init__(self, ir)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
@@ -67,6 +67,14 @@ class Constant(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo,
return self._idl_type
@property
+ def is_static(self):
+ return True
+
+ @property
+ def is_readonly(self):
+ return True
+
+ @property
def value(self):
"""Returns the value."""
return self._value
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py
index 486ee910d11..ceacd261c7c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py
@@ -27,14 +27,16 @@ class Constructor(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo,
class IR(FunctionLike.IR, WithExtendedAttributes, WithCodeGeneratorInfo,
WithExposure, WithOwnerMixin, WithComponent, WithDebugInfo):
def __init__(self,
+ identifier,
arguments,
return_type,
extended_attributes=None,
component=None,
debug_info=None):
+ assert identifier is None or isinstance(identifier, Identifier)
FunctionLike.IR.__init__(
self,
- identifier=Identifier('constructor'),
+ identifier=(identifier or Identifier('constructor')),
arguments=arguments,
return_type=return_type)
WithExtendedAttributes.__init__(self, extended_attributes)
@@ -48,7 +50,7 @@ class Constructor(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo,
assert isinstance(ir, Constructor.IR)
FunctionLike.__init__(self, ir)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
@@ -57,22 +59,25 @@ class Constructor(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo,
WithDebugInfo.__init__(self, ir)
-class ConstructorGroup(OverloadGroup, WithCodeGeneratorInfo, WithExposure,
- WithOwner, WithComponent, WithDebugInfo):
+class ConstructorGroup(OverloadGroup, WithExtendedAttributes,
+ WithCodeGeneratorInfo, WithExposure, WithOwner,
+ WithComponent, WithDebugInfo):
"""
- Represents a group of constructors for an interface.
+ Represents a group of constructors of an interface.
The number of constructors in this group may be 1 or 2+. In the latter
case, the constructors are overloaded.
"""
- class IR(OverloadGroup.IR, WithCodeGeneratorInfo, WithExposure,
- WithDebugInfo):
+ class IR(OverloadGroup.IR, WithExtendedAttributes, WithCodeGeneratorInfo,
+ WithExposure, WithDebugInfo):
def __init__(self,
constructors,
+ extended_attributes=None,
code_generator_info=None,
debug_info=None):
OverloadGroup.IR.__init__(self, constructors)
+ WithExtendedAttributes.__init__(self, extended_attributes)
WithCodeGeneratorInfo.__init__(self, code_generator_info)
WithExposure.__init__(self)
WithDebugInfo.__init__(self, debug_info)
@@ -92,6 +97,7 @@ class ConstructorGroup(OverloadGroup, WithCodeGeneratorInfo, WithExposure,
ir = make_copy(ir)
OverloadGroup.__init__(self, functions=constructors)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py
index b9ecfe5632e..c92cf48eb2a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/database.py
@@ -48,17 +48,17 @@ class DatabaseBody(object):
)
@classmethod
- def itervalues(cls):
+ def values(cls):
return cls._ALL_ENTRIES.__iter__()
def __init__(self):
self._defs = {}
- for kind in DatabaseBody.Kind.itervalues():
+ for kind in DatabaseBody.Kind.values():
self._defs[kind] = {}
def register(self, kind, user_defined_type):
assert isinstance(user_defined_type, (Typedef, Union, UserDefinedType))
- assert kind in DatabaseBody.Kind.itervalues()
+ assert kind in DatabaseBody.Kind.values()
try:
self.find_by_identifier(user_defined_type.identifier)
assert False, user_defined_type.identifier
@@ -67,7 +67,7 @@ class DatabaseBody(object):
self._defs[kind][user_defined_type.identifier] = user_defined_type
def find_by_identifier(self, identifier):
- for defs_per_kind in self._defs.itervalues():
+ for defs_per_kind in self._defs.values():
if identifier in defs_per_kind:
return defs_per_kind[identifier]
raise KeyError(identifier)
@@ -107,6 +107,26 @@ class Database(object):
return self._impl.find_by_identifier(identifier)
@property
+ def callback_functions(self):
+ """Returns all callback functions."""
+ return self._view_by_kind(Database._Kind.CALLBACK_FUNCTION)
+
+ @property
+ def callback_interfaces(self):
+ """Returns all callback interfaces."""
+ return self._view_by_kind(Database._Kind.CALLBACK_INTERFACE)
+
+ @property
+ def dictionaries(self):
+ """Returns all dictionaries."""
+ return self._view_by_kind(Database._Kind.DICTIONARY)
+
+ @property
+ def enumerations(self):
+ """Returns all enumerations."""
+ return self._view_by_kind(Database._Kind.ENUMERATION)
+
+ @property
def interfaces(self):
"""
Returns all interfaces.
@@ -121,26 +141,11 @@ class Database(object):
return self._view_by_kind(Database._Kind.INTERFACE_MIXIN)
@property
- def dictionaries(self):
- """Returns all dictionaries."""
- return self._view_by_kind(Database._Kind.DICTIONARY)
-
- @property
def namespaces(self):
"""Returns all namespaces."""
return self._view_by_kind(Database._Kind.NAMESPACE)
@property
- def callback_functions(self):
- """Returns all callback functions."""
- return self._view_by_kind(Database._Kind.CALLBACK_FUNCTION)
-
- @property
- def callback_interfaces(self):
- """Returns all callback interfaces."""
- return self._view_by_kind(Database._Kind.CALLBACK_INTERFACE)
-
- @property
def typedefs(self):
"""Returns all typedef definitions."""
return self._view_by_kind(Database._Kind.TYPEDEF)
@@ -151,4 +156,4 @@ class Database(object):
return self._view_by_kind(Database._Kind.UNION)
def _view_by_kind(self, kind):
- return self._impl.find_by_kind(kind).viewvalues()
+ return self._impl.find_by_kind(kind).values()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/demonstration_and_testing.idl b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/demonstration_and_testing.idl
index 1f94e76ad3b..766bfe7a7cf 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/demonstration_and_testing.idl
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/demonstration_and_testing.idl
@@ -12,7 +12,7 @@
Exposed=Window
] interface TestInterfaceConstructor {
constructor();
- constructor(DOMString arg1);
+ [HTMLConstructor] constructor(DOMString arg1);
[Custom] constructor(Node node);
[RuntimeEnabled=TestFeature1] constructor(long num);
};
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py
index 1f536e99b0d..01d2cdedcd6 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py
@@ -62,7 +62,7 @@ class Dictionary(UserDefinedType, WithExtendedAttributes,
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithComponent.__init__(self, ir, readonly=True)
@@ -143,7 +143,7 @@ class DictionaryMember(WithIdentifier, WithExtendedAttributes,
ir = make_copy(ir)
WithIdentifier.__init__(self, ir)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/enumeration.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/enumeration.py
index b402d14c2d7..f141e86e05d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/enumeration.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/enumeration.py
@@ -42,7 +42,7 @@ class Enumeration(UserDefinedType, WithExtendedAttributes,
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithComponent.__init__(self, ir, readonly=True)
WithDebugInfo.__init__(self, ir)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/exposure.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/exposure.py
index 266b7388a18..46e2e45af49 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/exposure.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/exposure.py
@@ -5,13 +5,29 @@
from .runtime_enabled_features import RuntimeEnabledFeatures
+class _Feature(str):
+ """Represents a runtime-enabled feature."""
+
+ def __init__(self, value):
+ str.__init__(self, value)
+ self._is_context_dependent = (
+ RuntimeEnabledFeatures.is_context_dependent(self))
+
+ @property
+ def is_context_dependent(self):
+ return self._is_context_dependent
+
+
class _GlobalNameAndFeature(object):
def __init__(self, global_name, feature=None):
assert isinstance(global_name, str)
assert feature is None or isinstance(feature, str)
self._global_name = global_name
- self._feature = feature
+ if feature is None:
+ self._feature = None
+ else:
+ self._feature = _Feature(feature)
@property
def global_name(self):
@@ -23,6 +39,8 @@ class _GlobalNameAndFeature(object):
class Exposure(object):
+ """Represents a set of conditions under which the construct is exposed."""
+
def __init__(self, other=None):
assert other is None or isinstance(other, Exposure)
@@ -94,6 +112,34 @@ class Exposure(object):
return False
return self._only_in_secure_contexts
+ def is_context_dependent(self, global_names=None):
+ """
+ Returns True if the exposure of this construct depends on a context.
+
+ Args:
+ global_names: When specified, it's taken into account that the
+ global object implements |global_names|.
+ """
+ assert (global_names is None
+ or (isinstance(global_names, (list, tuple))
+ and all(isinstance(name, str) for name in global_names)))
+
+ if (self.context_dependent_runtime_enabled_features
+ or self.context_enabled_features
+ or self.only_in_secure_contexts):
+ return True
+
+ if not global_names:
+ return bool(self.global_names_and_features)
+
+ is_context_dependent = False
+ for entry in self.global_names_and_features:
+ if entry.global_name not in global_names:
+ continue
+ if entry.feature and entry.feature.is_context_dependent:
+ is_context_dependent = True
+ return is_context_dependent
+
class ExposureMutable(Exposure):
def __init__(self):
@@ -118,11 +164,12 @@ class ExposureMutable(Exposure):
def add_runtime_enabled_feature(self, name):
assert isinstance(name, str)
- if RuntimeEnabledFeatures.is_context_dependent(name):
- self._context_dependent_runtime_enabled_features.append(name)
+ feature = _Feature(name)
+ if feature.is_context_dependent:
+ self._context_dependent_runtime_enabled_features.append(feature)
else:
- self._context_independent_runtime_enabled_features.append(name)
- self._runtime_enabled_features.append(name)
+ self._context_independent_runtime_enabled_features.append(feature)
+ self._runtime_enabled_features.append(feature)
def add_context_enabled_feature(self, name):
assert isinstance(name, str)
@@ -136,6 +183,6 @@ class ExposureMutable(Exposure):
if isinstance(value, bool):
self._only_in_secure_contexts = value
elif isinstance(value, str):
- self._only_in_secure_contexts = (value, )
+ self._only_in_secure_contexts = (_Feature(value), )
else:
- self._only_in_secure_contexts = tuple(value)
+ self._only_in_secure_contexts = tuple(map(_Feature, value))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
index ee6967af9b1..36eec862f47 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
@@ -169,10 +169,12 @@ class ExtendedAttributes(object):
"""
def __init__(self, extended_attributes=None):
- assert extended_attributes is None or (isinstance(
- extended_attributes, (list, tuple)) and all(
- isinstance(attr, ExtendedAttribute)
- for attr in extended_attributes))
+ assert (extended_attributes is None
+ or isinstance(extended_attributes, ExtendedAttributes)
+ or (isinstance(extended_attributes, (list, tuple)) and all(
+ isinstance(attr, ExtendedAttribute)
+ for attr in extended_attributes)))
+
sorted_ext_attrs = sorted(
extended_attributes or [], key=lambda x: x.key)
@@ -181,8 +183,15 @@ class ExtendedAttributes(object):
for key, ext_attrs in itertools.groupby(
sorted_ext_attrs, key=lambda x: x.key)
}
+ self._keys = None
+ self._length = None
+ self._on_ext_attrs_updated()
+
+ def _on_ext_attrs_updated(self):
self._keys = tuple(sorted(self._ext_attrs.keys()))
- self._length = len(sorted_ext_attrs)
+ self._length = 0
+ for ext_attrs in self._ext_attrs.values():
+ self._length += len(ext_attrs)
@classmethod
def equals(cls, lhs, rhs):
@@ -256,3 +265,26 @@ class ExtendedAttributes(object):
"""Returns self.get(key).values if the key exists or an empty list."""
ext_attr = self.get(key)
return ext_attr.values if ext_attr else ()
+
+ def _append(self, ext_attr):
+ assert isinstance(ext_attr, ExtendedAttribute)
+
+ if ext_attr.key not in self._ext_attrs:
+ self._ext_attrs[ext_attr.key] = (ext_attr, )
+ else:
+ self._ext_attrs[ext_attr.key] = (tuple(
+ sorted(
+ self._ext_attrs[ext_attr.key] + (ext_attr, ),
+ key=lambda x: x.syntactic_form)))
+ self._on_ext_attrs_updated()
+
+
+class ExtendedAttributesMutable(ExtendedAttributes):
+ def __getstate__(self):
+ assert False, "ExtendedAttributesMutable must not be pickled."
+
+ def __setstate__(self, state):
+ assert False, "ExtendedAttributesMutable must not be pickled."
+
+ def append(self, ext_attr):
+ self._append(ext_attr)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute_test.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute_test.py
index b4d4876ec74..2e4144f0477 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute_test.py
@@ -1,7 +1,6 @@
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Unit tests for extended_attributes.py."""
import unittest
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
index 9136a41a3b0..19e3327a8fb 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/file_io.py
@@ -3,14 +3,19 @@
# found in the LICENSE file.
import os
-import pickle
+import sys
+
+if sys.version_info.major == 2:
+ import cPickle as pickle # 'cPickle' is faster than 'pickle' on Py2
+else:
+ import pickle
def read_pickle_file(filepath):
"""
Reads the content of the file as a pickled object.
"""
- with open(filepath, 'r') as file_obj:
+ with open(filepath, 'rb') as file_obj:
return pickle.load(file_obj)
@@ -30,7 +35,7 @@ def write_to_file_if_changed(filepath, contents):
Returns True if the data is written to the file, and False if skipped.
"""
try:
- with open(filepath, 'r') as file_obj:
+ with open(filepath, 'rb') as file_obj:
old_contents = file_obj.read()
except (OSError, EnvironmentError):
pass
@@ -38,6 +43,10 @@ def write_to_file_if_changed(filepath, contents):
if contents == old_contents:
return False
os.remove(filepath)
- with open(filepath, 'w') as file_obj:
+
+ if not os.path.exists(os.path.dirname(filepath)):
+ os.makedirs(os.path.dirname(filepath))
+
+ with open(filepath, 'wb') as file_obj:
file_obj.write(contents)
return True
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/function_like.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/function_like.py
index 223a93fa09b..648c70d803d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/function_like.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/function_like.py
@@ -242,11 +242,10 @@ class OverloadGroup(WithIdentifier):
# step 1. If one type includes a nullable type and the other type either
# includes a nullable type, is a union type with flattened member
# types including a dictionary type, or is a dictionary type, ...
- type1_nullable = (idl_type1.does_include_nullable_type
- or idl_type1.unwrap().is_dictionary)
- type2_nullable = (idl_type2.does_include_nullable_type
- or idl_type2.unwrap().is_dictionary)
- if type1_nullable and type2_nullable:
+ if ((idl_type1.does_include_nullable_type
+ and idl_type2.does_include_nullable_or_dict)
+ or (idl_type2.does_include_nullable_type
+ and idl_type1.does_include_nullable_or_dict)):
return False
type1 = idl_type1.unwrap()
@@ -272,6 +271,9 @@ class OverloadGroup(WithIdentifier):
return True
# step 4. Consider the two "innermost" types ...
+ def is_string_type(idl_type):
+ return idl_type.is_string or idl_type.is_enumeration
+
def is_interface_like(idl_type):
return idl_type.is_interface or idl_type.is_buffer_source_type
@@ -292,11 +294,11 @@ class OverloadGroup(WithIdentifier):
return not type2.is_boolean
if type1.is_numeric:
return not type2.is_numeric
- if type1.is_string:
- return not type2.is_string
+ if is_string_type(type1):
+ return not is_string_type(type2)
if type1.is_object:
- return (type2.is_boolean or type2.is_numeric or type2.is_string
- or type2.is_symbol)
+ return (type2.is_boolean or type2.is_numeric
+ or is_string_type(type2) or type2.is_symbol)
if type1.is_symbol:
return not type2.is_symbol
if is_interface_like(type1):
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
index 847ba334683..e7c2cd0f615 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
@@ -4,6 +4,9 @@
import functools
import itertools
+import posixpath
+
+from blinkbuild.name_style_converter import NameStyleConverter
from .callback_function import CallbackFunction
from .callback_interface import CallbackInterface
@@ -13,8 +16,12 @@ from .database import Database
from .database import DatabaseBody
from .dictionary import Dictionary
from .enumeration import Enumeration
+from .exposure import ExposureMutable
+from .extended_attribute import ExtendedAttribute
+from .extended_attribute import ExtendedAttributesMutable
from .idl_type import IdlTypeFactory
from .interface import Interface
+from .interface import LegacyWindowAlias
from .ir_map import IRMap
from .make_copy import make_copy
from .namespace import Namespace
@@ -76,9 +83,15 @@ class IdlCompiler(object):
assert not self._did_run
self._did_run = True
+ # Remove the interface members that are specific to the old bindings
+ # generator, i.e. that are not necessary for (or even harmful to) the
+ # new bindings generator.
+ self._remove_legacy_interface_members()
+
# Merge partial definitions.
self._record_defined_in_partial_and_mixin()
self._propagate_extattrs_per_idl_fragment()
+ self._determine_blink_headers()
self._merge_partial_interface_likes()
self._merge_partial_dictionaries()
# Merge mixins.
@@ -88,10 +101,15 @@ class IdlCompiler(object):
# Process inheritances.
self._process_interface_inheritances()
+ self._copy_named_constructor_extattrs()
+
# Make groups of overloaded functions including inherited ones.
self._group_overloaded_functions()
+ self._propagate_extattrs_to_overload_group()
self._calculate_group_exposure()
+ self._fill_exposed_constructs()
+
self._sort_dictionary_members()
# Updates on IRs are finished. Create API objects.
@@ -107,6 +125,28 @@ class IdlCompiler(object):
return Database(self._db)
+ def _maybe_make_copy(self, ir):
+ # You can make this function return make_copy(ir) for debugging
+ # purpose, etc.
+ return ir # Skip copying as an optimization.
+
+ def _remove_legacy_interface_members(self):
+ old_irs = self._ir_map.irs_of_kinds(
+ IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.INTERFACE_MIXIN,
+ IRMap.IR.Kind.PARTIAL_INTERFACE,
+ IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN)
+
+ not_disabled = (
+ lambda x: 'DisableInNewIDLCompiler' not in x.extended_attributes)
+
+ self._ir_map.move_to_new_phase()
+
+ for old_ir in old_irs:
+ new_ir = make_copy(old_ir)
+ self._ir_map.add(new_ir)
+ new_ir.attributes = filter(not_disabled, new_ir.attributes)
+ new_ir.operations = filter(not_disabled, new_ir.operations)
+
def _record_defined_in_partial_and_mixin(self):
old_irs = self._ir_map.irs_of_kinds(
IRMap.IR.Kind.DICTIONARY, IRMap.IR.Kind.INTERFACE,
@@ -118,13 +158,19 @@ class IdlCompiler(object):
self._ir_map.move_to_new_phase()
for old_ir in old_irs:
- new_ir = make_copy(old_ir)
+ new_ir = self._maybe_make_copy(old_ir)
self._ir_map.add(new_ir)
+ is_partial = False
+ is_mixin = False
+ if 'LegacyTreatAsPartialInterface' in new_ir.extended_attributes:
+ is_partial = True
+ elif hasattr(new_ir, 'is_partial') and new_ir.is_partial:
+ is_partial = True
+ elif hasattr(new_ir, 'is_mixin') and new_ir.is_mixin:
+ is_mixin = True
for member in new_ir.iter_all_members():
- member.code_generator_info.set_defined_in_partial(
- hasattr(new_ir, 'is_partial') and new_ir.is_partial)
- member.code_generator_info.set_defined_in_mixin(
- hasattr(new_ir, 'is_mixin') and new_ir.is_mixin)
+ member.code_generator_info.set_defined_in_partial(is_partial)
+ member.code_generator_info.set_defined_in_mixin(is_mixin)
def _propagate_extattrs_per_idl_fragment(self):
def propagate_extattr(extattr_key_and_attr_name,
@@ -164,14 +210,14 @@ class IdlCompiler(object):
if not hasattr(ir, 'iter_all_members'):
return
if (only_to_members_of_partial_or_mixin
- and ((hasattr(ir, 'is_partial') and ir.is_partial) or
- (hasattr(ir, 'is_mixin') and ir.is_mixin))):
+ and not ((hasattr(ir, 'is_partial') and ir.is_partial) or
+ (hasattr(ir, 'is_mixin') and ir.is_mixin))):
return
for member in ir.iter_all_members():
apply_to(member)
def process_interface_like(ir):
- ir = make_copy(ir)
+ ir = self._maybe_make_copy(ir)
self._ir_map.add(ir)
propagate = functools.partial(propagate_extattr, ir=ir)
@@ -207,6 +253,33 @@ class IdlCompiler(object):
map(process_interface_like, old_irs)
+ def _determine_blink_headers(self):
+ irs = self._ir_map.irs_of_kinds(
+ IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.INTERFACE_MIXIN,
+ IRMap.IR.Kind.NAMESPACE, IRMap.IR.Kind.PARTIAL_INTERFACE,
+ IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN,
+ IRMap.IR.Kind.PARTIAL_NAMESPACE)
+
+ self._ir_map.move_to_new_phase()
+
+ for old_ir in irs:
+ new_ir = self._maybe_make_copy(old_ir)
+ self._ir_map.add(new_ir)
+
+ if (new_ir.is_mixin and 'LegacyTreatAsPartialInterface' not in
+ new_ir.extended_attributes):
+ continue
+
+ basepath, _ = posixpath.splitext(
+ new_ir.debug_info.location.filepath)
+ dirpath, filename = posixpath.split(basepath)
+ impl_class = new_ir.extended_attributes.value_of('ImplementedAs')
+ if impl_class:
+ filename = NameStyleConverter(impl_class).to_snake_case()
+ header = posixpath.join(dirpath,
+ posixpath.extsep.join([filename, 'h']))
+ new_ir.code_generator_info.set_blink_headers([header])
+
def _merge_partial_interface_likes(self):
irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
IRMap.IR.Kind.INTERFACE_MIXIN,
@@ -231,7 +304,7 @@ class IdlCompiler(object):
self._ir_map.move_to_new_phase()
- for identifier, old_dictionary in old_dictionaries.iteritems():
+ for identifier, old_dictionary in old_dictionaries.items():
new_dictionary = make_copy(old_dictionary)
self._ir_map.add(new_dictionary)
for partial_dictionary in old_partial_dictionaries.get(
@@ -248,7 +321,7 @@ class IdlCompiler(object):
self._ir_map.move_to_new_phase()
for old_ir in mixins:
- new_ir = make_copy(old_ir)
+ new_ir = self._maybe_make_copy(old_ir)
self._ir_map.add(new_ir)
ref_to_mixin = self._ref_to_idl_def_factory.create(
new_ir.identifier)
@@ -263,7 +336,7 @@ class IdlCompiler(object):
ir_sets_to_merge = [(interface, [
mixins[include.mixin_identifier]
for include in includes.get(identifier, [])
- ]) for identifier, interface in interfaces.iteritems()]
+ ]) for identifier, interface in interfaces.items()]
self._ir_map.move_to_new_phase()
@@ -275,33 +348,56 @@ class IdlCompiler(object):
self._ir_map.add(new_ir)
for ir in irs_to_be_merged:
to_be_merged = make_copy(ir)
- new_ir.add_components(to_be_merged.components)
+ if new_ir.is_mixin == to_be_merged.is_mixin:
+ new_ir.add_components(to_be_merged.components)
new_ir.debug_info.add_locations(
to_be_merged.debug_info.all_locations)
new_ir.attributes.extend(to_be_merged.attributes)
new_ir.constants.extend(to_be_merged.constants)
new_ir.operations.extend(to_be_merged.operations)
- def _process_interface_inheritances(self):
- def is_own_member(member):
- return 'Unforgeable' in member.extended_attributes
+ new_ir_headers = new_ir.code_generator_info.blink_headers
+ to_be_merged_headers = (
+ to_be_merged.code_generator_info.blink_headers)
+ if (new_ir_headers is not None
+ and to_be_merged_headers is not None):
+ new_ir_headers.extend(to_be_merged_headers)
- def create_inheritance_stack(obj, table):
+ def _process_interface_inheritances(self):
+ def create_inheritance_chain(obj, table):
if obj.inherited is None:
return [obj]
- return [obj] + create_inheritance_stack(
+ return [obj] + create_inheritance_chain(
table[obj.inherited.identifier], table)
+ inherited_ext_attrs = (
+ # (IDL extended attribute to be inherited,
+ # CodeGeneratorInfoMutable's set function)
+ ('ActiveScriptWrappable', 'set_is_active_script_wrappable'),
+ ('LegacyUnenumerableNamedProperties',
+ 'set_is_legacy_unenumerable_named_properties'),
+ )
+
+ def is_own_member(member):
+ return 'Unforgeable' in member.extended_attributes
+
old_interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE)
self._ir_map.move_to_new_phase()
- for old_interface in old_interfaces.itervalues():
+ for old_interface in old_interfaces.values():
new_interface = make_copy(old_interface)
self._ir_map.add(new_interface)
- inheritance_stack = create_inheritance_stack(
+ inheritance_chain = create_inheritance_chain(
old_interface, old_interfaces)
- for interface in inheritance_stack[1:]:
+
+ for interface in inheritance_chain:
+ for ext_attr, set_func in inherited_ext_attrs:
+ if ext_attr in interface.extended_attributes:
+ getattr(new_interface.code_generator_info,
+ set_func)(True)
+
+ for interface in inheritance_chain[1:]:
new_interface.attributes.extend([
make_copy(attribute) for attribute in interface.attributes
if is_own_member(attribute)
@@ -311,6 +407,28 @@ class IdlCompiler(object):
if is_own_member(operation)
])
+ def _copy_named_constructor_extattrs(self):
+ old_irs = self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE)
+
+ self._ir_map.move_to_new_phase()
+
+ def copy_extattrs(ext_attrs, ir):
+ if 'NamedConstructor_CallWith' in ext_attrs:
+ ir.extended_attributes.append(
+ ExtendedAttribute(
+ key='CallWith',
+ values=ext_attrs.values_of(
+ 'NamedConstructor_CallWith')))
+ if 'NamedConstructor_RaisesException' in ext_attrs:
+ ir.extended_attributes.append(
+ ExtendedAttribute(key='RaisesException'))
+
+ for old_ir in old_irs:
+ new_ir = self._maybe_make_copy(old_ir)
+ self._ir_map.add(new_ir)
+ for named_constructor_ir in new_ir.named_constructors:
+ copy_extattrs(new_ir.extended_attributes, named_constructor_ir)
+
def _group_overloaded_functions(self):
old_irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.CALLBACK_INTERFACE,
IRMap.IR.Kind.INTERFACE,
@@ -320,8 +438,9 @@ class IdlCompiler(object):
for old_ir in old_irs:
assert not old_ir.constructor_groups
+ assert not old_ir.named_constructor_groups
assert not old_ir.operation_groups
- new_ir = make_copy(old_ir)
+ new_ir = self._maybe_make_copy(old_ir)
self._ir_map.add(new_ir)
sort_key = lambda x: x.identifier
new_ir.constructor_groups = [
@@ -329,6 +448,12 @@ class IdlCompiler(object):
for identifier, constructors in itertools.groupby(
sorted(new_ir.constructors, key=sort_key), key=sort_key)
]
+ new_ir.named_constructor_groups = [
+ ConstructorGroup.IR(constructors=list(constructors))
+ for identifier, constructors in itertools.groupby(
+ sorted(new_ir.named_constructors, key=sort_key),
+ key=sort_key)
+ ]
new_ir.operation_groups = [
OperationGroup.IR(operations=list(operations))
for identifier, operations in itertools.groupby(
@@ -336,6 +461,33 @@ class IdlCompiler(object):
if identifier
]
+ def _propagate_extattrs_to_overload_group(self):
+ ANY_OF = ('CrossOrigin', 'Custom', 'LenientThis', 'NotEnumerable',
+ 'PerWorldBindings', 'SecureContext', 'Unforgeable',
+ 'Unscopable')
+
+ old_irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
+ IRMap.IR.Kind.NAMESPACE)
+
+ self._ir_map.move_to_new_phase()
+
+ for old_ir in old_irs:
+ new_ir = self._maybe_make_copy(old_ir)
+ self._ir_map.add(new_ir)
+
+ for group in itertools.chain(new_ir.constructor_groups,
+ new_ir.named_constructor_groups,
+ new_ir.operation_groups):
+ for key in ANY_OF:
+ if any(key in overload.extended_attributes
+ for overload in group):
+ group.extended_attributes.append(
+ ExtendedAttribute(key=key))
+ if all((overload.extended_attributes.value_of('Affects') ==
+ 'Nothing') for overload in group):
+ group.extended_attributes.append(
+ ExtendedAttribute(key='Affects', values='Nothing'))
+
def _calculate_group_exposure(self):
old_irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
IRMap.IR.Kind.NAMESPACE)
@@ -343,10 +495,12 @@ class IdlCompiler(object):
self._ir_map.move_to_new_phase()
for old_ir in old_irs:
- new_ir = make_copy(old_ir)
+ new_ir = self._maybe_make_copy(old_ir)
self._ir_map.add(new_ir)
- for group in new_ir.constructor_groups + new_ir.operation_groups:
+ for group in itertools.chain(new_ir.constructor_groups,
+ new_ir.named_constructor_groups,
+ new_ir.operation_groups):
exposures = map(lambda overload: overload.exposure, group)
# [Exposed]
@@ -393,6 +547,66 @@ class IdlCompiler(object):
]))
group.exposure.set_only_in_secure_contexts(flag_names)
+ def _fill_exposed_constructs(self):
+ old_interfaces = self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE)
+ old_namespaces = self._ir_map.irs_of_kind(IRMap.IR.Kind.NAMESPACE)
+
+ def make_legacy_window_alias(ir):
+ ext_attrs = ir.extended_attributes
+ identifier = Identifier(ext_attrs.value_of('LegacyWindowAlias'))
+ original = self._ref_to_idl_def_factory.create(ir.identifier)
+ extended_attributes = ExtendedAttributesMutable()
+ exposure = ExposureMutable()
+ if 'LegacyWindowAlias_Measure' in ext_attrs:
+ extended_attributes.append(
+ ExtendedAttribute(
+ key='Measure',
+ values=ext_attrs.value_of(
+ 'LegacyWindowAlias_Measure')))
+ if 'LegacyWindowAlias_RuntimeEnabled' in ext_attrs:
+ feature_name = ext_attrs.value_of(
+ 'LegacyWindowAlias_RuntimeEnabled')
+ extended_attributes.append(
+ ExtendedAttribute(
+ key='RuntimeEnabled', values=feature_name))
+ exposure.add_runtime_enabled_feature(feature_name)
+ return LegacyWindowAlias(
+ identifier=identifier,
+ original=original,
+ extended_attributes=extended_attributes,
+ exposure=exposure)
+
+ exposed_map = {} # global name: [construct's identifier...]
+ legacy_window_aliases = []
+ for ir in itertools.chain(old_interfaces, old_namespaces):
+ for pair in ir.exposure.global_names_and_features:
+ exposed_map.setdefault(pair.global_name,
+ []).append(ir.identifier)
+ if 'LegacyWindowAlias' in ir.extended_attributes:
+ legacy_window_aliases.append(make_legacy_window_alias(ir))
+
+ self._ir_map.move_to_new_phase()
+
+ for old_ir in old_interfaces:
+ new_ir = self._maybe_make_copy(old_ir)
+ self._ir_map.add(new_ir)
+
+ assert not new_ir.exposed_constructs
+ global_names = new_ir.extended_attributes.values_of('Global')
+ if not global_names:
+ continue
+ constructs = set()
+ for global_name in global_names:
+ constructs.update(exposed_map.get(global_name, []))
+ new_ir.exposed_constructs = map(
+ self._ref_to_idl_def_factory.create, sorted(constructs))
+
+ assert not new_ir.legacy_window_aliases
+ if new_ir.identifier != 'Window':
+ continue
+ new_ir.legacy_window_aliases = sorted(
+ legacy_window_aliases, key=lambda x: x.identifier)
+
def _sort_dictionary_members(self):
"""Sorts dictionary members in alphabetical order."""
old_irs = self._ir_map.irs_of_kind(IRMap.IR.Kind.DICTIONARY)
@@ -400,7 +614,7 @@ class IdlCompiler(object):
self._ir_map.move_to_new_phase()
for old_ir in old_irs:
- new_ir = make_copy(old_ir)
+ new_ir = self._maybe_make_copy(old_ir)
self._ir_map.add(new_ir)
new_ir.own_members.sort(key=lambda x: x.identifier)
@@ -455,9 +669,10 @@ class IdlCompiler(object):
idl_def = StubUserDefinedType(ref.identifier)
if isinstance(idl_def, UserDefinedType):
idl_type = self._idl_type_factory.definition_type(
- user_defined_type=idl_def)
+ reference_type=ref, user_defined_type=idl_def)
elif isinstance(idl_def, Typedef):
- idl_type = self._idl_type_factory.typedef_type(typedef=idl_def)
+ idl_type = self._idl_type_factory.typedef_type(
+ reference_type=ref, typedef=idl_def)
else:
assert False
ref.set_target_object(idl_type)
@@ -478,12 +693,20 @@ class IdlCompiler(object):
Returns an unique (but meaningless) key. Returns the same key for
the identical union types.
"""
- key_pieces = sorted([
- idl_type.syntactic_form
- for idl_type in union_type.flattened_member_types
- ])
- if union_type.does_include_nullable_type:
- key_pieces.append('type null') # something unique
+ # TODO(peria, yukishiino): Produce unique union names. Trying to
+ # produce the names compatible to the old bindings generator for
+ # the time being.
+ key_pieces = []
+
+ def flatten_member_types(idl_type):
+ idl_type = idl_type.unwrap()
+ if idl_type.is_union:
+ for member_type in idl_type.member_types:
+ flatten_member_types(member_type)
+ else:
+ key_pieces.append(idl_type.syntactic_form)
+
+ flatten_member_types(union_type)
return '|'.join(key_pieces)
grouped_unions = {} # {unique key: list of union types}
@@ -493,16 +716,15 @@ class IdlCompiler(object):
grouped_typedefs = {} # {unique key: list of typedefs to the union}
all_typedefs = self._db.find_by_kind(DatabaseBody.Kind.TYPEDEF)
- for typedef in all_typedefs.itervalues():
+ for typedef in all_typedefs.values():
if not typedef.idl_type.is_union:
continue
key = unique_key(typedef.idl_type)
grouped_typedefs.setdefault(key, []).append(typedef)
- for key, union_types in grouped_unions.iteritems():
+ for key, union_types in grouped_unions.items():
self._db.register(
DatabaseBody.Kind.UNION,
Union(
- Identifier(key), # dummy identifier
union_types=union_types,
typedef_backrefs=grouped_typedefs.get(key, [])))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
index 8c63a4998bd..1d7ae802659 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import exceptions
import functools
from blinkbuild.name_style_converter import NameStyleConverter
@@ -48,13 +47,8 @@ class IdlTypeFactory(object):
def __init__(self):
self._idl_types = []
# Factory to initialize instances of ReferenceType.
- attrs_to_be_proxied = (
- set(RefById.get_all_attributes(IdlType)).difference(
- # attributes not to be proxied
- set(('debug_info', 'extended_attributes', 'is_optional',
- 'optionality'))))
self._ref_by_id_factory = RefByIdFactory(
- target_attrs_with_priority=attrs_to_be_proxied)
+ target_attrs_with_priority=RefById.get_all_attributes(IdlType))
# |_is_frozen| is initially False and you can create new instances of
# IdlType. The first invocation of |for_each| freezes the factory and
# you can no longer create a new instance of IdlType.
@@ -167,7 +161,8 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
pass_key=None):
assert isinstance(is_optional, bool)
assert pass_key is _IDL_TYPE_PASS_KEY
- WithExtendedAttributes.__init__(self, extended_attributes)
+ WithExtendedAttributes.__init__(
+ self, extended_attributes, readonly=True)
WithDebugInfo.__init__(self, debug_info)
self._is_optional = is_optional
@@ -182,7 +177,7 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
return not self == other
def __hash__(self):
- raise exceptions.NotImplementedError()
+ raise NotImplementedError()
def make_copy(self, memo):
return self
@@ -192,7 +187,7 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
"""
Returns a text representation of the type in the form of Web IDL syntax.
"""
- raise exceptions.NotImplementedError()
+ raise NotImplementedError()
@property
def type_name(self):
@@ -201,7 +196,23 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
https://heycam.github.io/webidl/#dfn-type-name
Note that a type name is not necessarily unique.
"""
- raise exceptions.NotImplementedError()
+ return '{}{}'.format(
+ self.type_name_without_extended_attributes, ''.join(
+ sorted(self.effective_annotations.keys())))
+
+ @property
+ def type_name_with_extended_attribute_key_values(self):
+ name_pieces = []
+ name_pieces.append(self.type_name_without_extended_attributes)
+ annotations = self.effective_annotations
+ for key in sorted(annotations.keys()):
+ name_pieces.append(key)
+ name_pieces.extend(annotations.values_of(key))
+ return ''.join(name_pieces)
+
+ @property
+ def type_name_without_extended_attributes(self):
+ raise NotImplementedError()
@property
def keyword_typename(self):
@@ -220,8 +231,16 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
In case of x.apply_to_all_composing_elements(callback), |callback| will
be recursively called back on x, x.inner_type, x.element_type,
x.result_type.original_type, etc. if any.
+
+ If |callback| raises a StopIteration, then this function stops
+ traversing deeper than this type (inner type, etc.), however, siblings
+ are still traversed. E.g. For record<K, V>, raising a StopIteration at
+ K doesn't prevent from traversing V.
"""
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
def unwrap(self, nullable=None, typedef=None, variadic=None):
"""
@@ -231,6 +250,7 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
Args:
nullable:
typedef:
+ variadic:
All these arguments take tri-state value: True, False, or None.
True unwraps that type, False stops unwrapping that type. All
of specified arguments' values must be consistent, and mixture
@@ -245,25 +265,51 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
}
value_counts = {None: 0, False: 0, True: 0}
- for value in switches.itervalues():
+ for value in switches.values():
assert value is None or isinstance(value, bool)
value_counts[value] += 1
assert value_counts[False] == 0 or value_counts[True] == 0, (
"Specify only True or False arguments. Unspecified arguments are "
"automatically set to the opposite value.")
default = value_counts[True] == 0
- for arg, value in switches.iteritems():
+ for arg, value in switches.items():
if value is None:
switches[arg] = default
return self._unwrap(switches)
@property
+ def effective_annotations(self):
+ """
+ Returns the extended attributes associated with this IDL type.
+ https://heycam.github.io/webidl/#idl-type-extended-attribute-associated-with
+
+ For example, given the following IDL fragments,
+
+ typedef [ExtAttr1] long NewLong;
+ void f([ExtAttr2] NewLong arg);
+
+ arg.idl_type.extended_attributes returns [ExtAttr2],
+ arg.idl_type.unwrap().extended_attributes returns [ExtAttr1], and
+ arg.idl_type.effective_annotations returns [ExtAttr1, ExtAttr2].
+ """
+ return self.extended_attributes
+
+ @property
def does_include_nullable_type(self):
"""
- Returns True if |self| includes a nulllable type.
+ Returns True if this type includes a nulllable type.
https://heycam.github.io/webidl/#dfn-includes-a-nullable-type
- @return bool
+ """
+ return False
+
+ @property
+ def does_include_nullable_or_dict(self):
+ """
+ Returns True if this type includes a nullable type or a dictionary type.
+
+ IdlType's own definition of "includes a dictionary type" just follows
+ the definition of "includes a nullable type".
"""
return False
@@ -307,6 +353,11 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
return False
@property
+ def is_array_buffer_view(self):
+ """Returns True if this is ArrayBufferView."""
+ return False
+
+ @property
def is_data_view(self):
"""Returns True if this is DataView."""
return False
@@ -414,11 +465,6 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
return False
@property
- def is_annotated(self):
- """Returns True if this is annotated."""
- return bool(self.extended_attributes)
-
- @property
def is_optional(self):
"""
Returns True if this type is used for a non-required dictionary member
@@ -506,6 +552,15 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
"""
return None
+ @property
+ def union_definition_object(self):
+ """
+ Returns an object that represents an union or None.
+
+ Note that a returned object is not an IdlType. It's of type Union.
+ """
+ return None
+
def _format_syntactic_form(self, syntactic_form_inner):
"""Helper function to implement |syntactic_form|."""
optional_form = 'optional ' if self.is_optional else ''
@@ -514,11 +569,6 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
return '{}{}{}'.format(optional_form, ext_attr_form,
syntactic_form_inner)
- def _format_type_name(self, type_name_inner):
- """Helper function to implement |type_name|."""
- return '{}{}'.format(type_name_inner, ''.join(
- sorted(self.extended_attributes.keys())))
-
def _unwrap(self, switches):
return self
@@ -539,7 +589,17 @@ class SimpleType(IdlType):
_TYPED_ARRAY_TYPES = ('Int8Array', 'Int16Array', 'Int32Array',
'Uint8Array', 'Uint16Array', 'Uint32Array',
'Uint8ClampedArray', 'Float32Array', 'Float64Array')
- _BUFFER_SOURCE_TYPES = ('ArrayBuffer', 'DataView') + _TYPED_ARRAY_TYPES
+ # ArrayBufferView is not defined as a buffer source type in Web IDL, it's
+ # defined as an union type of all typed array types. However, practically
+ # it's much more convenient and reasonable for most of (if not all) use
+ # cases to treat ArrayBufferView as a buffer source type than as an union
+ # type.
+ # https://heycam.github.io/webidl/#ArrayBufferView
+ #
+ # Note that BufferSource is an union type as defined in Web IDL.
+ # https://heycam.github.io/webidl/#BufferSource
+ _BUFFER_SOURCE_TYPES = (
+ ('ArrayBuffer', 'ArrayBufferView', 'DataView') + _TYPED_ARRAY_TYPES)
_MISC_TYPES = ('any', 'boolean', 'object', 'symbol', 'void')
_VALID_TYPES = set(_NUMERIC_TYPES + _STRING_TYPES + _BUFFER_SOURCE_TYPES +
_MISC_TYPES)
@@ -567,16 +627,14 @@ class SimpleType(IdlType):
def __hash__(self):
return hash(self._name)
- # IdlType overrides
@property
def syntactic_form(self):
return self._format_syntactic_form(self._name)
@property
- def type_name(self):
+ def type_name_without_extended_attributes(self):
name = 'String' if self._name == 'DOMString' else self._name
- return self._format_type_name(
- NameStyleConverter(name).to_upper_camel_case())
+ return NameStyleConverter(name).to_upper_camel_case()
@property
def keyword_typename(self):
@@ -611,6 +669,10 @@ class SimpleType(IdlType):
return self._name == 'ArrayBuffer'
@property
+ def is_array_buffer_view(self):
+ return self._name == 'ArrayBufferView'
+
+ @property
def is_data_view(self):
return self._name == 'DataView'
@@ -672,6 +734,9 @@ class ReferenceType(IdlType, RefById):
def __hash__(self):
return hash(self.identifier)
+ def _unwrap(self, switches):
+ return self.target_object._unwrap(switches)
+
class DefinitionType(IdlType, WithIdentifier):
"""
@@ -682,14 +747,14 @@ class DefinitionType(IdlType, WithIdentifier):
TypedefType and UnionType respectively.
"""
- def __init__(self,
- user_defined_type,
- debug_info=None,
- pass_key=None):
+ def __init__(self, reference_type, user_defined_type, pass_key=None):
+ assert isinstance(reference_type, ReferenceType)
assert isinstance(user_defined_type, UserDefinedType)
IdlType.__init__(
self,
- debug_info=debug_info,
+ is_optional=reference_type.is_optional,
+ extended_attributes=reference_type.extended_attributes,
+ debug_info=reference_type.debug_info,
pass_key=pass_key)
WithIdentifier.__init__(self, user_defined_type.identifier)
self._type_definition_object = user_defined_type
@@ -701,20 +766,19 @@ class DefinitionType(IdlType, WithIdentifier):
def __hash__(self):
return hash(self.identifier)
- # IdlType overrides
@property
def syntactic_form(self):
- assert not self.extended_attributes
- assert not self.is_optional
- return self.identifier
+ return self._format_syntactic_form(self.identifier)
@property
- def type_name(self):
- assert not self.extended_attributes
- assert not self.is_optional
+ def type_name_without_extended_attributes(self):
return self.identifier
@property
+ def does_include_nullable_or_dict(self):
+ return self.is_dictionary
+
+ @property
def is_interface(self):
return self.type_definition_object.is_interface
@@ -750,14 +814,14 @@ class TypedefType(IdlType, WithIdentifier):
can track down the typedef'ed type to |original_type|.
"""
- def __init__(self,
- typedef,
- debug_info=None,
- pass_key=None):
+ def __init__(self, reference_type, typedef, pass_key=None):
+ assert isinstance(reference_type, ReferenceType)
assert isinstance(typedef, Typedef)
IdlType.__init__(
self,
- debug_info=debug_info,
+ is_optional=reference_type.is_optional,
+ extended_attributes=reference_type.extended_attributes,
+ debug_info=reference_type.debug_info,
pass_key=pass_key)
WithIdentifier.__init__(self, typedef.identifier)
self._typedef = typedef
@@ -769,28 +833,40 @@ class TypedefType(IdlType, WithIdentifier):
def __hash__(self):
return hash(self.identifier)
- # IdlType overrides
@property
def syntactic_form(self):
- assert not self.extended_attributes
- assert not self.is_optional
- return self.identifier
+ return self._format_syntactic_form(self.identifier)
@property
- def type_name(self):
- assert not self.extended_attributes
- assert not self.is_optional
- return self.original_type.type_name
+ def type_name_without_extended_attributes(self):
+ return self.original_type.type_name_without_extended_attributes
def apply_to_all_composing_elements(self, callback):
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
self.original_type.apply_to_all_composing_elements(callback)
@property
+ def effective_annotations(self):
+ original_annotations = self.original_type.effective_annotations
+ if not self.extended_attributes:
+ return original_annotations
+ if not original_annotations:
+ return self.extended_attributes
+ return ExtendedAttributes(
+ list(self.extended_attributes) + list(original_annotations))
+
+ @property
def does_include_nullable_type(self):
return self.original_type.does_include_nullable_type
@property
+ def does_include_nullable_or_dict(self):
+ return self.original_type.does_include_nullable_or_dict
+
+ @property
def is_typedef(self):
return True
@@ -827,9 +903,11 @@ class _ArrayLikeType(IdlType):
def __hash__(self):
return hash((self.__class__, self.element_type))
- # IdlType overrides
def apply_to_all_composing_elements(self, callback):
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
self.element_type.apply_to_all_composing_elements(callback)
@property
@@ -854,16 +932,14 @@ class SequenceType(_ArrayLikeType):
debug_info=debug_info,
pass_key=pass_key)
- # IdlType overrides
@property
def syntactic_form(self):
return self._format_syntactic_form('sequence<{}>'.format(
self.element_type.syntactic_form))
@property
- def type_name(self):
- return self._format_type_name('{}Sequence'.format(
- self.element_type.type_name))
+ def type_name_without_extended_attributes(self):
+ return '{}Sequence'.format(self.element_type.type_name)
@property
def is_sequence(self):
@@ -887,16 +963,14 @@ class FrozenArrayType(_ArrayLikeType):
debug_info=debug_info,
pass_key=pass_key)
- # IdlType overrides
@property
def syntactic_form(self):
return self._format_syntactic_form('FrozenArray<{}>'.format(
self.element_type.syntactic_form))
@property
- def type_name(self):
- return self._format_type_name('{}Array'.format(
- self.element_type.type_name))
+ def type_name_without_extended_attributes(self):
+ return '{}Array'.format(self.element_type.type_name)
@property
def is_frozen_array(self):
@@ -906,17 +980,10 @@ class FrozenArrayType(_ArrayLikeType):
class VariadicType(_ArrayLikeType):
"""Represents a type used for variadic arguments."""
- def __init__(self,
- element_type,
- debug_info=None,
- pass_key=None):
+ def __init__(self, element_type, debug_info=None, pass_key=None):
_ArrayLikeType.__init__(
- self,
- element_type,
- debug_info=debug_info,
- pass_key=pass_key)
+ self, element_type, debug_info=debug_info, pass_key=pass_key)
- # IdlType overrides
@property
def syntactic_form(self):
assert not self.extended_attributes
@@ -924,10 +991,11 @@ class VariadicType(_ArrayLikeType):
return '{}...'.format(self.element_type.syntactic_form)
@property
- def type_name(self):
+ def type_name_without_extended_attributes(self):
# Blink-specific expansion of type name
# The type name of a variadic type is the concatenation of the type
# name of the element type and the string "Variadic".
+ assert not self.extended_attributes
return '{}Variadic'.format(self.element_type.type_name)
@property
@@ -968,19 +1036,21 @@ class RecordType(IdlType):
def __hash__(self):
return hash((self.__class__, self.key_type, self.value_type))
- # IdlType overrides
@property
def syntactic_form(self):
return self._format_syntactic_form('record<{}, {}>'.format(
self.key_type.syntactic_form, self.value_type.syntactic_form))
@property
- def type_name(self):
- return self._format_type_name('{}{}Record'.format(
- self.key_type.type_name, self.value_type.type_name))
+ def type_name_without_extended_attributes(self):
+ return '{}{}Record'.format(self.key_type.type_name,
+ self.value_type.type_name)
def apply_to_all_composing_elements(self, callback):
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
self.key_type.apply_to_all_composing_elements(callback)
self.value_type.apply_to_all_composing_elements(callback)
@@ -1022,19 +1092,20 @@ class PromiseType(IdlType):
def __hash__(self):
return hash((self.__class__, self.result_type))
- # IdlType overrides
@property
def syntactic_form(self):
return self._format_syntactic_form('Promise<{}>'.format(
self.result_type.syntactic_form))
@property
- def type_name(self):
- return self._format_type_name('{}Promise'.format(
- self.result_type.type_name))
+ def type_name_without_extended_attributes(self):
+ return '{}Promise'.format(self.result_type.type_name)
def apply_to_all_composing_elements(self, callback):
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
self.result_type.apply_to_all_composing_elements(callback)
@property
@@ -1043,10 +1114,7 @@ class PromiseType(IdlType):
@property
def result_type(self):
- """
- Returns the result type.
- @return IdlType
- """
+ """Returns the result type."""
return self._result_type
@@ -1068,6 +1136,7 @@ class UnionType(IdlType):
debug_info=debug_info,
pass_key=pass_key)
self._member_types = tuple(member_types)
+ self._union_definition_object = None
def __eq__(self, other):
"""
@@ -1089,19 +1158,20 @@ class UnionType(IdlType):
functools.reduce(lambda x, idl_type: x + hash(idl_type),
self.member_types, 0)))
- # IdlType overrides
@property
def syntactic_form(self):
return self._format_syntactic_form('({})'.format(' or '.join(
[member.syntactic_form for member in self.member_types])))
@property
- def type_name(self):
- return self._format_type_name('Or'.join(
- [member.type_name for member in self.member_types]))
+ def type_name_without_extended_attributes(self):
+ return 'Or'.join([member.type_name for member in self.member_types])
def apply_to_all_composing_elements(self, callback):
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
for member_type in self.member_types:
member_type.apply_to_all_composing_elements(callback)
@@ -1111,6 +1181,11 @@ class UnionType(IdlType):
member.does_include_nullable_type for member in self.member_types)
@property
+ def does_include_nullable_or_dict(self):
+ return any(member.does_include_nullable_or_dict
+ for member in self.member_types)
+
+ @property
def is_union(self):
return True
@@ -1134,6 +1209,17 @@ class UnionType(IdlType):
return set(flatten(self))
+ @property
+ def union_definition_object(self):
+ return self._union_definition_object
+
+ def set_union_definition_object(self, union_definition_object):
+ # In Python2, we need to avoid circular imports.
+ from .union import Union
+ assert isinstance(union_definition_object, Union)
+ assert self._union_definition_object is None
+ self._union_definition_object = union_definition_object
+
class NullableType(IdlType):
"""https://heycam.github.io/webidl/#idl-nullable-type"""
@@ -1160,35 +1246,44 @@ class NullableType(IdlType):
def __hash__(self):
return hash((self.__class__, self.inner_type))
- # IdlType overrides
@property
def syntactic_form(self):
assert not self.extended_attributes
return '{}?'.format(self.inner_type.syntactic_form)
@property
- def type_name(self):
- assert not self.extended_attributes
+ def type_name_without_extended_attributes(self):
# https://heycam.github.io/webidl/#idl-annotated-types
# Web IDL seems not supposing a case of [X] ([Y] Type)?, i.e. something
# like [X] nullable<[Y] Type>, which should turn into "TypeYOrNullX".
#
# In case of '[Clamp] long?', it's interpreted as '([Clamp] long)?' but
# the type name must be "LongOrNullClamp" instead of "LongClampOrNull".
- name = self.inner_type.type_name
- ext_attrs = ''.join(sorted(self.inner_type.extended_attributes.keys()))
- sep_index = len(name) - len(ext_attrs)
- return '{}OrNull{}'.format(name[0:sep_index], name[sep_index:])
+ assert not self.extended_attributes
+ return '{}OrNull'.format(
+ self.inner_type.type_name_without_extended_attributes)
def apply_to_all_composing_elements(self, callback):
- callback(self)
+ try:
+ callback(self)
+ except StopIteration:
+ return
self.inner_type.apply_to_all_composing_elements(callback)
@property
+ def effective_annotations(self):
+ assert not self.extended_attributes
+ return self.inner_type.effective_annotations
+
+ @property
def does_include_nullable_type(self):
return True
@property
+ def does_include_nullable_or_dict(self):
+ return True
+
+ @property
def is_nullable(self):
return True
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py
index b8e71989991..b3d097a7442 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py
@@ -54,7 +54,7 @@ class IdlTypesTest(unittest.TestCase):
ext_attrs = ExtendedAttributes([ExtendedAttribute('Clamp')])
annotated_type = factory.simple_type(
'short', extended_attributes=ext_attrs)
- self.assertTrue(annotated_type.is_annotated)
+ self.assertTrue(annotated_type.extended_attributes)
self.assertTrue(annotated_type.is_numeric)
optional_type = factory.simple_type('DOMString', is_optional=True)
@@ -63,7 +63,7 @@ class IdlTypesTest(unittest.TestCase):
annotated_optional = factory.simple_type(
'long', is_optional=True, extended_attributes=ext_attrs)
- self.assertTrue(annotated_optional.is_annotated)
+ self.assertTrue(annotated_optional.extended_attributes)
self.assertTrue(annotated_optional.is_optional)
self.assertTrue(annotated_optional.is_numeric)
@@ -83,7 +83,7 @@ class IdlTypesTest(unittest.TestCase):
'void': 'Void',
'symbol': 'Symbol',
}
- for name, expect in type_names.iteritems():
+ for name, expect in type_names.items():
self.assertEqual(expect, factory.simple_type(name).type_name)
short_type = factory.simple_type('short')
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
index f3f81408a0e..ae67aab3fc9 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
@@ -9,6 +9,7 @@ from .composition_parts import WithComponent
from .composition_parts import WithDebugInfo
from .composition_parts import WithExposure
from .composition_parts import WithExtendedAttributes
+from .composition_parts import WithIdentifier
from .composition_parts import WithOwner
from .constant import Constant
from .constructor import Constructor
@@ -37,7 +38,9 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
attributes=None,
constants=None,
constructors=None,
+ named_constructors=None,
operations=None,
+ indexed_and_named_properties=None,
stringifier=None,
iterable=None,
maplike=None,
@@ -52,7 +55,11 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
assert constants is None or isinstance(constants, (list, tuple))
assert constructors is None or isinstance(constructors,
(list, tuple))
+ assert named_constructors is None or isinstance(
+ named_constructors, (list, tuple))
assert operations is None or isinstance(operations, (list, tuple))
+ assert indexed_and_named_properties is None or isinstance(
+ indexed_and_named_properties, IndexedAndNamedProperties.IR)
assert stringifier is None or isinstance(stringifier,
Stringifier.IR)
assert iterable is None or isinstance(iterable, Iterable)
@@ -62,6 +69,7 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
attributes = attributes or []
constants = constants or []
constructors = constructors or []
+ named_constructors = named_constructors or []
operations = operations or []
assert all(
isinstance(attribute, Attribute.IR)
@@ -72,6 +80,9 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
isinstance(constructor, Constructor.IR)
for constructor in constructors)
assert all(
+ isinstance(named_constructor, Constructor.IR)
+ for named_constructor in named_constructors)
+ assert all(
isinstance(operation, Operation.IR)
for operation in operations)
@@ -100,8 +111,13 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
self.constants = list(constants)
self.constructors = list(constructors)
self.constructor_groups = []
+ self.named_constructors = list(named_constructors)
+ self.named_constructor_groups = []
self.operations = list(operations)
self.operation_groups = []
+ self.exposed_constructs = []
+ self.legacy_window_aliases = []
+ self.indexed_and_named_properties = indexed_and_named_properties
self.stringifier = stringifier
self.iterable = iterable
self.maplike = maplike
@@ -114,6 +130,8 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
yield constant
for constructor in self.constructors:
yield constructor
+ for named_constructor in self.named_constructors:
+ yield named_constructor
for operation in self.operations:
yield operation
@@ -123,7 +141,7 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithComponent.__init__(self, ir, readonly=True)
@@ -144,24 +162,43 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
])
self._constructor_groups = tuple([
ConstructorGroup(
- constructor_group_ir,
- filter(
- lambda x: x.identifier == constructor_group_ir.identifier,
- self._constructors),
- owner=self) for constructor_group_ir in ir.constructor_groups
+ group_ir,
+ filter(lambda x: x.identifier == group_ir.identifier,
+ self._constructors),
+ owner=self) for group_ir in ir.constructor_groups
])
assert len(self._constructor_groups) <= 1
+ self._named_constructors = tuple([
+ Constructor(named_constructor_ir, owner=self)
+ for named_constructor_ir in ir.named_constructors
+ ])
+ self._named_constructor_groups = tuple([
+ ConstructorGroup(
+ group_ir,
+ filter(lambda x: x.identifier == group_ir.identifier,
+ self._named_constructors),
+ owner=self) for group_ir in ir.named_constructor_groups
+ ])
self._operations = tuple([
Operation(operation_ir, owner=self)
for operation_ir in ir.operations
])
self._operation_groups = tuple([
OperationGroup(
- operation_group_ir,
- filter(lambda x: x.identifier == operation_group_ir.identifier,
+ group_ir,
+ filter(lambda x: x.identifier == group_ir.identifier,
self._operations),
- owner=self) for operation_group_ir in ir.operation_groups
+ owner=self) for group_ir in ir.operation_groups
])
+ self._exposed_constructs = tuple(ir.exposed_constructs)
+ self._legacy_window_aliases = tuple(ir.legacy_window_aliases)
+ self._indexed_and_named_properties = None
+ if ir.indexed_and_named_properties:
+ operations = filter(
+ lambda x: x.is_indexed_or_named_property_operation,
+ self._operations)
+ self._indexed_and_named_properties = IndexedAndNamedProperties(
+ ir.indexed_and_named_properties, operations, owner=self)
self._stringifier = None
if ir.stringifier:
operations = filter(lambda x: x.is_stringifier, self._operations)
@@ -205,6 +242,17 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
interface = interface.inherited
return result
+ def does_implement(self, identifier):
+ """
+ Returns True if this is or inherits from the given interface.
+ """
+ assert isinstance(identifier, str)
+
+ for interface in self.inclusive_inherited_interfaces:
+ if interface.identifier == identifier:
+ return True
+ return False
+
@property
def attributes(self):
"""
@@ -232,6 +280,16 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
return self._constructor_groups
@property
+ def named_constructors(self):
+ """Returns named constructors."""
+ return self._named_constructors
+
+ @property
+ def named_constructor_groups(self):
+ """Returns groups of overloaded named constructors."""
+ return self._named_constructor_groups
+
+ @property
def operations(self):
"""
Returns all operations, including special operations without an
@@ -254,38 +312,22 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
return self._operation_groups
@property
- def named_constructor(self):
- """Returns a named constructor or None."""
- assert False, "Not implemented yet."
-
- @property
- def exposed_interfaces(self):
+ def exposed_constructs(self):
"""
- Returns a tuple of interfaces that are exposed to this interface, if
- this is a global interface. Returns None otherwise.
+ Returns a list of the constructs that are exposed on this global object.
"""
- assert False, "Not implemented yet."
+ return tuple(
+ map(lambda ref: ref.target_object, self._exposed_constructs))
- # Special operations
@property
- def indexed_property_handler(self):
- """
- Returns a set of handlers (getter/setter/deleter) for the indexed
- property.
- @return IndexedPropertyHandler?
- """
- # TODO: Include anonymous handlers of ancestors. https://crbug.com/695972
- assert False, "Not implemented yet."
+ def legacy_window_aliases(self):
+ """Returns a list of properties exposed as [LegacyWindowAlias]."""
+ return self._legacy_window_aliases
@property
- def named_property_handler(self):
- """
- Returns a set of handlers (getter/setter/deleter) for the named
- property.
- @return NamedPropertyHandler?
- """
- # TODO: Include anonymous handlers of ancestors. https://crbug.com/695972
- assert False, "Not implemented yet."
+ def indexed_and_named_properties(self):
+ """Returns a IndexedAndNamedProperties or None."""
+ return self._indexed_and_named_properties
@property
def stringifier(self):
@@ -313,6 +355,183 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
return True
+class LegacyWindowAlias(WithIdentifier, WithExtendedAttributes, WithExposure):
+ """
+ Represents a property exposed on a Window object as [LegacyWindowAlias].
+ """
+
+ def __init__(self, identifier, original, extended_attributes, exposure):
+ assert isinstance(original, RefById)
+
+ WithIdentifier.__init__(self, identifier)
+ WithExtendedAttributes.__init__(
+ self, extended_attributes, readonly=True)
+ WithExposure.__init__(self, exposure, readonly=True)
+
+ self._original = original
+
+ @property
+ def original(self):
+ """Returns the original object of this alias."""
+ return self._original.target_object
+
+
+class IndexedAndNamedProperties(WithOwner, WithDebugInfo):
+ """
+ Represents a set of indexed/named getter/setter/deleter.
+
+ https://heycam.github.io/webidl/#idl-indexed-properties
+ https://heycam.github.io/webidl/#idl-named-properties
+ """
+
+ class IR(WithDebugInfo):
+ def __init__(self, operations, debug_info=None):
+ assert isinstance(operations, (list, tuple))
+ assert all(
+ isinstance(operation, Operation.IR)
+ for operation in operations)
+
+ WithDebugInfo.__init__(self, debug_info)
+
+ self.indexed_getter = None
+ self.indexed_setter = None
+ self.named_getter = None
+ self.named_setter = None
+ self.named_deleter = None
+
+ for operation in operations:
+ arg1_type = operation.arguments[0].idl_type
+ if arg1_type.is_integer:
+ if operation.is_getter:
+ assert self.indexed_getter is None
+ self.indexed_getter = operation
+ elif operation.is_setter:
+ assert self.indexed_setter is None
+ self.indexed_setter = operation
+ else:
+ assert False
+ elif arg1_type.is_string:
+ if operation.is_getter:
+ assert self.named_getter is None
+ self.named_getter = operation
+ elif operation.is_setter:
+ assert self.named_setter is None
+ self.named_setter = operation
+ elif operation.is_deleter:
+ assert self.named_deleter is None
+ self.named_deleter = operation
+ else:
+ assert False
+ else:
+ assert False
+
+ def __init__(self, ir, operations, owner):
+ assert isinstance(ir, IndexedAndNamedProperties.IR)
+ assert isinstance(operations, (list, tuple))
+ assert all(
+ isinstance(operation, Operation) for operation in operations)
+
+ WithOwner.__init__(self, owner)
+ WithDebugInfo.__init__(self, ir)
+
+ self._own_indexed_getter = None
+ self._own_indexed_setter = None
+ self._own_named_getter = None
+ self._own_named_setter = None
+ self._own_named_deleter = None
+
+ for operation in operations:
+ arg1_type = operation.arguments[0].idl_type
+ if arg1_type.is_integer:
+ if operation.is_getter:
+ assert self._own_indexed_getter is None
+ self._own_indexed_getter = operation
+ elif operation.is_setter:
+ assert self._own_indexed_setter is None
+ self._own_indexed_setter = operation
+ else:
+ assert False
+ elif arg1_type.is_string:
+ if operation.is_getter:
+ assert self._own_named_getter is None
+ self._own_named_getter = operation
+ elif operation.is_setter:
+ assert self._own_named_setter is None
+ self._own_named_setter = operation
+ elif operation.is_deleter:
+ assert self._own_named_deleter is None
+ self._own_named_deleter = operation
+ else:
+ assert False
+ else:
+ assert False
+
+ @property
+ def has_indexed_properties(self):
+ return self.indexed_getter or self.indexed_setter
+
+ @property
+ def has_named_properties(self):
+ return self.named_getter or self.named_setter or self.named_deleter
+
+ @property
+ def is_named_property_enumerable(self):
+ named_getter = self.named_getter
+ return bool(named_getter
+ and 'NotEnumerable' not in named_getter.extended_attributes
+ and 'LegacyUnenumerableNamedProperties' not in self.owner.
+ extended_attributes)
+
+ @property
+ def indexed_getter(self):
+ return self._find_accessor('own_indexed_getter')
+
+ @property
+ def indexed_setter(self):
+ return self._find_accessor('own_indexed_setter')
+
+ @property
+ def named_getter(self):
+ return self._find_accessor('own_named_getter')
+
+ @property
+ def named_setter(self):
+ return self._find_accessor('own_named_setter')
+
+ @property
+ def named_deleter(self):
+ return self._find_accessor('own_named_deleter')
+
+ @property
+ def own_indexed_getter(self):
+ return self._own_indexed_getter
+
+ @property
+ def own_indexed_setter(self):
+ return self._own_indexed_setter
+
+ @property
+ def own_named_getter(self):
+ return self._own_named_getter
+
+ @property
+ def own_named_setter(self):
+ return self._own_named_setter
+
+ @property
+ def own_named_deleter(self):
+ return self._own_named_deleter
+
+ def _find_accessor(self, attr):
+ for interface in self.owner.inclusive_inherited_interfaces:
+ props = interface.indexed_and_named_properties
+ if props:
+ accessor = getattr(props, attr)
+ if accessor:
+ return accessor
+ return None
+
+
class Stringifier(WithOwner, WithDebugInfo):
"""https://heycam.github.io/webidl/#idl-stringifiers"""
@@ -349,10 +568,7 @@ class Stringifier(WithOwner, WithDebugInfo):
class Iterable(WithDebugInfo):
"""https://heycam.github.io/webidl/#idl-iterable"""
- def __init__(self,
- key_type=None,
- value_type=None,
- debug_info=None):
+ def __init__(self, key_type=None, value_type=None, debug_info=None):
assert key_type is None or isinstance(key_type, IdlType)
# iterable is declared in either form of
# iterable<value_type>
@@ -423,10 +639,7 @@ class Maplike(WithDebugInfo):
class Setlike(WithDebugInfo):
"""https://heycam.github.io/webidl/#idl-setlike"""
- def __init__(self,
- value_type,
- is_readonly=False,
- debug_info=None):
+ def __init__(self, value_type, is_readonly=False, debug_info=None):
assert isinstance(value_type, IdlType)
assert isinstance(is_readonly, bool)
@@ -450,55 +663,3 @@ class Setlike(WithDebugInfo):
@return bool
"""
return self._is_readonly
-
-
-class IndexedPropertyHandler(object):
- @property
- def getter(self):
- """
- Returns an Operation for indexed property getter.
- @return Operation?
- """
- assert False, "Not implemented yet."
-
- @property
- def setter(self):
- """
- Returns an Operation for indexed property setter.
- @return Operation?
- """
- assert False, "Not implemented yet."
-
- @property
- def deleter(self):
- """
- Returns an Operation for indexed property deleter.
- @return Operation?
- """
- assert False, "Not implemented yet."
-
-
-class NamedPropertyHandler(object):
- @property
- def getter(self):
- """
- Returns an Operation for named property getter.
- @return Operation?
- """
- assert False, "Not implemented yet."
-
- @property
- def setter(self):
- """
- Returns an Operation for named property setter.
- @return Operation?
- """
- assert False, "Not implemented yet."
-
- @property
- def deleter(self):
- """
- Returns an Operation for named property deleter.
- @return Operation?
- """
- assert False, "Not implemented yet."
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
index bc69ffff13e..5f2fe5f13aa 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
@@ -20,6 +20,7 @@ from .extended_attribute import ExtendedAttribute
from .extended_attribute import ExtendedAttributes
from .idl_type import IdlTypeFactory
from .includes import Includes
+from .interface import IndexedAndNamedProperties
from .interface import Interface
from .interface import Iterable
from .interface import Maplike
@@ -114,6 +115,7 @@ class _IRBuilder(object):
constants = []
constructors = []
operations = []
+ indexed_and_named_property_operations = []
for member in members:
if isinstance(member, Attribute.IR):
attributes.append(member)
@@ -122,16 +124,24 @@ class _IRBuilder(object):
elif isinstance(member, Constructor.IR):
constructors.append(member)
elif isinstance(member, Operation.IR):
- if member.identifier:
- operations.append(member)
+ operations.append(member)
+ if member.is_getter or member.is_setter or member.is_deleter:
+ indexed_and_named_property_operations.append(member)
else:
assert False
+ named_constructors = self._build_named_constructors(node)
+
+ indexed_and_named_properties = None
+ if indexed_and_named_property_operations:
+ indexed_and_named_properties = IndexedAndNamedProperties.IR(
+ indexed_and_named_property_operations,
+ self._build_debug_info(node))
+
if stringifier:
operations.append(stringifier.operation)
if stringifier.attribute:
attributes.append(stringifier.attribute)
- # TODO(peria): Create indexed/named property handlers from |operations|.
return Interface.IR(
identifier=identifier,
@@ -141,7 +151,9 @@ class _IRBuilder(object):
attributes=attributes,
constants=constants,
constructors=constructors,
+ named_constructors=named_constructors,
operations=operations,
+ indexed_and_named_properties=indexed_and_named_properties,
stringifier=stringifier,
iterable=iterable,
maplike=maplike,
@@ -189,7 +201,7 @@ class _IRBuilder(object):
idl_type = self._take_type(child_nodes)
extended_attributes = self._take_extended_attributes(
child_nodes) or fallback_extended_attributes
- assert len(child_nodes) == 0
+ assert not child_nodes
return Attribute.IR(
identifier=Identifier(node.GetName()),
idl_type=idl_type,
@@ -223,10 +235,11 @@ class _IRBuilder(object):
arguments = self._take_arguments(child_nodes)
extended_attributes = self._take_extended_attributes(
child_nodes) or fallback_extended_attributes
- assert len(child_nodes) == 0
+ assert not child_nodes
return_type = self._idl_type_factory.reference_type(
interface_identifier)
return Constructor.IR(
+ identifier=None,
arguments=arguments,
return_type=return_type,
extended_attributes=extended_attributes,
@@ -239,12 +252,15 @@ class _IRBuilder(object):
return_type = self._take_type(child_nodes)
extended_attributes = self._take_extended_attributes(
child_nodes) or fallback_extended_attributes
- assert len(child_nodes) == 0
+ assert not child_nodes
return Operation.IR(
identifier=Identifier(node.GetName()),
arguments=arguments,
return_type=return_type,
is_static=bool(node.GetProperty('STATIC')),
+ is_getter=bool(node.GetProperty('GETTER')),
+ is_setter=bool(node.GetProperty('SETTER')),
+ is_deleter=bool(node.GetProperty('DELETER')),
extended_attributes=extended_attributes,
component=self._component,
debug_info=self._build_debug_info(node))
@@ -257,6 +273,37 @@ class _IRBuilder(object):
}
return build_functions[node.GetClass()](node)
+ def _build_named_constructors(self, node):
+ assert node.GetClass() == 'Interface'
+ named_constructors = []
+
+ for child in node.GetChildren():
+ if child.GetClass() == 'ExtAttributes':
+ interface_ext_attrs = child.GetChildren()
+ break
+ else:
+ return named_constructors
+
+ for ext_attr in interface_ext_attrs:
+ if ext_attr.GetName() != 'NamedConstructor':
+ continue
+ call_node = ext_attr.GetChildren()[0]
+ assert call_node.GetClass() == 'Call'
+ child_nodes = list(call_node.GetChildren())
+ arguments = self._take_arguments(child_nodes)
+ return_type = self._idl_type_factory.reference_type(
+ Identifier(node.GetName()))
+ assert not child_nodes
+ named_constructors.append(
+ Constructor.IR(
+ identifier=Identifier(call_node.GetName()),
+ arguments=arguments,
+ return_type=return_type,
+ component=self._component,
+ debug_info=self._build_debug_info(node)))
+
+ return named_constructors
+
def _build_dictionary(self, node):
child_nodes = list(node.GetChildren())
inherited = self._take_inheritance(child_nodes)
@@ -280,7 +327,7 @@ class _IRBuilder(object):
idl_type = self._take_type(child_nodes, is_optional=(not is_required))
default_value = self._take_default_value(child_nodes)
extended_attributes = self._take_extended_attributes(child_nodes)
- assert len(child_nodes) == 0
+ assert not child_nodes
return DictionaryMember.IR(
identifier=Identifier(node.GetName()),
@@ -319,7 +366,7 @@ class _IRBuilder(object):
arguments = self._take_arguments(child_nodes)
return_type = self._take_type(child_nodes)
extended_attributes = self._take_extended_attributes(child_nodes)
- assert len(child_nodes) == 0
+ assert not child_nodes
return CallbackFunction.IR(
identifier=Identifier(node.GetName()),
arguments=arguments,
@@ -343,7 +390,7 @@ class _IRBuilder(object):
def _build_typedef(self, node):
child_nodes = list(node.GetChildren())
idl_type = self._take_type(child_nodes)
- assert len(child_nodes) == 0
+ assert not child_nodes
return Typedef.IR(
identifier=Identifier(node.GetName()),
@@ -375,7 +422,7 @@ class _IRBuilder(object):
is_variadic=is_variadic,
extended_attributes=extended_attributes)
default_value = self._take_default_value(child_nodes)
- assert len(child_nodes) == 0
+ assert not child_nodes
return Argument.IR(
identifier=Identifier(node.GetName()),
index=index,
@@ -408,21 +455,27 @@ class _IRBuilder(object):
key = node.GetName()
values = node.GetProperty('VALUE', default=None)
arguments = None
-
- # Drop constructors as they do not fit in ExtendedAttribute which
- # doesn't support IdlType.
- if key in ('Constructor', 'CustomConstructor', 'NamedConstructor'):
- return None
+ name = None
child_nodes = node.GetChildren()
if child_nodes:
assert len(child_nodes) == 1
- assert child_nodes[0].GetClass() == 'Arguments'
- arguments = map(build_extattr_argument,
- child_nodes[0].GetChildren())
+ child = child_nodes[0]
+ if child.GetClass() == 'Arguments':
+ arguments = map(build_extattr_argument,
+ child.GetChildren())
+ elif child.GetClass() == 'Call':
+ assert len(child.GetChildren()) == 1
+ grand_child = child.GetChildren()[0]
+ assert grand_child.GetClass() == 'Arguments'
+ # ExtendedAttribute is not designed to represent an
+ # operation, especially a complicated argument list.
+ # Discard the arguments.
+ arguments = ()
+ name = child.GetName()
return ExtendedAttribute(
- key=key, values=values, arguments=arguments)
+ key=key, values=values, arguments=arguments, name=name)
def build_extattr_argument(node):
assert node.GetClass() == 'Argument'
@@ -469,7 +522,7 @@ class _IRBuilder(object):
debug_info=self._build_debug_info(node))
def _build_literal_constant(self, node):
- assert len(node.GetChildren()) == 0
+ assert not node.GetChildren()
type_token = node.GetProperty('TYPE')
value_token = node.GetProperty('VALUE')
@@ -523,7 +576,7 @@ class _IRBuilder(object):
value = dict()
literal = '{}'
else:
- assert False, 'Unknown literal type: {}'.format(type_token)
+ assert False, "Unknown literal type: {}".format(type_token)
return LiteralConstant(idl_type=idl_type, value=value, literal=literal)
@@ -688,6 +741,7 @@ class _IRBuilder(object):
buffer_source_types = set([
'ArrayBuffer',
+ 'ArrayBufferView', # Blink-specific ArrayBufferView definition
'DataView',
'Int8Array',
'Int16Array',
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py
index 4651900f8a6..91806523243 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py
@@ -190,11 +190,11 @@ class IRMap(object):
"""Returns a flattened list of IRs of the given kind."""
if IRMap.IR.Kind.does_support_multiple_defs(kind):
accumulated = []
- for irs in self.find_by_kind(kind).itervalues():
+ for irs in self.find_by_kind(kind).values():
accumulated.extend(irs)
return accumulated
else:
- return self.find_by_kind(kind).itervalues()
+ return list(self.find_by_kind(kind).values())
def irs_of_kinds(self, *kinds):
"""
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py
index b9a22ebfaaf..a7a2b11f3f0 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py
@@ -48,11 +48,11 @@ def make_copy(obj, memo=None):
if isinstance(obj, dict):
return memoize(
cls([(make_copy(key, memo), make_copy(value, memo))
- for key, value in obj.iteritems()]))
+ for key, value in obj.items()]))
if hasattr(obj, '__dict__'):
copy = memoize(cls.__new__(cls))
- for name, value in obj.__dict__.iteritems():
+ for name, value in obj.__dict__.items():
setattr(copy, name, make_copy(value, memo))
return copy
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/migration_adapter.idl b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/migration_adapter.idl
index 38eacc2cfdf..7ede71f3a06 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/migration_adapter.idl
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/migration_adapter.idl
@@ -8,10 +8,6 @@
// and the *.idl files get updated to be spec conformant, almost all (if not
// really all) the followings will be gone.
-typedef object SerializedScriptValue;
-
-typedef object? Dictionary;
-
typedef EventHandlerNonNull? EventHandler;
typedef DOMMatrix DOMMatrixConstructor;
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py
index c00d88890cc..6c146122bdf 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py
@@ -60,10 +60,13 @@ class Namespace(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
WithDebugInfo.__init__(self, debug_info)
self.is_partial = is_partial
+ self.is_mixin = False
self.attributes = list(attributes)
self.constants = list(constants)
self.constructors = []
self.constructor_groups = []
+ self.named_constructors = []
+ self.named_constructor_groups = []
self.operations = list(operations)
self.operation_groups = []
@@ -81,7 +84,7 @@ class Namespace(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithComponent.__init__(self, ir, readonly=True)
@@ -140,3 +143,8 @@ class Namespace(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
def operation_groups(self):
"""Returns a list of OperationGroups."""
return self._operation_groups
+
+ @property
+ def exposed_constructs(self):
+ """Returns exposed constructs."""
+ return ()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/operation.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
index d4c66a00041..7613451d93e 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
@@ -32,9 +32,17 @@ class Operation(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo,
arguments,
return_type,
is_static=False,
+ is_getter=False,
+ is_setter=False,
+ is_deleter=False,
extended_attributes=None,
component=None,
debug_info=None):
+ assert isinstance(is_getter, bool)
+ assert isinstance(is_setter, bool)
+ assert isinstance(is_deleter, bool)
+ assert is_getter + is_setter + is_deleter <= 1 # At most 1 True
+
FunctionLike.IR.__init__(
self,
identifier=identifier,
@@ -48,13 +56,16 @@ class Operation(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo,
WithComponent.__init__(self, component)
WithDebugInfo.__init__(self, debug_info)
+ self.is_getter = is_getter
+ self.is_setter = is_setter
+ self.is_deleter = is_deleter
self.is_stringifier = False
def __init__(self, ir, owner):
assert isinstance(ir, Operation.IR)
FunctionLike.__init__(self, ir)
- WithExtendedAttributes.__init__(self, ir)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
@@ -62,15 +73,44 @@ class Operation(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo,
WithComponent.__init__(self, ir, readonly=True)
WithDebugInfo.__init__(self, ir)
+ self._is_getter = ir.is_getter
+ self._is_setter = ir.is_setter
+ self._is_deleter = ir.is_deleter
self._is_stringifier = ir.is_stringifier
@property
+ def is_special_operation(self):
+ return (self.is_getter or self.is_setter or self.is_deleter
+ or self.is_stringifier)
+
+ @property
+ def is_indexed_or_named_property_operation(self):
+ """
+ Returns True if this is an indexed or named property special operation
+ (one of getter, setter, or deleter).
+ """
+ return self.is_getter or self.is_setter or self.is_deleter
+
+ @property
+ def is_getter(self):
+ return self._is_getter
+
+ @property
+ def is_setter(self):
+ return self._is_setter
+
+ @property
+ def is_deleter(self):
+ return self._is_deleter
+
+ @property
def is_stringifier(self):
return self._is_stringifier
-class OperationGroup(OverloadGroup, WithCodeGeneratorInfo, WithExposure,
- WithOwner, WithComponent, WithDebugInfo):
+class OperationGroup(OverloadGroup, WithExtendedAttributes,
+ WithCodeGeneratorInfo, WithExposure, WithOwner,
+ WithComponent, WithDebugInfo):
"""
Represents a group of operations with the same identifier.
@@ -78,13 +118,15 @@ class OperationGroup(OverloadGroup, WithCodeGeneratorInfo, WithExposure,
the operations are overloaded.
"""
- class IR(OverloadGroup.IR, WithCodeGeneratorInfo, WithExposure,
- WithDebugInfo):
+ class IR(OverloadGroup.IR, WithExtendedAttributes, WithCodeGeneratorInfo,
+ WithExposure, WithDebugInfo):
def __init__(self,
operations,
+ extended_attributes=None,
code_generator_info=None,
debug_info=None):
OverloadGroup.IR.__init__(self, operations)
+ WithExtendedAttributes.__init__(self, extended_attributes)
WithCodeGeneratorInfo.__init__(self, code_generator_info)
WithExposure.__init__(self)
WithDebugInfo.__init__(self, debug_info)
@@ -103,6 +145,7 @@ class OperationGroup(OverloadGroup, WithCodeGeneratorInfo, WithExposure,
ir = make_copy(ir)
OverloadGroup.__init__(self, functions=operations)
+ WithExtendedAttributes.__init__(self, ir, readonly=True)
WithCodeGeneratorInfo.__init__(self, ir, readonly=True)
WithExposure.__init__(self, ir, readonly=True)
WithOwner.__init__(self, owner)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py
index 02f00b111ca..9bb06e94cd9 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/union.py
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from .composition_parts import Identifier
+from .composition_parts import WithCodeGeneratorInfo
from .composition_parts import WithComponent
from .composition_parts import WithDebugInfo
from .composition_parts import WithIdentifier
@@ -9,7 +11,8 @@ from .idl_type import IdlType
from .typedef import Typedef
-class Union(WithIdentifier, WithComponent, WithDebugInfo):
+class Union(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
+ WithDebugInfo):
"""
Union class makes a group of union types with the same flattened member
types and the same result whether it includes a nullable type or not.
@@ -28,7 +31,7 @@ class Union(WithIdentifier, WithComponent, WithDebugInfo):
expected to define an implementation class for each Union instance.
"""
- def __init__(self, identifier, union_types, typedef_backrefs):
+ def __init__(self, union_types, typedef_backrefs):
"""
Args:
union_types: Union types of which this object consists. All types
@@ -56,6 +59,7 @@ class Union(WithIdentifier, WithComponent, WithDebugInfo):
assert union_type.flattened_member_types == flattened_members
assert (union_type.does_include_nullable_type ==
does_include_nullable_type)
+ union_type.set_union_definition_object(self)
for direct_member in union_type.member_types:
if direct_member.is_nullable:
nullable_members.add(direct_member)
@@ -68,16 +72,49 @@ class Union(WithIdentifier, WithComponent, WithDebugInfo):
components = set()
- def collect_components(idl_type):
- user_defined_type = idl_type.type_definition_object
- if user_defined_type:
- components.update(user_defined_type.components)
+ def collect_primary_component(idl_type):
+ type_definition_object = idl_type.type_definition_object
+ if type_definition_object and type_definition_object.components:
+ components.add(type_definition_object.components[0])
for idl_type in flattened_members:
- idl_type.apply_to_all_composing_elements(collect_components)
+ idl_type.apply_to_all_composing_elements(collect_primary_component)
+ # Make this union type look defined in 'modules' if the union type is
+ # used in 'modules' in order to keep the backward compatibility with
+ # the old bindings generator.
+ is_defined_in_core = False
+ is_defined_in_modules = False
+ for idl_type in union_types:
+ filepath = idl_type.debug_info.location.filepath
+ if filepath.startswith('third_party/blink/renderer/core/'):
+ is_defined_in_core = True
+ if filepath.startswith('third_party/blink/renderer/modules/'):
+ is_defined_in_modules = True
+ if not is_defined_in_core and is_defined_in_modules:
+ from .composition_parts import Component
+ components.add(Component('modules'))
+
+ # TODO(peria, yukishiino): Produce unique union names. Trying to
+ # produce the names compatible to the old bindings generator for the
+ # time being.
+ #
+ # type_names = sorted(
+ # [idl_type.type_name for idl_type in flattened_members])
+ def backward_compatible_member_name(idl_type):
+ name = idl_type.unwrap().type_name
+ if name == 'StringTreatNullAs':
+ return 'StringTreatNullAsEmptyString'
+ else:
+ return name
+
+ identifier = Identifier('Or'.join([
+ backward_compatible_member_name(idl_type)
+ for idl_type in union_types[0].member_types
+ ]))
WithIdentifier.__init__(self, identifier)
- WithComponent.__init__(self, sorted(components))
+ WithCodeGeneratorInfo.__init__(self, readonly=True)
+ WithComponent.__init__(self, sorted(components), readonly=True)
WithDebugInfo.__init__(self)
# Sort improves reproducibility.
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/user_defined_type.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/user_defined_type.py
index 30837f2f31e..e7858c07ad6 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/user_defined_type.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/user_defined_type.py
@@ -45,4 +45,4 @@ class UserDefinedType(WithIdentifier):
class StubUserDefinedType(UserDefinedType, WithComponent):
def __init__(self, identifier):
UserDefinedType.__init__(self, identifier)
- WithComponent.__init__(self, components=[])
+ WithComponent.__init__(self, [])
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/validator.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/validator.py
index d9f15672f20..cb0290909b8 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/validator.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/validator.py
@@ -24,6 +24,7 @@ def _all_function_likes(ir_map):
IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.NAMESPACE)
for ir in irs:
accumulated.extend(ir.constructors)
+ accumulated.extend(ir.named_constructors)
accumulated.extend(ir.operations)
accumulated.extend(ir_map.irs_of_kinds(IRMap.IR.Kind.CALLBACK_FUNCTION))
return accumulated