| 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 |