| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2012, 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 provides shared functionality for the system to generate | 6 """This module provides shared functionality for the system to generate |
| 7 Dart:html APIs from the IDL database.""" | 7 Dart:html APIs from the IDL database.""" |
| 8 | 8 |
| 9 import emitter | 9 import emitter |
| 10 import os | 10 import os |
| 11 from generator import * | 11 from generator import * |
| 12 | 12 |
| 13 _js_custom_members = set([ | 13 _js_custom_members = set([ |
| 14 'AudioBufferSourceNode.start', | 14 'AudioBufferSourceNode.start', |
| 15 'AudioBufferSourceNode.stop', | 15 'AudioBufferSourceNode.stop', |
| 16 'CSSStyleDeclaration.getPropertyValue', | 16 'CSSStyleDeclaration.getPropertyValue', |
| 17 'CSSStyleDeclaration.setProperty', | 17 'CSSStyleDeclaration.setProperty', |
| 18 'Element.insertAdjacentElement', | 18 'Element.insertAdjacentElement', |
| 19 'Element.insertAdjacentHTML', | 19 'Element.insertAdjacentHTML', |
| 20 'Element.insertAdjacentText', | 20 'Element.insertAdjacentText', |
| 21 'Element.remove', | 21 'Element.remove', |
| 22 'ElementEvents.mouseWheel', | 22 'ElementEvents.mouseWheel', |
| 23 'IDBDatabase.transaction', | 23 'IDBDatabase.transaction', |
| 24 'IFrameElement.contentWindow', | 24 'IFrameElement.contentWindow', |
| 25 'MouseEvent.offsetX', | 25 'MouseEvent.offsetX', |
| 26 'MouseEvent.offsetY', | 26 'MouseEvent.offsetY', |
| 27 'TableElement.createTBody', | 27 'TableElement.createTBody', |
| 28 'Window.document', | 28 'LocalWindow.document', |
| 29 'Window.indexedDB', | 29 'LocalWindow.indexedDB', |
| 30 'Window.location', | 30 'LocalWindow.location', |
| 31 'Window.open', | 31 'LocalWindow.open', |
| 32 'Window.top', | 32 'LocalWindow.top', |
| 33 'Window.webkitCancelAnimationFrame', | 33 'LocalWindow.webkitCancelAnimationFrame', |
| 34 'Window.webkitRequestAnimationFrame', | 34 'LocalWindow.webkitRequestAnimationFrame', |
| 35 ]) | 35 ]) |
| 36 | 36 |
| 37 # This map controls merging of interfaces in dart:html library. | 37 # This map controls merging of interfaces in dart:html library. |
| 38 # All constants, attributes, and operations of merged interface (key) are | 38 # All constants, attributes, and operations of merged interface (key) are |
| 39 # added to target interface (value). All references to the merged interface | 39 # added to target interface (value). All references to the merged interface |
| 40 # (e.g. parameter types, return types, parent interfaces) are replaced with | 40 # (e.g. parameter types, return types, parent interfaces) are replaced with |
| 41 # target interface. There are two important restrictions: | 41 # target interface. There are two important restrictions: |
| 42 # 1) Merged and target interfaces shouldn't have common members, otherwise there | 42 # 1) Merged and target interfaces shouldn't have common members, otherwise there |
| 43 # would be duplicated declarations in generated Dart code. | 43 # would be duplicated declarations in generated Dart code. |
| 44 # 2) Merged interface should be direct child of target interface, so the | 44 # 2) Merged interface should be direct child of target interface, so the |
| 45 # children of merged interface are not affected by the merge. | 45 # children of merged interface are not affected by the merge. |
| 46 # As a consequence, target interface implementation and its direct children | 46 # As a consequence, target interface implementation and its direct children |
| 47 # interface implementations should implement merged attribute accessors and | 47 # interface implementations should implement merged attribute accessors and |
| 48 # operations. For example, SVGElement and Element implementation classes should | 48 # operations. For example, SVGElement and Element implementation classes should |
| 49 # implement HTMLElement.insertAdjacentElement(), HTMLElement.innerHTML, etc. | 49 # implement HTMLElement.insertAdjacentElement(), HTMLElement.innerHTML, etc. |
| 50 _merged_html_interfaces = { | 50 _merged_html_interfaces = { |
| 51 'HTMLDocument': 'Document', | 51 'HTMLDocument': 'Document', |
| 52 'HTMLElement': 'Element' | 52 'HTMLElement': 'Element' |
| 53 } | 53 } |
| 54 | 54 |
| 55 # Types that are accessible cross-frame in a limited fashion. |
| 56 # In these cases, the base type (e.g., Window) provides restricted access |
| 57 # while the subtype (e.g., LocalWindow) provides full access to the |
| 58 # corresponding objects if there are from the same frame. |
| 59 _secure_base_types = { |
| 60 'LocalWindow': 'Window', |
| 61 'LocalLocation': 'Location', |
| 62 'LocalHistory': 'History', |
| 63 } |
| 64 |
| 65 def SecureOutputType(generator, type_name): |
| 66 dart_name = generator._DartType(type_name) |
| 67 if dart_name in _secure_base_types: |
| 68 return _secure_base_types[dart_name] |
| 69 return dart_name |
| 70 |
| 55 # Information for generating element constructors. | 71 # Information for generating element constructors. |
| 56 # | 72 # |
| 57 # TODO(sra): maybe remove all the argument complexity and use cascades. | 73 # TODO(sra): maybe remove all the argument complexity and use cascades. |
| 58 # | 74 # |
| 59 # var c = new CanvasElement(width: 100, height: 70); | 75 # var c = new CanvasElement(width: 100, height: 70); |
| 60 # var c = new CanvasElement()..width = 100..height = 70; | 76 # var c = new CanvasElement()..width = 100..height = 70; |
| 61 # | 77 # |
| 62 class ElementConstructorInfo(object): | 78 class ElementConstructorInfo(object): |
| 63 def __init__(self, name=None, tag=None, | 79 def __init__(self, name=None, tag=None, |
| 64 params=[], opt_params=[], | 80 params=[], opt_params=[], |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 # Parent is a DOM type. | 259 # Parent is a DOM type. |
| 244 implements.append(self._DartType(parent.type.id)) | 260 implements.append(self._DartType(parent.type.id)) |
| 245 elif '<' in parent.type.id: | 261 elif '<' in parent.type.id: |
| 246 # Parent is a Dart collection type. | 262 # Parent is a Dart collection type. |
| 247 # TODO(vsm): Make this check more robust. | 263 # TODO(vsm): Make this check more robust. |
| 248 implements.append(self._DartType(parent.type.id)) | 264 implements.append(self._DartType(parent.type.id)) |
| 249 else: | 265 else: |
| 250 suppressed_implements.append('%s.%s' % | 266 suppressed_implements.append('%s.%s' % |
| 251 (self._common_prefix, self._DartType(parent.type.id))) | 267 (self._common_prefix, self._DartType(parent.type.id))) |
| 252 | 268 |
| 269 if typename in _secure_base_types: |
| 270 implements.append(_secure_base_types[typename]) |
| 271 |
| 253 comment = ' extends' | 272 comment = ' extends' |
| 254 implements_str = '' | 273 implements_str = '' |
| 255 if implements: | 274 if implements: |
| 256 implements_str += ' implements ' + ', '.join(implements) | 275 implements_str += ' implements ' + ', '.join(implements) |
| 257 comment = ',' | 276 comment = ',' |
| 258 if suppressed_implements: | 277 if suppressed_implements: |
| 259 implements_str += ' /*%s %s */' % (comment, | 278 implements_str += ' /*%s %s */' % (comment, |
| 260 ', '.join(suppressed_implements)) | 279 ', '.join(suppressed_implements)) |
| 261 | 280 |
| 262 factory_provider = None | 281 factory_provider = None |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', | 467 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', |
| 449 DOMINTERFACE=attribute.doc_js_interface_name, | 468 DOMINTERFACE=attribute.doc_js_interface_name, |
| 450 DOMNAME=dom_name) | 469 DOMNAME=dom_name) |
| 451 if read_only: | 470 if read_only: |
| 452 template = '\n abstract $TYPE get $NAME;\n' | 471 template = '\n abstract $TYPE get $NAME;\n' |
| 453 else: | 472 else: |
| 454 template = '\n $TYPE $NAME;\n' | 473 template = '\n $TYPE $NAME;\n' |
| 455 | 474 |
| 456 self._members_emitter.Emit(template, | 475 self._members_emitter.Emit(template, |
| 457 NAME=html_name, | 476 NAME=html_name, |
| 458 TYPE=self._DartType(attribute.type.id)) | 477 TYPE=SecureOutputType(self, attribute.type.id)) |
| 459 | 478 |
| 460 self._backend.AddAttribute(attribute, html_name, read_only) | 479 self._backend.AddAttribute(attribute, html_name, read_only) |
| 461 | 480 |
| 462 def AddSecondaryAttribute(self, interface, attribute): | 481 def AddSecondaryAttribute(self, interface, attribute): |
| 463 self._backend.SecondaryContext(interface) | 482 self._backend.SecondaryContext(interface) |
| 464 self.AddAttribute(attribute, True) | 483 self.AddAttribute(attribute, True) |
| 465 | 484 |
| 466 def AddOperation(self, info, skip_declaration=False): | 485 def AddOperation(self, info, skip_declaration=False): |
| 467 """ | 486 """ |
| 468 Arguments: | 487 Arguments: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 483 | 502 |
| 484 if info.IsStatic(): | 503 if info.IsStatic(): |
| 485 # FIXME: provide a type. | 504 # FIXME: provide a type. |
| 486 self._members_emitter.Emit('\n' | 505 self._members_emitter.Emit('\n' |
| 487 ' static final $NAME = $IMPL_CLASS_NAME.$NAME
;\n', | 506 ' static final $NAME = $IMPL_CLASS_NAME.$NAME
;\n', |
| 488 IMPL_CLASS_NAME=self._backend.ImplementationCl
assName(), | 507 IMPL_CLASS_NAME=self._backend.ImplementationCl
assName(), |
| 489 NAME=html_name) | 508 NAME=html_name) |
| 490 else: | 509 else: |
| 491 self._members_emitter.Emit('\n' | 510 self._members_emitter.Emit('\n' |
| 492 ' $TYPE $NAME($PARAMS);\n', | 511 ' $TYPE $NAME($PARAMS);\n', |
| 493 TYPE=self._DartType(info.type_name), | 512 TYPE=SecureOutputType(self, info.type_name), |
| 494 NAME=html_name, | 513 NAME=html_name, |
| 495 PARAMS=info.ParametersInterfaceDeclaration(sel
f._DartType)) | 514 PARAMS=info.ParametersInterfaceDeclaration(sel
f._DartType)) |
| 496 self._backend.AddOperation(info, html_name) | 515 self._backend.AddOperation(info, html_name) |
| 497 | 516 |
| 498 def AddSecondaryOperation(self, interface, info): | 517 def AddSecondaryOperation(self, interface, info): |
| 499 self._backend.SecondaryContext(interface) | 518 self._backend.SecondaryContext(interface) |
| 500 self.AddOperation(info, True) | 519 self.AddOperation(info, True) |
| 501 | 520 |
| 502 def AddConstant(self, constant): | 521 def AddConstant(self, constant): |
| 503 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) | 522 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 | 1059 |
| 1041 def _NarrowToImplementationType(self, type_name): | 1060 def _NarrowToImplementationType(self, type_name): |
| 1042 if self._ShouldNarrowToImplementationType(type_name): | 1061 if self._ShouldNarrowToImplementationType(type_name): |
| 1043 return self._ImplClassName(self._DartType(type_name)) | 1062 return self._ImplClassName(self._DartType(type_name)) |
| 1044 return self._DartType(type_name) | 1063 return self._DartType(type_name) |
| 1045 | 1064 |
| 1046 def _NarrowInputType(self, type_name): | 1065 def _NarrowInputType(self, type_name): |
| 1047 return self._NarrowToImplementationType(type_name) | 1066 return self._NarrowToImplementationType(type_name) |
| 1048 | 1067 |
| 1049 def _NarrowOutputType(self, type_name): | 1068 def _NarrowOutputType(self, type_name): |
| 1050 return self._NarrowToImplementationType(type_name) | 1069 return SecureOutputType(self, self._NarrowToImplementationType(type_name)) |
| 1051 | 1070 |
| 1052 def _FindShadowedAttribute(self, attr, merged_interfaces={}): | 1071 def _FindShadowedAttribute(self, attr, merged_interfaces={}): |
| 1053 """Returns (attribute, superinterface) or (None, None).""" | 1072 """Returns (attribute, superinterface) or (None, None).""" |
| 1054 def FindInParent(interface): | 1073 def FindInParent(interface): |
| 1055 """Returns matching attribute in parent, or None.""" | 1074 """Returns matching attribute in parent, or None.""" |
| 1056 if interface.parents: | 1075 if interface.parents: |
| 1057 parent = interface.parents[0] | 1076 parent = interface.parents[0] |
| 1058 if IsDartCollectionType(parent.type.id): | 1077 if IsDartCollectionType(parent.type.id): |
| 1059 return (None, None) | 1078 return (None, None) |
| 1060 if IsPureInterface(parent.type.id): | 1079 if IsPureInterface(parent.type.id): |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 | 1134 |
| 1116 library_emitter = self._multiemitter.FileEmitter(library_file_path) | 1135 library_emitter = self._multiemitter.FileEmitter(library_file_path) |
| 1117 library_file_dir = os.path.dirname(library_file_path) | 1136 library_file_dir = os.path.dirname(library_file_path) |
| 1118 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) | 1137 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) |
| 1119 imports_emitter = library_emitter.Emit( | 1138 imports_emitter = library_emitter.Emit( |
| 1120 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) | 1139 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) |
| 1121 for path in sorted(self._path_to_emitter.keys()): | 1140 for path in sorted(self._path_to_emitter.keys()): |
| 1122 relpath = os.path.relpath(path, library_file_dir) | 1141 relpath = os.path.relpath(path, library_file_dir) |
| 1123 imports_emitter.Emit( | 1142 imports_emitter.Emit( |
| 1124 "#source('$PATH');\n", PATH=massage_path(relpath)) | 1143 "#source('$PATH');\n", PATH=massage_path(relpath)) |
| OLD | NEW |