diff options
author | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-20 21:33:12 +0000 |
---|---|---|
committer | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-20 21:33:12 +0000 |
commit | d2eafd1bfcfe59e1d81d3f73a4473d1f1dd9e4b2 (patch) | |
tree | 43824a87f7664602c42eaf6eec012c70374b10af | |
parent | 659fe72aab8116c77a2dc46b38368ad8d02bdf8a (diff) | |
download | chromium_src-d2eafd1bfcfe59e1d81d3f73a4473d1f1dd9e4b2.zip chromium_src-d2eafd1bfcfe59e1d81d3f73a4473d1f1dd9e4b2.tar.gz chromium_src-d2eafd1bfcfe59e1d81d3f73a4473d1f1dd9e4b2.tar.bz2 |
Add JavaScript support to Mojo's bindings generator
This CL contains a first iteration of a JavaScript backend for Mojo's IPC
bindings generator. The generated code closely matches the hand-written
bindings for simple_service.js, although the generated message is off in a few
places.
This backend successfully generates code for hello_world_service.mojom and
math_calculator.mojom, but do not appear to be computing implicit ordinals yet,
which means these generated files not yet work. I'll fix these issues in the
next iteration.
Unlike the CPP backend, this JS backend uses jinja2 templates. If we're happy
with this approach, we'll likely port the CPP backend to jinja2 as well.
R=davemoore@chromium.org
BUG=317398
Review URL: https://codereview.chromium.org/77153003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236304 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | mojo/public/bindings/generators/js_templates/module.js.tmpl | 125 | ||||
-rw-r--r-- | mojo/public/bindings/generators/mojom_cpp_generator.py | 53 | ||||
-rw-r--r-- | mojo/public/bindings/generators/mojom_generator.py | 31 | ||||
-rw-r--r-- | mojo/public/bindings/generators/mojom_js_generator.py | 176 | ||||
-rw-r--r-- | mojo/public/bindings/generators/mojom_pack.py | 33 | ||||
-rw-r--r-- | mojo/public/bindings/generators/template_expander.py | 41 | ||||
-rw-r--r-- | mojo/public/bindings/js/codec.js | 21 | ||||
-rw-r--r-- | mojo/public/bindings/mojom_bindings_generator.gypi | 7 | ||||
-rwxr-xr-x | mojo/public/bindings/mojom_bindings_generator.py | 4 |
9 files changed, 452 insertions, 39 deletions
diff --git a/mojo/public/bindings/generators/js_templates/module.js.tmpl b/mojo/public/bindings/generators/js_templates/module.js.tmpl new file mode 100644 index 0000000..b13aaab7 --- /dev/null +++ b/mojo/public/bindings/generators/js_templates/module.js.tmpl @@ -0,0 +1,125 @@ +// Copyright 2013 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. + +define([ + "mojo/public/bindings/js/core", + "mojo/public/bindings/js/codec", + ], function(core, codec) { +{%- for struct in structs %} + + function {{struct.name}}() { +{%- for packed_field in struct.packed.packed_fields %} + this.{{packed_field.field.name}} = {{packed_field.field|default_value}}; +{%- endfor %} + } + + {{struct.name}}.encodedSize = codec.kStructHeaderSize + {{struct.packed|payload_size}}; + + {{struct.name}}.decode = function(decoder) { + var packed; + var val = new {{struct.name}}(); + var numberOfBytes = decoder.read32(); + var numberOfFields = decoder.read32(); +{%- for byte in struct.bytes %} +{%- if byte.packed_fields|length > 1 %} + packed = decoder.read8(); +{%- for packed_field in byte.packed_fields %} + val.{{packed_field.field.name}} = (packed >> {{packed_field.bit}}) & 1 ? true : false; +{%- endfor %} +{%- else %} +{%- for packed_field in byte.packed_fields %} + val.{{packed_field.field.name}} = decoder.{{packed_field.field.kind|decode_snippet}}; +{%- endfor %} +{%- endif %} +{%- if byte.is_padding %} + decoder.skip(1); +{%- endif %} +{%- endfor %} + return val; + }; + + {{struct.name}}.encode = function(encoder, val) { + var packed; + encoder.write32({{struct.name}}.encodedSize); + encoder.write32({{struct.packed.packed_fields|length}}); + +{%- for byte in struct.bytes %} +{%- if byte.packed_fields|length > 1 %} + packed = 0; +{%- for packed_field in byte.packed_fields %} + packed |= (val.{{packed_field.field.name}} & 1) << {{packed_field.bit}} +{%- endfor %} + encoder.write8(packed); +{%- else %} +{%- for packed_field in byte.packed_fields %} + encoder.{{packed_field.field.kind|encode_snippet}}val.{{packed_field.field.name}}); +{%- endfor %} +{%- endif %} +{%- if byte.is_padding %} + encoder.skip(1); +{%- endif %} +{%- endfor %} + }; +{%- endfor %} + +{%- for interface in interfaces %} +{%- for method in interface.methods %} + var k{{interface.name}}_{{method.name}}_Name = {{method.ordinal}}; +{%- endfor %} + + function {{interface.name}}Proxy(receiver) { + this.receiver_ = receiver; + } + +{%- for method in interface.methods %} + {{interface.name}}Proxy.prototype.{{method.name}} = function( +{%- for parameter in method.parameters -%} +{{parameter.name}}{% if not loop.last %}, {% endif %} +{%- endfor %}) { + var params = new {{interface.name}}_{{method.name}}_Params(); +{%- for parameter in method.parameters %} + params.{{parameter.name}} = {{parameter.name}}; +{%- endfor %} + + var builder = new codec.MessageBuilder( + k{{interface.name}}_{{method.name}}_Name, + codec.align({{interface.name}}_{{method.name}}_Params.encodedSize)); + builder.encodeStruct({{interface.name}}_{{method.name}}_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; +{%- endfor %} + + function {{interface.name}}Stub() { + } + + {{interface.name}}Stub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { +{%- for method in interface.methods %} + case k{{interface.name}}_{{method.name}}_Name: + var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params); + this.{{method.name}}( +{%- for parameter in method.parameters -%} +params.{{parameter.name}}{% if not loop.last %}, {% endif %} +{%- endfor %}); + return true; +{%- endfor %} + default: + return false; + } + }; + +{%- endfor %} + + var exports = {}; +{%- for struct in structs if struct.exported %} + exports.{{struct.name}} = {{struct.name}}; +{%- endfor %} +{%- for interface in interfaces %} + exports.{{interface.name}}Proxy = {{interface.name}}Proxy; + exports.{{interface.name}}Stub = {{interface.name}}Stub; +{%- endfor %} + return exports; +}); diff --git a/mojo/public/bindings/generators/mojom_cpp_generator.py b/mojo/public/bindings/generators/mojom_cpp_generator.py index a34a5b5..813491c 100644 --- a/mojo/public/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/bindings/generators/mojom_cpp_generator.py @@ -6,6 +6,7 @@ import datetime import mojom +import mojom_generator import mojom_pack import os import re @@ -39,22 +40,7 @@ class Lines(object): return '\n'.join(self.lines) -def GetStructFromMethod(interface, method): - """Converts a method's parameters into the fields of a struct.""" - params_class = "%s_%s_Params" % (interface.name, method.name) - struct = mojom.Struct(params_class) - for param in method.parameters: - struct.AddField(param.name, param.kind, param.ordinal) - return struct - -def IsPointerKind(kind): - return isinstance(kind, (mojom.Struct, mojom.Array)) or kind.spec == 's' - -def CamelToUnderscores(camel): - s = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel) - return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s).lower() - -class CPPGenerator(object): +class CPPGenerator(mojom_generator.Generator): struct_serialization_compute_template = \ Template(" +\n mojo::internal::ComputeSizeOf($NAME->$FIELD())") @@ -139,7 +125,7 @@ class CPPGenerator(object): @classmethod def GetGetterLine(cls, field): subs = {'FIELD': field.name, 'TYPE': cls.GetType(field.kind)} - if IsPointerKind(field.kind): + if mojom_generator.IsPointerKind(field.kind): return cls.ptr_getter_template.substitute(subs) else: return cls.getter_template.substitute(subs) @@ -147,7 +133,7 @@ class CPPGenerator(object): @classmethod def GetSetterLine(cls, field): subs = {'FIELD': field.name, 'TYPE': cls.GetType(field.kind)} - if IsPointerKind(field.kind): + if mojom_generator.IsPointerKind(field.kind): return cls.ptr_setter_template.substitute(subs) else: return cls.setter_template.substitute(subs) @@ -182,7 +168,7 @@ class CPPGenerator(object): def GetSerializedFields(cls, ps): fields = [] for pf in ps.packed_fields: - if IsPointerKind(pf.field.kind): + if mojom_generator.IsPointerKind(pf.field.kind): fields.append(pf.field) return fields @@ -199,21 +185,14 @@ class CPPGenerator(object): (self.module.name.upper(), name.upper()) def GetHeaderFile(self, *components): - components = map(lambda c: CamelToUnderscores(c), components) + components = map(mojom_generator.CamelToUnderscores, components) component_string = '_'.join(components) return os.path.join(self.header_dir, "%s.h" % component_string) - # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all files - # to stdout. - def __init__(self, module, header_dir, output_dir=None): - self.module = module - self.header_dir = header_dir - self.output_dir = output_dir - def WriteTemplateToFile(self, template_name, **substitutions): template = self.GetTemplate(template_name) - filename = \ - template_name.replace("module", CamelToUnderscores(self.module.name)) + filename = template_name.replace( + "module", mojom_generator.CamelToUnderscores(self.module.name)) substitutions['YEAR'] = datetime.date.today().year substitutions['NAMESPACE'] = self.module.namespace if self.output_dir is None: @@ -252,15 +231,13 @@ class CPPGenerator(object): if pad > 0: fields.append(self.pad_template.substitute(COUNT=pad_count, PAD=pad)) pad_count += 1 - size = offset + pad - else: - size = 0 + subs.update( CLASS = name, SETTERS = '\n'.join(setters), GETTERS = '\n'.join(getters), FIELDS = '\n'.join(fields), - SIZE = size + self.HEADER_SIZE) + SIZE = ps.GetTotalSize() + self.HEADER_SIZE) return template.substitute(subs) def GetStructSerialization( @@ -345,7 +322,7 @@ class CPPGenerator(object): INTERFACE_STUB_DECLARATIONS = self.GetInterfaceStubDeclarations()) def GetParamsDefinition(self, interface, method, next_id): - struct = GetStructFromMethod(interface, method) + struct = mojom_generator.GetStructFromMethod(interface, method) method_name = "k%s_%s_Name" % (interface.name, method.name) if method.ordinal is not None: next_id = method.ordinal @@ -372,7 +349,7 @@ class CPPGenerator(object): sets = [] computes = Lines(self.param_struct_compute_template) for param in method.parameters: - if IsPointerKind(param.kind): + if mojom_generator.IsPointerKind(param.kind): sets.append( self.param_struct_set_template.substitute(NAME=param.name)) computes.Add(NAME=param.name) @@ -406,7 +383,7 @@ class CPPGenerator(object): def GetStructSerializationDefinition(self, struct): ps = mojom_pack.PackedStruct(struct) - param_name = CamelToUnderscores(struct.name) + param_name = mojom_generator.CamelToUnderscores(struct.name) clones = Lines(self.struct_serialization_clone_template) sizes = " return sizeof(*%s)" % param_name @@ -435,7 +412,7 @@ class CPPGenerator(object): serializations = [] for interface in self.module.interfaces: for method in interface.methods: - struct = GetStructFromMethod(interface, method) + struct = mojom_generator.GetStructFromMethod(interface, method) ps = mojom_pack.PackedStruct(struct) serializations.append(self.GetStructSerialization( struct.name, @@ -470,7 +447,7 @@ class CPPGenerator(object): def GenerateModuleInternalHeader(self): traits = map( lambda s: self.GetTemplate("struct_serialization_traits").substitute( - NAME = CamelToUnderscores(s.name), + NAME = mojom_generator.CamelToUnderscores(s.name), FULL_CLASS = "%s::%s" % (self.module.namespace, s.name)), self.module.structs); self.WriteTemplateToFile("module_internal.h", diff --git a/mojo/public/bindings/generators/mojom_generator.py b/mojo/public/bindings/generators/mojom_generator.py new file mode 100644 index 0000000..06c59e4 --- /dev/null +++ b/mojo/public/bindings/generators/mojom_generator.py @@ -0,0 +1,31 @@ +# Copyright 2013 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. + +"""Code shared by the various language-specific code generators.""" + +import mojom +import re + +def GetStructFromMethod(interface, method): + """Converts a method's parameters into the fields of a struct.""" + params_class = "%s_%s_Params" % (interface.name, method.name) + struct = mojom.Struct(params_class) + for param in method.parameters: + struct.AddField(param.name, param.kind, param.ordinal) + return struct + +def IsPointerKind(kind): + return isinstance(kind, (mojom.Struct, mojom.Array)) or kind.spec == 's' + +def CamelToUnderscores(camel): + s = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel) + return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s).lower() + +class Generator(object): + # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all files + # to stdout. + def __init__(self, module, header_dir, output_dir=None): + self.module = module + self.header_dir = header_dir + self.output_dir = output_dir diff --git a/mojo/public/bindings/generators/mojom_js_generator.py b/mojo/public/bindings/generators/mojom_js_generator.py new file mode 100644 index 0000000..e1099be --- /dev/null +++ b/mojo/public/bindings/generators/mojom_js_generator.py @@ -0,0 +1,176 @@ +# Copyright 2013 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. + +"""Generates JS source files from a mojom.Module.""" + +import os +import mojom +import mojom_pack + +from functools import partial +from template_expander import UseJinja +from mojom_generator import Generator, GetStructFromMethod, CamelToUnderscores + +_kind_to_default_value = { + mojom.BOOL: "false", + mojom.INT8: "0", + mojom.UINT8: "0", + mojom.INT16: "0", + mojom.UINT16: "0", + mojom.INT32: "0", + mojom.UINT32: "0", + mojom.FLOAT: "0", + mojom.HANDLE: "codec.kInvalidHandle", + mojom.INT64: "0", + mojom.UINT64: "0", + mojom.DOUBLE: "0", + mojom.STRING: '""', +} + + +def DefaultValue(field): + if field.default: + return field.default + if field.kind in mojom.PRIMITIVES: + return _kind_to_default_value[field.kind] + if isinstance(field.kind, mojom.Struct): + return "null"; + if isinstance(field.kind, mojom.Array): + return "[]"; + + +def PayloadSize(packed): + packed_fields = packed.packed_fields + if not packed_fields: + return 0; + last_field = packed_fields[-1] + offset = last_field.offset + last_field.size + pad = mojom_pack.GetPad(offset, 8) + return offset + pad; + + +_kind_to_javascript_type = { + mojom.BOOL: "codec.Uint8", + mojom.INT8: "codec.Int8", + mojom.UINT8: "codec.Uint8", + mojom.INT16: "codec.Int16", + mojom.UINT16: "codec.Uint16", + mojom.INT32: "codec.Int32", + mojom.UINT32: "codec.Uint32", + mojom.FLOAT: "codec.Float", + mojom.HANDLE: "codec.Handle", + mojom.INT64: "codec.Int64", + mojom.UINT64: "codec.Uint64", + mojom.DOUBLE: "codec.Double", + mojom.STRING: "codec.String", +} + + +def GetJavaScriptType(kind): + if kind in mojom.PRIMITIVES: + return _kind_to_javascript_type[kind] + if isinstance(kind, mojom.Struct): + return "new codec.PointerTo(%s)" % GetJavaScriptType(kind.name) + if isinstance(kind, mojom.Array): + return "new codec.ArrayOf(%s)" % GetJavaScriptType(kind.kind) + return kind + + +_kind_to_decode_snippet = { + mojom.BOOL: "read8() & 1", + mojom.INT8: "read8()", + mojom.UINT8: "read8()", + mojom.INT16: "read16()", + mojom.UINT16: "read16()", + mojom.INT32: "read32()", + mojom.UINT32: "read32()", + mojom.FLOAT: "decodeFloat()", + mojom.HANDLE: "decodeHandle()", + mojom.INT64: "read64()", + mojom.UINT64: "read64()", + mojom.DOUBLE: "decodeDouble()", + mojom.STRING: "decodeString()", +} + + +def DecodeSnippet(kind): + if kind in mojom.PRIMITIVES: + return _kind_to_decode_snippet[kind] + if isinstance(kind, mojom.Struct): + return "decodeStructPointer(%s)" % GetJavaScriptType(kind.name); + if isinstance(kind, mojom.Array): + return "decodeArrayPointer(%s)" % GetJavaScriptType(kind.kind); + + +_kind_to_encode_snippet = { + mojom.BOOL: "write8(1 & ", + mojom.INT8: "write8(", + mojom.UINT8: "write8(", + mojom.INT16: "write16(", + mojom.UINT16: "write16(", + mojom.INT32: "write32(", + mojom.UINT32: "write32(", + mojom.FLOAT: "encodeFloat(", + mojom.HANDLE: "encodeHandle(", + mojom.INT64: "write64(", + mojom.UINT64: "write64(", + mojom.DOUBLE: "encodeDouble(", + mojom.STRING: "encodeString(", +} + + +def EncodeSnippet(kind): + if kind in mojom.PRIMITIVES: + return _kind_to_encode_snippet[kind] + if isinstance(kind, mojom.Struct): + return "encodeStructPointer(%s, " % GetJavaScriptType(kind.name); + if isinstance(kind, mojom.Array): + return "encodeArrayPointer(%s, " % GetJavaScriptType(kind.kind); + + +def GetStructInfo(exported, struct): + packed_struct = mojom_pack.PackedStruct(struct) + return { + "name": struct.name, + "packed": packed_struct, + "bytes": mojom_pack.GetByteLayout(packed_struct), + "exported": exported, + } + + +class JSGenerator(Generator): + filters = { + "default_value": DefaultValue, + "payload_size": PayloadSize, + "decode_snippet": DecodeSnippet, + "encode_snippet": EncodeSnippet, + } + + def GetStructsFromMethods(self): + result = [] + for interface in self.module.interfaces: + for method in interface.methods: + result.append(GetStructFromMethod(interface, method)) + return map(partial(GetStructInfo, False), result) + + def GetStructs(self): + return map(partial(GetStructInfo, True), self.module.structs) + + @UseJinja("js_templates/module.js.tmpl", filters=filters) + def GenerateModule(self): + return { + "structs": self.GetStructs() + self.GetStructsFromMethods(), + "interfaces": self.module.interfaces, + } + + def Write(self, contents): + if self.output_dir is None: + print contents + return + filename = "%s.js" % CamelToUnderscores(self.module.name) + with open(os.path.join(self.output_dir, filename), "w+") as f: + f.write(contents) + + def GenerateFiles(self): + self.Write(self.GenerateModule()) diff --git a/mojo/public/bindings/generators/mojom_pack.py b/mojo/public/bindings/generators/mojom_pack.py index 521dc14..3bf47ff 100644 --- a/mojo/public/bindings/generators/mojom_pack.py +++ b/mojo/public/bindings/generators/mojom_pack.py @@ -41,10 +41,12 @@ class PackedField(object): self.offset = None self.bit = None + # Returns the pad necessary to reserve space for alignment of |size|. def GetPad(offset, size): return (size - (offset % size)) % size + # Returns a 2-tuple of the field offset and bit (for BOOLs) def GetFieldOffset(field, last_field): if field.field.kind == mojom.BOOL and \ @@ -100,3 +102,34 @@ class PackedStruct(object): # Add to end src_field.offset, src_field.bit = GetFieldOffset(src_field, last_field) dst_fields.append(src_field) + + def GetTotalSize(self): + if not self.packed_fields: + return 0; + last_field = self.packed_fields[-1] + offset = last_field.offset + last_field.size + pad = GetPad(offset, 8) + return offset + pad; + + +class ByteInfo(object): + def __init__(self): + self.is_padding = False + self.packed_fields = [] + + +def GetByteLayout(packed_struct): + bytes = [ByteInfo() for i in xrange(packed_struct.GetTotalSize())] + + limit_of_previous_field = 0 + for packed_field in packed_struct.packed_fields: + for i in xrange(limit_of_previous_field, packed_field.offset): + bytes[i].is_padding = True + bytes[packed_field.offset].packed_fields.append(packed_field) + limit_of_previous_field = packed_field.offset + packed_field.size + + for byte in bytes: + # A given byte cannot both be padding and have a fields packed into it. + assert not (byte.is_padding and byte.packed_fields) + + return bytes diff --git a/mojo/public/bindings/generators/template_expander.py b/mojo/public/bindings/generators/template_expander.py new file mode 100644 index 0000000..41c3cc7 --- /dev/null +++ b/mojo/public/bindings/generators/template_expander.py @@ -0,0 +1,41 @@ +# Copyright 2013 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. + +# Based on: +# http://src.chromium.org/viewvc/blink/trunk/Source/build/scripts/template_expander.py + +import os +import sys + +_current_dir = os.path.dirname(os.path.realpath(__file__)) +# jinja2 is in the third_party directory. +# Insert at front to override system libraries, and after path[0] == script dir +sys.path.insert(1, os.path.join(_current_dir, + os.pardir, + os.pardir, + os.pardir, + os.pardir, + 'third_party')) +import jinja2 + + +def ApplyTemplate(path_to_template, params, filters=None): + template_directory, template_name = os.path.split(path_to_template) + path_to_templates = os.path.join(_current_dir, template_directory) + loader = jinja2.FileSystemLoader([path_to_templates]) + jinja_env = jinja2.Environment(loader=loader, keep_trailing_newline=True) + if filters: + jinja_env.filters.update(filters) + template = jinja_env.get_template(template_name) + return template.render(params) + + +def UseJinja(path_to_template, filters=None): + def RealDecorator(generator): + def GeneratorInternal(*args, **kwargs): + parameters = generator(*args, **kwargs) + return ApplyTemplate(path_to_template, parameters, filters=filters) + GeneratorInternal.func_name = generator.func_name + return GeneratorInternal + return RealDecorator diff --git a/mojo/public/bindings/js/codec.js b/mojo/public/bindings/js/codec.js index d2d108a..2b3f86c 100644 --- a/mojo/public/bindings/js/codec.js +++ b/mojo/public/bindings/js/codec.js @@ -382,6 +382,12 @@ define(function() { this.cls = cls; }; + // TODO(abarth): Add missing types: + // * String + // * Float + // * Double + // * Signed integers + PointerTo.prototype.encodedSize = 8; PointerTo.prototype.decode = function(decoder) { @@ -393,6 +399,20 @@ define(function() { this.cls.encode(objectEncoder, val); }; + function ArrayOf(cls) { + this.cls = cls; + }; + + ArrayOf.prototype.encodedSize = 8; + + ArrayOf.prototype.decode = function(decoder) { + return decoder.decodeArrayPointer(self.cls); + }; + + ArrayOf.prototype.encode = function(encoder, val) { + encoder.encodeArrayPointer(self.cls, val); + }; + function Handle() { } @@ -418,6 +438,7 @@ define(function() { exports.Uint32 = Uint32; exports.Uint64 = Uint64; exports.PointerTo = PointerTo; + exports.ArrayOf = ArrayOf; exports.Handle = Handle; return exports; }); diff --git a/mojo/public/bindings/mojom_bindings_generator.gypi b/mojo/public/bindings/mojom_bindings_generator.gypi index 099e3eb7..8ed8ec49 100644 --- a/mojo/public/bindings/mojom_bindings_generator.gypi +++ b/mojo/public/bindings/mojom_bindings_generator.gypi @@ -18,10 +18,15 @@ '<(mojom_bindings_generator)', '<(DEPTH)/mojo/public/bindings/parse/mojo_parser.py', '<(DEPTH)/mojo/public/bindings/parse/mojo_translate.py', + # TODO(abarth): We should list the cpp_templates here too. + '<(DEPTH)/mojo/public/bindings/generators/js_templates/module.js.tmpl', '<(DEPTH)/mojo/public/bindings/generators/mojom.py', + '<(DEPTH)/mojo/public/bindings/generators/mojom_cpp_generator.py', '<(DEPTH)/mojo/public/bindings/generators/mojom_data.py', + '<(DEPTH)/mojo/public/bindings/generators/mojom_generator.py', + '<(DEPTH)/mojo/public/bindings/generators/mojom_js_generator.py', '<(DEPTH)/mojo/public/bindings/generators/mojom_pack.py', - '<(DEPTH)/mojo/public/bindings/generators/mojom_cpp_generator.py', + '<(DEPTH)/mojo/public/bindings/generators/template_expander.py', ], 'outputs': [ '<(output_dir)/<(RULE_INPUT_ROOT).h', diff --git a/mojo/public/bindings/mojom_bindings_generator.py b/mojo/public/bindings/mojom_bindings_generator.py index 16cd9e6..41e2615 100755 --- a/mojo/public/bindings/mojom_bindings_generator.py +++ b/mojo/public/bindings/mojom_bindings_generator.py @@ -12,6 +12,7 @@ from optparse import OptionParser from parse import mojo_parser from parse import mojo_translate from generators import mojom_data +from generators import mojom_js_generator from generators import mojom_cpp_generator @@ -40,6 +41,9 @@ def Main(): cpp = mojom_cpp_generator.CPPGenerator( module, options.include_dir, options.output_dir) cpp.GenerateFiles() + js = mojom_js_generator.JSGenerator( + module, options.include_dir, options.output_dir) + js.GenerateFiles() if __name__ == '__main__': |