| 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 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 | 
| 11 import multiemitter | 11 import multiemitter | 
| 12 import os | 12 import os | 
| 13 import re | 13 import re | 
| 14 import shutil | 14 import shutil | 
| 15 from generator import * | 15 from generator import * | 
| 16 from systembase import * | 16 from systembase import * | 
| 17 from systemfrog import * | 17 from systemfrog import * | 
| 18 from systemhtml import * | 18 from systemhtml import * | 
| 19 from systeminterface import * | 19 from systeminterface import * | 
|  | 20 from systemnative import * | 
|  | 21 from systemwrapping import * | 
| 20 | 22 | 
| 21 _logger = logging.getLogger('dartgenerator') | 23 _logger = logging.getLogger('dartgenerator') | 
| 22 | 24 | 
| 23 def MergeNodes(node, other): | 25 def MergeNodes(node, other): | 
| 24   node.operations.extend(other.operations) | 26   node.operations.extend(other.operations) | 
| 25   for attribute in other.attributes: | 27   for attribute in other.attributes: | 
| 26     if not node.has_attribute(attribute): | 28     if not node.has_attribute(attribute): | 
| 27       node.attributes.append(attribute) | 29       node.attributes.append(attribute) | 
| 28 | 30 | 
| 29   node.constants.extend(other.constants) | 31   node.constants.extend(other.constants) | 
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 165       return self._StripModules(type_name) | 167       return self._StripModules(type_name) | 
| 166 | 168 | 
| 167     for interface in database.GetInterfaces(): | 169     for interface in database.GetInterfaces(): | 
| 168       for idl_type in interface.all(idlnode.IDLType): | 170       for idl_type in interface.all(idlnode.IDLType): | 
| 169         original_type_name = idl_type.id | 171         original_type_name = idl_type.id | 
| 170         idl_type.id = ConvertType(interface, idl_type.id) | 172         idl_type.id = ConvertType(interface, idl_type.id) | 
| 171         # FIXME: remember original idl types that are needed by native | 173         # FIXME: remember original idl types that are needed by native | 
| 172         # generator. We should migrate other generators to idl registry and | 174         # generator. We should migrate other generators to idl registry and | 
| 173         # remove this hack. | 175         # remove this hack. | 
| 174         if original_type_name != idl_type.id: | 176         if original_type_name != idl_type.id: | 
| 175           _original_idl_types[idl_type] = original_type_name | 177           original_idl_types[idl_type] = original_type_name | 
| 176 | 178 | 
| 177   def FilterInterfaces(self, database, | 179   def FilterInterfaces(self, database, | 
| 178                        and_annotations=[], | 180                        and_annotations=[], | 
| 179                        or_annotations=[], | 181                        or_annotations=[], | 
| 180                        exclude_displaced=[], | 182                        exclude_displaced=[], | 
| 181                        exclude_suppressed=[]): | 183                        exclude_suppressed=[]): | 
| 182     """Filters a database to remove interfaces and members that are missing | 184     """Filters a database to remove interfaces and members that are missing | 
| 183     annotations. | 185     annotations. | 
| 184 | 186 | 
| 185     The FremontCut IDLs use annotations to specify implementation | 187     The FremontCut IDLs use annotations to specify implementation | 
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 645         os.path.join(lib_dir, 'dom_dummy.dart'), | 647         os.path.join(lib_dir, 'dom_dummy.dart'), | 
| 646         (self._interface_system._dart_interface_file_paths + | 648         (self._interface_system._dart_interface_file_paths + | 
| 647          self._interface_system._dart_callback_file_paths + | 649          self._interface_system._dart_callback_file_paths + | 
| 648          [] | 650          [] | 
| 649          # FIXME: Move the implementation to a separate library. | 651          # FIXME: Move the implementation to a separate library. | 
| 650          # self._dart_wrapping_file_paths | 652          # self._dart_wrapping_file_paths | 
| 651          )) | 653          )) | 
| 652 | 654 | 
| 653 # ------------------------------------------------------------------------------ | 655 # ------------------------------------------------------------------------------ | 
| 654 | 656 | 
| 655 class WrappingImplementationSystem(System): |  | 
| 656 |  | 
| 657   def __init__(self, templates, database, emitters, output_dir): |  | 
| 658     """Prepared for generating wrapping implementation. |  | 
| 659 |  | 
| 660     - Creates emitter for JS code. |  | 
| 661     - Creates emitter for Dart code. |  | 
| 662     """ |  | 
| 663     super(WrappingImplementationSystem, self).__init__( |  | 
| 664         templates, database, emitters, output_dir) |  | 
| 665     self._dart_wrapping_file_paths = [] |  | 
| 666 |  | 
| 667 |  | 
| 668   def InterfaceGenerator(self, |  | 
| 669                          interface, |  | 
| 670                          common_prefix, |  | 
| 671                          super_interface_name, |  | 
| 672                          source_filter): |  | 
| 673     """.""" |  | 
| 674     interface_name = interface.id |  | 
| 675     dart_wrapping_file_path = self._FilePathForDartWrappingImpl(interface_name) |  | 
| 676 |  | 
| 677     self._dart_wrapping_file_paths.append(dart_wrapping_file_path) |  | 
| 678 |  | 
| 679     dart_code = self._emitters.FileEmitter(dart_wrapping_file_path) |  | 
| 680     dart_code.Emit(self._templates.Load('wrapping_impl.darttemplate')) |  | 
| 681     return WrappingInterfaceGenerator(interface, super_interface_name, |  | 
| 682                                       dart_code, |  | 
| 683                                       self._BaseDefines(interface)) |  | 
| 684 |  | 
| 685   def ProcessCallback(self, interface, info): |  | 
| 686     pass |  | 
| 687 |  | 
| 688   def GenerateLibraries(self, lib_dir): |  | 
| 689     # Library generated for implementation. |  | 
| 690     self._GenerateLibFile( |  | 
| 691         'wrapping_dom.darttemplate', |  | 
| 692         os.path.join(lib_dir, 'wrapping_dom.dart'), |  | 
| 693         (self._interface_system._dart_interface_file_paths + |  | 
| 694          self._interface_system._dart_callback_file_paths + |  | 
| 695          # FIXME: Move the implementation to a separate library. |  | 
| 696          self._dart_wrapping_file_paths |  | 
| 697          )) |  | 
| 698 |  | 
| 699 |  | 
| 700   def Finish(self): |  | 
| 701     pass |  | 
| 702 |  | 
| 703 |  | 
| 704   def _FilePathForDartWrappingImpl(self, interface_name): |  | 
| 705     """Returns the file path of the Dart wrapping implementation.""" |  | 
| 706     return os.path.join(self._output_dir, 'src', 'wrapping', |  | 
| 707                         '_%sWrappingImplementation.dart' % interface_name) |  | 
| 708 |  | 
| 709 # ------------------------------------------------------------------------------ |  | 
| 710 |  | 
| 711 class DummyInterfaceGenerator(object): | 657 class DummyInterfaceGenerator(object): | 
| 712   """Generates nothing.""" | 658   """Generates nothing.""" | 
| 713 | 659 | 
| 714   def __init__(self, system, interface): | 660   def __init__(self, system, interface): | 
| 715     pass | 661     pass | 
| 716 | 662 | 
| 717   def StartInterface(self): | 663   def StartInterface(self): | 
| 718     pass | 664     pass | 
| 719 | 665 | 
| 720   def FinishInterface(self): | 666   def FinishInterface(self): | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 736     pass | 682     pass | 
| 737 | 683 | 
| 738   def AddTypedArrayConstructors(self, element_type): | 684   def AddTypedArrayConstructors(self, element_type): | 
| 739     pass | 685     pass | 
| 740 | 686 | 
| 741   def AddOperation(self, info): | 687   def AddOperation(self, info): | 
| 742     pass | 688     pass | 
| 743 | 689 | 
| 744   def AddEventAttributes(self, event_attrs): | 690   def AddEventAttributes(self, event_attrs): | 
| 745     pass | 691     pass | 
| 746 |  | 
| 747 # ------------------------------------------------------------------------------ |  | 
| 748 |  | 
| 749 class WrappingInterfaceGenerator(object): |  | 
| 750   """Generates Dart and JS implementation for one DOM IDL interface.""" |  | 
| 751 |  | 
| 752   def __init__(self, interface, super_interface, dart_code, base_members): |  | 
| 753     """Generates Dart and JS code for the given interface. |  | 
| 754 |  | 
| 755     Args: |  | 
| 756 |  | 
| 757       interface: an IDLInterface instance. It is assumed that all types have |  | 
| 758           been converted to Dart types (e.g. int, String), unless they are in |  | 
| 759           the same package as the interface. |  | 
| 760       super_interface: A string or None, the name of the common interface that |  | 
| 761          this interface implements, if any. |  | 
| 762       dart_code: an Emitter for the file containing the Dart implementation |  | 
| 763           class. |  | 
| 764       base_members: a set of names of members defined in a base class.  This is |  | 
| 765           used to avoid static member 'overriding' in the generated Dart code. |  | 
| 766     """ |  | 
| 767     self._interface = interface |  | 
| 768     self._super_interface = super_interface |  | 
| 769     self._dart_code = dart_code |  | 
| 770     self._base_members = base_members |  | 
| 771     self._current_secondary_parent = None |  | 
| 772 |  | 
| 773 |  | 
| 774   def StartInterface(self): |  | 
| 775     interface = self._interface |  | 
| 776     interface_name = interface.id |  | 
| 777 |  | 
| 778     self._class_name = self._ImplClassName(interface_name) |  | 
| 779 |  | 
| 780     base = self._BaseClassName(interface) |  | 
| 781 |  | 
| 782     (self._members_emitter, |  | 
| 783      self._top_level_emitter) = self._dart_code.Emit( |  | 
| 784         '\n' |  | 
| 785         'class $CLASS extends $BASE implements $INTERFACE {\n' |  | 
| 786         '  $CLASS() : super() {}\n' |  | 
| 787         '\n' |  | 
| 788         '  static create_$CLASS() native {\n' |  | 
| 789         '    return new $CLASS();\n' |  | 
| 790         '  }\n' |  | 
| 791         '$!MEMBERS' |  | 
| 792         '\n' |  | 
| 793         '  String get typeName() { return "$INTERFACE"; }\n' |  | 
| 794         '}\n' |  | 
| 795         '$!TOP_LEVEL', |  | 
| 796         CLASS=self._class_name, BASE=base, INTERFACE=interface_name) |  | 
| 797 |  | 
| 798   def _ImplClassName(self, type_name): |  | 
| 799     return '_' + type_name + 'WrappingImplementation' |  | 
| 800 |  | 
| 801   def _BaseClassName(self, interface): |  | 
| 802     if not interface.parents: |  | 
| 803       return 'DOMWrapperBase' |  | 
| 804 |  | 
| 805     supertype = interface.parents[0].type.id |  | 
| 806 |  | 
| 807     # FIXME: We're currently injecting List<..> and EventTarget as |  | 
| 808     # supertypes in dart.idl. We should annotate/preserve as |  | 
| 809     # attributes instead.  For now, this hack lets the interfaces |  | 
| 810     # inherit, but not the classes. |  | 
| 811     # List methods are injected in AddIndexer. |  | 
| 812     if IsDartListType(supertype) or IsDartCollectionType(supertype): |  | 
| 813       return 'DOMWrapperBase' |  | 
| 814 |  | 
| 815     if supertype == 'EventTarget': |  | 
| 816       # Most implementors of EventTarget specify the EventListener operations |  | 
| 817       # again.  If the operations are not specified, try to inherit from the |  | 
| 818       # EventTarget implementation. |  | 
| 819       # |  | 
| 820       # Applies to MessagePort. |  | 
| 821       if not [op for op in interface.operations if op.id == 'addEventListener']: |  | 
| 822         return self._ImplClassName(supertype) |  | 
| 823       return 'DOMWrapperBase' |  | 
| 824 |  | 
| 825     return self._ImplClassName(supertype) |  | 
| 826 |  | 
| 827   def FinishInterface(self): |  | 
| 828     """.""" |  | 
| 829     pass |  | 
| 830 |  | 
| 831   def AddConstant(self, constant): |  | 
| 832     # Constants are already defined on the interface. |  | 
| 833     pass |  | 
| 834 |  | 
| 835   def _MethodName(self, prefix, name): |  | 
| 836     method_name = prefix + name |  | 
| 837     if name in self._base_members:  # Avoid illegal Dart 'static override'. |  | 
| 838       method_name = method_name + '_' + self._interface.id |  | 
| 839     return method_name |  | 
| 840 |  | 
| 841   def AddAttribute(self, getter, setter): |  | 
| 842     if getter: |  | 
| 843       self._AddGetter(getter) |  | 
| 844     if setter: |  | 
| 845       self._AddSetter(setter) |  | 
| 846 |  | 
| 847   def _AddGetter(self, attr): |  | 
| 848     # FIXME: Instead of injecting the interface name into the method when it is |  | 
| 849     # also implemented in the base class, suppress the method altogether if it |  | 
| 850     # has the same signature.  I.e., let the JS do the virtual dispatch instead. |  | 
| 851     method_name = self._MethodName('_get_', attr.id) |  | 
| 852     self._members_emitter.Emit( |  | 
| 853         '\n' |  | 
| 854         '  $TYPE get $NAME() { return $METHOD(this); }\n' |  | 
| 855         '  static $TYPE $METHOD(var _this) native;\n', |  | 
| 856         NAME=attr.id, TYPE=attr.type.id, METHOD=method_name) |  | 
| 857 |  | 
| 858   def _AddSetter(self, attr): |  | 
| 859     # FIXME: See comment on getter. |  | 
| 860     method_name = self._MethodName('_set_', attr.id) |  | 
| 861     self._members_emitter.Emit( |  | 
| 862         '\n' |  | 
| 863         '  void set $NAME($TYPE value) { $METHOD(this, value); }\n' |  | 
| 864         '  static void $METHOD(var _this, $TYPE value) native;\n', |  | 
| 865         NAME=attr.id, TYPE=attr.type.id, METHOD=method_name) |  | 
| 866 |  | 
| 867   def AddSecondaryAttribute(self, interface, getter, setter): |  | 
| 868     self._SecondaryContext(interface) |  | 
| 869     self.AddAttribute(getter, setter) |  | 
| 870 |  | 
| 871   def AddSecondaryOperation(self, interface, info): |  | 
| 872     self._SecondaryContext(interface) |  | 
| 873     self.AddOperation(info) |  | 
| 874 |  | 
| 875   def AddEventAttributes(self, event_attrs): |  | 
| 876     pass |  | 
| 877 |  | 
| 878   def _SecondaryContext(self, interface): |  | 
| 879     if interface is not self._current_secondary_parent: |  | 
| 880       self._current_secondary_parent = interface |  | 
| 881       self._members_emitter.Emit('\n  // From $WHERE\n', WHERE=interface.id) |  | 
| 882 |  | 
| 883   def AddIndexer(self, element_type): |  | 
| 884     """Adds all the methods required to complete implementation of List.""" |  | 
| 885     # We would like to simply inherit the implementation of everything except |  | 
| 886     # get length(), [], and maybe []=.  It is possible to extend from a base |  | 
| 887     # array implementation class only when there is no other implementation |  | 
| 888     # inheritance.  There might be no implementation inheritance other than |  | 
| 889     # DOMBaseWrapper for many classes, but there might be some where the |  | 
| 890     # array-ness is introduced by a non-root interface: |  | 
| 891     # |  | 
| 892     #   interface Y extends X, List<T> ... |  | 
| 893     # |  | 
| 894     # In the non-root case we have to choose between: |  | 
| 895     # |  | 
| 896     #   class YImpl extends XImpl { add List<T> methods; } |  | 
| 897     # |  | 
| 898     # and |  | 
| 899     # |  | 
| 900     #   class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |  | 
| 901     # |  | 
| 902     if self._HasNativeIndexGetter(self._interface): |  | 
| 903       self._EmitNativeIndexGetter(self._interface, element_type) |  | 
| 904     else: |  | 
| 905       self._members_emitter.Emit( |  | 
| 906           '\n' |  | 
| 907           '  $TYPE operator[](int index) {\n' |  | 
| 908           '    return item(index);\n' |  | 
| 909           '  }\n', |  | 
| 910           TYPE=element_type) |  | 
| 911 |  | 
| 912     if self._HasNativeIndexSetter(self._interface): |  | 
| 913       self._EmitNativeIndexSetter(self._interface, element_type) |  | 
| 914     else: |  | 
| 915       self._members_emitter.Emit( |  | 
| 916           '\n' |  | 
| 917           '  void operator[]=(int index, $TYPE value) {\n' |  | 
| 918           '    throw new UnsupportedOperationException("Cannot assign element of
       immutable List.");\n' |  | 
| 919           '  }\n', |  | 
| 920           TYPE=element_type) |  | 
| 921 |  | 
| 922     self._members_emitter.Emit( |  | 
| 923         '\n' |  | 
| 924         '  void add($TYPE value) {\n' |  | 
| 925         '    throw new UnsupportedOperationException("Cannot add to immutable Li
      st.");\n' |  | 
| 926         '  }\n' |  | 
| 927         '\n' |  | 
| 928         '  void addLast($TYPE value) {\n' |  | 
| 929         '    throw new UnsupportedOperationException("Cannot add to immutable Li
      st.");\n' |  | 
| 930         '  }\n' |  | 
| 931         '\n' |  | 
| 932         '  void addAll(Collection<$TYPE> collection) {\n' |  | 
| 933         '    throw new UnsupportedOperationException("Cannot add to immutable Li
      st.");\n' |  | 
| 934         '  }\n' |  | 
| 935         '\n' |  | 
| 936         '  void sort(int compare($TYPE a, $TYPE b)) {\n' |  | 
| 937         '    throw new UnsupportedOperationException("Cannot sort immutable List
      .");\n' |  | 
| 938         '  }\n' |  | 
| 939         '\n' |  | 
| 940         '  void copyFrom(List<Object> src, int srcStart, ' |  | 
| 941         'int dstStart, int count) {\n' |  | 
| 942         '    throw new UnsupportedOperationException("This object is immutable."
      );\n' |  | 
