Generate java bindings for structs.
[chromium-blink-merge.git] / mojo / public / tools / bindings / generators / mojom_js_generator.py
blob68f790861225be5f63b70c59e2289af215b83e53
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Generates JavaScript source files from a mojom.Module."""
7 import mojom.generate.generator as generator
8 import mojom.generate.module as mojom
9 import mojom.generate.pack as pack
10 from mojom.generate.template_expander import UseJinja
12 _kind_to_javascript_default_value = {
13 mojom.BOOL: "false",
14 mojom.INT8: "0",
15 mojom.UINT8: "0",
16 mojom.INT16: "0",
17 mojom.UINT16: "0",
18 mojom.INT32: "0",
19 mojom.UINT32: "0",
20 mojom.FLOAT: "0",
21 mojom.HANDLE: "null",
22 mojom.DCPIPE: "null",
23 mojom.DPPIPE: "null",
24 mojom.MSGPIPE: "null",
25 mojom.SHAREDBUFFER: "null",
26 mojom.INT64: "0",
27 mojom.UINT64: "0",
28 mojom.DOUBLE: "0",
29 mojom.STRING: '""',
33 def JavaScriptDefaultValue(field):
34 if field.default:
35 if isinstance(field.kind, mojom.Struct):
36 assert field.default == "default"
37 return "new %s()" % JavascriptType(field.kind)
38 return ExpressionToText(field.default)
39 if field.kind in mojom.PRIMITIVES:
40 return _kind_to_javascript_default_value[field.kind]
41 if isinstance(field.kind, mojom.Struct):
42 return "null"
43 if isinstance(field.kind, mojom.Array):
44 return "null"
45 if isinstance(field.kind, mojom.Interface) or \
46 isinstance(field.kind, mojom.InterfaceRequest):
47 return _kind_to_javascript_default_value[mojom.MSGPIPE]
48 if isinstance(field.kind, mojom.Enum):
49 return "0"
52 def JavaScriptPayloadSize(packed):
53 packed_fields = packed.packed_fields
54 if not packed_fields:
55 return 0
56 last_field = packed_fields[-1]
57 offset = last_field.offset + last_field.size
58 pad = pack.GetPad(offset, 8)
59 return offset + pad
62 _kind_to_codec_type = {
63 mojom.BOOL: "codec.Uint8",
64 mojom.INT8: "codec.Int8",
65 mojom.UINT8: "codec.Uint8",
66 mojom.INT16: "codec.Int16",
67 mojom.UINT16: "codec.Uint16",
68 mojom.INT32: "codec.Int32",
69 mojom.UINT32: "codec.Uint32",
70 mojom.FLOAT: "codec.Float",
71 mojom.HANDLE: "codec.Handle",
72 mojom.DCPIPE: "codec.Handle",
73 mojom.DPPIPE: "codec.Handle",
74 mojom.MSGPIPE: "codec.Handle",
75 mojom.SHAREDBUFFER: "codec.Handle",
76 mojom.INT64: "codec.Int64",
77 mojom.UINT64: "codec.Uint64",
78 mojom.DOUBLE: "codec.Double",
79 mojom.STRING: "codec.String",
83 def CodecType(kind):
84 if kind in mojom.PRIMITIVES:
85 return _kind_to_codec_type[kind]
86 if isinstance(kind, mojom.Struct):
87 return "new codec.PointerTo(%s)" % CodecType(kind.name)
88 if isinstance(kind, mojom.Array):
89 return "new codec.ArrayOf(%s)" % CodecType(kind.kind)
90 if isinstance(kind, mojom.Interface) or \
91 isinstance(kind, mojom.InterfaceRequest):
92 return CodecType(mojom.MSGPIPE)
93 if isinstance(kind, mojom.Enum):
94 return _kind_to_codec_type[mojom.INT32]
95 return kind
98 def JavaScriptDecodeSnippet(kind):
99 if kind in mojom.PRIMITIVES:
100 return "decodeStruct(%s)" % CodecType(kind)
101 if isinstance(kind, mojom.Struct):
102 return "decodeStructPointer(%s)" % CodecType(kind.name)
103 if isinstance(kind, mojom.Array):
104 return "decodeArrayPointer(%s)" % CodecType(kind.kind)
105 if isinstance(kind, mojom.Interface) or \
106 isinstance(kind, mojom.InterfaceRequest):
107 return JavaScriptDecodeSnippet(mojom.MSGPIPE)
108 if isinstance(kind, mojom.Enum):
109 return JavaScriptDecodeSnippet(mojom.INT32)
112 def JavaScriptEncodeSnippet(kind):
113 if kind in mojom.PRIMITIVES:
114 return "encodeStruct(%s, " % CodecType(kind)
115 if isinstance(kind, mojom.Struct):
116 return "encodeStructPointer(%s, " % CodecType(kind.name)
117 if isinstance(kind, mojom.Array):
118 return "encodeArrayPointer(%s, " % CodecType(kind.kind)
119 if isinstance(kind, mojom.Interface) or \
120 isinstance(kind, mojom.InterfaceRequest):
121 return JavaScriptEncodeSnippet(mojom.MSGPIPE)
122 if isinstance(kind, mojom.Enum):
123 return JavaScriptEncodeSnippet(mojom.INT32)
126 def TranslateConstants(token):
127 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
128 # Both variable and enum constants are constructed like:
129 # NamespaceUid.Struct[.Enum].CONSTANT_NAME
130 name = []
131 if token.imported_from:
132 name.append(token.imported_from["unique_name"])
133 if token.parent_kind:
134 name.append(token.parent_kind.name)
135 if isinstance(token, mojom.EnumValue):
136 name.append(token.enum_name)
137 name.append(token.name)
138 return ".".join(name)
139 return token
142 def ExpressionToText(value):
143 return TranslateConstants(value)
146 def JavascriptType(kind):
147 if kind.imported_from:
148 return kind.imported_from["unique_name"] + "." + kind.name
149 return kind.name
152 class Generator(generator.Generator):
154 js_filters = {
155 "default_value": JavaScriptDefaultValue,
156 "payload_size": JavaScriptPayloadSize,
157 "decode_snippet": JavaScriptDecodeSnippet,
158 "encode_snippet": JavaScriptEncodeSnippet,
159 "expression_to_text": ExpressionToText,
160 "js_type": JavascriptType,
161 "stylize_method": generator.StudlyCapsToCamel,
164 @UseJinja("js_templates/module.js.tmpl", filters=js_filters)
165 def GenerateJsModule(self):
166 return {
167 "namespace": self.module.namespace,
168 "imports": self.GetImports(),
169 "kinds": self.module.kinds,
170 "enums": self.module.enums,
171 "module": self.module,
172 "structs": self.GetStructs() + self.GetStructsFromMethods(),
173 "interfaces": self.module.interfaces,
176 def GenerateFiles(self, args):
177 self.Write(self.GenerateJsModule(), "%s.js" % self.module.name)
179 def GetImports(self):
180 # Since each import is assigned a variable in JS, they need to have unique
181 # names.
182 counter = 1
183 for each in self.module.imports:
184 each["unique_name"] = "import" + str(counter)
185 counter += 1
186 return self.module.imports