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 |