OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
6 | 6 |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 import 'dart:convert' show JSON; | 8 import 'dart:convert' show JSON; |
9 | 9 |
10 import '../../closure.dart' show ClosureTask, ClosureFieldElement; | 10 import '../../closure.dart' show ClosureTask, ClosureFieldElement; |
11 import '../../common.dart'; | 11 import '../../common.dart'; |
12 import '../../common/names.dart' show Names, Selectors; | 12 import '../../common/names.dart' show Names, Selectors; |
13 import '../../constants/values.dart' | 13 import '../../constants/values.dart' |
14 show ConstantValue, InterceptorConstantValue; | 14 show ConstantValue, InterceptorConstantValue; |
15 import '../../common_elements.dart' show CommonElements, ElementEnvironment; | 15 import '../../common_elements.dart' show CommonElements, ElementEnvironment; |
16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
17 import '../../elements/elements.dart' | 17 import '../../elements/elements.dart' |
18 show | 18 show |
19 ClassElement, | 19 ClassElement, |
20 ConstructorBodyElement, | |
20 Element, | 21 Element, |
21 Elements, | 22 Elements, |
22 FieldElement, | 23 FieldElement, |
23 FunctionElement, | 24 FunctionElement, |
24 FunctionSignature, | 25 FunctionSignature, |
25 GetterElement, | 26 GetterElement, |
26 LibraryElement, | 27 LibraryElement, |
27 MemberElement, | 28 MemberElement, |
28 MethodElement, | 29 MethodElement, |
29 ParameterElement, | 30 ParameterElement, |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 if (superclass != null) { | 230 if (superclass != null) { |
230 c.setSuperclass(_classes[superclass]); | 231 c.setSuperclass(_classes[superclass]); |
231 assert( | 232 assert( |
232 c.superclass != null, | 233 c.superclass != null, |
233 failedAt( | 234 failedAt( |
234 cls, | 235 cls, |
235 "No Class for has been created for superclass " | 236 "No Class for has been created for superclass " |
236 "${superclass} of $c.")); | 237 "${superclass} of $c.")); |
237 } | 238 } |
238 if (c is MixinApplication) { | 239 if (c is MixinApplication) { |
239 c.setMixinClass(_classes[computeMixinClass(cls)]); | 240 c.setMixinClass(_classes[computeMixinClass(cls)]); |
Siggi Cherem (dart-lang)
2017/06/08 18:01:46
should we do here the same fix you did in the othe
Johnni Winther
2017/06/09 09:28:49
ElementEnvironment.forEachMixin returns all mixins
Siggi Cherem (dart-lang)
2017/06/14 18:13:24
are you saying that the code in program_builder/co
Johnni Winther
2017/06/15 07:44:11
It wasn't - just weird: computeMixinClass didn't m
| |
240 assert(c.mixinClass != null); | 241 assert(c.mixinClass != null); |
241 } | 242 } |
242 }); | 243 }); |
243 | 244 |
244 List<Class> nativeClasses = collector.nativeClassesAndSubclasses | 245 List<Class> nativeClasses = collector.nativeClassesAndSubclasses |
245 .map((ClassEntity classElement) => _classes[classElement]) | 246 .map((ClassEntity classElement) => _classes[classElement]) |
246 .toList(); | 247 .toList(); |
247 | 248 |
248 Set<ClassEntity> interceptorClassesNeededByConstants = | 249 Set<ClassEntity> interceptorClassesNeededByConstants = |
249 collector.computeInterceptorsReferencedFromConstants(); | 250 collector.computeInterceptorsReferencedFromConstants(); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 // Interceptor class with implementations that directly call the | 511 // Interceptor class with implementations that directly call the |
511 // corresponding JavaScript member. We do not attempt to bind this when | 512 // corresponding JavaScript member. We do not attempt to bind this when |
512 // tearing off JavaScript methods as we cannot distinguish between calling | 513 // tearing off JavaScript methods as we cannot distinguish between calling |
513 // a regular getter that returns a JavaScript function and tearing off | 514 // a regular getter that returns a JavaScript function and tearing off |
514 // a method in the case where there exist multiple JavaScript classes | 515 // a method in the case where there exist multiple JavaScript classes |
515 // that conflict on whether the member is a getter or a method. | 516 // that conflict on whether the member is a getter or a method. |
516 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; | 517 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; |
517 var stubNames = new Set<String>(); | 518 var stubNames = new Set<String>(); |
518 librariesMap | 519 librariesMap |
519 .forEach((LibraryEntity library, List<ClassEntity> classElements, _) { | 520 .forEach((LibraryEntity library, List<ClassEntity> classElements, _) { |
520 for (ClassElement e in classElements) { | 521 for (ClassEntity cls in classElements) { |
521 if (_nativeData.isJsInteropClass(e)) { | 522 if (_nativeData.isJsInteropClass(cls)) { |
523 // TODO(johnniwinther): Handle class entities. | |
524 ClassElement e = cls; | |
522 e.declaration.forEachMember((_, Element member) { | 525 e.declaration.forEachMember((_, Element member) { |
523 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); | 526 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); |
524 if (!member.isInstanceMember) return; | 527 if (!member.isInstanceMember) return; |
525 if (member.isGetter || member.isField || member.isFunction) { | 528 if (member.isGetter || member.isField || member.isFunction) { |
526 var selectors = | 529 var selectors = |
527 _worldBuilder.getterInvocationsByName(member.name); | 530 _worldBuilder.getterInvocationsByName(member.name); |
528 if (selectors != null && !selectors.isEmpty) { | 531 if (selectors != null && !selectors.isEmpty) { |
529 for (var selector in selectors.keys) { | 532 for (var selector in selectors.keys) { |
530 var stubName = _namer.invocationName(selector); | 533 var stubName = _namer.invocationName(selector); |
531 if (stubNames.add(stubName.key)) { | 534 if (stubNames.add(stubName.key)) { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
656 .toList(growable: false); | 659 .toList(growable: false); |
657 | 660 |
658 bool visitStatics = true; | 661 bool visitStatics = true; |
659 List<Field> staticFieldsForReflection = | 662 List<Field> staticFieldsForReflection = |
660 _buildFields(library: library, visitStatics: visitStatics); | 663 _buildFields(library: library, visitStatics: visitStatics); |
661 | 664 |
662 return new Library( | 665 return new Library( |
663 library, uri, statics, classes, staticFieldsForReflection); | 666 library, uri, statics, classes, staticFieldsForReflection); |
664 } | 667 } |
665 | 668 |
666 bool _isSoftDeferred(ClassElement element) { | 669 bool _isSoftDeferred(ClassEntity element) { |
667 return _notSoftDeferred != null && !_notSoftDeferred.contains(element); | 670 return _notSoftDeferred != null && !_notSoftDeferred.contains(element); |
668 } | 671 } |
669 | 672 |
670 Class _buildClass(ClassElement element) { | 673 Class _buildClass(ClassEntity cls) { |
671 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); | 674 bool onlyForRti = collector.classesOnlyNeededForRti.contains(cls); |
672 bool hasRtiField = _rtiNeed.classNeedsRtiField(element); | 675 bool hasRtiField = _rtiNeed.classNeedsRtiField(cls); |
673 if (_nativeData.isJsInteropClass(element)) { | 676 if (_nativeData.isJsInteropClass(cls)) { |
674 // TODO(jacobr): check whether the class has any active static fields | 677 // TODO(jacobr): check whether the class has any active static fields |
675 // if it does not we can suppress it completely. | 678 // if it does not we can suppress it completely. |
676 onlyForRti = true; | 679 onlyForRti = true; |
677 } | 680 } |
678 bool isClosureBaseClass = element == _commonElements.closureClass; | 681 bool isClosureBaseClass = cls == _commonElements.closureClass; |
679 | 682 |
680 List<Method> methods = []; | 683 List<Method> methods = []; |
681 List<StubMethod> callStubs = <StubMethod>[]; | 684 List<StubMethod> callStubs = <StubMethod>[]; |
682 | 685 |
683 ClassStubGenerator classStubGenerator = new ClassStubGenerator( | 686 ClassStubGenerator classStubGenerator = new ClassStubGenerator( |
684 _task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld, | 687 _task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld, |
685 enableMinification: _options.enableMinification); | 688 enableMinification: _options.enableMinification); |
686 RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator( | 689 RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator( |
687 _commonElements, | 690 _commonElements, |
688 _closureToClassMapper, | 691 _closureToClassMapper, |
689 _task, | 692 _task, |
690 _namer, | 693 _namer, |
691 _nativeData, | 694 _nativeData, |
692 _rtiChecks, | 695 _rtiChecks, |
693 _rtiEncoder, | 696 _rtiEncoder, |
694 _rtiNeed, | 697 _rtiNeed, |
695 _rtiSubstitutions, | 698 _rtiSubstitutions, |
696 _jsInteropAnalysis); | 699 _jsInteropAnalysis); |
697 | 700 |
698 void visitMember(ClassElement enclosing, MemberElement member) { | 701 void visitMember(ClassEntity declarer, MemberEntity member) { |
699 assert(member.isDeclaration, failedAt(element)); | 702 if (cls != declarer) return; |
700 assert(element == enclosing, failedAt(element)); | |
701 | 703 |
702 if (Elements.isNonAbstractInstanceMember(member)) { | 704 if (member.isInstanceMember && !member.isAbstract && !member.isField) { |
703 // TODO(herhut): Remove once _buildMethod can no longer return null. | 705 // TODO(herhut): Remove once _buildMethod can no longer return null. |
704 Method method = _buildMethod(member); | 706 Method method = _buildMethod(member); |
705 if (method != null) methods.add(method); | 707 if (method != null) methods.add(method); |
706 } | 708 } |
707 if (member.isGetter || member.isField) { | 709 if (member.isGetter || member.isField) { |
708 Map<Selector, SelectorConstraints> selectors = | 710 Map<Selector, SelectorConstraints> selectors = |
709 _worldBuilder.invocationsByName(member.name); | 711 _worldBuilder.invocationsByName(member.name); |
710 if (selectors != null && !selectors.isEmpty) { | 712 if (selectors != null && !selectors.isEmpty) { |
711 Map<js.Name, js.Expression> callStubsForMember = | 713 Map<js.Name, js.Expression> callStubsForMember = |
712 classStubGenerator.generateCallStubsForGetter(member, selectors); | 714 classStubGenerator.generateCallStubsForGetter(member, selectors); |
713 callStubsForMember.forEach((js.Name name, js.Expression code) { | 715 callStubsForMember.forEach((js.Name name, js.Expression code) { |
714 callStubs.add(_buildStubMethod(name, code, element: member)); | 716 callStubs.add(_buildStubMethod(name, code, element: member)); |
715 }); | 717 }); |
716 } | 718 } |
717 } | 719 } |
718 } | 720 } |
719 | 721 |
720 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; | 722 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; |
721 | 723 |
722 if (_backendUsage.isNoSuchMethodUsed && element.isObject) { | 724 if (_backendUsage.isNoSuchMethodUsed && |
725 cls == _commonElements.objectClass) { | |
723 Map<js.Name, Selector> selectors = | 726 Map<js.Name, Selector> selectors = |
724 classStubGenerator.computeSelectorsForNsmHandlers(); | 727 classStubGenerator.computeSelectorsForNsmHandlers(); |
725 selectors.forEach((js.Name name, Selector selector) { | 728 selectors.forEach((js.Name name, Selector selector) { |
726 // If the program contains `const Symbol` names we have to retain them. | 729 // If the program contains `const Symbol` names we have to retain them. |
727 String selectorName = selector.name; | 730 String selectorName = selector.name; |
728 if (selector.isSetter) selectorName = "$selectorName="; | 731 if (selector.isSetter) selectorName = "$selectorName="; |
729 if (_mirrorsData.symbolsUsed.contains(selectorName)) { | 732 if (_mirrorsData.symbolsUsed.contains(selectorName)) { |
730 _symbolsMap[name] = selectorName; | 733 _symbolsMap[name] = selectorName; |
731 } | 734 } |
732 noSuchMethodStubs.add( | 735 noSuchMethodStubs.add( |
733 classStubGenerator.generateStubForNoSuchMethod(name, selector)); | 736 classStubGenerator.generateStubForNoSuchMethod(name, selector)); |
734 }); | 737 }); |
735 } | 738 } |
736 | 739 |
737 if (isClosureBaseClass) { | 740 if (isClosureBaseClass) { |
738 // We add a special getter to allow for tearing off a closure from itself. | 741 // We add a special getter to allow for tearing off a closure from itself. |
739 js.Name name = _namer.getterForMember(Names.call); | 742 js.Name name = _namer.getterForMember(Names.call); |
740 js.Fun function = js.js('function() { return this; }'); | 743 js.Fun function = js.js('function() { return this; }'); |
741 callStubs.add(_buildStubMethod(name, function)); | 744 callStubs.add(_buildStubMethod(name, function)); |
742 } | 745 } |
743 | 746 |
744 ClassElement implementation = element.implementation; | |
745 | |
746 // MixinApplications run through the members of their mixin. Here, we are | 747 // MixinApplications run through the members of their mixin. Here, we are |
747 // only interested in direct members. | 748 // only interested in direct members. |
748 if (!onlyForRti && !element.isMixinApplication) { | 749 if (!onlyForRti && !_elementEnvironment.isUnnamedMixinApplication(cls)) { |
749 implementation.forEachMember(visitMember, includeBackendMembers: true); | 750 _elementEnvironment.forEachClassMember(cls, visitMember); |
751 if (cls is ClassElement) { | |
752 // TODO(johnniwinther): Support constructor bodies for entities. | |
753 cls.forEachBackendMember((ConstructorBodyElement constructorBody) => | |
754 visitMember(cls, constructorBody)); | |
755 } | |
750 } | 756 } |
751 bool isInterceptedClass = _interceptorData.isInterceptedClass(element); | 757 bool isInterceptedClass = _interceptorData.isInterceptedClass(cls); |
752 List<Field> instanceFields = onlyForRti | 758 List<Field> instanceFields = onlyForRti |
753 ? const <Field>[] | 759 ? const <Field>[] |
754 : _buildFields( | 760 : _buildFields( |
755 cls: element, | 761 cls: cls, |
756 visitStatics: false, | 762 visitStatics: false, |
757 isHolderInterceptedClass: isInterceptedClass); | 763 isHolderInterceptedClass: isInterceptedClass); |
758 List<Field> staticFieldsForReflection = onlyForRti | 764 List<Field> staticFieldsForReflection = onlyForRti |
759 ? const <Field>[] | 765 ? const <Field>[] |
760 : _buildFields( | 766 : _buildFields( |
761 cls: element, | 767 cls: cls, |
762 visitStatics: true, | 768 visitStatics: true, |
763 isHolderInterceptedClass: isInterceptedClass); | 769 isHolderInterceptedClass: isInterceptedClass); |
764 | 770 |
765 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, | 771 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(cls, |
766 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 772 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
767 | 773 |
768 List<StubMethod> checkedSetters = <StubMethod>[]; | 774 List<StubMethod> checkedSetters = <StubMethod>[]; |
769 List<StubMethod> isChecks = <StubMethod>[]; | 775 List<StubMethod> isChecks = <StubMethod>[]; |
770 if (_nativeData.isJsInteropClass(element)) { | 776 if (_nativeData.isJsInteropClass(cls)) { |
771 typeTests.properties.forEach((js.Name name, js.Node code) { | 777 typeTests.properties.forEach((js.Name name, js.Node code) { |
772 _classes[_commonElements.jsInterceptorClass] | 778 _classes[_commonElements.jsInterceptorClass] |
773 .isChecks | 779 .isChecks |
774 .add(_buildStubMethod(name, code)); | 780 .add(_buildStubMethod(name, code)); |
775 }); | 781 }); |
776 } else { | 782 } else { |
777 for (Field field in instanceFields) { | 783 for (Field field in instanceFields) { |
778 if (field.needsCheckedSetter) { | 784 if (field.needsCheckedSetter) { |
779 assert(!field.needsUncheckedSetter); | 785 assert(!field.needsUncheckedSetter); |
780 FieldElement element = field.element; | 786 FieldElement element = field.element; |
781 js.Expression code = _generatedCode[element]; | 787 js.Expression code = _generatedCode[element]; |
782 assert(code != null); | 788 assert(code != null); |
783 js.Name name = _namer.deriveSetterName(field.accessorName); | 789 js.Name name = _namer.deriveSetterName(field.accessorName); |
784 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 790 checkedSetters.add(_buildStubMethod(name, code, element: element)); |
785 } | 791 } |
786 } | 792 } |
787 | 793 |
788 typeTests.properties.forEach((js.Name name, js.Node code) { | 794 typeTests.properties.forEach((js.Name name, js.Node code) { |
789 isChecks.add(_buildStubMethod(name, code)); | 795 isChecks.add(_buildStubMethod(name, code)); |
790 }); | 796 }); |
791 } | 797 } |
792 | 798 |
793 js.Name name = _namer.className(element); | 799 js.Name name = _namer.className(cls); |
794 String holderName = _namer.globalObjectForClass(element); | 800 String holderName = _namer.globalObjectForClass(cls); |
795 // TODO(floitsch): we shouldn't update the registry in the middle of | 801 // TODO(floitsch): we shouldn't update the registry in the middle of |
796 // building a class. | 802 // building a class. |
797 Holder holder = _registry.registerHolder(holderName); | 803 Holder holder = _registry.registerHolder(holderName); |
798 bool isInstantiated = !_nativeData.isJsInteropClass(element) && | 804 bool isInstantiated = !_nativeData.isJsInteropClass(cls) && |
799 _worldBuilder.directlyInstantiatedClasses.contains(element); | 805 _worldBuilder.directlyInstantiatedClasses.contains(cls); |
800 | 806 |
801 Class result; | 807 Class result; |
802 if (element.isMixinApplication && !onlyForRti) { | 808 if (_elementEnvironment.isUnnamedMixinApplication(cls) && !onlyForRti) { |
803 assert(!_nativeData.isNativeClass(element)); | 809 assert(!_nativeData.isNativeClass(cls)); |
804 assert(methods.isEmpty); | 810 assert(methods.isEmpty); |
805 assert(!isClosureBaseClass); | 811 assert(!isClosureBaseClass); |
806 | 812 |
807 result = new MixinApplication( | 813 result = new MixinApplication( |
808 element, | 814 cls, |
809 name, | 815 name, |
810 holder, | 816 holder, |
811 instanceFields, | 817 instanceFields, |
812 staticFieldsForReflection, | 818 staticFieldsForReflection, |
813 callStubs, | 819 callStubs, |
814 checkedSetters, | 820 checkedSetters, |
815 isChecks, | 821 isChecks, |
816 typeTests.functionTypeIndex, | 822 typeTests.functionTypeIndex, |
817 isDirectlyInstantiated: isInstantiated, | 823 isDirectlyInstantiated: isInstantiated, |
818 hasRtiField: hasRtiField, | 824 hasRtiField: hasRtiField, |
819 onlyForRti: onlyForRti); | 825 onlyForRti: onlyForRti); |
820 } else { | 826 } else { |
821 result = new Class( | 827 result = new Class( |
822 element, | 828 cls, |
823 name, | 829 name, |
824 holder, | 830 holder, |
825 methods, | 831 methods, |
826 instanceFields, | 832 instanceFields, |
827 staticFieldsForReflection, | 833 staticFieldsForReflection, |
828 callStubs, | 834 callStubs, |
829 noSuchMethodStubs, | 835 noSuchMethodStubs, |
830 checkedSetters, | 836 checkedSetters, |
831 isChecks, | 837 isChecks, |
832 typeTests.functionTypeIndex, | 838 typeTests.functionTypeIndex, |
833 isDirectlyInstantiated: isInstantiated, | 839 isDirectlyInstantiated: isInstantiated, |
834 hasRtiField: hasRtiField, | 840 hasRtiField: hasRtiField, |
835 onlyForRti: onlyForRti, | 841 onlyForRti: onlyForRti, |
836 isNative: _nativeData.isNativeClass(element), | 842 isNative: _nativeData.isNativeClass(cls), |
837 isClosureBaseClass: isClosureBaseClass, | 843 isClosureBaseClass: isClosureBaseClass, |
838 isSoftDeferred: _isSoftDeferred(element)); | 844 isSoftDeferred: _isSoftDeferred(cls)); |
839 } | 845 } |
840 _classes[element] = result; | 846 _classes[cls] = result; |
841 return result; | 847 return result; |
842 } | 848 } |
843 | 849 |
844 bool _methodNeedsStubs(FunctionEntity method) { | 850 bool _methodNeedsStubs(FunctionEntity method) { |
845 return method.parameterStructure.optionalParameters != 0; | 851 return method.parameterStructure.optionalParameters != 0; |
846 } | 852 } |
847 | 853 |
848 bool _methodCanBeReflected(FunctionEntity method) { | 854 bool _methodCanBeReflected(FunctionEntity method) { |
849 return _mirrorsData.isMemberAccessibleByReflection(method); | 855 return _mirrorsData.isMemberAccessibleByReflection(method); |
850 } | 856 } |
(...skipping 16 matching lines...) Expand all Loading... | |
867 optionalParameterDefaultValues = <ConstantValue>[]; | 873 optionalParameterDefaultValues = <ConstantValue>[]; |
868 signature.forEachOptionalParameter((ParameterElement parameter) { | 874 signature.forEachOptionalParameter((ParameterElement parameter) { |
869 ConstantValue def = | 875 ConstantValue def = |
870 _constantHandler.getConstantValue(parameter.constant); | 876 _constantHandler.getConstantValue(parameter.constant); |
871 optionalParameterDefaultValues.add(def); | 877 optionalParameterDefaultValues.add(def); |
872 }); | 878 }); |
873 } | 879 } |
874 return optionalParameterDefaultValues; | 880 return optionalParameterDefaultValues; |
875 } | 881 } |
876 | 882 |
877 DartMethod _buildMethod(MethodElement element) { | 883 DartMethod _buildMethod(FunctionEntity element) { |
878 assert(element.isDeclaration); | 884 assert(!(element is MethodElement && !element.isDeclaration)); |
879 js.Name name = _namer.methodPropertyName(element); | 885 js.Name name = _namer.methodPropertyName(element); |
880 js.Expression code = _generatedCode[element]; | 886 js.Expression code = _generatedCode[element]; |
881 | 887 |
882 // TODO(kasperl): Figure out under which conditions code is null. | 888 // TODO(kasperl): Figure out under which conditions code is null. |
883 if (code == null) return null; | 889 if (code == null) return null; |
884 | 890 |
885 bool canTearOff = false; | 891 bool canTearOff = false; |
886 js.Name tearOffName; | 892 js.Name tearOffName; |
887 bool isClosureCallMethod = false; | 893 bool isClosureCallMethod = false; |
888 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 894 bool isNotApplyTarget = |
895 !element.isFunction || element.isGetter || element.isSetter; | |
889 | 896 |
890 bool canBeReflected = _methodCanBeReflected(element); | 897 bool canBeReflected = _methodCanBeReflected(element); |
891 bool canBeApplied = _methodCanBeApplied(element); | 898 bool canBeApplied = _methodCanBeApplied(element); |
892 | 899 |
893 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) | 900 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) |
894 ? _namer.aliasedSuperMemberPropertyName(element) | 901 ? _namer.aliasedSuperMemberPropertyName(element) |
895 : null; | 902 : null; |
896 | 903 |
897 if (isNotApplyTarget) { | 904 if (isNotApplyTarget) { |
898 canTearOff = false; | 905 canTearOff = false; |
899 } else { | 906 } else { |
900 if (element.enclosingClass.isClosure) { | 907 if (element.enclosingClass.isClosure) { |
901 canTearOff = false; | 908 canTearOff = false; |
902 isClosureCallMethod = true; | 909 isClosureCallMethod = true; |
903 } else { | 910 } else { |
904 // Careful with operators. | 911 // Careful with operators. |
905 canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) || | 912 canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) || |
906 (canBeReflected && !element.isOperator); | 913 (canBeReflected && !Selector.isOperatorName(element.name)); |
907 assert(canTearOff || | 914 assert(canTearOff || |
908 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); | 915 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); |
909 tearOffName = _namer.getterForElement(element); | 916 tearOffName = _namer.getterForElement(element); |
910 } | 917 } |
911 } | 918 } |
912 | 919 |
913 if (canTearOff) { | 920 if (canTearOff) { |
914 assert(!element.isGenerativeConstructor, failedAt(element)); | 921 assert(element is! ConstructorEntity, failedAt(element)); |
915 assert(!element.isGenerativeConstructorBody, failedAt(element)); | 922 assert(element is! ConstructorBodyElement, failedAt(element)); |
916 assert(!element.isConstructor, failedAt(element)); | |
917 } | 923 } |
918 | 924 |
919 js.Name callName = null; | 925 js.Name callName = null; |
920 if (canTearOff) { | 926 if (canTearOff) { |
921 Selector callSelector = | 927 Selector callSelector = |
922 new Selector.fromElement(element).toCallSelector(); | 928 new Selector.fromElement(element).toCallSelector(); |
923 callName = _namer.invocationName(callSelector); | 929 callName = _namer.invocationName(callSelector); |
924 } | 930 } |
925 | 931 |
926 ResolutionDartType memberType; | 932 DartType memberType = _elementEnvironment.getFunctionType(element); |
927 if (element.isGenerativeConstructorBody) { | |
928 // TODO(herhut): Why does this need to be normalized away? We never need | |
929 // this information anyway as they cannot be torn off or | |
930 // reflected. | |
931 var body = element; | |
932 memberType = body.constructor.type; | |
933 } else { | |
934 memberType = element.type; | |
935 } | |
936 | |
937 js.Expression functionType; | 933 js.Expression functionType; |
938 if (canTearOff || canBeReflected) { | 934 if (canTearOff || canBeReflected) { |
939 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element); | 935 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); |
940 functionType = _generateFunctionType(memberType, outputUnit); | 936 functionType = _generateFunctionType(memberType, outputUnit); |
941 } | 937 } |
942 | 938 |
943 int requiredParameterCount; | 939 int requiredParameterCount; |
944 var /* List | Map */ optionalParameterDefaultValues; | 940 var /* List | Map */ optionalParameterDefaultValues; |
945 if (canBeApplied || canBeReflected) { | 941 if (canBeApplied || canBeReflected) { |
946 FunctionSignature signature = element.functionSignature; | 942 // TODO(johnniwinther): Handle function entities. |
943 MethodElement method = element; | |
944 FunctionSignature signature = method.functionSignature; | |
947 requiredParameterCount = signature.requiredParameterCount; | 945 requiredParameterCount = signature.requiredParameterCount; |
948 optionalParameterDefaultValues = | 946 optionalParameterDefaultValues = |
949 _computeParameterDefaultValues(signature); | 947 _computeParameterDefaultValues(signature); |
950 } | 948 } |
951 | 949 |
952 return new InstanceMethod(element, name, code, | 950 return new InstanceMethod(element, name, code, |
953 _generateParameterStubs(element, canTearOff), callName, | 951 _generateParameterStubs(element, canTearOff), callName, |
954 needsTearOff: canTearOff, | 952 needsTearOff: canTearOff, |
955 tearOffName: tearOffName, | 953 tearOffName: tearOffName, |
956 isClosureCallMethod: isClosureCallMethod, | 954 isClosureCallMethod: isClosureCallMethod, |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1185 Constant constant = new Constant(name, holder, constantValue); | 1183 Constant constant = new Constant(name, holder, constantValue); |
1186 _constants[constantValue] = constant; | 1184 _constants[constantValue] = constant; |
1187 } | 1185 } |
1188 } | 1186 } |
1189 | 1187 |
1190 Holder _registerStaticStateHolder() { | 1188 Holder _registerStaticStateHolder() { |
1191 return _registry.registerHolder(_namer.staticStateHolder, | 1189 return _registry.registerHolder(_namer.staticStateHolder, |
1192 isStaticStateHolder: true); | 1190 isStaticStateHolder: true); |
1193 } | 1191 } |
1194 } | 1192 } |
OLD | NEW |