Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / public / tools / bindings / generators / mojom_js_generator.py
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.
4
5 """Generates JavaScript source files from a mojom.Module."""
6
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
11
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.NULLABLE_HANDLE:       "null",
27   mojom.NULLABLE_DCPIPE:       "null",
28   mojom.NULLABLE_DPPIPE:       "null",
29   mojom.NULLABLE_MSGPIPE:      "null",
30   mojom.NULLABLE_SHAREDBUFFER: "null",
31   mojom.INT64:                 "0",
32   mojom.UINT64:                "0",
33   mojom.DOUBLE:                "0",
34   mojom.STRING:                '""',
35   mojom.NULLABLE_STRING:       '""'
36 }
37
38
39 def JavaScriptDefaultValue(field):
40   if field.default:
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):
48     return "null"
49   if mojom.IsArrayKind(field.kind):
50     return "null"
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):
55     return "0"
56
57
58 def JavaScriptPayloadSize(packed):
59   packed_fields = packed.packed_fields
60   if not packed_fields:
61     return 0
62   last_field = packed_fields[-1]
63   offset = last_field.offset + last_field.size
64   pad = pack.GetPad(offset, 8)
65   return offset + pad
66
67
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",
92 }
93
94
95 def CodecType(kind):
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]
108   return kind
109
110
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)
124
125
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)
139
140
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
145     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)
154   return token
155
156
157 def ExpressionToText(value):
158   return TranslateConstants(value)
159
160
161 def JavascriptType(kind):
162   if kind.imported_from:
163     return kind.imported_from["unique_name"] + "." + kind.name
164   return kind.name
165
166
167 class Generator(generator.Generator):
168
169   js_filters = {
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,
177   }
178
179   @UseJinja("js_templates/module.js.tmpl", filters=js_filters)
180   def GenerateJsModule(self):
181     return {
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,
189     }
190
191   def GenerateFiles(self, args):
192     self.Write(self.GenerateJsModule(), "%s.js" % self.module.name)
193
194   def GetImports(self):
195     # Since each import is assigned a variable in JS, they need to have unique
196     # names.
197     counter = 1
198     for each in self.module.imports:
199       each["unique_name"] = "import" + str(counter)
200       counter += 1
201     return self.module.imports