| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 'SerializedScriptValue': 'String', | 47 'SerializedScriptValue': 'String', |
| 48 # TODO(vsm): Automatically recognize types defined in src. | 48 # TODO(vsm): Automatically recognize types defined in src. |
| 49 'TimeoutHandler': 'TimeoutHandler', | 49 'TimeoutHandler': 'TimeoutHandler', |
| 50 'RequestAnimationFrameCallback': 'RequestAnimationFrameCallback', | 50 'RequestAnimationFrameCallback': 'RequestAnimationFrameCallback', |
| 51 } | 51 } |
| 52 | 52 |
| 53 _dart_to_idl_type_conversions = dict((v,k) for k, v in | 53 _dart_to_idl_type_conversions = dict((v,k) for k, v in |
| 54 _idl_to_dart_type_conversions.iteritems()) | 54 _idl_to_dart_type_conversions.iteritems()) |
| 55 | 55 |
| 56 # | 56 # |
| 57 # Types which are unreachable until we call something that returns an instance. | |
| 58 # | |
| 59 _evasive_types = set(['CanvasPixelArray', | |
| 60 'ImageData', # Not really unreachable, testing multi-hop | |
| 61 'Notification', | |
| 62 'NotificationCenter', | |
| 63 'TouchList', | |
| 64 'Touch' | |
| 65 ]) | |
| 66 | |
| 67 # | |
| 68 # Types with user-invocable constructors. We do not have enough | 57 # Types with user-invocable constructors. We do not have enough |
| 69 # information in IDL to create the signature. | 58 # information in IDL to create the signature. |
| 70 # | 59 # |
| 71 # Each entry is of the form: | 60 # Each entry is of the form: |
| 72 # type name: constructor parameters | 61 # type name: constructor parameters |
| 73 _constructable_types = { | 62 _constructable_types = { |
| 74 'AudioContext': '', | 63 'AudioContext': '', |
| 75 'FileReader': '', | 64 'FileReader': '', |
| 76 'XMLHttpRequest': '', | 65 'XMLHttpRequest': '', |
| 77 'WebKitCSSMatrix': '[String spec]', | 66 'WebKitCSSMatrix': '[String spec]', |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 common_prefix -- prefix for the common library, if any. | 566 common_prefix -- prefix for the common library, if any. |
| 578 lib_file_path -- filename for generated .lib file, None if not required. | 567 lib_file_path -- filename for generated .lib file, None if not required. |
| 579 lib_template -- template file in this directory for generated lib file. | 568 lib_template -- template file in this directory for generated lib file. |
| 580 """ | 569 """ |
| 581 | 570 |
| 582 self._emitters = multiemitter.MultiEmitter() | 571 self._emitters = multiemitter.MultiEmitter() |
| 583 self._database = database | 572 self._database = database |
| 584 self._output_dir = output_dir | 573 self._output_dir = output_dir |
| 585 self._dart_callback_file_paths = [] | 574 self._dart_callback_file_paths = [] |
| 586 | 575 |
| 576 self._ComputeInheritanceClosure() |
| 587 self._StartGenerateInterfaceLibrary() | 577 self._StartGenerateInterfaceLibrary() |
| 588 self._StartGenerateJavaScriptMonkeyImpl(output_dir) | |
| 589 self._StartGenerateWrappingImpl(output_dir) | 578 self._StartGenerateWrappingImpl(output_dir) |
| 590 self._StartGenerateFrogImpl(output_dir) | 579 self._StartGenerateFrogImpl(output_dir) |
| 591 | 580 |
| 592 # Render all interfaces into Dart and save them in files. | 581 # Render all interfaces into Dart and save them in files. |
| 593 dart_file_paths = [] | 582 dart_file_paths = [] |
| 594 processed_interfaces = [] | 583 processed_interfaces = [] |
| 595 for interface in database.GetInterfaces(): | 584 for interface in database.GetInterfaces(): |
| 596 | 585 |
| 597 super_interface = None | 586 super_interface = None |
| 598 super_name = interface.id | 587 super_name = interface.id |
| (...skipping 23 matching lines...) Expand all Loading... |
| 622 self._ProcessCallback(interface, info) | 611 self._ProcessCallback(interface, info) |
| 623 else: | 612 else: |
| 624 if 'Callback' in interface.ext_attrs: | 613 if 'Callback' in interface.ext_attrs: |
| 625 _logger.info('Malformed callback: %s' % interface.id) | 614 _logger.info('Malformed callback: %s' % interface.id) |
| 626 self._ProcessInterface(interface, super_interface, | 615 self._ProcessInterface(interface, super_interface, |
| 627 source_filter, common_prefix) | 616 source_filter, common_prefix) |
| 628 processed_interfaces.append(interface) | 617 processed_interfaces.append(interface) |
| 629 | 618 |
| 630 # Libraries | 619 # Libraries |
| 631 if lib_dir: | 620 if lib_dir: |
| 632 # New version: Monkey-patching interface library. | |
| 633 self.GenerateLibFile('template_monkey_dom.darttemplate', | |
| 634 os.path.join(lib_dir, 'monkey_dom.dart'), | |
| 635 self._dart_interface_file_paths + | |
| 636 self._dart_callback_file_paths) | |
| 637 | |
| 638 # New version: Wrapping implementation combined interface and | 621 # New version: Wrapping implementation combined interface and |
| 639 # implementation library. | 622 # implementation library. |
| 640 self.GenerateLibFile('template_wrapping_dom.darttemplate', | 623 self.GenerateLibFile('template_wrapping_dom.darttemplate', |
| 641 os.path.join(lib_dir, 'wrapping_dom.dart'), | 624 os.path.join(lib_dir, 'wrapping_dom.dart'), |
| 642 (self._dart_interface_file_paths + | 625 (self._dart_interface_file_paths + |
| 643 self._dart_callback_file_paths + | 626 self._dart_callback_file_paths + |
| 644 # FIXME: Move the implementation to a separate | 627 # FIXME: Move the implementation to a separate |
| 645 # library. | 628 # library. |
| 646 self._dart_wrapping_file_paths)) | 629 self._dart_wrapping_file_paths)) |
| 647 | 630 |
| 648 # New version: Frog | 631 # New version: Frog |
| 649 self.GenerateLibFile('template_frog_dom.darttemplate', | 632 self.GenerateLibFile('template_frog_dom.darttemplate', |
| 650 os.path.join(lib_dir, 'dom_frog.dart'), | 633 os.path.join(lib_dir, 'dom_frog.dart'), |
| 651 self._dart_frog_file_paths + | 634 self._dart_frog_file_paths + |
| 652 self._dart_callback_file_paths) | 635 self._dart_callback_file_paths) |
| 653 | 636 |
| 654 | 637 |
| 655 # JavaScript externs files | 638 # JavaScript externs files |
| 656 self._GenerateJavaScriptExternsMonkey(database, output_dir) | |
| 657 self._GenerateJavaScriptExternsWrapping(database, output_dir) | 639 self._GenerateJavaScriptExternsWrapping(database, output_dir) |
| 658 | 640 |
| 659 | 641 |
| 660 def _RecognizeCallback(self, interface): | 642 def _RecognizeCallback(self, interface): |
| 661 """Returns the info for the callback method if the interface smells like a | 643 """Returns the info for the callback method if the interface smells like a |
| 662 callback. | 644 callback. |
| 663 """ | 645 """ |
| 664 if 'Callback' not in interface.ext_attrs: return None | 646 if 'Callback' not in interface.ext_attrs: return None |
| 665 handlers = [op for op in interface.operations if op.id == 'handleEvent'] | 647 handlers = [op for op in interface.operations if op.id == 'handleEvent'] |
| 666 if not handlers: return None | 648 if not handlers: return None |
| (...skipping 20 matching lines...) Expand all Loading... |
| 687 common_prefix): | 669 common_prefix): |
| 688 """.""" | 670 """.""" |
| 689 _logger.info('Generating %s' % interface.id) | 671 _logger.info('Generating %s' % interface.id) |
| 690 | 672 |
| 691 dart_interface_generator = self._MakeDartInterfaceGenerator( | 673 dart_interface_generator = self._MakeDartInterfaceGenerator( |
| 692 interface, | 674 interface, |
| 693 common_prefix, | 675 common_prefix, |
| 694 super_interface_name, | 676 super_interface_name, |
| 695 source_filter) | 677 source_filter) |
| 696 | 678 |
| 697 monkey_interface_generator = self._MakeMonkeyInterfaceGenerator(interface) | |
| 698 | |
| 699 wrapping_interface_generator = self._MakeWrappingImplInterfaceGenerator( | 679 wrapping_interface_generator = self._MakeWrappingImplInterfaceGenerator( |
| 700 interface, | 680 interface, |
| 701 common_prefix, | 681 common_prefix, |
| 702 super_interface_name, | 682 super_interface_name, |
| 703 source_filter) | 683 source_filter) |
| 704 | 684 |
| 705 frog_interface_generator = self._MakeFrogImplInterfaceGenerator( | 685 frog_interface_generator = self._MakeFrogImplInterfaceGenerator( |
| 706 interface, | 686 interface, |
| 707 common_prefix, | 687 common_prefix, |
| 708 super_interface_name, | 688 super_interface_name, |
| 709 source_filter) | 689 source_filter) |
| 710 | 690 |
| 711 generators = [dart_interface_generator, | 691 generators = [dart_interface_generator, |
| 712 monkey_interface_generator, | |
| 713 wrapping_interface_generator, | 692 wrapping_interface_generator, |
| 714 frog_interface_generator] | 693 frog_interface_generator] |
| 715 | 694 |
| 716 for generator in generators: | 695 for generator in generators: |
| 717 generator.StartInterface() | 696 generator.StartInterface() |
| 718 | 697 |
| 719 for const in sorted(interface.constants, ConstantOutputOrder): | 698 for const in sorted(interface.constants, ConstantOutputOrder): |
| 720 for generator in generators: | 699 for generator in generators: |
| 721 generator.AddConstant(const) | 700 generator.AddConstant(const) |
| 722 | 701 |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 self._dart_frog_file_paths.append(dart_frog_file_path) | 1039 self._dart_frog_file_paths.append(dart_frog_file_path) |
| 1061 | 1040 |
| 1062 dart_code = self._emitters.FileEmitter(dart_frog_file_path) | 1041 dart_code = self._emitters.FileEmitter(dart_frog_file_path) |
| 1063 dart_code.Emit( | 1042 dart_code.Emit( |
| 1064 ''.join(open('template_frog_impl.darttemplate').readlines())) | 1043 ''.join(open('template_frog_impl.darttemplate').readlines())) |
| 1065 return FrogInterfaceGenerator(interface, super_interface_name, | 1044 return FrogInterfaceGenerator(interface, super_interface_name, |
| 1066 self._interface_names_with_subtypes, | 1045 self._interface_names_with_subtypes, |
| 1067 dart_code) | 1046 dart_code) |
| 1068 | 1047 |
| 1069 | 1048 |
| 1070 def _StartGenerateJavaScriptMonkeyImpl(self, output_dir): | |
| 1071 """Generate a JavaScript implementation that is coherent with | |
| 1072 generated Dart APIs. | |
| 1073 """ | |
| 1074 self._ComputeInheritanceClosure() | |
| 1075 js_file_name = os.path.join(output_dir, 'monkey_dom.js') | |
| 1076 code = self._emitters.FileEmitter(js_file_name) | |
| 1077 | |
| 1078 template = ''.join(open('template_monkey_dom.js').readlines()) | |
| 1079 | |
| 1080 (self._monkey_global_code, | |
| 1081 self._monkey_init_sequence) = code.Emit(template) | |
| 1082 | |
| 1083 self._monkey_init_sequence.Emit('var $TEMP;\n', TEMP='_') | |
| 1084 self._protomap = self._GenerateProtoMap() | |
| 1085 | |
| 1086 _logger.info('Started Generating %s' % js_file_name) | |
| 1087 | |
| 1088 def _MakeMonkeyInterfaceGenerator(self, interface): | |
| 1089 """Generate JavaScript patch code to match DartC output. | |
| 1090 """ | |
| 1091 return MonkeyInterfaceGenerator(self, | |
| 1092 interface, | |
| 1093 self._monkey_global_code, | |
| 1094 self._monkey_init_sequence) | |
| 1095 | |
| 1096 def _ComputeInheritanceClosure(self): | 1049 def _ComputeInheritanceClosure(self): |
| 1097 def Collect(interface, seen, collected): | 1050 def Collect(interface, seen, collected): |
| 1098 name = interface.id | 1051 name = interface.id |
| 1099 if '<' in name: | 1052 if '<' in name: |
| 1100 # TODO(sra): Handle parameterized types. | 1053 # TODO(sra): Handle parameterized types. |
| 1101 return | 1054 return |
| 1102 if not name in seen: | 1055 if not name in seen: |
| 1103 seen.add(name) | 1056 seen.add(name) |
| 1104 collected.append(name) | 1057 collected.append(name) |
| 1105 for parent in interface.parents: | 1058 for parent in interface.parents: |
| 1106 # TODO(sra): Handle parameterized types. | 1059 # TODO(sra): Handle parameterized types. |
| 1107 if not '<' in parent.type.id: | 1060 if not '<' in parent.type.id: |
| 1108 if self._database.HasInterface(parent.type.id): | 1061 if self._database.HasInterface(parent.type.id): |
| 1109 Collect(self._database.GetInterface(parent.type.id), | 1062 Collect(self._database.GetInterface(parent.type.id), |
| 1110 seen, collected) | 1063 seen, collected) |
| 1111 | 1064 |
| 1112 self._inheritance_closure = {} | 1065 self._inheritance_closure = {} |
| 1113 for interface in self._database.GetInterfaces(): | 1066 for interface in self._database.GetInterfaces(): |
| 1114 seen = set() | 1067 seen = set() |
| 1115 collected = [] | 1068 collected = [] |
| 1116 Collect(interface, seen, collected) | 1069 Collect(interface, seen, collected) |
| 1117 self._inheritance_closure[interface.id] = collected | 1070 self._inheritance_closure[interface.id] = collected |
| 1118 | 1071 |
| 1119 def _AllImplementedInterfaces(self, interface): | 1072 def _AllImplementedInterfaces(self, interface): |
| 1120 """Returns a list of the names of all interfaces implemented by 'interface'. | 1073 """Returns a list of the names of all interfaces implemented by 'interface'. |
| 1121 List includes the name of 'interface'. | 1074 List includes the name of 'interface'. |
| 1122 """ | 1075 """ |
| 1123 if not self._inheritance_closure: | |
| 1124 self._ComputeInheritanceClosure() | |
| 1125 return self._inheritance_closure[interface.id] | 1076 return self._inheritance_closure[interface.id] |
| 1126 | 1077 |
| 1127 def _GenerateProtoMap(self): | 1078 def _GenerateProtoMap(self): |
| 1128 """Determine which DOM type prototypes can be obtained | 1079 """Determine which DOM type prototypes can be obtained |
| 1129 from window properties. | 1080 from window properties. |
| 1130 """ | 1081 """ |
| 1131 window = None | 1082 window = None |
| 1132 for interface in self._database.GetInterfaces(): | 1083 for interface in self._database.GetInterfaces(): |
| 1133 if interface.id == 'DOMWindow': | 1084 if interface.id == 'DOMWindow': |
| 1134 window = interface | 1085 window = interface |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 # Add a big comment of all the attributes and operations contributing to | 1131 # Add a big comment of all the attributes and operations contributing to |
| 1181 # the export. | 1132 # the export. |
| 1182 filler = ' ' * (40 - 2 - len(extern)) # '2' for 2 spaces before comment. | 1133 filler = ' ' * (40 - 2 - len(extern)) # '2' for 2 spaces before comment. |
| 1183 separator = filler + ' //' | 1134 separator = filler + ' //' |
| 1184 for (interface, kind) in sorted(names[name]): | 1135 for (interface, kind) in sorted(names[name]): |
| 1185 members.Emit('$SEP $KIND $INTERFACE.$NAME', | 1136 members.Emit('$SEP $KIND $INTERFACE.$NAME', |
| 1186 NAME=name, INTERFACE=interface, KIND=kind, SEP=separator) | 1137 NAME=name, INTERFACE=interface, KIND=kind, SEP=separator) |
| 1187 separator = ',' | 1138 separator = ',' |
| 1188 members.Emit('\n') | 1139 members.Emit('\n') |
| 1189 | 1140 |
| 1190 def _GenerateJavaScriptExternsMonkey(self, database, output_dir): | |
| 1191 """Generates a JavaScript externs file. | |
| 1192 | |
| 1193 Generates an externs file that is consistent with generated JavaScript code | |
| 1194 and Dart APIs for the monkey-patching implementation. | |
| 1195 """ | |
| 1196 js_file_name = os.path.join(output_dir, 'monkey_dom_externs.js') | |
| 1197 code = self._emitters.FileEmitter(js_file_name) | |
| 1198 | |
| 1199 template = ''.join(open('template_monkey_dom_externs.js').readlines()) | |
| 1200 namespace = 'dart_externs' | |
| 1201 (window_code, defs_code) = code.Emit(template, NAMESPACE=namespace) | |
| 1202 | |
| 1203 self._GenerateJavaScriptExternInterfaces( | |
| 1204 database, namespace, window_code, defs_code) | |
| 1205 | |
| 1206 _logger.info('Generated %s' % js_file_name) | |
| 1207 | 1141 |
| 1208 def _GenerateJavaScriptExternInterfaces(self, | 1142 def _GenerateJavaScriptExternInterfaces(self, |
| 1209 database, | 1143 database, |
| 1210 namespace, | 1144 namespace, |
| 1211 window_code, | 1145 window_code, |
| 1212 prop_code): | 1146 prop_code): |
| 1213 """Generate externs for JavaScript patch code. | 1147 """Generate externs for JavaScript patch code. |
| 1214 """ | 1148 """ |
| 1215 | 1149 |
| 1216 props = set() | 1150 props = set() |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2007 '$!TRUE' | 1941 '$!TRUE' |
| 2008 '$(INDENT)}\n', | 1942 '$(INDENT)}\n', |
| 2009 COND=test, INDENT=indent) | 1943 COND=test, INDENT=indent) |
| 2010 self.GenerateDispatch( | 1944 self.GenerateDispatch( |
| 2011 true_code, info, indent + ' ', position + 1, positive) | 1945 true_code, info, indent + ' ', position + 1, positive) |
| 2012 return True | 1946 return True |
| 2013 | 1947 |
| 2014 | 1948 |
| 2015 # ------------------------------------------------------------------------------ | 1949 # ------------------------------------------------------------------------------ |
| 2016 | 1950 |
| 2017 class MonkeyInterfaceGenerator(object): | |
| 2018 """Generates JS code for monkey-patched implementation of DOM.""" | |
| 2019 | |
| 2020 def __init__(self, generator, interface, global_code, init_sequence): | |
| 2021 self._generator = generator | |
| 2022 self._interface = interface | |
| 2023 self._global_code = global_code | |
| 2024 self._init_sequence = init_sequence | |
| 2025 | |
| 2026 def StartInterface(self): | |
| 2027 temp = '_' | |
| 2028 (fixup, guard) = self._init_sequence.Emit('$!FIXUP$!GUARD', | |
| 2029 ID=self._interface.id, TEMP=temp) | |
| 2030 global_helper_code = self._global_code.Emit('$!HELPERS', | |
| 2031 ID=self._interface.id) | |
| 2032 # Define a function that initializes the class prototype and constructor. | |
| 2033 (init_proto_code, fix_members_code, init_class_code) = global_helper_code.Em
it( | |
| 2034 'function DOM$fixClass$$ID(c) {\n' | |
| 2035 ' if (c.prototype) {\n' | |
| 2036 '$!INIT_PROTO_CODE' | |
| 2037 ' }\n' | |
| 2038 '$!FIX_MEMBERS_CODE$!INIT_CLASS_CODE' | |
| 2039 '}\n'); | |
| 2040 fix_members_code.Bind('CLASSREF', 'c'); | |
| 2041 init_class_code.Bind('CLASSREF', 'c'); | |
| 2042 init_proto_code.Bind('PROTOREF', 'c.prototype'); | |
| 2043 | |
| 2044 # Generate code that finds the constructor | |
| 2045 if self._interface.id in self._generator._protomap: | |
| 2046 # Use an existing field to find the actual prototype. | |
| 2047 exemplar_access_path = self._generator._protomap[self._interface.id] | |
| 2048 fetch_alternate = self._FetchAlternateConstructor( | |
| 2049 'w', self._interface.id, exemplar_access_path, temp); | |
| 2050 fixup.Emit( | |
| 2051 ' if (!w.$ID && $FETCH) {\n' | |
| 2052 ' w.$ID = $TEMP;\n' | |
| 2053 ' }\n', FETCH=fetch_alternate) | |
| 2054 | |
| 2055 call_fix_class = guard.Emit( | |
| 2056 ' if (($TEMP = w.$ID)) {\n' | |
| 2057 ' w.$ID$Dart = $TEMP;\n' | |
| 2058 ' $!CALL\n' | |
| 2059 ' }\n') | |
| 2060 | |
| 2061 if self._InterfaceIsAugmentedOnDemand(self._interface): | |
| 2062 self._GenerateOnDemandInterfaceSetupHelpers(self._interface, | |
| 2063 global_helper_code) | |
| 2064 call_fix_class.Emit('DOM$fixClassOnDemand$$ID($TEMP);') | |
| 2065 else: | |
| 2066 call_fix_class.Emit('DOM$fixClass$$ID($TEMP);') | |
| 2067 | |
| 2068 self._fix_members_code = fix_members_code | |
| 2069 self._class_code = init_class_code | |
| 2070 self._proto_code = init_proto_code | |
| 2071 self._batched_operation_names = [] | |
| 2072 | |
| 2073 def FinishInterface(self): | |
| 2074 # Any operations left over for fixMembers? | |
| 2075 if self._batched_operation_names: | |
| 2076 member_string = _FormatNameList(self._batched_operation_names) | |
| 2077 self._fix_members_code.Emit(' DOM$fixMembers($CLASSREF, $NAMES);\n', | |
| 2078 NAMES=member_string) | |
| 2079 | |
| 2080 # Define instanceof metadata. | |
| 2081 names = self._generator._AllImplementedInterfaces(self._interface) | |
| 2082 for name in names: | |
| 2083 # TODO(sra): Make this more compact. | |
| 2084 # TODO(sra): Generate metadata for parameterized superclasses. | |
| 2085 self._class_code.Emit(' $CLASSREF.$implements$$NAME$Dart = 1;\n', | |
| 2086 NAME=name) | |
| 2087 | |
| 2088 def _InterfaceIsAugmentedOnDemand(self, interface): | |
| 2089 return interface.id in _evasive_types | |
| 2090 | |
| 2091 def _GenerateOnDemandInterfaceSetupHelpers(self, interface, code): | |
| 2092 """Generate functions that can initialize a prototype given an instance.""" | |
| 2093 code.Emit( | |
| 2094 'function DOM$fixClassOnDemand$$ID(c) {\n' | |
| 2095 ' if (c.DOM$initialized === true)\n' | |
| 2096 ' return;\n' | |
| 2097 ' c.DOM$initialized = true;\n' | |
| 2098 ' DOM$fixClass$$ID(c);\n' | |
| 2099 '}\n' | |
| 2100 'function DOM$fixValue$$ID(value) {\n' | |
| 2101 ' if (value == null)\n' | |
| 2102 ' return DOM$EnsureDartNull(value);\n' | |
| 2103 ' if (typeof value != "object")\n' | |
| 2104 ' return value;\n' | |
| 2105 ' var constructor = value.constructor;\n' | |
| 2106 ' if (constructor == null)\n' | |
| 2107 ' return value;\n' | |
| 2108 ' DOM$fixClassOnDemand$$ID(constructor);\n' | |
| 2109 ' return value;\n' | |
| 2110 '}\n') | |
| 2111 | |
| 2112 | |
| 2113 def _FetchAlternateConstructor(self, root, typename, accessors, temp): | |
| 2114 """Returns an expression that fetches the constructor for |typename|. | |
| 2115 | |
| 2116 The expression also assigns the constructor to temp. | |
| 2117 | |
| 2118 The constructor is generated by traversing a path of property accessors to | |
| 2119 find an exemplar object and then creating a fake constructor for the type of | |
| 2120 the object.. The temp is also used to avoid re-evaluation of the path | |
| 2121 prefixes. | |
| 2122 """ | |
| 2123 # TODO(sra): Rather than return the fake constructor: | |
| 2124 # {prototype: window.blah.blah.__proto__} | |
| 2125 # perhaps we should return the real constructor: | |
| 2126 # window.blah.blah.constructor | |
| 2127 prefix = root; | |
| 2128 steps = [] | |
| 2129 for accessor in accessors + ['__proto__']: | |
| 2130 steps.append("(%s = %s.%s)" % (temp, prefix, accessor)); | |
| 2131 prefix = temp | |
| 2132 return "%s && (%s = {prototype: %s})" % (' && '.join(steps), temp, temp) | |
| 2133 | |
| 2134 def AddConstant(self, constant): | |
| 2135 pass | |
| 2136 | |
| 2137 def AddGetter(self, attr): | |
| 2138 """Emits code to initialize an attribute getter.""" | |
| 2139 if attr.type.id in _evasive_types: | |
| 2140 self._proto_code.Emit(' $PROTOREF.$NAME$getter = function() {' | |
| 2141 ' return DOM$fixValue$$TYPE(this.$NAME);' | |
| 2142 ' };\n', | |
| 2143 NAME=attr.id, TYPE=attr.type.id) | |
| 2144 else: | |
| 2145 self._proto_code.Emit(' $PROTOREF.$NAME$getter = function() {' | |
| 2146 ' return DOM$EnsureDartNull(this.$NAME);' | |
| 2147 ' };\n', | |
| 2148 NAME=attr.id) | |
| 2149 | |
| 2150 def AddSetter(self, attr): | |
| 2151 """Emits code to initialize an attribute setter.""" | |
| 2152 # TODO(sra): Pick implementation depending on checked/unchecked mode. | |
| 2153 self._proto_code.Emit(' $PROTOREF.$NAME$setter = function(value) {' | |
| 2154 ' this.$NAME = value;' | |
| 2155 ' };\n', | |
| 2156 NAME=attr.id) | |
| 2157 | |
| 2158 def AddIndexer(self, element_type): | |
| 2159 """Emits code to initialize an indexer.""" | |
| 2160 # Does the indexer return an evasive type? | |
| 2161 if element_type in _evasive_types: | |
| 2162 self._proto_code.Emit( | |
| 2163 ' $PROTOREF.INDEX$operator = function(k) {' | |
| 2164 ' return DOM$fixValue$$TYPE(this[k]);' | |
| 2165 ' };\n', | |
| 2166 TYPE=element_type) | |
| 2167 else: | |
| 2168 self._proto_code.Emit( | |
| 2169 ' $PROTOREF.INDEX$operator = function(k) {' | |
| 2170 ' return DOM$EnsureDartNull(this[k]);' | |
| 2171 ' };\n') | |
| 2172 # TODO(sra): Check for read-only indexers. | |
| 2173 # TODO(sra): Validate 'v' argument when checked. | |
| 2174 self._proto_code.Emit( | |
| 2175 ' $PROTOREF.ASSIGN_INDEX$operator = function(k, v) {' | |
| 2176 ' this[k] = v;' | |
| 2177 ' };\n') | |
| 2178 | |
| 2179 def AddOperation(self, info): | |
| 2180 """ | |
| 2181 Arguments: | |
| 2182 info: An OperationInfo object. | |
| 2183 """ | |
| 2184 name = info.name | |
| 2185 | |
| 2186 returned_types = [op.type.id for op in info.overloads] | |
| 2187 if any(type in _evasive_types for type in returned_types): | |
| 2188 if len(set(returned_types)) > 1: | |
| 2189 raise Exception('Cannot fix types on the fly when types different %s' % | |
| 2190 returned_types); | |
| 2191 | |
| 2192 self._class_code.Emit( | |
| 2193 ' $CLASSREF.prototype.$NAME$member = function() {\n' | |
| 2194 ' return DOM$fixValue$$TYPE(this.$JSNAME.apply(this, arguments));\n
' | |
| 2195 ' };\n', | |
| 2196 NAME=info.name, JSNAME=info.js_name, TYPE=returned_types[0]) | |
| 2197 elif info.name != info.js_name: | |
| 2198 self._class_code.Emit( | |
| 2199 ' $CLASSREF.prototype.$NAME$member = function() {\n' | |
| 2200 ' return DOM$EnsureDartNull(this.$JSNAME.apply(this, arguments));\n
' | |
| 2201 ' };\n', | |
| 2202 NAME=info.name, JSNAME=info.js_name, TYPE=returned_types[0]) | |
| 2203 else: | |
| 2204 self._batched_operation_names.append(info.name) | |
| 2205 | |
| 2206 def AddSecondaryGetter(self, interface, attr): | |
| 2207 self.AddGetter(attr) | |
| 2208 | |
| 2209 def AddSecondarySetter(self, interface, attr): | |
| 2210 self.AddSetter(attr) | |
| 2211 | |
| 2212 def AddSecondaryOperation(self, interface, info): | |
| 2213 self.AddOperation(info) | |
| 2214 | |
| 2215 # ------------------------------------------------------------------------------ | |
| 2216 | |
| 2217 class FrogInterfaceGenerator(object): | 1951 class FrogInterfaceGenerator(object): |
| 2218 """Generates a Frog class for a DOM IDL interface.""" | 1952 """Generates a Frog class for a DOM IDL interface.""" |
| 2219 | 1953 |
| 2220 def __init__(self, interface, super_interface, interfaces_with_subtypes, | 1954 def __init__(self, interface, super_interface, interfaces_with_subtypes, |
| 2221 dart_code): | 1955 dart_code): |
| 2222 """Generates Dart code for the given interface. | 1956 """Generates Dart code for the given interface. |
| 2223 | 1957 |
| 2224 Args: | 1958 Args: |
| 2225 | 1959 |
| 2226 interface: an IDLInterface instance. It is assumed that all types have | 1960 interface: an IDLInterface instance. It is assumed that all types have |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2429 Arguments: | 2163 Arguments: |
| 2430 info: An OperationInfo object. | 2164 info: An OperationInfo object. |
| 2431 """ | 2165 """ |
| 2432 # TODO(vsm): Handle overloads. | 2166 # TODO(vsm): Handle overloads. |
| 2433 self._members_emitter.Emit( | 2167 self._members_emitter.Emit( |
| 2434 '\n' | 2168 '\n' |
| 2435 ' $TYPE $NAME($ARGS) native;\n', | 2169 ' $TYPE $NAME($ARGS) native;\n', |
| 2436 TYPE=info.type_name, | 2170 TYPE=info.type_name, |
| 2437 NAME=info.name, | 2171 NAME=info.name, |
| 2438 ARGS=info.arg_implementation_declaration) | 2172 ARGS=info.arg_implementation_declaration) |
| OLD | NEW |