summaryrefslogtreecommitdiff
path: root/deps/v8/build/fuchsia/fidlgen_js/gen.py
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-08-07 22:45:47 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-08-07 22:45:47 +0200
commit65e39b7046a29aa299f06285441b62bcf1e4df01 (patch)
tree2eb012aabb59533b954aa169199733292de336cf /deps/v8/build/fuchsia/fidlgen_js/gen.py
parent936cd90b7def6ef7c1e0b80265a9dc77a9ad23c6 (diff)
downloadandroid-node-v8-65e39b7046a29aa299f06285441b62bcf1e4df01.tar.gz
android-node-v8-65e39b7046a29aa299f06285441b62bcf1e4df01.tar.bz2
android-node-v8-65e39b7046a29aa299f06285441b62bcf1e4df01.zip
Move v8/build into this repository.
Since we need to patch some files, we don't let depot_tools manage these files anymore. build.git commit a0b2e3b2708bcf81ec00ac1738b586bcc5e04eea
Diffstat (limited to 'deps/v8/build/fuchsia/fidlgen_js/gen.py')
-rwxr-xr-xdeps/v8/build/fuchsia/fidlgen_js/gen.py673
1 files changed, 673 insertions, 0 deletions
diff --git a/deps/v8/build/fuchsia/fidlgen_js/gen.py b/deps/v8/build/fuchsia/fidlgen_js/gen.py
new file mode 100755
index 0000000000..484440e2d1
--- /dev/null
+++ b/deps/v8/build/fuchsia/fidlgen_js/gen.py
@@ -0,0 +1,673 @@
+#!/usr/bin/env python
+
+# Copyright 2018 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 argparse
+import fidl
+import json
+
+
+class _CompoundIdentifier(object):
+
+ def __init__(self, library, name):
+ self.library = library
+ self.name = name
+
+
+def _ParseLibraryName(lib):
+ return lib.split('.')
+
+
+def _ParseCompoundIdentifier(ident):
+ parts = ident.split('/', 2)
+ raw_library = ''
+ raw_name = parts[0]
+ if len(parts) == 2:
+ raw_library, raw_name = parts
+ library = _ParseLibraryName(raw_library)
+ return _CompoundIdentifier(library, raw_name)
+
+
+def _ChangeIfReserved(name):
+ # TODO(crbug.com/883496): Remap any JS keywords.
+ return name
+
+
+def _CompileCompoundIdentifier(compound, ext=''):
+ result = _ChangeIfReserved(compound.name) + ext
+ return result
+
+
+def _CompileIdentifier(ident):
+ return _ChangeIfReserved(ident)
+
+
+def _GetUnderlyingPrimitiveType(t):
+ """Returns the underlying FIDL primitive type for a higher level type."""
+ if t.kind == fidl.TypeKind.PRIMITIVE:
+ return t.subtype
+ elif t.kind == fidl.TypeKind.STRING:
+ return 'string'
+ elif t.kind == fidl.TypeKind.IDENTIFIER:
+ # No underlying type is required because it will be implied by the type of
+ # the value that the identifer represents.
+ return None
+ else:
+ raise Exception(
+ 'expected primitive or identifier representing primitive underlying '
+ 'type, but got ' + str(t.kind))
+
+
+def _InlineSizeOfPrimitiveType(primitive_type):
+ return {
+ 'bool': 1,
+ 'float32': 4,
+ 'float64': 8,
+ 'int16': 2,
+ 'int32': 4,
+ 'int64': 8,
+ 'int8': 1,
+ 'uint16': 2,
+ 'uint32': 4,
+ 'uint64': 8,
+ 'uint8': 1,
+ }[primitive_type]
+
+
+def _JsTypeForPrimitiveType(t):
+ mapping = {
+ fidl.IntegerType.INT16: 'number',
+ fidl.IntegerType.INT32: 'number',
+ fidl.IntegerType.INT64: 'BigInt',
+ fidl.IntegerType.INT8: 'number',
+ fidl.IntegerType.UINT16: 'number',
+ fidl.IntegerType.UINT32: 'number',
+ fidl.IntegerType.UINT64: 'BigInt',
+ fidl.IntegerType.UINT8: 'number',
+ }
+ return mapping[t]
+
+
+def _BuildInlineSizeTable(fidl):
+ """Builds a mapping from type name to inline type size. These need to be
+ extracted beforehand because a vector<X> can be required during compilation
+ before seeing the compilation of X."""
+ result = {}
+ for enum in fidl.enum_declarations:
+ result[enum.name] = _InlineSizeOfPrimitiveType(enum.type.value)
+ for union in fidl.union_declarations:
+ result[union.name] = union.size
+ for struct in fidl.struct_declarations:
+ result[struct.name] = struct.size
+ return result
+
+
+class Compiler(object):
+
+ def __init__(self, fidl, output_file):
+ self.fidl = fidl
+ self.f = output_file
+ self.output_deferred_to_eof = ''
+ self.type_table_defined = set()
+ self.type_inline_size_by_name = _BuildInlineSizeTable(self.fidl)
+ # Used to hold the JS name for constants and enumerants. In particular,
+ # enums aren't scoped by name to their enum in the fidl json, but the JS
+ # bindings emit them as Enum.Something. So this maps from Something ->
+ # Enum.Something.
+ self.resolved_constant_name = {}
+
+ def Compile(self):
+ self._EmitHeader()
+ for c in self.fidl.const_declarations:
+ self._CompileConst(c)
+ for e in self.fidl.enum_declarations:
+ self._CompileEnum(e)
+ for u in self.fidl.union_declarations:
+ self._CompileUnion(u)
+ for s in self.fidl.struct_declarations:
+ self._CompileStruct(s)
+ for i in self.fidl.interface_declarations:
+ self._CompileInterface(i)
+
+ self.f.write(self.output_deferred_to_eof)
+
+ def _InlineSizeOfType(self, t):
+ if t.kind == fidl.TypeKind.PRIMITIVE:
+ return _InlineSizeOfPrimitiveType(t.subtype)
+ elif t.kind == fidl.TypeKind.STRING:
+ return 16
+ elif t.kind == fidl.TypeKind.IDENTIFIER:
+ size = self.type_inline_size_by_name.get(t.identifier)
+ if size is None:
+ raise Exception('expected ' + t.identifier +
+ ' to be in self.type_inline_size_by_name')
+ return size
+ elif t.kind == fidl.TypeKind.HANDLE:
+ return 4
+ else:
+ raise NotImplementedError(t.kind)
+
+ def _CompileConstant(self, val, primitive_type):
+ """primitive_type is the string representation of the underlying FIDL type
+ of the constant's value. Note that this is not a type object, but rather
+ the string name of a basic primitive type, e.g. 'int8' or 'uint64'."""
+ if val.kind == fidl.ConstantKind.IDENTIFIER:
+ js_name = self.resolved_constant_name.get(val.identifier)
+ if not js_name:
+ raise Exception('expected ' + val.identifer +
+ ' to be in self.resolved_constant_name')
+ return js_name
+ elif val.kind == fidl.ConstantKind.LITERAL:
+ lit_kind = val.literal.kind
+ if lit_kind == fidl.LiteralKind.STRING:
+ return json.dumps(val.literal.value)
+ elif lit_kind == fidl.LiteralKind.NUMERIC:
+ suffix = 'n' if primitive_type in ('int64', 'uint64') else ''
+ return val.literal.value + suffix
+ elif lit_kind == fidl.LiteralKind.TRUE:
+ return 'true'
+ elif lit_kind == fidl.LiteralKind.FALSE:
+ return 'false'
+ elif lit_kind == fidl.LiteralKind.DEFAULT:
+ return 'default'
+ else:
+ raise Exception('unexpected kind')
+
+ def _EmitHeader(self):
+ self.f.write('''// Copyright 2018 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.
+//
+// WARNING: This file is machine generated by fidlgen_js.
+
+''')
+
+ def _CompileConst(self, const):
+ compound = _ParseCompoundIdentifier(const.name)
+ name = _CompileCompoundIdentifier(compound)
+ value = self._CompileConstant(const.value,
+ _GetUnderlyingPrimitiveType(const.type))
+ self.f.write('''/**
+ * @const
+ */
+const %(name)s = %(value)s;
+
+''' % {
+ 'name': name,
+ 'value': value
+ })
+ self.resolved_constant_name[const.name] = name
+
+ def _CompileEnum(self, enum):
+ compound = _ParseCompoundIdentifier(enum.name)
+ name = _CompileCompoundIdentifier(compound)
+ js_type = _JsTypeForPrimitiveType(enum.type)
+ data = {'js_type': js_type, 'type': enum.type.value, 'name': name}
+ self.f.write('''/**
+ * @enum {%(js_type)s}
+ */
+const %(name)s = {
+''' % data)
+ for member in enum.members:
+ # The 'type' of an enum isn't a real Type like most other places, but
+ # instead just a simple 'int8' or similar.
+ underlying_type = enum.type.value
+ self.f.write(
+ ''' %s: %s,\n''' %
+ (member.name, self._CompileConstant(member.value, underlying_type)))
+ fidl_constant_name = '.'.join(compound.library) + '/' + member.name
+ javascript_name = name + '.' + member.name
+ self.resolved_constant_name[fidl_constant_name] = javascript_name
+ self.f.write('};\n')
+ self.f.write('const _kTT_%(name)s = _kTT_%(type)s;\n\n' % data)
+
+ def _CompileUnion(self, union):
+ compound = _ParseCompoundIdentifier(union.name)
+ name = _CompileCompoundIdentifier(compound)
+ member_names = []
+ enc_cases = []
+ dec_cases = []
+ for i, m in enumerate(union.members):
+ member_name = _ChangeIfReserved(m.name)
+ member_names.append(member_name)
+ member_type = self._CompileType(m.type)
+ enc_cases.append('''\
+ case %(index)s:
+ _kTT_%(member_type)s.enc(e, o + 4, v.%(member_name)s);
+ break;''' % {
+ 'index': i,
+ 'member_type': member_type,
+ 'member_name': member_name,
+ })
+ dec_cases.append('''\
+ case %(index)s:
+ result.set_%(member_name)s(_kTT_%(member_type)s.dec(d, o + 4));
+ break;''' % {
+ 'index': i,
+ 'member_type': member_type,
+ 'member_name': member_name,
+ })
+
+ self.f.write(
+ '''\
+const _kTT_%(name)s = {
+ enc: function(e, o, v) {
+ if (v.$tag === $fidl__kInvalidUnionTag) throw "invalid tag";
+ e.data.setUint32(o, v.$tag, $fidl__kLE);
+ switch (v.$tag) {
+%(enc_cases)s
+ }
+ },
+ dec: function(d, o) {
+ var tag = d.data.getUint32(o, $fidl__kLE);
+ var result = new %(name)s();
+ switch (tag) {
+%(dec_cases)s
+ default:
+ throw "invalid tag";
+ }
+ return result;
+ },
+};
+
+const _kTT_%(name)s_Nullable = {
+ enc: function(e, o, v) {
+ e.data.setUint32(o, v ? 0xffffffff : 0, $fidl__kLE);
+ e.data.setUint32(o + 4, v ? 0xffffffff : 0, $fidl__kLE);
+ var start = e.alloc(%(size)s);
+ _kTT_%(name)s.enc(e, start, v);
+ },
+ dec: function(d, o) {
+ if (d.data.getUint32(o, $fidl__kLE) === 0) {
+ return new %(name)s();
+ }
+ var pointer = d.data.getUint32(o + 4, $fidl__kLE);
+ var dataOffset = d.claimMemory(%(size)s);
+ return _kTT_%(name)s.dec(d, dataOffset);
+ },
+};
+
+/**
+ * @constructor
+ */
+function %(name)s() { this.reset(); }
+
+%(name)s.prototype.reset = function(i) {
+ this.$tag = (i === undefined) ? $fidl__kInvalidUnionTag : i;
+''' % {
+ 'name': name,
+ 'size': union.size,
+ 'enc_cases': '\n'.join(enc_cases),
+ 'dec_cases': '\n'.join(dec_cases),
+ })
+ for m in member_names:
+ self.f.write(' this.%s = null;\n' % m)
+ self.f.write('}\n\n')
+
+ for i, m in enumerate(member_names):
+ self.f.write('''\
+%(name)s.prototype.set_%(member_name)s = function(v) {
+ this.reset(%(index)s);
+ this.%(member_name)s = v;
+};
+
+%(name)s.prototype.is_%(member_name)s = function() {
+ return this.$tag === %(index)s;
+};
+
+''' % {
+ 'name': name,
+ 'member_name': m,
+ 'index': i,
+ })
+
+ def _CompileStruct(self, struct):
+ compound = _ParseCompoundIdentifier(struct.name)
+ name = _CompileCompoundIdentifier(compound)
+ param_names = [_ChangeIfReserved(x.name) for x in struct.members]
+ # TODO(crbug.com/883496): @param and types.
+ self.f.write('''/**
+ * @constructor
+ * @struct
+ */
+function %(name)s(%(param_names)s) {
+''' % {
+ 'name': name,
+ 'param_names': ', '.join(param_names)
+ })
+ for member in struct.members:
+ member_name = _ChangeIfReserved(member.name)
+ value = '%(member_name)s'
+ if member.maybe_default_value:
+ underlying_type = _GetUnderlyingPrimitiveType(member.type)
+ value = (
+ '(%(member_name)s !== undefined) ? %(member_name)s : ' +
+ self._CompileConstant(member.maybe_default_value, underlying_type))
+ elif self.fidl.declarations.get(member.type.identifier) == \
+ fidl.DeclarationsMap.UNION:
+ union_compound = _ParseCompoundIdentifier(member.type.identifier)
+ union_name = _CompileCompoundIdentifier(union_compound)
+ value = ('(%(member_name)s !== undefined) ? %(member_name)s : ' + 'new '
+ + union_name + '()')
+ self.f.write((' this.%(member_name)s = ' + value + ';\n') %
+ {'member_name': member_name})
+ self.f.write('}\n\n')
+
+ self.f.write('''const _kTT_%(name)s = {
+ enc: function(e, o, v) {
+''' % {'name': name})
+
+ for member in struct.members:
+ element_ttname = self._CompileType(member.type)
+ self.f.write(
+ ' _kTT_%(element_ttname)s.enc('
+ 'e, o + %(offset)s, v.%(member_name)s);\n' % {
+ 'element_ttname': element_ttname,
+ 'offset': member.offset,
+ 'member_name': _ChangeIfReserved(member.name)
+ })
+
+ self.f.write(''' },
+ dec: function(d, o) {
+''')
+
+ for member in struct.members:
+ element_ttname = self._CompileType(member.type)
+ self.f.write(
+ ' var $temp_%(member_name)s = _kTT_%(element_ttname)s.dec('
+ 'd, o + %(offset)s);\n' % {
+ 'element_ttname': element_ttname,
+ 'offset': member.offset,
+ 'member_name': _ChangeIfReserved(member.name)
+ })
+ self.f.write(''' return new %(name)s(%(temp_names)s);
+ }
+};
+
+''' % {
+ 'name': name,
+ 'temp_names': ', '.join(['$temp_' + x for x in param_names])
+ })
+
+ def _CompileType(self, t):
+ """Ensures there's a type table for the given type, and returns the stem of
+ its name."""
+ if t.kind == fidl.TypeKind.PRIMITIVE:
+ return t.subtype
+ elif t.kind == fidl.TypeKind.STRING:
+ return 'String' + ('_Nullable' if t.nullable else '')
+ elif t.kind == fidl.TypeKind.IDENTIFIER:
+ compound = _ParseCompoundIdentifier(t.identifier)
+ name = _CompileCompoundIdentifier(compound)
+ return name + ('_Nullable' if t.nullable else '')
+ elif t.kind == fidl.TypeKind.HANDLE or t.kind == fidl.TypeKind.REQUEST:
+ return 'Handle'
+ elif t.kind == fidl.TypeKind.ARRAY:
+ element_ttname = self._CompileType(t.element_type)
+ ttname = 'ARR_%d_%s' % (t.element_count, element_ttname)
+ if ttname not in self.type_table_defined:
+ self.type_table_defined.add(ttname)
+ self.output_deferred_to_eof += ('''\
+const _kTT_%(ttname)s = {
+ enc: function(e, o, v) {
+ for (var i = 0; i < %(element_count)s; i++) {
+ _kTT_%(element_ttname)s.enc(e, o + (i * %(element_size)s), v[i]);
+ }
+ },
+ dec: function(d, o) {
+ var result = [];
+ for (var i = 0; i < %(element_count)s; i++) {
+ result.push(_kTT_%(element_ttname)s.dec(d, o + (i * %(element_size)s)));
+ }
+ return result;
+ },
+};
+
+''' % {
+ 'ttname': ttname,
+ 'element_ttname': element_ttname,
+ 'element_count': t.element_count,
+ 'element_size': self._InlineSizeOfType(t.element_type),
+ })
+ return ttname
+ elif t.kind == fidl.TypeKind.VECTOR:
+ element_ttname = self._CompileType(t.element_type)
+ ttname = ('VEC_' + ('Nullable_' if t.nullable else '') + element_ttname)
+ if t.nullable:
+ handle_null_enc = '''e.data.setUint32(o, 0, $fidl__kLE);
+ e.data.setUint32(o + 4, 0, $fidl__kLE);
+ e.data.setUint32(o + 8, 0, $fidl__kLE);
+ e.data.setUint32(o + 12, 0, $fidl__kLE);
+ return;
+'''
+ handle_null_dec = 'return null;'
+ else:
+ handle_null_enc = 'throw "non-null vector required";'
+ handle_null_dec = 'throw "non-null vector required";'
+
+ if ttname not in self.type_table_defined:
+ self.type_table_defined.add(ttname)
+ self.output_deferred_to_eof += ('''\
+const _kTT_%(ttname)s = {
+ enc: function(e, o, v) {
+ if (v === null || v === undefined) {
+ %(handle_null_enc)s
+ }
+ e.data.setUint32(o, v.length, $fidl__kLE);
+ e.data.setUint32(o + 4, 0, $fidl__kLE);
+ e.data.setUint32(o + 8, 0xffffffff, $fidl__kLE);
+ e.data.setUint32(o + 12, 0xffffffff, $fidl__kLE);
+ var start = e.alloc(v.length * %(element_size)s);
+ for (var i = 0; i < v.length; i++) {
+ _kTT_%(element_ttname)s.enc(e, start + (i * %(element_size)s), v[i]);
+ }
+ },
+ dec: function(d, o) {
+ var len = d.data.getUint32(o, $fidl__kLE);
+ var pointer = d.data.getUint32(o + 8, $fidl__kLE);
+ if (pointer === 0) {
+ %(handle_null_dec)s
+ }
+ var dataOffset = d.claimMemory(len * %(element_size)s);
+ var result = [];
+ for (var i = 0; i < len; i++) {
+ result.push(_kTT_%(element_ttname)s.dec(
+ d, dataOffset + (i * %(element_size)s)));
+ }
+ return result;
+ }
+};
+
+''' % {
+ 'ttname': ttname,
+ 'element_ttname': element_ttname,
+ 'element_size': self._InlineSizeOfType(t.element_type),
+ 'handle_null_enc': handle_null_enc,
+ 'handle_null_dec': handle_null_dec,
+ })
+ return ttname
+ else:
+ raise NotImplementedError(t.kind)
+
+ def _GenerateJsInterfaceForInterface(self, name, interface):
+ """Generates a JS @interface for the given FIDL interface."""
+ self.f.write('''/**
+ * @interface
+ */
+function %(name)s() {}
+
+''' % {'name': name})
+
+ # Define a JS interface part for the interface for typechecking.
+ for method in interface.methods:
+ method_name = _CompileIdentifier(method.name)
+ if method.has_request:
+ param_names = [_CompileIdentifier(x.name) for x in method.maybe_request]
+ if len(param_names):
+ self.f.write('/**\n')
+ # TODO(crbug.com/883496): Emit @param and @return type comments.
+ self.f.write(' */\n')
+ self.f.write(
+ '%(name)s.prototype.%(method_name)s = '
+ 'function(%(param_names)s) {};\n\n' % {
+ 'name': name,
+ 'method_name': method_name,
+ 'param_names': ', '.join(param_names)
+ })
+
+ # Emit message ordinals for later use.
+ for method in interface.methods:
+ method_name = _CompileIdentifier(method.name)
+ self.f.write(
+ 'const _k%(name)s_%(method_name)s_Ordinal = %(ordinal)s;\n' % {
+ 'name': name,
+ 'method_name': method_name,
+ 'ordinal': method.ordinal
+ })
+
+ self.f.write('\n')
+
+ def _GenerateJsProxyForInterface(self, name, interface):
+ """Generates the JS side implementation of a proxy class implementing the
+ given interface."""
+ proxy_name = name + 'Proxy'
+ self.f.write('''/**
+ * @constructor
+ * @implements %(name)s
+ */
+function %(proxy_name)s() {
+ this.channel = $ZX_HANDLE_INVALID;
+}
+
+%(proxy_name)s.prototype.$bind = function(channel) {
+ this.channel = channel;
+};
+
+%(proxy_name)s.prototype.$is_bound = function() {
+ return this.channel != $ZX_HANDLE_INVALID;
+};
+
+%(proxy_name)s.prototype.$request = function() {
+ if (this.$is_bound())
+ throw "Proxy already bound";
+ var pair = $ZxChannelCreate();
+ if (pair.status != $ZX_OK)
+ throw "ChannelPair creation failed";
+ this.channel = pair.first;
+ return pair.second;
+};
+
+%(proxy_name)s.prototype.$close = function() {
+ if (!this.$is_bound())
+ return;
+ var status = $zx_handle_close(this.channel);
+ if (status !== $ZX_OK) {
+ throw "close handle failed";
+ }
+ this.channel = $ZX_HANDLE_INVALID;
+};
+
+''' % {
+ 'name': name,
+ 'proxy_name': proxy_name
+ })
+ for method in interface.methods:
+ method_name = _CompileIdentifier(method.name)
+ if method.has_request:
+ type_tables = []
+ for param in method.maybe_request:
+ type_tables.append(self._CompileType(param.type))
+ param_names = [_CompileIdentifier(x.name) for x in method.maybe_request]
+ self.f.write(
+ '''\
+%(proxy_name)s.prototype.%(method_name)s = function(%(param_names)s) {
+ if (this.channel === $ZX_HANDLE_INVALID) {
+ throw "channel closed";
+ }
+ var $encoder = new $fidl_Encoder(_k%(name)s_%(method_name)s_Ordinal);
+ $encoder.alloc(%(size)s - $fidl_kMessageHeaderSize);
+''' % {
+ 'name': name,
+ 'proxy_name': proxy_name,
+ 'method_name': method_name,
+ 'param_names': ', '.join(param_names),
+ 'size': method.maybe_request_size
+ })
+
+ for param, ttname in zip(method.maybe_request, type_tables):
+ self.f.write(
+ '''\
+ _kTT_%(type_table)s.enc($encoder, %(offset)s, %(param_name)s);
+''' % {
+ 'type_table': ttname,
+ 'param_name': _CompileIdentifier(param.name),
+ 'offset': param.offset
+ })
+
+ self.f.write(''' var $writeResult = $ZxChannelWrite(this.channel,
+ $encoder.messageData(),
+ $encoder.messageHandles());
+ if ($writeResult !== $ZX_OK) {
+ throw "$ZxChannelWrite failed: " + $writeResult;
+ }
+''')
+
+ if method.has_response:
+ type_tables = []
+ for param in method.maybe_response:
+ type_tables.append(self._CompileType(param.type))
+ self.f.write('''
+ return $ZxObjectWaitOne(this.channel, $ZX_CHANNEL_READABLE, $ZX_TIME_INFINITE)
+ .then(() => new Promise(res => {
+ var $readResult = $ZxChannelRead(this.channel);
+ if ($readResult.status !== $ZX_OK) {
+ throw "channel read failed";
+ }
+
+ var $view = new DataView($readResult.data);
+
+ var $decoder = new $fidl_Decoder($view, $readResult.handles);
+ $decoder.claimMemory(%(size)s - $fidl_kMessageHeaderSize);
+''' % {'size': method.maybe_response_size})
+ for param, ttname in zip(method.maybe_response, type_tables):
+ self.f.write(
+ '''\
+ var %(param_name)s = _kTT_%(type_table)s.dec($decoder, %(offset)s);
+''' % {
+ 'type_table': ttname,
+ 'param_name': _CompileIdentifier(param.name),
+ 'offset': param.offset
+ })
+
+ self.f.write('''
+ res(%(args)s);
+ }));
+''' % {'args': ', '.join(x.name for x in method.maybe_response)})
+
+ self.f.write('''};
+
+''')
+
+ def _CompileInterface(self, interface):
+ compound = _ParseCompoundIdentifier(interface.name)
+ name = _CompileCompoundIdentifier(compound)
+ self._GenerateJsInterfaceForInterface(name, interface)
+ self._GenerateJsProxyForInterface(name, interface)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('json')
+ parser.add_argument('--output', required=True)
+ args = parser.parse_args()
+
+ fidl_obj = fidl.fidl_from_dict(json.load(open(args.json, 'r')))
+ with open(args.output, 'w') as f:
+ c = Compiler(fidl_obj, f)
+ c.Compile()
+
+
+if __name__ == '__main__':
+ main()