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 = {
24 mojom.MSGPIPE: "null",
25 mojom.SHAREDBUFFER: "null",
26 mojom.NULLABLE_HANDLE: "null",
27 mojom.NULLABLE_DCPIPE: "null",
28 mojom.NULLABLE_DPPIPE: "null",
29 mojom.NULLABLE_MSGPIPE: "null",
30 mojom.NULLABLE_SHAREDBUFFER: "null",
35 mojom.NULLABLE_STRING: '""'
39 def JavaScriptDefaultValue(field):
41 if mojom.IsStructKind(field.kind):
42 assert field.default == "default"
43 return "new %s()" % JavascriptType(field.kind)
44 return ExpressionToText(field.default)
45 if field.kind in mojom.PRIMITIVES:
46 return _kind_to_javascript_default_value[field.kind]
47 if mojom.IsStructKind(field.kind):
49 if mojom.IsArrayKind(field.kind):
51 if mojom.IsInterfaceKind(field.kind) or \
52 mojom.IsInterfaceRequestKind(field.kind):
53 return _kind_to_javascript_default_value[mojom.MSGPIPE]
54 if mojom.IsEnumKind(field.kind):
58 def JavaScriptPayloadSize(packed):
59 packed_fields = packed.packed_fields
62 last_field = packed_fields[-1]
63 offset = last_field.offset + last_field.size
64 pad = pack.GetPad(offset, 8)
68 _kind_to_codec_type = {
69 mojom.BOOL: "codec.Uint8",
70 mojom.INT8: "codec.Int8",
71 mojom.UINT8: "codec.Uint8",
72 mojom.INT16: "codec.Int16",
73 mojom.UINT16: "codec.Uint16",
74 mojom.INT32: "codec.Int32",
75 mojom.UINT32: "codec.Uint32",
76 mojom.FLOAT: "codec.Float",
77 mojom.HANDLE: "codec.Handle",
78 mojom.DCPIPE: "codec.Handle",
79 mojom.DPPIPE: "codec.Handle",
80 mojom.MSGPIPE: "codec.Handle",
81 mojom.SHAREDBUFFER: "codec.Handle",
82 mojom.NULLABLE_HANDLE: "codec.Handle",
83 mojom.NULLABLE_DCPIPE: "codec.Handle",
84 mojom.NULLABLE_DPPIPE: "codec.Handle",
85 mojom.NULLABLE_MSGPIPE: "codec.Handle",
86 mojom.NULLABLE_SHAREDBUFFER: "codec.Handle",
87 mojom.INT64: "codec.Int64",
88 mojom.UINT64: "codec.Uint64",
89 mojom.DOUBLE: "codec.Double",
90 mojom.STRING: "codec.String",
91 mojom.NULLABLE_STRING: "codec.String",
96 if kind in mojom.PRIMITIVES:
97 return _kind_to_codec_type[kind]
98 if mojom.IsStructKind(kind):
99 return "new codec.PointerTo(%s)" % CodecType(kind.name)
100 if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
101 return "new codec.ArrayOf(new codec.ArrayOf(codec.PackedBool))"
102 if mojom.IsArrayKind(kind):
103 return "new codec.ArrayOf(%s)" % CodecType(kind.kind)
104 if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
105 return CodecType(mojom.MSGPIPE)
106 if mojom.IsEnumKind(kind):
107 return _kind_to_codec_type[mojom.INT32]
111 def JavaScriptDecodeSnippet(kind):
112 if kind in mojom.PRIMITIVES:
113 return "decodeStruct(%s)" % CodecType(kind)
114 if mojom.IsStructKind(kind):
115 return "decodeStructPointer(%s)" % CodecType(kind.name)
116 if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
117 return "decodeArrayPointer(new codec.ArrayOf(codec.PackedBool))"
118 if mojom.IsArrayKind(kind):
119 return "decodeArrayPointer(%s)" % CodecType(kind.kind)
120 if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
121 return JavaScriptDecodeSnippet(mojom.MSGPIPE)
122 if mojom.IsEnumKind(kind):
123 return JavaScriptDecodeSnippet(mojom.INT32)
126 def JavaScriptEncodeSnippet(kind):
127 if kind in mojom.PRIMITIVES:
128 return "encodeStruct(%s, " % CodecType(kind)
129 if mojom.IsStructKind(kind):
130 return "encodeStructPointer(%s, " % CodecType(kind.name)
131 if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
132 return "encodeArrayPointer(new codec.ArrayOf(codec.PackedBool), ";
133 if mojom.IsAnyArrayKind(kind):
134 return "encodeArrayPointer(%s, " % CodecType(kind.kind)
135 if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
136 return JavaScriptEncodeSnippet(mojom.MSGPIPE)
137 if mojom.IsEnumKind(kind):
138 return JavaScriptEncodeSnippet(mojom.INT32)
141 def TranslateConstants(token):
142 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
143 # Both variable and enum constants are constructed like:
144 # NamespaceUid.Struct[.Enum].CONSTANT_NAME
146 if token.imported_from:
147 name.append(token.imported_from["unique_name"])
148 if token.parent_kind:
149 name.append(token.parent_kind.name)
150 if isinstance(token, mojom.EnumValue):
151 name.append(token.enum_name)
152 name.append(token.name)
153 return ".".join(name)
157 def ExpressionToText(value):
158 return TranslateConstants(value)
161 def JavascriptType(kind):
162 if kind.imported_from:
163 return kind.imported_from["unique_name"] + "." + kind.name
167 class Generator(generator.Generator):
170 "default_value": JavaScriptDefaultValue,
171 "payload_size": JavaScriptPayloadSize,
172 "decode_snippet": JavaScriptDecodeSnippet,
173 "encode_snippet": JavaScriptEncodeSnippet,
174 "expression_to_text": ExpressionToText,
175 "js_type": JavascriptType,
176 "stylize_method": generator.StudlyCapsToCamel,
179 @UseJinja("js_templates/module.js.tmpl", filters=js_filters)
180 def GenerateJsModule(self):
182 "namespace": self.module.namespace,
183 "imports": self.GetImports(),
184 "kinds": self.module.kinds,
185 "enums": self.module.enums,
186 "module": self.module,
187 "structs": self.GetStructs() + self.GetStructsFromMethods(),
188 "interfaces": self.module.interfaces,
191 def GenerateFiles(self, args):
192 self.Write(self.GenerateJsModule(), "%s.js" % self.module.name)
194 def GetImports(self):
195 # Since each import is assigned a variable in JS, they need to have unique
198 for each in self.module.imports:
199 each["unique_name"] = "import" + str(counter)
201 return self.module.imports