Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 3 # for details. All rights reserved. Use of this source code is governed by a | 3 # for details. All rights reserved. Use of this source code is governed by a |
| 4 # BSD-style license that can be found in the LICENSE file. | 4 # BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 """This module generates Dart APIs from the IDL database.""" | 6 """This module generates Dart APIs from the IDL database.""" |
| 7 | 7 |
| 8 import emitter | 8 import emitter |
| 9 import idlnode | 9 import idlnode |
| 10 import logging | 10 import logging |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 ]) | 94 ]) |
| 95 | 95 |
| 96 # | 96 # |
| 97 # Custom getters that must be implemented by hand. | 97 # Custom getters that must be implemented by hand. |
| 98 # | 98 # |
| 99 _custom_getters = set([ | 99 _custom_getters = set([ |
| 100 ('DOMWindow', 'localStorage'), | 100 ('DOMWindow', 'localStorage'), |
| 101 ]) | 101 ]) |
| 102 | 102 |
| 103 # | 103 # |
| 104 # Custom native specs for the Frog dom. | |
| 105 # | |
| 106 _frog_dom_custom_native_specs = { | |
| 107 'Console': '=console', # Decorate the singleton Console object. | |
| 108 'DOMWindow': '@*DOMWindow', # DOMWindow aliased with global scope. | |
| 109 } | |
| 110 | |
| 111 # | |
| 104 # Publically visible types common across all supported browsers. | 112 # Publically visible types common across all supported browsers. |
| 105 # | 113 # |
| 106 _BROWSER_SHARED_TYPES = [ | 114 _BROWSER_SHARED_TYPES = [ |
| 107 'Attr', | 115 'Attr', |
| 108 'CDATASection', | 116 'CDATASection', |
| 109 'CSSFontFaceRule', | 117 'CSSFontFaceRule', |
| 110 'CSSImportRule', | 118 'CSSImportRule', |
| 111 'CSSMediaRule', | 119 'CSSMediaRule', |
| 112 'CSSPageRule', | 120 'CSSPageRule', |
| 113 'CSSRule', | 121 'CSSRule', |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 lib_file_path -- filename for generated .lib file, None if not required. | 554 lib_file_path -- filename for generated .lib file, None if not required. |
| 547 lib_template -- template file in this directory for generated lib file. | 555 lib_template -- template file in this directory for generated lib file. |
| 548 """ | 556 """ |
| 549 | 557 |
| 550 self._emitters = multiemitter.MultiEmitter() | 558 self._emitters = multiemitter.MultiEmitter() |
| 551 self._database = database | 559 self._database = database |
| 552 self._output_dir = output_dir | 560 self._output_dir = output_dir |
| 553 self._dart_callback_file_paths = [] | 561 self._dart_callback_file_paths = [] |
| 554 | 562 |
| 555 self._StartGenerateInterfaceLibrary() | 563 self._StartGenerateInterfaceLibrary() |
| 556 self._StartGenerateJavaScriptMonkeyImpl(database, output_dir) | 564 self._StartGenerateJavaScriptMonkeyImpl(output_dir) |
|
Emily Fortuna
2011/12/06 23:23:00
(thumbs up!)
| |
| 557 self._StartGenerateWrappingImpl(output_dir) | 565 self._StartGenerateWrappingImpl(output_dir) |
| 558 self._StartGenerateFrogImpl(database, output_dir) | 566 self._StartGenerateFrogImpl(output_dir) |
| 559 | 567 |
| 560 # Render all interfaces into Dart and save them in files. | 568 # Render all interfaces into Dart and save them in files. |
| 561 dart_file_paths = [] | 569 dart_file_paths = [] |
| 562 processed_interfaces = [] | 570 processed_interfaces = [] |
| 563 for interface in database.GetInterfaces(): | 571 for interface in database.GetInterfaces(): |
| 564 | 572 |
| 565 super_interface = None | 573 super_interface = None |
| 566 super_name = interface.id | 574 super_name = interface.id |
| 567 | 575 |
| 568 if not _MatchSourceFilter(source_filter, interface): | 576 if not _MatchSourceFilter(source_filter, interface): |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 result.add(attr.id) | 1012 result.add(attr.id) |
| 1005 for op in parent_interface.operations: | 1013 for op in parent_interface.operations: |
| 1006 result.add(op.id) | 1014 result.add(op.id) |
| 1007 WalkParentChain(parent_interface) | 1015 WalkParentChain(parent_interface) |
| 1008 | 1016 |
| 1009 result = set() | 1017 result = set() |
| 1010 WalkParentChain(interface) | 1018 WalkParentChain(interface) |
| 1011 return result; | 1019 return result; |
| 1012 | 1020 |
| 1013 | 1021 |
| 1014 def _StartGenerateFrogImpl(self, database, output_dir): | 1022 def _StartGenerateFrogImpl(self, output_dir): |
| 1015 """Prepared for generating frog implementation. | 1023 """Prepared for generating frog implementation. |
| 1016 """ | 1024 """ |
| 1017 self._interface_names_with_subtypes = set() | 1025 self._interface_names_with_subtypes = set() |
| 1018 for interface in database.GetInterfaces(): | 1026 for interface in self._database.GetInterfaces(): |
| 1019 for parent in interface.parents: | 1027 for parent in interface.parents: |
| 1020 self._interface_names_with_subtypes.add(parent.type.id) | 1028 self._interface_names_with_subtypes.add(parent.type.id) |
| 1021 | 1029 |
| 1022 def _MakeFrogImplInterfaceGenerator(self, | 1030 def _MakeFrogImplInterfaceGenerator(self, |
| 1023 interface, | 1031 interface, |
| 1024 common_prefix, | 1032 common_prefix, |
| 1025 super_interface_name, | 1033 super_interface_name, |
| 1026 source_filter): | 1034 source_filter): |
| 1027 """.""" | 1035 """.""" |
| 1028 interface_name = interface.id | 1036 interface_name = interface.id |
| 1029 dart_frog_file_path = self.FilePathForFrogImpl(interface_name) | 1037 dart_frog_file_path = self.FilePathForFrogImpl(interface_name) |
| 1030 | 1038 |
| 1031 self._dart_frog_file_paths.append(dart_frog_file_path) | 1039 self._dart_frog_file_paths.append(dart_frog_file_path) |
| 1032 | 1040 |
| 1033 dart_code = self._emitters.FileEmitter(dart_frog_file_path) | 1041 dart_code = self._emitters.FileEmitter(dart_frog_file_path) |
| 1034 dart_code.Emit( | 1042 dart_code.Emit( |
| 1035 ''.join(open('template_frog_impl.darttemplate').readlines())) | 1043 ''.join(open('template_frog_impl.darttemplate').readlines())) |
| 1036 return FrogInterfaceGenerator(interface, super_interface_name, | 1044 return FrogInterfaceGenerator(interface, super_interface_name, |
| 1037 self._interface_names_with_subtypes, | 1045 self._interface_names_with_subtypes, |
| 1038 dart_code) | 1046 dart_code) |
| 1039 | 1047 |
| 1040 | 1048 |
| 1041 def _StartGenerateJavaScriptMonkeyImpl(self, database, output_dir): | 1049 def _StartGenerateJavaScriptMonkeyImpl(self, output_dir): |
| 1042 """Generate a JavaScript implementation that is coherent with | 1050 """Generate a JavaScript implementation that is coherent with |
| 1043 generated Dart APIs. | 1051 generated Dart APIs. |
| 1044 """ | 1052 """ |
| 1045 self._ComputeInheritanceClosure(database) | 1053 self._ComputeInheritanceClosure() |
| 1046 js_file_name = os.path.join(output_dir, 'monkey_dom.js') | 1054 js_file_name = os.path.join(output_dir, 'monkey_dom.js') |
| 1047 code = self._emitters.FileEmitter(js_file_name) | 1055 code = self._emitters.FileEmitter(js_file_name) |
| 1048 | 1056 |
| 1049 template = ''.join(open('template_monkey_dom.js').readlines()) | 1057 template = ''.join(open('template_monkey_dom.js').readlines()) |
| 1050 | 1058 |
| 1051 (self._monkey_global_code, | 1059 (self._monkey_global_code, |
| 1052 self._monkey_init_sequence) = code.Emit(template) | 1060 self._monkey_init_sequence) = code.Emit(template) |
| 1053 | 1061 |
| 1054 self._monkey_init_sequence.Emit('var $TEMP;\n', TEMP='_') | 1062 self._monkey_init_sequence.Emit('var $TEMP;\n', TEMP='_') |
| 1055 self._protomap = self._GenerateProtoMap(database) | 1063 self._protomap = self._GenerateProtoMap() |
| 1056 | 1064 |
| 1057 _logger.info('Started Generating %s' % js_file_name) | 1065 _logger.info('Started Generating %s' % js_file_name) |
| 1058 | 1066 |
| 1059 def _MakeMonkeyInterfaceGenerator(self, interface): | 1067 def _MakeMonkeyInterfaceGenerator(self, interface): |
| 1060 """Generate JavaScript patch code to match DartC output. | 1068 """Generate JavaScript patch code to match DartC output. |
| 1061 """ | 1069 """ |
| 1062 return MonkeyInterfaceGenerator(self, | 1070 return MonkeyInterfaceGenerator(self, |
| 1063 interface, | 1071 interface, |
| 1064 self._monkey_global_code, | 1072 self._monkey_global_code, |
| 1065 self._monkey_init_sequence) | 1073 self._monkey_init_sequence) |
| 1066 | 1074 |
| 1067 def _ComputeInheritanceClosure(self, database): | 1075 def _ComputeInheritanceClosure(self): |
| 1068 def Collect(interface, seen, collected): | 1076 def Collect(interface, seen, collected): |
| 1069 name = interface.id | 1077 name = interface.id |
| 1070 if '<' in name: | 1078 if '<' in name: |
| 1071 # TODO(sra): Handle parameterized types. | 1079 # TODO(sra): Handle parameterized types. |
| 1072 return | 1080 return |
| 1073 if not name in seen: | 1081 if not name in seen: |
| 1074 seen.add(name) | 1082 seen.add(name) |
| 1075 collected.append(name) | 1083 collected.append(name) |
| 1076 for parent in interface.parents: | 1084 for parent in interface.parents: |
| 1077 # TODO(sra): Handle parameterized types. | 1085 # TODO(sra): Handle parameterized types. |
| 1078 if not '<' in parent.type.id: | 1086 if not '<' in parent.type.id: |
| 1079 if database.HasInterface(parent.type.id): | 1087 if self._database.HasInterface(parent.type.id): |
| 1080 Collect(database.GetInterface(parent.type.id), seen, collected) | 1088 Collect(self._database.GetInterface(parent.type.id), |
| 1089 seen, collected) | |
| 1081 | 1090 |
| 1082 self._inheritance_closure = {} | 1091 self._inheritance_closure = {} |
| 1083 for interface in database.GetInterfaces(): | 1092 for interface in self._database.GetInterfaces(): |
| 1084 seen = set() | 1093 seen = set() |
| 1085 collected = [] | 1094 collected = [] |
| 1086 Collect(interface, seen, collected) | 1095 Collect(interface, seen, collected) |
| 1087 self._inheritance_closure[interface.id] = collected | 1096 self._inheritance_closure[interface.id] = collected |
| 1088 | 1097 |
| 1089 def _AllImplementedInterfaces(self, interface): | 1098 def _AllImplementedInterfaces(self, interface): |
| 1090 """Returns a list of the names of all interfaces implemented by 'interface'. | 1099 """Returns a list of the names of all interfaces implemented by 'interface'. |
| 1091 List includes the name of 'interface'. | 1100 List includes the name of 'interface'. |
| 1092 """ | 1101 """ |
| 1093 return self._inheritance_closure[interface.id] | 1102 return self._inheritance_closure[interface.id] |
| 1094 | 1103 |
| 1095 def _GenerateProtoMap(self, database): | 1104 def _GenerateProtoMap(self): |
| 1096 """Determine which DOM type prototypes can be obtained | 1105 """Determine which DOM type prototypes can be obtained |
| 1097 from window properties. | 1106 from window properties. |
| 1098 """ | 1107 """ |
| 1099 window = None | 1108 window = None |
| 1100 for interface in database.GetInterfaces(): | 1109 for interface in self._database.GetInterfaces(): |
| 1101 if interface.id == 'DOMWindow': | 1110 if interface.id == 'DOMWindow': |
| 1102 window = interface | 1111 window = interface |
| 1103 prototype_table = {} | 1112 prototype_table = {} |
| 1104 boring_type_ids = set(['bool', 'int', 'Number', 'String']) | 1113 boring_type_ids = set(['bool', 'int', 'Number', 'String']) |
| 1105 if window: | 1114 if window: |
| 1106 for attr in window.attributes: | 1115 for attr in window.attributes: |
| 1107 if attr.is_fc_getter: | 1116 if attr.is_fc_getter: |
| 1108 if attr.type.id not in boring_type_ids: | 1117 if attr.type.id not in boring_type_ids: |
| 1109 prototype_table[attr.type.id] = [attr.id] | 1118 prototype_table[attr.type.id] = [attr.id] |
| 1110 | 1119 |
| (...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2262 extends = " extends " + base | 2271 extends = " extends " + base |
| 2263 else: | 2272 else: |
| 2264 extends = "" | 2273 extends = "" |
| 2265 | 2274 |
| 2266 if interface_name in _constructable_types.keys(): | 2275 if interface_name in _constructable_types.keys(): |
| 2267 parameters = _constructable_types[interface_name] | 2276 parameters = _constructable_types[interface_name] |
| 2268 constructor = ' %s(%s) native;\n\n' % (interface_name, parameters) | 2277 constructor = ' %s(%s) native;\n\n' % (interface_name, parameters) |
| 2269 else: | 2278 else: |
| 2270 constructor = '' | 2279 constructor = '' |
| 2271 | 2280 |
| 2272 # Is the type's constructor accessible from the global scope? If so, we can | 2281 if interface_name in _frog_dom_custom_native_specs: |
| 2273 # directly patch the prototype. We don't really want to do this yet because | 2282 native_spec = _frog_dom_custom_native_specs[interface_name] |
| 2274 # the dynamic patching mechanism is tricky and we want to test it a lot. | 2283 else: |
| 2275 # But patching is currently broken on FireFox for non-leaf types, so 'hide' | 2284 # Is the type's constructor accessible from the global scope? If so, we |
| 2276 # only the leaf types. | 2285 # can directly patch the prototype. We don't really want to do this yet |
| 2277 is_hidden = interface_name not in _BROWSER_SHARED_TYPES | 2286 # because the dynamic patching mechanism is tricky and we want to test it |
| 2278 if interface_name not in self._interfaces_with_subtypes: | 2287 # a lot. But patching is currently broken on FireFox for non-leaf types, |
| 2279 is_hidden = True | 2288 # so 'hide' only the leaf types. |
| 2289 is_hidden = interface_name not in _BROWSER_SHARED_TYPES | |
| 2290 if interface_name not in self._interfaces_with_subtypes: | |
| 2291 is_hidden = True | |
| 2280 | 2292 |
| 2281 # Compiler needs to know window is aliased with global scope. | 2293 native_spec = '*' if is_hidden else '' |
| 2282 global_marker = '@' if interface_name == 'DOMWindow' else '' | 2294 native_spec += interface_name |
| 2283 | 2295 |
| 2284 (self._members_emitter, self._base_emitter) = self._dart_code.Emit( | 2296 (self._members_emitter, self._base_emitter) = self._dart_code.Emit( |
| 2285 '\n' | 2297 '\n' |
| 2286 'class $CLASS$BASE native "$SPLAT$HIDDEN$CLASS" {\n' | 2298 'class $CLASS$BASE native "$NATIVE" {\n' |
| 2287 '$CONSTRUCTOR$!MEMBERS' | 2299 '$CONSTRUCTOR$!MEMBERS' |
| 2288 '$!ADDITIONS' | 2300 '$!ADDITIONS' |
| 2289 '}\n', | 2301 '}\n', |
| 2290 CLASS=self._class_name, BASE=extends, | 2302 CLASS=self._class_name, BASE=extends, |
| 2291 INTERFACE=interface_name, CONSTRUCTOR=constructor, | 2303 INTERFACE=interface_name, CONSTRUCTOR=constructor, |
| 2292 SPLAT=global_marker, | 2304 NATIVE=native_spec) |
| 2293 HIDDEN='*' if is_hidden else '') | |
| 2294 | 2305 |
| 2295 if not base: | 2306 if not base: |
| 2296 # Emit shared base functionality here as we have no common base type. | 2307 # Emit shared base functionality here as we have no common base type. |
| 2297 self._base_emitter.Emit( | 2308 self._base_emitter.Emit( |
| 2298 '\n' | 2309 '\n' |
| 2299 ' var dartObjectLocalStorage;\n' | 2310 ' var dartObjectLocalStorage;\n' |
| 2300 '\n' | 2311 '\n' |
| 2301 ' String get typeName() native;\n') | 2312 ' String get typeName() native;\n') |
| 2302 | 2313 |
| 2303 def _ImplClassName(self, type_name): | 2314 def _ImplClassName(self, type_name): |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2376 Arguments: | 2387 Arguments: |
| 2377 info: An OperationInfo object. | 2388 info: An OperationInfo object. |
| 2378 """ | 2389 """ |
| 2379 # TODO(vsm): Handle overloads. | 2390 # TODO(vsm): Handle overloads. |
| 2380 self._members_emitter.Emit( | 2391 self._members_emitter.Emit( |
| 2381 '\n' | 2392 '\n' |
| 2382 ' $TYPE $NAME($ARGS) native;\n', | 2393 ' $TYPE $NAME($ARGS) native;\n', |
| 2383 TYPE=info.type_name, | 2394 TYPE=info.type_name, |
| 2384 NAME=info.name, | 2395 NAME=info.name, |
| 2385 ARGS=info.arg_implementation_declaration) | 2396 ARGS=info.arg_implementation_declaration) |
| OLD | NEW |