| 943         '  }\n' |  | 
| 944         '\n' |  | 
| 945         '  int indexOf($TYPE element, [int start = 0]) {\n' |  | 
| 946         '    return _Lists.indexOf(this, element, start, this.length);\n' |  | 
| 947         '  }\n' |  | 
| 948         '\n' |  | 
| 949         '  int lastIndexOf($TYPE element, [int start = null]) {\n' |  | 
| 950         '    if (start === null) start = length - 1;\n' |  | 
| 951         '    return _Lists.lastIndexOf(this, element, start);\n' |  | 
| 952         '  }\n' |  | 
| 953         '\n' |  | 
| 954         '  int clear() {\n' |  | 
| 955         '    throw new UnsupportedOperationException("Cannot clear immutable Lis
      t.");\n' |  | 
| 956         '  }\n' |  | 
| 957         '\n' |  | 
| 958         '  $TYPE removeLast() {\n' |  | 
| 959         '    throw new UnsupportedOperationException("Cannot removeLast on immut
      able List.");\n' |  | 
| 960         '  }\n' |  | 
| 961         '\n' |  | 
| 962         '  $TYPE last() {\n' |  | 
| 963         '    return this[length - 1];\n' |  | 
| 964         '  }\n' |  | 
| 965         '\n' |  | 
| 966         '  void forEach(void f($TYPE element)) {\n' |  | 
| 967         '    _Collections.forEach(this, f);\n' |  | 
| 968         '  }\n' |  | 
| 969         '\n' |  | 
| 970         '  Collection map(f($TYPE element)) {\n' |  | 
| 971         '    return _Collections.map(this, [], f);\n' |  | 
| 972         '  }\n' |  | 
| 973         '\n' |  | 
| 974         '  Collection<$TYPE> filter(bool f($TYPE element)) {\n' |  | 
| 975         '    return _Collections.filter(this, new List<$TYPE>(), f);\n' |  | 
| 976         '  }\n' |  | 
| 977         '\n' |  | 
| 978         '  bool every(bool f($TYPE element)) {\n' |  | 
| 979         '    return _Collections.every(this, f);\n' |  | 
| 980         '  }\n' |  | 
| 981         '\n' |  | 
| 982         '  bool some(bool f($TYPE element)) {\n' |  | 
| 983         '    return _Collections.some(this, f);\n' |  | 
| 984         '  }\n' |  | 
| 985         '\n' |  | 
| 986         '  void setRange(int start, int length, List<$TYPE> from, [int startFrom
      ]) {\n' |  | 
| 987         '    throw new UnsupportedOperationException("Cannot setRange on immutab
      le List.");\n' |  | 
| 988         '  }\n' |  | 
| 989         '\n' |  | 
| 990         '  void removeRange(int start, int length) {\n' |  | 
| 991         '    throw new UnsupportedOperationException("Cannot removeRange on immu
      table List.");\n' |  | 
| 992         '  }\n' |  | 
| 993         '\n' |  | 
| 994         '  void insertRange(int start, int length, [$TYPE initialValue]) {\n' |  | 
| 995         '    throw new UnsupportedOperationException("Cannot insertRange on immu
      table List.");\n' |  | 
| 996         '  }\n' |  | 
| 997         '\n' |  | 
| 998         '  List<$TYPE> getRange(int start, int length) {\n' |  | 
| 999         '    throw new NotImplementedException();\n' |  | 
| 1000         '  }\n' |  | 
| 1001         '\n' |  | 
| 1002         '  bool isEmpty() {\n' |  | 
| 1003         '    return length == 0;\n' |  | 
| 1004         '  }\n' |  | 
| 1005         '\n' |  | 
| 1006         '  Iterator<$TYPE> iterator() {\n' |  | 
| 1007         '    return new _FixedSizeListIterator<$TYPE>(this);\n' |  | 
| 1008         '  }\n', |  | 
| 1009         TYPE=element_type) |  | 
| 1010 |  | 
| 1011   def _HasNativeIndexGetter(self, interface): |  | 
| 1012     return ('IndexedGetter' in interface.ext_attrs or |  | 
| 1013             'NumericIndexedGetter' in interface.ext_attrs) |  | 
| 1014 |  | 
| 1015   def _EmitNativeIndexGetter(self, interface, element_type): |  | 
| 1016     method_name = '_index' |  | 
| 1017     self._members_emitter.Emit( |  | 
| 1018         '\n' |  | 
| 1019         '  $TYPE operator[](int index) { return $METHOD(this, index); }\n' |  | 
| 1020         '  static $TYPE $METHOD(var _this, int index) native;\n', |  | 
| 1021         TYPE=element_type, METHOD=method_name) |  | 
| 1022 |  | 
| 1023   def _HasNativeIndexSetter(self, interface): |  | 
| 1024     return 'CustomIndexedSetter' in interface.ext_attrs |  | 
| 1025 |  | 
| 1026   def _EmitNativeIndexSetter(self, interface, element_type): |  | 
| 1027     method_name = '_set_index' |  | 
| 1028     self._members_emitter.Emit( |  | 
| 1029         '\n' |  | 
| 1030         '  void operator[]=(int index, $TYPE value) {\n' |  | 
| 1031         '    return $METHOD(this, index, value);\n' |  | 
| 1032         '  }\n' |  | 
| 1033         '  static $METHOD(_this, index, value) native;\n', |  | 
| 1034         TYPE=element_type, METHOD=method_name) |  | 
| 1035 |  | 
| 1036   def AddOperation(self, info): |  | 
| 1037     """ |  | 
| 1038     Arguments: |  | 
| 1039       info: An OperationInfo object. |  | 
| 1040     """ |  | 
| 1041     body = self._members_emitter.Emit( |  | 
| 1042         '\n' |  | 
| 1043         '  $TYPE $NAME($PARAMS) {\n' |  | 
| 1044         '$!BODY' |  | 
| 1045         '  }\n', |  | 
| 1046         TYPE=info.type_name, |  | 
| 1047         NAME=info.name, |  | 
| 1048         PARAMS=info.ParametersImplementationDeclaration()) |  | 
| 1049 |  | 
| 1050     # Process in order of ascending number of arguments to ensure missing |  | 
| 1051     # optional arguments are processed early. |  | 
| 1052     overloads = sorted(info.overloads, |  | 
| 1053                        key=lambda overload: len(overload.arguments)) |  | 
| 1054     self._native_version = 0 |  | 
| 1055     fallthrough = self.GenerateDispatch(body, info, '    ', 0, overloads) |  | 
| 1056     if fallthrough: |  | 
| 1057       body.Emit('    throw "Incorrect number or type of arguments";\n'); |  | 
| 1058 |  | 
| 1059   def GenerateSingleOperation(self,  emitter, info, indent, operation): |  | 
| 1060     """Generates a call to a single operation. |  | 
| 1061 |  | 
| 1062     Arguments: |  | 
| 1063       emitter: an Emitter for the body of a block of code. |  | 
| 1064       info: the compound information about the operation and its overloads. |  | 
| 1065       indent: an indentation string for generated code. |  | 
| 1066       operation: the IDLOperation to call. |  | 
| 1067     """ |  | 
| 1068     # TODO(sra): Do we need to distinguish calling with missing optional |  | 
| 1069     # arguments from passing 'null' which is represented as 'undefined'? |  | 
| 1070     def UnwrapArgExpression(name, type): |  | 
| 1071       # TODO: Type specific unwrapping. |  | 
| 1072       return '__dom_unwrap(%s)' % (name) |  | 
| 1073 |  | 
| 1074     def ArgNameAndUnwrapper(arg_info, overload_arg): |  | 
| 1075       (name, type, value) = arg_info |  | 
| 1076       return (name, UnwrapArgExpression(name, type)) |  | 
| 1077 |  | 
| 1078     names_and_unwrappers = [ArgNameAndUnwrapper(info.arg_infos[i], arg) |  | 
| 1079                             for (i, arg) in enumerate(operation.arguments)] |  | 
| 1080     unwrap_args = [unwrap_arg for (_, unwrap_arg) in names_and_unwrappers] |  | 
| 1081     arg_names = [name for (name, _) in names_and_unwrappers] |  | 
| 1082 |  | 
| 1083     self._native_version += 1 |  | 
| 1084     native_name = self._MethodName('_', info.name) |  | 
| 1085     if self._native_version > 1: |  | 
| 1086       native_name = '%s_%s' % (native_name, self._native_version) |  | 
| 1087 |  | 
| 1088     argument_expressions = ', '.join(['this'] + arg_names) |  | 
| 1089     if info.type_name != 'void': |  | 
| 1090       emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n', |  | 
| 1091                    INDENT=indent, |  | 
| 1092                    NATIVENAME=native_name, |  | 
| 1093                    ARGS=argument_expressions) |  | 
| 1094     else: |  | 
| 1095       emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' |  | 
| 1096                    '$(INDENT)return;\n', |  | 
| 1097                    INDENT=indent, |  | 
| 1098                    NATIVENAME=native_name, |  | 
| 1099                    ARGS=argument_expressions) |  | 
| 1100 |  | 
| 1101     self._members_emitter.Emit('  static $TYPE $NAME($PARAMS) native;\n', |  | 
| 1102                                NAME=native_name, |  | 
| 1103                                TYPE=info.type_name, |  | 
| 1104                                PARAMS=', '.join(['receiver'] + arg_names) ) |  | 
| 1105 |  | 
| 1106 |  | 
| 1107   def GenerateDispatch(self, emitter, info, indent, position, overloads): |  | 
| 1108     """Generates a dispatch to one of the overloads. |  | 
| 1109 |  | 
| 1110     Arguments: |  | 
| 1111       emitter: an Emitter for the body of a block of code. |  | 
| 1112       info: the compound information about the operation and its overloads. |  | 
| 1113       indent: an indentation string for generated code. |  | 
| 1114       position: the index of the parameter to dispatch on. |  | 
| 1115       overloads: a list of the remaining IDLOperations to dispatch. |  | 
| 1116 |  | 
| 1117     Returns True if the dispatch can fall through on failure, False if the code |  | 
| 1118     always dispatches. |  | 
| 1119     """ |  | 
| 1120 |  | 
| 1121     def NullCheck(name): |  | 
| 1122       return '%s === null' % name |  | 
| 1123 |  | 
| 1124     def TypeCheck(name, type): |  | 
| 1125       return '%s is %s' % (name, type) |  | 
| 1126 |  | 
| 1127     if position == len(info.arg_infos): |  | 
| 1128       if len(overloads) > 1: |  | 
| 1129         raise Exception('Duplicate operations ' + str(overloads)) |  | 
| 1130       operation = overloads[0] |  | 
| 1131       self.GenerateSingleOperation(emitter, info, indent, operation) |  | 
| 1132       return False |  | 
| 1133 |  | 
| 1134     # FIXME: Consider a simpler dispatch that iterates over the |  | 
| 1135     # overloads and generates an overload specific check.  Revisit |  | 
| 1136     # when we move to named optional arguments. |  | 
| 1137 |  | 
| 1138     # Partition the overloads to divide and conquer on the dispatch. |  | 
| 1139     positive = [] |  | 
| 1140     negative = [] |  | 
| 1141     first_overload = overloads[0] |  | 
| 1142     (param_name, param_type, param_default) = info.arg_infos[position] |  | 
| 1143 |  | 
| 1144     if position < len(first_overload.arguments): |  | 
| 1145       # FIXME: This will not work if the second overload has a more |  | 
| 1146       # precise type than the first.  E.g., |  | 
| 1147       # void foo(Node x); |  | 
| 1148       # void foo(Element x); |  | 
| 1149       type = first_overload.arguments[position].type.id |  | 
| 1150       test = TypeCheck(param_name, type) |  | 
| 1151       pred = lambda op: len(op.arguments) > position and op.arguments[position].
      type.id == type |  | 
