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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart

Issue 1234493003: dart2js: fill in the basic functionality of the startup emitter. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comments. Created 5 years, 5 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
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 dart2js.js_emitter.startup_emitter.model_emitter; 5 part of dart2js.js_emitter.startup_emitter.model_emitter;
6 6
7 /// The fast startup emitter's goal is to minimize the amount of work that the 7 /// The fast startup emitter's goal is to minimize the amount of work that the
8 /// JavaScript engine has to do before it can start running user code. 8 /// JavaScript engine has to do before it can start running user code.
9 /// 9 ///
10 /// Whenever possible, the emitter uses object literals instead of updating 10 /// Whenever possible, the emitter uses object literals instead of updating
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 // Makes [cls] inherit from [sup]. 50 // Makes [cls] inherit from [sup].
51 // On Chrome, Firefox and recent IEs this happens by updating the internal 51 // On Chrome, Firefox and recent IEs this happens by updating the internal
52 // proto-property of the classes 'prototype' field. 52 // proto-property of the classes 'prototype' field.
53 // Older IEs use `Object.create` and copy over the properties. 53 // Older IEs use `Object.create` and copy over the properties.
54 function inherit(cls, sup) { 54 function inherit(cls, sup) {
55 // TODO(floitsch): IE doesn't support changing the __proto__ property. There, 55 // TODO(floitsch): IE doesn't support changing the __proto__ property. There,
56 // we need to copy the properties instead. 56 // we need to copy the properties instead.
57 cls.#typeNameProperty = cls.name; // Needed for RTI. 57 cls.#typeNameProperty = cls.name; // Needed for RTI.
58 cls.prototype.constructor = cls; 58 cls.prototype.constructor = cls;
59 cls.prototype[#operatorIsPrefix + cls.name] = cls; 59 cls.prototype[#operatorIsPrefix + cls.name] = cls;
60 cls.prototype.__proto__ = sup.prototype; 60
61 // The superclass is only null for the Dart Object.
62 if (sup != null) {
63 cls.prototype.__proto__ = sup.prototype;
64 }
61 } 65 }
62 66
63 // Mixes in the properties of [mixin] into [cls]. 67 // Mixes in the properties of [mixin] into [cls].
64 function mixin(cls, mixin) { 68 function mixin(cls, mixin) {
65 copyProperties(mixin.prototype, cls.prototype); 69 copyProperties(mixin.prototype, cls.prototype);
66 } 70 }
67 71
68 // Creates a lazy field. 72 // Creates a lazy field.
69 // 73 //
70 // A lazy field has a storage entry, [name], which holds the value, and a 74 // A lazy field has a storage entry, [name], which holds the value, and a
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 var oldPrototype = holder.__proto__; 153 var oldPrototype = holder.__proto__;
150 newHolder.__proto__ = oldPrototype; 154 newHolder.__proto__ = oldPrototype;
151 holder.__proto__ = newHolder; 155 holder.__proto__ = newHolder;
152 return holder; 156 return holder;
153 } 157 }
154 158
155 // Every deferred hunk (i.e. fragment) is a function that we can invoke to 159 // Every deferred hunk (i.e. fragment) is a function that we can invoke to
156 // initialize it. At this moment it contributes its data to the main hunk. 160 // initialize it. At this moment it contributes its data to the main hunk.
157 function initializeDeferredHunk(hunk) { 161 function initializeDeferredHunk(hunk) {
158 // TODO(floitsch): extend natives. 162 // TODO(floitsch): extend natives.
159 hunk(derive, mixin, lazy, makeConstList, installTearOff, 163 hunk(inherit, mixin, lazy, makeConstList, installTearOff,
160 updateHolder, updateTypes, updateInterceptorsByTag, updateLeafTags, 164 updateHolder, updateTypes, updateInterceptorsByTag, updateLeafTags,
161 #embeddedGlobalsObject, #holdersList, #currentIsolate); 165 #embeddedGlobalsObject, #holdersList, #staticState);
162 } 166 }
163 167
164 // Creates the holders. 168 // Creates the holders.
165 #holders; 169 #holders;
170 // TODO(floitsch): if name is not set (for example in IE), run through all
171 // functions and set the name.
172
173 // TODO(floitsch): we should build this object as a literal.
174 var #staticStateDeclaration = {};
175
166 // Sets the prototypes of classes. 176 // Sets the prototypes of classes.
167 #prototypes; 177 #prototypes;
168 // Sets aliases of methods (on the prototypes of classes). 178 // Sets aliases of methods (on the prototypes of classes).
169 #aliases; 179 #aliases;
170 // Installs the tear-offs of functions. 180 // Installs the tear-offs of functions.
171 #tearOffs; 181 #tearOffs;
172 // Builds the inheritance structure. 182 // Builds the inheritance structure.
173 #inheritance; 183 #inheritance;
174 184
175 // Emits the embedded globals. 185 // Emits the embedded globals.
(...skipping 16 matching lines...) Expand all
192 }'''; 202 }''';
193 203
194 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment. 204 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
195 /// 205 ///
196 /// However, at specific moments they need to contribute their data. 206 /// However, at specific moments they need to contribute their data.
197 /// For example, once the holders have been created, they are included into 207 /// For example, once the holders have been created, they are included into
198 /// the main holders. 208 /// the main holders.
199 const String deferredBoilerplate = ''' 209 const String deferredBoilerplate = '''
200 { 210 {
201 #deferredInitializers.current = 211 #deferredInitializers.current =
202 function(derive, mixin, lazy, makeConstList, installTearOff, 212 function(inherit, mixin, lazy, makeConstList, installTearOff,
203 updateHolder, updateTypes, 213 updateHolder, updateTypes,
204 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags, 214 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
205 #embeddedGlobalsObject, holdersList, #currentIsolate) { 215 #embeddedGlobalsObject, holdersList, #staticState) {
206 216
207 // Builds the holders. They only contain the data for new holders. 217 // Builds the holders. They only contain the data for new holders.
208 #holders; 218 #holders;
209 // Updates the holders of the main-fragment. Uses the provided holdersList to 219 // Updates the holders of the main-fragment. Uses the provided holdersList to
210 // access the main holders. 220 // access the main holders.
211 // The local holders are replaced by the combined holders. This is necessary 221 // The local holders are replaced by the combined holders. This is necessary
212 // for the inheritance setup below. 222 // for the inheritance setup below.
213 #updateHolders; 223 #updateHolders;
214 // Sets the prototypes of the new classes. 224 // Sets the prototypes of the new classes.
215 #prototypes; 225 #prototypes;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 266
257 FragmentEmitter(this.compiler, this.namer, this.backend, this.constantEmitter, 267 FragmentEmitter(this.compiler, this.namer, this.backend, this.constantEmitter,
258 this.modelEmitter); 268 this.modelEmitter);
259 269
260 js.Expression generateEmbeddedGlobalAccess(String global) => 270 js.Expression generateEmbeddedGlobalAccess(String global) =>
261 modelEmitter.generateEmbeddedGlobalAccess(global); 271 modelEmitter.generateEmbeddedGlobalAccess(global);
262 272
263 js.Expression generateConstantReference(ConstantValue value) => 273 js.Expression generateConstantReference(ConstantValue value) =>
264 modelEmitter.generateConstantReference(value); 274 modelEmitter.generateConstantReference(value);
265 275
276 js.Expression classReference(Class cls) {
277 return js.js('#.#', [cls.holder.name, cls.name]);
278 }
279
266 js.Statement emitMainFragment(Program program) { 280 js.Statement emitMainFragment(Program program) {
267 MainFragment fragment = program.fragments.first; 281 MainFragment fragment = program.fragments.first;
268 throw new UnimplementedError('emitMain'); 282
283 return js.js.statement(mainBoilerplate,
284 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
285 'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
286 'cyclicThrow': backend.emitter.staticFunctionAccess(
287 backend.getCyclicThrowHelper()),
288 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
289 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
290 'embeddedInterceptorTags':
291 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
292 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
293 'embeddedGlobalsObject': js.js("init"),
294 'holdersList': new js.ArrayInitializer(program.holders.map((holder) {
295 return js.js("#", holder.name);
296 }).toList()),
297 'staticStateDeclaration': new js.VariableDeclaration(
298 namer.staticStateHolder, allowRename: false),
299 'staticState': js.js('#', namer.staticStateHolder),
300 'holders': emitHolders(program.holders, fragment),
301 'callName': js.string(namer.callNameField),
302 'argumentCount': js.string(namer.requiredParameterField),
303 'defaultArgumentValues': js.string(namer.defaultValuesField),
304 'prototypes': emitPrototypes(fragment),
305 'inheritance': emitInheritance(fragment),
306 'aliases': emitInstanceMethodAliases(fragment),
307 'tearOffs': emitInstallTearOffs(fragment),
308 'constants': emitConstants(fragment),
309 'staticNonFinalFields': emitStaticNonFinalFields(fragment),
310 'lazyStatics': emitLazilyInitializedStatics(fragment),
311 'embeddedGlobals': emitEmbeddedGlobals(program),
312 'nativeSupport': program.needsNativeSupport
313 ? emitNativeSupport(fragment)
314 : new js.EmptyStatement(),
315 'invokeMain': fragment.invokeMain,
316 });
269 } 317 }
270 318
271 js.Statement emitDeferredFragment(DeferredFragment fragment, 319 js.Statement emitDeferredFragment(DeferredFragment fragment,
272 js.Expression deferredTypes, 320 js.Expression deferredTypes,
273 List<Holder> holders) { 321 List<Holder> holders) {
274 throw new UnimplementedError('emitDeferred'); 322 List<js.Statement> updateHolderAssignments = <js.Statement>[];
323 for (int i = 0; i < holders.length; i++) {
324 Holder holder = holders[i];
325 if (holder.isStaticStateHolder) continue;
326 updateHolderAssignments.add(js.js.statement(
327 '#holder = updateHolder(holdersList[#index], #holder)',
328 {'index': js.number(i),
329 'holder': new js.VariableUse(holder.name)}));
330 }
331
332 // TODO(floitsch): if name is not set, run through all functions and set the
333 // name for IE.
334 // TODO(floitsch): don't just reference 'init'.
335 return js.js.statement(deferredBoilerplate,
336 {'deferredInitializers':
337 js.js('#', ModelEmitter.deferredInitializersGlobal),
338 'embeddedGlobalsObject': new js.Parameter('init'),
339 'staticState': new js.Parameter(namer.staticStateHolder),
340 'holders': emitHolders(holders, fragment),
341 'updateHolders': new js.Block(updateHolderAssignments),
342 'prototypes': emitPrototypes(fragment),
343 'inheritance': emitInheritance(fragment),
344 'aliases': emitInstanceMethodAliases(fragment),
345 'tearOffs': emitInstallTearOffs(fragment),
346 'constants': emitConstants(fragment),
347 'staticNonFinalFields': emitStaticNonFinalFields(fragment),
348 'lazyStatics': emitLazilyInitializedStatics(fragment),
349 'types': deferredTypes,
350 // TODO(floitsch): only call emitNativeSupport if we need native.
351 'nativeSupport': emitNativeSupport(fragment),
352 'hash': js.number(fragment.hashCode),
353 });
354 }
355
356 js.Statement emitDeferredInitializerGlobal(Map loadMap) {
357 if (loadMap.isEmpty) return new js.Block.empty();
358
359 return js.js.statement("""
360 if (typeof(${ModelEmitter.deferredInitializersGlobal}) === 'undefined')
361 var ${ModelEmitter.deferredInitializersGlobal} = Object.create(null);""");
362 }
363
364 /// Emits all holders, except for the static-state holder.
365 ///
366 /// The emitted holders contain classes (only the constructors) and all
367 /// static functions.
368 js.Statement emitHolders(List<Holder> holders, Fragment fragment) {
369 // Skip the static-state holder in this function.
370 holders = holders
371 .where((Holder holder) => !holder.isStaticStateHolder)
372 .toList(growable: false);
373
374 Map<Holder, Map<js.Name, js.Expression>> holderCode =
375 <Holder, Map<js.Name, js.Expression>>{};
376
377 for (Holder holder in holders) {
378 holderCode[holder] = <js.Name, js.Expression>{};
379 }
380
381 for (Library library in fragment.libraries) {
382 for (StaticMethod method in library.statics) {
383 assert(!method.holder.isStaticStateHolder);
384 holderCode[method.holder].addAll(emitStaticMethod(method));
385 }
386 for (Class cls in library.classes) {
387 assert(!cls.holder.isStaticStateHolder);
388 holderCode[cls.holder][cls.name] = emitConstructor(cls);
389 }
390 }
391
392 js.VariableInitialization emitHolderInitialization(Holder holder) {
393 List<js.Property> properties = <js.Property>[];
394 holderCode[holder].forEach((js.Name key, js.Expression value) {
395 properties.add(new js.Property(js.quoteName(key), value));
396 });
397
398 return new js.VariableInitialization(
399 new js.VariableDeclaration(holder.name, allowRename: false),
400 new js.ObjectInitializer(properties));
401 }
402
403 // The generated code looks like this:
404 //
405 // {
406 // var H = {...}, ..., G = {...};
407 // var holders = [ H, ..., G ];
408 // }
409
410 List<js.Statement> statements = [
411 new js.ExpressionStatement(
412 new js.VariableDeclarationList(holders
413 .map(emitHolderInitialization)
414 .toList())),
415 js.js.statement('var holders = #', new js.ArrayInitializer(
416 holders
417 .map((holder) => new js.VariableUse(holder.name))
418 .toList(growable: false)))];
419 return new js.Block(statements);
420 }
421
422 /// Emits the given [method].
423 ///
424 /// A Dart method might result in several JavaScript functions, if it
425 /// requires stubs. The returned map contains the original method and all
426 /// the stubs it needs.
427 Map<js.Name, js.Expression> emitStaticMethod(StaticMethod method) {
428 Map<js.Name, js.Expression> jsMethods = <js.Name, js.Expression>{};
429
430 jsMethods[method.name] = method.code;
431 // TODO(floitsch): can there be anything else than a StaticDartMethod?
432 if (method is StaticDartMethod) {
433 for (ParameterStubMethod stubMethod in method.parameterStubs) {
434 jsMethods[stubMethod.name] = stubMethod.code;
435 }
436 }
437
438 return jsMethods;
439 }
440
441 /// Emits a constructor for the given class [cls].
442 ///
443 /// The constructor is statically built.
444 js.Expression emitConstructor(Class cls) {
445 List<js.Name> fieldNames = const <js.Name>[];
446
447 // If the class is not directly instantiated we only need it for inheritance
448 // or RTI. In either case we don't need its fields.
449 if (cls.isDirectlyInstantiated && !cls.isNative) {
450 fieldNames = cls.fields.map((Field field) => field.name).toList();
451 }
452 js.Name name = cls.name;
453
454 Iterable<js.Name> assignments = fieldNames.map((js.Name field) {
455 return js.js("this.#field = #field", {"field": field});
456 });
457
458 return js.js('function #(#) { # }', [name, fieldNames, assignments]);
459 }
460
461 /// Emits the prototype-section of the fragment.
462 ///
463 /// This section updates the prototype-property of all constructors in the
464 /// global holders.
465 js.Statement emitPrototypes(Fragment fragment) {
466 List<js.Statement> assignments = fragment.libraries
467 .expand((Library library) => library.classes)
468 .map((Class cls) => js.js.statement(
469 '#.prototype = #;',
470 [classReference(cls), emitPrototype(cls)]))
471 .toList(growable: false);
472
473 return new js.Block(assignments);
474 }
475
476 /// Emits the prototype of the given class [cls].
477 ///
478 /// The prototype is generated as object literal. Inheritance is ignored.
479 ///
480 /// The prototype also includes the `is-property` that every class must have.
481 // TODO(floitsch): we could avoid that property if we knew that it wasn't
482 // needed.
483 js.Expression emitPrototype(Class cls) {
484 Iterable<Method> methods = cls.methods;
485 Iterable<Method> isChecks = cls.isChecks;
486 Iterable<Method> callStubs = cls.callStubs;
487 Iterable<Method> typeVariableReaderStubs = cls.typeVariableReaderStubs;
488 Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
489 Iterable<Method> gettersSetters = generateGettersSetters(cls);
490 Iterable<Method> allMethods =
491 [methods, isChecks, callStubs, typeVariableReaderStubs,
492 noSuchMethodStubs, gettersSetters].expand((x) => x);
493
494 List<js.Property> properties = <js.Property>[];
495
496 if (cls.superclass == null) {
497 properties.add(new js.Property(js.string("constructor"),
498 classReference(cls)));
499 properties.add(new js.Property(namer.operatorIs(cls.element),
500 js.number(1)));
501 }
502
503 allMethods.forEach((Method method) {
504 emitInstanceMethod(method).forEach((js.Name name, js.Expression code) {
505 properties.add(new js.Property(name, code));
506 });
507 });
508
509 return new js.ObjectInitializer(properties);
510 }
511
512 /// Generates a getter for the given [field].
513 Method generateGetter(Field field) {
514 assert(field.needsGetter);
515
516 String template;
517 if (field.needsInterceptedGetterOnReceiver) {
518 template = "function(receiver) { return receiver[#]; }";
519 } else if (field.needsInterceptedGetterOnThis) {
520 template = "function(receiver) { return this[#]; }";
521 } else {
522 assert(!field.needsInterceptedGetter);
523 template = "function() { return this[#]; }";
524 }
525 js.Expression fieldName = js.quoteName(field.name);
526 js.Expression code = js.js(template, fieldName);
527 js.Name getterName = namer.deriveGetterName(field.accessorName);
528 return new StubMethod(getterName, code);
529 }
530
531 /// Generates a setter for the given [field].
532 Method generateSetter(Field field) {
533 assert(field.needsUncheckedSetter);
534
535 String template;
536 if (field.needsInterceptedSetterOnReceiver) {
537 template = "function(receiver, val) { return receiver[#] = val; }";
538 } else if (field.needsInterceptedSetterOnThis) {
539 template = "function(receiver, val) { return this[#] = val; }";
540 } else {
541 assert(!field.needsInterceptedSetter);
542 template = "function(val) { return this[#] = val; }";
543 }
544
545 js.Expression fieldName = js.quoteName(field.name);
546 js.Expression code = js.js(template, fieldName);
547 js.Name setterName = namer.deriveSetterName(field.accessorName);
548 return new StubMethod(setterName, code);
549 }
550
551 /// Generates all getters and setters the given class [cls] needs.
552 Iterable<Method> generateGettersSetters(Class cls) {
553 Iterable<Method> getters = cls.fields
554 .where((Field field) => field.needsGetter)
555 .map(generateGetter);
556
557 Iterable<Method> setters = cls.fields
558 .where((Field field) => field.needsUncheckedSetter)
559 .map(generateSetter);
560
561 return [getters, setters].expand((x) => x);
562 }
563
564 /// Emits the given instance [method].
565 ///
566 /// The given method may be a stub-method (for example for is-checks).
567 ///
568 /// If it is a Dart-method, all necessary stub-methods are emitted, too. In
569 /// that case the returned map contains more than just one entry.
570 Map<js.Name, js.Expression> emitInstanceMethod(Method method) {
571 Map<js.Name, js.Expression> jsMethods = <js.Name, js.Expression>{};
572
573 jsMethods[method.name] = method.code;
574 if (method is InstanceMethod) {
575 for (ParameterStubMethod stubMethod in method.parameterStubs) {
576 jsMethods[stubMethod.name] = stubMethod.code;
577 }
578 }
579
580 return jsMethods;
581 }
582
583 /// Emits the inheritance block of the fragment.
584 ///
585 /// In this section prototype chains are updated and mixin functions are
586 /// copied.
587 js.Statement emitInheritance(Fragment fragment) {
588 List<js.Expression> inheritCalls = <js.Expression>[];
589 List<js.Expression> mixinCalls = <js.Expression>[];
590
591 for (Library library in fragment.libraries) {
592 for (Class cls in library.classes) {
593 js.Expression superclassReference = (cls.superclass == null)
594 ? new js.LiteralNull()
595 : classReference(cls.superclass);
596
597 inheritCalls.add(js.js('inherit(#, #)',
598 [classReference(cls), superclassReference]));
599
600 if (cls.isMixinApplication) {
601 MixinApplication mixin = cls;
602 mixinCalls.add(js.js('mixin(#, #)',
603 [classReference(cls), classReference(mixin.mixinClass)]));
604 }
605 }
606 }
607
608 return new js.Block([inheritCalls, mixinCalls]
609 .expand((e) => e)
610 .map((e) => new js.ExpressionStatement(e))
611 .toList(growable: false));
612 }
613
614 /// Emits the setup of method aliases.
615 ///
616 /// This step consists of simply copying JavaScript functions to their
617 /// aliased names so they point to the same function.
618 js.Statement emitInstanceMethodAliases(Fragment fragment) {
619 List<js.Statement> assignments = <js.Statement>[];
620
621 for (Library library in fragment.libraries) {
622 for (Class cls in library.classes) {
623 for (InstanceMethod method in cls.methods) {
624 if (method.aliasName != null) {
625 assignments.add(js.js.statement(
626 '#.prototype.# = #.prototype.#',
627 [classReference(cls), js.quoteName(method.aliasName),
628 classReference(cls), js.quoteName(method.name)]));
629
630 }
631 }
632 }
633 }
634 return new js.Block(assignments);
635 }
636
637 /// Emits the section that installs tear-off getters.
638 js.Statement emitInstallTearOffs(fragment) {
639 throw new UnimplementedError('emitInstallTearOffs');
640 }
641
642 /// Emits the constants section.
643 js.Statement emitConstants(Fragment fragment) {
644 List<js.Statement> assignments = <js.Statement>[];
645 for (Constant constant in fragment.constants) {
646 // TODO(floitsch): instead of just updating the constant holder, we should
647 // find the constants that don't have any dependency on other constants
648 // and create an object-literal with them (and assign it to the
649 // constant-holder variable).
650 assignments.add(js.js.statement('#.# = #',
651 [constant.holder.name,
652 constant.name,
653 constantEmitter.generate(constant.value)]));
654 }
655 return new js.Block(assignments);
656 }
657
658
659 /// Emits the static non-final fields section.
660 ///
661 /// This section initializes all static non-final fields that don't require
662 /// an initializer.
663 js.Block emitStaticNonFinalFields(Fragment fragment) {
664 List<StaticField> fields = fragment.staticNonFinalFields;
665 // TODO(floitsch): instead of assigning the fields one-by-one we should
666 // create a literal and assign it to the static-state holder.
667 // TODO(floitsch): if we don't make a literal we should at least initialize
668 // statics that have the same initial value in the same expression:
669 // `$.x = $.y = $.z = null;`.
670 Iterable<js.Statement> statements = fields.map((StaticField field) {
671 assert(field.holder.isStaticStateHolder);
672 return js.js.statement("#.# = #;",
673 [field.holder.name, field.name, field.code]);
674 });
675 return new js.Block(statements.toList());
676 }
677
678 /// Emits lazy fields.
679 ///
680 /// This section initializes all static (final and non-final) fields that
681 /// require an initializer.
682 js.Block emitLazilyInitializedStatics(Fragment fragment) {
683 List<StaticField> fields = fragment.staticLazilyInitializedFields;
684 Iterable<js.Statement> statements = fields.map((StaticField field) {
685 assert(field.holder.isStaticStateHolder);
686 return js.js.statement("lazy(#, #, #, #);",
687 [field.holder.name,
688 js.quoteName(field.name),
689 js.quoteName(namer.deriveLazyInitializerName(field.name)),
690 field.code]);
691 });
692
693 return new js.Block(statements.toList());
694 }
695
696 emitEmbeddedGlobals(program) {
697 throw new UnimplementedError('emitEmbeddedGlobals');
698 }
699
700 emitNativeSupport(fragment) {
701 throw new UnimplementedError('emitNativeSupport');
275 } 702 }
276 } 703 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698