| 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 newPrototype[member] = prototype[member]; | 280 newPrototype[member] = prototype[member]; |
| 259 } | 281 } |
| 260 } | 282 } |
| 261 } | 283 } |
| 262 } | 284 } |
| 263 for (var cls in pendingClasses) finishClass(cls); | 285 for (var cls in pendingClasses) finishClass(cls); |
| 264 }'''; | 286 }'''; |
| 265 } | 287 } |
| 266 | 288 |
| 267 String get finishIsolateConstructorFunction { | 289 String get finishIsolateConstructorFunction { |
| 268 String isolate = namer.ISOLATE; | 290 String isolate = namer.isolateName; |
| 269 // We replace the old Isolate function with a new one that initializes | 291 // We replace the old Isolate function with a new one that initializes |
| 270 // all its field with the initial (and often final) value of all globals. | 292 // all its field with the initial (and often final) value of all globals. |
| 271 // This has two advantages: | 293 // This has two advantages: |
| 272 // 1. the properties are in the object itself (thus avoiding to go through | 294 // 1. the properties are in the object itself (thus avoiding to go through |
| 273 // the prototype when looking up globals. | 295 // the prototype when looking up globals. |
| 274 // 2. a new isolate goes through a (usually well optimized) constructor | 296 // 2. a new isolate goes through a (usually well optimized) constructor |
| 275 // function of the form: "function() { this.x = ...; this.y = ...; }". | 297 // function of the form: "function() { this.x = ...; this.y = ...; }". |
| 276 // | 298 // |
| 277 // Example: If [isolateProperties] is an object containing: x = 3 and | 299 // Example: If [isolateProperties] is an object containing: x = 3 and |
| 278 // A = function A() { /* constructor of class A. */ }, then we generate: | 300 // A = function A() { /* constructor of class A. */ }, then we generate: |
| 279 // str = "{ | 301 // str = "{ |
| 280 // var isolateProperties = Isolate.$isolateProperties; | 302 // var isolateProperties = Isolate.$isolateProperties; |
| 281 // this.x = isolateProperties.x; | 303 // this.x = isolateProperties.x; |
| 282 // this.A = isolateProperties.A; | 304 // this.A = isolateProperties.A; |
| 283 // }"; | 305 // }"; |
| 284 // which is then dynamically evaluated: | 306 // which is then dynamically evaluated: |
| 285 // var newIsolate = new Function(str); | 307 // var newIsolate = new Function(str); |
| 286 // | 308 // |
| 287 // We also copy over old values like the prototype, and the | 309 // We also copy over old values like the prototype, and the |
| 288 // isolateProperties themselves. | 310 // isolateProperties themselves. |
| 289 return """function(oldIsolate) { | 311 return """function(oldIsolate) { |
| 290 var isolateProperties = oldIsolate.${namer.ISOLATE_PROPERTIES}; | 312 var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; |
| 291 var isolatePrototype = oldIsolate.prototype; | 313 var isolatePrototype = oldIsolate.prototype; |
| 292 var str = "{\\n"; | 314 var str = "{\\n"; |
| 293 str += "var properties = $isolate.${namer.ISOLATE_PROPERTIES};\\n"; | 315 str += "var properties = $isolate.${namer.isolatePropertiesName};\\n"; |
| 294 for (var staticName in isolateProperties) { | 316 for (var staticName in isolateProperties) { |
| 295 if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) { | 317 if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) { |
| 296 str += "this." + staticName + "= properties." + staticName + ";\\n"; | 318 str += "this." + staticName + "= properties." + staticName + ";\\n"; |
| 297 } | 319 } |
| 298 } | 320 } |
| 299 str += "}\\n"; | 321 str += "}\\n"; |
| 300 var newIsolate = new Function(str); | 322 var newIsolate = new Function(str); |
| 301 newIsolate.prototype = isolatePrototype; | 323 newIsolate.prototype = isolatePrototype; |
| 302 isolatePrototype.constructor = newIsolate; | 324 isolatePrototype.constructor = newIsolate; |
| 303 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; | 325 newIsolate.${namer.isolatePropertiesName} = isolateProperties; |
| 304 return newIsolate; | 326 return newIsolate; |
| 305 }"""; | 327 }"""; |
| 306 } | 328 } |
| 307 | 329 |
| 308 String get lazyInitializerFunction { | 330 String get lazyInitializerFunction { |
| 309 String isolate = namer.CURRENT_ISOLATE; | 331 String isolate = namer.CURRENT_ISOLATE; |
| 310 return """ | 332 return """ |
| 311 function(prototype, staticName, fieldName, getterName, lazyValue) { | 333 function(prototype, staticName, fieldName, getterName, lazyValue) { |
| 312 var getter = new Function("{ return $isolate." + fieldName + ";}"); | 334 var getter = new Function("{ return $isolate." + fieldName + ";}"); |
| 313 $lazyInitializerLogic | 335 $lazyInitializerLogic |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 } | 386 } |
| 365 } | 387 } |
| 366 | 388 |
| 367 void emitFinishIsolateConstructor(CodeBuffer buffer) { | 389 void emitFinishIsolateConstructor(CodeBuffer buffer) { |
| 368 String name = finishIsolateConstructorName; | 390 String name = finishIsolateConstructorName; |
| 369 String value = finishIsolateConstructorFunction; | 391 String value = finishIsolateConstructorFunction; |
| 370 buffer.add("$name = $value;\n"); | 392 buffer.add("$name = $value;\n"); |
| 371 } | 393 } |
| 372 | 394 |
| 373 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 395 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 374 String isolate = namer.ISOLATE; | 396 String isolate = namer.isolateName; |
| 375 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | 397 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); |
| 376 } | 398 } |
| 377 | 399 |
| 378 /** | 400 /** |
| 379 * Generate stubs to handle invocation of methods with optional | 401 * Generate stubs to handle invocation of methods with optional |
| 380 * arguments. | 402 * arguments. |
| 381 * | 403 * |
| 382 * A method like [: foo([x]) :] may be invoked by the following | 404 * A method like [: foo([x]) :] may be invoked by the following |
| 383 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 405 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this |
| 384 * function for detailed examples. | 406 * function for detailed examples. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); | 542 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); |
| 521 // (4) No stub generated, call is direct. | 543 // (4) No stub generated, call is direct. |
| 522 // (5) No stub generated, call is direct. | 544 // (5) No stub generated, call is direct. |
| 523 | 545 |
| 524 // Keep a cache of which stubs have already been generated, to | 546 // Keep a cache of which stubs have already been generated, to |
| 525 // avoid duplicates. Note that even if selectors are | 547 // avoid duplicates. Note that even if selectors are |
| 526 // canonicalized, we would still need this cache: a typed selector | 548 // canonicalized, we would still need this cache: a typed selector |
| 527 // on A and a typed selector on B could yield the same stub. | 549 // on A and a typed selector on B could yield the same stub. |
| 528 Set<String> generatedStubNames = new Set<String>(); | 550 Set<String> generatedStubNames = new Set<String>(); |
| 529 if (compiler.enabledFunctionApply | 551 if (compiler.enabledFunctionApply |
| 530 && member.name == Namer.CLOSURE_INVOCATION_NAME) { | 552 && member.name == namer.closureInvocationSelector) { |
| 531 // If [Function.apply] is called, we pessimistically compile all | 553 // If [Function.apply] is called, we pessimistically compile all |
| 532 // possible stubs for this closure. | 554 // possible stubs for this closure. |
| 533 FunctionSignature signature = member.computeSignature(compiler); | 555 FunctionSignature signature = member.computeSignature(compiler); |
| 534 Set<Selector> selectors = signature.optionalParametersAreNamed | 556 Set<Selector> selectors = signature.optionalParametersAreNamed |
| 535 ? computeNamedSelectors(signature, member) | 557 ? computeNamedSelectors(signature, member) |
| 536 : computeOptionalSelectors(signature, member); | 558 : computeOptionalSelectors(signature, member); |
| 537 for (Selector selector in selectors) { | 559 for (Selector selector in selectors) { |
| 538 addParameterStub( | 560 addParameterStub( |
| 539 member, selector, defineInstanceMember, generatedStubNames); | 561 member, selector, defineInstanceMember, generatedStubNames); |
| 540 } | 562 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 | 637 |
| 616 bool instanceFieldNeedsSetter(Element member) { | 638 bool instanceFieldNeedsSetter(Element member) { |
| 617 assert(member.isField()); | 639 assert(member.isField()); |
| 618 return (!member.modifiers.isFinalOrConst()) | 640 return (!member.modifiers.isFinalOrConst()) |
| 619 && compiler.codegenWorld.hasInvokedSetter(member, compiler); | 641 && compiler.codegenWorld.hasInvokedSetter(member, compiler); |
| 620 } | 642 } |
| 621 | 643 |
| 622 String compiledFieldName(Element member) { | 644 String compiledFieldName(Element member) { |
| 623 assert(member.isField()); | 645 assert(member.isField()); |
| 624 return member.isNative() | 646 return member.isNative() |
| 625 ? member.name.slowToString() | 647 ? member.nativeName() |
| 626 : namer.getName(member); | 648 : namer.getName(member); |
| 627 } | 649 } |
| 628 | 650 |
| 629 /** | 651 /** |
| 630 * Documentation wanted -- johnniwinther | 652 * Documentation wanted -- johnniwinther |
| 631 * | 653 * |
| 632 * Invariant: [member] must be a declaration element. | 654 * Invariant: [member] must be a declaration element. |
| 633 */ | 655 */ |
| 634 void addInstanceMember(Element member, | 656 void addInstanceMember(Element member, |
| 635 DefineMemberFunction defineInstanceMember) { | 657 DefineMemberFunction defineInstanceMember) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 } | 741 } |
| 720 | 742 |
| 721 /** | 743 /** |
| 722 * Documentation wanted -- johnniwinther | 744 * Documentation wanted -- johnniwinther |
| 723 * | 745 * |
| 724 * Invariant: [classElement] must be a declaration element. | 746 * Invariant: [classElement] must be a declaration element. |
| 725 */ | 747 */ |
| 726 void visitClassFields(ClassElement classElement, | 748 void visitClassFields(ClassElement classElement, |
| 727 void addField(Element member, | 749 void addField(Element member, |
| 728 String name, | 750 String name, |
| 751 String accessorName, |
| 729 bool needsGetter, | 752 bool needsGetter, |
| 730 bool needsSetter, | 753 bool needsSetter, |
| 731 bool needsCheckedSetter)) { | 754 bool needsCheckedSetter)) { |
| 732 assert(invariant(classElement, classElement.isDeclaration)); | 755 assert(invariant(classElement, classElement.isDeclaration)); |
| 733 // If the class is never instantiated we still need to set it up for | 756 // If the class is never instantiated we still need to set it up for |
| 734 // inheritance purposes, but we can simplify its JavaScript constructor. | 757 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 735 bool isInstantiated = | 758 bool isInstantiated = |
| 736 compiler.codegenWorld.instantiatedClasses.contains(classElement); | 759 compiler.codegenWorld.instantiatedClasses.contains(classElement); |
| 737 | 760 |
| 738 void visitField(ClassElement enclosingClass, Element member) { | 761 void visitField(ClassElement enclosingClass, Element member) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 768 : accessorName; | 791 : accessorName; |
| 769 bool needsCheckedSetter = false; | 792 bool needsCheckedSetter = false; |
| 770 if (needsSetter && compiler.enableTypeAssertions | 793 if (needsSetter && compiler.enableTypeAssertions |
| 771 && canGenerateCheckedSetter(member)) { | 794 && canGenerateCheckedSetter(member)) { |
| 772 needsCheckedSetter = true; | 795 needsCheckedSetter = true; |
| 773 needsSetter = false; | 796 needsSetter = false; |
| 774 } | 797 } |
| 775 // Getters and setters with suffixes will be generated dynamically. | 798 // Getters and setters with suffixes will be generated dynamically. |
| 776 addField(member, | 799 addField(member, |
| 777 fieldName, | 800 fieldName, |
| 801 accessorName, |
| 778 needsGetter, | 802 needsGetter, |
| 779 needsSetter, | 803 needsSetter, |
| 780 needsCheckedSetter); | 804 needsCheckedSetter); |
| 781 } | 805 } |
| 782 } | 806 } |
| 783 | 807 |
| 784 // If a class is not instantiated then we add the field just so we can | 808 // If a class is not instantiated then we add the field just so we can |
| 785 // generate the field getter/setter dynamically. Since this is only | 809 // generate the field getter/setter dynamically. Since this is only |
| 786 // allowed on fields that are in [classElement] we don't need to visit | 810 // allowed on fields that are in [classElement] we don't need to visit |
| 787 // superclasses for non-instantiated classes. | 811 // superclasses for non-instantiated classes. |
| 788 classElement.implementation.forEachInstanceField( | 812 classElement.implementation.forEachInstanceField( |
| 789 visitField, | 813 visitField, |
| 790 includeBackendMembers: true, | 814 includeBackendMembers: true, |
| 791 includeSuperMembers: isInstantiated && !classElement.isNative()); | 815 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 792 } | 816 } |
| 793 | 817 |
| 794 void generateGetter(Element member, String fieldName, CodeBuffer buffer) { | |
| 795 String getterName = namer.getterName(member.getLibrary(), member.name); | |
| 796 buffer.add("$getterName: function() { return this.$fieldName; }"); | |
| 797 } | |
| 798 | |
| 799 void generateSetter(Element member, String fieldName, CodeBuffer buffer) { | |
| 800 String setterName = namer.setterName(member.getLibrary(), member.name); | |
| 801 buffer.add("$setterName: function(v) { this.$fieldName = v; }"); | |
| 802 } | |
| 803 | |
| 804 bool canGenerateCheckedSetter(Element member) { | 818 bool canGenerateCheckedSetter(Element member) { |
| 805 DartType type = member.computeType(compiler); | 819 DartType type = member.computeType(compiler); |
| 806 if (type.element.isTypeVariable() | 820 if (type.element.isTypeVariable() |
| 807 || type.element == compiler.dynamicClass | 821 || type.element == compiler.dynamicClass |
| 808 || type.element == compiler.objectClass) { | 822 || type.element == compiler.objectClass) { |
| 809 // TODO(ngeoffray): Support type checks on type parameters. | 823 // TODO(ngeoffray): Support type checks on type parameters. |
| 810 return false; | 824 return false; |
| 811 } | 825 } |
| 812 return true; | 826 return true; |
| 813 } | 827 } |
| 814 | 828 |
| 815 void generateCheckedSetter(Element member, | 829 void generateCheckedSetter(Element member, |
| 816 String fieldName, | 830 String fieldName, |
| 831 String accessorName, |
| 817 CodeBuffer buffer) { | 832 CodeBuffer buffer) { |
| 818 assert(canGenerateCheckedSetter(member)); | 833 assert(canGenerateCheckedSetter(member)); |
| 819 DartType type = member.computeType(compiler); | 834 DartType type = member.computeType(compiler); |
| 820 SourceString helper = compiler.backend.getCheckedModeHelper(type); | 835 SourceString helper = compiler.backend.getCheckedModeHelper(type); |
| 821 FunctionElement helperElement = compiler.findHelper(helper); | 836 FunctionElement helperElement = compiler.findHelper(helper); |
| 822 String helperName = namer.isolateAccess(helperElement); | 837 String helperName = namer.isolateAccess(helperElement); |
| 823 String additionalArgument = ''; | 838 String additionalArgument = ''; |
| 824 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 839 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 825 additionalArgument = ", '${namer.operatorIs(type.element)}'"; | 840 additionalArgument = ", '${namer.operatorIs(type.element)}'"; |
| 826 } | 841 } |
| 827 String setterName = namer.setterName(member.getLibrary(), member.name); | 842 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 828 buffer.add("$setterName: function(v) { " | 843 buffer.add("$setterName: function(v) { " |
| 829 "this.$fieldName = $helperName(v$additionalArgument); }"); | 844 "this.$fieldName = $helperName(v$additionalArgument); }"); |
| 830 } | 845 } |
| 831 | 846 |
| 832 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 847 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { |
| 833 /* Do nothing. */ | 848 /* Do nothing. */ |
| 834 } | 849 } |
| 835 | 850 |
| 836 void emitClassFields(ClassElement classElement, | 851 void emitClassFields(ClassElement classElement, |
| 837 CodeBuffer buffer, | 852 CodeBuffer buffer, |
| 838 bool emitEndingComma, | 853 bool emitEndingComma, |
| 839 { String superClass: "", | 854 { String superClass: "", |
| 840 bool isNative: false}) { | 855 bool isNative: false}) { |
| 841 bool isFirstField = true; | 856 bool isFirstField = true; |
| 842 bool isAnythingOutput = false; | 857 bool isAnythingOutput = false; |
| 843 if (!isNative) { | 858 if (!isNative) { |
| 844 buffer.add('"":"$superClass;'); | 859 buffer.add('"":"$superClass;'); |
| 845 isAnythingOutput = true; | 860 isAnythingOutput = true; |
| 846 } | 861 } |
| 847 visitClassFields(classElement, (Element member, | 862 visitClassFields(classElement, (Element member, |
| 848 String name, | 863 String name, |
| 864 String accessorName, |
| 849 bool needsGetter, | 865 bool needsGetter, |
| 850 bool needsSetter, | 866 bool needsSetter, |
| 851 bool needsCheckedSetter) { | 867 bool needsCheckedSetter) { |
| 852 if (!getterAndSetterCanBeImplementedByFieldSpec( | |
| 853 member, name, needsGetter, needsSetter)) { | |
| 854 return; | |
| 855 } | |
| 856 if (!isNative || needsCheckedSetter || needsGetter || needsSetter) { | 868 if (!isNative || needsCheckedSetter || needsGetter || needsSetter) { |
| 857 if (isFirstField) { | 869 if (isFirstField) { |
| 858 isFirstField = false; | 870 isFirstField = false; |
| 859 if (!isAnythingOutput) { | 871 if (!isAnythingOutput) { |
| 860 buffer.add('"":"'); | 872 buffer.add('"":"'); |
| 861 isAnythingOutput = true; | 873 isAnythingOutput = true; |
| 862 } | 874 } |
| 863 } else { | 875 } else { |
| 864 buffer.add(","); | 876 buffer.add(","); |
| 865 } | 877 } |
| 866 buffer.add('$name'); | 878 buffer.add('$accessorName'); |
| 879 int flag = 0; |
| 880 if (name != accessorName) { |
| 881 buffer.add(':$name'); |
| 882 assert(needsGetter || needsSetter); |
| 883 flag = RENAMING_FLAG; |
| 884 } |
| 867 if (needsGetter && needsSetter) { | 885 if (needsGetter && needsSetter) { |
| 868 buffer.add(GETTER_SETTER_SUFFIX); | 886 buffer.addCharCode(GETTER_SETTER_CODE + flag); |
| 869 } else if (needsGetter) { | 887 } else if (needsGetter) { |
| 870 buffer.add(GETTER_SUFFIX); | 888 buffer.addCharCode(GETTER_CODE + flag); |
| 871 } else if (needsSetter) { | 889 } else if (needsSetter) { |
| 872 buffer.add(SETTER_SUFFIX); | 890 buffer.addCharCode(SETTER_CODE + flag); |
| 873 } | 891 } |
| 874 } | 892 } |
| 875 }); | 893 }); |
| 876 if (isAnythingOutput) { | 894 if (isAnythingOutput) { |
| 877 buffer.add('"'); | 895 buffer.add('"'); |
| 878 if (emitEndingComma) { | 896 if (emitEndingComma) { |
| 879 buffer.add(','); | 897 buffer.add(','); |
| 880 } | 898 } |
| 881 } | 899 } |
| 882 } | 900 } |
| 883 | 901 |
| 884 /** Each getter/setter must be prefixed with a ",\n ". */ | 902 /** Each getter/setter must be prefixed with a ",\n ". */ |
| 885 void emitClassGettersSetters(ClassElement classElement, | 903 void emitClassGettersSetters(ClassElement classElement, |
| 886 CodeBuffer buffer, | 904 CodeBuffer buffer, |
| 887 bool emitLeadingComma) { | 905 bool emitLeadingComma) { |
| 888 emitComma() { | 906 emitComma() { |
| 889 if (emitLeadingComma) { | 907 if (emitLeadingComma) { |
| 890 buffer.add(",\n "); | 908 buffer.add(",\n "); |
| 891 } else { | 909 } else { |
| 892 emitLeadingComma = true; | 910 emitLeadingComma = true; |
| 893 } | 911 } |
| 894 } | 912 } |
| 895 | 913 |
| 896 visitClassFields(classElement, (Element member, | 914 visitClassFields(classElement, (Element member, |
| 897 String name, | 915 String name, |
| 916 String accessorName, |
| 898 bool needsGetter, | 917 bool needsGetter, |
| 899 bool needsSetter, | 918 bool needsSetter, |
| 900 bool needsCheckedSetter) { | 919 bool needsCheckedSetter) { |
| 901 if (name == null) throw 123; | |
| 902 if (getterAndSetterCanBeImplementedByFieldSpec( | |
| 903 member, name, needsGetter, needsSetter)) { | |
| 904 needsGetter = false; | |
| 905 needsSetter = false; | |
| 906 } | |
| 907 if (needsGetter) { | |
| 908 emitComma(); | |
| 909 generateGetter(member, name, buffer); | |
| 910 } | |
| 911 if (needsSetter) { | |
| 912 emitComma(); | |
| 913 generateSetter(member, name, buffer); | |
| 914 } | |
| 915 if (needsCheckedSetter) { | 920 if (needsCheckedSetter) { |
| 916 assert(!needsSetter); | 921 assert(!needsSetter); |
| 917 emitComma(); | 922 emitComma(); |
| 918 generateCheckedSetter(member, name, buffer); | 923 generateCheckedSetter(member, name, accessorName, buffer); |
| 919 } | 924 } |
| 920 }); | 925 }); |
| 921 } | 926 } |
| 922 | 927 |
| 923 bool getterAndSetterCanBeImplementedByFieldSpec(Element member, | |
| 924 String name, | |
| 925 bool needsGetter, | |
| 926 bool needsSetter) { | |
| 927 if (needsGetter) { | |
| 928 if (namer.getterName(member.getLibrary(), member.name) != 'get\$$name') { | |
| 929 return false; | |
| 930 } | |
| 931 } | |
| 932 if (needsSetter) { | |
| 933 if (namer.setterName(member.getLibrary(), member.name) != 'set\$$name') { | |
| 934 return false; | |
| 935 } | |
| 936 } | |
| 937 return true; | |
| 938 } | |
| 939 | |
| 940 /** | 928 /** |
| 941 * Documentation wanted -- johnniwinther | 929 * Documentation wanted -- johnniwinther |
| 942 * | 930 * |
| 943 * Invariant: [classElement] must be a declaration element. | 931 * Invariant: [classElement] must be a declaration element. |
| 944 */ | 932 */ |
| 945 void generateClass(ClassElement classElement, CodeBuffer buffer) { | 933 void generateClass(ClassElement classElement, CodeBuffer buffer) { |
| 946 assert(invariant(classElement, classElement.isDeclaration)); | 934 assert(invariant(classElement, classElement.isDeclaration)); |
| 947 if (classElement.isNative()) { | 935 if (classElement.isNative()) { |
| 948 nativeEmitter.generateNativeClass(classElement); | 936 nativeEmitter.generateNativeClass(classElement); |
| 949 return; | 937 return; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 | 1149 |
| 1162 void emitStaticFunctionGetters(CodeBuffer buffer) { | 1150 void emitStaticFunctionGetters(CodeBuffer buffer) { |
| 1163 Set<FunctionElement> functionsNeedingGetter = | 1151 Set<FunctionElement> functionsNeedingGetter = |
| 1164 compiler.codegenWorld.staticFunctionsNeedingGetter; | 1152 compiler.codegenWorld.staticFunctionsNeedingGetter; |
| 1165 for (FunctionElement element in functionsNeedingGetter) { | 1153 for (FunctionElement element in functionsNeedingGetter) { |
| 1166 // The static function does not have the correct name. Since | 1154 // The static function does not have the correct name. Since |
| 1167 // [addParameterStubs] use the name to create its stubs we simply | 1155 // [addParameterStubs] use the name to create its stubs we simply |
| 1168 // create a fake element with the correct name. | 1156 // create a fake element with the correct name. |
| 1169 // Note: the callElement will not have any enclosingElement. | 1157 // Note: the callElement will not have any enclosingElement. |
| 1170 FunctionElement callElement = | 1158 FunctionElement callElement = |
| 1171 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); | 1159 new ClosureInvocationElement(namer.closureInvocationSelector, element)
; |
| 1172 String staticName = namer.getName(element); | 1160 String staticName = namer.getName(element); |
| 1173 String invocationName = namer.instanceMethodName(callElement); | 1161 String invocationName = namer.instanceMethodName(callElement); |
| 1174 String fieldAccess = '$isolateProperties.$staticName'; | 1162 String fieldAccess = '$isolateProperties.$staticName'; |
| 1175 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); | 1163 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); |
| 1176 addParameterStubs(callElement, (String name, CodeBuffer value) { | 1164 addParameterStubs(callElement, (String name, CodeBuffer value) { |
| 1177 buffer.add('$fieldAccess.$name = $value;\n'); | 1165 buffer.add('$fieldAccess.$name = $value;\n'); |
| 1178 }); | 1166 }); |
| 1179 // If a static function is used as a closure we need to add its name | 1167 // If a static function is used as a closure we need to add its name |
| 1180 // in case it is used in spawnFunction. | 1168 // in case it is used in spawnFunction. |
| 1181 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1169 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 | 1246 |
| 1259 // Define the constructor with a name so that Object.toString can | 1247 // Define the constructor with a name so that Object.toString can |
| 1260 // find the class name of the closure class. | 1248 // find the class name of the closure class. |
| 1261 emitBoundClosureClassHeader( | 1249 emitBoundClosureClassHeader( |
| 1262 mangledName, superName, extraArgWithoutComma, boundClosureBuffer); | 1250 mangledName, superName, extraArgWithoutComma, boundClosureBuffer); |
| 1263 // Now add the methods on the closure class. The instance method does not | 1251 // Now add the methods on the closure class. The instance method does not |
| 1264 // have the correct name. Since [addParameterStubs] use the name to create | 1252 // have the correct name. Since [addParameterStubs] use the name to create |
| 1265 // its stubs we simply create a fake element with the correct name. | 1253 // its stubs we simply create a fake element with the correct name. |
| 1266 // Note: the callElement will not have any enclosingElement. | 1254 // Note: the callElement will not have any enclosingElement. |
| 1267 FunctionElement callElement = | 1255 FunctionElement callElement = |
| 1268 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); | 1256 new ClosureInvocationElement(namer.closureInvocationSelector, member); |
| 1269 | 1257 |
| 1270 String invocationName = namer.instanceMethodName(callElement); | 1258 String invocationName = namer.instanceMethodName(callElement); |
| 1271 List<String> arguments = new List<String>(parameterCount); | 1259 List<String> arguments = new List<String>(parameterCount); |
| 1272 for (int i = 0; i < parameterCount; i++) { | 1260 for (int i = 0; i < parameterCount; i++) { |
| 1273 arguments[i] = "p$i"; | 1261 arguments[i] = "p$i"; |
| 1274 } | 1262 } |
| 1275 String joinedArgs = Strings.join(arguments, ", "); | 1263 String joinedArgs = Strings.join(arguments, ", "); |
| 1276 boundClosureBuffer.add( | 1264 boundClosureBuffer.add( |
| 1277 "$invocationName: function($joinedArgs) {"); | 1265 "$invocationName: function($joinedArgs) {"); |
| 1278 String callArgs = hasExtraArgument | 1266 String callArgs = hasExtraArgument |
| 1279 ? joinedArgs.isEmpty | 1267 ? joinedArgs.isEmpty |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 : namer.instanceFieldName(memberLibrary, member.name); | 1323 : namer.instanceFieldName(memberLibrary, member.name); |
| 1336 return new js.VariableUse('this').dot(fieldName); | 1324 return new js.VariableUse('this').dot(fieldName); |
| 1337 } | 1325 } |
| 1338 } | 1326 } |
| 1339 | 1327 |
| 1340 for (Selector selector in selectors) { | 1328 for (Selector selector in selectors) { |
| 1341 if (selector.applies(member, compiler)) { | 1329 if (selector.applies(member, compiler)) { |
| 1342 String invocationName = | 1330 String invocationName = |
| 1343 namer.instanceMethodInvocationName(memberLibrary, member.name, | 1331 namer.instanceMethodInvocationName(memberLibrary, member.name, |
| 1344 selector); | 1332 selector); |
| 1345 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; | 1333 SourceString callName = namer.closureInvocationSelector; |
| 1346 String closureCallName = | 1334 String closureCallName = |
| 1347 namer.instanceMethodInvocationName(memberLibrary, callName, | 1335 namer.instanceMethodInvocationName(memberLibrary, callName, |
| 1348 selector); | 1336 selector); |
| 1349 | 1337 |
| 1350 List<js.Parameter> parameters = <js.Parameter>[]; | 1338 List<js.Parameter> parameters = <js.Parameter>[]; |
| 1351 List<js.Expression> arguments = <js.Expression>[]; | 1339 List<js.Expression> arguments = <js.Expression>[]; |
| 1352 if (isInterceptorClass) { | 1340 if (isInterceptorClass) { |
| 1353 parameters.add(new js.Parameter(receiverArgumentName)); | 1341 parameters.add(new js.Parameter(receiverArgumentName)); |
| 1354 } | 1342 } |
| 1355 | 1343 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 new js.PropertyAccess.field( | 1440 new js.PropertyAccess.field( |
| 1453 new js.VariableUse(isolateProperties), | 1441 new js.VariableUse(isolateProperties), |
| 1454 name), | 1442 name), |
| 1455 constantInitializerExpression(constant)); | 1443 constantInitializerExpression(constant)); |
| 1456 buffer.add(js.prettyPrint(init, compiler)); | 1444 buffer.add(js.prettyPrint(init, compiler)); |
| 1457 buffer.add(';\n'); | 1445 buffer.add(';\n'); |
| 1458 } | 1446 } |
| 1459 } | 1447 } |
| 1460 | 1448 |
| 1461 void emitMakeConstantList(CodeBuffer buffer) { | 1449 void emitMakeConstantList(CodeBuffer buffer) { |
| 1462 buffer.add(namer.ISOLATE); | 1450 buffer.add(namer.isolateName); |
| 1463 buffer.add(r'''.makeConstantList = function(list) { | 1451 buffer.add(r'''.makeConstantList = function(list) { |
| 1464 list.immutable$list = true; | 1452 list.immutable$list = true; |
| 1465 list.fixed$length = true; | 1453 list.fixed$length = true; |
| 1466 return list; | 1454 return list; |
| 1467 }; | 1455 }; |
| 1468 '''); | 1456 '''); |
| 1469 } | 1457 } |
| 1470 | 1458 |
| 1471 /** | 1459 /** |
| 1472 * Documentation wanted -- johnniwinther | 1460 * Documentation wanted -- johnniwinther |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 CodeBuffer argNames = new CodeBuffer(); | 1528 CodeBuffer argNames = new CodeBuffer(); |
| 1541 List<SourceString> names = selector.getOrderedNamedArguments(); | 1529 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 1542 for (int i = 0; i < names.length; i++) { | 1530 for (int i = 0; i < names.length; i++) { |
| 1543 if (i != 0) argNames.add(', '); | 1531 if (i != 0) argNames.add(', '); |
| 1544 argNames.add('"'); | 1532 argNames.add('"'); |
| 1545 argNames.add(names[i].slowToString()); | 1533 argNames.add(names[i].slowToString()); |
| 1546 argNames.add('"'); | 1534 argNames.add('"'); |
| 1547 } | 1535 } |
| 1548 String internalName = namer.instanceMethodInvocationName( | 1536 String internalName = namer.instanceMethodInvocationName( |
| 1549 selector.library, new SourceString(methodName), selector); | 1537 selector.library, new SourceString(methodName), selector); |
| 1538 Element createInvocationMirror = |
| 1539 compiler.findHelper(const SourceString('createInvocationMirror')); |
| 1550 CodeBuffer buffer = new CodeBuffer(); | 1540 CodeBuffer buffer = new CodeBuffer(); |
| 1551 buffer.add('function($args) {\n'); | 1541 buffer.add('function($args) {\n'); |
| 1552 buffer.add(' return this.$noSuchMethodName(' | 1542 buffer.add(' return this.$noSuchMethodName(' |
| 1553 '\$.createInvocationMirror("$methodName", "$internalName",' | 1543 '${namer.isolateAccess(createInvocationMirror)}(' |
| 1554 ' $type, [$args], [$argNames]));\n'); | 1544 '"$methodName", "$internalName",' |
| 1545 '$type, [$args], [$argNames]));\n'); |
| 1555 buffer.add(' }'); | 1546 buffer.add(' }'); |
| 1556 return buffer; | 1547 return buffer; |
| 1557 } | 1548 } |
| 1558 | 1549 |
| 1559 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 1550 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
| 1560 // Cache the object class and type. | 1551 // Cache the object class and type. |
| 1561 ClassElement objectClass = compiler.objectClass; | 1552 ClassElement objectClass = compiler.objectClass; |
| 1562 DartType objectType = objectClass.computeType(compiler); | 1553 DartType objectType = objectClass.computeType(compiler); |
| 1563 | 1554 |
| 1564 for (Selector selector in selectors) { | 1555 for (Selector selector in selectors) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 buffer.add(""" | 1681 buffer.add(""" |
| 1691 var \$globalThis = $currentIsolate; | 1682 var \$globalThis = $currentIsolate; |
| 1692 var \$globalState; | 1683 var \$globalState; |
| 1693 var \$globals; | 1684 var \$globals; |
| 1694 var \$isWorker = false; | 1685 var \$isWorker = false; |
| 1695 var \$supportsWorkers = false; | 1686 var \$supportsWorkers = false; |
| 1696 var \$thisScriptUrl; | 1687 var \$thisScriptUrl; |
| 1697 function \$static_init(){}; | 1688 function \$static_init(){}; |
| 1698 | 1689 |
| 1699 function \$initGlobals(context) { | 1690 function \$initGlobals(context) { |
| 1700 context.isolateStatics = new ${namer.ISOLATE}(); | 1691 context.isolateStatics = new ${namer.isolateName}(); |
| 1701 } | 1692 } |
| 1702 function \$setGlobals(context) { | 1693 function \$setGlobals(context) { |
| 1703 $currentIsolate = context.isolateStatics; | 1694 $currentIsolate = context.isolateStatics; |
| 1704 \$globalThis = $currentIsolate; | 1695 \$globalThis = $currentIsolate; |
| 1705 } | 1696 } |
| 1706 $mainEnsureGetter | 1697 $mainEnsureGetter |
| 1707 """); | 1698 """); |
| 1708 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; | 1699 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; |
| 1709 } | 1700 } |
| 1710 | 1701 |
| 1711 emitMain(CodeBuffer buffer) { | 1702 emitMain(CodeBuffer buffer) { |
| 1712 if (compiler.isMockCompilation) return; | 1703 if (compiler.isMockCompilation) return; |
| 1713 Element main = compiler.mainApp.find(Compiler.MAIN); | 1704 Element main = compiler.mainApp.find(Compiler.MAIN); |
| 1714 String mainCall = null; | 1705 String mainCall = null; |
| 1715 if (compiler.isolateLibrary != null) { | 1706 if (compiler.isolateLibrary != null) { |
| 1716 Element isolateMain = | 1707 Element isolateMain = |
| 1717 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); | 1708 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); |
| 1718 mainCall = buildIsolateSetup(buffer, main, isolateMain); | 1709 mainCall = buildIsolateSetup(buffer, main, isolateMain); |
| 1719 } else { | 1710 } else { |
| 1720 mainCall = '${namer.isolateAccess(main)}()'; | 1711 mainCall = '${namer.isolateAccess(main)}()'; |
| 1721 } | 1712 } |
| 1722 buffer.add(""" | 1713 buffer.add(""" |
| 1723 | 1714 |
| 1724 // | 1715 // |
| 1725 // BEGIN invoke [main]. | 1716 // BEGIN invoke [main]. |
| 1726 // | 1717 // |
| 1727 if (typeof document != 'undefined' && document.readyState != 'complete') { | 1718 if (typeof document !== 'undefined' && document.readyState !== 'complete') { |
| 1728 document.addEventListener('readystatechange', function () { | 1719 document.addEventListener('readystatechange', function () { |
| 1729 if (document.readyState == 'complete') { | 1720 if (document.readyState == 'complete') { |
| 1730 if (typeof dartMainRunner == 'function') { | 1721 if (typeof dartMainRunner === 'function') { |
| 1731 dartMainRunner(function() { ${mainCall}; }); | 1722 dartMainRunner(function() { ${mainCall}; }); |
| 1732 } else { | 1723 } else { |
| 1733 ${mainCall}; | 1724 ${mainCall}; |
| 1734 } | 1725 } |
| 1735 } | 1726 } |
| 1736 }, false); | 1727 }, false); |
| 1737 } else { | 1728 } else { |
| 1738 if (typeof dartMainRunner == 'function') { | 1729 if (typeof dartMainRunner === 'function') { |
| 1739 dartMainRunner(function() { ${mainCall}; }); | 1730 dartMainRunner(function() { ${mainCall}; }); |
| 1740 } else { | 1731 } else { |
| 1741 ${mainCall}; | 1732 ${mainCall}; |
| 1742 } | 1733 } |
| 1743 } | 1734 } |
| 1744 // | 1735 // |
| 1745 // END invoke [main]. | 1736 // END invoke [main]. |
| 1746 // | 1737 // |
| 1747 | 1738 |
| 1748 """); | 1739 """); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 emitInterceptorCheck(cls, buffer); | 1782 emitInterceptorCheck(cls, buffer); |
| 1792 } | 1783 } |
| 1793 } | 1784 } |
| 1794 buffer.add('\n return $objectName.prototype;\n};\n'); | 1785 buffer.add('\n return $objectName.prototype;\n};\n'); |
| 1795 }); | 1786 }); |
| 1796 } | 1787 } |
| 1797 | 1788 |
| 1798 String assembleProgram() { | 1789 String assembleProgram() { |
| 1799 measure(() { | 1790 measure(() { |
| 1800 mainBuffer.add(HOOKS_API_USAGE); | 1791 mainBuffer.add(HOOKS_API_USAGE); |
| 1801 mainBuffer.add('function ${namer.ISOLATE}() {}\n'); | 1792 mainBuffer.add('function ${namer.isolateName}() {}\n'); |
| 1802 mainBuffer.add('init();\n\n'); | 1793 mainBuffer.add('init();\n\n'); |
| 1803 // Shorten the code by using "$$" as temporary. | 1794 // Shorten the code by using "$$" as temporary. |
| 1804 classesCollector = r"$$"; | 1795 classesCollector = r"$$"; |
| 1805 mainBuffer.add('var $classesCollector = {};\n'); | 1796 mainBuffer.add('var $classesCollector = {};\n'); |
| 1806 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. | 1797 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. |
| 1807 isolateProperties = namer.CURRENT_ISOLATE; | 1798 isolateProperties = namer.CURRENT_ISOLATE; |
| 1808 mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); | 1799 mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); |
| 1809 emitClasses(mainBuffer); | 1800 emitClasses(mainBuffer); |
| 1810 mainBuffer.add(boundClosureBuffer); | 1801 mainBuffer.add(boundClosureBuffer); |
| 1811 // Clear the buffer, so that we can reuse it for the native classes. | 1802 // Clear the buffer, so that we can reuse it for the native classes. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1827 // initialStatics. | 1818 // initialStatics. |
| 1828 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); | 1819 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); |
| 1829 mainBuffer.add(boundClosureBuffer); | 1820 mainBuffer.add(boundClosureBuffer); |
| 1830 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1821 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1831 // After this assignment we will produce invalid JavaScript code if we use | 1822 // After this assignment we will produce invalid JavaScript code if we use |
| 1832 // the classesCollector variable. | 1823 // the classesCollector variable. |
| 1833 classesCollector = 'classesCollector should not be used from now on'; | 1824 classesCollector = 'classesCollector should not be used from now on'; |
| 1834 | 1825 |
| 1835 emitFinishIsolateConstructorInvocation(mainBuffer); | 1826 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 1836 mainBuffer.add( | 1827 mainBuffer.add( |
| 1837 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 1828 'var ${namer.CURRENT_ISOLATE} = new ${namer.isolateName}();\n'); |
| 1838 | 1829 |
| 1839 nativeEmitter.assembleCode(mainBuffer); | 1830 nativeEmitter.assembleCode(mainBuffer); |
| 1840 emitMain(mainBuffer); | 1831 emitMain(mainBuffer); |
| 1841 mainBuffer.add('function init() {\n'); | 1832 mainBuffer.add('function init() {\n'); |
| 1842 mainBuffer.add('$isolateProperties = {};\n'); | 1833 mainBuffer.add('$isolateProperties = {};\n'); |
| 1843 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 1834 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); |
| 1844 addLazyInitializerFunctionIfNecessary(mainBuffer); | 1835 addLazyInitializerFunctionIfNecessary(mainBuffer); |
| 1845 emitFinishIsolateConstructor(mainBuffer); | 1836 emitFinishIsolateConstructor(mainBuffer); |
| 1846 mainBuffer.add('}\n'); | 1837 mainBuffer.add('}\n'); |
| 1847 compiler.assembledCode = mainBuffer.toString(); | 1838 compiler.assembledCode = mainBuffer.toString(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1871 const String HOOKS_API_USAGE = """ | 1862 const String HOOKS_API_USAGE = """ |
| 1872 // Generated by dart2js, the Dart to JavaScript compiler. | 1863 // Generated by dart2js, the Dart to JavaScript compiler. |
| 1873 // The code supports the following hooks: | 1864 // The code supports the following hooks: |
| 1874 // dartPrint(message) - if this function is defined it is called | 1865 // dartPrint(message) - if this function is defined it is called |
| 1875 // instead of the Dart [print] method. | 1866 // instead of the Dart [print] method. |
| 1876 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1867 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 1877 // method will not be invoked directly. | 1868 // method will not be invoked directly. |
| 1878 // Instead, a closure that will invoke [main] is | 1869 // Instead, a closure that will invoke [main] is |
| 1879 // passed to [dartMainRunner]. | 1870 // passed to [dartMainRunner]. |
| 1880 """; | 1871 """; |
| OLD | NEW |