| 1152     else: |  | 
| 1153       type = None |  | 
| 1154       test = NullCheck(param_name) |  | 
| 1155       pred = lambda op: position >= len(op.arguments) |  | 
| 1156 |  | 
| 1157     for overload in overloads: |  | 
| 1158       if pred(overload): |  | 
| 1159         positive.append(overload) |  | 
| 1160       else: |  | 
| 1161         negative.append(overload) |  | 
| 1162 |  | 
| 1163     if positive and negative: |  | 
| 1164       (true_code, false_code) = emitter.Emit( |  | 
| 1165           '$(INDENT)if ($COND) {\n' |  | 
| 1166           '$!TRUE' |  | 
| 1167           '$(INDENT)} else {\n' |  | 
| 1168           '$!FALSE' |  | 
| 1169           '$(INDENT)}\n', |  | 
| 1170           COND=test, INDENT=indent) |  | 
| 1171       fallthrough1 = self.GenerateDispatch( |  | 
| 1172           true_code, info, indent + '  ', position + 1, positive) |  | 
| 1173       fallthrough2 = self.GenerateDispatch( |  | 
| 1174           false_code, info, indent + '  ', position, negative) |  | 
| 1175       return fallthrough1 or fallthrough2 |  | 
| 1176 |  | 
| 1177     if negative: |  | 
| 1178       raise Exception('Internal error, must be all positive') |  | 
| 1179 |  | 
| 1180     # All overloads require the same test.  Do we bother? |  | 
| 1181 |  | 
| 1182     # If the test is the same as the method's formal parameter then checked mode |  | 
| 1183     # will have done the test already. (It could be null too but we ignore that |  | 
| 1184     # case since all the overload behave the same and we don't know which types |  | 
| 1185     # in the IDL are not nullable.) |  | 
| 1186     if type == param_type: |  | 
| 1187       return self.GenerateDispatch( |  | 
| 1188           emitter, info, indent, position + 1, positive) |  | 
| 1189 |  | 
| 1190     # Otherwise the overloads have the same type but the type is a substype of |  | 
| 1191     # the method's synthesized formal parameter. e.g we have overloads f(X) and |  | 
| 1192     # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The |  | 
| 1193     # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |  | 
| 1194     # that Y = Z-X, so we need to check for Y. |  | 
| 1195     true_code = emitter.Emit( |  | 
| 1196         '$(INDENT)if ($COND) {\n' |  | 
| 1197         '$!TRUE' |  | 
| 1198         '$(INDENT)}\n', |  | 
| 1199         COND=test, INDENT=indent) |  | 
| 1200     self.GenerateDispatch( |  | 
| 1201         true_code, info, indent + '  ', position + 1, positive) |  | 
| 1202     return True |  | 
| 1203 |  | 
| 1204 # ------------------------------------------------------------------------------ |  | 
| 1205 |  | 
| 1206 class IDLTypeInfo(object): |  | 
| 1207   def __init__(self, idl_type, native_type=None, ref_counted=True, |  | 
| 1208                has_dart_wrapper=True, conversion_template=None, |  | 
| 1209                custom_to_dart=False): |  | 
| 1210     self._idl_type = idl_type |  | 
| 1211     self._native_type = native_type |  | 
| 1212     self._ref_counted = ref_counted |  | 
| 1213     self._has_dart_wrapper = has_dart_wrapper |  | 
| 1214     self._conversion_template = conversion_template |  | 
| 1215     self._custom_to_dart = custom_to_dart |  | 
| 1216 |  | 
| 1217   def idl_type(self): |  | 
| 1218     return self._idl_type |  | 
| 1219 |  | 
| 1220   def native_type(self): |  | 
| 1221     if self._native_type: |  | 
| 1222       return self._native_type |  | 
| 1223     return self._idl_type |  | 
| 1224 |  | 
| 1225   def parameter_adapter_info(self): |  | 
| 1226     native_type = self.native_type() |  | 
| 1227     if self._ref_counted: |  | 
| 1228       native_type = 'RefPtr< %s >' % native_type |  | 
| 1229     if self._has_dart_wrapper: |  | 
| 1230       wrapper_type = 'Dart%s' % self.idl_type() |  | 
| 1231       adapter_type = 'ParameterAdapter<%s, %s>' % (native_type, wrapper_type) |  | 
| 1232       return (adapter_type, wrapper_type) |  | 
| 1233     return ('ParameterAdapter< %s >' % native_type, self._idl_type) |  | 
| 1234 |  | 
| 1235   def parameter_type(self): |  | 
| 1236     return '%s*' % self.native_type() |  | 
| 1237 |  | 
| 1238   def webcore_include(self): |  | 
| 1239     if self._idl_type == 'SVGNumber' or self._idl_type == 'SVGPoint': |  | 
| 1240       return None |  | 
| 1241     if self._idl_type.startswith('SVGPathSeg'): |  | 
| 1242       return self._idl_type.replace('Abs', '').replace('Rel', '') |  | 
| 1243     return self._idl_type |  | 
| 1244 |  | 
| 1245   def receiver(self): |  | 
| 1246     return 'receiver->' |  | 
| 1247 |  | 
| 1248   def conversion_include(self): |  | 
| 1249     return 'Dart%s' % self._idl_type |  | 
| 1250 |  | 
| 1251   def conversion_cast(self, expression): |  | 
| 1252     if self._conversion_template: |  | 
| 1253       return self._conversion_template % expression |  | 
| 1254     return expression |  | 
| 1255 |  | 
| 1256   def custom_to_dart(self): |  | 
| 1257     return self._custom_to_dart |  | 
| 1258 |  | 
| 1259 class PrimitiveIDLTypeInfo(IDLTypeInfo): |  | 
| 1260   def __init__(self, idl_type, native_type=None, ref_counted=False, |  | 
| 1261                conversion_template=None, |  | 
| 1262                webcore_getter_name='getAttribute', |  | 
| 1263                webcore_setter_name='setAttribute'): |  | 
| 1264     super(PrimitiveIDLTypeInfo, self).__init__(idl_type, |  | 
| 1265         native_type=native_type, ref_counted=ref_counted, |  | 
| 1266         conversion_template=conversion_template) |  | 
| 1267     self._webcore_getter_name = webcore_getter_name |  | 
| 1268     self._webcore_setter_name = webcore_setter_name |  | 
| 1269 |  | 
| 1270   def parameter_adapter_info(self): |  | 
| 1271     native_type = self.native_type() |  | 
| 1272     if self._ref_counted: |  | 
| 1273       native_type = 'RefPtr< %s >' % native_type |  | 
| 1274     return ('ParameterAdapter< %s >' % native_type, None) |  | 
| 1275 |  | 
| 1276   def parameter_type(self): |  | 
| 1277     if self.native_type() == 'String': |  | 
| 1278       return 'const String&' |  | 
| 1279     return self.native_type() |  | 
| 1280 |  | 
| 1281   def conversion_include(self): |  | 
| 1282     return None |  | 
| 1283 |  | 
| 1284   def webcore_getter_name(self): |  | 
| 1285     return self._webcore_getter_name |  | 
| 1286 |  | 
| 1287   def webcore_setter_name(self): |  | 
| 1288     return self._webcore_setter_name |  | 
| 1289 |  | 
| 1290 class SVGTearOffIDLTypeInfo(IDLTypeInfo): |  | 
| 1291   def __init__(self, idl_type, native_type='', ref_counted=True): |  | 
| 1292     super(SVGTearOffIDLTypeInfo, self).__init__(idl_type, |  | 
| 1293                                                 native_type=native_type, |  | 
| 1294                                                 ref_counted=ref_counted) |  | 
| 1295 |  | 
| 1296   def native_type(self): |  | 
| 1297     if self._native_type: |  | 
| 1298       return self._native_type |  | 
| 1299     tear_off_type = 'SVGPropertyTearOff' |  | 
| 1300     if self._idl_type.endswith('List'): |  | 
| 1301       tear_off_type = 'SVGListPropertyTearOff' |  | 
| 1302     return '%s<%s>' % (tear_off_type, self._idl_type) |  | 
| 1303 |  | 
| 1304   def receiver(self): |  | 
| 1305     if self._idl_type.endswith('List'): |  | 
| 1306       return 'receiver->' |  | 
| 1307     return 'receiver->propertyReference().' |  | 
| 1308 |  | 
| 1309 |  | 
| 1310 _idl_type_registry = { |  | 
| 1311      # There is GC3Dboolean which is not a bool, but unsigned char for OpenGL co
      mpatibility. |  | 
| 1312     'boolean': PrimitiveIDLTypeInfo('boolean', native_type='bool', |  | 
| 1313                                     conversion_template='static_cast<bool>(%s)', |  | 
| 1314                                     webcore_getter_name='hasAttribute', |  | 
| 1315                                     webcore_setter_name='setBooleanAttribute'), |  | 
| 1316     # Some IDL's unsigned shorts/shorts are mapped to WebCore C++ enums, so we |  | 
| 1317     # use a static_cast<int> here not to provide overloads for all enums. |  | 
| 1318     'short': PrimitiveIDLTypeInfo('short', native_type='int', conversion_templat
      e='static_cast<int>(%s)'), |  | 
| 1319     'unsigned short': PrimitiveIDLTypeInfo('unsigned short', native_type='int', 
      conversion_template='static_cast<int>(%s)'), |  | 
| 1320     'int': PrimitiveIDLTypeInfo('int'), |  | 
| 1321     'unsigned int': PrimitiveIDLTypeInfo('unsigned int', native_type='unsigned')
      , |  | 
| 1322     'long': PrimitiveIDLTypeInfo('long', native_type='int', |  | 
| 1323         webcore_getter_name='getIntegralAttribute', |  | 
| 1324         webcore_setter_name='setIntegralAttribute'), |  | 
| 1325     'unsigned long': PrimitiveIDLTypeInfo('unsigned long', native_type='unsigned
      ', |  | 
| 1326         webcore_getter_name='getUnsignedIntegralAttribute', |  | 
| 1327         webcore_setter_name='setUnsignedIntegralAttribute'), |  | 
| 1328     'long long': PrimitiveIDLTypeInfo('long long'), |  | 
| 1329     'unsigned long long': PrimitiveIDLTypeInfo('unsigned long long'), |  | 
| 1330     'double': PrimitiveIDLTypeInfo('double'), |  | 
| 1331 |  | 
| 1332     'Date': PrimitiveIDLTypeInfo('Date',  native_type='double'), |  | 
| 1333     'DOMString': PrimitiveIDLTypeInfo('DOMString',  native_type='String'), |  | 
| 1334     'DOMTimeStamp': PrimitiveIDLTypeInfo('DOMTimeStamp'), |  | 
| 1335     'object': PrimitiveIDLTypeInfo('object',  native_type='ScriptValue'), |  | 
| 1336     'SerializedScriptValue': PrimitiveIDLTypeInfo('SerializedScriptValue', ref_c
      ounted=True), |  | 
| 1337 |  | 
| 1338     'DOMException': IDLTypeInfo('DOMCoreException'), |  | 
| 1339     'DOMWindow': IDLTypeInfo('DOMWindow', custom_to_dart=True), |  | 
| 1340     'Element': IDLTypeInfo('Element', custom_to_dart=True), |  | 
| 1341     'EventListener': IDLTypeInfo('EventListener', has_dart_wrapper=False), |  | 
| 1342     'EventTarget': IDLTypeInfo('EventTarget', has_dart_wrapper=False), |  | 
| 1343     'HTMLElement': IDLTypeInfo('HTMLElement', custom_to_dart=True), |  | 
| 1344     'MediaQueryListListener': IDLTypeInfo('MediaQueryListListener', has_dart_wra
      pper=False), |  | 
| 1345     'OptionsObject': IDLTypeInfo('OptionsObject', has_dart_wrapper=False), |  | 
| 1346     'SVGElement': IDLTypeInfo('SVGElement', custom_to_dart=True), |  | 
| 1347 |  | 
| 1348     'SVGAngle': SVGTearOffIDLTypeInfo('SVGAngle'), |  | 
| 1349     'SVGLength': SVGTearOffIDLTypeInfo('SVGLength'), |  | 
| 1350     'SVGLengthList': SVGTearOffIDLTypeInfo('SVGLengthList', ref_counted=False), |  | 
| 1351     'SVGMatrix': SVGTearOffIDLTypeInfo('SVGMatrix'), |  | 
| 1352     'SVGNumber': SVGTearOffIDLTypeInfo('SVGNumber', native_type='SVGPropertyTear
      Off<float>'), |  | 
| 1353     'SVGNumberList': SVGTearOffIDLTypeInfo('SVGNumberList', ref_counted=False), |  | 
| 1354     'SVGPathSegList': SVGTearOffIDLTypeInfo('SVGPathSegList', native_type='SVGPa
      thSegListPropertyTearOff', ref_counted=False), |  | 
| 1355     'SVGPoint': SVGTearOffIDLTypeInfo('SVGPoint', native_type='SVGPropertyTearOf
      f<FloatPoint>'), |  | 
| 1356     'SVGPointList': SVGTearOffIDLTypeInfo('SVGPointList', ref_counted=False), |  | 
| 1357     'SVGPreserveAspectRatio': SVGTearOffIDLTypeInfo('SVGPreserveAspectRatio'), |  | 
| 1358     'SVGRect': SVGTearOffIDLTypeInfo('SVGRect', native_type='SVGPropertyTearOff<
      FloatRect>'), |  | 
| 1359     'SVGStringList': SVGTearOffIDLTypeInfo('SVGStringList', native_type='SVGStat
      icListPropertyTearOff<SVGStringList>', ref_counted=False), |  | 
| 1360     'SVGTransform': SVGTearOffIDLTypeInfo('SVGTransform'), |  | 
| 1361     'SVGTransformList': SVGTearOffIDLTypeInfo('SVGTransformList', native_type='S
      VGTransformListPropertyTearOff', ref_counted=False) |  | 
| 1362 } |  | 
| 1363 |  | 
| 1364 _original_idl_types = { |  | 
| 1365 } |  | 
| 1366 |  | 
| 1367 def GetIDLTypeInfo(idl_type): |  | 
| 1368   idl_type_name = _original_idl_types.get(idl_type, idl_type.id) |  | 
| 1369   return GetIDLTypeInfoByName(idl_type_name) |  | 
| 1370 |  | 
| 1371 def GetIDLTypeInfoByName(idl_type_name): |  | 
| 1372   return _idl_type_registry.get(idl_type_name, IDLTypeInfo(idl_type_name)) |  | 
| 1373 |  | 
| 1374 class NativeImplementationSystem(System): |  | 
| 1375 |  | 
| 1376   def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): |  | 
| 1377     super(NativeImplementationSystem, self).__init__( |  | 
| 1378         templates, database, emitters, output_dir) |  | 
| 1379 |  | 
| 1380     self._auxiliary_dir = auxiliary_dir |  | 
| 1381     self._dom_public_files = [] |  | 
| 1382     self._dom_impl_files = [] |  | 
| 1383     self._cpp_header_files = [] |  | 
| 1384     self._cpp_impl_files = [] |  | 
| 1385 |  | 
| 1386   def InterfaceGenerator(self, |  | 
| 1387                          interface, |  | 
| 1388                          common_prefix, |  | 
| 1389                          super_interface_name, |  | 
| 1390                          source_filter): |  | 
| 1391     interface_name = interface.id |  | 
| 1392 |  | 
| 1393     dart_interface_path = self._FilePathForDartInterface(interface_name) |  | 
| 1394     self._dom_public_files.append(dart_interface_path) |  | 
| 1395 |  | 
| 1396     pure_interfaces = set([ |  | 
| 1397         'ElementTimeControl', |  | 
| 1398         'ElementTraversal', |  | 
| 1399         'MediaQueryListListener', |  | 
| 1400         'NodeSelector', |  | 
| 1401         'SVGExternalResourcesRequired', |  | 
| 1402         'SVGFilterPrimitiveStandardAttributes', |  | 
| 1403         'SVGFitToViewBox', |  | 
| 1404         'SVGLangSpace', |  | 
| 1405         'SVGLocatable', |  | 
| 1406         'SVGStylable', |  | 
| 1407         'SVGTests', |  | 
| 1408         'SVGTransformable', |  | 
| 1409         'SVGURIReference', |  | 
| 1410         'SVGViewSpec', |  | 
| 1411         'SVGZoomAndPan']) |  | 
| 1412     if interface_name in pure_interfaces: |  | 
| 1413       return None |  | 
| 1414 |  | 
| 1415     dart_impl_path = self._FilePathForDartImplementation(interface_name) |  | 
| 1416     self._dom_impl_files.append(dart_impl_path) |  | 
| 1417 |  | 
| 1418     cpp_header_path = self._FilePathForCppHeader(interface_name) |  | 
| 1419     self._cpp_header_files.append(cpp_header_path) |  | 
| 1420 |  | 
| 1421     cpp_impl_path = self._FilePathForCppImplementation(interface_name) |  | 
| 1422     self._cpp_impl_files.append(cpp_impl_path) |  | 
| 1423 |  | 
| 1424     return NativeImplementationGenerator(interface, super_interface_name, |  | 
| 1425         self._emitters.FileEmitter(dart_impl_path), |  | 
| 1426         self._emitters.FileEmitter(cpp_header_path), |  | 
| 1427         self._emitters.FileEmitter(cpp_impl_path), |  | 
| 1428         self._BaseDefines(interface), |  | 
| 1429         self._templates) |  | 
| 1430 |  | 
| 1431   def ProcessCallback(self, interface, info): |  | 
| 1432     self._interface = interface |  | 
| 1433 |  | 
| 1434     dart_interface_path = self._FilePathForDartInterface(self._interface.id) |  | 
| 1435     self._dom_public_files.append(dart_interface_path) |  | 
| 1436 |  | 
| 1437     cpp_header_handlers_emitter = emitter.Emitter() |  | 
| 1438     cpp_impl_handlers_emitter = emitter.Emitter() |  | 
| 1439     class_name = 'Dart%s' % self._interface.id |  | 
| 1440     for operation in interface.operations: |  | 
| 1441       if operation.type.id == 'void': |  | 
| 1442         return_type = 'void' |  | 
| 1443         return_prefix = '' |  | 
| 1444       else: |  | 
| 1445         return_type = 'bool' |  | 
| 1446         return_prefix = 'return ' |  | 
| 1447 |  | 
| 1448       parameters = [] |  | 
| 1449       arguments = [] |  | 
| 1450       for argument in operation.arguments: |  | 
| 1451         argument_type_info = GetIDLTypeInfo(argument.type) |  | 
| 1452         parameters.append('%s %s' % (argument_type_info.parameter_type(), |  | 
| 1453                                      argument.id)) |  | 
| 1454         arguments.append(argument.id) |  | 
| 1455 |  | 
| 1456       cpp_header_handlers_emitter.Emit( |  | 
| 1457           '\n' |  | 
| 1458           '    virtual $TYPE handleEvent($PARAMETERS);\n', |  | 
| 1459           TYPE=return_type, PARAMETERS=', '.join(parameters)) |  | 
| 1460 |  | 
| 1461       cpp_impl_handlers_emitter.Emit( |  | 
| 1462           '\n' |  | 
| 1463           '$TYPE $CLASS_NAME::handleEvent($PARAMETERS)\n' |  | 
| 1464           '{\n' |  | 
| 1465           '    $(RETURN_PREFIX)m_callback.handleEvent($ARGUMENTS);\n' |  | 
| 1466           '}\n', |  | 
| 1467           TYPE=return_type, |  | 
| 1468           CLASS_NAME=class_name, |  | 
| 1469           PARAMETERS=', '.join(parameters), |  | 
| 1470           RETURN_PREFIX=return_prefix, |  | 
| 1471           ARGUMENTS=', '.join(arguments)) |  | 
| 1472 |  | 
| 1473     cpp_header_path = self._FilePathForCppHeader(self._interface.id) |  | 
| 1474     cpp_header_emitter = self._emitters.FileEmitter(cpp_header_path) |  | 
| 1475     cpp_header_emitter.Emit( |  | 
| 1476         self._templates.Load('cpp_callback_header.template'), |  | 
| 1477         INTERFACE=self._interface.id, |  | 
| 1478         HANDLERS=cpp_header_handlers_emitter.Fragments()) |  | 
| 1479 |  | 
| 1480     cpp_impl_path = self._FilePathForCppImplementation(self._interface.id) |  | 
| 1481     self._cpp_impl_files.append(cpp_impl_path) |  | 
| 1482     cpp_impl_emitter = self._emitters.FileEmitter(cpp_impl_path) |  | 
| 1483     cpp_impl_emitter.Emit( |  | 
| 1484         self._templates.Load('cpp_callback_implementation.template'), |  | 
| 1485         INTERFACE=self._interface.id, |  | 
| 1486         HANDLERS=cpp_impl_handlers_emitter.Fragments()) |  | 
| 1487 |  | 
| 1488   def GenerateLibraries(self, lib_dir): |  | 
| 1489     auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) |  | 
| 1490 |  | 
| 1491     # Generate dom_public.dart. |  | 
| 1492     self._GenerateLibFile( |  | 
| 1493         'dom_public.darttemplate', |  | 
| 1494         os.path.join(self._output_dir, 'dom_public.dart'), |  | 
| 1495         self._dom_public_files, |  | 
| 1496         AUXILIARY_DIR=auxiliary_dir); |  | 
| 1497 |  | 
| 1498     # Generate dom_impl.dart. |  | 
| 1499     self._GenerateLibFile( |  | 
| 1500         'dom_impl.darttemplate', |  | 
| 1501         os.path.join(self._output_dir, 'dom_impl.dart'), |  | 
| 1502         self._dom_impl_files, |  | 
| 1503         AUXILIARY_DIR=auxiliary_dir); |  | 
| 1504 |  | 
| 1505     # Generate DartDerivedSourcesAll.cpp. |  | 
| 1506     cpp_all_in_one_path = os.path.join(self._output_dir, |  | 
| 1507         'DartDerivedSourcesAll.cpp') |  | 
| 1508 |  | 
| 1509     includes_emitter = emitter.Emitter() |  | 
| 1510     for f in self._cpp_impl_files: |  | 
| 1511         path = os.path.relpath(f, os.path.dirname(cpp_all_in_one_path)) |  | 
| 1512         includes_emitter.Emit('#include "$PATH"\n', PATH=path) |  | 
| 1513 |  | 
| 1514     cpp_all_in_one_emitter = self._emitters.FileEmitter(cpp_all_in_one_path) |  | 
| 1515     cpp_all_in_one_emitter.Emit( |  | 
| 1516         self._templates.Load('cpp_all_in_one.template'), |  | 
| 1517         INCLUDES=includes_emitter.Fragments()) |  | 
| 1518 |  | 
| 1519     # Generate DartResolver.cpp. |  | 
| 1520     cpp_resolver_path = os.path.join(self._output_dir, 'DartResolver.cpp') |  | 
| 1521 |  | 
| 1522     includes_emitter = emitter.Emitter() |  | 
| 1523     resolver_body_emitter = emitter.Emitter() |  | 
| 1524     for f in self._cpp_header_files: |  | 
| 1525       path = os.path.relpath(f, os.path.dirname(cpp_resolver_path)) |  | 
| 1526       includes_emitter.Emit('#include "$PATH"\n', PATH=path) |  | 
| 1527       resolver_body_emitter.Emit( |  | 
| 1528           '    if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argume
      ntCount))\n' |  | 
| 1529           '        return func;\n', |  | 
| 1530           CLASS_NAME=os.path.splitext(os.path.basename(path))[0]) |  | 
| 1531 |  | 
| 1532     cpp_resolver_emitter = self._emitters.FileEmitter(cpp_resolver_path) |  | 
| 1533     cpp_resolver_emitter.Emit( |  | 
| 1534         self._templates.Load('cpp_resolver.template'), |  | 
| 1535         INCLUDES=includes_emitter.Fragments(), |  | 
| 1536         RESOLVER_BODY=resolver_body_emitter.Fragments()) |  | 
| 1537 |  | 
| 1538     # Generate DartDerivedSourcesAll.cpp |  | 
| 1539     cpp_all_in_one_path = os.path.join(self._output_dir, |  | 
| 1540         'DartDerivedSourcesAll.cpp') |  | 
| 1541 |  | 
| 1542     includes_emitter = emitter.Emitter() |  | 
| 1543     for file in self._cpp_impl_files: |  | 
| 1544         path = os.path.relpath(file, os.path.dirname(cpp_all_in_one_path)) |  | 
| 1545         includes_emitter.Emit('#include "$PATH"\n', PATH=path) |  | 
| 1546 |  | 
| 1547     cpp_all_in_one_emitter = self._emitters.FileEmitter(cpp_all_in_one_path) |  | 
| 1548     cpp_all_in_one_emitter.Emit( |  | 
| 1549         self._templates.Load('cpp_all_in_one.template'), |  | 
| 1550         INCLUDES=includes_emitter.Fragments()) |  | 
| 1551 |  | 
| 1552     # Generate DartResolver.cpp |  | 
| 1553     cpp_resolver_path = os.path.join(self._output_dir, 'DartResolver.cpp') |  | 
| 1554 |  | 
| 1555     includes_emitter = emitter.Emitter() |  | 
| 1556     resolver_body_emitter = emitter.Emitter() |  | 
| 1557     for file in self._cpp_header_files: |  | 
| 1558         path = os.path.relpath(file, os.path.dirname(cpp_resolver_path)) |  | 
| 1559         includes_emitter.Emit('#include "$PATH"\n', PATH=path) |  | 
| 1560         resolver_body_emitter.Emit( |  | 
| 1561             '    if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argu
      mentCount))\n' |  | 
| 1562             '        return func;\n', |  | 
| 1563             CLASS_NAME=os.path.splitext(os.path.basename(path))[0]) |  | 
| 1564 |  | 
| 1565     cpp_resolver_emitter = self._emitters.FileEmitter(cpp_resolver_path) |  | 
| 1566     cpp_resolver_emitter.Emit( |  | 
| 1567         self._templates.Load('cpp_resolver.template'), |  | 
| 1568         INCLUDES=includes_emitter.Fragments(), |  | 
| 1569         RESOLVER_BODY=resolver_body_emitter.Fragments()) |  | 
| 1570 |  | 
| 1571   def Finish(self): |  | 
| 1572     pass |  | 
| 1573 |  | 
| 1574   def _FilePathForDartInterface(self, interface_name): |  | 
| 1575     return os.path.join(self._output_dir, 'src', 'interface', |  | 
| 1576                         '%s.dart' % interface_name) |  | 
| 1577 |  | 
| 1578   def _FilePathForDartImplementation(self, interface_name): |  | 
| 1579     return os.path.join(self._output_dir, 'dart', |  | 
| 1580                         '%sImplementation.dart' % interface_name) |  | 
| 1581 |  | 
| 1582   def _FilePathForCppHeader(self, interface_name): |  | 
| 1583     return os.path.join(self._output_dir, 'cpp', 'Dart%s.h' % interface_name) |  | 
| 1584 |  | 
| 1585   def _FilePathForCppImplementation(self, interface_name): |  | 
| 1586     return os.path.join(self._output_dir, 'cpp', 'Dart%s.cpp' % interface_name) |  | 
| 1587 |  | 
| 1588 |  | 
| 1589 class NativeImplementationGenerator(WrappingInterfaceGenerator): |  | 
| 1590   """Generates Dart implementation for one DOM IDL interface.""" |  | 
| 1591 |  | 
| 1592   def __init__(self, interface, super_interface, |  | 
| 1593                dart_impl_emitter, cpp_header_emitter, cpp_impl_emitter, |  | 
| 1594                base_members, templates): |  | 
| 1595     """Generates Dart and C++ code for the given interface. |  | 
| 1596 |  | 
| 1597     Args: |  | 
| 1598 |  | 
| 1599       interface: an IDLInterface instance. It is assumed that all types have |  | 
| 1600           been converted to Dart types (e.g. int, String), unless they are in |  | 
| 1601           the same package as the interface. |  | 
| 1602       super_interface: A string or None, the name of the common interface that |  | 
| 1603          this interface implements, if any. |  | 
| 1604       dart_impl_emitter: an Emitter for the file containing the Dart |  | 
| 1605          implementation class. |  | 
| 1606       cpp_header_emitter: an Emitter for the file containing the C++ header. |  | 
| 1607       cpp_impl_emitter: an Emitter for the file containing the C++ |  | 
| 1608          implementation. |  | 
| 1609       base_members: a set of names of members defined in a base class.  This is |  | 
| 1610           used to avoid static member 'overriding' in the generated Dart code. |  | 
| 1611     """ |  | 
| 1612     self._interface = interface |  | 
| 1613     self._super_interface = super_interface |  | 
| 1614     self._dart_impl_emitter = dart_impl_emitter |  | 
| 1615     self._cpp_header_emitter = cpp_header_emitter |  | 
| 1616     self._cpp_impl_emitter = cpp_impl_emitter |  | 
| 1617     self._base_members = base_members |  | 
| 1618     self._templates = templates |  | 
| 1619     self._current_secondary_parent = None |  | 
| 1620 |  | 
| 1621   def StartInterface(self): |  | 
| 1622     self._class_name = self._ImplClassName(self._interface.id) |  | 
| 1623     self._interface_type_info = GetIDLTypeInfoByName(self._interface.id) |  | 
| 1624     self._members_emitter = emitter.Emitter() |  | 
| 1625     self._cpp_declarations_emitter = emitter.Emitter() |  | 
| 1626     self._cpp_impl_includes = {} |  | 
| 1627     self._cpp_definitions_emitter = emitter.Emitter() |  | 
| 1628     self._cpp_resolver_emitter = emitter.Emitter() |  | 
| 1629 |  | 
| 1630     # Generate constructor. |  | 
| 1631     # FIXME: add proper support for non-custom constructors. |  | 
| 1632     if ('CustomConstructor' in self._interface.ext_attrs or |  | 
| 1633         'V8CustomConstructor' in self._interface.ext_attrs or |  | 
| 1634         self._interface.id in ['FileReader', 'WebKitCSSMatrix', 'XSLTProcessor']
      ): |  | 
