Index: third_party/WebKit/Source/bindings/scripts/code_generator_v8.py |
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py |
index 5f89b681dd9301689777ee11fedf88fea3b3de62..3852bd18b703764bee1b4b8fbbc9bb15d88996a4 100644 |
--- a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py |
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py |
@@ -129,15 +129,20 @@ def should_generate_code(definitions): |
return definitions.interfaces or definitions.dictionaries |
-def depends_on_union_types(idl_type): |
- """Returns true when a given idl_type depends on union containers |
- directly. |
+def depending_union_type_name(idl_type): |
+ """Returns the union type name if the given idl_type depends on a |
+ union type. |
""" |
- if idl_type.is_union_type: |
- return True |
- if idl_type.is_array_or_sequence_type: |
- return idl_type.element_type.is_union_type |
- return False |
+ def find_base_type(current_type): |
+ if current_type.is_array_or_sequence_type: |
+ return find_base_type(current_type.element_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.name |
+ return None |
class TypedefResolver(Visitor): |
@@ -149,16 +154,14 @@ class TypedefResolver(Visitor): |
self.typedefs = {} |
for name, typedef in self.info_provider.typedefs.iteritems(): |
self.typedefs[name] = typedef.idl_type |
- self.additional_includes = set() |
+ self.additional_header_includes = set() |
definitions.accept(self) |
self._update_dependencies_include_paths(definition_name) |
def _update_dependencies_include_paths(self, definition_name): |
interface_info = self.info_provider.interfaces_info[definition_name] |
- dependencies_include_paths = interface_info['dependencies_include_paths'] |
- for include_path in self.additional_includes: |
- if include_path not in dependencies_include_paths: |
- dependencies_include_paths.append(include_path) |
+ interface_info['additional_header_includes'] = set( |
+ self.additional_header_includes) |
def _resolve_typedefs(self, typed_object): |
"""Resolve typedefs to actual types in the object.""" |
@@ -170,9 +173,13 @@ class TypedefResolver(Visitor): |
if not idl_type: |
continue |
resolved_idl_type = idl_type.resolve_typedefs(self.typedefs) |
- if depends_on_union_types(resolved_idl_type): |
- self.additional_includes.add( |
- self.info_provider.include_path_for_union_types) |
+ # TODO(bashi): Dependency resolution shouldn't happen here. |
+ # Move this into includes_for_type() families. |
+ union_type_name = depending_union_type_name(resolved_idl_type) |
+ if union_type_name: |
+ self.additional_header_includes.add( |
+ self.info_provider.include_path_for_union_types( |
+ union_type_name)) |
# 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) |
@@ -265,7 +272,8 @@ class CodeGeneratorV8(CodeGeneratorBase): |
template_context['header_includes'].add('core/dom/DOMTypedArray.h') |
elif 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_template = self.jinja_env.get_template(header_template_filename) |
cpp_template = self.jinja_env.get_template(cpp_template_filename) |
header_text, cpp_text = render_template( |
@@ -323,16 +331,11 @@ class CodeGeneratorDictionaryImpl(CodeGeneratorBase): |
template_context = v8_dictionary.dictionary_impl_context( |
dictionary, interfaces_info) |
include_paths = interface_info.get('dependencies_include_paths') |
- # Add union containers header file to header_includes rather than |
- # cpp file so that union containers can be used in dictionary headers. |
- union_container_headers = [header for header in include_paths |
- if header.find('UnionTypes') > 0] |
- include_paths = [header for header in include_paths |
- if header not in union_container_headers] |
- template_context['header_includes'].update(union_container_headers) |
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['header_includes'].update( |
+ interface_info.get('additional_header_includes', [])) |
header_text, cpp_text = render_template( |
include_paths, header_template, cpp_template, template_context) |
header_path, cpp_path = self.output_paths( |
@@ -356,45 +359,53 @@ class CodeGeneratorUnionType(object): |
self.target_component = target_component |
set_global_type_info(info_provider) |
- def generate_code(self): |
- union_types = self.info_provider.union_types |
- if not union_types: |
- return () |
- header_template = self.jinja_env.get_template('union.h') |
- cpp_template = self.jinja_env.get_template('union.cpp') |
- template_context = v8_union.union_context( |
- union_types, self.info_provider.interfaces_info) |
+ def _generate_container_code(self, union_type): |
+ header_template = self.jinja_env.get_template('union_container.h') |
+ cpp_template = self.jinja_env.get_template('union_container.cpp') |
+ template_context = v8_union.container_context( |
+ union_type, self.info_provider.interfaces_info) |
+ template_context['header_includes'].append( |
+ self.info_provider.include_path_for_export) |
+ template_context['header_includes'] = normalize_and_sort_includes( |
+ template_context['header_includes']) |
template_context['code_generator'] = module_pyname |
- capitalized_component = self.target_component.capitalize() |
template_context['exported'] = self.info_provider.specifier_for_export |
- template_context['header_filename'] = 'bindings/%s/v8/UnionTypes%s.h' % ( |
- self.target_component, capitalized_component) |
- template_context['macro_guard'] = 'UnionType%s_h' % capitalized_component |
- additional_header_includes = [self.info_provider.include_path_for_export] |
- |
- # Add UnionTypesCore.h as a dependency when we generate modules union types |
- # because we only generate union type containers which are used by both |
- # core and modules in UnionTypesCore.h. |
- # FIXME: This is an ad hoc workaround and we need a general way to |
- # handle core <-> modules dependency. |
- if self.target_component == 'modules': |
- additional_header_includes.append( |
- 'bindings/core/v8/UnionTypesCore.h') |
- |
- template_context['header_includes'] = normalize_and_sort_includes( |
- template_context['header_includes'] + additional_header_includes) |
- |
header_text = header_template.render(template_context) |
cpp_text = cpp_template.render(template_context) |
- header_path = posixpath.join(self.output_dir, |
- 'UnionTypes%s.h' % capitalized_component) |
- cpp_path = posixpath.join(self.output_dir, |
- 'UnionTypes%s.cpp' % capitalized_component) |
+ name = union_type.cpp_type |
+ header_path = posixpath.join(self.output_dir, '%s.h' % name) |
+ cpp_path = posixpath.join(self.output_dir, '%s.cpp' % name) |
return ( |
(header_path, header_text), |
(cpp_path, cpp_text), |
) |
+ def _get_union_types_for_containers(self): |
+ union_types = self.info_provider.union_types |
+ if not union_types: |
+ return None |
+ # For container classes we strip nullable wrappers. For example, |
+ # both (A or B)? and (A? or B) will become AOrB. This should be OK |
+ # because container classes can handle null and it seems that |
+ # distinguishing (A or B)? and (A? or B) doesn't make sense. |
+ container_cpp_types = set() |
+ union_types_for_containers = set() |
+ for union_type in union_types: |
+ cpp_type = union_type.cpp_type |
+ if cpp_type not in container_cpp_types: |
+ union_types_for_containers.add(union_type) |
+ container_cpp_types.add(cpp_type) |
+ return union_types_for_containers |
+ |
+ def generate_code(self): |
+ union_types = self._get_union_types_for_containers() |
+ if not union_types: |
+ return () |
+ outputs = set() |
+ for union_type in union_types: |
+ outputs.update(self._generate_container_code(union_type)) |
+ return outputs |
+ |
def initialize_jinja_env(cache_dir): |
jinja_env = jinja2.Environment( |