| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 85     return constantEmitter.reference(value); | 85     return constantEmitter.reference(value); | 
| 86   } | 86   } | 
| 87 | 87 | 
| 88   js.Expression constantInitializerExpression(Constant value) { | 88   js.Expression constantInitializerExpression(Constant value) { | 
| 89     return constantEmitter.initializationExpression(value); | 89     return constantEmitter.initializationExpression(value); | 
| 90   } | 90   } | 
| 91 | 91 | 
| 92   String get name => 'CodeEmitter'; | 92   String get name => 'CodeEmitter'; | 
| 93 | 93 | 
| 94   String get defineClassName | 94   String get defineClassName | 
| 95       => '${namer.ISOLATE}.\$defineClass'; | 95       => '${namer.isolateName}.\$defineClass'; | 
| 96   String get currentGenerateAccessorName | 96   String get currentGenerateAccessorName | 
| 97       => '${namer.CURRENT_ISOLATE}.\$generateAccessor'; | 97       => '${namer.CURRENT_ISOLATE}.\$generateAccessor'; | 
| 98   String get generateAccessorHolder | 98   String get generateAccessorHolder | 
| 99       => '$isolatePropertiesName.\$generateAccessor'; | 99       => '$isolatePropertiesName.\$generateAccessor'; | 
| 100   String get finishClassesName | 100   String get finishClassesName | 
| 101       => '${namer.ISOLATE}.\$finishClasses'; | 101       => '${namer.isolateName}.\$finishClasses'; | 
| 102   String get finishIsolateConstructorName | 102   String get finishIsolateConstructorName | 
| 103       => '${namer.ISOLATE}.\$finishIsolateConstructor'; | 103       => '${namer.isolateName}.\$finishIsolateConstructor'; | 
| 104   String get pendingClassesName | 104   String get pendingClassesName | 
| 105       => '${namer.ISOLATE}.\$pendingClasses'; | 105       => '${namer.isolateName}.\$pendingClasses'; | 
| 106   String get isolatePropertiesName | 106   String get isolatePropertiesName | 
| 107       => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; | 107       => '${namer.isolateName}.${namer.isolatePropertiesName}'; | 
| 108   String get supportsProtoName | 108   String get supportsProtoName | 
| 109       => 'supportsProto'; | 109       => 'supportsProto'; | 
| 110   String get lazyInitializerName | 110   String get lazyInitializerName | 
| 111       => '${namer.ISOLATE}.\$lazy'; | 111       => '${namer.isolateName}.\$lazy'; | 
| 112 | 112 | 
| 113   final String GETTER_SUFFIX = "?"; | 113   // Property name suffixes.  If the accessors are renaming then the format | 
| 114   final String SETTER_SUFFIX = "!"; | 114   // is <accessorName>:<fieldName><suffix>.  We use the suffix to know whether | 
| 115   final String GETTER_SETTER_SUFFIX = "="; | 115   // to look for the ':' separator in order to avoid doing the indexOf operation | 
|  | 116   // on every single property (they are quite rare).  None of these characters | 
|  | 117   // are legal in an identifier and they are related by bit patterns. | 
|  | 118   // setter          <          0x3c | 
|  | 119   // both            =          0x3d | 
|  | 120   // getter          >          0x3e | 
|  | 121   // renaming setter |          0x7c | 
|  | 122   // renaming both   }          0x7d | 
|  | 123   // renaming getter ~          0x7e | 
|  | 124   const SUFFIX_MASK = 0x3f; | 
|  | 125   const FIRST_SUFFIX_CODE = 0x3c; | 
|  | 126   const SETTER_CODE = 0x3c; | 
|  | 127   const GETTER_SETTER_CODE = 0x3d; | 
|  | 128   const GETTER_CODE = 0x3e; | 
|  | 129   const RENAMING_FLAG = 0x40; | 
|  | 130   String needsGetterCode(String variable) => '($variable & 3) > 0'; | 
|  | 131   String needsSetterCode(String variable) => '($variable & 2) == 0'; | 
|  | 132   String isRenaming(String variable) => '($variable & $RENAMING_FLAG) != 0'; | 
| 116 | 133 | 
| 117   String get generateAccessorFunction { | 134   String get generateAccessorFunction { | 
| 118     return """ | 135     return """ | 
| 119 function generateAccessor(field, prototype) { | 136 function generateAccessor(field, prototype) { | 
| 120   var len = field.length; | 137   var len = field.length; | 
| 121   var lastChar = field[len - 1]; | 138   var lastCharCode = field.charCodeAt(len - 1); | 
| 122   var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTER_
      SUFFIX'; | 139   var needsAccessor = (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE; | 
| 123   var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTER_
      SUFFIX'; | 140   if (needsAccessor) { | 
| 124   if (needsGetter || needsSetter) field = field.substring(0, len - 1); | 141     var needsGetter = ${needsGetterCode('lastCharCode')}; | 
| 125   if (needsGetter) { | 142     var needsSetter = ${needsSetterCode('lastCharCode')}; | 
| 126     var getterString = "return this." + field + ";"; | 143     var renaming = ${isRenaming('lastCharCode')}; | 
| 127 """ | 144     var accessorName = field = field.substring(0, len - 1); | 
| 128   /* The supportsProtoCheck below depends on the getter/setter convention. | 145     if (renaming) { | 
| 129          When changing here, update the protoCheck too. */ | 146       var divider = field.indexOf(":"); | 
| 130   """ | 147       accessorName = field.substring(0, divider); | 
| 131       prototype["get\$" + field] = new Function(getterString); | 148       field = field.substring(divider + 1); | 
|  | 149     } | 
|  | 150     if (needsGetter) { | 
|  | 151       var getterString = "return this." + field + ";"; | 
|  | 152       prototype["get\$" + accessorName] = new Function(getterString); | 
| 132     } | 153     } | 
| 133     if (needsSetter) { | 154     if (needsSetter) { | 
| 134       var setterString = "this." + field + " = v;"; | 155       var setterString = "this." + field + " = v;"; | 
| 135       prototype["set\$" + field] = new Function("v", setterString); | 156       prototype["set\$" + accessorName] = new Function("v", setterString); | 
| 136     } | 157     } | 
| 137     return field; | 158   } | 
| 138   }"""; | 159   return field; | 
|  | 160 }"""; | 
| 139   } | 161   } | 
| 140 | 162 | 
| 141   String get defineClassFunction { | 163   String get defineClassFunction { | 
| 142     // First the class name, then the field names in an array and the members | 164     // First the class name, then the field names in an array and the members | 
| 143     // (inside an Object literal). | 165     // (inside an Object literal). | 
| 144     // The caller can also pass in the constructor as a function if needed. | 166     // The caller can also pass in the constructor as a function if needed. | 
| 145     // | 167     // | 
| 146     // Example: | 168     // Example: | 
| 147     // defineClass("A", ["x", "y"], { | 169     // defineClass("A", ["x", "y"], { | 
| 148     //  foo$1: function(y) { | 170     //  foo$1: function(y) { | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 186     // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). | 208     // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). | 
| 187     // If the browser does not support __proto__ we need to instantiate an | 209     // If the browser does not support __proto__ we need to instantiate an | 
| 188     // object with the correct (internal) prototype set up correctly, and then | 210     // object with the correct (internal) prototype set up correctly, and then | 
| 189     // copy the members. | 211     // copy the members. | 
| 190 | 212 | 
| 191     return ''' | 213     return ''' | 
| 192 var $supportsProtoName = false; | 214 var $supportsProtoName = false; | 
| 193 var tmp = $defineClassName('c', ['f?'], {}).prototype; | 215 var tmp = $defineClassName('c', ['f?'], {}).prototype; | 
| 194 if (tmp.__proto__) { | 216 if (tmp.__proto__) { | 
| 195   tmp.__proto__ = {}; | 217   tmp.__proto__ = {}; | 
| 196   if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true; | 218   if (typeof tmp.get\$f !== 'undefined') $supportsProtoName = true; | 
| 197 } | 219 } | 
| 198 '''; | 220 '''; | 
| 199   } | 221   } | 
| 200 | 222 | 
| 201   String get finishClassesFunction { | 223   String get finishClassesFunction { | 
| 202     // 'defineClass' does not require the classes to be constructed in order. | 224     // 'defineClass' does not require the classes to be constructed in order. | 
| 203     // Classes are initially just stored in the 'pendingClasses' field. | 225     // Classes are initially just stored in the 'pendingClasses' field. | 
| 204     // 'finishClasses' takes all pending classes and sets up the prototype. | 226     // 'finishClasses' takes all pending classes and sets up the prototype. | 
| 205     // Once set up, the constructors prototype field satisfy: | 227     // Once set up, the constructors prototype field satisfy: | 
| 206     //  - it contains all (local) members. | 228     //  - it contains all (local) members. | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 265           newPrototype[member] = prototype[member]; | 287           newPrototype[member] = prototype[member]; | 
| 266         } | 288         } | 
| 267       } | 289       } | 
| 268     } | 290     } | 
| 269   } | 291   } | 
| 270   for (var cls in pendingClasses) finishClass(cls); | 292   for (var cls in pendingClasses) finishClass(cls); | 
| 271 }'''; | 293 }'''; | 
| 272   } | 294   } | 
| 273 | 295 | 
| 274   String get finishIsolateConstructorFunction { | 296   String get finishIsolateConstructorFunction { | 
| 275     String isolate = namer.ISOLATE; | 297     String isolate = namer.isolateName; | 
| 276     // We replace the old Isolate function with a new one that initializes | 298     // We replace the old Isolate function with a new one that initializes | 
| 277     // all its field with the initial (and often final) value of all globals. | 299     // all its field with the initial (and often final) value of all globals. | 
| 278     // This has two advantages: | 300     // This has two advantages: | 
| 279     //   1. the properties are in the object itself (thus avoiding to go through | 301     //   1. the properties are in the object itself (thus avoiding to go through | 
| 280     //      the prototype when looking up globals. | 302     //      the prototype when looking up globals. | 
| 281     //   2. a new isolate goes through a (usually well optimized) constructor | 303     //   2. a new isolate goes through a (usually well optimized) constructor | 
| 282     //      function of the form: "function() { this.x = ...; this.y = ...; }". | 304     //      function of the form: "function() { this.x = ...; this.y = ...; }". | 
| 283     // | 305     // | 
| 284     // Example: If [isolateProperties] is an object containing: x = 3 and | 306     // Example: If [isolateProperties] is an object containing: x = 3 and | 
| 285     // A = function A() { /* constructor of class A. */ }, then we generate: | 307     // A = function A() { /* constructor of class A. */ }, then we generate: | 
| 286     // str = "{ | 308     // str = "{ | 
| 287     //   var isolateProperties = Isolate.$isolateProperties; | 309     //   var isolateProperties = Isolate.$isolateProperties; | 
| 288     //   this.x = isolateProperties.x; | 310     //   this.x = isolateProperties.x; | 
| 289     //   this.A = isolateProperties.A; | 311     //   this.A = isolateProperties.A; | 
| 290     // }"; | 312     // }"; | 
| 291     // which is then dynamically evaluated: | 313     // which is then dynamically evaluated: | 
| 292     //   var newIsolate = new Function(str); | 314     //   var newIsolate = new Function(str); | 
| 293     // | 315     // | 
| 294     // We also copy over old values like the prototype, and the | 316     // We also copy over old values like the prototype, and the | 
| 295     // isolateProperties themselves. | 317     // isolateProperties themselves. | 
| 296     return """function(oldIsolate) { | 318     return """function(oldIsolate) { | 
| 297   var isolateProperties = oldIsolate.${namer.ISOLATE_PROPERTIES}; | 319   var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; | 
| 298   var isolatePrototype = oldIsolate.prototype; | 320   var isolatePrototype = oldIsolate.prototype; | 
| 299   var str = "{\\n"; | 321   var str = "{\\n"; | 
| 300   str += "var properties = $isolate.${namer.ISOLATE_PROPERTIES};\\n"; | 322   str += "var properties = $isolate.${namer.isolatePropertiesName};\\n"; | 
| 301   for (var staticName in isolateProperties) { | 323   for (var staticName in isolateProperties) { | 
| 302     if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) { | 324     if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) { | 
| 303       str += "this." + staticName + "= properties." + staticName + ";\\n"; | 325       str += "this." + staticName + "= properties." + staticName + ";\\n"; | 
| 304     } | 326     } | 
| 305   } | 327   } | 
| 306   str += "}\\n"; | 328   str += "}\\n"; | 
| 307   var newIsolate = new Function(str); | 329   var newIsolate = new Function(str); | 
| 308   newIsolate.prototype = isolatePrototype; | 330   newIsolate.prototype = isolatePrototype; | 
| 309   isolatePrototype.constructor = newIsolate; | 331   isolatePrototype.constructor = newIsolate; | 
| 310   newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; | 332   newIsolate.${namer.isolatePropertiesName} = isolateProperties; | 
| 311   return newIsolate; | 333   return newIsolate; | 
| 312 }"""; | 334 }"""; | 
| 313   } | 335   } | 
| 314 | 336 | 
| 315   String get lazyInitializerFunction { | 337   String get lazyInitializerFunction { | 
| 316     String isolate = namer.CURRENT_ISOLATE; | 338     String isolate = namer.CURRENT_ISOLATE; | 
| 317     return """ | 339     return """ | 
| 318 function(prototype, staticName, fieldName, getterName, lazyValue) { | 340 function(prototype, staticName, fieldName, getterName, lazyValue) { | 
| 319   var getter = new Function("{ return $isolate." + fieldName + ";}"); | 341   var getter = new Function("{ return $isolate." + fieldName + ";}"); | 
| 320 $lazyInitializerLogic | 342 $lazyInitializerLogic | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 371     } | 393     } | 
| 372   } | 394   } | 
| 373 | 395 | 
| 374   void emitFinishIsolateConstructor(CodeBuffer buffer) { | 396   void emitFinishIsolateConstructor(CodeBuffer buffer) { | 
| 375     String name = finishIsolateConstructorName; | 397     String name = finishIsolateConstructorName; | 
| 376     String value = finishIsolateConstructorFunction; | 398     String value = finishIsolateConstructorFunction; | 
| 377     buffer.add("$name = $value;\n"); | 399     buffer.add("$name = $value;\n"); | 
| 378   } | 400   } | 
| 379 | 401 | 
| 380   void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 402   void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 
| 381     String isolate = namer.ISOLATE; | 403     String isolate = namer.isolateName; | 
| 382     buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | 404     buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | 
| 383   } | 405   } | 
| 384 | 406 | 
| 385   /** | 407   /** | 
| 386    * Generate stubs to handle invocation of methods with optional | 408    * Generate stubs to handle invocation of methods with optional | 
| 387    * arguments. | 409    * arguments. | 
| 388    * | 410    * | 
| 389    * A method like [: foo([x]) :] may be invoked by the following | 411    * A method like [: foo([x]) :] may be invoked by the following | 
| 390    * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 412    * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 
| 391    * function for detailed examples. | 413    * function for detailed examples. | 
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 527     // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); | 549     // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); | 
| 528     // (4) No stub generated, call is direct. | 550     // (4) No stub generated, call is direct. | 
| 529     // (5) No stub generated, call is direct. | 551     // (5) No stub generated, call is direct. | 
| 530 | 552 | 
| 531     // Keep a cache of which stubs have already been generated, to | 553     // Keep a cache of which stubs have already been generated, to | 
| 532     // avoid duplicates. Note that even if selectors are | 554     // avoid duplicates. Note that even if selectors are | 
| 533     // canonicalized, we would still need this cache: a typed selector | 555     // canonicalized, we would still need this cache: a typed selector | 
| 534     // on A and a typed selector on B could yield the same stub. | 556     // on A and a typed selector on B could yield the same stub. | 
| 535     Set<String> generatedStubNames = new Set<String>(); | 557     Set<String> generatedStubNames = new Set<String>(); | 
| 536     if (compiler.enabledFunctionApply | 558     if (compiler.enabledFunctionApply | 
| 537         && member.name == Namer.CLOSURE_INVOCATION_NAME) { | 559         && member.name == namer.closureInvocationSelectorName) { | 
| 538       // If [Function.apply] is called, we pessimistically compile all | 560       // If [Function.apply] is called, we pessimistically compile all | 
| 539       // possible stubs for this closure. | 561       // possible stubs for this closure. | 
| 540       FunctionSignature signature = member.computeSignature(compiler); | 562       FunctionSignature signature = member.computeSignature(compiler); | 
| 541       Set<Selector> selectors = signature.optionalParametersAreNamed | 563       Set<Selector> selectors = signature.optionalParametersAreNamed | 
| 542           ? computeNamedSelectors(signature, member) | 564           ? computeNamedSelectors(signature, member) | 
| 543           : computeOptionalSelectors(signature, member); | 565           : computeOptionalSelectors(signature, member); | 
| 544       for (Selector selector in selectors) { | 566       for (Selector selector in selectors) { | 
| 545         addParameterStub( | 567         addParameterStub( | 
| 546             member, selector, defineInstanceMember, generatedStubNames); | 568             member, selector, defineInstanceMember, generatedStubNames); | 
| 547       } | 569       } | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 622 | 644 | 
| 623   bool instanceFieldNeedsSetter(Element member) { | 645   bool instanceFieldNeedsSetter(Element member) { | 
| 624     assert(member.isField()); | 646     assert(member.isField()); | 
| 625     return (!member.modifiers.isFinalOrConst()) | 647     return (!member.modifiers.isFinalOrConst()) | 
| 626         && compiler.codegenWorld.hasInvokedSetter(member, compiler); | 648         && compiler.codegenWorld.hasInvokedSetter(member, compiler); | 
| 627   } | 649   } | 
| 628 | 650 | 
| 629   String compiledFieldName(Element member) { | 651   String compiledFieldName(Element member) { | 
| 630     assert(member.isField()); | 652     assert(member.isField()); | 
| 631     return member.isNative() | 653     return member.isNative() | 
| 632         ? member.name.slowToString() | 654         ? member.nativeName() | 
| 633         : namer.getName(member); | 655         : namer.getName(member); | 
| 634   } | 656   } | 
| 635 | 657 | 
| 636   /** | 658   /** | 
| 637    * Documentation wanted -- johnniwinther | 659    * Documentation wanted -- johnniwinther | 
| 638    * | 660    * | 
| 639    * Invariant: [member] must be a declaration element. | 661    * Invariant: [member] must be a declaration element. | 
| 640    */ | 662    */ | 
| 641   void addInstanceMember(Element member, | 663   void addInstanceMember(Element member, | 
| 642                          DefineMemberFunction defineInstanceMember) { | 664                          DefineMemberFunction defineInstanceMember) { | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 726   } | 748   } | 
| 727 | 749 | 
| 728   /** | 750   /** | 
| 729    * Documentation wanted -- johnniwinther | 751    * Documentation wanted -- johnniwinther | 
| 730    * | 752    * | 
| 731    * Invariant: [classElement] must be a declaration element. | 753    * Invariant: [classElement] must be a declaration element. | 
| 732    */ | 754    */ | 
| 733   void visitClassFields(ClassElement classElement, | 755   void visitClassFields(ClassElement classElement, | 
| 734                         void addField(Element member, | 756                         void addField(Element member, | 
| 735                                       String name, | 757                                       String name, | 
|  | 758                                       String accessorName, | 
| 736                                       bool needsGetter, | 759                                       bool needsGetter, | 
| 737                                       bool needsSetter, | 760                                       bool needsSetter, | 
| 738                                       bool needsCheckedSetter)) { | 761                                       bool needsCheckedSetter)) { | 
| 739     assert(invariant(classElement, classElement.isDeclaration)); | 762     assert(invariant(classElement, classElement.isDeclaration)); | 
| 740     // If the class is never instantiated we still need to set it up for | 763     // If the class is never instantiated we still need to set it up for | 
| 741     // inheritance purposes, but we can simplify its JavaScript constructor. | 764     // inheritance purposes, but we can simplify its JavaScript constructor. | 
| 742     bool isInstantiated = | 765     bool isInstantiated = | 
| 743         compiler.codegenWorld.instantiatedClasses.contains(classElement); | 766         compiler.codegenWorld.instantiatedClasses.contains(classElement); | 
| 744 | 767 | 
| 745     void visitField(ClassElement enclosingClass, Element member) { | 768     void visitField(ClassElement enclosingClass, Element member) { | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 775             : accessorName; | 798             : accessorName; | 
| 776         bool needsCheckedSetter = false; | 799         bool needsCheckedSetter = false; | 
| 777         if (needsSetter && compiler.enableTypeAssertions | 800         if (needsSetter && compiler.enableTypeAssertions | 
| 778             && canGenerateCheckedSetter(member)) { | 801             && canGenerateCheckedSetter(member)) { | 
| 779           needsCheckedSetter = true; | 802           needsCheckedSetter = true; | 
| 780           needsSetter = false; | 803           needsSetter = false; | 
| 781         } | 804         } | 
| 782         // Getters and setters with suffixes will be generated dynamically. | 805         // Getters and setters with suffixes will be generated dynamically. | 
| 783         addField(member, | 806         addField(member, | 
| 784                  fieldName, | 807                  fieldName, | 
|  | 808                  accessorName, | 
| 785                  needsGetter, | 809                  needsGetter, | 
| 786                  needsSetter, | 810                  needsSetter, | 
| 787                  needsCheckedSetter); | 811                  needsCheckedSetter); | 
| 788       } | 812       } | 
| 789     } | 813     } | 
| 790 | 814 | 
| 791     // If a class is not instantiated then we add the field just so we can | 815     // If a class is not instantiated then we add the field just so we can | 
| 792     // generate the field getter/setter dynamically. Since this is only | 816     // generate the field getter/setter dynamically. Since this is only | 
| 793     // allowed on fields that are in [classElement] we don't need to visit | 817     // allowed on fields that are in [classElement] we don't need to visit | 
| 794     // superclasses for non-instantiated classes. | 818     // superclasses for non-instantiated classes. | 
| 795     classElement.implementation.forEachInstanceField( | 819     classElement.implementation.forEachInstanceField( | 
| 796         visitField, | 820         visitField, | 
| 797         includeBackendMembers: true, | 821         includeBackendMembers: true, | 
| 798         includeSuperMembers: isInstantiated && !classElement.isNative()); | 822         includeSuperMembers: isInstantiated && !classElement.isNative()); | 
| 799   } | 823   } | 
| 800 | 824 | 
| 801   void generateGetter(Element member, String fieldName, CodeBuffer buffer) { |  | 
| 802     String getterName = namer.getterName(member.getLibrary(), member.name); |  | 
| 803     buffer.add("$getterName: function() { return this.$fieldName; }"); |  | 
| 804   } |  | 
| 805 |  | 
| 806   void generateSetter(Element member, String fieldName, CodeBuffer buffer) { |  | 
| 807     String setterName = namer.setterName(member.getLibrary(), member.name); |  | 
| 808     buffer.add("$setterName: function(v) { this.$fieldName = v; }"); |  | 
| 809   } |  | 
| 810 |  | 
| 811   bool canGenerateCheckedSetter(Element member) { | 825   bool canGenerateCheckedSetter(Element member) { | 
| 812     DartType type = member.computeType(compiler); | 826     DartType type = member.computeType(compiler); | 
| 813     if (type.element.isTypeVariable() | 827     if (type.element.isTypeVariable() | 
| 814         || type.element == compiler.dynamicClass | 828         || type.element == compiler.dynamicClass | 
| 815         || type.element == compiler.objectClass) { | 829         || type.element == compiler.objectClass) { | 
| 816       // TODO(ngeoffray): Support type checks on type parameters. | 830       // TODO(ngeoffray): Support type checks on type parameters. | 
| 817       return false; | 831       return false; | 
| 818     } | 832     } | 
| 819     return true; | 833     return true; | 
| 820   } | 834   } | 
| 821 | 835 | 
| 822   void generateCheckedSetter(Element member, | 836   void generateCheckedSetter(Element member, | 
| 823                              String fieldName, | 837                              String fieldName, | 
|  | 838                              String accessorName, | 
| 824                              CodeBuffer buffer) { | 839                              CodeBuffer buffer) { | 
| 825     assert(canGenerateCheckedSetter(member)); | 840     assert(canGenerateCheckedSetter(member)); | 
| 826     DartType type = member.computeType(compiler); | 841     DartType type = member.computeType(compiler); | 
| 827     SourceString helper = compiler.backend.getCheckedModeHelper(type); | 842     SourceString helper = compiler.backend.getCheckedModeHelper(type); | 
| 828     FunctionElement helperElement = compiler.findHelper(helper); | 843     FunctionElement helperElement = compiler.findHelper(helper); | 
| 829     String helperName = namer.isolateAccess(helperElement); | 844     String helperName = namer.isolateAccess(helperElement); | 
| 830     String additionalArgument = ''; | 845     String additionalArgument = ''; | 
| 831     if (helperElement.computeSignature(compiler).parameterCount != 1) { | 846     if (helperElement.computeSignature(compiler).parameterCount != 1) { | 
| 832       additionalArgument = ", '${namer.operatorIs(type.element)}'"; | 847       additionalArgument = ", '${namer.operatorIs(type.element)}'"; | 
| 833     } | 848     } | 
| 834     String setterName = namer.setterName(member.getLibrary(), member.name); | 849     String setterName = namer.setterNameFromAccessorName(accessorName); | 
| 835     buffer.add("$setterName: function(v) { " | 850     buffer.add("$setterName: function(v) { " | 
| 836         "this.$fieldName = $helperName(v$additionalArgument); }"); | 851         "this.$fieldName = $helperName(v$additionalArgument); }"); | 
| 837   } | 852   } | 
| 838 | 853 | 
| 839   void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 854   void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 
| 840     /* Do nothing. */ | 855     /* Do nothing. */ | 
| 841   } | 856   } | 
| 842 | 857 | 
| 843   void emitSuper(String superName, CodeBuffer buffer) { | 858   void emitSuper(String superName, CodeBuffer buffer) { | 
| 844     /* Do nothing. */ | 859     /* Do nothing. */ | 
| 845   } | 860   } | 
| 846 | 861 | 
| 847   void emitClassFields(ClassElement classElement, | 862   void emitClassFields(ClassElement classElement, | 
| 848                        CodeBuffer buffer, | 863                        CodeBuffer buffer, | 
| 849                        bool emitEndingComma, | 864                        bool emitEndingComma, | 
| 850                        { String superClass: "", | 865                        { String superClass: "", | 
| 851                          bool isNative: false}) { | 866                          bool isNative: false}) { | 
| 852     bool isFirstField = true; | 867     bool isFirstField = true; | 
| 853     bool isAnythingOutput = false; | 868     bool isAnythingOutput = false; | 
| 854     if (!isNative) { | 869     if (!isNative) { | 
| 855       buffer.add('"":"$superClass;'); | 870       buffer.add('"":"$superClass;'); | 
| 856       isAnythingOutput = true; | 871       isAnythingOutput = true; | 
| 857     } | 872     } | 
| 858     visitClassFields(classElement, (Element member, | 873     visitClassFields(classElement, (Element member, | 
| 859                                     String name, | 874                                     String name, | 
|  | 875                                     String accessorName, | 
| 860                                     bool needsGetter, | 876                                     bool needsGetter, | 
| 861                                     bool needsSetter, | 877                                     bool needsSetter, | 
| 862                                     bool needsCheckedSetter) { | 878                                     bool needsCheckedSetter) { | 
| 863       if (!getterAndSetterCanBeImplementedByFieldSpec( |  | 
| 864           member, name, needsGetter, needsSetter)) { |  | 
| 865         return; |  | 
| 866       } |  | 
| 867       if (!isNative || needsCheckedSetter || needsGetter || needsSetter) { | 879       if (!isNative || needsCheckedSetter || needsGetter || needsSetter) { | 
| 868         if (isFirstField) { | 880         if (isFirstField) { | 
| 869           isFirstField = false; | 881           isFirstField = false; | 
| 870           if (!isAnythingOutput) { | 882           if (!isAnythingOutput) { | 
| 871             buffer.add('"":"'); | 883             buffer.add('"":"'); | 
| 872             isAnythingOutput = true; | 884             isAnythingOutput = true; | 
| 873           } | 885           } | 
| 874         } else { | 886         } else { | 
| 875           buffer.add(","); | 887           buffer.add(","); | 
| 876         } | 888         } | 
| 877         buffer.add('$name'); | 889         buffer.add('$accessorName'); | 
|  | 890         int flag = 0; | 
|  | 891         if (name != accessorName) { | 
|  | 892           buffer.add(':$name'); | 
|  | 893           assert(needsGetter || needsSetter); | 
|  | 894           flag = RENAMING_FLAG; | 
|  | 895         } | 
| 878         if (needsGetter && needsSetter) { | 896         if (needsGetter && needsSetter) { | 
| 879           buffer.add(GETTER_SETTER_SUFFIX); | 897           buffer.addCharCode(GETTER_SETTER_CODE + flag); | 
| 880         } else if (needsGetter) { | 898         } else if (needsGetter) { | 
| 881           buffer.add(GETTER_SUFFIX); | 899           buffer.addCharCode(GETTER_CODE + flag); | 
| 882         } else if (needsSetter) { | 900         } else if (needsSetter) { | 
| 883           buffer.add(SETTER_SUFFIX); | 901           buffer.addCharCode(SETTER_CODE + flag); | 
| 884         } | 902         } | 
| 885       } | 903       } | 
| 886     }); | 904     }); | 
| 887     if (isAnythingOutput) { | 905     if (isAnythingOutput) { | 
| 888       buffer.add('"'); | 906       buffer.add('"'); | 
| 889       if (emitEndingComma) { | 907       if (emitEndingComma) { | 
| 890         buffer.add(','); | 908         buffer.add(','); | 
| 891       } | 909       } | 
| 892     } | 910     } | 
| 893   } | 911   } | 
| 894 | 912 | 
| 895   /** Each getter/setter must be prefixed with a ",\n ". */ | 913   /** Each getter/setter must be prefixed with a ",\n ". */ | 
| 896   void emitClassGettersSetters(ClassElement classElement, | 914   void emitClassGettersSetters(ClassElement classElement, | 
| 897                                CodeBuffer buffer, | 915                                CodeBuffer buffer, | 
| 898                                bool emitLeadingComma) { | 916                                bool emitLeadingComma) { | 
| 899     emitComma() { | 917     emitComma() { | 
| 900       if (emitLeadingComma) { | 918       if (emitLeadingComma) { | 
| 901         buffer.add(",\n "); | 919         buffer.add(",\n "); | 
| 902       } else { | 920       } else { | 
| 903         emitLeadingComma = true; | 921         emitLeadingComma = true; | 
| 904       } | 922       } | 
| 905     } | 923     } | 
| 906 | 924 | 
| 907     visitClassFields(classElement, (Element member, | 925     visitClassFields(classElement, (Element member, | 
| 908                                     String name, | 926                                     String name, | 
|  | 927                                     String accessorName, | 
| 909                                     bool needsGetter, | 928                                     bool needsGetter, | 
| 910                                     bool needsSetter, | 929                                     bool needsSetter, | 
| 911                                     bool needsCheckedSetter) { | 930                                     bool needsCheckedSetter) { | 
| 912           if (name == null) throw 123; |  | 
| 913       if (getterAndSetterCanBeImplementedByFieldSpec( |  | 
| 914           member, name, needsGetter, needsSetter)) { |  | 
| 915         needsGetter = false; |  | 
| 916         needsSetter = false; |  | 
| 917       } |  | 
| 918       if (needsGetter) { |  | 
| 919         emitComma(); |  | 
| 920         generateGetter(member, name, buffer); |  | 
| 921       } |  | 
| 922       if (needsSetter) { |  | 
| 923         emitComma(); |  | 
| 924         generateSetter(member, name, buffer); |  | 
| 925       } |  | 
| 926       if (needsCheckedSetter) { | 931       if (needsCheckedSetter) { | 
| 927         assert(!needsSetter); | 932         assert(!needsSetter); | 
| 928         emitComma(); | 933         emitComma(); | 
| 929         generateCheckedSetter(member, name, buffer); | 934         generateCheckedSetter(member, name, accessorName, buffer); | 
| 930       } | 935       } | 
| 931     }); | 936     }); | 
| 932   } | 937   } | 
| 933 | 938 | 
| 934   bool getterAndSetterCanBeImplementedByFieldSpec(Element member, |  | 
| 935       String name, |  | 
| 936       bool needsGetter, |  | 
| 937       bool needsSetter) { |  | 
| 938     if (needsGetter) { |  | 
| 939       if (namer.getterName(member.getLibrary(), member.name) != 'get\$$name') { |  | 
| 940         return false; |  | 
| 941       } |  | 
| 942     } |  | 
| 943     if (needsSetter) { |  | 
| 944       if (namer.setterName(member.getLibrary(), member.name) != 'set\$$name') { |  | 
| 945         return false; |  | 
| 946       } |  | 
| 947     } |  | 
| 948     return true; |  | 
| 949   } |  | 
| 950 |  | 
| 951   /** | 939   /** | 
| 952    * Documentation wanted -- johnniwinther | 940    * Documentation wanted -- johnniwinther | 
| 953    * | 941    * | 
| 954    * Invariant: [classElement] must be a declaration element. | 942    * Invariant: [classElement] must be a declaration element. | 
| 955    */ | 943    */ | 
| 956   void generateClass(ClassElement classElement, CodeBuffer buffer) { | 944   void generateClass(ClassElement classElement, CodeBuffer buffer) { | 
| 957     assert(invariant(classElement, classElement.isDeclaration)); | 945     assert(invariant(classElement, classElement.isDeclaration)); | 
| 958     if (classElement.isNative()) { | 946     if (classElement.isNative()) { | 
| 959       nativeEmitter.generateNativeClass(classElement); | 947       nativeEmitter.generateNativeClass(classElement); | 
| 960       return; | 948       return; | 
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1173 | 1161 | 
| 1174   void emitStaticFunctionGetters(CodeBuffer buffer) { | 1162   void emitStaticFunctionGetters(CodeBuffer buffer) { | 
| 1175     Set<FunctionElement> functionsNeedingGetter = | 1163     Set<FunctionElement> functionsNeedingGetter = | 
| 1176         compiler.codegenWorld.staticFunctionsNeedingGetter; | 1164         compiler.codegenWorld.staticFunctionsNeedingGetter; | 
| 1177     for (FunctionElement element in functionsNeedingGetter) { | 1165     for (FunctionElement element in functionsNeedingGetter) { | 
| 1178       // The static function does not have the correct name. Since | 1166       // The static function does not have the correct name. Since | 
| 1179       // [addParameterStubs] use the name to create its stubs we simply | 1167       // [addParameterStubs] use the name to create its stubs we simply | 
| 1180       // create a fake element with the correct name. | 1168       // create a fake element with the correct name. | 
| 1181       // Note: the callElement will not have any enclosingElement. | 1169       // Note: the callElement will not have any enclosingElement. | 
| 1182       FunctionElement callElement = | 1170       FunctionElement callElement = | 
| 1183           new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); | 1171           new ClosureInvocationElement(namer.closureInvocationSelectorName, | 
|  | 1172                                        element); | 
| 1184       String staticName = namer.getName(element); | 1173       String staticName = namer.getName(element); | 
| 1185       String invocationName = namer.instanceMethodName(callElement); | 1174       String invocationName = namer.instanceMethodName(callElement); | 
| 1186       String fieldAccess = '$isolateProperties.$staticName'; | 1175       String fieldAccess = '$isolateProperties.$staticName'; | 
| 1187       buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 1176       buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 
| 1188       addParameterStubs(callElement, (String name, CodeBuffer value) { | 1177       addParameterStubs(callElement, (String name, CodeBuffer value) { | 
| 1189         buffer.add('$fieldAccess.$name = $value;\n'); | 1178         buffer.add('$fieldAccess.$name = $value;\n'); | 
| 1190       }); | 1179       }); | 
| 1191       // If a static function is used as a closure we need to add its name | 1180       // If a static function is used as a closure we need to add its name | 
| 1192       // in case it is used in spawnFunction. | 1181       // in case it is used in spawnFunction. | 
| 1193       String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1182       String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1268 | 1257 | 
| 1269       // Define the constructor with a name so that Object.toString can | 1258       // Define the constructor with a name so that Object.toString can | 
| 1270       // find the class name of the closure class. | 1259       // find the class name of the closure class. | 
| 1271       emitBoundClosureClassHeader( | 1260       emitBoundClosureClassHeader( | 
| 1272           mangledName, superName, fieldNames, boundClosureBuffer); | 1261           mangledName, superName, fieldNames, boundClosureBuffer); | 
| 1273       // Now add the methods on the closure class. The instance method does not | 1262       // Now add the methods on the closure class. The instance method does not | 
| 1274       // have the correct name. Since [addParameterStubs] use the name to create | 1263       // have the correct name. Since [addParameterStubs] use the name to create | 
| 1275       // its stubs we simply create a fake element with the correct name. | 1264       // its stubs we simply create a fake element with the correct name. | 
| 1276       // Note: the callElement will not have any enclosingElement. | 1265       // Note: the callElement will not have any enclosingElement. | 
| 1277       FunctionElement callElement = | 1266       FunctionElement callElement = | 
| 1278           new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); | 1267           new ClosureInvocationElement(namer.closureInvocationSelectorName, | 
| 1279 | 1268                                        member); | 
|  | 1269 | 
| 1280       String invocationName = namer.instanceMethodName(callElement); | 1270       String invocationName = namer.instanceMethodName(callElement); | 
| 1281 | 1271 | 
| 1282       List<js.Parameter> parameters = <js.Parameter>[]; | 1272       List<js.Parameter> parameters = <js.Parameter>[]; | 
| 1283       List<js.Expression> arguments = <js.Expression>[]; | 1273       List<js.Expression> arguments = <js.Expression>[]; | 
| 1284       if (inInterceptor) { | 1274       if (inInterceptor) { | 
| 1285         arguments.add(new js.This().dot(fieldNames[2])); | 1275         arguments.add(new js.This().dot(fieldNames[2])); | 
| 1286       } | 1276       } | 
| 1287       for (int i = 0; i < parameterCount; i++) { | 1277       for (int i = 0; i < parameterCount; i++) { | 
| 1288         String name = 'p$i'; | 1278         String name = 'p$i'; | 
| 1289         parameters.add(new js.Parameter(name)); | 1279         parameters.add(new js.Parameter(name)); | 
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1374             : namer.instanceFieldName(memberLibrary, member.name); | 1364             : namer.instanceFieldName(memberLibrary, member.name); | 
| 1375         return new js.VariableUse('this').dot(fieldName); | 1365         return new js.VariableUse('this').dot(fieldName); | 
| 1376       } | 1366       } | 
| 1377     } | 1367     } | 
| 1378 | 1368 | 
| 1379     for (Selector selector in selectors) { | 1369     for (Selector selector in selectors) { | 
| 1380       if (selector.applies(member, compiler)) { | 1370       if (selector.applies(member, compiler)) { | 
| 1381         String invocationName = | 1371         String invocationName = | 
| 1382             namer.instanceMethodInvocationName(memberLibrary, member.name, | 1372             namer.instanceMethodInvocationName(memberLibrary, member.name, | 
| 1383                                                selector); | 1373                                                selector); | 
| 1384         SourceString callName = Namer.CLOSURE_INVOCATION_NAME; | 1374         SourceString callName = namer.closureInvocationSelectorName; | 
| 1385         String closureCallName = | 1375         String closureCallName = | 
| 1386             namer.instanceMethodInvocationName(memberLibrary, callName, | 1376             namer.instanceMethodInvocationName(memberLibrary, callName, | 
| 1387                                                selector); | 1377                                                selector); | 
| 1388 | 1378 | 
| 1389         List<js.Parameter> parameters = <js.Parameter>[]; | 1379         List<js.Parameter> parameters = <js.Parameter>[]; | 
| 1390         List<js.Expression> arguments = <js.Expression>[]; | 1380         List<js.Expression> arguments = <js.Expression>[]; | 
| 1391         if (isInterceptorClass) { | 1381         if (isInterceptorClass) { | 
| 1392           parameters.add(new js.Parameter(receiverArgumentName)); | 1382           parameters.add(new js.Parameter(receiverArgumentName)); | 
| 1393         } | 1383         } | 
| 1394 | 1384 | 
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1491               new js.PropertyAccess.field( | 1481               new js.PropertyAccess.field( | 
| 1492                   new js.VariableUse(isolateProperties), | 1482                   new js.VariableUse(isolateProperties), | 
| 1493                   name), | 1483                   name), | 
| 1494               constantInitializerExpression(constant)); | 1484               constantInitializerExpression(constant)); | 
| 1495       buffer.add(js.prettyPrint(init, compiler)); | 1485       buffer.add(js.prettyPrint(init, compiler)); | 
| 1496       buffer.add(';\n'); | 1486       buffer.add(';\n'); | 
| 1497     } | 1487     } | 
| 1498   } | 1488   } | 
| 1499 | 1489 | 
| 1500   void emitMakeConstantList(CodeBuffer buffer) { | 1490   void emitMakeConstantList(CodeBuffer buffer) { | 
| 1501     buffer.add(namer.ISOLATE); | 1491     buffer.add(namer.isolateName); | 
| 1502     buffer.add(r'''.makeConstantList = function(list) { | 1492     buffer.add(r'''.makeConstantList = function(list) { | 
| 1503   list.immutable$list = true; | 1493   list.immutable$list = true; | 
| 1504   list.fixed$length = true; | 1494   list.fixed$length = true; | 
| 1505   return list; | 1495   return list; | 
| 1506 }; | 1496 }; | 
| 1507 '''); | 1497 '''); | 
| 1508   } | 1498   } | 
| 1509 | 1499 | 
| 1510   /** | 1500   /** | 
| 1511    * Documentation wanted -- johnniwinther | 1501    * Documentation wanted -- johnniwinther | 
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1745     buffer.add(""" | 1735     buffer.add(""" | 
| 1746 var \$globalThis = $currentIsolate; | 1736 var \$globalThis = $currentIsolate; | 
| 1747 var \$globalState; | 1737 var \$globalState; | 
| 1748 var \$globals; | 1738 var \$globals; | 
| 1749 var \$isWorker = false; | 1739 var \$isWorker = false; | 
| 1750 var \$supportsWorkers = false; | 1740 var \$supportsWorkers = false; | 
| 1751 var \$thisScriptUrl; | 1741 var \$thisScriptUrl; | 
| 1752 function \$static_init(){}; | 1742 function \$static_init(){}; | 
| 1753 | 1743 | 
| 1754 function \$initGlobals(context) { | 1744 function \$initGlobals(context) { | 
| 1755   context.isolateStatics = new ${namer.ISOLATE}(); | 1745   context.isolateStatics = new ${namer.isolateName}(); | 
| 1756 } | 1746 } | 
| 1757 function \$setGlobals(context) { | 1747 function \$setGlobals(context) { | 
| 1758   $currentIsolate = context.isolateStatics; | 1748   $currentIsolate = context.isolateStatics; | 
| 1759   \$globalThis = $currentIsolate; | 1749   \$globalThis = $currentIsolate; | 
| 1760 } | 1750 } | 
| 1761 $mainEnsureGetter | 1751 $mainEnsureGetter | 
| 1762 """); | 1752 """); | 
| 1763   return "${namer.isolateAccess(isolateMain)}($mainAccess)"; | 1753   return "${namer.isolateAccess(isolateMain)}($mainAccess)"; | 
| 1764   } | 1754   } | 
| 1765 | 1755 | 
| 1766   emitMain(CodeBuffer buffer) { | 1756   emitMain(CodeBuffer buffer) { | 
| 1767     if (compiler.isMockCompilation) return; | 1757     if (compiler.isMockCompilation) return; | 
| 1768     Element main = compiler.mainApp.find(Compiler.MAIN); | 1758     Element main = compiler.mainApp.find(Compiler.MAIN); | 
| 1769     String mainCall = null; | 1759     String mainCall = null; | 
| 1770     if (compiler.isolateLibrary != null) { | 1760     if (compiler.isolateLibrary != null) { | 
| 1771       Element isolateMain = | 1761       Element isolateMain = | 
| 1772         compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); | 1762         compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); | 
| 1773       mainCall = buildIsolateSetup(buffer, main, isolateMain); | 1763       mainCall = buildIsolateSetup(buffer, main, isolateMain); | 
| 1774     } else { | 1764     } else { | 
| 1775       mainCall = '${namer.isolateAccess(main)}()'; | 1765       mainCall = '${namer.isolateAccess(main)}()'; | 
| 1776     } | 1766     } | 
| 1777     buffer.add(""" | 1767     buffer.add(""" | 
| 1778 | 1768 | 
| 1779 // | 1769 // | 
| 1780 // BEGIN invoke [main]. | 1770 // BEGIN invoke [main]. | 
| 1781 // | 1771 // | 
| 1782 if (typeof document != 'undefined' && document.readyState != 'complete') { | 1772 if (typeof document !== 'undefined' && document.readyState !== 'complete') { | 
| 1783   document.addEventListener('readystatechange', function () { | 1773   document.addEventListener('readystatechange', function () { | 
| 1784     if (document.readyState == 'complete') { | 1774     if (document.readyState == 'complete') { | 
| 1785       if (typeof dartMainRunner == 'function') { | 1775       if (typeof dartMainRunner === 'function') { | 
| 1786         dartMainRunner(function() { ${mainCall}; }); | 1776         dartMainRunner(function() { ${mainCall}; }); | 
| 1787       } else { | 1777       } else { | 
| 1788         ${mainCall}; | 1778         ${mainCall}; | 
| 1789       } | 1779       } | 
| 1790     } | 1780     } | 
| 1791   }, false); | 1781   }, false); | 
| 1792 } else { | 1782 } else { | 
| 1793   if (typeof dartMainRunner == 'function') { | 1783   if (typeof dartMainRunner === 'function') { | 
| 1794     dartMainRunner(function() { ${mainCall}; }); | 1784     dartMainRunner(function() { ${mainCall}; }); | 
| 1795   } else { | 1785   } else { | 
| 1796     ${mainCall}; | 1786     ${mainCall}; | 
| 1797   } | 1787   } | 
| 1798 } | 1788 } | 
| 1799 // | 1789 // | 
| 1800 // END invoke [main]. | 1790 // END invoke [main]. | 
| 1801 // | 1791 // | 
| 1802 | 1792 | 
| 1803 """); | 1793 """); | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1846               emitInterceptorCheck(cls, buffer); | 1836               emitInterceptorCheck(cls, buffer); | 
| 1847             } | 1837             } | 
| 1848           } | 1838           } | 
| 1849           buffer.add('\n  return $objectName.prototype;\n};\n'); | 1839           buffer.add('\n  return $objectName.prototype;\n};\n'); | 
| 1850         }); | 1840         }); | 
| 1851   } | 1841   } | 
| 1852 | 1842 | 
| 1853   String assembleProgram() { | 1843   String assembleProgram() { | 
| 1854     measure(() { | 1844     measure(() { | 
| 1855       mainBuffer.add(HOOKS_API_USAGE); | 1845       mainBuffer.add(HOOKS_API_USAGE); | 
| 1856       mainBuffer.add('function ${namer.ISOLATE}() {}\n'); | 1846       mainBuffer.add('function ${namer.isolateName}() {}\n'); | 
| 1857       mainBuffer.add('init();\n\n'); | 1847       mainBuffer.add('init();\n\n'); | 
| 1858       // Shorten the code by using "$$" as temporary. | 1848       // Shorten the code by using "$$" as temporary. | 
| 1859       classesCollector = r"$$"; | 1849       classesCollector = r"$$"; | 
| 1860       mainBuffer.add('var $classesCollector = {};\n'); | 1850       mainBuffer.add('var $classesCollector = {};\n'); | 
| 1861       // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. | 1851       // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. | 
| 1862       isolateProperties = namer.CURRENT_ISOLATE; | 1852       isolateProperties = namer.CURRENT_ISOLATE; | 
| 1863       mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); | 1853       mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); | 
| 1864       emitClasses(mainBuffer); | 1854       emitClasses(mainBuffer); | 
| 1865       mainBuffer.add(boundClosureBuffer); | 1855       mainBuffer.add(boundClosureBuffer); | 
| 1866       // Clear the buffer, so that we can reuse it for the native classes. | 1856       // Clear the buffer, so that we can reuse it for the native classes. | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 1882       // initialStatics. | 1872       // initialStatics. | 
| 1883       mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); | 1873       mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); | 
| 1884       mainBuffer.add(boundClosureBuffer); | 1874       mainBuffer.add(boundClosureBuffer); | 
| 1885       emitFinishClassesInvocationIfNecessary(mainBuffer); | 1875       emitFinishClassesInvocationIfNecessary(mainBuffer); | 
| 1886       // After this assignment we will produce invalid JavaScript code if we use | 1876       // After this assignment we will produce invalid JavaScript code if we use | 
| 1887       // the classesCollector variable. | 1877       // the classesCollector variable. | 
| 1888       classesCollector = 'classesCollector should not be used from now on'; | 1878       classesCollector = 'classesCollector should not be used from now on'; | 
| 1889 | 1879 | 
| 1890       emitFinishIsolateConstructorInvocation(mainBuffer); | 1880       emitFinishIsolateConstructorInvocation(mainBuffer); | 
| 1891       mainBuffer.add( | 1881       mainBuffer.add( | 
| 1892         'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 1882         'var ${namer.CURRENT_ISOLATE} = new ${namer.isolateName}();\n'); | 
| 1893 | 1883 | 
| 1894       nativeEmitter.assembleCode(mainBuffer); | 1884       nativeEmitter.assembleCode(mainBuffer); | 
| 1895       emitMain(mainBuffer); | 1885       emitMain(mainBuffer); | 
| 1896       mainBuffer.add('function init() {\n'); | 1886       mainBuffer.add('function init() {\n'); | 
| 1897       mainBuffer.add('$isolateProperties = {};\n'); | 1887       mainBuffer.add('$isolateProperties = {};\n'); | 
| 1898       addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 1888       addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 
| 1899       addLazyInitializerFunctionIfNecessary(mainBuffer); | 1889       addLazyInitializerFunctionIfNecessary(mainBuffer); | 
| 1900       emitFinishIsolateConstructor(mainBuffer); | 1890       emitFinishIsolateConstructor(mainBuffer); | 
| 1901       mainBuffer.add('}\n'); | 1891       mainBuffer.add('}\n'); | 
| 1902       compiler.assembledCode = mainBuffer.toString(); | 1892       compiler.assembledCode = mainBuffer.toString(); | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 1926 const String HOOKS_API_USAGE = """ | 1916 const String HOOKS_API_USAGE = """ | 
| 1927 // Generated by dart2js, the Dart to JavaScript compiler. | 1917 // Generated by dart2js, the Dart to JavaScript compiler. | 
| 1928 // The code supports the following hooks: | 1918 // The code supports the following hooks: | 
| 1929 // dartPrint(message)   - if this function is defined it is called | 1919 // dartPrint(message)   - if this function is defined it is called | 
| 1930 //                        instead of the Dart [print] method. | 1920 //                        instead of the Dart [print] method. | 
| 1931 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1921 // dartMainRunner(main) - if this function is defined, the Dart [main] | 
| 1932 //                        method will not be invoked directly. | 1922 //                        method will not be invoked directly. | 
| 1933 //                        Instead, a closure that will invoke [main] is | 1923 //                        Instead, a closure that will invoke [main] is | 
| 1934 //                        passed to [dartMainRunner]. | 1924 //                        passed to [dartMainRunner]. | 
| 1935 """; | 1925 """; | 
| OLD | NEW | 
|---|