| 1635       self._cpp_resolver_emitter.Emit( |  | 
| 1636           '    if (name == "$(INTERFACE_NAME)_constructor_Callback")\n' |  | 
| 1637           '        return Dart$(INTERFACE_NAME)Internal::constructorCallback;\n'
      , |  | 
| 1638           INTERFACE_NAME=self._interface.id) |  | 
| 1639       self._cpp_declarations_emitter.Emit( |  | 
| 1640           '\n' |  | 
| 1641           'void constructorCallback(Dart_NativeArguments);\n') |  | 
| 1642 |  | 
| 1643   def _ImplClassName(self, interface_name): |  | 
| 1644     return interface_name + 'Implementation' |  | 
| 1645 |  | 
| 1646   def FinishInterface(self): |  | 
| 1647     base = self._BaseClassName(self._interface) |  | 
| 1648     self._dart_impl_emitter.Emit( |  | 
| 1649         self._templates.Load('dart_implementation.darttemplate'), |  | 
| 1650         CLASS=self._class_name, BASE=base, INTERFACE=self._interface.id, |  | 
| 1651         MEMBERS=self._members_emitter.Fragments()) |  | 
| 1652 |  | 
| 1653     self._GenerateCppHeader() |  | 
| 1654 |  | 
| 1655     self._cpp_impl_emitter.Emit( |  | 
| 1656         self._templates.Load('cpp_implementation.template'), |  | 
| 1657         INTERFACE=self._interface.id, |  | 
| 1658         INCLUDES=''.join(['#include "%s.h"\n' % |  | 
| 1659           k for k in self._cpp_impl_includes.keys()]), |  | 
| 1660         CALLBACKS=self._cpp_definitions_emitter.Fragments(), |  | 
| 1661         RESOLVER=self._cpp_resolver_emitter.Fragments()) |  | 
| 1662 |  | 
| 1663   def _GenerateCppHeader(self): |  | 
| 1664     webcore_include = self._interface_type_info.webcore_include() |  | 
| 1665     if webcore_include: |  | 
| 1666       webcore_include = '#include "%s.h"\n' % webcore_include |  | 
| 1667     else: |  | 
| 1668       webcore_include = '' |  | 
| 1669 |  | 
| 1670     if ('CustomToJS' in self._interface.ext_attrs or |  | 
| 1671         'CustomToJSObject' in self._interface.ext_attrs or |  | 
| 1672         'PureInterface' in self._interface.ext_attrs or |  | 
| 1673         'CPPPureInterface' in self._interface.ext_attrs or |  | 
| 1674         self._interface_type_info.custom_to_dart()): |  | 
| 1675       to_dart_value_template = ( |  | 
| 1676           'Dart_Handle toDartValue($(WEBCORE_CLASS_NAME)* value);\n') |  | 
| 1677     else: |  | 
| 1678       to_dart_value_template = ( |  | 
| 1679           'inline Dart_Handle toDartValue($(WEBCORE_CLASS_NAME)* value)\n' |  | 
| 1680           '{\n' |  | 
| 1681           '    return DartDOMWrapper::toDart<Dart$(INTERFACE)>(value);\n' |  | 
| 1682           '}\n') |  | 
| 1683     to_dart_value_emitter = emitter.Emitter() |  | 
| 1684     to_dart_value_emitter.Emit( |  | 
| 1685         to_dart_value_template, |  | 
| 1686         INTERFACE=self._interface.id, |  | 
| 1687         WEBCORE_CLASS_NAME=self._interface_type_info.native_type()) |  | 
| 1688 |  | 
| 1689     self._cpp_header_emitter.Emit( |  | 
| 1690         self._templates.Load('cpp_header.template'), |  | 
| 1691         INTERFACE=self._interface.id, |  | 
| 1692         WEBCORE_INCLUDE=webcore_include, |  | 
| 1693         ADDITIONAL_INCLUDES='', |  | 
| 1694         WEBCORE_CLASS_NAME=self._interface_type_info.native_type(), |  | 
| 1695         TO_DART_VALUE=to_dart_value_emitter.Fragments(), |  | 
| 1696         DECLARATIONS=self._cpp_declarations_emitter.Fragments()) |  | 
| 1697 |  | 
| 1698   def AddAttribute(self, getter, setter): |  | 
| 1699     # FIXME: Dartium does not support attribute event listeners. However, JS |  | 
| 1700     # implementation falls back to them when addEventListener is not available. |  | 
| 1701     # Make sure addEventListener is available in all EventTargets and remove |  | 
| 1702     # this check. |  | 
| 1703     if (getter or setter).type.id == 'EventListener': |  | 
| 1704       return |  | 
| 1705 |  | 
| 1706     # FIXME: support 'ImplementedBy'. |  | 
| 1707     if 'ImplementedBy' in (getter or setter).ext_attrs: |  | 
| 1708       return |  | 
| 1709 |  | 
| 1710     # FIXME: these should go away. |  | 
| 1711     classes_with_unsupported_custom_getters = [ |  | 
| 1712         'Clipboard', 'Console', 'Coordinates', 'DeviceMotionEvent', |  | 
| 1713         'DeviceOrientationEvent', 'FileReader', 'JavaScriptCallFrame', |  | 
| 1714         'HTMLInputElement', 'HTMLOptionsCollection', 'HTMLOutputElement', |  | 
| 1715         'ScriptProfileNode', 'WebKitAnimation'] |  | 
| 1716     if (self._interface.id in classes_with_unsupported_custom_getters and |  | 
| 1717         getter and set(['Custom', 'CustomGetter']) & set(getter.ext_attrs)): |  | 
| 1718       return |  | 
| 1719 |  | 
| 1720     if getter: |  | 
| 1721       self._AddGetter(getter) |  | 
| 1722     if setter: |  | 
| 1723       self._AddSetter(setter) |  | 
| 1724 |  | 
| 1725   def _AddGetter(self, attr): |  | 
| 1726     dart_declaration = '%s get %s()' % (attr.type.id, attr.id) |  | 
| 1727     is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs |  | 
| 1728     cpp_callback_name = self._GenerateNativeBinding(attr.id, 1, |  | 
| 1729         dart_declaration, 'Getter', is_custom) |  | 
| 1730     if is_custom: |  | 
| 1731       return |  | 
| 1732 |  | 
| 1733     arguments = [] |  | 
| 1734     if 'Reflect' in attr.ext_attrs: |  | 
| 1735       webcore_function_name = GetIDLTypeInfo(attr.type).webcore_getter_name() |  | 
| 1736       if 'URL' in attr.ext_attrs: |  | 
| 1737         if 'NonEmpty' in attr.ext_attrs: |  | 
| 1738           webcore_function_name = 'getNonEmptyURLAttribute' |  | 
| 1739         else: |  | 
| 1740           webcore_function_name = 'getURLAttribute' |  | 
| 1741       arguments.append(self._GenerateWebCoreReflectionAttributeName(attr)) |  | 
| 1742     else: |  | 
| 1743       if attr.id == 'operator': |  | 
| 1744         webcore_function_name = '_operator' |  | 
| 1745       elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString': |  | 
| 1746         webcore_function_name = 'svgTarget' |  | 
| 1747       else: |  | 
| 1748         webcore_function_name = re.sub(r'^(HTML|URL|JS|XML|XSLT|\w)', |  | 
| 1749                                        lambda s: s.group(1).lower(), |  | 
| 1750                                        attr.id) |  | 
| 1751         webcore_function_name = re.sub(r'^(create|exclusive)', |  | 
| 1752                                        lambda s: 'is' + s.group(1).capitalize(), |  | 
| 1753                                        webcore_function_name) |  | 
| 1754       if attr.type.id.startswith('SVGAnimated'): |  | 
| 1755         webcore_function_name += 'Animated' |  | 
| 1756 |  | 
| 1757     self._GenerateNativeCallback(cpp_callback_name, attr, '', |  | 
| 1758         webcore_function_name, arguments, idl_return_type=attr.type, |  | 
| 1759         raises_dart_exceptions=attr.get_raises, |  | 
| 1760         raises_dom_exceptions=attr.get_raises) |  | 
| 1761 |  | 
| 1762   def _AddSetter(self, attr): |  | 
| 1763     dart_declaration = 'void set %s(%s)' % (attr.id, attr.type.id) |  | 
| 1764     is_custom = set(['Custom', 'CustomSetter', 'V8CustomSetter']) & set(attr.ext
      _attrs) |  | 
