| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 => '${namer.ISOLATE}.\$finishIsolateConstructor'; | 86 => '${namer.ISOLATE}.\$finishIsolateConstructor'; |
| 87 String get pendingClassesName | 87 String get pendingClassesName |
| 88 => '${namer.ISOLATE}.\$pendingClasses'; | 88 => '${namer.ISOLATE}.\$pendingClasses'; |
| 89 String get isolatePropertiesName | 89 String get isolatePropertiesName |
| 90 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; | 90 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; |
| 91 String get supportsProtoName | 91 String get supportsProtoName |
| 92 => 'supportsProto'; | 92 => 'supportsProto'; |
| 93 String get lazyInitializerName | 93 String get lazyInitializerName |
| 94 => '${namer.ISOLATE}.\$lazy'; | 94 => '${namer.ISOLATE}.\$lazy'; |
| 95 | 95 |
| 96 // Property name suffixes. If the accessors are renaming then the format | 96 final String GETTER_SUFFIX = "?"; |
| 97 // is <accessorName>:<fieldName><suffix>. We use the suffix to know whether | 97 final String SETTER_SUFFIX = "!"; |
| 98 // to look for the ':' separator in order to avoid doing the indexOf operation | 98 final String GETTER_SETTER_SUFFIX = "="; |
| 99 // on every single property (they are quite rare). None of these characters | |
| 100 // are legal in an identifier and they are related by bit patterns. | |
| 101 // setter < 0x3c | |
| 102 // both = 0x3d | |
| 103 // getter > 0x3e | |
| 104 // renaming setter | 0x7c | |
| 105 // renaming both } 0x7d | |
| 106 // renaming getter ~ 0x7e | |
| 107 const SUFFIX_MASK = 0x3f; | |
| 108 const FIRST_SUFFIX_CODE = 0x3c; | |
| 109 const SETTER_CODE = 0x3c; | |
| 110 const GETTER_SETTER_CODE = 0x3d; | |
| 111 const GETTER_CODE = 0x3e; | |
| 112 const RENAMING_FLAG = 0x40; | |
| 113 String needsGetterCode(String variable) => '($variable & 3) > 0'; | |
| 114 String needsSetterCode(String variable) => '($variable & 2) == 0'; | |
| 115 String isRenaming(String variable) => '($variable & $RENAMING_FLAG) != 0'; | |
| 116 | 99 |
| 117 String get generateGetterSetterFunction { | 100 String get generateGetterSetterFunction { |
| 118 return """ | 101 return """ |
| 119 function(field, prototype) { | 102 function(field, prototype) { |
| 120 var len = field.length; | 103 var len = field.length; |
| 121 var lastCharCode = field.charCodeAt(len - 1); | 104 var lastChar = field[len - 1]; |
| 122 var needsAccessor = (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE; | 105 var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTE
R_SUFFIX'; |
| 123 if (needsAccessor) { | 106 var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTE
R_SUFFIX'; |
| 124 var needsGetter = ${needsGetterCode('lastCharCode')}; | 107 if (needsGetter || needsSetter) field = field.substring(0, len - 1); |
| 125 var needsSetter = ${needsSetterCode('lastCharCode')}; | 108 if (needsGetter) { |
| 126 var renaming = ${isRenaming('lastCharCode')}; | 109 var getterString = "return this." + field + ";"; |
| 127 var accessorName = field = field.substring(0, len - 1); | 110 """ |
| 128 if (renaming) { | 111 /* The supportsProtoCheck below depends on the getter/setter convention. |
| 129 var divider = field.indexOf(":"); | 112 When changing here, update the protoCheck too. */ |
| 130 accessorName = field.substring(0, divider); | 113 """ |
| 131 field = field.substring(divider + 1); | 114 prototype["get\$" + field] = new Function(getterString); |
| 132 } | 115 } |
| 133 if (needsGetter) { | 116 if (needsSetter) { |
| 134 var getterString = "return this." + field + ";"; | 117 var setterString = "this." + field + " = v;"; |
| 135 prototype["get\$" + accessorName] = new Function(getterString); | 118 prototype["set\$" + field] = new Function("v", setterString); |
| 136 } | |
| 137 if (needsSetter) { | |
| 138 var setterString = "this." + field + " = v;"; | |
| 139 prototype["set\$" + accessorName] = new Function("v", setterString); | |
| 140 } | |
| 141 } | 119 } |
| 142 return field; | 120 return field; |
| 143 }"""; | 121 }"""; |
| 144 } | 122 } |
| 145 | 123 |
| 146 String get defineClassFunction { | 124 String get defineClassFunction { |
| 147 // First the class name, then the super class name, followed by the fields | 125 // First the class name, then the super class name, followed by the fields |
| 148 // (in an array) and the members (inside an Object literal). | 126 // (in an array) and the members (inside an Object literal). |
| 149 // The caller can also pass in the constructor as a function if needed. | 127 // The caller can also pass in the constructor as a function if needed. |
| 150 // | 128 // |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). | 169 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). |
| 192 // If the browser does not support __proto__ we need to instantiate an | 170 // If the browser does not support __proto__ we need to instantiate an |
| 193 // object with the correct (internal) prototype set up correctly, and then | 171 // object with the correct (internal) prototype set up correctly, and then |
| 194 // copy the members. | 172 // copy the members. |
| 195 | 173 |
| 196 return ''' | 174 return ''' |
| 197 var $supportsProtoName = false; | 175 var $supportsProtoName = false; |
| 198 var tmp = $defineClassName('c', ['f?'], {}).prototype; | 176 var tmp = $defineClassName('c', ['f?'], {}).prototype; |
| 199 if (tmp.__proto__) { | 177 if (tmp.__proto__) { |
| 200 tmp.__proto__ = {}; | 178 tmp.__proto__ = {}; |
| 201 if (typeof tmp.get\$f !== 'undefined') $supportsProtoName = true; | 179 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true; |
| 202 } | 180 } |
| 203 '''; | 181 '''; |
| 204 } | 182 } |
| 205 | 183 |
| 206 String get finishClassesFunction { | 184 String get finishClassesFunction { |
| 207 // 'defineClass' does not require the classes to be constructed in order. | 185 // 'defineClass' does not require the classes to be constructed in order. |
| 208 // Classes are initially just stored in the 'pendingClasses' field. | 186 // Classes are initially just stored in the 'pendingClasses' field. |
| 209 // 'finishClasses' takes all pending classes and sets up the prototype. | 187 // 'finishClasses' takes all pending classes and sets up the prototype. |
| 210 // Once set up, the constructors prototype field satisfy: | 188 // Once set up, the constructors prototype field satisfy: |
| 211 // - it contains all (local) members. | 189 // - it contains all (local) members. |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 // | 478 // |
| 501 // We need to generate a stub for (5) because the order of the | 479 // We need to generate a stub for (5) because the order of the |
| 502 // stub arguments and the real method may be different. | 480 // stub arguments and the real method may be different. |
| 503 | 481 |
| 504 // Keep a cache of which stubs have already been generated, to | 482 // Keep a cache of which stubs have already been generated, to |
| 505 // avoid duplicates. Note that even if selectors are | 483 // avoid duplicates. Note that even if selectors are |
| 506 // canonicalized, we would still need this cache: a typed selector | 484 // canonicalized, we would still need this cache: a typed selector |
| 507 // on A and a typed selector on B could yield the same stub. | 485 // on A and a typed selector on B could yield the same stub. |
| 508 Set<String> generatedStubNames = new Set<String>(); | 486 Set<String> generatedStubNames = new Set<String>(); |
| 509 if (compiler.enabledFunctionApply | 487 if (compiler.enabledFunctionApply |
| 510 && member.name == namer.CLOSURE_INVOCATION_NAME) { | 488 && member.name == Namer.CLOSURE_INVOCATION_NAME) { |
| 511 // If [Function.apply] is called, we pessimistically compile all | 489 // If [Function.apply] is called, we pessimistically compile all |
| 512 // possible stubs for this closure. | 490 // possible stubs for this closure. |
| 513 // TODO(5074): This functionality only supports the new | 491 // TODO(5074): This functionality only supports the new |
| 514 // parameter specification, and this comment should be removed | 492 // parameter specification, and this comment should be removed |
| 515 // once the old specification is not supported. | 493 // once the old specification is not supported. |
| 516 FunctionSignature signature = member.computeSignature(compiler); | 494 FunctionSignature signature = member.computeSignature(compiler); |
| 517 Set<Selector> selectors = signature.optionalParametersAreNamed | 495 Set<Selector> selectors = signature.optionalParametersAreNamed |
| 518 ? computeNamedSelectors(signature, member) | 496 ? computeNamedSelectors(signature, member) |
| 519 : computeOptionalSelectors(signature, member); | 497 : computeOptionalSelectors(signature, member); |
| 520 for (Selector selector in selectors) { | 498 for (Selector selector in selectors) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 } | 675 } |
| 698 | 676 |
| 699 /** | 677 /** |
| 700 * Documentation wanted -- johnniwinther | 678 * Documentation wanted -- johnniwinther |
| 701 * | 679 * |
| 702 * Invariant: [classElement] must be a declaration element. | 680 * Invariant: [classElement] must be a declaration element. |
| 703 */ | 681 */ |
| 704 void visitClassFields(ClassElement classElement, | 682 void visitClassFields(ClassElement classElement, |
| 705 void addField(Element member, | 683 void addField(Element member, |
| 706 String name, | 684 String name, |
| 707 String accessorName, | |
| 708 bool needsGetter, | 685 bool needsGetter, |
| 709 bool needsSetter, | 686 bool needsSetter, |
| 710 bool needsCheckedSetter)) { | 687 bool needsCheckedSetter)) { |
| 711 assert(invariant(classElement, classElement.isDeclaration)); | 688 assert(invariant(classElement, classElement.isDeclaration)); |
| 712 // If the class is never instantiated we still need to set it up for | 689 // If the class is never instantiated we still need to set it up for |
| 713 // inheritance purposes, but we can simplify its JavaScript constructor. | 690 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 714 bool isInstantiated = | 691 bool isInstantiated = |
| 715 compiler.codegenWorld.instantiatedClasses.contains(classElement); | 692 compiler.codegenWorld.instantiatedClasses.contains(classElement); |
| 716 | 693 |
| 717 void visitField(ClassElement enclosingClass, Element member) { | 694 void visitField(ClassElement enclosingClass, Element member) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 733 if (identical(enclosingClass, classElement)) { | 710 if (identical(enclosingClass, classElement)) { |
| 734 needsGetter = instanceFieldNeedsGetter(member); | 711 needsGetter = instanceFieldNeedsGetter(member); |
| 735 needsSetter = instanceFieldNeedsSetter(member); | 712 needsSetter = instanceFieldNeedsSetter(member); |
| 736 } else { | 713 } else { |
| 737 isShadowed = classElement.isShadowedByField(member); | 714 isShadowed = classElement.isShadowedByField(member); |
| 738 } | 715 } |
| 739 | 716 |
| 740 if ((isInstantiated && !enclosingClass.isNative()) | 717 if ((isInstantiated && !enclosingClass.isNative()) |
| 741 || needsGetter | 718 || needsGetter |
| 742 || needsSetter) { | 719 || needsSetter) { |
| 743 String accessorName = isShadowed | 720 String fieldName = isShadowed |
| 744 ? namer.shadowedFieldName(member) | 721 ? namer.shadowedFieldName(member) |
| 745 : namer.getName(member); | 722 : namer.getName(member); |
| 746 String fieldName = enclosingClass.isNative() ? | |
| 747 member.name.slowToString() : accessorName; | |
| 748 bool needsCheckedSetter = false; | 723 bool needsCheckedSetter = false; |
| 749 if (needsSetter && compiler.enableTypeAssertions | 724 if (needsSetter && compiler.enableTypeAssertions |
| 750 && canGenerateCheckedSetter(member)) { | 725 && canGenerateCheckedSetter(member)) { |
| 751 needsCheckedSetter = true; | 726 needsCheckedSetter = true; |
| 752 needsSetter = false; | 727 needsSetter = false; |
| 753 } | 728 } |
| 754 // Getters and setters with suffixes will be generated dynamically. | 729 // Getters and setters with suffixes will be generated dynamically. |
| 755 addField(member, | 730 addField(member, |
| 756 fieldName, | 731 fieldName, |
| 757 accessorName, | |
| 758 needsGetter, | 732 needsGetter, |
| 759 needsSetter, | 733 needsSetter, |
| 760 needsCheckedSetter); | 734 needsCheckedSetter); |
| 761 } | 735 } |
| 762 } | 736 } |
| 763 | 737 |
| 764 // If a class is not instantiated then we add the field just so we can | 738 // If a class is not instantiated then we add the field just so we can |
| 765 // generate the field getter/setter dynamically. Since this is only | 739 // generate the field getter/setter dynamically. Since this is only |
| 766 // allowed on fields that are in [classElement] we don't need to visit | 740 // allowed on fields that are in [classElement] we don't need to visit |
| 767 // superclasses for non-instantiated classes. | 741 // superclasses for non-instantiated classes. |
| 768 classElement.implementation.forEachInstanceField( | 742 classElement.implementation.forEachInstanceField( |
| 769 visitField, | 743 visitField, |
| 770 includeBackendMembers: true, | 744 includeBackendMembers: true, |
| 771 includeSuperMembers: isInstantiated && !classElement.isNative()); | 745 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 772 } | 746 } |
| 773 | 747 |
| 774 void generateGetter(Element member, String fieldName, String accessorName, | 748 void generateGetter(Element member, String fieldName, CodeBuffer buffer) { |
| 775 CodeBuffer buffer) { | 749 String getterName = namer.getterName(member.getLibrary(), member.name); |
| 776 String getterName = | |
| 777 namer.getterName(member.getLibrary(), new SourceString(accessorName)); | |
| 778 buffer.add("$getterName: function() { return this.$fieldName; }"); | 750 buffer.add("$getterName: function() { return this.$fieldName; }"); |
| 779 } | 751 } |
| 780 | 752 |
| 781 void generateSetter(Element member, String fieldName, String accessorName, | 753 void generateSetter(Element member, String fieldName, CodeBuffer buffer) { |
| 782 CodeBuffer buffer) { | 754 String setterName = namer.setterName(member.getLibrary(), member.name); |
| 783 String setterName = | |
| 784 namer.setterName(member.getLibrary(), new SourceString(accessorName)); | |
| 785 buffer.add("$setterName: function(v) { this.$fieldName = v; }"); | 755 buffer.add("$setterName: function(v) { this.$fieldName = v; }"); |
| 786 } | 756 } |
| 787 | 757 |
| 788 bool canGenerateCheckedSetter(Element member) { | 758 bool canGenerateCheckedSetter(Element member) { |
| 789 DartType type = member.computeType(compiler); | 759 DartType type = member.computeType(compiler); |
| 790 if (type.element.isTypeVariable() | 760 if (type.element.isTypeVariable() |
| 791 || type.element == compiler.dynamicClass | 761 || type.element == compiler.dynamicClass |
| 792 || type.element == compiler.objectClass) { | 762 || type.element == compiler.objectClass) { |
| 793 // TODO(ngeoffray): Support type checks on type parameters. | 763 // TODO(ngeoffray): Support type checks on type parameters. |
| 794 return false; | 764 return false; |
| 795 } | 765 } |
| 796 return true; | 766 return true; |
| 797 } | 767 } |
| 798 | 768 |
| 799 void generateCheckedSetter(Element member, | 769 void generateCheckedSetter(Element member, |
| 800 String fieldName, | 770 String fieldName, |
| 801 String accessorName, | |
| 802 CodeBuffer buffer) { | 771 CodeBuffer buffer) { |
| 803 assert(canGenerateCheckedSetter(member)); | 772 assert(canGenerateCheckedSetter(member)); |
| 804 DartType type = member.computeType(compiler); | 773 DartType type = member.computeType(compiler); |
| 805 SourceString helper = compiler.backend.getCheckedModeHelper(type); | 774 SourceString helper = compiler.backend.getCheckedModeHelper(type); |
| 806 FunctionElement helperElement = compiler.findHelper(helper); | 775 FunctionElement helperElement = compiler.findHelper(helper); |
| 807 String helperName = namer.isolateAccess(helperElement); | 776 String helperName = namer.isolateAccess(helperElement); |
| 808 String additionalArgument = ''; | 777 String additionalArgument = ''; |
| 809 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 778 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 810 additionalArgument = ", '${namer.operatorIs(type.element)}'"; | 779 additionalArgument = ", '${namer.operatorIs(type.element)}'"; |
| 811 } | 780 } |
| 812 String setterName = | 781 String setterName = namer.setterName(member.getLibrary(), member.name); |
| 813 namer.setterName(member.getLibrary(), new SourceString(accessorName)); | |
| 814 buffer.add("$setterName: function(v) { " | 782 buffer.add("$setterName: function(v) { " |
| 815 "this.$fieldName = $helperName(v$additionalArgument); }"); | 783 "this.$fieldName = $helperName(v$additionalArgument); }"); |
| 816 } | 784 } |
| 817 | 785 |
| 818 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 786 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { |
| 819 /* Do nothing. */ | 787 /* Do nothing. */ |
| 820 } | 788 } |
| 821 | 789 |
| 822 void emitClassFields(ClassElement classElement, CodeBuffer buffer) { | 790 void emitClassFields(ClassElement classElement, CodeBuffer buffer) { |
| 823 buffer.add('"": ['); | 791 buffer.add('"": ['); |
| 824 bool isFirstField = true; | 792 bool isFirstField = true; |
| 825 visitClassFields(classElement, (Element member, | 793 visitClassFields(classElement, (Element member, |
| 826 String name, | 794 String name, |
| 827 String accessorName, | |
| 828 bool needsGetter, | 795 bool needsGetter, |
| 829 bool needsSetter, | 796 bool needsSetter, |
| 830 bool needsCheckedSetter) { | 797 bool needsCheckedSetter) { |
| 831 if (isFirstField) { | 798 if (isFirstField) { |
| 832 isFirstField = false; | 799 isFirstField = false; |
| 833 } else { | 800 } else { |
| 834 buffer.add(", "); | 801 buffer.add(", "); |
| 835 } | 802 } |
| 836 buffer.add('"$accessorName'); | 803 buffer.add('"$name'); |
| 837 int flag = 0; | |
| 838 if (name != accessorName) { | |
| 839 buffer.add(':$name'); | |
| 840 assert(needsGetter || needsSetter); | |
| 841 flag = RENAMING_FLAG; | |
| 842 } | |
| 843 if (needsGetter && needsSetter) { | 804 if (needsGetter && needsSetter) { |
| 844 buffer.addCharCode(GETTER_SETTER_CODE + flag); | 805 buffer.add(GETTER_SETTER_SUFFIX); |
| 845 } else if (needsGetter) { | 806 } else if (needsGetter) { |
| 846 buffer.addCharCode(GETTER_CODE + flag); | 807 buffer.add(GETTER_SUFFIX); |
| 847 } else if (needsSetter) { | 808 } else if (needsSetter) { |
| 848 buffer.addCharCode(SETTER_CODE + flag); | 809 buffer.add(SETTER_SUFFIX); |
| 849 } | 810 } |
| 850 buffer.add('"'); | 811 buffer.add('"'); |
| 851 }); | 812 }); |
| 852 buffer.add(']'); | 813 buffer.add(']'); |
| 853 } | 814 } |
| 854 | 815 |
| 855 /** Each getter/setter must be prefixed with a ",\n ". */ | 816 /** Each getter/setter must be prefixed with a ",\n ". */ |
| 856 void emitClassGettersSetters(ClassElement classElement, CodeBuffer buffer, | 817 void emitClassGettersSetters(ClassElement classElement, CodeBuffer buffer, |
| 857 {bool omitLeadingComma: false}) { | 818 {bool omitLeadingComma: false}) { |
| 858 visitClassFields(classElement, (Element member, | 819 visitClassFields(classElement, (Element member, |
| 859 String name, | 820 String name, |
| 860 String accessorName, | |
| 861 bool needsGetter, | 821 bool needsGetter, |
| 862 bool needsSetter, | 822 bool needsSetter, |
| 863 bool needsCheckedSetter) { | 823 bool needsCheckedSetter) { |
| 864 if (needsCheckedSetter) { | 824 if (needsCheckedSetter) { |
| 865 assert(!needsSetter); | 825 assert(!needsSetter); |
| 866 if (!omitLeadingComma) { | 826 if (!omitLeadingComma) { |
| 867 buffer.add(",\n "); | 827 buffer.add(",\n "); |
| 868 } else { | 828 } else { |
| 869 omitLeadingComma = false; | 829 omitLeadingComma = false; |
| 870 } | 830 } |
| 871 generateCheckedSetter(member, name, accessorName, buffer); | 831 generateCheckedSetter(member, name, buffer); |
| 872 } | 832 } |
| 873 }); | 833 }); |
| 874 } | 834 } |
| 875 | 835 |
| 876 /** | 836 /** |
| 877 * Documentation wanted -- johnniwinther | 837 * Documentation wanted -- johnniwinther |
| 878 * | 838 * |
| 879 * Invariant: [classElement] must be a declaration element. | 839 * Invariant: [classElement] must be a declaration element. |
| 880 */ | 840 */ |
| 881 void generateClass(ClassElement classElement, CodeBuffer buffer) { | 841 void generateClass(ClassElement classElement, CodeBuffer buffer) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 | 1008 |
| 1049 void emitStaticFunctionGetters(CodeBuffer buffer) { | 1009 void emitStaticFunctionGetters(CodeBuffer buffer) { |
| 1050 Set<FunctionElement> functionsNeedingGetter = | 1010 Set<FunctionElement> functionsNeedingGetter = |
| 1051 compiler.codegenWorld.staticFunctionsNeedingGetter; | 1011 compiler.codegenWorld.staticFunctionsNeedingGetter; |
| 1052 for (FunctionElement element in functionsNeedingGetter) { | 1012 for (FunctionElement element in functionsNeedingGetter) { |
| 1053 // The static function does not have the correct name. Since | 1013 // The static function does not have the correct name. Since |
| 1054 // [addParameterStubs] use the name to create its stubs we simply | 1014 // [addParameterStubs] use the name to create its stubs we simply |
| 1055 // create a fake element with the correct name. | 1015 // create a fake element with the correct name. |
| 1056 // Note: the callElement will not have any enclosingElement. | 1016 // Note: the callElement will not have any enclosingElement. |
| 1057 FunctionElement callElement = | 1017 FunctionElement callElement = |
| 1058 new ClosureInvocationElement(namer.CLOSURE_INVOCATION_NAME, element); | 1018 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); |
| 1059 String staticName = namer.getName(element); | 1019 String staticName = namer.getName(element); |
| 1060 String invocationName = namer.instanceMethodName(callElement); | 1020 String invocationName = namer.instanceMethodName(callElement); |
| 1061 String fieldAccess = '$isolateProperties.$staticName'; | 1021 String fieldAccess = '$isolateProperties.$staticName'; |
| 1062 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 1022 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); |
| 1063 addParameterStubs(callElement, (String name, CodeBuffer value) { | 1023 addParameterStubs(callElement, (String name, CodeBuffer value) { |
| 1064 buffer.add('$fieldAccess.$name = $value;\n'); | 1024 buffer.add('$fieldAccess.$name = $value;\n'); |
| 1065 }); | 1025 }); |
| 1066 // If a static function is used as a closure we need to add its name | 1026 // If a static function is used as a closure we need to add its name |
| 1067 // in case it is used in spawnFunction. | 1027 // in case it is used in spawnFunction. |
| 1068 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1028 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1125 needsClosureClass = true; | 1085 needsClosureClass = true; |
| 1126 | 1086 |
| 1127 // Define the constructor with a name so that Object.toString can | 1087 // Define the constructor with a name so that Object.toString can |
| 1128 // find the class name of the closure class. | 1088 // find the class name of the closure class. |
| 1129 emitBoundClosureClassHeader(mangledName, superName, boundClosureBuffer); | 1089 emitBoundClosureClassHeader(mangledName, superName, boundClosureBuffer); |
| 1130 // Now add the methods on the closure class. The instance method does not | 1090 // Now add the methods on the closure class. The instance method does not |
| 1131 // have the correct name. Since [addParameterStubs] use the name to create | 1091 // have the correct name. Since [addParameterStubs] use the name to create |
| 1132 // its stubs we simply create a fake element with the correct name. | 1092 // its stubs we simply create a fake element with the correct name. |
| 1133 // Note: the callElement will not have any enclosingElement. | 1093 // Note: the callElement will not have any enclosingElement. |
| 1134 FunctionElement callElement = | 1094 FunctionElement callElement = |
| 1135 new ClosureInvocationElement(namer.CLOSURE_INVOCATION_NAME, member); | 1095 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); |
| 1136 | 1096 |
| 1137 String invocationName = namer.instanceMethodName(callElement); | 1097 String invocationName = namer.instanceMethodName(callElement); |
| 1138 List<String> arguments = new List<String>(parameterCount); | 1098 List<String> arguments = new List<String>(parameterCount); |
| 1139 for (int i = 0; i < parameterCount; i++) { | 1099 for (int i = 0; i < parameterCount; i++) { |
| 1140 arguments[i] = "p$i"; | 1100 arguments[i] = "p$i"; |
| 1141 } | 1101 } |
| 1142 String joinedArgs = Strings.join(arguments, ", "); | 1102 String joinedArgs = Strings.join(arguments, ", "); |
| 1143 boundClosureBuffer.add( | 1103 boundClosureBuffer.add( |
| 1144 "$invocationName: function($joinedArgs) {"); | 1104 "$invocationName: function($joinedArgs) {"); |
| 1145 boundClosureBuffer.add(" return this.self[this.target]($joinedArgs);"); | 1105 boundClosureBuffer.add(" return this.self[this.target]($joinedArgs);"); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; | 1141 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; |
| 1182 } else { | 1142 } else { |
| 1183 String name = namer.instanceFieldName(memberLibrary, member.name); | 1143 String name = namer.instanceFieldName(memberLibrary, member.name); |
| 1184 getter = "this.$name"; | 1144 getter = "this.$name"; |
| 1185 } | 1145 } |
| 1186 for (Selector selector in selectors) { | 1146 for (Selector selector in selectors) { |
| 1187 if (selector.applies(member, compiler)) { | 1147 if (selector.applies(member, compiler)) { |
| 1188 String invocationName = | 1148 String invocationName = |
| 1189 namer.instanceMethodInvocationName(memberLibrary, member.name, | 1149 namer.instanceMethodInvocationName(memberLibrary, member.name, |
| 1190 selector); | 1150 selector); |
| 1191 SourceString callName = namer.CLOSURE_INVOCATION_NAME; | 1151 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; |
| 1192 String closureCallName = | 1152 String closureCallName = |
| 1193 namer.instanceMethodInvocationName(memberLibrary, callName, | 1153 namer.instanceMethodInvocationName(memberLibrary, callName, |
| 1194 selector); | 1154 selector); |
| 1195 List<String> arguments = <String>[]; | 1155 List<String> arguments = <String>[]; |
| 1196 for (int i = 0; i < selector.argumentCount; i++) { | 1156 for (int i = 0; i < selector.argumentCount; i++) { |
| 1197 arguments.add("arg$i"); | 1157 arguments.add("arg$i"); |
| 1198 } | 1158 } |
| 1199 String joined = Strings.join(arguments, ", "); | 1159 String joined = Strings.join(arguments, ", "); |
| 1200 CodeBuffer getterBuffer = new CodeBuffer(); | 1160 CodeBuffer getterBuffer = new CodeBuffer(); |
| 1201 getterBuffer.add( | 1161 getterBuffer.add( |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); | 1471 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); |
| 1512 mainCall = buildIsolateSetup(buffer, main, isolateMain); | 1472 mainCall = buildIsolateSetup(buffer, main, isolateMain); |
| 1513 } else { | 1473 } else { |
| 1514 mainCall = '${namer.isolateAccess(main)}()'; | 1474 mainCall = '${namer.isolateAccess(main)}()'; |
| 1515 } | 1475 } |
| 1516 buffer.add(""" | 1476 buffer.add(""" |
| 1517 | 1477 |
| 1518 // | 1478 // |
| 1519 // BEGIN invoke [main]. | 1479 // BEGIN invoke [main]. |
| 1520 // | 1480 // |
| 1521 if (typeof document !== 'undefined' && document.readyState != 'complete') { | 1481 if (typeof document != 'undefined' && document.readyState != 'complete') { |
| 1522 document.addEventListener('readystatechange', function () { | 1482 document.addEventListener('readystatechange', function () { |
| 1523 if (document.readyState == 'complete') { | 1483 if (document.readyState == 'complete') { |
| 1524 if (typeof dartMainRunner === 'function') { | 1484 if (typeof dartMainRunner == 'function') { |
| 1525 dartMainRunner(function() { ${mainCall}; }); | 1485 dartMainRunner(function() { ${mainCall}; }); |
| 1526 } else { | 1486 } else { |
| 1527 ${mainCall}; | 1487 ${mainCall}; |
| 1528 } | 1488 } |
| 1529 } | 1489 } |
| 1530 }, false); | 1490 }, false); |
| 1531 } else { | 1491 } else { |
| 1532 if (typeof dartMainRunner === 'function') { | 1492 if (typeof dartMainRunner == 'function') { |
| 1533 dartMainRunner(function() { ${mainCall}; }); | 1493 dartMainRunner(function() { ${mainCall}; }); |
| 1534 } else { | 1494 } else { |
| 1535 ${mainCall}; | 1495 ${mainCall}; |
| 1536 } | 1496 } |
| 1537 } | 1497 } |
| 1538 // | 1498 // |
| 1539 // END invoke [main]. | 1499 // END invoke [main]. |
| 1540 // | 1500 // |
| 1541 | 1501 |
| 1542 """); | 1502 """); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 const String HOOKS_API_USAGE = """ | 1580 const String HOOKS_API_USAGE = """ |
| 1621 // Generated by dart2js, the Dart to JavaScript compiler. | 1581 // Generated by dart2js, the Dart to JavaScript compiler. |
| 1622 // The code supports the following hooks: | 1582 // The code supports the following hooks: |
| 1623 // dartPrint(message) - if this function is defined it is called | 1583 // dartPrint(message) - if this function is defined it is called |
| 1624 // instead of the Dart [print] method. | 1584 // instead of the Dart [print] method. |
| 1625 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1585 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 1626 // method will not be invoked directly. | 1586 // method will not be invoked directly. |
| 1627 // Instead, a closure that will invoke [main] is | 1587 // Instead, a closure that will invoke [main] is |
| 1628 // passed to [dartMainRunner]. | 1588 // passed to [dartMainRunner]. |
| 1629 """; | 1589 """; |
| OLD | NEW |