blob: 82b9b8e0abdd5fcb01c66e90ebf3bb53f6519e62 [file] [log] [blame]
# 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
import mojom_generator
from functools import partial
from template_expander import UseJinja
_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: "core.kInvalidHandle",
mojom.MSGPIPE: "core.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.MSGPIPE: "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.MSGPIPE: "decodeHandle()",
mojom.INT64: "read64()",
mojom.UINT64: "read64()",
mojom.DOUBLE: "decodeDouble()",
mojom.STRING: "decodeStringPointer()",
}
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.MSGPIPE: "encodeHandle(",
mojom.INT64: "write64(",
mojom.UINT64: "write64(",
mojom.DOUBLE: "encodeDouble(",
mojom.STRING: "encodeStringPointer(",
}
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(mojom_generator.Generator):
filters = {
"default_value": DefaultValue,
"payload_size": PayloadSize,
"decode_snippet": DecodeSnippet,
"encode_snippet": EncodeSnippet,
"stylize_method": mojom_generator.StudlyCapsToCamel,
}
def GetStructsFromMethods(self):
result = []
for interface in self.module.interfaces:
for method in interface.methods:
result.append(mojom_generator.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" % 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())