| 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 import emitter |
| 10 from generator import AnalyzeOperation, ConstantOutputOrder, \ | 10 from generator import AnalyzeOperation, ConstantOutputOrder, \ |
| 11 DartDomNameOfAttribute, FindMatchingAttribute, IsPureInterface, \ | 11 DartDomNameOfAttribute, FindMatchingAttribute, IsPureInterface, \ |
| 12 TypeOrNothing, ConvertToFuture, GetCallbackInfo | 12 TypeOrNothing, ConvertToFuture, GetCallbackInfo |
| 13 from copy import deepcopy | 13 from copy import deepcopy |
| 14 from htmlrenamer import convert_to_future_members, custom_html_constructors, \ | 14 from htmlrenamer import convert_to_future_members, custom_html_constructors, \ |
| 15 keep_overloaded_members, overloaded_and_renamed, private_html_members, \ | 15 keep_overloaded_members, overloaded_and_renamed, private_html_members, \ |
| 16 renamed_html_members, renamed_overloads, removed_html_members | 16 renamed_html_members, renamed_overloads, removed_html_members |
| 17 from generator import TypeOrVar |
| 17 import logging | 18 import logging |
| 18 import monitored | 19 import monitored |
| 19 import sys | 20 import sys |
| 20 | 21 |
| 21 _logger = logging.getLogger('htmldartgenerator') | 22 _logger = logging.getLogger('htmldartgenerator') |
| 22 | 23 |
| 23 # Types that are accessible cross-frame in a limited fashion. | 24 # Types that are accessible cross-frame in a limited fashion. |
| 24 # In these cases, the base type (e.g., WindowBase) provides restricted access | 25 # In these cases, the base type (e.g., WindowBase) provides restricted access |
| 25 # while the subtype (e.g., Window) provides full access to the | 26 # while the subtype (e.g., Window) provides full access to the |
| 26 # corresponding objects if there are from the same frame. | 27 # corresponding objects if there are from the same frame. |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 member and not include invocation code. | 318 member and not include invocation code. |
| 318 """ | 319 """ |
| 319 # FIXME: When we pass in operations[0] below, we're assuming all | 320 # FIXME: When we pass in operations[0] below, we're assuming all |
| 320 # overloaded operations have the same security attributes. This | 321 # overloaded operations have the same security attributes. This |
| 321 # is currently true, but we should consider filtering earlier or | 322 # is currently true, but we should consider filtering earlier or |
| 322 # merging the relevant data into info itself. | 323 # merging the relevant data into info itself. |
| 323 method_name = self._renamer.RenameMember(self._interface.id, | 324 method_name = self._renamer.RenameMember(self._interface.id, |
| 324 info.operations[0], | 325 info.operations[0], |
| 325 info.name, | 326 info.name, |
| 326 'call:') | 327 'call:') |
| 328 |
| 327 if not method_name: | 329 if not method_name: |
| 328 if info.name == 'item': | 330 if info.name == 'item': |
| 329 # FIXME: item should be renamed to operator[], not removed. | 331 # FIXME: item should be renamed to operator[], not removed. |
| 330 self.EmitOperation(info, '_item') | 332 self.EmitOperation(info, '_item') |
| 331 return | 333 return |
| 332 | 334 |
| 333 if declare_only: | 335 if declare_only: |
| 334 self.DeclareOperation(info, | 336 self.DeclareOperation(info, |
| 335 self.SecureOutputType(info.type_name), method_name) | 337 self.SecureOutputType(info.type_name), method_name) |
| 336 else: | 338 else: |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 factory_name to call (calls an autogenerated FactoryProvider | 521 factory_name to call (calls an autogenerated FactoryProvider |
| 520 if unspecified) | 522 if unspecified) |
| 521 """ | 523 """ |
| 522 for constructor_info in constructors: | 524 for constructor_info in constructors: |
| 523 self._AddConstructor( | 525 self._AddConstructor( |
| 524 constructor_info, factory_name, factory_constructor_name) | 526 constructor_info, factory_name, factory_constructor_name) |
| 525 | 527 |
| 526 def _AddConstructor(self, | 528 def _AddConstructor(self, |
| 527 constructor_info, factory_name, factory_constructor_name): | 529 constructor_info, factory_name, factory_constructor_name): |
| 528 # Hack to ignore the Image constructor used by JavaScript. | 530 # Hack to ignore the Image constructor used by JavaScript. |
| 529 if (self._interface.id == 'HTMLImageElement' | 531 if ((self._interface.id == 'HTMLImageElement' or self._interface.id == 'Blob
') |
| 530 and not constructor_info.pure_dart_constructor): | 532 and not constructor_info.pure_dart_constructor): |
| 531 return | 533 return |
| 532 | 534 |
| 533 if self.GenerateCustomFactory(constructor_info): | 535 if self.GenerateCustomFactory(constructor_info): |
| 534 return | 536 return |
| 535 | 537 |
| 536 metadata = self._metadata.GetFormattedMetadata( | 538 metadata = self._metadata.GetFormattedMetadata( |
| 537 self._library_name, self._interface, self._interface.id, ' ') | 539 self._library_name, self._interface, self._interface.id, ' ') |
| 538 | 540 |
| 539 if not factory_constructor_name: | 541 if not factory_constructor_name: |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 custom_factory_ctr = self._interface.id in _custom_factories | 590 custom_factory_ctr = self._interface.id in _custom_factories |
| 589 constructor_full_name = constructor_info._ConstructorFullName( | 591 constructor_full_name = constructor_info._ConstructorFullName( |
| 590 self._DartType) | 592 self._DartType) |
| 591 | 593 |
| 592 def GenerateCall( | 594 def GenerateCall( |
| 593 stmts_emitter, call_emitter, | 595 stmts_emitter, call_emitter, |
| 594 version, signature_index, argument_count): | 596 version, signature_index, argument_count): |
| 595 name = emitter.Format('_create_$VERSION', VERSION=version) | 597 name = emitter.Format('_create_$VERSION', VERSION=version) |
| 596 arguments = constructor_info.idl_args[signature_index][:argument_count] | 598 arguments = constructor_info.idl_args[signature_index][:argument_count] |
| 597 args = None | 599 args = None |
| 600 call_template = '' |
| 598 if self._dart_use_blink: | 601 if self._dart_use_blink: |
| 599 type_ids = [p.type.id for p in arguments] | 602 type_ids = [p.type.id for p in arguments] |
| 600 base_name, rs = \ | 603 base_name, rs = \ |
| 601 self.DeriveNativeEntry("constructorCallback", 'Constructor', arg
ument_count) | 604 self.DeriveNativeEntry("constructorCallback", 'Constructor', arg
ument_count) |
| 602 qualified_name = \ | 605 qualified_name = \ |
| 603 self.DeriveQualifiedBlinkName(self._interface.id, | 606 self.DeriveQualifiedBlinkName(self._interface.id, |
| 604 base_name) | 607 base_name) |
| 605 args = constructor_info.ParametersAsArgumentList(argument_count) | 608 args = constructor_info.ParametersAsArgumentList(argument_count) |
| 609 |
| 610 # Handle converting Maps to Dictionaries, etc. |
| 611 (factory_params, converted_arguments) = self._ConvertArgumentTypes( |
| 612 stmts_emitter, arguments, argument_count, constructor_info) |
| 613 args = ', '.join(converted_arguments) |
| 614 call_template = 'wrap_jso($FACTORY_NAME($FACTORY_PARAMS))' |
| 606 else: | 615 else: |
| 607 qualified_name = emitter.Format( | 616 qualified_name = emitter.Format( |
| 608 '$FACTORY.$NAME', | 617 '$FACTORY.$NAME', |
| 609 FACTORY=factory_name, | 618 FACTORY=factory_name, |
| 610 NAME=name) | 619 NAME=name) |
| 611 (factory_params, converted_arguments) = self._ConvertArgumentTypes( | 620 (factory_params, converted_arguments) = self._ConvertArgumentTypes( |
| 612 stmts_emitter, arguments, argument_count, constructor_info) | 621 stmts_emitter, arguments, argument_count, constructor_info) |
| 613 args = ', '.join(converted_arguments) | 622 args = ', '.join(converted_arguments) |
| 614 call_emitter.Emit('$FACTORY_NAME($FACTORY_PARAMS)', | 623 call_template = '$FACTORY_NAME($FACTORY_PARAMS)' |
| 615 FACTORY_NAME=qualified_name, | 624 call_emitter.Emit(call_template, FACTORY_NAME=qualified_name, FACTORY_PA
RAMS=args) |
| 616 FACTORY_PARAMS=args) | |
| 617 self.EmitStaticFactoryOverload(constructor_info, name, arguments) | 625 self.EmitStaticFactoryOverload(constructor_info, name, arguments) |
| 618 | 626 |
| 619 def IsOptional(signature_index, argument): | 627 def IsOptional(signature_index, argument): |
| 620 return self.IsConstructorArgumentOptional(argument) | 628 return self.IsConstructorArgumentOptional(argument) |
| 621 | 629 |
| 622 entry_declaration = emitter.Format( | 630 entry_declaration = emitter.Format( |
| 623 '$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)', | 631 '$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)', |
| 624 FACTORY_KEYWORD=('factory' if not custom_factory_ctr else | 632 FACTORY_KEYWORD=('factory' if not custom_factory_ctr else |
| 625 'static %s' % constructor_full_name), | 633 'static %s' % constructor_full_name), |
| 626 CTOR=(('' if not custom_factory_ctr else '_factory') | 634 CTOR=(('' if not custom_factory_ctr else '_factory') |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 self._members_emitter.Emit( | 700 self._members_emitter.Emit( |
| 693 ' // To suppress missing implicit constructor warnings.\n' | 701 ' // To suppress missing implicit constructor warnings.\n' |
| 694 ' factory $CLASSNAME._() { ' | 702 ' factory $CLASSNAME._() { ' |
| 695 'throw new UnsupportedError("Not supported"); }\n', | 703 'throw new UnsupportedError("Not supported"); }\n', |
| 696 CLASSNAME=self._interface_type_info.implementation_name()) | 704 CLASSNAME=self._interface_type_info.implementation_name()) |
| 697 | 705 |
| 698 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): | 706 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): |
| 699 """ Declares an attribute but does not include the code to invoke it. | 707 """ Declares an attribute but does not include the code to invoke it. |
| 700 """ | 708 """ |
| 701 if read_only: | 709 if read_only: |
| 702 template = '\n $TYPE get $NAME;\n' | 710 # HACK(terry): Element is not abstract for Dartium so isContentEditable |
| 711 # must have a body see impl_Element.darttemplate |
| 712 if (self._interface.id == 'Element' and |
| 713 attr_name == 'isContentEditable' and |
| 714 self._dart_js_interop): |
| 715 return |
| 716 else: |
| 717 template = '\n $TYPE get $NAME;\n' |
| 703 else: | 718 else: |
| 704 template = '\n $TYPE $NAME;\n' | 719 template = '\n $TYPE $NAME;\n' |
| 705 | 720 |
| 706 self._members_emitter.Emit(template, | 721 self._members_emitter.Emit(template, |
| 707 NAME=attr_name, | 722 NAME=attr_name, |
| 708 TYPE=type_name) | 723 TYPE=type_name) |
| 709 | 724 |
| 710 def DeclareOperation(self, operation, return_type_name, method_name): | 725 def DeclareOperation(self, operation, return_type_name, method_name): |
| 711 """ Declares an operation but does not include the code to invoke it. | 726 """ Declares an operation but does not include the code to invoke it. |
| 712 Arguments: | 727 Arguments: |
| 713 operation - The operation to be declared. | 728 operation - The operation to be declared. |
| 714 return_type_name - The name of the return type. | 729 return_type_name - The name of the return type. |
| 715 method_name - The name of the method. | 730 method_name - The name of the method. |
| 716 """ | 731 """ |
| 732 # HACK(terry): Element is not abstract for Dartium so click |
| 733 # must have a body see impl_Element.darttemplate |
| 734 if (self._interface.id == 'Element' and |
| 735 method_name == 'click' and |
| 736 self._dart_js_interop): |
| 737 return |
| 738 else: |
| 739 template = '\n $TYPE $NAME($PARAMS);\n' |
| 740 |
| 717 self._members_emitter.Emit( | 741 self._members_emitter.Emit( |
| 718 '\n' | 742 template, |
| 719 ' $TYPE $NAME($PARAMS);\n', | |
| 720 TYPE=return_type_name, | 743 TYPE=return_type_name, |
| 721 NAME=method_name, | 744 NAME=method_name, |
| 722 PARAMS=operation.ParametersAsDeclaration(self._DartType)) | 745 PARAMS=operation.ParametersAsDeclaration(self._DartType)) |
| 723 | 746 |
| 724 def EmitListMixin(self, element_name): | 747 def EmitListMixin(self, element_name): |
| 725 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | 748 # TODO(sra): Use separate mixins for mutable implementations of List<T>. |
| 726 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | 749 # TODO(sra): Use separate mixins for typed array implementations of List<T>. |
| 727 template_file = 'immutable_list_mixin.darttemplate' | 750 template_file = 'immutable_list_mixin.darttemplate' |
| 728 has_length = False | 751 has_length = False |
| 729 has_length_setter = False | 752 has_length_setter = False |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 return self._type_registry.TypeInfo(type_name).narrow_dart_type() | 820 return self._type_registry.TypeInfo(type_name).narrow_dart_type() |
| 798 | 821 |
| 799 def _NarrowInputType(self, type_name): | 822 def _NarrowInputType(self, type_name): |
| 800 return self._NarrowToImplementationType(type_name) | 823 return self._NarrowToImplementationType(type_name) |
| 801 | 824 |
| 802 def _DartType(self, type_name): | 825 def _DartType(self, type_name): |
| 803 return self._type_registry.DartType(type_name) | 826 return self._type_registry.DartType(type_name) |
| 804 | 827 |
| 805 def _TypeInfo(self, type_name): | 828 def _TypeInfo(self, type_name): |
| 806 return self._type_registry.TypeInfo(type_name) | 829 return self._type_registry.TypeInfo(type_name) |
| 830 |
| 831 def _ConvertArgumentTypes(self, stmts_emitter, arguments, argument_count, info
): |
| 832 temp_version = [0] |
| 833 converted_arguments = [] |
| 834 target_parameters = [] |
| 835 for position, arg in enumerate(arguments[:argument_count]): |
| 836 conversion = self._InputConversion(arg.type.id, info.declared_name) |
| 837 param_name = arguments[position].id |
| 838 if conversion: |
| 839 temp_version[0] += 1 |
| 840 temp_name = '%s_%s' % (param_name, temp_version[0]) |
| 841 temp_type = conversion.output_type |
| 842 stmts_emitter.Emit( |
| 843 '$(INDENT)$TYPE $NAME = $CONVERT($ARG);\n', |
| 844 TYPE=TypeOrVar(temp_type), |
| 845 NAME=temp_name, |
| 846 CONVERT=conversion.function_name, |
| 847 ARG=info.param_infos[position].name) |
| 848 converted_arguments.append(temp_name) |
| 849 param_type = temp_type |
| 850 verified_type = temp_type # verified by assignment in checked mode. |
| 851 else: |
| 852 converted_arguments.append(info.param_infos[position].name) |
| 853 param_type = self._NarrowInputType(arg.type.id) |
| 854 # Verified by argument checking on entry to the dispatcher. |
| 855 |
| 856 verified_type = self._InputType( |
| 857 info.param_infos[position].type_id, info) |
| 858 # The native method does not need an argument type if we know the type. |
| 859 # But we do need the native methods to have correct function types, so |
| 860 # be conservative. |
| 861 if param_type == verified_type: |
| 862 if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']: |
| 863 param_type = 'dynamic' |
| 864 |
| 865 target_parameters.append( |
| 866 '%s%s' % (TypeOrNothing(param_type), param_name)) |
| 867 |
| 868 return target_parameters, converted_arguments |
| 869 |
| 870 def _InputType(self, type_name, info): |
| 871 conversion = self._InputConversion(type_name, info.declared_name) |
| 872 if conversion: |
| 873 return conversion.input_type |
| 874 else: |
| 875 return self._NarrowInputType(type_name) if type_name else 'dynamic' |
| OLD | NEW |