Index: bindings/scripts/code_generator_v8.py |
diff --git a/bindings/scripts/code_generator_v8.py b/bindings/scripts/code_generator_v8.py |
index 778a87ec79b9d11b1959bd6d4f80820616e90b29..272b611c34fa69196540cdcf73c0a8ab0a1a0b36 100644 |
--- a/bindings/scripts/code_generator_v8.py |
+++ b/bindings/scripts/code_generator_v8.py |
@@ -73,17 +73,34 @@ import jinja2 |
import idl_types |
from idl_types import IdlType |
import v8_callback_interface |
+import v8_dictionary |
from v8_globals import includes, interfaces |
import v8_interface |
import v8_types |
from v8_utilities import capitalize, cpp_name, conditional_string, v8_class_name |
+def render_template(interface_info, header_template, cpp_template, |
+ template_context): |
+ template_context['code_generator'] = module_pyname |
+ |
+ # Add includes for any dependencies |
+ template_context['header_includes'] = sorted( |
+ template_context['header_includes']) |
+ includes.update(interface_info.get('dependencies_include_paths', [])) |
+ template_context['cpp_includes'] = sorted(includes) |
+ |
+ header_text = header_template.render(template_context) |
+ cpp_text = cpp_template.render(template_context) |
+ return header_text, cpp_text |
+ |
+ |
class CodeGeneratorV8(object): |
- def __init__(self, interfaces_info, cache_dir): |
+ def __init__(self, interfaces_info, cache_dir, output_dir): |
interfaces_info = interfaces_info or {} |
self.interfaces_info = interfaces_info |
self.jinja_env = initialize_jinja_env(cache_dir) |
+ self.output_dir = output_dir |
# Set global type info |
idl_types.set_ancestors(dict( |
@@ -94,6 +111,10 @@ class CodeGeneratorV8(object): |
interface_name |
for interface_name, interface_info in interfaces_info.iteritems() |
if interface_info['is_callback_interface'])) |
+ IdlType.set_dictionaries(set( |
+ dictionary_name |
+ for dictionary_name, interface_info in interfaces_info.iteritems() |
+ if interface_info['is_dictionary'])) |
IdlType.set_implemented_as_interfaces(dict( |
(interface_name, interface_info['implemented_as']) |
for interface_name, interface_info in interfaces_info.iteritems() |
@@ -110,48 +131,100 @@ class CodeGeneratorV8(object): |
(interface_name, interface_info['component_dir']) |
for interface_name, interface_info in interfaces_info.iteritems())) |
- def generate_code(self, definitions, interface_name): |
- """Returns .h/.cpp code as (header_text, cpp_text).""" |
- try: |
- interface = definitions.interfaces[interface_name] |
- except KeyError: |
- raise Exception('%s not in IDL definitions' % interface_name) |
+ def output_paths_for_bindings(self, definition_name): |
+ header_path = posixpath.join(self.output_dir, |
+ 'V8%s.h' % definition_name) |
+ cpp_path = posixpath.join(self.output_dir, 'V8%s.cpp' % definition_name) |
+ return header_path, cpp_path |
- # Store other interfaces for introspection |
- interfaces.update(definitions.interfaces) |
+ def output_paths_for_impl(self, definition_name): |
+ header_path = posixpath.join(self.output_dir, '%s.h' % definition_name) |
+ cpp_path = posixpath.join(self.output_dir, '%s.cpp' % definition_name) |
+ return header_path, cpp_path |
+ def generate_code(self, definitions, definition_name): |
+ """Returns .h/.cpp code as (header_text, cpp_text).""" |
# Set local type info |
IdlType.set_callback_functions(definitions.callback_functions.keys()) |
IdlType.set_enums((enum.name, enum.values) |
for enum in definitions.enumerations.values()) |
+ if definition_name in definitions.interfaces: |
+ return self.generate_interface_code( |
+ definitions, definition_name, |
+ definitions.interfaces[definition_name]) |
+ if definition_name in definitions.dictionaries: |
+ return self.generate_dictionary_code( |
+ definitions, definition_name, |
+ definitions.dictionaries[definition_name]) |
+ raise ValueError('%s is not in IDL definitions' % definition_name) |
+ |
+ def generate_interface_code(self, definitions, interface_name, interface): |
+ # Store other interfaces for introspection |
+ interfaces.update(definitions.interfaces) |
+ |
# Select appropriate Jinja template and contents function |
if interface.is_callback: |
header_template_filename = 'callback_interface.h' |
cpp_template_filename = 'callback_interface.cpp' |
- generate_contents = v8_callback_interface.generate_callback_interface |
+ interface_context = v8_callback_interface.callback_interface_context |
else: |
header_template_filename = 'interface.h' |
cpp_template_filename = 'interface.cpp' |
- generate_contents = v8_interface.generate_interface |
+ interface_context = v8_interface.interface_context |
header_template = self.jinja_env.get_template(header_template_filename) |
cpp_template = self.jinja_env.get_template(cpp_template_filename) |
- # Generate contents (input parameters for Jinja) |
- template_contents = generate_contents(interface) |
- template_contents['code_generator'] = module_pyname |
- |
- # Add includes for interface itself and any dependencies |
interface_info = self.interfaces_info[interface_name] |
- template_contents['header_includes'].add(interface_info['include_path']) |
- template_contents['header_includes'] = sorted(template_contents['header_includes']) |
- includes.update(interface_info.get('dependencies_include_paths', [])) |
- template_contents['cpp_includes'] = sorted(includes) |
- # Render Jinja templates |
- header_text = header_template.render(template_contents) |
- cpp_text = cpp_template.render(template_contents) |
- return header_text, cpp_text |
+ template_context = interface_context(interface) |
+ # Add the include for interface itself |
+ template_context['header_includes'].add(interface_info['include_path']) |
+ header_text, cpp_text = render_template( |
+ interface_info, header_template, cpp_template, template_context) |
+ header_path, cpp_path = self.output_paths_for_bindings(interface_name) |
+ return ( |
+ (header_path, header_text), |
+ (cpp_path, cpp_text), |
+ ) |
+ |
+ def generate_dictionary_code(self, definitions, dictionary_name, |
+ dictionary): |
+ interface_info = self.interfaces_info[dictionary_name] |
+ bindings_results = self.generate_dictionary_bindings( |
+ dictionary_name, interface_info, dictionary) |
+ impl_results = self.generate_dictionary_impl( |
+ dictionary_name, interface_info, dictionary) |
+ return bindings_results + impl_results |
+ |
+ def generate_dictionary_bindings(self, dictionary_name, |
+ interface_info, dictionary): |
+ header_template = self.jinja_env.get_template('dictionary_v8.h') |
+ cpp_template = self.jinja_env.get_template('dictionary_v8.cpp') |
+ template_context = v8_dictionary.dictionary_context(dictionary) |
+ # Add the include for interface itself |
+ template_context['header_includes'].add(interface_info['include_path']) |
+ header_text, cpp_text = render_template( |
+ interface_info, header_template, cpp_template, template_context) |
+ header_path, cpp_path = self.output_paths_for_bindings(dictionary_name) |
+ return ( |
+ (header_path, header_text), |
+ (cpp_path, cpp_text), |
+ ) |
+ |
+ def generate_dictionary_impl(self, dictionary_name, |
+ interface_info, dictionary): |
+ header_template = self.jinja_env.get_template('dictionary_impl.h') |
+ cpp_template = self.jinja_env.get_template('dictionary_impl.cpp') |
+ template_context = v8_dictionary.dictionary_impl_context( |
+ dictionary, self.interfaces_info) |
+ header_text, cpp_text = render_template( |
+ interface_info, header_template, cpp_template, template_context) |
+ header_path, cpp_path = self.output_paths_for_impl(dictionary_name) |
+ return ( |
+ (header_path, header_text), |
+ (cpp_path, cpp_text), |
+ ) |
def initialize_jinja_env(cache_dir): |
@@ -166,11 +239,21 @@ def initialize_jinja_env(cache_dir): |
jinja_env.filters.update({ |
'blink_capitalize': capitalize, |
'conditional': conditional_if_endif, |
+ 'exposed': exposed_if, |
+ 'per_context_enabled': per_context_enabled_if, |
'runtime_enabled': runtime_enabled_if, |
}) |
return jinja_env |
+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) |
+ |
+ |
# [Conditional] |
def conditional_if_endif(code, conditional_string): |
# Jinja2 filter to generate if/endif directive blocks |
@@ -181,15 +264,25 @@ def conditional_if_endif(code, conditional_string): |
'#endif // %s\n' % conditional_string) |
+# [Exposed] |
+def exposed_if(code, exposed_test): |
+ if not exposed_test: |
+ return code |
+ return generate_indented_conditional(code, 'context && (%s)' % exposed_test) |
+ |
+ |
+# [PerContextEnabled] |
+def per_context_enabled_if(code, per_context_enabled_function): |
+ if not per_context_enabled_function: |
+ return code |
+ return generate_indented_conditional(code, 'context && context->isDocument() && %s(toDocument(context))' % per_context_enabled_function) |
+ |
+ |
# [RuntimeEnabled] |
def runtime_enabled_if(code, runtime_enabled_function_name): |
if not runtime_enabled_function_name: |
return code |
- # Indent if statement to level of original code |
- indent = re.match(' *', code).group(0) |
- return ('%sif (%s()) {\n' % (indent, runtime_enabled_function_name) + |
- ' %s\n' % '\n '.join(code.splitlines()) + |
- '%s}\n' % indent) |
+ return generate_indented_conditional(code, '%s()' % runtime_enabled_function_name) |
################################################################################ |