OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 part of dart2js.js_emitter.startup_emitter.model_emitter; | 5 part of dart2js.js_emitter.startup_emitter.model_emitter; |
6 | 6 |
7 /// The name of the property that stores the tear-off getter on a static | 7 /// The name of the property that stores the tear-off getter on a static |
8 /// function. | 8 /// function. |
9 /// | 9 /// |
10 /// This property is only used when isolates are used. | 10 /// This property is only used when isolates are used. |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 List<js.Property> properties = <js.Property>[]; | 606 List<js.Property> properties = <js.Property>[]; |
607 | 607 |
608 if (cls.superclass == null) { | 608 if (cls.superclass == null) { |
609 properties.add(new js.Property(js.string("constructor"), | 609 properties.add(new js.Property(js.string("constructor"), |
610 classReference(cls))); | 610 classReference(cls))); |
611 properties.add(new js.Property(namer.operatorIs(cls.element), | 611 properties.add(new js.Property(namer.operatorIs(cls.element), |
612 js.number(1))); | 612 js.number(1))); |
613 } | 613 } |
614 | 614 |
615 allMethods.forEach((Method method) { | 615 allMethods.forEach((Method method) { |
616 emitInstanceMethod(method).forEach((js.Name name, js.Expression code) { | 616 emitInstanceMethod(method) |
| 617 .forEach((js.Expression name, js.Expression code) { |
617 properties.add(new js.Property(name, code)); | 618 properties.add(new js.Property(name, code)); |
618 }); | 619 }); |
619 }); | 620 }); |
620 | 621 |
621 return new js.ObjectInitializer(properties); | 622 return new js.ObjectInitializer(properties); |
622 } | 623 } |
623 | 624 |
624 /// Generates a getter for the given [field]. | 625 /// Generates a getter for the given [field]. |
625 Method generateGetter(Field field) { | 626 Method generateGetter(Field field) { |
626 assert(field.needsGetter); | 627 assert(field.needsGetter); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 | 673 |
673 return [getters, setters].expand((x) => x); | 674 return [getters, setters].expand((x) => x); |
674 } | 675 } |
675 | 676 |
676 /// Emits the given instance [method]. | 677 /// Emits the given instance [method]. |
677 /// | 678 /// |
678 /// The given method may be a stub-method (for example for is-checks). | 679 /// The given method may be a stub-method (for example for is-checks). |
679 /// | 680 /// |
680 /// If it is a Dart-method, all necessary stub-methods are emitted, too. In | 681 /// If it is a Dart-method, all necessary stub-methods are emitted, too. In |
681 /// that case the returned map contains more than just one entry. | 682 /// that case the returned map contains more than just one entry. |
682 Map<js.Name, js.Expression> emitInstanceMethod(Method method) { | 683 /// |
683 Map<js.Name, js.Expression> jsMethods = <js.Name, js.Expression>{}; | 684 /// If the method is a closure call-method, also returns the necessary |
| 685 /// properties in case the closure can be applied. |
| 686 Map<js.Expression, js.Expression> emitInstanceMethod(Method method) { |
| 687 var properties = <js.Expression, js.Expression>{}; |
684 | 688 |
685 jsMethods[method.name] = method.code; | 689 properties[method.name] = method.code; |
686 if (method is InstanceMethod) { | 690 if (method is InstanceMethod) { |
687 for (ParameterStubMethod stubMethod in method.parameterStubs) { | 691 for (ParameterStubMethod stubMethod in method.parameterStubs) { |
688 jsMethods[stubMethod.name] = stubMethod.code; | 692 properties[stubMethod.name] = stubMethod.code; |
| 693 } |
| 694 |
| 695 if (method.isClosureCallMethod && method.canBeApplied) { |
| 696 properties[js.string(namer.callCatchAllName)] = |
| 697 js.quoteName(method.name); |
| 698 properties[js.string(namer.requiredParameterField)] = |
| 699 js.number(method.requiredParameterCount); |
| 700 properties[js.string(namer.defaultValuesField)] = |
| 701 js.js('function() { return #; }', |
| 702 _encodeOptionalParameterDefaultValues(method)); |
689 } | 703 } |
690 } | 704 } |
691 | 705 |
692 return jsMethods; | 706 return properties; |
693 } | 707 } |
694 | 708 |
695 /// Emits the inheritance block of the fragment. | 709 /// Emits the inheritance block of the fragment. |
696 /// | 710 /// |
697 /// In this section prototype chains are updated and mixin functions are | 711 /// In this section prototype chains are updated and mixin functions are |
698 /// copied. | 712 /// copied. |
699 js.Statement emitInheritance(Fragment fragment) { | 713 js.Statement emitInheritance(Fragment fragment) { |
700 List<js.Expression> inheritCalls = <js.Expression>[]; | 714 List<js.Expression> inheritCalls = <js.Expression>[]; |
701 List<js.Expression> mixinCalls = <js.Expression>[]; | 715 List<js.Expression> mixinCalls = <js.Expression>[]; |
702 | 716 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole]. | 766 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole]. |
753 if (method.optionalParameterDefaultValues is List) { | 767 if (method.optionalParameterDefaultValues is List) { |
754 List<ConstantValue> defaultValues = method.optionalParameterDefaultValues; | 768 List<ConstantValue> defaultValues = method.optionalParameterDefaultValues; |
755 Iterable<js.Expression> elements = | 769 Iterable<js.Expression> elements = |
756 defaultValues.map(generateConstantReference); | 770 defaultValues.map(generateConstantReference); |
757 return new js.ArrayInitializer(elements.toList()); | 771 return new js.ArrayInitializer(elements.toList()); |
758 } else { | 772 } else { |
759 Map<String, ConstantValue> defaultValues = | 773 Map<String, ConstantValue> defaultValues = |
760 method.optionalParameterDefaultValues; | 774 method.optionalParameterDefaultValues; |
761 List<js.Property> properties = <js.Property>[]; | 775 List<js.Property> properties = <js.Property>[]; |
762 defaultValues.forEach((String name, ConstantValue value) { | 776 List<String> names = defaultValues.keys.toList(growable: false); |
| 777 // Sort the names the same way we sort them for the named-argument calling |
| 778 // convention. |
| 779 names.sort(); |
| 780 |
| 781 for (String name in names) { |
| 782 ConstantValue value = defaultValues[name]; |
763 properties.add(new js.Property(js.string(name), | 783 properties.add(new js.Property(js.string(name), |
764 generateConstantReference(value))); | 784 generateConstantReference(value))); |
765 }); | 785 } |
766 return new js.ObjectInitializer(properties); | 786 return new js.ObjectInitializer(properties); |
767 } | 787 } |
768 } | 788 } |
769 | 789 |
770 /// Emits the statement that installs a tear off for a method. | 790 /// Emits the statement that installs a tear off for a method. |
771 /// | 791 /// |
772 /// Tear-offs might be passed to `Function.apply` which means that all | 792 /// Tear-offs might be passed to `Function.apply` which means that all |
773 /// calling-conventions (with or without optional positional/named arguments) | 793 /// calling-conventions (with or without optional positional/named arguments) |
774 /// are possible. As such, the tear-off needs enough information to fill in | 794 /// are possible. As such, the tear-off needs enough information to fill in |
775 /// missing parameters. | 795 /// missing parameters. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 isIntercepted = backend.isInterceptedMethod(method.element); | 829 isIntercepted = backend.isInterceptedMethod(method.element); |
810 } | 830 } |
811 int requiredParameterCount = 0; | 831 int requiredParameterCount = 0; |
812 js.Expression optionalParameterDefaultValues = new js.LiteralNull(); | 832 js.Expression optionalParameterDefaultValues = new js.LiteralNull(); |
813 if (method.canBeApplied) { | 833 if (method.canBeApplied) { |
814 requiredParameterCount = method.requiredParameterCount; | 834 requiredParameterCount = method.requiredParameterCount; |
815 optionalParameterDefaultValues = | 835 optionalParameterDefaultValues = |
816 _encodeOptionalParameterDefaultValues(method); | 836 _encodeOptionalParameterDefaultValues(method); |
817 } | 837 } |
818 | 838 |
819 // TODO(floitsch): this can be more efficient. | 839 // TODO(floitsch): this can be more efficient. |
820 return js.js.statement(''' | 840 return js.js.statement(''' |
821 installTearOff(#container, #getterName, #isStatic, #isIntercepted, | 841 installTearOff(#container, #getterName, #isStatic, #isIntercepted, |
822 #requiredParameterCount, #optionalParameterDefaultValues, | 842 #requiredParameterCount, #optionalParameterDefaultValues, |
823 #callNames, #funsOrNames, #funType)''', | 843 #callNames, #funsOrNames, #funType)''', |
824 { | 844 { |
825 "container": container, | 845 "container": container, |
826 "getterName": js.quoteName(method.tearOffName), | 846 "getterName": js.quoteName(method.tearOffName), |
827 "isStatic": new js.LiteralBool(method.isStatic), | 847 "isStatic": new js.LiteralBool(method.isStatic), |
828 "isIntercepted": new js.LiteralBool(isIntercepted), | 848 "isIntercepted": new js.LiteralBool(isIntercepted), |
829 "requiredParameterCount": js.number(requiredParameterCount), | 849 "requiredParameterCount": js.number(requiredParameterCount), |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 } | 1233 } |
1214 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", | 1234 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", |
1215 js.objectLiteral(interceptorsByTag))); | 1235 js.objectLiteral(interceptorsByTag))); |
1216 statements.add(js.js.statement("setOrUpdateLeafTags(#);", | 1236 statements.add(js.js.statement("setOrUpdateLeafTags(#);", |
1217 js.objectLiteral(leafTags))); | 1237 js.objectLiteral(leafTags))); |
1218 statements.add(subclassAssignment); | 1238 statements.add(subclassAssignment); |
1219 | 1239 |
1220 return new js.Block(statements); | 1240 return new js.Block(statements); |
1221 } | 1241 } |
1222 } | 1242 } |
OLD | NEW |