Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(513)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 11453032: Reapply class/method/field minification (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Review feedback Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698