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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 => '${namer.ISOLATE}.\$finishIsolateConstructor'; | 100 => '${namer.ISOLATE}.\$finishIsolateConstructor'; |
101 String get pendingClassesName | 101 String get pendingClassesName |
102 => '${namer.ISOLATE}.\$pendingClasses'; | 102 => '${namer.ISOLATE}.\$pendingClasses'; |
103 String get isolatePropertiesName | 103 String get isolatePropertiesName |
104 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; | 104 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; |
105 String get supportsProtoName | 105 String get supportsProtoName |
106 => 'supportsProto'; | 106 => 'supportsProto'; |
107 String get lazyInitializerName | 107 String get lazyInitializerName |
108 => '${namer.ISOLATE}.\$lazy'; | 108 => '${namer.ISOLATE}.\$lazy'; |
109 | 109 |
110 // Property name suffixes. If the accessors are renaming then the format | 110 final String GETTER_SUFFIX = "?"; |
111 // is <accessorName>:<fieldName><suffix>. We use the suffix to know whether | 111 final String SETTER_SUFFIX = "!"; |
112 // to look for the ':' separator in order to avoid doing the indexOf operation | 112 final String GETTER_SETTER_SUFFIX = "="; |
113 // on every single property (they are quite rare). None of these characters | |
114 // are legal in an identifier and they are related by bit patterns. | |
115 // setter < 0x3c | |
116 // both = 0x3d | |
117 // getter > 0x3e | |
118 // renaming setter | 0x7c | |
119 // renaming both } 0x7d | |
120 // renaming getter ~ 0x7e | |
121 const SUFFIX_MASK = 0x3f; | |
122 const FIRST_SUFFIX_CODE = 0x3c; | |
123 const SETTER_CODE = 0x3c; | |
124 const GETTER_SETTER_CODE = 0x3d; | |
125 const GETTER_CODE = 0x3e; | |
126 const RENAMING_FLAG = 0x40; | |
127 String needsGetterCode(String variable) => '($variable & 3) > 0'; | |
128 String needsSetterCode(String variable) => '($variable & 2) == 0'; | |
129 String isRenaming(String variable) => '($variable & $RENAMING_FLAG) != 0'; | |
130 | 113 |
131 String get generateGetterSetterFunction { | 114 String get generateGetterSetterFunction { |
132 return """ | 115 return """ |
133 function(field, prototype) { | 116 function(field, prototype) { |
134 var len = field.length; | 117 var len = field.length; |
135 var lastCharCode = field.charCodeAt(len - 1); | 118 var lastChar = field[len - 1]; |
136 var needsAccessor = (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE; | 119 var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTE
R_SUFFIX'; |
137 if (needsAccessor) { | 120 var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTE
R_SUFFIX'; |
138 var needsGetter = ${needsGetterCode('lastCharCode')}; | 121 if (needsGetter || needsSetter) field = field.substring(0, len - 1); |
139 var needsSetter = ${needsSetterCode('lastCharCode')}; | 122 if (needsGetter) { |
140 var renaming = ${isRenaming('lastCharCode')}; | 123 var getterString = "return this." + field + ";"; |
141 var accessorName = field = field.substring(0, len - 1); | 124 """ |
142 if (renaming) { | 125 /* The supportsProtoCheck below depends on the getter/setter convention. |
143 var divider = field.indexOf(":"); | 126 When changing here, update the protoCheck too. */ |
144 accessorName = field.substring(0, divider); | 127 """ |
145 field = field.substring(divider + 1); | 128 prototype["get\$" + field] = new Function(getterString); |
146 } | 129 } |
147 if (needsGetter) { | 130 if (needsSetter) { |
148 var getterString = "return this." + field + ";"; | 131 var setterString = "this." + field + " = v;"; |
149 prototype["get\$" + accessorName] = new Function(getterString); | 132 prototype["set\$" + field] = new Function("v", setterString); |
150 } | |
151 if (needsSetter) { | |
152 var setterString = "this." + field + " = v;"; | |
153 prototype["set\$" + accessorName] = new Function("v", setterString); | |
154 } | |
155 } | 133 } |
156 return field; | 134 return field; |
157 }"""; | 135 }"""; |
158 } | 136 } |
159 | 137 |
160 String get defineClassFunction { | 138 String get defineClassFunction { |
161 // First the class name, then the super class name, followed by the fields | 139 // First the class name, then the super class name, followed by the fields |
162 // (in an array) and the members (inside an Object literal). | 140 // (in an array) and the members (inside an Object literal). |
163 // The caller can also pass in the constructor as a function if needed. | 141 // The caller can also pass in the constructor as a function if needed. |
164 // | 142 // |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). | 184 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). |
207 // If the browser does not support __proto__ we need to instantiate an | 185 // If the browser does not support __proto__ we need to instantiate an |
208 // object with the correct (internal) prototype set up correctly, and then | 186 // object with the correct (internal) prototype set up correctly, and then |
209 // copy the members. | 187 // copy the members. |
210 | 188 |
211 return ''' | 189 return ''' |
212 var $supportsProtoName = false; | 190 var $supportsProtoName = false; |
213 var tmp = $defineClassName('c', ['f?'], {}).prototype; | 191 var tmp = $defineClassName('c', ['f?'], {}).prototype; |
214 if (tmp.__proto__) { | 192 if (tmp.__proto__) { |
215 tmp.__proto__ = {}; | 193 tmp.__proto__ = {}; |
216 if (typeof tmp.get\$f !== 'undefined') $supportsProtoName = true; | 194 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true; |
217 } | 195 } |
218 '''; | 196 '''; |
219 } | 197 } |
220 | 198 |
221 String get finishClassesFunction { | 199 String get finishClassesFunction { |
222 // 'defineClass' does not require the classes to be constructed in order. | 200 // 'defineClass' does not require the classes to be constructed in order. |
223 // Classes are initially just stored in the 'pendingClasses' field. | 201 // Classes are initially just stored in the 'pendingClasses' field. |
224 // 'finishClasses' takes all pending classes and sets up the prototype. | 202 // 'finishClasses' takes all pending classes and sets up the prototype. |
225 // Once set up, the constructors prototype field satisfy: | 203 // Once set up, the constructors prototype field satisfy: |
226 // - it contains all (local) members. | 204 // - it contains all (local) members. |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); | 511 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); |
534 // (4) No stub generated, call is direct. | 512 // (4) No stub generated, call is direct. |
535 // (5) No stub generated, call is direct. | 513 // (5) No stub generated, call is direct. |
536 | 514 |
537 // Keep a cache of which stubs have already been generated, to | 515 // Keep a cache of which stubs have already been generated, to |
538 // avoid duplicates. Note that even if selectors are | 516 // avoid duplicates. Note that even if selectors are |
539 // canonicalized, we would still need this cache: a typed selector | 517 // canonicalized, we would still need this cache: a typed selector |
540 // on A and a typed selector on B could yield the same stub. | 518 // on A and a typed selector on B could yield the same stub. |
541 Set<String> generatedStubNames = new Set<String>(); | 519 Set<String> generatedStubNames = new Set<String>(); |
542 if (compiler.enabledFunctionApply | 520 if (compiler.enabledFunctionApply |
543 && member.name == namer.CLOSURE_INVOCATION_NAME) { | 521 && member.name == Namer.CLOSURE_INVOCATION_NAME) { |
544 // If [Function.apply] is called, we pessimistically compile all | 522 // If [Function.apply] is called, we pessimistically compile all |
545 // possible stubs for this closure. | 523 // possible stubs for this closure. |
546 FunctionSignature signature = member.computeSignature(compiler); | 524 FunctionSignature signature = member.computeSignature(compiler); |
547 Set<Selector> selectors = signature.optionalParametersAreNamed | 525 Set<Selector> selectors = signature.optionalParametersAreNamed |
548 ? computeNamedSelectors(signature, member) | 526 ? computeNamedSelectors(signature, member) |
549 : computeOptionalSelectors(signature, member); | 527 : computeOptionalSelectors(signature, member); |
550 for (Selector selector in selectors) { | 528 for (Selector selector in selectors) { |
551 addParameterStub( | 529 addParameterStub( |
552 member, selector, defineInstanceMember, generatedStubNames); | 530 member, selector, defineInstanceMember, generatedStubNames); |
553 } | 531 } |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 } | 710 } |
733 | 711 |
734 /** | 712 /** |
735 * Documentation wanted -- johnniwinther | 713 * Documentation wanted -- johnniwinther |
736 * | 714 * |
737 * Invariant: [classElement] must be a declaration element. | 715 * Invariant: [classElement] must be a declaration element. |
738 */ | 716 */ |
739 void visitClassFields(ClassElement classElement, | 717 void visitClassFields(ClassElement classElement, |
740 void addField(Element member, | 718 void addField(Element member, |
741 String name, | 719 String name, |
742 String accessorName, | |
743 bool needsGetter, | 720 bool needsGetter, |
744 bool needsSetter, | 721 bool needsSetter, |
745 bool needsCheckedSetter)) { | 722 bool needsCheckedSetter)) { |
746 assert(invariant(classElement, classElement.isDeclaration)); | 723 assert(invariant(classElement, classElement.isDeclaration)); |
747 // If the class is never instantiated we still need to set it up for | 724 // If the class is never instantiated we still need to set it up for |
748 // inheritance purposes, but we can simplify its JavaScript constructor. | 725 // inheritance purposes, but we can simplify its JavaScript constructor. |
749 bool isInstantiated = | 726 bool isInstantiated = |
750 compiler.codegenWorld.instantiatedClasses.contains(classElement); | 727 compiler.codegenWorld.instantiatedClasses.contains(classElement); |
751 | 728 |
752 void visitField(ClassElement enclosingClass, Element member) { | 729 void visitField(ClassElement enclosingClass, Element member) { |
(...skipping 15 matching lines...) Expand all Loading... |
768 if (identical(enclosingClass, classElement)) { | 745 if (identical(enclosingClass, classElement)) { |
769 needsGetter = instanceFieldNeedsGetter(member); | 746 needsGetter = instanceFieldNeedsGetter(member); |
770 needsSetter = instanceFieldNeedsSetter(member); | 747 needsSetter = instanceFieldNeedsSetter(member); |
771 } else { | 748 } else { |
772 isShadowed = classElement.isShadowedByField(member); | 749 isShadowed = classElement.isShadowedByField(member); |
773 } | 750 } |
774 | 751 |
775 if ((isInstantiated && !enclosingClass.isNative()) | 752 if ((isInstantiated && !enclosingClass.isNative()) |
776 || needsGetter | 753 || needsGetter |
777 || needsSetter) { | 754 || needsSetter) { |
778 String accessorName = isShadowed | 755 String fieldName = isShadowed |
779 ? namer.shadowedFieldName(member) | 756 ? namer.shadowedFieldName(member) |
780 : namer.getName(member); | 757 : namer.getName(member); |
781 String fieldName = enclosingClass.isNative() ? | |
782 member.name.slowToString() : accessorName; | |
783 bool needsCheckedSetter = false; | 758 bool needsCheckedSetter = false; |
784 if (needsSetter && compiler.enableTypeAssertions | 759 if (needsSetter && compiler.enableTypeAssertions |
785 && canGenerateCheckedSetter(member)) { | 760 && canGenerateCheckedSetter(member)) { |
786 needsCheckedSetter = true; | 761 needsCheckedSetter = true; |
787 needsSetter = false; | 762 needsSetter = false; |
788 } | 763 } |
789 // Getters and setters with suffixes will be generated dynamically. | 764 // Getters and setters with suffixes will be generated dynamically. |
790 addField(member, | 765 addField(member, |
791 fieldName, | 766 fieldName, |
792 accessorName, | |
793 needsGetter, | 767 needsGetter, |
794 needsSetter, | 768 needsSetter, |
795 needsCheckedSetter); | 769 needsCheckedSetter); |
796 } | 770 } |
797 } | 771 } |
798 | 772 |
799 // If a class is not instantiated then we add the field just so we can | 773 // If a class is not instantiated then we add the field just so we can |
800 // generate the field getter/setter dynamically. Since this is only | 774 // generate the field getter/setter dynamically. Since this is only |
801 // allowed on fields that are in [classElement] we don't need to visit | 775 // allowed on fields that are in [classElement] we don't need to visit |
802 // superclasses for non-instantiated classes. | 776 // superclasses for non-instantiated classes. |
803 classElement.implementation.forEachInstanceField( | 777 classElement.implementation.forEachInstanceField( |
804 visitField, | 778 visitField, |
805 includeBackendMembers: true, | 779 includeBackendMembers: true, |
806 includeSuperMembers: isInstantiated && !classElement.isNative()); | 780 includeSuperMembers: isInstantiated && !classElement.isNative()); |
807 } | 781 } |
808 | 782 |
809 void generateGetter(Element member, String fieldName, String accessorName, | 783 void generateGetter(Element member, String fieldName, CodeBuffer buffer) { |
810 CodeBuffer buffer) { | 784 String getterName = namer.getterName(member.getLibrary(), member.name); |
811 String getterName = | |
812 namer.getterName(member.getLibrary(), new SourceString(accessorName)); | |
813 buffer.add("$getterName: function() { return this.$fieldName; }"); | 785 buffer.add("$getterName: function() { return this.$fieldName; }"); |
814 } | 786 } |
815 | 787 |
816 void generateSetter(Element member, String fieldName, String accessorName, | 788 void generateSetter(Element member, String fieldName, CodeBuffer buffer) { |
817 CodeBuffer buffer) { | 789 String setterName = namer.setterName(member.getLibrary(), member.name); |
818 String setterName = | |
819 namer.setterName(member.getLibrary(), new SourceString(accessorName)); | |
820 buffer.add("$setterName: function(v) { this.$fieldName = v; }"); | 790 buffer.add("$setterName: function(v) { this.$fieldName = v; }"); |
821 } | 791 } |
822 | 792 |
823 bool canGenerateCheckedSetter(Element member) { | 793 bool canGenerateCheckedSetter(Element member) { |
824 DartType type = member.computeType(compiler); | 794 DartType type = member.computeType(compiler); |
825 if (type.element.isTypeVariable() | 795 if (type.element.isTypeVariable() |
826 || type.element == compiler.dynamicClass | 796 || type.element == compiler.dynamicClass |
827 || type.element == compiler.objectClass) { | 797 || type.element == compiler.objectClass) { |
828 // TODO(ngeoffray): Support type checks on type parameters. | 798 // TODO(ngeoffray): Support type checks on type parameters. |
829 return false; | 799 return false; |
830 } | 800 } |
831 return true; | 801 return true; |
832 } | 802 } |
833 | 803 |
834 void generateCheckedSetter(Element member, | 804 void generateCheckedSetter(Element member, |
835 String fieldName, | 805 String fieldName, |
836 String accessorName, | |
837 CodeBuffer buffer) { | 806 CodeBuffer buffer) { |
838 assert(canGenerateCheckedSetter(member)); | 807 assert(canGenerateCheckedSetter(member)); |
839 DartType type = member.computeType(compiler); | 808 DartType type = member.computeType(compiler); |
840 SourceString helper = compiler.backend.getCheckedModeHelper(type); | 809 SourceString helper = compiler.backend.getCheckedModeHelper(type); |
841 FunctionElement helperElement = compiler.findHelper(helper); | 810 FunctionElement helperElement = compiler.findHelper(helper); |
842 String helperName = namer.isolateAccess(helperElement); | 811 String helperName = namer.isolateAccess(helperElement); |
843 String additionalArgument = ''; | 812 String additionalArgument = ''; |
844 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 813 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
845 additionalArgument = ", '${namer.operatorIs(type.element)}'"; | 814 additionalArgument = ", '${namer.operatorIs(type.element)}'"; |
846 } | 815 } |
847 String setterName = | 816 String setterName = namer.setterName(member.getLibrary(), member.name); |
848 namer.publicSetterName(new SourceString(accessorName)); | |
849 buffer.add("$setterName: function(v) { " | 817 buffer.add("$setterName: function(v) { " |
850 "this.$fieldName = $helperName(v$additionalArgument); }"); | 818 "this.$fieldName = $helperName(v$additionalArgument); }"); |
851 } | 819 } |
852 | 820 |
853 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 821 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { |
854 /* Do nothing. */ | 822 /* Do nothing. */ |
855 } | 823 } |
856 | 824 |
857 void emitClassFields(ClassElement classElement, | 825 void emitClassFields(ClassElement classElement, |
858 CodeBuffer buffer, | 826 CodeBuffer buffer, |
859 bool emitEndingComma) { | 827 bool emitEndingComma) { |
860 bool isFirstField = true; | 828 bool isFirstField = true; |
861 visitClassFields(classElement, (Element member, | 829 visitClassFields(classElement, (Element member, |
862 String name, | 830 String name, |
863 String accessorName, | |
864 bool needsGetter, | 831 bool needsGetter, |
865 bool needsSetter, | 832 bool needsSetter, |
866 bool needsCheckedSetter) { | 833 bool needsCheckedSetter) { |
867 if (isFirstField) { | 834 if (isFirstField) { |
868 buffer.add('"": ['); | 835 buffer.add('"": ['); |
869 isFirstField = false; | 836 isFirstField = false; |
870 } else { | 837 } else { |
871 buffer.add(", "); | 838 buffer.add(", "); |
872 } | 839 } |
873 buffer.add('"$accessorName'); | 840 buffer.add('"$name'); |
874 int flag = 0; | |
875 if (name != accessorName) { | |
876 buffer.add(':$name'); | |
877 assert(needsGetter || needsSetter); | |
878 flag = RENAMING_FLAG; | |
879 } | |
880 if (needsGetter && needsSetter) { | 841 if (needsGetter && needsSetter) { |
881 buffer.addCharCode(GETTER_SETTER_CODE + flag); | 842 buffer.add(GETTER_SETTER_SUFFIX); |
882 } else if (needsGetter) { | 843 } else if (needsGetter) { |
883 buffer.addCharCode(GETTER_CODE + flag); | 844 buffer.add(GETTER_SUFFIX); |
884 } else if (needsSetter) { | 845 } else if (needsSetter) { |
885 buffer.addCharCode(SETTER_CODE + flag); | 846 buffer.add(SETTER_SUFFIX); |
886 } | 847 } |
887 buffer.add('"'); | 848 buffer.add('"'); |
888 }); | 849 }); |
889 if (!isFirstField) { | 850 if (!isFirstField) { |
890 // There was at least one field. | 851 // There was at least one field. |
891 buffer.add(']'); | 852 buffer.add(']'); |
892 if (emitEndingComma) { | 853 if (emitEndingComma) { |
893 buffer.add(','); | 854 buffer.add(','); |
894 } | 855 } |
895 } | 856 } |
896 } | 857 } |
897 | 858 |
898 /** Each getter/setter must be prefixed with a ",\n ". */ | 859 /** Each getter/setter must be prefixed with a ",\n ". */ |
899 void emitClassGettersSetters(ClassElement classElement, | 860 void emitClassGettersSetters(ClassElement classElement, |
900 CodeBuffer buffer, | 861 CodeBuffer buffer, |
901 bool emitLeadingComma) { | 862 bool emitLeadingComma) { |
902 visitClassFields(classElement, (Element member, | 863 visitClassFields(classElement, (Element member, |
903 String name, | 864 String name, |
904 String accessorName, | |
905 bool needsGetter, | 865 bool needsGetter, |
906 bool needsSetter, | 866 bool needsSetter, |
907 bool needsCheckedSetter) { | 867 bool needsCheckedSetter) { |
908 if (needsCheckedSetter) { | 868 if (needsCheckedSetter) { |
909 assert(!needsSetter); | 869 assert(!needsSetter); |
910 if (emitLeadingComma) { | 870 if (emitLeadingComma) { |
911 buffer.add(",\n "); | 871 buffer.add(",\n "); |
912 } else { | 872 } else { |
913 emitLeadingComma = true; | 873 emitLeadingComma = true; |
914 } | 874 } |
915 generateCheckedSetter(member, name, accessorName, buffer); | 875 generateCheckedSetter(member, name, buffer); |
916 } | 876 } |
917 }); | 877 }); |
918 } | 878 } |
919 | 879 |
920 /** | 880 /** |
921 * Documentation wanted -- johnniwinther | 881 * Documentation wanted -- johnniwinther |
922 * | 882 * |
923 * Invariant: [classElement] must be a declaration element. | 883 * Invariant: [classElement] must be a declaration element. |
924 */ | 884 */ |
925 void generateClass(ClassElement classElement, CodeBuffer buffer) { | 885 void generateClass(ClassElement classElement, CodeBuffer buffer) { |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1131 | 1091 |
1132 void emitStaticFunctionGetters(CodeBuffer buffer) { | 1092 void emitStaticFunctionGetters(CodeBuffer buffer) { |
1133 Set<FunctionElement> functionsNeedingGetter = | 1093 Set<FunctionElement> functionsNeedingGetter = |
1134 compiler.codegenWorld.staticFunctionsNeedingGetter; | 1094 compiler.codegenWorld.staticFunctionsNeedingGetter; |
1135 for (FunctionElement element in functionsNeedingGetter) { | 1095 for (FunctionElement element in functionsNeedingGetter) { |
1136 // The static function does not have the correct name. Since | 1096 // The static function does not have the correct name. Since |
1137 // [addParameterStubs] use the name to create its stubs we simply | 1097 // [addParameterStubs] use the name to create its stubs we simply |
1138 // create a fake element with the correct name. | 1098 // create a fake element with the correct name. |
1139 // Note: the callElement will not have any enclosingElement. | 1099 // Note: the callElement will not have any enclosingElement. |
1140 FunctionElement callElement = | 1100 FunctionElement callElement = |
1141 new ClosureInvocationElement(namer.CLOSURE_INVOCATION_NAME, element); | 1101 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); |
1142 String staticName = namer.getName(element); | 1102 String staticName = namer.getName(element); |
1143 String invocationName = namer.instanceMethodName(callElement); | 1103 String invocationName = namer.instanceMethodName(callElement); |
1144 String fieldAccess = '$isolateProperties.$staticName'; | 1104 String fieldAccess = '$isolateProperties.$staticName'; |
1145 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 1105 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); |
1146 addParameterStubs(callElement, (String name, CodeBuffer value) { | 1106 addParameterStubs(callElement, (String name, CodeBuffer value) { |
1147 buffer.add('$fieldAccess.$name = $value;\n'); | 1107 buffer.add('$fieldAccess.$name = $value;\n'); |
1148 }); | 1108 }); |
1149 // If a static function is used as a closure we need to add its name | 1109 // If a static function is used as a closure we need to add its name |
1150 // in case it is used in spawnFunction. | 1110 // in case it is used in spawnFunction. |
1151 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1111 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 | 1189 |
1230 // Define the constructor with a name so that Object.toString can | 1190 // Define the constructor with a name so that Object.toString can |
1231 // find the class name of the closure class. | 1191 // find the class name of the closure class. |
1232 emitBoundClosureClassHeader( | 1192 emitBoundClosureClassHeader( |
1233 mangledName, superName, extraArgWithoutComma, boundClosureBuffer); | 1193 mangledName, superName, extraArgWithoutComma, boundClosureBuffer); |
1234 // Now add the methods on the closure class. The instance method does not | 1194 // Now add the methods on the closure class. The instance method does not |
1235 // have the correct name. Since [addParameterStubs] use the name to create | 1195 // have the correct name. Since [addParameterStubs] use the name to create |
1236 // its stubs we simply create a fake element with the correct name. | 1196 // its stubs we simply create a fake element with the correct name. |
1237 // Note: the callElement will not have any enclosingElement. | 1197 // Note: the callElement will not have any enclosingElement. |
1238 FunctionElement callElement = | 1198 FunctionElement callElement = |
1239 new ClosureInvocationElement(namer.CLOSURE_INVOCATION_NAME, member); | 1199 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); |
1240 | 1200 |
1241 String invocationName = namer.instanceMethodName(callElement); | 1201 String invocationName = namer.instanceMethodName(callElement); |
1242 List<String> arguments = new List<String>(parameterCount); | 1202 List<String> arguments = new List<String>(parameterCount); |
1243 for (int i = 0; i < parameterCount; i++) { | 1203 for (int i = 0; i < parameterCount; i++) { |
1244 arguments[i] = "p$i"; | 1204 arguments[i] = "p$i"; |
1245 } | 1205 } |
1246 String joinedArgs = Strings.join(arguments, ", "); | 1206 String joinedArgs = Strings.join(arguments, ", "); |
1247 boundClosureBuffer.add( | 1207 boundClosureBuffer.add( |
1248 "$invocationName: function($joinedArgs) {"); | 1208 "$invocationName: function($joinedArgs) {"); |
1249 String callArgs = hasExtraArgument | 1209 String callArgs = hasExtraArgument |
1250 ? joinedArgs.isEmpty | 1210 ? joinedArgs.isEmpty |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; | 1250 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; |
1291 } else { | 1251 } else { |
1292 String name = namer.instanceFieldName(memberLibrary, member.name); | 1252 String name = namer.instanceFieldName(memberLibrary, member.name); |
1293 getter = "this.$name"; | 1253 getter = "this.$name"; |
1294 } | 1254 } |
1295 for (Selector selector in selectors) { | 1255 for (Selector selector in selectors) { |
1296 if (selector.applies(member, compiler)) { | 1256 if (selector.applies(member, compiler)) { |
1297 String invocationName = | 1257 String invocationName = |
1298 namer.instanceMethodInvocationName(memberLibrary, member.name, | 1258 namer.instanceMethodInvocationName(memberLibrary, member.name, |
1299 selector); | 1259 selector); |
1300 SourceString callName = namer.CLOSURE_INVOCATION_NAME; | 1260 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; |
1301 String closureCallName = | 1261 String closureCallName = |
1302 namer.instanceMethodInvocationName(memberLibrary, callName, | 1262 namer.instanceMethodInvocationName(memberLibrary, callName, |
1303 selector); | 1263 selector); |
1304 List<String> arguments = <String>[]; | 1264 List<String> arguments = <String>[]; |
1305 for (int i = 0; i < selector.argumentCount; i++) { | 1265 for (int i = 0; i < selector.argumentCount; i++) { |
1306 arguments.add("arg$i"); | 1266 arguments.add("arg$i"); |
1307 } | 1267 } |
1308 String joined = Strings.join(arguments, ", "); | 1268 String joined = Strings.join(arguments, ", "); |
1309 CodeBuffer getterBuffer = new CodeBuffer(); | 1269 CodeBuffer getterBuffer = new CodeBuffer(); |
1310 getterBuffer.add( | 1270 getterBuffer.add( |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1470 CodeBuffer argNames = new CodeBuffer(); | 1430 CodeBuffer argNames = new CodeBuffer(); |
1471 List<SourceString> names = selector.getOrderedNamedArguments(); | 1431 List<SourceString> names = selector.getOrderedNamedArguments(); |
1472 for (int i = 0; i < names.length; i++) { | 1432 for (int i = 0; i < names.length; i++) { |
1473 if (i != 0) argNames.add(', '); | 1433 if (i != 0) argNames.add(', '); |
1474 argNames.add('"'); | 1434 argNames.add('"'); |
1475 argNames.add(names[i].slowToString()); | 1435 argNames.add(names[i].slowToString()); |
1476 argNames.add('"'); | 1436 argNames.add('"'); |
1477 } | 1437 } |
1478 String internalName = namer.instanceMethodInvocationName( | 1438 String internalName = namer.instanceMethodInvocationName( |
1479 selector.library, new SourceString(methodName), selector); | 1439 selector.library, new SourceString(methodName), selector); |
1480 Element createInvocationMirror = | |
1481 compiler.findHelper(const SourceString('createInvocationMirror')); | |
1482 CodeBuffer buffer = new CodeBuffer(); | 1440 CodeBuffer buffer = new CodeBuffer(); |
1483 buffer.add('function($args) {\n'); | 1441 buffer.add('function($args) {\n'); |
1484 buffer.add(' return this.$noSuchMethodName(' | 1442 buffer.add(' return this.$noSuchMethodName(' |
1485 '${namer.isolateAccess(createInvocationMirror)}(' | 1443 '\$.createInvocationMirror("$methodName", "$internalName",' |
1486 '"$methodName", "$internalName",' | 1444 ' $type, [$args], [$argNames]));\n'); |
1487 '$type, [$args], [$argNames]));\n'); | |
1488 buffer.add(' }'); | 1445 buffer.add(' }'); |
1489 return buffer; | 1446 return buffer; |
1490 } | 1447 } |
1491 | 1448 |
1492 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 1449 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
1493 // Cache the object class and type. | 1450 // Cache the object class and type. |
1494 ClassElement objectClass = compiler.objectClass; | 1451 ClassElement objectClass = compiler.objectClass; |
1495 DartType objectType = objectClass.computeType(compiler); | 1452 DartType objectType = objectClass.computeType(compiler); |
1496 | 1453 |
1497 for (Selector selector in selectors) { | 1454 for (Selector selector in selectors) { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1650 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); | 1607 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); |
1651 mainCall = buildIsolateSetup(buffer, main, isolateMain); | 1608 mainCall = buildIsolateSetup(buffer, main, isolateMain); |
1652 } else { | 1609 } else { |
1653 mainCall = '${namer.isolateAccess(main)}()'; | 1610 mainCall = '${namer.isolateAccess(main)}()'; |
1654 } | 1611 } |
1655 buffer.add(""" | 1612 buffer.add(""" |
1656 | 1613 |
1657 // | 1614 // |
1658 // BEGIN invoke [main]. | 1615 // BEGIN invoke [main]. |
1659 // | 1616 // |
1660 if (typeof document !== 'undefined' && document.readyState != 'complete') { | 1617 if (typeof document != 'undefined' && document.readyState != 'complete') { |
1661 document.addEventListener('readystatechange', function () { | 1618 document.addEventListener('readystatechange', function () { |
1662 if (document.readyState == 'complete') { | 1619 if (document.readyState == 'complete') { |
1663 if (typeof dartMainRunner === 'function') { | 1620 if (typeof dartMainRunner == 'function') { |
1664 dartMainRunner(function() { ${mainCall}; }); | 1621 dartMainRunner(function() { ${mainCall}; }); |
1665 } else { | 1622 } else { |
1666 ${mainCall}; | 1623 ${mainCall}; |
1667 } | 1624 } |
1668 } | 1625 } |
1669 }, false); | 1626 }, false); |
1670 } else { | 1627 } else { |
1671 if (typeof dartMainRunner === 'function') { | 1628 if (typeof dartMainRunner == 'function') { |
1672 dartMainRunner(function() { ${mainCall}; }); | 1629 dartMainRunner(function() { ${mainCall}; }); |
1673 } else { | 1630 } else { |
1674 ${mainCall}; | 1631 ${mainCall}; |
1675 } | 1632 } |
1676 } | 1633 } |
1677 // | 1634 // |
1678 // END invoke [main]. | 1635 // END invoke [main]. |
1679 // | 1636 // |
1680 | 1637 |
1681 """); | 1638 """); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1756 const String HOOKS_API_USAGE = """ | 1713 const String HOOKS_API_USAGE = """ |
1757 // Generated by dart2js, the Dart to JavaScript compiler. | 1714 // Generated by dart2js, the Dart to JavaScript compiler. |
1758 // The code supports the following hooks: | 1715 // The code supports the following hooks: |
1759 // dartPrint(message) - if this function is defined it is called | 1716 // dartPrint(message) - if this function is defined it is called |
1760 // instead of the Dart [print] method. | 1717 // instead of the Dart [print] method. |
1761 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1718 // dartMainRunner(main) - if this function is defined, the Dart [main] |
1762 // method will not be invoked directly. | 1719 // method will not be invoked directly. |
1763 // Instead, a closure that will invoke [main] is | 1720 // Instead, a closure that will invoke [main] is |
1764 // passed to [dartMainRunner]. | 1721 // passed to [dartMainRunner]. |
1765 """; | 1722 """; |
OLD | NEW |