| 1765     cpp_callback_name = self._GenerateNativeBinding(attr.id, 2, |  | 
| 1766         dart_declaration, 'Setter', is_custom) |  | 
| 1767     if is_custom: |  | 
| 1768       return |  | 
| 1769 |  | 
| 1770     arguments = [] |  | 
| 1771     if 'Reflect' in attr.ext_attrs: |  | 
| 1772       webcore_function_name = GetIDLTypeInfo(attr.type).webcore_setter_name() |  | 
| 1773       arguments.append(self._GenerateWebCoreReflectionAttributeName(attr)) |  | 
| 1774     else: |  | 
| 1775       webcore_function_name = re.sub(r'^(xml(?=[A-Z])|\w)', |  | 
| 1776                                      lambda s: s.group(1).upper(), |  | 
| 1777                                      attr.id) |  | 
| 1778       webcore_function_name = 'set%s' % webcore_function_name |  | 
| 1779       if attr.type.id.startswith('SVGAnimated'): |  | 
| 1780         webcore_function_name += 'Animated' |  | 
| 1781 |  | 
| 1782     arguments.append(attr.id) |  | 
| 1783     parameter_definitions_emitter = emitter.Emitter() |  | 
| 1784     self._GenerateParameterAdapter(parameter_definitions_emitter, attr, 0) |  | 
| 1785     parameter_definitions = parameter_definitions_emitter.Fragments() |  | 
| 1786     self._GenerateNativeCallback(cpp_callback_name, attr, parameter_definitions, |  | 
| 1787         webcore_function_name, arguments, idl_return_type=None, |  | 
| 1788         raises_dart_exceptions=True, |  | 
| 1789         raises_dom_exceptions=attr.set_raises) |  | 
| 1790 |  | 
| 1791   def _HasNativeIndexGetter(self, interface): |  | 
| 1792     return ('CustomIndexedGetter' in interface.ext_attrs or |  | 
| 1793             'NumericIndexedGetter' in interface.ext_attrs) |  | 
| 1794 |  | 
| 1795   def _EmitNativeIndexGetter(self, interface, element_type): |  | 
| 1796     dart_declaration = '%s operator[](int index)' % element_type |  | 
| 1797     self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, |  | 
| 1798         'Callback', True) |  | 
| 1799 |  | 
| 1800   def _EmitNativeIndexSetter(self, interface, element_type): |  | 
| 1801     dart_declaration = 'void operator[]=(int index, %s value)' % element_type |  | 
| 1802     self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, |  | 
| 1803         'Callback', True) |  | 
| 1804 |  | 
| 1805   def AddOperation(self, info): |  | 
| 1806     """ |  | 
| 1807     Arguments: |  | 
| 1808       info: An OperationInfo object. |  | 
| 1809     """ |  | 
| 1810 |  | 
| 1811     if 'Custom' in info.overloads[0].ext_attrs: |  | 
| 1812       parameters = info.ParametersImplementationDeclaration() |  | 
| 1813       dart_declaration = '%s %s(%s)' % (info.type_name, info.name, parameters) |  | 
| 1814       argument_count = 1 + len(info.arg_infos) |  | 
| 1815       self._GenerateNativeBinding(info.name, argument_count, dart_declaration, |  | 
| 1816           'Callback', True) |  | 
| 1817       return |  | 
| 1818 |  | 
| 1819     body = self._members_emitter.Emit( |  | 
| 1820         '\n' |  | 
| 1821         '  $TYPE $NAME($PARAMETERS) {\n' |  | 
| 1822         '$!BODY' |  | 
| 1823         '  }\n', |  | 
| 1824         TYPE=info.type_name, |  | 
| 1825         NAME=info.name, |  | 
| 1826         PARAMETERS=info.ParametersImplementationDeclaration()) |  | 
| 1827 |  | 
| 1828     # Process in order of ascending number of arguments to ensure missing |  | 
| 1829     # optional arguments are processed early. |  | 
| 1830     overloads = sorted(info.overloads, |  | 
| 1831                        key=lambda overload: len(overload.arguments)) |  | 
| 1832     self._native_version = 0 |  | 
| 1833     fallthrough = self.GenerateDispatch(body, info, '    ', 0, overloads) |  | 
| 1834     if fallthrough: |  | 
| 1835       body.Emit('    throw "Incorrect number or type of arguments";\n'); |  | 
| 1836 |  | 
| 1837   def GenerateSingleOperation(self,  dispatch_emitter, info, indent, operation): |  | 
| 1838     """Generates a call to a single operation. |  | 
| 1839 |  | 
| 1840     Arguments: |  | 
| 1841       dispatch_emitter: an dispatch_emitter for the body of a block of code. |  | 
| 1842       info: the compound information about the operation and its overloads. |  | 
| 1843       indent: an indentation string for generated code. |  | 
| 1844       operation: the IDLOperation to call. |  | 
| 1845     """ |  | 
| 1846 |  | 
| 1847     # FIXME: support ImplementedBy callbacks. |  | 
| 1848     if 'ImplementedBy' in operation.ext_attrs: |  | 
| 1849       return |  | 
| 1850 |  | 
| 1851     for op in self._interface.operations: |  | 
| 1852       if op.id != operation.id or len(op.arguments) <= len(operation.arguments): |  | 
| 1853         continue |  | 
| 1854       next_argument = op.arguments[len(operation.arguments)] |  | 
| 1855       if next_argument.is_optional and 'Callback' in next_argument.ext_attrs: |  | 
| 1856         # FIXME: '[Optional, Callback]' arguments could be non-optional in |  | 
| 1857         # webcore. We need to fix overloads handling to generate native |  | 
| 1858         # callbacks properly. |  | 
| 1859         return |  | 
| 1860 |  | 
| 1861     self._native_version += 1 |  | 
| 1862     native_name = info.name |  | 
| 1863     if self._native_version > 1: |  | 
| 1864       native_name = '%s_%s' % (native_name, self._native_version) |  | 
| 1865     argument_list = ', '.join([info.arg_infos[i][0] |  | 
| 1866                                for (i, arg) in enumerate(operation.arguments)]) |  | 
| 1867 |  | 
| 1868     # Generate dispatcher. |  | 
| 1869     if info.type_name != 'void': |  | 
| 1870       dispatch_emitter.Emit('$(INDENT)return _$NATIVENAME($ARGS);\n', |  | 
| 1871                             INDENT=indent, |  | 
| 1872                             NATIVENAME=native_name, |  | 
| 1873                             ARGS=argument_list) |  | 
| 1874     else: |  | 
| 1875       dispatch_emitter.Emit('$(INDENT)_$NATIVENAME($ARGS);\n' |  | 
| 1876                             '$(INDENT)return;\n', |  | 
| 1877                             INDENT=indent, |  | 
| 1878                             NATIVENAME=native_name, |  | 
| 1879                             ARGS=argument_list) |  | 
| 1880     # Generate binding. |  | 
| 1881     dart_declaration = '%s _%s(%s)' % (info.type_name, native_name, |  | 
| 1882                                        argument_list) |  | 
| 1883     is_custom = 'Custom' in operation.ext_attrs |  | 
| 1884     cpp_callback_name = self._GenerateNativeBinding( |  | 
| 1885         native_name, 1 + len(operation.arguments), dart_declaration, 'Callback', |  | 
| 1886         is_custom) |  | 
| 1887     if is_custom: |  | 
| 1888       return |  | 
| 1889 |  | 
| 1890     # Generate callback. |  | 
| 1891     webcore_function_name = operation.id |  | 
| 1892     if 'ImplementedAs' in operation.ext_attrs: |  | 
| 1893       webcore_function_name = operation.ext_attrs['ImplementedAs'] |  | 
| 1894 |  | 
| 1895     parameter_definitions_emitter = emitter.Emitter() |  | 
| 1896     raises_dart_exceptions = len(operation.arguments) > 0 or operation.raises |  | 
| 1897     arguments = [] |  | 
| 1898 |  | 
| 1899     # Process 'CallWith' argument. |  | 
| 1900     if 'CallWith' in operation.ext_attrs: |  | 
| 1901       call_with = operation.ext_attrs['CallWith'] |  | 
| 1902       if call_with == 'ScriptExecutionContext': |  | 
| 1903         parameter_definitions_emitter.Emit( |  | 
| 1904             '        ScriptExecutionContext* context = DartUtilities::scriptExec
      utionContext();\n' |  | 
| 1905             '        if (!context)\n' |  | 
| 1906             '            return;\n') |  | 
| 1907         arguments.append('context') |  | 
| 1908       elif call_with == 'ScriptArguments|CallStack': |  | 
| 1909         raises_dart_exceptions = True |  | 
| 1910         self._cpp_impl_includes['ScriptArguments'] = 1 |  | 
| 1911         self._cpp_impl_includes['ScriptCallStack'] = 1 |  | 
| 1912         self._cpp_impl_includes['V8Proxy'] = 1 |  | 
| 1913         self._cpp_impl_includes['v8'] = 1 |  | 
| 1914         parameter_definitions_emitter.Emit( |  | 
| 1915             '        v8::HandleScope handleScope;\n' |  | 
| 1916             '        v8::Context::Scope scope(V8Proxy::mainWorldContext(DartUtil
      ities::domWindowForCurrentIsolate()->frame()));\n' |  | 
