Commit 51b79729 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Refactor the new binding gentor to support IDL callbacks

Refactors bind_gen/ to support IDL callback functions and IDL
callback interfaces in https://crrev.com/c/2434004

Bug: 839389
Change-Id: Ie58f15269efe7c80f0157c4296f0cb37465deab0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2432708Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811132}
parent 26e5926b
...@@ -151,12 +151,10 @@ def blink_type_info(idl_type): ...@@ -151,12 +151,10 @@ def blink_type_info(idl_type):
if real_type.is_void: if real_type.is_void:
assert False, "Blink does not support/accept IDL void type." 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: if real_type.type_definition_object is not None:
blink_impl_type = blink_class_name(real_type.type_definition_object) blink_impl_type = blink_class_name(real_type.type_definition_object)
if real_type.is_enumeration:
return TypeInfo(blink_impl_type)
return TypeInfo( return TypeInfo(
blink_impl_type, blink_impl_type,
member_fmt="Member<{}>", member_fmt="Member<{}>",
...@@ -280,6 +278,39 @@ def native_value_tag(idl_type): ...@@ -280,6 +278,39 @@ def native_value_tag(idl_type):
assert False, "Unknown type: {}".format(idl_type.syntactic_form) assert False, "Unknown type: {}".format(idl_type.syntactic_form)
def make_blink_to_v8_value(v8_var_name, blink_value_expr, idl_type,
v8_creation_context):
"""
Returns a SymbolNode whose definition converts a Blink value to a v8::Value.
"""
assert isinstance(v8_var_name, str)
assert isinstance(blink_value_expr, str)
assert isinstance(idl_type, web_idl.IdlType)
assert isinstance(v8_creation_context, str)
def create_definition(symbol_node):
if (idl_type.unwrap(typedef=True).is_nullable
and idl_type.unwrap().is_string):
pattern = ("v8::Local<v8::Value> {v8_var_name} = "
"{blink_value_expr}.IsNull() "
"? v8::Null(${isolate}).As<v8::Value>() "
": ToV8("
"{blink_value_expr}, {v8_creation_context}, ${isolate})"
".As<v8::Value>();")
else:
pattern = (
"auto&& {v8_var_name} = ToV8("
"{blink_value_expr}, {v8_creation_context}, ${isolate});")
node = TextNode(
_format(pattern,
v8_var_name=v8_var_name,
blink_value_expr=blink_value_expr,
v8_creation_context=v8_creation_context))
return SymbolDefinitionNode(symbol_node, [node])
return SymbolNode(v8_var_name, definition_constructor=create_definition)
def make_default_value_expr(idl_type, default_value): def make_default_value_expr(idl_type, default_value):
""" """
Returns a set of C++ expressions to be used for initialization with default Returns a set of C++ expressions to be used for initialization with default
......
...@@ -8,10 +8,12 @@ code_node.CodeNode. ...@@ -8,10 +8,12 @@ code_node.CodeNode.
from .code_node import CodeNode from .code_node import CodeNode
from .code_node import CompositeNode from .code_node import CompositeNode
from .code_node import EmptyNode
from .code_node import Likeliness from .code_node import Likeliness
from .code_node import ListNode from .code_node import ListNode
from .code_node import SymbolScopeNode from .code_node import SymbolScopeNode
from .code_node import TextNode from .code_node import TextNode
from .code_node import WeakDependencyNode
from .codegen_expr import CodeGenExpr from .codegen_expr import CodeGenExpr
from .codegen_format import format_template from .codegen_format import format_template
...@@ -210,6 +212,30 @@ switch (${{{cond}}}) {{ ...@@ -210,6 +212,30 @@ switch (${{{cond}}}) {{
self._Clause(case, body, should_add_break)) self._Clause(case, body, should_add_break))
class CxxForLoopNode(CompositeNode):
def __init__(self, cond, body, weak_dep_syms=None):
assert weak_dep_syms is None or isinstance(weak_dep_syms,
(list, tuple))
if weak_dep_syms is None:
weak_deps = EmptyNode()
else:
weak_deps = WeakDependencyNode(weak_dep_syms)
template_format = (
"{weak_deps}" #
"for ({cond}) {{\n"
" {body}\n"
"}}\n")
CompositeNode.__init__(self,
template_format,
weak_deps=weak_deps,
cond=_to_conditional_node(cond),
body=_to_symbol_scope_node(
body, Likeliness.LIKELY))
class CxxBreakableBlockNode(CompositeNode): class CxxBreakableBlockNode(CompositeNode):
def __init__(self, body, likeliness=Likeliness.LIKELY): def __init__(self, body, likeliness=Likeliness.LIKELY):
template_format = ("do {{ // Dummy loop for use of 'break'.\n" template_format = ("do {{ // Dummy loop for use of 'break'.\n"
...@@ -234,7 +260,8 @@ class CxxFuncDeclNode(CompositeNode): ...@@ -234,7 +260,8 @@ class CxxFuncDeclNode(CompositeNode):
const=False, const=False,
override=False, override=False,
default=False, default=False,
delete=False): delete=False,
warn_unused_result=False):
""" """
Args: Args:
name: Function name. name: Function name.
...@@ -248,6 +275,7 @@ class CxxFuncDeclNode(CompositeNode): ...@@ -248,6 +275,7 @@ class CxxFuncDeclNode(CompositeNode):
override: True makes this an overriding function. override: True makes this an overriding function.
default: True makes this have the default implementation. default: True makes this have the default implementation.
delete: True makes this function be deleted. delete: True makes this function be deleted.
warn_unused_result: True adds WARN_UNUSED_RESULT annotation.
""" """
assert isinstance(name, str) assert isinstance(name, str)
assert isinstance(static, bool) assert isinstance(static, bool)
...@@ -258,6 +286,7 @@ class CxxFuncDeclNode(CompositeNode): ...@@ -258,6 +286,7 @@ class CxxFuncDeclNode(CompositeNode):
assert isinstance(default, bool) assert isinstance(default, bool)
assert isinstance(delete, bool) assert isinstance(delete, bool)
assert not (default and delete) assert not (default and delete)
assert isinstance(warn_unused_result, bool)
template_format = ("{template}" template_format = ("{template}"
"{static}{explicit}{constexpr}" "{static}{explicit}{constexpr}"
...@@ -266,40 +295,42 @@ class CxxFuncDeclNode(CompositeNode): ...@@ -266,40 +295,42 @@ class CxxFuncDeclNode(CompositeNode):
"{const}" "{const}"
"{override}" "{override}"
"{default_or_delete}" "{default_or_delete}"
"{warn_unused_result}"
";") ";")
if template_params is None: if template_params is None:
template = "" template = ""
else: else:
template = "template <{}>\n".format(", ".join(template_params)) template = "template <{}>\n".format(", ".join(template_params))
static = "static " if static else "" static = "static " if static else ""
explicit = "explicit " if explicit else "" explicit = "explicit " if explicit else ""
constexpr = "constexpr " if constexpr else "" constexpr = "constexpr " if constexpr else ""
const = " const" if const else "" const = " const" if const else ""
override = " override" if override else "" override = " override" if override else ""
if default: if default:
default_or_delete = " = default" default_or_delete = " = default"
elif delete: elif delete:
default_or_delete = " = delete" default_or_delete = " = delete"
else: else:
default_or_delete = "" default_or_delete = ""
warn_unused_result = (" WARN_UNUSED_RESULT"
CompositeNode.__init__( if warn_unused_result else "")
self,
template_format, CompositeNode.__init__(self,
name=_to_maybe_text_node(name), template_format,
arg_decls=ListNode( name=_to_maybe_text_node(name),
map(_to_maybe_text_node, arg_decls), separator=", "), arg_decls=ListNode(map(_to_maybe_text_node,
return_type=_to_maybe_text_node(return_type), arg_decls),
template=template, separator=", "),
static=static, return_type=_to_maybe_text_node(return_type),
explicit=explicit, template=template,
constexpr=constexpr, static=static,
const=const, explicit=explicit,
override=override, constexpr=constexpr,
default_or_delete=default_or_delete) const=const,
override=override,
default_or_delete=default_or_delete,
warn_unused_result=warn_unused_result)
class CxxFuncDefNode(CompositeNode): class CxxFuncDefNode(CompositeNode):
......
...@@ -7,6 +7,7 @@ import web_idl ...@@ -7,6 +7,7 @@ import web_idl
from . import name_style from . import name_style
from .blink_v8_bridge import blink_class_name from .blink_v8_bridge import blink_class_name
from .blink_v8_bridge import blink_type_info from .blink_v8_bridge import blink_type_info
from .blink_v8_bridge import make_blink_to_v8_value
from .blink_v8_bridge import make_default_value_expr from .blink_v8_bridge import make_default_value_expr
from .blink_v8_bridge import make_v8_to_blink_value from .blink_v8_bridge import make_v8_to_blink_value
from .blink_v8_bridge import native_value_tag from .blink_v8_bridge import native_value_tag
...@@ -59,7 +60,7 @@ def _blink_member_name(member): ...@@ -59,7 +60,7 @@ def _blink_member_name(member):
# C++ data member that shows the presence of the IDL member. # C++ data member that shows the presence of the IDL member.
self.presence_var = name_style.member_var("has", blink_name) self.presence_var = name_style.member_var("has", blink_name)
# C++ data member that holds the value of the IDL member. # C++ data member that holds the value of the IDL member.
self.value_var = name_style.member_var(blink_name) self.value_var = name_style.member_var_f("member_{}", blink_name)
# Migration Adapters # Migration Adapters
self.get_non_null_api = name_style.api_func(blink_name, "non_null") self.get_non_null_api = name_style.api_func(blink_name, "non_null")
self.has_non_null_api = name_style.api_func( self.has_non_null_api = name_style.api_func(
...@@ -97,7 +98,7 @@ def bind_member_iteration_local_vars(code_node): ...@@ -97,7 +98,7 @@ def bind_member_iteration_local_vars(code_node):
"current_context", "v8::Local<v8::Context> ${current_context} = " "current_context", "v8::Local<v8::Context> ${current_context} = "
"${isolate}->GetCurrentContext();"), "${isolate}->GetCurrentContext();"),
SymbolNode( SymbolNode(
"member_names", "const auto* ${member_names} = " "v8_member_names", "const auto* ${v8_member_names} = "
"GetV8MemberNames(${isolate}).data();"), "GetV8MemberNames(${isolate}).data();"),
SymbolNode( SymbolNode(
"is_in_secure_context", "const bool ${is_in_secure_context} = " "is_in_secure_context", "const bool ${is_in_secure_context} = "
...@@ -776,43 +777,32 @@ def make_fill_with_own_dict_members_func(cg_context): ...@@ -776,43 +777,32 @@ def make_fill_with_own_dict_members_func(cg_context):
func_def.set_base_template_vars(cg_context.template_bindings()) func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body body = func_def.body
body.add_template_var("isolate", "isolate") body.add_template_var("isolate", "isolate")
body.add_template_var("creation_context", "creation_context")
body.add_template_var("v8_dictionary", "v8_dictionary")
bind_member_iteration_local_vars(body) bind_member_iteration_local_vars(body)
def to_v8_expr(member): for index, member in enumerate(own_members):
get_api = _blink_member_name(member).get_api member_name = _blink_member_name(member)
member_type = member.idl_type.unwrap(typedef=True) v8_member_name = name_style.local_var_f("v8_member_{}",
expr = _format("ToV8({}(), creation_context, isolate)", get_api) member.identifier)
if member_type.is_nullable and member_type.unwrap().is_string: body.register_code_symbol(
expr = _format( make_blink_to_v8_value(v8_member_name,
"({get_api}().IsNull() ? v8::Null(isolate).As<v8::Value>() " "{}()".format(member_name.get_api),
": {to_v8})", member.idl_type, "${creation_context}"))
get_api=get_api, node = CxxLikelyIfNode(
to_v8=expr) cond="{}()".format(member_name.has_api),
return expr body=TextNode(
_format(
for key_index, member in enumerate(own_members): "${v8_dictionary}->CreateDataProperty("
pattern = """\ "${current_context}, "
if ({has_api}()) {{ "${v8_member_names}[{index}].Get(${isolate}), "
if (!v8_dictionary "${{{v8_member_name}}}"
->CreateDataProperty( ").ToChecked();",
${current_context}, index=index,
${member_names}[{index}].Get(isolate), v8_member_name=v8_member_name)))
{to_v8_expr})
.ToChecked()) {{
return false;
}}
}}\
"""
node = TextNode(
_format(pattern,
has_api=_blink_member_name(member).has_api,
index=key_index,
to_v8_expr=to_v8_expr(member)))
conditional = expr_from_exposure(member.exposure) conditional = expr_from_exposure(member.exposure)
if not conditional.is_always_true: if not conditional.is_always_true:
node = CxxLikelyIfNode(cond=conditional, body=node) node = CxxLikelyIfNode(cond=conditional, body=node)
body.append(node) body.append(node)
body.append(TextNode("return true;")) body.append(TextNode("return true;"))
...@@ -944,7 +934,7 @@ if (!bindings::ConvertDictionaryMember<{nvt_tag}, {is_required}>( ...@@ -944,7 +934,7 @@ if (!bindings::ConvertDictionaryMember<{nvt_tag}, {is_required}>(
${isolate}, ${isolate},
${current_context}, ${current_context},
v8_dictionary, v8_dictionary,
${member_names}[{key_index}].Get(${isolate}), ${v8_member_names}[{key_index}].Get(${isolate}),
"${{dictionary.identifier}}", "${{dictionary.identifier}}",
"{member_name}", "{member_name}",
{value_var}, {value_var},
......
...@@ -317,13 +317,14 @@ def generate_enumeration(enumeration_identifier): ...@@ -317,13 +317,14 @@ def generate_enumeration(enumeration_identifier):
make_forward_declarations(source_node.accumulator), make_forward_declarations(source_node.accumulator),
EmptyNode(), EmptyNode(),
]) ])
# Assemble the parts.
header_node.accumulator.add_include_headers([ header_node.accumulator.add_include_headers([
component_export_header(api_component, for_testing), component_export_header(api_component, for_testing),
"third_party/blink/renderer/bindings/core/v8/generated_code_helper.h", "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
"third_party/blink/renderer/platform/bindings/enumeration_base.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(class_def)
header_blink_ns.body.append(EmptyNode()) header_blink_ns.body.append(EmptyNode())
......
...@@ -4671,9 +4671,11 @@ class _PropEntryOperationGroup(_PropEntryBase): ...@@ -4671,9 +4671,11 @@ class _PropEntryOperationGroup(_PropEntryBase):
self.no_alloc_direct_callback_name = no_alloc_direct_callback_name self.no_alloc_direct_callback_name = no_alloc_direct_callback_name
def _make_property_entries_and_callback_defs( def make_property_entries_and_callback_defs(cg_context, attribute_entries,
cg_context, attribute_entries, constant_entries, constructor_entries, constant_entries,
exposed_construct_entries, operation_entries): constructor_entries,
exposed_construct_entries,
operation_entries):
""" """
Creates intermediate objects to help property installation and also makes Creates intermediate objects to help property installation and also makes
code nodes of callback functions. code nodes of callback functions.
...@@ -4692,8 +4694,9 @@ def _make_property_entries_and_callback_defs( ...@@ -4692,8 +4694,9 @@ def _make_property_entries_and_callback_defs(
assert isinstance(exposed_construct_entries, list) assert isinstance(exposed_construct_entries, list)
assert isinstance(operation_entries, list) assert isinstance(operation_entries, list)
class_like = cg_context.class_like
interface = cg_context.interface interface = cg_context.interface
global_names = interface.extended_attributes.values_of("Global") global_names = class_like.extended_attributes.values_of("Global")
callback_def_nodes = ListNode() callback_def_nodes = ListNode()
...@@ -4911,22 +4914,24 @@ def _make_property_entries_and_callback_defs( ...@@ -4911,22 +4914,24 @@ def _make_property_entries_and_callback_defs(
op_callback_name=op_callback_name, op_callback_name=op_callback_name,
op_func_length=0)) op_func_length=0))
iterate(interface.attributes, process_attribute) iterate(class_like.attributes, process_attribute)
iterate(interface.constants, process_constant) iterate(class_like.constants, process_constant)
iterate(interface.constructor_groups, process_constructor_group) if interface:
iterate(interface.exposed_constructs, process_exposed_construct) iterate(interface.constructor_groups, process_constructor_group)
iterate(interface.legacy_window_aliases, process_exposed_construct) iterate(interface.exposed_constructs, process_exposed_construct)
named_constructor_groups = [ iterate(interface.legacy_window_aliases, process_exposed_construct)
group for construct in interface.exposed_constructs named_constructor_groups = [
for group in construct.named_constructor_groups group for construct in interface.exposed_constructs
if construct.named_constructor_groups for group in construct.named_constructor_groups
] if construct.named_constructor_groups
iterate(named_constructor_groups, process_named_constructor_group) ]
iterate(interface.operation_groups, process_operation_group) iterate(named_constructor_groups, process_named_constructor_group)
if interface.stringifier: if not class_like.is_callback_interface:
iterate(class_like.operation_groups, process_operation_group)
if interface and interface.stringifier:
iterate([interface.stringifier.operation], process_stringifier) iterate([interface.stringifier.operation], process_stringifier)
collectionlike = (interface.iterable or interface.maplike collectionlike = interface and (interface.iterable or interface.maplike
or interface.setlike) or interface.setlike)
if collectionlike: if collectionlike:
def should_define(target): def should_define(target):
...@@ -5150,6 +5155,12 @@ def make_install_interface_template(cg_context, function_name, class_name, ...@@ -5150,6 +5155,12 @@ def make_install_interface_template(cg_context, function_name, class_name,
assert False assert False
body.append(EmptyNode()) body.append(EmptyNode())
if cg_context.callback_interface:
body.extend([
T("${interface_template}->RemovePrototype();"),
EmptyNode(),
])
body.extend([ body.extend([
supplemental_install_node, supplemental_install_node,
EmptyNode(), EmptyNode(),
...@@ -5301,8 +5312,8 @@ ${prototype_template}->SetIntrinsicDataProperty( ...@@ -5301,8 +5312,8 @@ ${prototype_template}->SetIntrinsicDataProperty(
${instance_template}->SetImmutableProto(); ${instance_template}->SetImmutableProto();
${prototype_template}->SetImmutableProto(); ${prototype_template}->SetImmutableProto();
""")) """))
elif any("Global" in derived.extended_attributes elif interface and any("Global" in derived.extended_attributes
for derived in class_like.deriveds): for derived in interface.deriveds):
body.append( body.append(
TextNode("""\ TextNode("""\
// [Global] - prototype object in the prototype chain of global objects // [Global] - prototype object in the prototype chain of global objects
...@@ -6219,16 +6230,17 @@ const WrapperTypeInfo ${class_name}::wrapper_type_info_{{ ...@@ -6219,16 +6230,17 @@ const WrapperTypeInfo ${class_name}::wrapper_type_info_{{
"InstallContextDependentPropertiesAdapter") "InstallContextDependentPropertiesAdapter")
else: else:
install_context_dependent_func = "nullptr" install_context_dependent_func = "nullptr"
if class_like.inherited: if class_like.is_interface and class_like.inherited:
wrapper_type_info_of_inherited = "{}::GetWrapperTypeInfo()".format( wrapper_type_info_of_inherited = "{}::GetWrapperTypeInfo()".format(
v8_bridge_class_name(class_like.inherited)) v8_bridge_class_name(class_like.inherited))
else: else:
wrapper_type_info_of_inherited = "nullptr" wrapper_type_info_of_inherited = "nullptr"
wrapper_type_prototype = ("WrapperTypeInfo::kWrapperTypeObjectPrototype" wrapper_type_prototype = ("WrapperTypeInfo::kWrapperTypeObjectPrototype"
if isinstance(class_like, web_idl.Interface) else if class_like.is_interface else
"WrapperTypeInfo::kWrapperTypeNoPrototype") "WrapperTypeInfo::kWrapperTypeNoPrototype")
wrapper_class_id = ("WrapperTypeInfo::kNodeClassId" wrapper_class_id = ("WrapperTypeInfo::kNodeClassId"
if class_like.does_implement("Node") else if class_like.is_interface
and class_like.does_implement("Node") else
"WrapperTypeInfo::kObjectClassId") "WrapperTypeInfo::kObjectClassId")
active_script_wrappable_inheritance = ( active_script_wrappable_inheritance = (
"WrapperTypeInfo::kInheritFromActiveScriptWrappable" "WrapperTypeInfo::kInheritFromActiveScriptWrappable"
...@@ -6243,12 +6255,13 @@ const WrapperTypeInfo ${class_name}::wrapper_type_info_{{ ...@@ -6243,12 +6255,13 @@ const WrapperTypeInfo ${class_name}::wrapper_type_info_{{
active_script_wrappable_inheritance=( active_script_wrappable_inheritance=(
active_script_wrappable_inheritance))) active_script_wrappable_inheritance)))
blink_class = blink_class_name(class_like) if class_like.is_interface:
pattern = """\ blink_class = blink_class_name(class_like)
pattern = """\
const WrapperTypeInfo& {blink_class}::wrapper_type_info_ = const WrapperTypeInfo& {blink_class}::wrapper_type_info_ =
${class_name}::wrapper_type_info_; ${class_name}::wrapper_type_info_;
""" """
wrapper_type_info_def.append(F(pattern, blink_class=blink_class)) wrapper_type_info_def.append(F(pattern, blink_class=blink_class))
if class_like.code_generator_info.is_active_script_wrappable: if class_like.code_generator_info.is_active_script_wrappable:
pattern = """\ pattern = """\
...@@ -6274,7 +6287,8 @@ static_assert( ...@@ -6274,7 +6287,8 @@ static_assert(
decltype(&ScriptWrappable::HasPendingActivity)>::value, decltype(&ScriptWrappable::HasPendingActivity)>::value,
"{blink_class} is overriding hasPendingActivity() without " "{blink_class} is overriding hasPendingActivity() without "
"[ActiveScriptWrappable] extended attribute.");""" "[ActiveScriptWrappable] extended attribute.");"""
wrapper_type_info_def.append(F(pattern, blink_class=blink_class)) if class_like.is_interface:
wrapper_type_info_def.append(F(pattern, blink_class=blink_class))
return func_def, member_var_def, wrapper_type_info_def return func_def, member_var_def, wrapper_type_info_def
...@@ -6721,7 +6735,7 @@ def generate_interface(interface_identifier): ...@@ -6721,7 +6735,7 @@ def generate_interface(interface_identifier):
constructor_entries = [] constructor_entries = []
exposed_construct_entries = [] exposed_construct_entries = []
operation_entries = [] operation_entries = []
callback_defs = _make_property_entries_and_callback_defs( callback_defs = make_property_entries_and_callback_defs(
cg_context, cg_context,
attribute_entries=attribute_entries, attribute_entries=attribute_entries,
constant_entries=constant_entries, constant_entries=constant_entries,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment