Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1142)

Side by Side Diff: client/dom/scripts/dartgenerator.py

Issue 9424035: Move native system generator to a separate script. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698