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