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