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