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 | |
18 import logging | 17 import logging |
19 import monitored | 18 import monitored |
20 import sys | 19 import sys |
21 | 20 |
22 _logger = logging.getLogger('htmldartgenerator') | 21 _logger = logging.getLogger('htmldartgenerator') |
23 | 22 |
24 # Types that are accessible cross-frame in a limited fashion. | 23 # Types that are accessible cross-frame in a limited fashion. |
25 # In these cases, the base type (e.g., WindowBase) provides restricted access | 24 # In these cases, the base type (e.g., WindowBase) provides restricted access |
26 # while the subtype (e.g., Window) provides full access to the | 25 # while the subtype (e.g., Window) provides full access to the |
27 # corresponding objects if there are from the same frame. | 26 # corresponding objects if there are from the same frame. |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 member and not include invocation code. | 317 member and not include invocation code. |
319 """ | 318 """ |
320 # FIXME: When we pass in operations[0] below, we're assuming all | 319 # FIXME: When we pass in operations[0] below, we're assuming all |
321 # overloaded operations have the same security attributes. This | 320 # overloaded operations have the same security attributes. This |
322 # is currently true, but we should consider filtering earlier or | 321 # is currently true, but we should consider filtering earlier or |
323 # merging the relevant data into info itself. | 322 # merging the relevant data into info itself. |
324 method_name = self._renamer.RenameMember(self._interface.id, | 323 method_name = self._renamer.RenameMember(self._interface.id, |
325 info.operations[0], | 324 info.operations[0], |
326 info.name, | 325 info.name, |
327 'call:') | 326 'call:') |
328 | |
329 if not method_name: | 327 if not method_name: |
330 if info.name == 'item': | 328 if info.name == 'item': |
331 # FIXME: item should be renamed to operator[], not removed. | 329 # FIXME: item should be renamed to operator[], not removed. |
332 self.EmitOperation(info, '_item') | 330 self.EmitOperation(info, '_item') |
333 return | 331 return |
334 | 332 |
335 if declare_only: | 333 if declare_only: |
336 self.DeclareOperation(info, | 334 self.DeclareOperation(info, |
337 self.SecureOutputType(info.type_name), method_name) | 335 self.SecureOutputType(info.type_name), method_name) |
338 else: | 336 else: |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 factory_name to call (calls an autogenerated FactoryProvider | 519 factory_name to call (calls an autogenerated FactoryProvider |
522 if unspecified) | 520 if unspecified) |
523 """ | 521 """ |
524 for constructor_info in constructors: | 522 for constructor_info in constructors: |
525 self._AddConstructor( | 523 self._AddConstructor( |
526 constructor_info, factory_name, factory_constructor_name) | 524 constructor_info, factory_name, factory_constructor_name) |
527 | 525 |
528 def _AddConstructor(self, | 526 def _AddConstructor(self, |
529 constructor_info, factory_name, factory_constructor_name): | 527 constructor_info, factory_name, factory_constructor_name): |
530 # Hack to ignore the Image constructor used by JavaScript. | 528 # Hack to ignore the Image constructor used by JavaScript. |
531 if ((self._interface.id == 'HTMLImageElement' or self._interface.id == 'Blob
') | 529 if (self._interface.id == 'HTMLImageElement' |
532 and not constructor_info.pure_dart_constructor): | 530 and not constructor_info.pure_dart_constructor): |
533 return | 531 return |
534 | 532 |
535 if self.GenerateCustomFactory(constructor_info): | 533 if self.GenerateCustomFactory(constructor_info): |
536 return | 534 return |
537 | 535 |
538 metadata = self._metadata.GetFormattedMetadata( | 536 metadata = self._metadata.GetFormattedMetadata( |
539 self._library_name, self._interface, self._interface.id, ' ') | 537 self._library_name, self._interface, self._interface.id, ' ') |
540 | 538 |
541 if not factory_constructor_name: | 539 if not factory_constructor_name: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 custom_factory_ctr = self._interface.id in _custom_factories | 588 custom_factory_ctr = self._interface.id in _custom_factories |
591 constructor_full_name = constructor_info._ConstructorFullName( | 589 constructor_full_name = constructor_info._ConstructorFullName( |
592 self._DartType) | 590 self._DartType) |
593 | 591 |
594 def GenerateCall( | 592 def GenerateCall( |
595 stmts_emitter, call_emitter, | 593 stmts_emitter, call_emitter, |
596 version, signature_index, argument_count): | 594 version, signature_index, argument_count): |
597 name = emitter.Format('_create_$VERSION', VERSION=version) | 595 name = emitter.Format('_create_$VERSION', VERSION=version) |
598 arguments = constructor_info.idl_args[signature_index][:argument_count] | 596 arguments = constructor_info.idl_args[signature_index][:argument_count] |
599 args = None | 597 args = None |
600 call_template = '' | |
601 if self._dart_use_blink: | 598 if self._dart_use_blink: |
602 type_ids = [p.type.id for p in arguments] | 599 type_ids = [p.type.id for p in arguments] |
603 base_name, rs = \ | 600 base_name, rs = \ |
604 self.DeriveNativeEntry("constructorCallback", 'Constructor', arg
ument_count) | 601 self.DeriveNativeEntry("constructorCallback", 'Constructor', arg
ument_count) |
605 qualified_name = \ | 602 qualified_name = \ |
606 self.DeriveQualifiedBlinkName(self._interface.id, | 603 self.DeriveQualifiedBlinkName(self._interface.id, |
607 base_name) | 604 base_name) |
608 args = constructor_info.ParametersAsArgumentList(argument_count) | 605 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))' | |
615 else: | 606 else: |
616 qualified_name = emitter.Format( | 607 qualified_name = emitter.Format( |
617 '$FACTORY.$NAME', | 608 '$FACTORY.$NAME', |
618 FACTORY=factory_name, | 609 FACTORY=factory_name, |
619 NAME=name) | 610 NAME=name) |
620 (factory_params, converted_arguments) = self._ConvertArgumentTypes( | 611 (factory_params, converted_arguments) = self._ConvertArgumentTypes( |
621 stmts_emitter, arguments, argument_count, constructor_info) | 612 stmts_emitter, arguments, argument_count, constructor_info) |
622 args = ', '.join(converted_arguments) | 613 args = ', '.join(converted_arguments) |
623 call_template = '$FACTORY_NAME($FACTORY_PARAMS)' | 614 call_emitter.Emit('$FACTORY_NAME($FACTORY_PARAMS)', |
624 call_emitter.Emit(call_template, FACTORY_NAME=qualified_name, FACTORY_PA
RAMS=args) | 615 FACTORY_NAME=qualified_name, |
| 616 FACTORY_PARAMS=args) |
625 self.EmitStaticFactoryOverload(constructor_info, name, arguments) | 617 self.EmitStaticFactoryOverload(constructor_info, name, arguments) |
626 | 618 |
627 def IsOptional(signature_index, argument): | 619 def IsOptional(signature_index, argument): |
628 return self.IsConstructorArgumentOptional(argument) | 620 return self.IsConstructorArgumentOptional(argument) |
629 | 621 |
630 entry_declaration = emitter.Format( | 622 entry_declaration = emitter.Format( |
631 '$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)', | 623 '$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)', |
632 FACTORY_KEYWORD=('factory' if not custom_factory_ctr else | 624 FACTORY_KEYWORD=('factory' if not custom_factory_ctr else |
633 'static %s' % constructor_full_name), | 625 'static %s' % constructor_full_name), |
634 CTOR=(('' if not custom_factory_ctr else '_factory') | 626 CTOR=(('' if not custom_factory_ctr else '_factory') |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 self._members_emitter.Emit( | 692 self._members_emitter.Emit( |
701 ' // To suppress missing implicit constructor warnings.\n' | 693 ' // To suppress missing implicit constructor warnings.\n' |
702 ' factory $CLASSNAME._() { ' | 694 ' factory $CLASSNAME._() { ' |
703 'throw new UnsupportedError("Not supported"); }\n', | 695 'throw new UnsupportedError("Not supported"); }\n', |
704 CLASSNAME=self._interface_type_info.implementation_name()) | 696 CLASSNAME=self._interface_type_info.implementation_name()) |
705 | 697 |
706 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): | 698 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): |
707 """ Declares an attribute but does not include the code to invoke it. | 699 """ Declares an attribute but does not include the code to invoke it. |
708 """ | 700 """ |
709 if read_only: | 701 if read_only: |
710 # HACK(terry): Element is not abstract for Dartium so isContentEditable | 702 template = '\n $TYPE get $NAME;\n' |
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' | |
718 else: | 703 else: |
719 template = '\n $TYPE $NAME;\n' | 704 template = '\n $TYPE $NAME;\n' |
720 | 705 |
721 self._members_emitter.Emit(template, | 706 self._members_emitter.Emit(template, |
722 NAME=attr_name, | 707 NAME=attr_name, |
723 TYPE=type_name) | 708 TYPE=type_name) |
724 | 709 |
725 def DeclareOperation(self, operation, return_type_name, method_name): | 710 def DeclareOperation(self, operation, return_type_name, method_name): |
726 """ Declares an operation but does not include the code to invoke it. | 711 """ Declares an operation but does not include the code to invoke it. |
727 Arguments: | 712 Arguments: |
728 operation - The operation to be declared. | 713 operation - The operation to be declared. |
729 return_type_name - The name of the return type. | 714 return_type_name - The name of the return type. |
730 method_name - The name of the method. | 715 method_name - The name of the method. |
731 """ | 716 """ |
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 | |
741 self._members_emitter.Emit( | 717 self._members_emitter.Emit( |
742 template, | 718 '\n' |
| 719 ' $TYPE $NAME($PARAMS);\n', |
743 TYPE=return_type_name, | 720 TYPE=return_type_name, |
744 NAME=method_name, | 721 NAME=method_name, |
745 PARAMS=operation.ParametersAsDeclaration(self._DartType)) | 722 PARAMS=operation.ParametersAsDeclaration(self._DartType)) |
746 | 723 |
747 def EmitListMixin(self, element_name): | 724 def EmitListMixin(self, element_name): |
748 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | 725 # TODO(sra): Use separate mixins for mutable implementations of List<T>. |
749 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | 726 # TODO(sra): Use separate mixins for typed array implementations of List<T>. |
750 template_file = 'immutable_list_mixin.darttemplate' | 727 template_file = 'immutable_list_mixin.darttemplate' |
751 has_length = False | 728 has_length = False |
752 has_length_setter = False | 729 has_length_setter = False |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 return self._type_registry.TypeInfo(type_name).narrow_dart_type() | 797 return self._type_registry.TypeInfo(type_name).narrow_dart_type() |
821 | 798 |
822 def _NarrowInputType(self, type_name): | 799 def _NarrowInputType(self, type_name): |
823 return self._NarrowToImplementationType(type_name) | 800 return self._NarrowToImplementationType(type_name) |
824 | 801 |
825 def _DartType(self, type_name): | 802 def _DartType(self, type_name): |
826 return self._type_registry.DartType(type_name) | 803 return self._type_registry.DartType(type_name) |
827 | 804 |
828 def _TypeInfo(self, type_name): | 805 def _TypeInfo(self, type_name): |
829 return self._type_registry.TypeInfo(type_name) | 806 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 |