| 1917             '        Dart_Handle customArgument = Dart_GetNativeArgument(args, $
      INDEX);\n' |  | 
| 1918             '        RefPtr<ScriptArguments> scriptArguments(DartUtilities::crea
      teScriptArguments(customArgument, exception));\n' |  | 
| 1919             '        if (!scriptArguments)\n' |  | 
| 1920             '            goto fail;\n' |  | 
| 1921             '        RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::crea
      teScriptCallStack());\n' |  | 
| 1922             '        if (!scriptCallStack->size())\n' |  | 
| 1923             '            return;\n', |  | 
| 1924             INDEX=len(operation.arguments)) |  | 
| 1925         arguments.extend(['scriptArguments', 'scriptCallStack']) |  | 
| 1926 |  | 
| 1927     # Process Dart arguments. |  | 
| 1928     for (i, argument) in enumerate(operation.arguments): |  | 
| 1929       if i == len(operation.arguments) - 1 and self._interface.id == 'Console' a
      nd argument.id == 'arg': |  | 
| 1930         # FIXME: we are skipping last argument here because it was added in |  | 
| 1931         # supplemental dart.idl. Cleanup dart.idl and remove this check. |  | 
| 1932         break |  | 
| 1933       self._GenerateParameterAdapter(parameter_definitions_emitter, argument, i) |  | 
| 1934       arguments.append(argument.id) |  | 
| 1935 |  | 
| 1936     if operation.id in ['addEventListener', 'removeEventListener']: |  | 
| 1937       # addEventListener's and removeEventListener's last argument is marked |  | 
| 1938       # as optional in idl, but is not optional in webcore implementation. |  | 
| 1939       if len(operation.arguments) == 2: |  | 
| 1940         arguments.append('false') |  | 
| 1941 |  | 
| 1942     if self._interface.id == 'CSSStyleDeclaration' and operation.id == 'setPrope
      rty': |  | 
