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

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

Powered by Google App Engine
This is Rietveld 408576698