| Index: Source/bindings/scripts/code_generator_web_modules.py
|
| diff --git a/Source/bindings/scripts/code_generator_web_modules.py b/Source/bindings/scripts/code_generator_web_modules.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ffad01ab66506ff422cdd8521d9cae92179a7e24
|
| --- /dev/null
|
| +++ b/Source/bindings/scripts/code_generator_web_modules.py
|
| @@ -0,0 +1,134 @@
|
| +# Copyright 2015 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 Blink WebModules bindings (.h and .cpp files).
|
| +
|
| +These are used to expose C++ bindings to the rest of Blink for building
|
| +features on top of web APIs instead of baking them into the core code.
|
| +The way these APIs work is to wrap a pointer to the underlying type and
|
| +then pass the wrapped thing by value. Compilers will optimize the
|
| +wrapper out entirely, so there is no performance overhead, but lets
|
| +us enforce that a strictly controlled API surface is exposed to the calling
|
| +code.
|
| +
|
| +We don't want to expose the bad parts of the platform, so we only expose
|
| +APIs that have the WebModulesExposed annotation.
|
| +
|
| +Input: An object of class IdlDefinitions, containing an IDL interface X
|
| +Output: WebModuleX.h and WebModuleX.cpp
|
| +
|
| +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
|
| +"""
|
| +
|
| +import os
|
| +import posixpath
|
| +import sys
|
| +
|
| +# TODO(ojan): Share this path handling code with code_generator_v8.py..
|
| +
|
| +# Path handling for libraries and templates
|
| +# Paths have to be normalized because Jinja uses the exact template path to
|
| +# determine the hash used in the cache filename, and we need a pre-caching step
|
| +# to be concurrency-safe. Use absolute path because __file__ is absolute if
|
| +# module is imported, and relative if executed directly.
|
| +# If paths differ between pre-caching and individual file compilation, the cache
|
| +# 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, module_filename = 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'))
|
| +# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
|
| +module_pyname = os.path.splitext(module_filename)[0] + '.py'
|
| +
|
| +# jinja2 is in chromium's third_party directory.
|
| +# Insert at 1 so at front to override system libraries, and
|
| +# after path[0] == invoking script dir
|
| +sys.path.insert(1, third_party_dir)
|
| +import jinja2
|
| +
|
| +from v8_utilities import cpp_name
|
| +from utilities import idl_filename_to_component
|
| +
|
| +
|
| +def initialize_jinja_env(cache_dir):
|
| + return jinja2.Environment(
|
| + loader=jinja2.FileSystemLoader(templates_dir),
|
| + # Bytecode cache is not concurrency-safe unless pre-cached:
|
| + # if pre-cached this is read-only, but writing creates a race condition.
|
| + bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
|
| + keep_trailing_newline=True, # newline-terminate generated files
|
| + lstrip_blocks=True, # so can indent control flow tags
|
| + trim_blocks=True)
|
| +
|
| +
|
| +def web_modules_class_name(interface_name):
|
| + return "WebModule" + interface_name
|
| +
|
| +
|
| +def includes_for_type(component, idl_type):
|
| + base_idl_type = idl_type.preprocessed_type.base_type
|
| +
|
| + # TODO(ojan): Make this work for things that have more dependencies (e.g. NodeLists).
|
| + # e.g. see v8_types.includes_for_type.
|
| + return set(['bindings/%s/webmodules/WebModule%s.h' % (component, base_idl_type)])
|
| +
|
| +
|
| +class Attribute(object):
|
| + def __init__(self, name, idl_type):
|
| + self.name = name
|
| + self.idl_type = idl_type
|
| +
|
| +
|
| +class CodeGeneratorWebModules(object):
|
| + def __init__(self, info_provider, cache_dir, output_dir):
|
| + self.info_provider = info_provider
|
| + self.jinja_env = initialize_jinja_env(cache_dir)
|
| + self.output_dir = output_dir
|
| +
|
| + def generate_code(self, definitions, definition_name):
|
| + """Returns .h/.cpp code as ((path, content)...)."""
|
| + # TODO(ojan): Make this work for dictionaries as well.
|
| + assert(definition_name in definitions.interfaces)
|
| + return self.generate_interface_code(
|
| + definitions, definition_name,
|
| + definitions.interfaces[definition_name])
|
| +
|
| + def generate_interface_code(self, definitions, interface_name, interface):
|
| + interface_info = self.info_provider.interfaces_info[interface_name]
|
| + full_path = interface_info.get('full_path')
|
| + component = idl_filename_to_component(full_path)
|
| +
|
| + attributes = []
|
| + type_includes = set()
|
| + for attribute in interface.attributes:
|
| + if 'WebModulesExposed' in attribute.extended_attributes:
|
| + type_includes = type_includes.union(
|
| + includes_for_type(component, attribute.idl_type))
|
| +
|
| + # TODO(ojan): handle void return types
|
| + return_type = 'WebModule%s' % attribute.idl_type.preprocessed_type.base_type
|
| + attribute = Attribute(cpp_name(attribute), return_type)
|
| + attributes.append(attribute)
|
| +
|
| + template_context = {
|
| + 'class_name': web_modules_class_name(interface_name),
|
| + 'header_includes': sorted([
|
| + interface_info['include_path'],
|
| + ] + list(type_includes)),
|
| + 'attributes': attributes,
|
| + 'interface_name': interface_name
|
| + }
|
| +
|
| + header_path = posixpath.join(self.output_dir, 'WebModule%s.h' % interface_name)
|
| + cpp_path = posixpath.join(self.output_dir, 'WebModule%s.cpp' % interface_name)
|
| +
|
| + header_template = self.jinja_env.get_template('web_modules_interface.h')
|
| + cpp_template = self.jinja_env.get_template('web_modules_interface.cpp')
|
| +
|
| + return (
|
| + (header_path, header_template.render(template_context)),
|
| + (cpp_path, cpp_template.render(template_context)),
|
| + )
|
|
|