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

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

Issue 14018036: Remove holders for runtime type information. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix type annotation. Created 7 years, 7 months 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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 // Example: 293 // Example:
294 // defineClass("A", ["x", "y"], { 294 // defineClass("A", ["x", "y"], {
295 // foo$1: function(y) { 295 // foo$1: function(y) {
296 // print(this.x + y); 296 // print(this.x + y);
297 // }, 297 // },
298 // bar$2: function(t, v) { 298 // bar$2: function(t, v) {
299 // this.x = t - v; 299 // this.x = t - v;
300 // }, 300 // },
301 // }); 301 // });
302 302
303 // function(cls, fields, prototype) { 303 var defineClass = js.fun(['name', 'cls', 'fields', 'prototype'], [
304 var defineClass = js.fun(['cls', 'fields', 'prototype'], [
305 js('var constructor'), 304 js('var constructor'),
306 305
307 // if (typeof fields == "function") {
308 js.if_(js('typeof fields == "function"'), [ 306 js.if_(js('typeof fields == "function"'), [
309 js('constructor = fields') 307 js('constructor = fields')
310 ], /* else */ [ 308 ], /* else */ [
311 js('var str = "function " + cls + "("'), 309 js('var str = "function " + cls + "("'),
312 js('var body = ""'), 310 js('var body = ""'),
313 311
314 // for (var i = 0; i < fields.length; i++) {
315 js.for_('var i = 0', 'i < fields.length', 'i++', [ 312 js.for_('var i = 0', 'i < fields.length', 'i++', [
316 // if (i != 0) str += ", ";
317 js.if_('i != 0', js('str += ", "')), 313 js.if_('i != 0', js('str += ", "')),
318 314
319 js('var field = fields[i]'), 315 js('var field = fields[i]'),
320 js('field = generateAccessor(field, prototype)'), 316 js('field = generateAccessor(field, prototype)'),
321 js('str += field'), 317 js('str += field'),
322 js('body += ("this." + field + " = " + field + ";\\n")') 318 js('body += ("this." + field + " = " + field + ";\\n")')
323 ]), 319 ]),
324 320
325 js('str += (") {" + body + "}\\nreturn " + cls)'), 321 js('str += (") {" + body + "}\\nreturn " + cls)'),
326 322
327 js('constructor = new Function(str)()') 323 js('constructor = new Function(str)()')
328 ]), 324 ]),
329 325
330 js('constructor.prototype = prototype'), 326 js('constructor.prototype = prototype'),
331 js('constructor.builtin\$cls = cls'), 327 js(r'constructor.builtin$cls = name'),
332 328
333 // return constructor;
334 js.return_('constructor') 329 js.return_('constructor')
335 ]); 330 ]);
336 // Declare a function called "generateAccessor". This is used in 331 // Declare a function called "generateAccessor". This is used in
337 // defineClassFunction (it's a local declaration in init()). 332 // defineClassFunction (it's a local declaration in init()).
338 return [ 333 return [
339 generateAccessorFunction, 334 generateAccessorFunction,
340 js('$generateAccessorHolder = generateAccessor'), 335 js('$generateAccessorHolder = generateAccessor'),
341 new jsAst.FunctionDeclaration( 336 new jsAst.FunctionDeclaration(
342 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; 337 new jsAst.VariableDeclaration('defineClass'), defineClass) ];
343 } 338 }
344 339
345 /** Needs defineClass to be defined. */ 340 /** Needs defineClass to be defined. */
346 List buildProtoSupportCheck() { 341 List buildProtoSupportCheck() {
347 // On Firefox and Webkit browsers we can manipulate the __proto__ 342 // On Firefox and Webkit browsers we can manipulate the __proto__
348 // directly. Opera claims to have __proto__ support, but it is buggy. 343 // directly. Opera claims to have __proto__ support, but it is buggy.
349 // So we have to do more checks. 344 // So we have to do more checks.
350 // Opera bug was filed as DSK-370158, and fixed as CORE-47615 345 // Opera bug was filed as DSK-370158, and fixed as CORE-47615
351 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). 346 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes).
352 // If the browser does not support __proto__ we need to instantiate an 347 // If the browser does not support __proto__ we need to instantiate an
353 // object with the correct (internal) prototype set up correctly, and then 348 // object with the correct (internal) prototype set up correctly, and then
354 // copy the members. 349 // copy the members.
355 // TODO(8541): Remove this work around. 350 // TODO(8541): Remove this work around.
356 351
357 return [ 352 return [
358 js('var $supportsProtoName = false'), 353 js('var $supportsProtoName = false'),
359 js('var tmp = defineClass("c", ["f?"], {}).prototype'), 354 js('var tmp = defineClass("c", "c", ["f?"], {}).prototype'),
360 355
361 js.if_(js('tmp.__proto__'), [ 356 js.if_(js('tmp.__proto__'), [
362 js('tmp.__proto__ = {}'), 357 js('tmp.__proto__ = {}'),
363 js.if_(js(r'typeof tmp.get$f != "undefined"'), 358 js.if_(js(r'typeof tmp.get$f != "undefined"'),
364 js('$supportsProtoName = true')) 359 js('$supportsProtoName = true'))
365 360
366 ]) 361 ])
367 ]; 362 ];
368 } 363 }
369 364
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 // constructor. 592 // constructor.
598 // For engines where we have access to the '__proto__' we can manipulate 593 // For engines where we have access to the '__proto__' we can manipulate
599 // the object literal directly. For other engines we have to create a new 594 // the object literal directly. For other engines we have to create a new
600 // object and copy over the members. 595 // object and copy over the members.
601 596
602 List<jsAst.Node> statements = [ 597 List<jsAst.Node> statements = [
603 js('var pendingClasses = {}'), 598 js('var pendingClasses = {}'),
604 599
605 js('var hasOwnProperty = Object.prototype.hasOwnProperty'), 600 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
606 601
607 // for (var cls in collectedClasses)
608 js.forIn('cls', 'collectedClasses', [ 602 js.forIn('cls', 'collectedClasses', [
609 // if (hasOwnProperty.call(collectedClasses, cls))
610 js.if_('hasOwnProperty.call(collectedClasses, cls)', [ 603 js.if_('hasOwnProperty.call(collectedClasses, cls)', [
611 js('var desc = collectedClasses[cls]'), 604 js('var desc = collectedClasses[cls]'),
612 605
613 /* The 'fields' are either a constructor function or a 606 /* The 'fields' are either a constructor function or a
614 * string encoding fields, constructor and superclass. Get 607 * string encoding fields, constructor and superclass. Get
615 * the superclass and the fields in the format 608 * the superclass and the fields in the format
616 * Super;field1,field2 from the null-string property on the 609 * '[name/]Super;field1,field2'
617 * descriptor. 610 * from the null-string property on the descriptor.
611 * The 'name/' is optional and contains the name that should be used
612 * when printing the runtime type string. It is used, for example, to
613 * print the runtime type JSInt as 'int'.
618 */ 614 */
619 js('var fields = desc[""], supr'), 615 js('var classData = desc[""], supr, name, fields'),
616 js('var split = classData.split("/")'),
617 js.if_('split.length == 2', [
618 js('name = split[0]'),
619 js('fields = split[1]')
620 ], /* else */ [
621 js('name = cls'),
622 js('fields = classData')
623 ]),
620 624
621 js.if_('typeof fields == "string"', [ 625 js.if_('typeof fields == "string"', [
622 js('var s = fields.split(";")'), 626 js('var s = fields.split(";")'),
623 js('fields = s[1] == "" ? [] : s[1].split(",")'), 627 js('fields = s[1] == "" ? [] : s[1].split(",")'),
624 js('supr = s[0]'), 628 js('supr = s[0]'),
625 ], /* else */ [ 629 ], /* else */ [
626 js('supr = desc.super'), 630 js('supr = desc.super'),
627 ]), 631 ]),
628 632
629 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [ 633 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [
630 js('s = supr.split("+")'), 634 js('s = supr.split("+")'),
631 js('supr = s[0]'), 635 js('supr = s[0]'),
632 js('var mixin = collectedClasses[s[1]]'), 636 js('var mixin = collectedClasses[s[1]]'),
633 js.forIn('d', 'mixin', [ 637 js.forIn('d', 'mixin', [
634 js.if_('hasOwnProperty.call(mixin, d)' 638 js.if_('hasOwnProperty.call(mixin, d)'
635 '&& !hasOwnProperty.call(desc, d)', 639 '&& !hasOwnProperty.call(desc, d)',
636 js('desc[d] = mixin[d]')) 640 js('desc[d] = mixin[d]'))
637 ]), 641 ]),
638 ])), 642 ])),
639 643
640 js('isolateProperties[cls] = defineClass(cls, fields, desc)'), 644 js('isolateProperties[cls] = defineClass(name, cls, fields, desc)'),
641 js.if_('supr', js('pendingClasses[cls] = supr')) 645 js.if_('supr', js('pendingClasses[cls] = supr'))
642 ]) 646 ])
643 ]), 647 ]),
644 648
645 js('var finishedClasses = {}'), 649 js('var finishedClasses = {}'),
646 650
647 buildFinishClass(), 651 buildFinishClass(),
648 ]; 652 ];
649 653
650 addTrivialNsmHandlers(statements); 654 addTrivialNsmHandlers(statements);
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 } 1211 }
1208 1212
1209 void emitIsTests(ClassElement classElement, ClassBuilder builder) { 1213 void emitIsTests(ClassElement classElement, ClassBuilder builder) {
1210 assert(invariant(classElement, classElement.isDeclaration)); 1214 assert(invariant(classElement, classElement.isDeclaration));
1211 1215
1212 void generateIsTest(Element other) { 1216 void generateIsTest(Element other) {
1213 if (other == compiler.objectClass && other != classElement) { 1217 if (other == compiler.objectClass && other != classElement) {
1214 // Avoid emitting [:$isObject:] on all classes but [Object]. 1218 // Avoid emitting [:$isObject:] on all classes but [Object].
1215 return; 1219 return;
1216 } 1220 }
1221 other = backend.getImplementationClass(other);
1217 builder.addProperty(namer.operatorIs(other), js('true')); 1222 builder.addProperty(namer.operatorIs(other), js('true'));
1218 } 1223 }
1219 1224
1220 void generateSubstitution(Element other, {bool emitNull: false}) { 1225 void generateSubstitution(Element other, {bool emitNull: false}) {
1221 RuntimeTypes rti = backend.rti; 1226 RuntimeTypes rti = backend.rti;
1222 // TODO(karlklose): support typedefs with variables. 1227 // TODO(karlklose): support typedefs with variables.
1223 jsAst.Expression expression; 1228 jsAst.Expression expression;
1224 bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other); 1229 bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other);
1225 if (other.kind == ElementKind.CLASS) { 1230 if (other.kind == ElementKind.CLASS) {
1226 String substitution = rti.getSupertypeSubstitution(classElement, other, 1231 String substitution = rti.getSupertypeSubstitution(classElement, other,
1227 alwaysGenerateFunction: true); 1232 alwaysGenerateFunction: true);
1228 if (substitution != null) { 1233 if (substitution != null) {
1229 expression = new jsAst.LiteralExpression(substitution); 1234 expression = new jsAst.LiteralExpression(substitution);
1230 } else if (emitNull || needsNativeCheck) { 1235 } else if (emitNull || needsNativeCheck) {
1231 expression = new jsAst.LiteralNull(); 1236 expression = new jsAst.LiteralNull();
1232 } 1237 }
1233 } 1238 }
1234 if (expression != null) { 1239 if (expression != null) {
1235 builder.addProperty(namer.substitutionName(other), expression); 1240 builder.addProperty(namer.substitutionName(other), expression);
1236 } 1241 }
1237 } 1242 }
1238 1243
1239 generateIsTestsOn(classElement, generateIsTest, generateSubstitution); 1244 generateIsTestsOn(classElement, generateIsTest, generateSubstitution);
1240 } 1245 }
1241 1246
1242 void emitRuntimeTypeSupport(CodeBuffer buffer) { 1247 void emitRuntimeTypeSupport(CodeBuffer buffer) {
1243 RuntimeTypes rti = backend.rti; 1248 RuntimeTypes rti = backend.rti;
1244 TypeChecks typeChecks = rti.getRequiredChecks(); 1249 TypeChecks typeChecks = rti.requiredChecks;
1245 1250
1246 /// Classes that are not instantiated and native classes need a holder 1251 // Add checks to the constructors of instantiated classes.
1247 /// object for their checks, because there will be no class defined for
1248 /// them.
1249
1250 // TODO(9556): Get rid of holders.
1251 //
1252 // - For primitive classes, use the interceptors (e.g JSInt).
1253 //
1254 // - For uninstantiated classes, define the class anyway. It will not need
1255 // fields or a constructor, or any methods, so the class definition will
1256 // be smaller than a holder.
1257
1258 bool needsHolder(ClassElement cls) {
1259 return !neededClasses.contains(cls) ||
1260 rti.isJsNative(cls);
1261 }
1262
1263 /**
1264 * Generates a holder object if it is needed. A holder is a JavaScript
1265 * object literal with a field [builtin$cls] that contains the name of the
1266 * class as a string (just like object constructors do). The is-checks for
1267 * the class are are added to the holder object later.
1268 */
1269 void maybeGenerateHolder(ClassElement cls) {
1270 if (!needsHolder(cls)) return;
1271 String holder = namer.isolateAccess(cls);
1272 String name = namer.getRuntimeTypeName(cls);
1273 buffer.write('$holder$_=$_{builtin\$cls:$_"$name"');
1274 buffer.write('}$N');
1275 }
1276
1277 // Create representation objects for classes that we do not have a class
1278 // definition for (because they are uninstantiated or native).
1279 for (ClassElement cls in rti.allArguments) {
1280 maybeGenerateHolder(cls);
1281 }
1282
1283 // Add checks to the constructors of instantiated classes or to the created
1284 // holder object.
1285 for (ClassElement cls in typeChecks) { 1252 for (ClassElement cls in typeChecks) {
1286 String holder = namer.isolateAccess(cls); 1253 String holder = namer.isolateAccess(backend.getImplementationClass(cls));
1287 for (ClassElement check in typeChecks[cls]) { 1254 for (ClassElement check in typeChecks[cls]) {
1288 buffer.write('$holder.${namer.operatorIs(check)}$_=${_}true$N'); 1255 buffer.write('$holder.${namer.operatorIs(check)}$_=${_}true$N');
1289 String body = rti.getSupertypeSubstitution(cls, check); 1256 String body = rti.getSupertypeSubstitution(cls, check);
1290 if (body != null) { 1257 if (body != null) {
1291 buffer.write('$holder.${namer.substitutionName(check)}$_=${_}$body$N') ; 1258 buffer.write('$holder.${namer.substitutionName(check)}$_=${_}$body$N') ;
1292 } 1259 }
1293 }; 1260 };
1294 } 1261 }
1295 } 1262 }
1296 1263
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 /* Do nothing. */ 1418 /* Do nothing. */
1452 } 1419 }
1453 1420
1454 /// Returns `true` if fields added. 1421 /// Returns `true` if fields added.
1455 bool emitClassFields(ClassElement classElement, 1422 bool emitClassFields(ClassElement classElement,
1456 ClassBuilder builder, 1423 ClassBuilder builder,
1457 String superName, 1424 String superName,
1458 { bool classIsNative: false }) { 1425 { bool classIsNative: false }) {
1459 assert(superName != null); 1426 assert(superName != null);
1460 String separator = ''; 1427 String separator = '';
1461 StringBuffer buffer = new StringBuffer('$superName;'); 1428 String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement);
1429 StringBuffer buffer = new StringBuffer();
1430 if (nativeName != null) {
1431 buffer.write('$nativeName/');
1432 }
1433 buffer.write('$superName;');
1462 int bufferClassLength = buffer.length; 1434 int bufferClassLength = buffer.length;
1463 1435
1464 visitClassFields(classElement, (Element member, 1436 visitClassFields(classElement, (Element member,
1465 String name, 1437 String name,
1466 String accessorName, 1438 String accessorName,
1467 bool needsGetter, 1439 bool needsGetter,
1468 bool needsSetter, 1440 bool needsSetter,
1469 bool needsCheckedSetter) { 1441 bool needsCheckedSetter) {
1470 // Ignore needsCheckedSetter - that is handled below. 1442 // Ignore needsCheckedSetter - that is handled below.
1471 bool needsAccessor = (needsGetter || needsSetter); 1443 bool needsAccessor = (needsGetter || needsSetter);
(...skipping 16 matching lines...) Expand all
1488 buffer.write(':$name'); 1460 buffer.write(':$name');
1489 // Only the native classes can have renaming accessors. 1461 // Only the native classes can have renaming accessors.
1490 assert(classIsNative); 1462 assert(classIsNative);
1491 } 1463 }
1492 1464
1493 int getterCode = 0; 1465 int getterCode = 0;
1494 if (needsGetter) { 1466 if (needsGetter) {
1495 // 01: function() { return this.field; } 1467 // 01: function() { return this.field; }
1496 // 10: function(receiver) { return receiver.field; } 1468 // 10: function(receiver) { return receiver.field; }
1497 // 11: function(receiver) { return this.field; } 1469 // 11: function(receiver) { return this.field; }
1498 getterCode += backend.fieldHasInterceptedGetter(member) ? 2 : 0; 1470 getterCode += backend.fieldHasInterceptedGetter(member) ? 2 : 0;
ahe 2013/07/19 16:30:25 Read my comment on line 2602 first. Consider CssS
1499 getterCode += backend.isInterceptorClass(classElement) ? 0 : 1; 1471 getterCode += backend.isInterceptorClass(classElement) ? 0 : 1;
ahe 2013/07/19 16:30:25 For CssStyleDeclaration.cssText, classElement is a
1500 // TODO(sra): 'isInterceptorClass' might not be the correct test for 1472 // TODO(sra): 'isInterceptorClass' might not be the correct test for
1501 // methods forced to use the interceptor convention because the 1473 // methods forced to use the interceptor convention because the
1502 // method's class was elsewhere mixed-in to an interceptor. 1474 // method's class was elsewhere mixed-in to an interceptor.
1503 assert(getterCode != 0); 1475 assert(getterCode != 0);
ahe 2013/07/19 16:30:25 This assertion fails.
1504 } 1476 }
1505 int setterCode = 0; 1477 int setterCode = 0;
1506 if (needsSetter) { 1478 if (needsSetter) {
1507 // 01: function(value) { this.field = value; } 1479 // 01: function(value) { this.field = value; }
1508 // 10: function(receiver, value) { receiver.field = value; } 1480 // 10: function(receiver, value) { receiver.field = value; }
1509 // 11: function(receiver, value) { this.field = value; } 1481 // 11: function(receiver, value) { this.field = value; }
1510 setterCode += backend.fieldHasInterceptedSetter(member) ? 2 : 0; 1482 setterCode += backend.fieldHasInterceptedSetter(member) ? 2 : 0;
1511 setterCode += backend.isInterceptorClass(classElement) ? 0 : 1; 1483 setterCode += backend.isInterceptorClass(classElement) ? 0 : 1;
1512 assert(setterCode != 0); 1484 assert(setterCode != 0);
1513 } 1485 }
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after
2611 } 2583 }
2612 2584
2613 /** 2585 /**
2614 * Compute all the classes that must be emitted. 2586 * Compute all the classes that must be emitted.
2615 */ 2587 */
2616 void computeNeededClasses() { 2588 void computeNeededClasses() {
2617 instantiatedClasses = 2589 instantiatedClasses =
2618 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) 2590 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter())
2619 .toSet(); 2591 .toSet();
2620 2592
2621 // The set of classes that must be emitted are based on instantiated 2593 RuntimeTypes rti = backend.rti;
2622 // classes. 2594
2595 // We need to generate classes that are instantiated or used as a type
2596 // arguments.
2623 neededClasses.addAll(instantiatedClasses); 2597 neededClasses.addAll(instantiatedClasses);
2598 rti.allArguments.forEach((ClassElement c) {
2599 // Types that we represent with JS native types (like int and String) do
2600 // not need a class definition as we use the interceptor classes instead.
2601 if (!rti.isJsNative(c)) {
2602 neededClasses.add(c);
ahe 2013/07/19 16:30:25 I'm not sure how this is supposed to work? These
2603 }
2604 });
2624 2605
2625 // Then add all superclasses of these classes. 2606 // Then add all superclasses of these classes.
2626 for (ClassElement element in neededClasses.toList() /* copy */) { 2607 for (ClassElement element in neededClasses.toList() /* copy */) {
2627 for (ClassElement superclass = element.superclass; 2608 for (ClassElement superclass = element.superclass;
2628 superclass != null; 2609 superclass != null;
2629 superclass = superclass.superclass) { 2610 superclass = superclass.superclass) {
2630 if (neededClasses.contains(superclass)) break; 2611 if (neededClasses.contains(superclass)) break;
2631 neededClasses.add(superclass); 2612 neededClasses.add(superclass);
2632 } 2613 }
2633 } 2614 }
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
2882 ..addAll(buildLazyInitializerFunctionIfNecessary()) 2863 ..addAll(buildLazyInitializerFunctionIfNecessary())
2883 ..addAll(buildFinishIsolateConstructor()) 2864 ..addAll(buildFinishIsolateConstructor())
2884 ); 2865 );
2885 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( 2866 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration(
2886 new jsAst.VariableDeclaration('init'), fun); 2867 new jsAst.VariableDeclaration('init'), fun);
2887 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); 2868 buffer.write(jsAst.prettyPrint(decl, compiler).getText());
2888 } 2869 }
2889 2870
2890 String assembleProgram() { 2871 String assembleProgram() {
2891 measure(() { 2872 measure(() {
2892 computeNeededClasses();
2893
2894 // Compute the required type checks to know which classes need a 2873 // Compute the required type checks to know which classes need a
2895 // 'is$' method. 2874 // 'is$' method.
2896 computeRequiredTypeChecks(); 2875 computeRequiredTypeChecks();
2897 2876
2877 computeNeededClasses();
2878
2898 mainBuffer.add(GENERATED_BY); 2879 mainBuffer.add(GENERATED_BY);
2899 addComment(HOOKS_API_USAGE, mainBuffer); 2880 addComment(HOOKS_API_USAGE, mainBuffer);
2900 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); 2881 mainBuffer.add('function ${namer.isolateName}()$_{}\n');
2901 mainBuffer.add('init()$N$n'); 2882 mainBuffer.add('init()$N$n');
2902 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. 2883 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
2903 isolateProperties = namer.CURRENT_ISOLATE; 2884 isolateProperties = namer.CURRENT_ISOLATE;
2904 mainBuffer.add( 2885 mainBuffer.add(
2905 'var $isolateProperties$_=$_$isolatePropertiesName$N'); 2886 'var $isolateProperties$_=$_$isolatePropertiesName$N');
2906 2887
2907 if (!regularClasses.isEmpty || 2888 if (!regularClasses.isEmpty ||
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3074 """; 3055 """;
3075 const String HOOKS_API_USAGE = """ 3056 const String HOOKS_API_USAGE = """
3076 // The code supports the following hooks: 3057 // The code supports the following hooks:
3077 // dartPrint(message) - if this function is defined it is called 3058 // dartPrint(message) - if this function is defined it is called
3078 // instead of the Dart [print] method. 3059 // instead of the Dart [print] method.
3079 // dartMainRunner(main) - if this function is defined, the Dart [main] 3060 // dartMainRunner(main) - if this function is defined, the Dart [main]
3080 // method will not be invoked directly. 3061 // method will not be invoked directly.
3081 // Instead, a closure that will invoke [main] is 3062 // Instead, a closure that will invoke [main] is
3082 // passed to [dartMainRunner]. 3063 // passed to [dartMainRunner].
3083 """; 3064 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698