| 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 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 from generator import AnalyzeOperation, ConstantOutputOrder, \ | 10 from generator import AnalyzeOperation, ConstantOutputOrder, \ |
| 10 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \ | 11 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \ |
| 11 IsPureInterface, TypeOrNothing | 12 IsPureInterface, TypeOrNothing |
| 12 | 13 |
| 13 # Types that are accessible cross-frame in a limited fashion. | 14 # Types that are accessible cross-frame in a limited fashion. |
| 14 # In these cases, the base type (e.g., WindowBase) provides restricted access | 15 # In these cases, the base type (e.g., WindowBase) provides restricted access |
| 15 # while the subtype (e.g., Window) provides full access to the | 16 # while the subtype (e.g., Window) provides full access to the |
| 16 # corresponding objects if there are from the same frame. | 17 # corresponding objects if there are from the same frame. |
| 17 _secure_base_types = { | 18 _secure_base_types = { |
| 18 'Window': 'WindowBase', | 19 'Window': 'WindowBase', |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 # FIXME: item should be renamed to operator[], not removed. | 170 # FIXME: item should be renamed to operator[], not removed. |
| 170 self.EmitOperation(info, '_item') | 171 self.EmitOperation(info, '_item') |
| 171 return | 172 return |
| 172 | 173 |
| 173 if declare_only: | 174 if declare_only: |
| 174 self.DeclareOperation(info, | 175 self.DeclareOperation(info, |
| 175 self.SecureOutputType(info.type_name), method_name) | 176 self.SecureOutputType(info.type_name), method_name) |
| 176 else: | 177 else: |
| 177 self.EmitOperation(info, method_name) | 178 self.EmitOperation(info, method_name) |
| 178 | 179 |
| 179 def _GenerateDispatcherBody(self, | 180 def _GenerateOverloadDispatcher(self, |
| 180 operations, | 181 signatures, |
| 182 is_void, |
| 181 parameter_names, | 183 parameter_names, |
| 182 declaration, | 184 declaration, |
| 183 generate_call, | 185 generate_call, |
| 184 is_optional, | 186 is_optional, |
| 185 can_omit_type_check=lambda type, pos: False): | 187 can_omit_type_check=lambda type, pos: False): |
| 186 | 188 |
| 187 body_emitter = self._members_emitter.Emit( | 189 body_emitter = self._members_emitter.Emit( |
| 188 '\n' | 190 '\n' |
| 189 ' $DECLARATION {\n' | 191 ' $DECLARATION {\n' |
| 190 '$!BODY' | 192 '$!BODY' |
| 191 ' }\n', | 193 ' }\n', |
| 192 DECLARATION=declaration) | 194 DECLARATION=declaration) |
| 193 | 195 |
| 194 version = [0] | 196 version = [0] |
| 195 def GenerateCall(operation, argument_count, checks): | 197 def GenerateCall(signature_index, argument_count, checks): |
| 196 if checks: | 198 if checks: |
| 197 (stmts_emitter, call_emitter) = body_emitter.Emit( | 199 (stmts_emitter, call_emitter) = body_emitter.Emit( |
| 198 ' if ($CHECKS) {\n$!STMTS$!CALL }\n', | 200 ' if ($CHECKS) {\n$!STMTS$!CALL }\n', |
| 199 INDENT=' ', | 201 INDENT=' ', |
| 200 CHECKS=' && '.join(checks)) | 202 CHECKS=' && '.join(checks)) |
| 201 else: | 203 else: |
| 202 (stmts_emitter, call_emitter) = body_emitter.Emit( | 204 (stmts_emitter, call_emitter) = body_emitter.Emit( |
| 203 '$!STMTS$!CALL', | 205 '$!STMTS$!CALL', |
| 204 INDENT=' '); | 206 INDENT=' '); |
| 205 | 207 |
| 206 if operation.type.id == 'void': | 208 if is_void: |
| 207 call_emitter = call_emitter.Emit('$(INDENT)$!CALL;\n$(INDENT)return;\n') | 209 call_emitter = call_emitter.Emit('$(INDENT)$!CALL;\n$(INDENT)return;\n') |
| 208 else: | 210 else: |
| 209 call_emitter = call_emitter.Emit('$(INDENT)return $!CALL;\n') | 211 call_emitter = call_emitter.Emit('$(INDENT)return $!CALL;\n') |
| 210 | 212 |
| 211 version[0] += 1 | 213 version[0] += 1 |
| 212 generate_call( | 214 generate_call(stmts_emitter, call_emitter, |
| 213 stmts_emitter, call_emitter, version[0], operation, argument_count) | 215 version[0], signature_index, argument_count) |
| 214 | 216 |
| 215 def GenerateChecksAndCall(operation, argument_count): | 217 def GenerateChecksAndCall(signature_index, argument_count): |
| 216 checks = [] | 218 checks = [] |
| 217 for i in range(0, argument_count): | 219 for i in range(0, argument_count): |
| 218 argument = operation.arguments[i] | 220 argument = signatures[signature_index][i] |
| 219 parameter_name = parameter_names[i] | 221 parameter_name = parameter_names[i] |
| 220 test_type = self._DartType(argument.type.id) | 222 test_type = self._DartType(argument.type.id) |
| 221 if test_type in ['dynamic', 'Object']: | 223 if test_type in ['dynamic', 'Object']: |
| 222 checks.append('?%s' % parameter_name) | 224 checks.append('?%s' % parameter_name) |
| 223 elif not can_omit_type_check(test_type, i): | 225 elif not can_omit_type_check(test_type, i): |
| 224 checks.append('(%s is %s || %s == null)' % ( | 226 checks.append('(%s is %s || %s == null)' % ( |
| 225 parameter_name, test_type, parameter_name)) | 227 parameter_name, test_type, parameter_name)) |
| 226 # There can be multiple presence checks. We need them all since a later | 228 # There can be multiple presence checks. We need them all since a later |
| 227 # optional argument could have been passed by name, leaving 'holes'. | 229 # optional argument could have been passed by name, leaving 'holes'. |
| 228 checks.extend(['!?%s' % name for name in parameter_names[argument_count:]]
) | 230 checks.extend(['!?%s' % name for name in parameter_names[argument_count:]]
) |
| 229 | 231 |
| 230 GenerateCall(operation, argument_count, checks) | 232 GenerateCall(signature_index, argument_count, checks) |
| 231 | 233 |
| 232 # TODO: Optimize the dispatch to avoid repeated checks. | 234 # TODO: Optimize the dispatch to avoid repeated checks. |
| 233 if len(operations) > 1: | 235 if len(signatures) > 1: |
| 234 for operation in operations: | 236 for signature_index, signature in enumerate(signatures): |
| 235 for position, argument in enumerate(operation.arguments): | 237 for argument_position, argument in enumerate(signature): |
| 236 if is_optional(operation, argument): | 238 if is_optional(signature_index, argument): |
| 237 GenerateChecksAndCall(operation, position) | 239 GenerateChecksAndCall(signature_index, argument_position) |
| 238 GenerateChecksAndCall(operation, len(operation.arguments)) | 240 GenerateChecksAndCall(signature_index, len(signature)) |
| 239 body_emitter.Emit( | 241 body_emitter.Emit( |
| 240 ' throw new ArgumentError("Incorrect number or type of arguments");
' | 242 ' throw new ArgumentError("Incorrect number or type of arguments");
' |
| 241 '\n'); | 243 '\n'); |
| 242 else: | 244 else: |
| 243 operation = operations[0] | 245 signature = signatures[0] |
| 244 argument_count = len(operation.arguments) | 246 argument_count = len(signature) |
| 245 for position, argument in list(enumerate(operation.arguments))[::-1]: | 247 for argument_position, argument in list(enumerate(signature))[::-1]: |
| 246 if is_optional(operation, argument): | 248 if is_optional(0, argument): |
| 247 check = '?%s' % parameter_names[position] | 249 check = '?%s' % parameter_names[argument_position] |
| 248 # argument_count instead of position + 1 is used here to cover one | 250 # argument_count instead of argument_position + 1 is used here to cove
r one |
| 249 # complicated case with the effectively optional argument in the middl
e. | 251 # complicated case with the effectively optional argument in the middl
e. |
| 250 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z) | 252 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z) |
| 251 # (as of now it's modelled after HTMLMediaElement.webkitAddKey). | 253 # (as of now it's modelled after HTMLMediaElement.webkitAddKey). |
| 252 # y is optional in WebCore, while z is not. | 254 # y is optional in WebCore, while z is not. |
| 253 # In this case, if y was actually passed, we'd like to emit foo(x, y,
z) invocation, | 255 # In this case, if y was actually passed, we'd like to emit foo(x, y,
z) invocation, |
| 254 # not foo(x, y). | 256 # not foo(x, y). |
| 255 GenerateCall(operation, argument_count, [check]) | 257 GenerateCall(0, argument_count, [check]) |
| 256 argument_count = position | 258 argument_count = argument_position |
| 257 GenerateCall(operation, argument_count, []) | 259 GenerateCall(0, argument_count, []) |
| 260 |
| 261 def _GenerateDispatcherBody(self, |
| 262 operations, |
| 263 parameter_names, |
| 264 declaration, |
| 265 generate_call, |
| 266 is_optional, |
| 267 can_omit_type_check=lambda type, pos: False): |
| 268 |
| 269 def GenerateCall( |
| 270 stmts_emitter, call_emitter, version, signature_index, argument_count): |
| 271 generate_call( |
| 272 stmts_emitter, call_emitter, |
| 273 version, operations[signature_index], argument_count) |
| 274 |
| 275 def IsOptional(signature_index, argument): |
| 276 return is_optional(operations[signature_index], argument) |
| 277 |
| 278 self._GenerateOverloadDispatcher( |
| 279 [operation.arguments for operation in operations], |
| 280 operations[0].type.id == 'void', |
| 281 parameter_names, |
| 282 declaration, |
| 283 GenerateCall, |
| 284 IsOptional, |
| 285 can_omit_type_check) |
| 258 | 286 |
| 259 def AdditionalImplementedInterfaces(self): | 287 def AdditionalImplementedInterfaces(self): |
| 260 # TODO: Include all implemented interfaces, including other Lists. | 288 # TODO: Include all implemented interfaces, including other Lists. |
| 261 implements = [] | 289 implements = [] |
| 262 if self._interface_type_info.is_typed_array(): | 290 if self._interface_type_info.is_typed_array(): |
| 263 element_type = self._interface_type_info.list_item_type() | 291 element_type = self._interface_type_info.list_item_type() |
| 264 implements.append('List<%s>' % self._DartType(element_type)) | 292 implements.append('List<%s>' % self._DartType(element_type)) |
| 265 if self._interface_type_info.list_item_type(): | 293 if self._interface_type_info.list_item_type(): |
| 266 item_type_info = self._type_registry.TypeInfo( | 294 item_type_info = self._type_registry.TypeInfo( |
| 267 self._interface_type_info.list_item_type()) | 295 self._interface_type_info.list_item_type()) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 '\n' | 327 '\n' |
| 300 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, ' | 328 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, ' |
| 301 '[int byteOffset, int length]) => \n' | 329 '[int byteOffset, int length]) => \n' |
| 302 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n'
, | 330 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n'
, |
| 303 CTOR=self._interface.id, | 331 CTOR=self._interface.id, |
| 304 TYPE=self._DartType(typed_array_type), | 332 TYPE=self._DartType(typed_array_type), |
| 305 FACTORY=factory_name) | 333 FACTORY=factory_name) |
| 306 | 334 |
| 307 def _AddConstructor(self, | 335 def _AddConstructor(self, |
| 308 constructor_info, factory_name, factory_constructor_name): | 336 constructor_info, factory_name, factory_constructor_name): |
| 337 if self.GenerateCustomFactory(constructor_info): |
| 338 return |
| 339 |
| 309 self._members_emitter.Emit('\n @DocsEditable'); | 340 self._members_emitter.Emit('\n @DocsEditable'); |
| 310 | 341 |
| 311 if not factory_constructor_name: | 342 if not factory_constructor_name: |
| 312 factory_constructor_name = '_create' | 343 factory_constructor_name = '_create' |
| 313 factory_parameters = constructor_info.ParametersAsArgumentList() | 344 factory_parameters = constructor_info.ParametersAsArgumentList() |
| 314 has_factory_provider = True | 345 has_factory_provider = True |
| 315 else: | 346 else: |
| 316 factory_parameters = ', '.join(constructor_info.factory_parameters) | 347 factory_parameters = ', '.join(constructor_info.factory_parameters) |
| 317 has_factory_provider = False | 348 has_factory_provider = False |
| 318 | 349 |
| 319 has_optional = any(param_info.is_optional | 350 if constructor_info.pure_dart_constructor: |
| 320 for param_info in constructor_info.param_infos) | 351 # TODO(antonm): use common dispatcher generation for this case as well. |
| 352 has_optional = any(param_info.is_optional |
| 353 for param_info in constructor_info.param_infos) |
| 321 | 354 |
| 322 if not has_optional: | 355 if not has_optional: |
| 323 self._members_emitter.Emit( | 356 self._members_emitter.Emit( |
| 324 '\n' | |
| 325 ' factory $CTOR($PARAMS) => ' | |
| 326 '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n', | |
| 327 CTOR=constructor_info._ConstructorFullName(self._DartType), | |
| 328 PARAMS=constructor_info.ParametersDeclaration(self._DartType), | |
| 329 FACTORY=factory_name, | |
| 330 CTOR_FACTORY_NAME=factory_constructor_name, | |
| 331 FACTORY_PARAMS=factory_parameters) | |
| 332 else: | |
| 333 if has_factory_provider: | |
| 334 dispatcher_emitter = self._members_emitter.Emit( | |
| 335 '\n' | 357 '\n' |
| 336 ' factory $CTOR($PARAMS) {\n' | 358 ' factory $CTOR($PARAMS) => ' |
| 337 '$!DISPATCHER' | 359 '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n', |
| 338 ' return $FACTORY._create($FACTORY_PARAMS);\n' | |
| 339 ' }\n', | |
| 340 CTOR=constructor_info._ConstructorFullName(self._DartType), | 360 CTOR=constructor_info._ConstructorFullName(self._DartType), |
| 341 PARAMS=constructor_info.ParametersDeclaration(self._DartType), | 361 PARAMS=constructor_info.ParametersDeclaration(self._DartType), |
| 342 FACTORY=factory_name, | 362 FACTORY=factory_name, |
| 343 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList()) | 363 CTOR_FACTORY_NAME=factory_constructor_name, |
| 364 FACTORY_PARAMS=factory_parameters) |
| 365 else: |
| 366 if has_factory_provider: |
| 367 dispatcher_emitter = self._members_emitter.Emit( |
| 368 '\n' |
| 369 ' factory $CTOR($PARAMS) {\n' |
| 370 '$!DISPATCHER' |
| 371 ' return $FACTORY._create($FACTORY_PARAMS);\n' |
| 372 ' }\n', |
| 373 CTOR=constructor_info._ConstructorFullName(self._DartType), |
| 374 PARAMS=constructor_info.ParametersDeclaration(self._DartType), |
| 375 FACTORY=factory_name, |
| 376 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList()) |
| 344 | 377 |
| 345 for index, param_info in enumerate(constructor_info.param_infos): | 378 for index, param_info in enumerate(constructor_info.param_infos): |
| 346 if param_info.is_optional: | 379 if param_info.is_optional: |
| 347 dispatcher_emitter.Emit( | 380 dispatcher_emitter.Emit( |
| 348 ' if (!?$OPT_PARAM_NAME) {\n' | 381 ' if (!?$OPT_PARAM_NAME) {\n' |
| 349 ' return $FACTORY._create($FACTORY_PARAMS);\n' | 382 ' return $FACTORY._create($FACTORY_PARAMS);\n' |
| 350 ' }\n', | 383 ' }\n', |
| 351 OPT_PARAM_NAME=param_info.name, | 384 OPT_PARAM_NAME=param_info.name, |
| 385 FACTORY=factory_name, |
| 386 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index)) |
| 387 else: |
| 388 inits = self._members_emitter.Emit( |
| 389 '\n' |
| 390 ' factory $CONSTRUCTOR($PARAMS) {\n' |
| 391 ' var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n' |
| 392 '$!INITS' |
| 393 ' return e;\n' |
| 394 ' }\n', |
| 395 CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType), |
| 352 FACTORY=factory_name, | 396 FACTORY=factory_name, |
| 353 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index)) | 397 CTOR_FACTORY_NAME=factory_constructor_name, |
| 354 else: | 398 PARAMS=constructor_info.ParametersDeclaration(self._DartType), |
| 355 inits = self._members_emitter.Emit( | 399 FACTORY_PARAMS=factory_parameters) |
| 356 '\n' | 400 |
| 357 ' factory $CONSTRUCTOR($PARAMS) {\n' | 401 for index, param_info in enumerate(constructor_info.param_infos): |
| 358 ' var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n' | 402 if param_info.is_optional: |
| 359 '$!INITS' | 403 inits.Emit(' if ($E != null) e.$E = $E;\n', E=param_info.name) |
| 360 ' return e;\n' | 404 else: |
| 361 ' }\n', | 405 def GenerateCall( |
| 362 CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType), | 406 stmts_emitter, call_emitter, |
| 407 version, signature_index, argument_count): |
| 408 name = emitter.Format('_create_$VERSION', VERSION=version) |
| 409 call_emitter.Emit('$FACTORY.$NAME($FACTORY_PARAMS)', |
| 363 FACTORY=factory_name, | 410 FACTORY=factory_name, |
| 364 CTOR_FACTORY_NAME=factory_constructor_name, | 411 NAME=name, |
| 365 PARAMS=constructor_info.ParametersDeclaration(self._DartType), | 412 FACTORY_PARAMS= \ |
| 366 FACTORY_PARAMS=factory_parameters) | 413 constructor_info.ParametersAsArgumentList(argument_count)) |
| 414 self.EmitStaticFactoryOverload( |
| 415 constructor_info, name, |
| 416 constructor_info.idl_args[signature_index][:argument_count]) |
| 367 | 417 |
| 368 for index, param_info in enumerate(constructor_info.param_infos): | 418 def IsOptional(signature_index, argument): |
| 369 if param_info.is_optional: | 419 return self.IsConstructorArgumentOptional(argument) |
| 370 inits.Emit(' if ($E != null) e.$E = $E;\n', E=param_info.name) | |
| 371 | 420 |
| 372 if not constructor_info.pure_dart_constructor: | 421 self._GenerateOverloadDispatcher( |
| 373 self.EmitStaticFactory(constructor_info) | 422 constructor_info.idl_args, |
| 423 False, |
| 424 [info.name for info in constructor_info.param_infos], |
| 425 emitter.Format('factory $CTOR($PARAMS)', |
| 426 CTOR=constructor_info._ConstructorFullName(self._DartType), |
| 427 PARAMS=constructor_info.ParametersDeclaration(self._DartType)), |
| 428 GenerateCall, |
| 429 IsOptional) |
| 374 | 430 |
| 375 def EmitHelpers(self, base_class): | 431 def EmitHelpers(self, base_class): |
| 376 pass | 432 pass |
| 377 | 433 |
| 378 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): | 434 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): |
| 379 """ Declares an attribute but does not include the code to invoke it. | 435 """ Declares an attribute but does not include the code to invoke it. |
| 380 """ | 436 """ |
| 381 if read_only: | 437 if read_only: |
| 382 template = '\n $TYPE get $NAME;\n' | 438 template = '\n $TYPE get $NAME;\n' |
| 383 else: | 439 else: |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 walk(interface.parents) | 529 walk(interface.parents) |
| 474 else: | 530 else: |
| 475 walk(interface.parents[1:]) | 531 walk(interface.parents[1:]) |
| 476 return result | 532 return result |
| 477 | 533 |
| 478 def _DartType(self, type_name): | 534 def _DartType(self, type_name): |
| 479 return self._type_registry.DartType(type_name) | 535 return self._type_registry.DartType(type_name) |
| 480 | 536 |
| 481 def _IsPrivate(self, name): | 537 def _IsPrivate(self, name): |
| 482 return name.startswith('_') | 538 return name.startswith('_') |
| OLD | NEW |