| 1943       # CSSStyleDeclaration.setProperty priority parameter is optional in Dart |  | 
| 1944       # idl, but is not optional in webcore implementation. |  | 
| 1945       if len(operation.arguments) == 2: |  | 
| 1946         arguments.append('String()') |  | 
| 1947 |  | 
| 1948     if 'NeedsUserGestureCheck' in operation.ext_attrs: |  | 
| 1949       arguments.extend('DartUtilities::processingUserGesture') |  | 
| 1950 |  | 
| 1951     parameter_definitions = parameter_definitions_emitter.Fragments() |  | 
| 1952     self._GenerateNativeCallback(cpp_callback_name, operation, |  | 
| 1953         parameter_definitions, webcore_function_name, arguments, |  | 
| 1954         idl_return_type=operation.type, |  | 
| 1955         raises_dart_exceptions=raises_dart_exceptions, |  | 
| 1956         raises_dom_exceptions=operation.raises) |  | 
| 1957 |  | 
| 1958   def _GenerateNativeCallback(self, callback_name, idl_node, |  | 
| 1959       parameter_definitions, function_name, arguments, idl_return_type, |  | 
| 1960       raises_dart_exceptions, raises_dom_exceptions): |  | 
| 1961     receiver = self._interface_type_info.receiver() |  | 
| 1962     if raises_dom_exceptions: |  | 
| 1963       arguments.append('ec') |  | 
| 1964     callback = '%s%s(%s)' % (receiver, function_name, ', '.join(arguments)) |  | 
| 1965 |  | 
| 1966     nested_templates = [] |  | 
| 1967     if idl_return_type and idl_return_type.id != 'void': |  | 
| 1968       return_type_info = GetIDLTypeInfo(idl_return_type) |  | 
| 1969       conversion_cast = return_type_info.conversion_cast('$BODY') |  | 
| 1970       if isinstance(return_type_info, SVGTearOffIDLTypeInfo): |  | 
| 1971         svg_primitive_types = ['SVGAngle', 'SVGLength', 'SVGMatrix', |  | 
| 1972             'SVGNumber', 'SVGPoint', 'SVGRect', 'SVGTransform'] |  | 
| 1973         conversion_cast = '%s::create($BODY)' |  | 
| 1974         if self._interface.id.startswith('SVGAnimated'): |  | 
| 1975           conversion_cast = 'static_cast<%s*>($BODY)' |  | 
| 1976         elif return_type_info.idl_type() == 'SVGStringList': |  | 
| 1977           conversion_cast = '%s::create(receiver, $BODY)' |  | 
| 1978         elif self._interface.id.endswith('List'): |  | 
| 1979           conversion_cast = 'static_cast<%s*>($BODY.get())' |  | 
| 1980         elif return_type_info.idl_type() in svg_primitive_types: |  | 
| 1981           conversion_cast = '%s::create($BODY)' |  | 
| 1982         else: |  | 
| 1983           conversion_cast = 'static_cast<%s*>($BODY)' |  | 
| 1984         conversion_cast = conversion_cast % return_type_info.native_type() |  | 
| 1985       nested_templates.append(conversion_cast) |  | 
| 1986 |  | 
| 1987       if return_type_info.conversion_include(): |  | 
| 1988         self._cpp_impl_includes[return_type_info.conversion_include()] = 1 |  | 
| 1989       if (return_type_info.idl_type() in ['DOMString', 'AtomicString'] and |  | 
| 1990           'TreatReturnedNullStringAs' in idl_node.ext_attrs): |  | 
| 1991         nested_templates.append('$BODY, ConvertDefaultToNull') |  | 
| 1992       nested_templates.append( |  | 
| 1993           '        Dart_Handle returnValue = toDartValue($BODY);\n' |  | 
| 1994           '        if (returnValue)\n' |  | 
| 1995           '            Dart_SetReturnValue(args, returnValue);\n') |  | 
| 1996     else: |  | 
| 1997       nested_templates.append('        $BODY;\n') |  | 
| 1998 |  | 
| 1999     if raises_dom_exceptions: |  | 
| 2000       nested_templates.append( |  | 
| 2001           '        ExceptionCode ec = 0;\n' |  | 
| 2002           '$BODY' |  | 
| 2003           '        if (UNLIKELY(ec)) {\n' |  | 
| 2004           '            exception = DartDOMWrapper::exceptionCodeToDartException(
      ec);\n' |  | 
