| 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 |