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

Side by Side Diff: lib/dom/scripts/systemhtml.py

Issue 10879025: Revert "Conversions between Dart code and DOM code." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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
« no previous file with comments | « lib/dom/scripts/generator.py ('k') | lib/dom/templates/html/dart2js/html_dart2js.darttemplate » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 provides shared functionality for the system to generate 6 """This module provides shared functionality for the system to generate
7 Dart:html APIs from the IDL database.""" 7 Dart:html APIs from the IDL database."""
8 8
9 import emitter 9 import emitter
10 10
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 if self._interface.id != 'NodeList': 891 if self._interface.id != 'NodeList':
892 template_file = 'immutable_list_mixin.darttemplate' 892 template_file = 'immutable_list_mixin.darttemplate'
893 template = self._system._templates.Load(template_file) 893 template = self._system._templates.Load(template_file)
894 self._members_emitter.Emit(template, E=self._DartType(element_type)) 894 self._members_emitter.Emit(template, E=self._DartType(element_type))
895 895
896 def AddAttribute(self, attribute, html_name, read_only): 896 def AddAttribute(self, attribute, html_name, read_only):
897 if self._HasCustomImplementation(attribute.id): 897 if self._HasCustomImplementation(attribute.id):
898 return 898 return
899 899
900 if attribute.id != html_name: 900 if attribute.id != html_name:
901 self._AddAttributeUsingProperties(attribute, html_name, read_only) 901 self._AddRenamingGetter(attribute, html_name)
902 if not read_only:
903 self._AddRenamingSetter(attribute, html_name)
902 return 904 return
903 905
904 # If the attribute is shadowing, we can't generate a shadowing 906 # If the attribute is shadowing, we can't generate a shadowing
905 # field (Issue 1633). 907 # field (Issue 1633).
906 # TODO(sra): _FindShadowedAttribute does not take into account the html 908 (super_attribute, super_attribute_interface) = self._FindShadowedAttribute(a ttribute, _merged_html_interfaces)
907 # renaming. we should be looking for another attribute that has the same
908 # html_name. Two attributes with the same IDL name might not match if one
909 # is renamed.
910 (super_attribute, super_attribute_interface) = self._FindShadowedAttribute(
911 attribute, _merged_html_interfaces)
912 if super_attribute: 909 if super_attribute:
913 if read_only: 910 if read_only:
914 if attribute.type.id == super_attribute.type.id: 911 if attribute.type.id == super_attribute.type.id:
915 # Compatible attribute, use the superclass property. This works 912 # Compatible attribute, use the superclass property. This works
916 # because JavaScript will do its own dynamic dispatch. 913 # because JavaScript will do its own dynamic dispatch.
917 self._members_emitter.Emit( 914 self._members_emitter.Emit(
918 '\n' 915 '\n'
919 ' // Use implementation from $SUPER.\n' 916 ' // Use implementation from $SUPER.\n'
920 ' // final $TYPE $NAME;\n', 917 ' // final $TYPE $NAME;\n',
921 SUPER=super_attribute_interface, 918 SUPER=super_attribute_interface,
922 NAME=DartDomNameOfAttribute(attribute), 919 NAME=DartDomNameOfAttribute(attribute),
923 TYPE=self._NarrowOutputType(attribute.type.id)) 920 TYPE=self._NarrowOutputType(attribute.type.id))
924 return 921 return
922
925 self._members_emitter.Emit('\n // Shadowing definition.') 923 self._members_emitter.Emit('\n // Shadowing definition.')
926 self._AddAttributeUsingProperties(attribute, html_name, read_only) 924 self._AddAttributeUsingProperties(attribute, read_only)
927 return
928
929 # If the type has a conversion we need a getter or setter to contain the
930 # conversion code.
931 if (self._OutputConversion(attribute.type.id, attribute.id) or
932 self._InputConversion(attribute.type.id, attribute.id)):
933 self._AddAttributeUsingProperties(attribute, html_name, read_only)
934 return 925 return
935 926
936 output_type = self._NarrowOutputType(attribute.type.id) 927 output_type = self._NarrowOutputType(attribute.type.id)
937 input_type = self._NarrowInputType(attribute.type.id) 928 input_type = self._NarrowInputType(attribute.type.id)
938 if not read_only: 929 if not read_only:
939 self._members_emitter.Emit( 930 self._members_emitter.Emit(
940 '\n $TYPE $NAME;\n', 931 '\n $TYPE $NAME;\n',
941 NAME=DartDomNameOfAttribute(attribute), 932 NAME=DartDomNameOfAttribute(attribute),
942 TYPE=output_type) 933 TYPE=output_type)
943 else: 934 else:
944 self._members_emitter.Emit( 935 self._members_emitter.Emit(
945 '\n final $TYPE $NAME;\n', 936 '\n final $TYPE $NAME;\n',
946 NAME=DartDomNameOfAttribute(attribute), 937 NAME=DartDomNameOfAttribute(attribute),
947 TYPE=output_type) 938 TYPE=output_type)
948 939
949 def _AddAttributeUsingProperties(self, attribute, html_name, read_only): 940 def _AddAttributeUsingProperties(self, attribute, read_only):
950 self._AddRenamingGetter(attribute, html_name) 941 self._AddGetter(attribute)
951 if not read_only: 942 if not read_only:
952 self._AddRenamingSetter(attribute, html_name) 943 self._AddSetter(attribute)
944
945 def _AddGetter(self, attr):
946 self._AddRenamingGetter(attr, DartDomNameOfAttribute(attr))
947
948 def _AddSetter(self, attr):
949 self._AddRenamingSetter(attr, DartDomNameOfAttribute(attr))
953 950
954 def _AddRenamingGetter(self, attr, html_name): 951 def _AddRenamingGetter(self, attr, html_name):
955 conversion = self._OutputConversion(attr.type.id, attr.id)
956 if conversion:
957 return self._AddConvertingGetter(attr, html_name, conversion)
958 return_type = self._NarrowOutputType(attr.type.id) 952 return_type = self._NarrowOutputType(attr.type.id)
959 self._members_emitter.Emit( 953 self._members_emitter.Emit(
960 '\n $TYPE get $HTML_NAME() native "return this.$NAME;";\n', 954 '\n $TYPE get $(HTML_NAME)() native "return this.$NAME;";\n',
961 HTML_NAME=html_name, 955 HTML_NAME=html_name,
962 NAME=attr.id, 956 NAME=attr.id,
963 TYPE=return_type) 957 TYPE=return_type)
964 958
965 def _AddRenamingSetter(self, attr, html_name): 959 def _AddRenamingSetter(self, attr, html_name):
966 conversion = self._InputConversion(attr.type.id, attr.id)
967 if conversion:
968 return self._AddConvertingSetter(attr, html_name, conversion)
969 self._members_emitter.Emit( 960 self._members_emitter.Emit(
970 '\n void set $HTML_NAME($TYPE value)' 961 '\n void set $HTML_NAME($TYPE value)'
971 ' native "this.$NAME = value;";\n', 962 ' native "this.$NAME = value;";\n',
972 HTML_NAME=html_name, 963 HTML_NAME=html_name,
973 NAME=attr.id, 964 NAME=attr.id,
974 TYPE=self._NarrowInputType(attr.type.id)) 965 TYPE=self._NarrowInputType(attr.type.id))
975 966
976 def _AddConvertingGetter(self, attr, html_name, conversion):
977 self._members_emitter.Emit(
978 '\n $RETURN_TYPE get $HTML_NAME() => $CONVERT(this._$(HTML_NAME));'
979 '\n $NATIVE_TYPE get _$HTML_NAME() native "return this.$NAME;";'
980 '\n',
981 CONVERT=conversion.function_name,
982 HTML_NAME=html_name,
983 NAME=attr.id,
984 RETURN_TYPE=conversion.output_type,
985 NATIVE_TYPE=conversion.input_type)
986
987 def _AddConvertingSetter(self, attr, html_name, conversion):
988 self._members_emitter.Emit(
989 '\n void set $HTML_NAME($INPUT_TYPE value) {'
990 ' this._$HTML_NAME = $CONVERT(value); }'
991 '\n void set _$HTML_NAME(/*$NATIVE_TYPE*/ value)'
992 ' native "this.$NAME = value;";'
993 '\n',
994 CONVERT=conversion.function_name,
995 HTML_NAME=html_name,
996 NAME=attr.id,
997 INPUT_TYPE=conversion.input_type,
998 NATIVE_TYPE=conversion.output_type)
999
1000
1001 def AddOperation(self, info, html_name): 967 def AddOperation(self, info, html_name):
1002 """ 968 """
1003 Arguments: 969 Arguments:
1004 info: An OperationInfo object. 970 info: An OperationInfo object.
1005 """ 971 """
1006 if self._HasCustomImplementation(info.name): 972 if self._HasCustomImplementation(info.name):
1007 return 973 return
1008 974
1009 # FIXME: support static operations. 975 # FIXME: support static operations.
1010 if info.IsStatic(): 976 if info.IsStatic():
1011 return 977 return
1012 978
1013 # Any conversions needed?
1014 if any(self._OperationRequiresConversions(op) for op in info.overloads):
1015 self._AddOperationWithConversions(info, html_name)
1016 else:
1017 self._AddDirectNativeOperation(info, html_name)
1018
1019 def _AddDirectNativeOperation(self, info, html_name):
1020 # Do we need a native body? 979 # Do we need a native body?
1021 if html_name != info.declared_name: 980 if html_name != info.declared_name:
1022 return_type = self._NarrowOutputType(info.type_name) 981 return_type = self._NarrowOutputType(info.type_name)
1023 982
1024 operation_emitter = self._members_emitter.Emit('$!SCOPE', 983 operation_emitter = self._members_emitter.Emit('$!SCOPE',
1025 TYPE=return_type, 984 TYPE=return_type,
1026 HTML_NAME=html_name, 985 HTML_NAME=html_name,
1027 NAME=info.declared_name, 986 NAME=info.declared_name,
1028 PARAMS=info.ParametersImplementationDeclaration( 987 PARAMS=info.ParametersImplementationDeclaration(
1029 lambda type_name: self._NarrowInputType(type_name))) 988 lambda type_name: self._NarrowInputType(type_name)))
1030 989
1031 operation_emitter.Emit( 990 operation_emitter.Emit(
1032 '\n' 991 '\n'
1033 #' // @native("$NAME")\n;'
1034 ' $TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n') 992 ' $TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n')
1035 else: 993 else:
1036 self._members_emitter.Emit( 994 self._members_emitter.Emit(
1037 '\n' 995 '\n'
1038 ' $TYPE $NAME($PARAMS) native;\n', 996 ' $TYPE $NAME($PARAMS) native;\n',
1039 TYPE=self._NarrowOutputType(info.type_name), 997 TYPE=self._NarrowOutputType(info.type_name),
1040 NAME=info.name, 998 NAME=info.name,
1041 PARAMS=info.ParametersImplementationDeclaration( 999 PARAMS=info.ParametersImplementationDeclaration(
1042 lambda type_name: self._NarrowInputType(type_name))) 1000 lambda type_name: self._NarrowInputType(type_name)))
1043 1001
1044 def _AddOperationWithConversions(self, info, html_name):
1045 # Assert all operations have same return type.
1046 assert len(set([op.type.id for op in info.operations])) == 1
1047 info = info.CopyAndWidenDefaultParameters()
1048 output_conversion = self._OutputConversion(info.type_name,
1049 info.declared_name)
1050 if output_conversion:
1051 return_type = output_conversion.output_type
1052 native_return_type = output_conversion.input_type
1053 else:
1054 return_type = self._NarrowInputType(info.type_name)
1055 native_return_type = return_type
1056
1057 def InputType(type_name):
1058 conversion = self._InputConversion(type_name, info.declared_name)
1059 if conversion:
1060 return conversion.input_type
1061 else:
1062 return self._NarrowInputType(type_name)
1063
1064 body = self._members_emitter.Emit(
1065 '\n'
1066 ' $TYPE $(HTML_NAME)($PARAMS) {\n'
1067 '$!BODY'
1068 ' }\n',
1069 TYPE=return_type,
1070 HTML_NAME=html_name,
1071 PARAMS=info.ParametersImplementationDeclaration(InputType, '_default'))
1072
1073 argument_names = [param_info.name for param_info in info.param_infos]
1074 argument_types = [InputType(param_info.dart_type)
1075 for param_info in info.param_infos]
1076 operations = info.operations
1077
1078 method_version = [0]
1079 temp_version = [0]
1080
1081 def GenerateCall(operation, argument_count, checks):
1082 if checks:
1083 (stmts_emitter, call_emitter) = body.Emit(
1084 ' if ($CHECKS) {\n$!STMTS$!CALL }\n',
1085 INDENT=' ',
1086 CHECKS=' &&\n '.join(checks))
1087 else:
1088 (stmts_emitter, call_emitter) = body.Emit('$!A$!B', INDENT=' ');
1089
1090 method_version[0] += 1
1091 target = '_%s_%d' % (html_name, method_version[0])
1092 arguments = []
1093 target_parameters = []
1094 for position, arg in enumerate(operation.arguments[:argument_count]):
1095 conversion = self._InputConversion(arg.type.id, operation.id)
1096 param_name = operation.arguments[position].id
1097 if conversion:
1098 temp_version[0] += 1
1099 temp_name = '%s_%s' % (param_name, temp_version[0])
1100 temp_type = conversion.output_type
1101 stmts_emitter.Emit(
1102 '$(INDENT)$TYPE $NAME = $CONVERT($ARG);\n',
1103 TYPE=TypeOrVar(temp_type),
1104 NAME=temp_name,
1105 CONVERT=conversion.function_name,
1106 ARG=argument_names[position])
1107 arguments.append(temp_name)
1108 param_type = temp_type
1109 verified_type = temp_type # verified by assignment in checked mode.
1110 else:
1111 arguments.append(argument_names[position])
1112 param_type = self._NarrowInputType(DartType(arg.type.id))
1113 # Verified by argument checking on entry to the dispatcher.
1114 verified_type = InputType(info.param_infos[position].dart_type)
1115
1116 # The native method does not need an argument type if we know the type.
1117 # But we do need the native methods to have correct function types, so
1118 # be conservative.
1119 if param_type == verified_type:
1120 if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']:
1121 param_type = 'Dynamic'
1122 target_parameters.append(
1123 '%s%s' % (TypeOrNothing(param_type), param_name))
1124
1125 argument_list = ', '.join(arguments)
1126 # TODO(sra): If the native method has zero type checks, we can 'inline' is
1127 # and call it directly with a JS-expression.
1128 call = '%s(%s)' % (target, argument_list)
1129
1130 if output_conversion:
1131 call = '%s(%s)' % (output_conversion.function_name, call)
1132
1133 if operation.type.id == 'void':
1134 call_emitter.Emit('$(INDENT)$CALL;\n$(INDENT)return;\n',
1135 CALL=call)
1136 else:
1137 call_emitter.Emit('$(INDENT)return $CALL;\n', CALL=call)
1138
1139 self._members_emitter.Emit(
1140 ' $TYPE$TARGET($PARAMS) native "$NATIVE";\n',
1141 TYPE=TypeOrNothing(native_return_type),
1142 TARGET=target,
1143 PARAMS=', '.join(target_parameters),
1144 NATIVE=info.declared_name)
1145
1146 def GenerateChecksAndCall(operation, argument_count):
1147 checks = ['_default == %s' % name for name in argument_names]
1148 for i in range(0, argument_count):
1149 argument = operation.arguments[i]
1150 argument_name = argument_names[i]
1151 test_type = self._DartType(argument.type.id)
1152 if test_type in ['Dynamic', 'Object']:
1153 checks[i] = '_default != %s' % argument_name
1154 else:
1155 checks[i] = '(%s is %s || %s == null)' % (
1156 argument_name, self._DartType(argument.type.id), argument_name)
1157 GenerateCall(operation, argument_count, checks)
1158
1159 # TODO: Optimize the dispatch to avoid repeated checks.
1160 if len(operations) > 1:
1161 for operation in operations:
1162 for position, argument in enumerate(operation.arguments):
1163 if self._IsOptional(operation, argument):
1164 GenerateChecksAndCall(operation, position)
1165 GenerateChecksAndCall(operation, len(operation.arguments))
1166 body.Emit(' throw "Incorrect number or type of arguments";\n');
1167 else:
1168 operation = operations[0]
1169 argument_count = len(operation.arguments)
1170 for position, argument in list(enumerate(operation.arguments))[::-1]:
1171 if self._IsOptional(operation, argument):
1172 check = '_default != %s' % argument_names[position]
1173 GenerateCall(operation, position + 1, [check])
1174 argument_count = position
1175 GenerateCall(operation, argument_count, [])
1176
1177
1178 def _IsOptional(self, operation, argument):
1179 return IsOptional(argument)
1180
1181
1182 def _OperationRequiresConversions(self, operation):
1183 return (self._OperationRequiresOutputConversion(operation) or
1184 self._OperationRequiresInputConversions(operation))
1185
1186 def _OperationRequiresOutputConversion(self, operation):
1187 return self._OutputConversion(operation.type.id, operation.id)
1188
1189 def _OperationRequiresInputConversions(self, operation):
1190 return any(self._InputConversion(arg.type.id, operation.id)
1191 for arg in operation.arguments)
1192
1193 def _OutputConversion(self, idl_type, member):
1194 return FindConversion(idl_type, 'get', self._interface.id, member)
1195
1196 def _InputConversion(self, idl_type, member):
1197 return FindConversion(idl_type, 'set', self._interface.id, member)
1198
1199 def _HasCustomImplementation(self, member_name): 1002 def _HasCustomImplementation(self, member_name):
1200 member_name = '%s.%s' % (self._html_interface_name, member_name) 1003 member_name = '%s.%s' % (self._html_interface_name, member_name)
1201 return member_name in _js_custom_members 1004 return member_name in _js_custom_members
1202 1005
1203 def _HasJavaScriptIndexingBehaviour(self): 1006 def _HasJavaScriptIndexingBehaviour(self):
1204 """Returns True if the native object has an indexer and length property.""" 1007 """Returns True if the native object has an indexer and length property."""
1205 (element_type, requires_indexer) = ListImplementationInfo( 1008 (element_type, requires_indexer) = ListImplementationInfo(
1206 self._interface, self._database) 1009 self._interface, self._database)
1207 if element_type and requires_indexer: return True 1010 if element_type and requires_indexer: return True
1208 return False 1011 return False
1209 1012
1210 # ------------------------------------------------------------------------------ 1013 # ------------------------------------------------------------------------------
1211 1014
1212 class HtmlDart2JSSystem(System): 1015 class HtmlDart2JSSystem(System):
1213 1016
1214 def __init__(self, options): 1017 def __init__(self, options):
1215 super(HtmlDart2JSSystem, self).__init__(options) 1018 super(HtmlDart2JSSystem, self).__init__(options)
1216 1019
1217 def ImplementationGenerator(self, interface): 1020 def ImplementationGenerator(self, interface):
1218 return HtmlDart2JSClassGenerator(self, interface) 1021 return HtmlDart2JSClassGenerator(self, interface)
1219 1022
1220 def GenerateLibraries(self, dart_files): 1023 def GenerateLibraries(self, dart_files):
1221 self._GenerateLibFile( 1024 self._GenerateLibFile(
1222 'html_dart2js.darttemplate', 1025 'html_dart2js.darttemplate',
1223 os.path.join(self._output_dir, 'html_dart2js.dart'), 1026 os.path.join(self._output_dir, 'html_dart2js.dart'),
1224 dart_files) 1027 dart_files)
1225 1028
1226 def Finish(self): 1029 def Finish(self):
1227 pass 1030 pass
OLDNEW
« no previous file with comments | « lib/dom/scripts/generator.py ('k') | lib/dom/templates/html/dart2js/html_dart2js.darttemplate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698