| 2005           '            goto fail;\n' |  | 
| 2006           '        }\n') |  | 
| 2007 |  | 
| 2008     nested_templates.append( |  | 
| 2009         '    {\n' |  | 
| 2010         '        $WEBCORE_CLASS_NAME* receiver = DartDOMWrapper::receiver< $WEBC
      ORE_CLASS_NAME >(args);\n' |  | 
| 2011         '$PARAMETER_DEFINITIONS' |  | 
| 2012         '\n' |  | 
| 2013         '$BODY' |  | 
| 2014         '        return;\n' |  | 
| 2015         '    }\n') |  | 
| 2016 |  | 
| 2017     if raises_dart_exceptions: |  | 
| 2018       nested_templates.append( |  | 
| 2019           '    Dart_Handle exception;\n' |  | 
| 2020           '$BODY' |  | 
| 2021           '\n' |  | 
| 2022           'fail:\n' |  | 
| 2023           '    Dart_ThrowException(exception);\n' |  | 
| 2024           '    ASSERT_NOT_REACHED();\n') |  | 
| 2025 |  | 
| 2026     nested_templates.append( |  | 
| 2027         '\n' |  | 
| 2028         'static void $CALLBACK_NAME(Dart_NativeArguments args)\n' |  | 
| 2029         '{\n' |  | 
| 2030         '    DartApiScope dartApiScope;\n' |  | 
| 2031         '$BODY' |  | 
| 2032         '}\n') |  | 
| 2033 |  | 
| 2034     template_parameters = { |  | 
| 2035         'CALLBACK_NAME': callback_name, |  | 
| 2036         'WEBCORE_CLASS_NAME': self._interface_type_info.native_type(), |  | 
| 2037         'PARAMETER_DEFINITIONS': parameter_definitions, |  | 
| 2038     } |  | 
| 2039     for template in nested_templates: |  | 
| 2040       template_parameters['BODY'] = callback |  | 
| 2041       callback_emitter = emitter.Emitter() |  | 
| 2042       callback_emitter.Emit(template, **template_parameters) |  | 
| 2043       callback = ''.join(callback_emitter.Fragments()) |  | 
| 2044 |  | 
| 2045     self._cpp_definitions_emitter.Emit(callback) |  | 
| 2046 |  | 
| 2047   def _GenerateParameterAdapter(self, emitter, idl_argument, index): |  | 
| 2048     type_info = GetIDLTypeInfo(idl_argument.type) |  | 
| 2049     (adapter_type, include_name) = type_info.parameter_adapter_info() |  | 
| 2050     if include_name: |  | 
| 2051       self._cpp_impl_includes[include_name] = 1 |  | 
| 2052     emitter.Emit( |  | 
| 2053         '\n' |  | 
| 2054         '        const $ADAPTER_TYPE $NAME(Dart_GetNativeArgument(args, $INDEX))
      ;\n' |  | 
| 2055         '        if (!$NAME.conversionSuccessful()) {\n' |  | 
| 2056         '            exception = $NAME.exception();\n' |  | 
| 2057         '            goto fail;\n' |  | 
| 2058         '        }\n', |  | 
| 2059         ADAPTER_TYPE=adapter_type, |  | 
| 2060         NAME=idl_argument.id, |  | 
| 2061         INDEX=index + 1) |  | 
| 2062 |  | 
| 2063   def _GenerateNativeBinding(self, idl_name, argument_count, dart_declaration, |  | 
| 2064       native_suffix, is_custom): |  | 
| 2065     native_binding = '%s_%s_%s' % (self._interface.id, idl_name, native_suffix) |  | 
| 2066     self._members_emitter.Emit( |  | 
| 2067         '\n' |  | 
| 2068         '  $DART_DECLARATION native "$NATIVE_BINDING";\n', |  | 
| 2069         DART_DECLARATION=dart_declaration, NATIVE_BINDING=native_binding) |  | 
| 2070 |  | 
| 2071     cpp_callback_name = '%s%s' % (idl_name, native_suffix) |  | 
| 2072     self._cpp_resolver_emitter.Emit( |  | 
| 2073         '    if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n' |  | 
| 2074         '        return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n', |  | 
| 2075         ARGC=argument_count, |  | 
| 2076         NATIVE_BINDING=native_binding, |  | 
| 2077         INTERFACE_NAME=self._interface.id, |  | 
| 2078         CPP_CALLBACK_NAME=cpp_callback_name) |  | 
| 2079 |  | 
| 2080     if is_custom: |  | 
| 2081       self._cpp_declarations_emitter.Emit( |  | 
| 2082           '\n' |  | 
| 2083           'void $CPP_CALLBACK_NAME(Dart_NativeArguments);\n', |  | 
| 2084           CPP_CALLBACK_NAME=cpp_callback_name) |  | 
| 2085 |  | 
| 2086     return cpp_callback_name |  | 
| 2087 |  | 
| 2088   def _GenerateWebCoreReflectionAttributeName(self, attr): |  | 
| 2089     namespace = 'HTMLNames' |  | 
| 2090     svg_exceptions = ['class', 'id', 'onabort', 'onclick', 'onerror', 'onload', |  | 
| 2091                       'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', |  | 
| 2092                       'onmouseup', 'onresize', 'onscroll', 'onunload'] |  | 
| 2093     if self._interface.id.startswith('SVG') and not attr.id in svg_exceptions: |  | 
| 2094       namespace = 'SVGNames' |  | 
| 2095     self._cpp_impl_includes[namespace] = 1 |  | 
| 2096 |  | 
| 2097     attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower() |  | 
| 2098     return 'WebCore::%s::%sAttr' % (namespace, attribute_name) |  | 
| OLD | NEW | 
|---|