Commit 3e95b49a authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Implement boiler-plated bindings generation of IDL union

As a first step of IDL union implementation, implements mostly-
empty code generation of IDL union bindings.

Bug: 839389
Change-Id: Ia15933cfa57cd8e2f6cc5e93870ba18316dbbc3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2512329Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824337}
parent 4529c95d
...@@ -36,7 +36,6 @@ namespace bindings { ...@@ -36,7 +36,6 @@ namespace bindings {
class DictionaryBase; class DictionaryBase;
class EnumerationBase; class EnumerationBase;
class UnionBase;
CORE_EXPORT void NativeValueTraitsInterfaceNotOfType( CORE_EXPORT void NativeValueTraitsInterfaceNotOfType(
const WrapperTypeInfo* wrapper_type_info, const WrapperTypeInfo* wrapper_type_info,
...@@ -1254,19 +1253,6 @@ struct NativeValueTraits< ...@@ -1254,19 +1253,6 @@ struct NativeValueTraits<
} }
}; };
// Union types
template <typename T>
struct NativeValueTraits<
T,
typename std::enable_if_t<std::is_base_of<bindings::UnionBase, T>::value>>
: public NativeValueTraitsBase<T> {
static T NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
return T::Create(isolate, value, exception_state);
}
};
// Migration Adapters: union types generated by the old bindings generator. // Migration Adapters: union types generated by the old bindings generator.
template <typename T> template <typename T>
struct NativeValueTraits<IDLUnionNotINT<T>> : public NativeValueTraitsBase<T> { struct NativeValueTraits<IDLUnionNotINT<T>> : public NativeValueTraitsBase<T> {
......
...@@ -40,6 +40,7 @@ from .enumeration import generate_enumerations ...@@ -40,6 +40,7 @@ from .enumeration import generate_enumerations
from .interface import generate_interfaces from .interface import generate_interfaces
from .namespace import generate_namespaces from .namespace import generate_namespaces
from .task_queue import TaskQueue from .task_queue import TaskQueue
from .union import generate_unions
def init(web_idl_database_path, root_src_dir, root_gen_dir, component_reldirs): def init(web_idl_database_path, root_src_dir, root_gen_dir, component_reldirs):
......
...@@ -29,7 +29,7 @@ def blink_class_name(idl_definition): ...@@ -29,7 +29,7 @@ def blink_class_name(idl_definition):
# is implemented as |class EXTsRGB|, not as |ExtSRgb| nor |ExtsRgb|. # is implemented as |class EXTsRGB|, not as |ExtSRgb| nor |ExtsRgb|.
if isinstance(idl_definition, if isinstance(idl_definition,
(web_idl.CallbackFunction, web_idl.CallbackInterface, (web_idl.CallbackFunction, web_idl.CallbackInterface,
web_idl.Enumeration)): web_idl.Enumeration, web_idl.NewUnion)):
return "V8{}".format(idl_definition.identifier) return "V8{}".format(idl_definition.identifier)
else: else:
return idl_definition.identifier return idl_definition.identifier
......
...@@ -94,9 +94,10 @@ class PathManager(object): ...@@ -94,9 +94,10 @@ class PathManager(object):
components = sorted(idl_definition.components) # "core" < "modules" components = sorted(idl_definition.components) # "core" < "modules"
if len(components) == 0: if len(components) == 0:
assert isinstance(idl_definition, web_idl.Union) assert isinstance(idl_definition,
# Unions of built-in types, e.g. DoubleOrString, do not have a (web_idl.Union, web_idl.NewUnion))
# component. # Unions of built-in types, e.g. (double or DOMString), do not have
# a component.
self._is_cross_components = False self._is_cross_components = False
default_component = web_idl.Component("core") default_component = web_idl.Component("core")
self._api_component = default_component self._api_component = default_component
...@@ -110,10 +111,10 @@ class PathManager(object): ...@@ -110,10 +111,10 @@ class PathManager(object):
assert components[0] == "core" assert components[0] == "core"
assert components[1] == "modules" assert components[1] == "modules"
self._is_cross_components = True self._is_cross_components = True
# Union does not have to support cross-component code generation # Union does not support cross-component code generation because
# because clients of IDL union must be on an upper or same layer to # clients of IDL union must be on an upper or same layer to any of
# any of union members. # union members.
if isinstance(idl_definition, web_idl.Union): if isinstance(idl_definition, (web_idl.Union, web_idl.NewUnion)):
self._api_component = components[1] self._api_component = components[1]
else: else:
self._api_component = components[0] self._api_component = components[0]
...@@ -125,17 +126,29 @@ class PathManager(object): ...@@ -125,17 +126,29 @@ class PathManager(object):
self._impl_dir = self._component_reldirs[self._impl_component] self._impl_dir = self._component_reldirs[self._impl_component]
self._api_basename = name_style.file("v8", idl_definition.identifier) self._api_basename = name_style.file("v8", idl_definition.identifier)
self._impl_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 if isinstance(idl_definition, web_idl.NewUnion):
# produce the same filepaths with the old bindings generator for the # In case of IDL unions, underscore is used as a separator of union
# time being. # members, so we don't want any underscore inside a union member.
if isinstance(idl_definition, web_idl.Union): # For example, (Foo or Bar or Baz) and (FooBar or Baz) are defined
# in v8_union_foo_bar_baz.ext and v8_union_foobar_baz.ext
# respectively.
#
# Avoid name_style.file not to make "Int32Array" into
# "int_32_array".
filename = "V8_{}".format(idl_definition.identifier).lower()
self._api_basename = filename
self._impl_basename = filename
elif isinstance(idl_definition, web_idl.Union):
union_class_name = idl_definition.identifier union_class_name = idl_definition.identifier
union_filepath = _BACKWARD_COMPATIBLE_UNION_FILEPATHS.get( union_filepath = _BACKWARD_COMPATIBLE_UNION_FILEPATHS.get(
union_class_name, union_class_name) union_class_name, union_class_name)
self._api_basename = name_style.file(union_filepath) self._api_basename = name_style.file(union_filepath)
self._impl_basename = name_style.file(union_filepath) self._impl_basename = name_style.file(union_filepath)
if not isinstance(idl_definition, web_idl.Union): if isinstance(idl_definition, (web_idl.Union, web_idl.NewUnion)):
self._blink_dir = None
self._blink_basename = None
else:
idl_path = idl_definition.debug_info.location.filepath idl_path = idl_definition.debug_info.location.filepath
self._blink_dir = posixpath.dirname(idl_path) self._blink_dir = posixpath.dirname(idl_path)
self._blink_basename = name_style.file( self._blink_basename = name_style.file(
......
# 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 web_idl
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 .package_initializer import package_initializer
from .path_manager import PathManager
from .task_queue import TaskQueue
def generate_union(union_identifier):
assert isinstance(union_identifier, web_idl.Identifier)
web_idl_database = package_initializer().web_idl_database()
union = web_idl_database.find(union_identifier)
path_manager = PathManager(union)
assert path_manager.api_component == path_manager.impl_component
api_component = path_manager.api_component
for_testing = union.code_generator_info.for_testing
# Class names
class_name = blink_class_name(union)
cg_context = CodeGenContext(union=union,
class_name=class_name,
base_class_name="bindings::UnionBase")
# 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::UnionBase"],
final=True,
export=component_export(
api_component, for_testing))
class_def.set_base_template_vars(cg_context.template_bindings())
# 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(),
])
# Assemble the parts.
header_node.accumulator.add_include_headers([
component_export_header(api_component, for_testing),
"third_party/blink/renderer/platform/bindings/union_base.h",
])
header_blink_ns.body.append(class_def)
header_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_unions(task_queue):
assert isinstance(task_queue, TaskQueue)
web_idl_database = package_initializer().web_idl_database()
for union in web_idl_database.new_union_types:
task_queue.post_task(generate_union, union.identifier)
...@@ -68,6 +68,7 @@ def main(): ...@@ -68,6 +68,7 @@ def main():
'enumeration': bind_gen.generate_enumerations, 'enumeration': bind_gen.generate_enumerations,
'interface': bind_gen.generate_interfaces, 'interface': bind_gen.generate_interfaces,
'namespace': bind_gen.generate_namespaces, 'namespace': bind_gen.generate_namespaces,
'union': bind_gen.generate_unions,
} }
for task in tasks: for task in tasks:
......
...@@ -46,6 +46,7 @@ bind_gen/package_initializer.py ...@@ -46,6 +46,7 @@ bind_gen/package_initializer.py
bind_gen/path_manager.py bind_gen/path_manager.py
bind_gen/style_format.py bind_gen/style_format.py
bind_gen/task_queue.py bind_gen/task_queue.py
bind_gen/union.py
generate_bindings.py generate_bindings.py
web_idl/__init__.py web_idl/__init__.py
web_idl/argument.py web_idl/argument.py
......
...@@ -95,17 +95,6 @@ inline v8::Local<v8::Value> ToV8(const bindings::EnumerationBase& enumeration, ...@@ -95,17 +95,6 @@ inline v8::Local<v8::Value> ToV8(const bindings::EnumerationBase& enumeration,
return V8String(isolate, enumeration.AsCStr()); return V8String(isolate, enumeration.AsCStr());
} }
// Union type
inline v8::Local<v8::Value> ToV8(const bindings::UnionBase& value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
v8::Local<v8::Value> v8_value =
value.CreateV8Object(isolate, creation_context);
DCHECK(!v8_value.IsEmpty());
return v8_value;
}
// Primitives // Primitives
inline v8::Local<v8::Value> ToV8(const String& value, inline v8::Local<v8::Value> ToV8(const String& value,
......
...@@ -11,31 +11,21 @@ ...@@ -11,31 +11,21 @@
namespace blink { namespace blink {
class Visitor;
namespace bindings { namespace bindings {
// This class is the base class for all IDL dictionary implementations. This // UnionBase is the common base class of all the IDL union classes. Most
// is designed to collaborate with NativeValueTraits and ToV8 with supporting // importantly this class provides a way of type dispatching (e.g. overload
// type dispatching (SFINAE, etc.). // resolutions, SFINAE technique, etc.) so that it's possible to distinguish
class PLATFORM_EXPORT UnionBase { // IDL unions from anything else. Also it provides a common implementation of
DISALLOW_NEW(); // IDL unions.
class PLATFORM_EXPORT UnionBase : public GarbageCollected<UnionBase> {
public: public:
virtual ~UnionBase() = default; virtual ~UnionBase() = default;
virtual v8::Local<v8::Value> CreateV8Object( virtual void Trace(Visitor*) const {}
v8::Isolate* isolate,
v8::Local<v8::Object> creation_context) const = 0;
void Trace(Visitor*) const {}
protected: protected:
UnionBase() = default; UnionBase() = default;
UnionBase(const UnionBase&) = default;
UnionBase(UnionBase&&) = default;
UnionBase& operator=(const UnionBase&) = default;
UnionBase& operator=(UnionBase&&) = default;
}; };
} // namespace bindings } // namespace bindings
......
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