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

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

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
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 name of the property that stores the tear-off getter on a static 7 /// The name of the property that stores the tear-off getter on a static
8 /// function. 8 /// function.
9 /// 9 ///
10 /// This property is only used when isolates are used. 10 /// This property is only used when isolates are used.
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 js.Expression generateEmbeddedGlobalAccess(String global) => 420 js.Expression generateEmbeddedGlobalAccess(String global) =>
421 modelEmitter.generateEmbeddedGlobalAccess(global); 421 modelEmitter.generateEmbeddedGlobalAccess(global);
422 422
423 js.Expression generateConstantReference(ConstantValue value) => 423 js.Expression generateConstantReference(ConstantValue value) =>
424 modelEmitter.generateConstantReference(value); 424 modelEmitter.generateConstantReference(value);
425 425
426 js.Expression classReference(Class cls) { 426 js.Expression classReference(Class cls) {
427 return js.js('#.#', [cls.holder.name, cls.name]); 427 return js.js('#.#', [cls.holder.name, cls.name]);
428 } 428 }
429 429
430 js.Statement emitMainFragment( 430 js.Statement emitMainFragment(Program program,
431 Program program,
432 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) { 431 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
433 MainFragment fragment = program.fragments.first; 432 MainFragment fragment = program.fragments.first;
434 433
435 Iterable<Holder> nonStaticStateHolders = program.holders 434 Iterable<Holder> nonStaticStateHolders =
436 .where((Holder holder) => !holder.isStaticStateHolder); 435 program.holders.where((Holder holder) => !holder.isStaticStateHolder);
437 436
438 return js.js.statement(mainBoilerplate, 437 return js.js.statement(mainBoilerplate, {
439 {'typeNameProperty': js.string(ModelEmitter.typeNameProperty), 438 'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
440 'cyclicThrow': backend.emitter.staticFunctionAccess( 439 'cyclicThrow': backend.emitter
441 backend.helpers.cyclicThrowHelper), 440 .staticFunctionAccess(backend.helpers.cyclicThrowHelper),
442 'operatorIsPrefix': js.string(namer.operatorIsPrefix), 441 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
443 'tearOffCode': new js.Block(buildTearOffCode(backend)), 442 'tearOffCode': new js.Block(buildTearOffCode(backend)),
444 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES), 443 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
445 'embeddedInterceptorTags': 444 'embeddedInterceptorTags':
446 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG), 445 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
447 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS), 446 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
448 'embeddedGlobalsObject': js.js("init"), 447 'embeddedGlobalsObject': js.js("init"),
449 'holdersList': new js.ArrayInitializer(nonStaticStateHolders 448 'holdersList': new js.ArrayInitializer(nonStaticStateHolders
450 .map((holder) => js.js("#", holder.name)) 449 .map((holder) => js.js("#", holder.name))
451 .toList(growable: false)), 450 .toList(growable: false)),
452 'staticStateDeclaration': new js.VariableDeclaration( 451 'staticStateDeclaration': new js.VariableDeclaration(
453 namer.staticStateHolder, allowRename: false), 452 namer.staticStateHolder,
454 'staticState': js.js('#', namer.staticStateHolder), 453 allowRename: false),
455 'constantHolderReference': buildConstantHolderReference(program), 454 'staticState': js.js('#', namer.staticStateHolder),
456 'holders': emitHolders(program.holders, fragment), 455 'constantHolderReference': buildConstantHolderReference(program),
457 'callName': js.string(namer.callNameField), 456 'holders': emitHolders(program.holders, fragment),
458 'argumentCount': js.string(namer.requiredParameterField), 457 'callName': js.string(namer.callNameField),
459 'defaultArgumentValues': js.string(namer.defaultValuesField), 458 'argumentCount': js.string(namer.requiredParameterField),
460 'prototypes': emitPrototypes(fragment), 459 'defaultArgumentValues': js.string(namer.defaultValuesField),
461 'inheritance': emitInheritance(fragment), 460 'prototypes': emitPrototypes(fragment),
462 'aliases': emitInstanceMethodAliases(fragment), 461 'inheritance': emitInheritance(fragment),
463 'tearOffs': emitInstallTearOffs(fragment), 462 'aliases': emitInstanceMethodAliases(fragment),
464 'constants': emitConstants(fragment), 463 'tearOffs': emitInstallTearOffs(fragment),
465 'staticNonFinalFields': emitStaticNonFinalFields(fragment), 464 'constants': emitConstants(fragment),
466 'lazyStatics': emitLazilyInitializedStatics(fragment), 465 'staticNonFinalFields': emitStaticNonFinalFields(fragment),
467 'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes), 466 'lazyStatics': emitLazilyInitializedStatics(fragment),
468 'nativeSupport': program.needsNativeSupport 467 'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes),
469 ? emitNativeSupport(fragment) 468 'nativeSupport': program.needsNativeSupport
470 : new js.EmptyStatement(), 469 ? emitNativeSupport(fragment)
471 'invokeMain': fragment.invokeMain, 470 : new js.EmptyStatement(),
472 }); 471 'invokeMain': fragment.invokeMain,
472 });
473 } 473 }
474 474
475 js.Expression emitDeferredFragment(DeferredFragment fragment, 475 js.Expression emitDeferredFragment(DeferredFragment fragment,
476 js.Expression deferredTypes, 476 js.Expression deferredTypes, List<Holder> holders) {
477 List<Holder> holders) {
478 List<Holder> nonStaticStateHolders = holders 477 List<Holder> nonStaticStateHolders = holders
479 .where((Holder holder) => !holder.isStaticStateHolder) 478 .where((Holder holder) => !holder.isStaticStateHolder)
480 .toList(growable: false); 479 .toList(growable: false);
481 480
482 List<js.Statement> updateHolderAssignments = <js.Statement>[]; 481 List<js.Statement> updateHolderAssignments = <js.Statement>[];
483 for (int i = 0; i < nonStaticStateHolders.length; i++) { 482 for (int i = 0; i < nonStaticStateHolders.length; i++) {
484 Holder holder = nonStaticStateHolders[i]; 483 Holder holder = nonStaticStateHolders[i];
485 updateHolderAssignments.add(js.js.statement( 484 updateHolderAssignments.add(js.js.statement(
486 '#holder = updateHolder(holdersList[#index], #holder)', 485 '#holder = updateHolder(holdersList[#index], #holder)',
487 {'index': js.number(i), 486 {'index': js.number(i), 'holder': new js.VariableUse(holder.name)}));
488 'holder': new js.VariableUse(holder.name)}));
489 } 487 }
490 488
491 // TODO(floitsch): don't just reference 'init'. 489 // TODO(floitsch): don't just reference 'init'.
492 return js.js(deferredBoilerplate, 490 return js.js(deferredBoilerplate, {
493 {'embeddedGlobalsObject': new js.Parameter('init'), 491 'embeddedGlobalsObject': new js.Parameter('init'),
494 'staticState': new js.Parameter(namer.staticStateHolder), 492 'staticState': new js.Parameter(namer.staticStateHolder),
495 'holders': emitHolders(holders, fragment), 493 'holders': emitHolders(holders, fragment),
496 'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders 494 'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders
497 .map((holder) => js.js("#", holder.name)) 495 .map((holder) => js.js("#", holder.name))
498 .toList(growable: false)), 496 .toList(growable: false)),
499 'updateHolders': new js.Block(updateHolderAssignments), 497 'updateHolders': new js.Block(updateHolderAssignments),
500 'prototypes': emitPrototypes(fragment), 498 'prototypes': emitPrototypes(fragment),
501 'inheritance': emitInheritance(fragment), 499 'inheritance': emitInheritance(fragment),
502 'aliases': emitInstanceMethodAliases(fragment), 500 'aliases': emitInstanceMethodAliases(fragment),
503 'tearOffs': emitInstallTearOffs(fragment), 501 'tearOffs': emitInstallTearOffs(fragment),
504 'constants': emitConstants(fragment), 502 'constants': emitConstants(fragment),
505 'staticNonFinalFields': emitStaticNonFinalFields(fragment), 503 'staticNonFinalFields': emitStaticNonFinalFields(fragment),
506 'lazyStatics': emitLazilyInitializedStatics(fragment), 504 'lazyStatics': emitLazilyInitializedStatics(fragment),
507 'types': deferredTypes, 505 'types': deferredTypes,
508 // TODO(floitsch): only call emitNativeSupport if we need native. 506 // TODO(floitsch): only call emitNativeSupport if we need native.
509 'nativeSupport': emitNativeSupport(fragment), 507 'nativeSupport': emitNativeSupport(fragment),
510 }); 508 });
511 } 509 }
512 510
513 /// Emits all holders, except for the static-state holder. 511 /// Emits all holders, except for the static-state holder.
514 /// 512 ///
515 /// The emitted holders contain classes (only the constructors) and all 513 /// The emitted holders contain classes (only the constructors) and all
516 /// static functions. 514 /// static functions.
517 js.Statement emitHolders(List<Holder> holders, Fragment fragment) { 515 js.Statement emitHolders(List<Holder> holders, Fragment fragment) {
518 // Skip the static-state holder in this function. 516 // Skip the static-state holder in this function.
519 holders = holders 517 holders = holders
(...skipping 30 matching lines...) Expand all
550 } 548 }
551 549
552 // The generated code looks like this: 550 // The generated code looks like this:
553 // 551 //
554 // { 552 // {
555 // var H = {...}, ..., G = {...}; 553 // var H = {...}, ..., G = {...};
556 // var holders = [ H, ..., G ]; 554 // var holders = [ H, ..., G ];
557 // } 555 // }
558 556
559 List<js.Statement> statements = [ 557 List<js.Statement> statements = [
560 new js.ExpressionStatement( 558 new js.ExpressionStatement(new js.VariableDeclarationList(
561 new js.VariableDeclarationList(holders 559 holders.map(emitHolderInitialization).toList())),
562 .map(emitHolderInitialization) 560 js.js.statement(
563 .toList())), 561 'var holders = #',
564 js.js.statement('var holders = #', new js.ArrayInitializer( 562 new js.ArrayInitializer(holders
565 holders
566 .map((holder) => new js.VariableUse(holder.name)) 563 .map((holder) => new js.VariableUse(holder.name))
567 .toList(growable: false)))]; 564 .toList(growable: false)))
565 ];
568 return new js.Block(statements); 566 return new js.Block(statements);
569 } 567 }
570 568
571 /// Returns a reference to the constant holder, or the JS-literal `null`. 569 /// Returns a reference to the constant holder, or the JS-literal `null`.
572 js.Expression buildConstantHolderReference(Program program) { 570 js.Expression buildConstantHolderReference(Program program) {
573 Holder constantHolder = program.holders 571 Holder constantHolder = program.holders.firstWhere(
574 .firstWhere((Holder holder) => holder.isConstantsHolder, 572 (Holder holder) => holder.isConstantsHolder,
575 orElse: () => null); 573 orElse: () => null);
576 if (constantHolder == null) return new js.LiteralNull(); 574 if (constantHolder == null) return new js.LiteralNull();
577 return new js.VariableUse(constantHolder.name); 575 return new js.VariableUse(constantHolder.name);
578 } 576 }
579 577
580 /// Emits the given [method]. 578 /// Emits the given [method].
581 /// 579 ///
582 /// A Dart method might result in several JavaScript functions, if it 580 /// A Dart method might result in several JavaScript functions, if it
583 /// requires stubs. The returned map contains the original method and all 581 /// requires stubs. The returned map contains the original method and all
584 /// the stubs it needs. 582 /// the stubs it needs.
585 Map<js.Name, js.Expression> emitStaticMethod(StaticMethod method) { 583 Map<js.Name, js.Expression> emitStaticMethod(StaticMethod method) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 } 617 }
620 618
621 /// Emits the prototype-section of the fragment. 619 /// Emits the prototype-section of the fragment.
622 /// 620 ///
623 /// This section updates the prototype-property of all constructors in the 621 /// This section updates the prototype-property of all constructors in the
624 /// global holders. 622 /// global holders.
625 js.Statement emitPrototypes(Fragment fragment) { 623 js.Statement emitPrototypes(Fragment fragment) {
626 List<js.Statement> assignments = fragment.libraries 624 List<js.Statement> assignments = fragment.libraries
627 .expand((Library library) => library.classes) 625 .expand((Library library) => library.classes)
628 .map((Class cls) => js.js.statement( 626 .map((Class cls) => js.js.statement(
629 '#.prototype = #;', 627 '#.prototype = #;', [classReference(cls), emitPrototype(cls)]))
630 [classReference(cls), emitPrototype(cls)]))
631 .toList(growable: false); 628 .toList(growable: false);
632 629
633 return new js.Block(assignments); 630 return new js.Block(assignments);
634 } 631 }
635 632
636 /// Emits the prototype of the given class [cls]. 633 /// Emits the prototype of the given class [cls].
637 /// 634 ///
638 /// The prototype is generated as object literal. Inheritance is ignored. 635 /// The prototype is generated as object literal. Inheritance is ignored.
639 /// 636 ///
640 /// The prototype also includes the `is-property` that every class must have. 637 /// The prototype also includes the `is-property` that every class must have.
641 // TODO(floitsch): we could avoid that property if we knew that it wasn't 638 // TODO(floitsch): we could avoid that property if we knew that it wasn't
642 // needed. 639 // needed.
643 js.Expression emitPrototype(Class cls) { 640 js.Expression emitPrototype(Class cls) {
644 Iterable<Method> methods = cls.methods; 641 Iterable<Method> methods = cls.methods;
645 Iterable<Method> checkedSetters = cls.checkedSetters; 642 Iterable<Method> checkedSetters = cls.checkedSetters;
646 Iterable<Method> isChecks = cls.isChecks; 643 Iterable<Method> isChecks = cls.isChecks;
647 Iterable<Method> callStubs = cls.callStubs; 644 Iterable<Method> callStubs = cls.callStubs;
648 Iterable<Method> typeVariableReaderStubs = cls.typeVariableReaderStubs; 645 Iterable<Method> typeVariableReaderStubs = cls.typeVariableReaderStubs;
649 Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs; 646 Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
650 Iterable<Method> gettersSetters = generateGettersSetters(cls); 647 Iterable<Method> gettersSetters = generateGettersSetters(cls);
651 Iterable<Method> allMethods = 648 Iterable<Method> allMethods = [
652 [methods, checkedSetters, isChecks, callStubs, typeVariableReaderStubs, 649 methods,
653 noSuchMethodStubs, gettersSetters].expand((x) => x); 650 checkedSetters,
651 isChecks,
652 callStubs,
653 typeVariableReaderStubs,
654 noSuchMethodStubs,
655 gettersSetters
656 ].expand((x) => x);
654 657
655 List<js.Property> properties = <js.Property>[]; 658 List<js.Property> properties = <js.Property>[];
656 659
657 if (cls.superclass == null) { 660 if (cls.superclass == null) {
658 properties.add(new js.Property(js.string("constructor"), 661 properties
659 classReference(cls))); 662 .add(new js.Property(js.string("constructor"), classReference(cls)));
660 properties.add(new js.Property(namer.operatorIs(cls.element), 663 properties
661 js.number(1))); 664 .add(new js.Property(namer.operatorIs(cls.element), js.number(1)));
662 } 665 }
663 666
664 allMethods.forEach((Method method) { 667 allMethods.forEach((Method method) {
665 emitInstanceMethod(method) 668 emitInstanceMethod(method)
666 .forEach((js.Expression name, js.Expression code) { 669 .forEach((js.Expression name, js.Expression code) {
667 properties.add(new js.Property(name, code)); 670 properties.add(new js.Property(name, code));
668 }); 671 });
669 }); 672 });
670 673
671 return new js.ObjectInitializer(properties); 674 return new js.ObjectInitializer(properties);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 for (ParameterStubMethod stubMethod in method.parameterStubs) { 743 for (ParameterStubMethod stubMethod in method.parameterStubs) {
741 properties[stubMethod.name] = stubMethod.code; 744 properties[stubMethod.name] = stubMethod.code;
742 } 745 }
743 746
744 if (method.isClosureCallMethod && method.canBeApplied) { 747 if (method.isClosureCallMethod && method.canBeApplied) {
745 properties[js.string(namer.callCatchAllName)] = 748 properties[js.string(namer.callCatchAllName)] =
746 js.quoteName(method.name); 749 js.quoteName(method.name);
747 properties[js.string(namer.requiredParameterField)] = 750 properties[js.string(namer.requiredParameterField)] =
748 js.number(method.requiredParameterCount); 751 js.number(method.requiredParameterCount);
749 properties[js.string(namer.defaultValuesField)] = 752 properties[js.string(namer.defaultValuesField)] =
750 _encodeOptionalParameterDefaultValues(method); 753 _encodeOptionalParameterDefaultValues(method);
751 } 754 }
752 } 755 }
753 756
754 return properties; 757 return properties;
755 } 758 }
756 759
757 /// Emits the inheritance block of the fragment. 760 /// Emits the inheritance block of the fragment.
758 /// 761 ///
759 /// In this section prototype chains are updated and mixin functions are 762 /// In this section prototype chains are updated and mixin functions are
760 /// copied. 763 /// copied.
761 js.Statement emitInheritance(Fragment fragment) { 764 js.Statement emitInheritance(Fragment fragment) {
762 List<js.Expression> inheritCalls = <js.Expression>[]; 765 List<js.Expression> inheritCalls = <js.Expression>[];
763 List<js.Expression> mixinCalls = <js.Expression>[]; 766 List<js.Expression> mixinCalls = <js.Expression>[];
764 767
765 Set<Class> emittedClasses = new Set<Class>(); 768 Set<Class> emittedClasses = new Set<Class>();
766 769
767 void emitInheritanceForClass(cls) { 770 void emitInheritanceForClass(cls) {
768 if (cls == null || emittedClasses.contains(cls)) return; 771 if (cls == null || emittedClasses.contains(cls)) return;
769 772
770 Class superclass = cls.superclass; 773 Class superclass = cls.superclass;
771 emitInheritanceForClass(superclass); 774 emitInheritanceForClass(superclass);
772 775
773 js.Expression superclassReference = (superclass == null) 776 js.Expression superclassReference = (superclass == null)
774 ? new js.LiteralNull() 777 ? new js.LiteralNull()
775 : classReference(superclass); 778 : classReference(superclass);
776 779
777 inheritCalls.add(js.js('inherit(#, #)', 780 inheritCalls.add(
778 [classReference(cls), superclassReference])); 781 js.js('inherit(#, #)', [classReference(cls), superclassReference]));
779 782
780 emittedClasses.add(cls); 783 emittedClasses.add(cls);
781 } 784 }
782 785
783 for (Library library in fragment.libraries) { 786 for (Library library in fragment.libraries) {
784 for (Class cls in library.classes) { 787 for (Class cls in library.classes) {
785 emitInheritanceForClass(cls); 788 emitInheritanceForClass(cls);
786 789
787 if (cls.isMixinApplication) { 790 if (cls.isMixinApplication) {
788 MixinApplication mixin = cls; 791 MixinApplication mixin = cls;
(...skipping 13 matching lines...) Expand all
802 /// 805 ///
803 /// This step consists of simply copying JavaScript functions to their 806 /// This step consists of simply copying JavaScript functions to their
804 /// aliased names so they point to the same function. 807 /// aliased names so they point to the same function.
805 js.Statement emitInstanceMethodAliases(Fragment fragment) { 808 js.Statement emitInstanceMethodAliases(Fragment fragment) {
806 List<js.Statement> assignments = <js.Statement>[]; 809 List<js.Statement> assignments = <js.Statement>[];
807 810
808 for (Library library in fragment.libraries) { 811 for (Library library in fragment.libraries) {
809 for (Class cls in library.classes) { 812 for (Class cls in library.classes) {
810 for (InstanceMethod method in cls.methods) { 813 for (InstanceMethod method in cls.methods) {
811 if (method.aliasName != null) { 814 if (method.aliasName != null) {
812 assignments.add(js.js.statement( 815 assignments.add(js.js.statement('#.prototype.# = #.prototype.#', [
813 '#.prototype.# = #.prototype.#', 816 classReference(cls),
814 [classReference(cls), js.quoteName(method.aliasName), 817 js.quoteName(method.aliasName),
815 classReference(cls), js.quoteName(method.name)])); 818 classReference(cls),
816 819 js.quoteName(method.name)
820 ]));
817 } 821 }
818 } 822 }
819 } 823 }
820 } 824 }
821 return new js.Block(assignments); 825 return new js.Block(assignments);
822 } 826 }
823 827
824 /// Encodes the optional default values so that the runtime Function.apply 828 /// Encodes the optional default values so that the runtime Function.apply
825 /// can use them. 829 /// can use them.
826 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) { 830 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
827 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole]. 831 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
828 if (method.optionalParameterDefaultValues is List) { 832 if (method.optionalParameterDefaultValues is List) {
829 List<ConstantValue> defaultValues = method.optionalParameterDefaultValues; 833 List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
830 Iterable<js.Expression> elements = 834 Iterable<js.Expression> elements =
831 defaultValues.map(generateConstantReference); 835 defaultValues.map(generateConstantReference);
832 return js.js('function() { return #; }', 836 return js.js('function() { return #; }',
833 new js.ArrayInitializer(elements.toList())); 837 new js.ArrayInitializer(elements.toList()));
834 } else { 838 } else {
835 Map<String, ConstantValue> defaultValues = 839 Map<String, ConstantValue> defaultValues =
836 method.optionalParameterDefaultValues; 840 method.optionalParameterDefaultValues;
837 List<js.Property> properties = <js.Property>[]; 841 List<js.Property> properties = <js.Property>[];
838 List<String> names = defaultValues.keys.toList(growable: false); 842 List<String> names = defaultValues.keys.toList(growable: false);
839 // Sort the names the same way we sort them for the named-argument calling 843 // Sort the names the same way we sort them for the named-argument calling
840 // convention. 844 // convention.
841 names.sort(); 845 names.sort();
842 846
843 for (String name in names) { 847 for (String name in names) {
844 ConstantValue value = defaultValues[name]; 848 ConstantValue value = defaultValues[name];
845 properties.add(new js.Property(js.string(name), 849 properties.add(
846 generateConstantReference(value))); 850 new js.Property(js.string(name), generateConstantReference(value)));
847 } 851 }
848 return js.js('function() { return #; }', 852 return js.js(
849 new js.ObjectInitializer(properties)); 853 'function() { return #; }', new js.ObjectInitializer(properties));
850 } 854 }
851 } 855 }
852 856
853 /// Emits the statement that installs a tear off for a method. 857 /// Emits the statement that installs a tear off for a method.
854 /// 858 ///
855 /// Tear-offs might be passed to `Function.apply` which means that all 859 /// Tear-offs might be passed to `Function.apply` which means that all
856 /// calling-conventions (with or without optional positional/named arguments) 860 /// calling-conventions (with or without optional positional/named arguments)
857 /// are possible. As such, the tear-off needs enough information to fill in 861 /// are possible. As such, the tear-off needs enough information to fill in
858 /// missing parameters. 862 /// missing parameters.
859 js.Statement emitInstallTearOff(js.Expression container, DartMethod method) { 863 js.Statement emitInstallTearOff(js.Expression container, DartMethod method) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 isIntercepted = backend.isInterceptedMethod(method.element); 896 isIntercepted = backend.isInterceptedMethod(method.element);
893 } 897 }
894 int requiredParameterCount = 0; 898 int requiredParameterCount = 0;
895 js.Expression optionalParameterDefaultValues = new js.LiteralNull(); 899 js.Expression optionalParameterDefaultValues = new js.LiteralNull();
896 if (method.canBeApplied) { 900 if (method.canBeApplied) {
897 requiredParameterCount = method.requiredParameterCount; 901 requiredParameterCount = method.requiredParameterCount;
898 optionalParameterDefaultValues = 902 optionalParameterDefaultValues =
899 _encodeOptionalParameterDefaultValues(method); 903 _encodeOptionalParameterDefaultValues(method);
900 } 904 }
901 905
902 return js.js.statement(''' 906 return js.js.statement(
907 '''
903 installTearOff(#container, #getterName, #isStatic, #isIntercepted, 908 installTearOff(#container, #getterName, #isStatic, #isIntercepted,
904 #requiredParameterCount, #optionalParameterDefaultValues, 909 #requiredParameterCount, #optionalParameterDefaultValues,
905 #callNames, #funsOrNames, #funType)''', 910 #callNames, #funsOrNames, #funType)''',
906 { 911 {
907 "container": container, 912 "container": container,
908 "getterName": js.quoteName(method.tearOffName), 913 "getterName": js.quoteName(method.tearOffName),
909 "isStatic": new js.LiteralBool(method.isStatic), 914 "isStatic": new js.LiteralBool(method.isStatic),
910 "isIntercepted": new js.LiteralBool(isIntercepted), 915 "isIntercepted": new js.LiteralBool(isIntercepted),
911 "requiredParameterCount": js.number(requiredParameterCount), 916 "requiredParameterCount": js.number(requiredParameterCount),
912 "optionalParameterDefaultValues": optionalParameterDefaultValues, 917 "optionalParameterDefaultValues": optionalParameterDefaultValues,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 } 949 }
945 950
946 /// Emits the constants section. 951 /// Emits the constants section.
947 js.Statement emitConstants(Fragment fragment) { 952 js.Statement emitConstants(Fragment fragment) {
948 List<js.Statement> assignments = <js.Statement>[]; 953 List<js.Statement> assignments = <js.Statement>[];
949 for (Constant constant in fragment.constants) { 954 for (Constant constant in fragment.constants) {
950 // TODO(floitsch): instead of just updating the constant holder, we should 955 // TODO(floitsch): instead of just updating the constant holder, we should
951 // find the constants that don't have any dependency on other constants 956 // find the constants that don't have any dependency on other constants
952 // and create an object-literal with them (and assign it to the 957 // and create an object-literal with them (and assign it to the
953 // constant-holder variable). 958 // constant-holder variable).
954 assignments.add(js.js.statement('#.# = #', 959 assignments.add(js.js.statement('#.# = #', [
955 [constant.holder.name, 960 constant.holder.name,
956 constant.name, 961 constant.name,
957 constantEmitter.generate(constant.value)])); 962 constantEmitter.generate(constant.value)
963 ]));
958 } 964 }
959 return new js.Block(assignments); 965 return new js.Block(assignments);
960 } 966 }
961 967
962
963 /// Emits the static non-final fields section. 968 /// Emits the static non-final fields section.
964 /// 969 ///
965 /// This section initializes all static non-final fields that don't require 970 /// This section initializes all static non-final fields that don't require
966 /// an initializer. 971 /// an initializer.
967 js.Block emitStaticNonFinalFields(Fragment fragment) { 972 js.Block emitStaticNonFinalFields(Fragment fragment) {
968 List<StaticField> fields = fragment.staticNonFinalFields; 973 List<StaticField> fields = fragment.staticNonFinalFields;
969 // TODO(floitsch): instead of assigning the fields one-by-one we should 974 // TODO(floitsch): instead of assigning the fields one-by-one we should
970 // create a literal and assign it to the static-state holder. 975 // create a literal and assign it to the static-state holder.
971 // TODO(floitsch): if we don't make a literal we should at least initialize 976 // TODO(floitsch): if we don't make a literal we should at least initialize
972 // statics that have the same initial value in the same expression: 977 // statics that have the same initial value in the same expression:
973 // `$.x = $.y = $.z = null;`. 978 // `$.x = $.y = $.z = null;`.
974 Iterable<js.Statement> statements = fields.map((StaticField field) { 979 Iterable<js.Statement> statements = fields.map((StaticField field) {
975 assert(field.holder.isStaticStateHolder); 980 assert(field.holder.isStaticStateHolder);
976 return js.js.statement("#.# = #;", 981 return js.js
977 [field.holder.name, field.name, field.code]); 982 .statement("#.# = #;", [field.holder.name, field.name, field.code]);
978 }); 983 });
979 return new js.Block(statements.toList()); 984 return new js.Block(statements.toList());
980 } 985 }
981 986
982 /// Emits lazy fields. 987 /// Emits lazy fields.
983 /// 988 ///
984 /// This section initializes all static (final and non-final) fields that 989 /// This section initializes all static (final and non-final) fields that
985 /// require an initializer. 990 /// require an initializer.
986 js.Block emitLazilyInitializedStatics(Fragment fragment) { 991 js.Block emitLazilyInitializedStatics(Fragment fragment) {
987 List<StaticField> fields = fragment.staticLazilyInitializedFields; 992 List<StaticField> fields = fragment.staticLazilyInitializedFields;
988 Iterable<js.Statement> statements = fields.map((StaticField field) { 993 Iterable<js.Statement> statements = fields.map((StaticField field) {
989 assert(field.holder.isStaticStateHolder); 994 assert(field.holder.isStaticStateHolder);
990 return js.js.statement("lazy(#, #, #, #);", 995 return js.js.statement("lazy(#, #, #, #);", [
991 [field.holder.name, 996 field.holder.name,
992 js.quoteName(field.name), 997 js.quoteName(field.name),
993 js.quoteName(namer.deriveLazyInitializerName(field.name)), 998 js.quoteName(namer.deriveLazyInitializerName(field.name)),
994 field.code]); 999 field.code
1000 ]);
995 }); 1001 });
996 1002
997 return new js.Block(statements.toList()); 1003 return new js.Block(statements.toList());
998 } 1004 }
999 1005
1000 /// Emits the embedded globals that are needed for deferred loading. 1006 /// Emits the embedded globals that are needed for deferred loading.
1001 /// 1007 ///
1002 /// This function is only invoked for the main fragment. 1008 /// This function is only invoked for the main fragment.
1003 /// 1009 ///
1004 /// The [loadMap] contains a map from load-ids (for each deferred library) 1010 /// The [loadMap] contains a map from load-ids (for each deferred library)
1005 /// to the list of generated fragments that must be installed when the 1011 /// to the list of generated fragments that must be installed when the
1006 /// deferred library is loaded. 1012 /// deferred library is loaded.
1007 Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading( 1013 Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
1008 Map<String, List<Fragment>> loadMap, 1014 Map<String, List<Fragment>> loadMap,
1009 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) { 1015 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
1010 if (loadMap.isEmpty) return []; 1016 if (loadMap.isEmpty) return [];
1011 1017
1012 List<js.Property> globals = <js.Property>[]; 1018 List<js.Property> globals = <js.Property>[];
1013 1019
1014 js.ArrayInitializer fragmentUris(List<Fragment> fragments) { 1020 js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
1015 return js.stringArray(fragments.map((DeferredFragment fragment) => 1021 return js.stringArray(fragments.map((DeferredFragment fragment) =>
1016 "${fragment.outputFileName}.${ModelEmitter.deferredExtension}")); 1022 "${fragment.outputFileName}.${ModelEmitter.deferredExtension}"));
1017 } 1023 }
1018 js.ArrayInitializer fragmentHashes(List<Fragment> fragments) { 1024 js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
1019 return new js.ArrayInitializer( 1025 return new js.ArrayInitializer(fragments
1020 fragments 1026 .map((fragment) => deferredLoadHashes[fragment])
1021 .map((fragment) => deferredLoadHashes[fragment]) 1027 .toList(growable: false));
1022 .toList(growable: false));
1023 } 1028 }
1024 1029
1025 List<js.Property> uris = new List<js.Property>(loadMap.length); 1030 List<js.Property> uris = new List<js.Property>(loadMap.length);
1026 List<js.Property> hashes = new List<js.Property>(loadMap.length); 1031 List<js.Property> hashes = new List<js.Property>(loadMap.length);
1027 int count = 0; 1032 int count = 0;
1028 loadMap.forEach((String loadId, List<Fragment> fragmentList) { 1033 loadMap.forEach((String loadId, List<Fragment> fragmentList) {
1029 uris[count] = 1034 uris[count] =
1030 new js.Property(js.string(loadId), fragmentUris(fragmentList)); 1035 new js.Property(js.string(loadId), fragmentUris(fragmentList));
1031 hashes[count] = 1036 hashes[count] =
1032 new js.Property(js.string(loadId), fragmentHashes(fragmentList)); 1037 new js.Property(js.string(loadId), fragmentHashes(fragmentList));
1033 count++; 1038 count++;
1034 }); 1039 });
1035 1040
1036 globals.add(new js.Property(js.string(DEFERRED_LIBRARY_URIS), 1041 globals.add(new js.Property(
1037 new js.ObjectInitializer(uris))); 1042 js.string(DEFERRED_LIBRARY_URIS), new js.ObjectInitializer(uris)));
1038 globals.add(new js.Property(js.string(DEFERRED_LIBRARY_HASHES), 1043 globals.add(new js.Property(
1039 new js.ObjectInitializer(hashes))); 1044 js.string(DEFERRED_LIBRARY_HASHES), new js.ObjectInitializer(hashes)));
1040 globals.add(new js.Property(js.string(DEFERRED_INITIALIZED), 1045 globals.add(new js.Property(
1041 js.js("Object.create(null)"))); 1046 js.string(DEFERRED_INITIALIZED), js.js("Object.create(null)")));
1042 1047
1043 String deferredGlobal = ModelEmitter.deferredInitializersGlobal; 1048 String deferredGlobal = ModelEmitter.deferredInitializersGlobal;
1044 js.Expression isHunkLoadedFunction = 1049 js.Expression isHunkLoadedFunction =
1045 js.js("function(hash) { return !!$deferredGlobal[hash]; }"); 1050 js.js("function(hash) { return !!$deferredGlobal[hash]; }");
1046 globals.add(new js.Property(js.string(IS_HUNK_LOADED), 1051 globals
1047 isHunkLoadedFunction)); 1052 .add(new js.Property(js.string(IS_HUNK_LOADED), isHunkLoadedFunction));
1048 1053
1049 js.Expression isHunkInitializedFunction = 1054 js.Expression isHunkInitializedFunction = js.js(
1050 js.js("function(hash) { return !!#deferredInitialized[hash]; }", 1055 "function(hash) { return !!#deferredInitialized[hash]; }", {
1051 {'deferredInitialized': 1056 'deferredInitialized': generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)
1052 generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)}); 1057 });
1053 globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED), 1058 globals.add(new js.Property(
1054 isHunkInitializedFunction)); 1059 js.string(IS_HUNK_INITIALIZED), isHunkInitializedFunction));
1055 1060
1056 /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the 1061 /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the
1057 /// deferred hunk. 1062 /// deferred hunk.
1058 js.Expression initializeLoadedHunkFunction = 1063 js.Expression initializeLoadedHunkFunction = js.js(
1059 js.js(""" 1064 """
1060 function(hash) { 1065 function(hash) {
1061 initializeDeferredHunk($deferredGlobal[hash]); 1066 initializeDeferredHunk($deferredGlobal[hash]);
1062 #deferredInitialized[hash] = true; 1067 #deferredInitialized[hash] = true;
1063 }""", {'deferredInitialized': 1068 }""",
1064 generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)}); 1069 {
1070 'deferredInitialized':
1071 generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)
1072 });
1065 1073
1066 globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK), 1074 globals.add(new js.Property(
1067 initializeLoadedHunkFunction)); 1075 js.string(INITIALIZE_LOADED_HUNK), initializeLoadedHunkFunction));
1068 1076
1069 return globals; 1077 return globals;
1070 } 1078 }
1071 1079
1072 /// Emits the [MANGLED_GLOBAL_NAMES] embedded global. 1080 /// Emits the [MANGLED_GLOBAL_NAMES] embedded global.
1073 /// 1081 ///
1074 /// This global maps minified names for selected classes (some important 1082 /// This global maps minified names for selected classes (some important
1075 /// core classes, and some native classes) to their unminified names. 1083 /// core classes, and some native classes) to their unminified names.
1076 js.Property emitMangledGlobalNames() { 1084 js.Property emitMangledGlobalNames() {
1077 List<js.Property> names = <js.Property>[]; 1085 List<js.Property> names = <js.Property>[];
1078 1086
1079 CoreClasses coreClasses = compiler.coreClasses; 1087 CoreClasses coreClasses = compiler.coreClasses;
1080 // We want to keep the original names for the most common core classes when 1088 // We want to keep the original names for the most common core classes when
1081 // calling toString on them. 1089 // calling toString on them.
1082 List<ClassElement> nativeClassesNeedingUnmangledName = 1090 List<ClassElement> nativeClassesNeedingUnmangledName = [
1083 [coreClasses.intClass, coreClasses.doubleClass, coreClasses.numClass, 1091 coreClasses.intClass,
1084 coreClasses.stringClass, coreClasses.boolClass, coreClasses.nullClass, 1092 coreClasses.doubleClass,
1085 coreClasses.listClass]; 1093 coreClasses.numClass,
1094 coreClasses.stringClass,
1095 coreClasses.boolClass,
1096 coreClasses.nullClass,
1097 coreClasses.listClass
1098 ];
1086 // TODO(floitsch): this should probably be on a per-fragment basis. 1099 // TODO(floitsch): this should probably be on a per-fragment basis.
1087 nativeClassesNeedingUnmangledName.forEach((element) { 1100 nativeClassesNeedingUnmangledName.forEach((element) {
1088 names.add(new js.Property(js.quoteName(namer.className(element)), 1101 names.add(new js.Property(
1089 js.string(element.name))); 1102 js.quoteName(namer.className(element)), js.string(element.name)));
1090 }); 1103 });
1091 1104
1092 return new js.Property(js.string(MANGLED_GLOBAL_NAMES), 1105 return new js.Property(
1093 new js.ObjectInitializer(names)); 1106 js.string(MANGLED_GLOBAL_NAMES), new js.ObjectInitializer(names));
1094 } 1107 }
1095 1108
1096 /// Emits the [GET_TYPE_FROM_NAME] embedded global. 1109 /// Emits the [GET_TYPE_FROM_NAME] embedded global.
1097 /// 1110 ///
1098 /// This embedded global provides a way to go from a class name (which is 1111 /// This embedded global provides a way to go from a class name (which is
1099 /// also the constructor's name) to the constructor itself. 1112 /// also the constructor's name) to the constructor itself.
1100 js.Property emitGetTypeFromName() { 1113 js.Property emitGetTypeFromName() {
1101 js.Expression function = js.js("getGlobalFromName"); 1114 js.Expression function = js.js("getGlobalFromName");
1102 return new js.Property(js.string(GET_TYPE_FROM_NAME), function); 1115 return new js.Property(js.string(GET_TYPE_FROM_NAME), function);
1103 } 1116 }
(...skipping 11 matching lines...) Expand all
1115 1128
1116 metadataGlobals.add(createGlobal(program.metadata, METADATA)); 1129 metadataGlobals.add(createGlobal(program.metadata, METADATA));
1117 js.Expression types = 1130 js.Expression types =
1118 program.metadataTypesForOutputUnit(program.mainFragment.outputUnit); 1131 program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
1119 metadataGlobals.add(createGlobal(types, TYPES)); 1132 metadataGlobals.add(createGlobal(types, TYPES));
1120 1133
1121 return metadataGlobals; 1134 return metadataGlobals;
1122 } 1135 }
1123 1136
1124 /// Emits all embedded globals. 1137 /// Emits all embedded globals.
1125 js.Statement emitEmbeddedGlobals( 1138 js.Statement emitEmbeddedGlobals(Program program,
1126 Program program,
1127 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) { 1139 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
1128 List<js.Property> globals = <js.Property>[]; 1140 List<js.Property> globals = <js.Property>[];
1129 1141
1130 if (program.loadMap.isNotEmpty) { 1142 if (program.loadMap.isNotEmpty) {
1131 globals.addAll(emitEmbeddedGlobalsForDeferredLoading( 1143 globals.addAll(emitEmbeddedGlobalsForDeferredLoading(
1132 program.loadMap, deferredLoadHashes)); 1144 program.loadMap, deferredLoadHashes));
1133 } 1145 }
1134 1146
1135 if (program.typeToInterceptorMap != null) { 1147 if (program.typeToInterceptorMap != null) {
1136 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP), 1148 globals.add(new js.Property(
1137 program.typeToInterceptorMap)); 1149 js.string(TYPE_TO_INTERCEPTOR_MAP), program.typeToInterceptorMap));
1138 } 1150 }
1139 1151
1140 if (program.hasIsolateSupport) { 1152 if (program.hasIsolateSupport) {
1141 String staticStateName = namer.staticStateHolder; 1153 String staticStateName = namer.staticStateHolder;
1142 // TODO(floitsch): this doesn't create a new isolate, but just reuses 1154 // TODO(floitsch): this doesn't create a new isolate, but just reuses
1143 // the current static state. Since we don't run multiple isolates in the 1155 // the current static state. Since we don't run multiple isolates in the
1144 // same JavaScript context (except for testing) this shouldn't have any 1156 // same JavaScript context (except for testing) this shouldn't have any
1145 // impact on real-world programs, though. 1157 // impact on real-world programs, though.
1146 globals.add( 1158 globals.add(new js.Property(js.string(CREATE_NEW_ISOLATE),
1147 new js.Property(js.string(CREATE_NEW_ISOLATE), 1159 js.js('function () { return $staticStateName; }')));
1148 js.js('function () { return $staticStateName; }')));
1149 1160
1150 js.Expression nameToClosureFunction = js.js(''' 1161 js.Expression nameToClosureFunction = js.js('''
1151 // First fetch the static function. From there we can execute its 1162 // First fetch the static function. From there we can execute its
1152 // getter function which builds a Dart closure. 1163 // getter function which builds a Dart closure.
1153 function(name) { 1164 function(name) {
1154 var staticFunction = getGlobalFromName(name); 1165 var staticFunction = getGlobalFromName(name);
1155 var getterFunction = staticFunction.$tearOffPropertyName; 1166 var getterFunction = staticFunction.$tearOffPropertyName;
1156 return getterFunction(); 1167 return getterFunction();
1157 }'''); 1168 }''');
1158 globals.add(new js.Property(js.string(STATIC_FUNCTION_NAME_TO_CLOSURE), 1169 globals.add(new js.Property(
1159 nameToClosureFunction)); 1170 js.string(STATIC_FUNCTION_NAME_TO_CLOSURE), nameToClosureFunction));
1160 1171
1161 globals.add( 1172 globals.add(new js.Property(js.string(CLASS_ID_EXTRACTOR),
1162 new js.Property(js.string(CLASS_ID_EXTRACTOR), 1173 js.js('function(o) { return o.constructor.name; }')));
1163 js.js('function(o) { return o.constructor.name; }')));
1164 1174
1165 js.Expression extractFieldsFunction = js.js(''' 1175 js.Expression extractFieldsFunction = js.js('''
1166 function(o) { 1176 function(o) {
1167 var constructor = o.constructor; 1177 var constructor = o.constructor;
1168 var fieldNames = constructor.$cachedClassFieldNames; 1178 var fieldNames = constructor.$cachedClassFieldNames;
1169 if (!fieldNames) { 1179 if (!fieldNames) {
1170 // Extract the fields from an empty unmodified object. 1180 // Extract the fields from an empty unmodified object.
1171 var empty = new constructor(); 1181 var empty = new constructor();
1172 // This gives us the keys that the constructor sets. 1182 // This gives us the keys that the constructor sets.
1173 fieldNames = constructor.$cachedClassFieldNames = Object.keys(empty); 1183 fieldNames = constructor.$cachedClassFieldNames = Object.keys(empty);
1174 } 1184 }
1175 var result = new Array(fieldNames.length); 1185 var result = new Array(fieldNames.length);
1176 for (var i = 0; i < fieldNames.length; i++) { 1186 for (var i = 0; i < fieldNames.length; i++) {
1177 result[i] = o[fieldNames[i]]; 1187 result[i] = o[fieldNames[i]];
1178 } 1188 }
1179 return result; 1189 return result;
1180 }'''); 1190 }''');
1181 globals.add(new js.Property(js.string(CLASS_FIELDS_EXTRACTOR), 1191 globals.add(new js.Property(
1182 extractFieldsFunction)); 1192 js.string(CLASS_FIELDS_EXTRACTOR), extractFieldsFunction));
1183 1193
1184 js.Expression createInstanceFromClassIdFunction = js.js(''' 1194 js.Expression createInstanceFromClassIdFunction = js.js('''
1185 function(name) { 1195 function(name) {
1186 var constructor = getGlobalFromName(name); 1196 var constructor = getGlobalFromName(name);
1187 return new constructor(); 1197 return new constructor();
1188 } 1198 }
1189 '''); 1199 ''');
1190 globals.add(new js.Property(js.string(INSTANCE_FROM_CLASS_ID), 1200 globals.add(new js.Property(js.string(INSTANCE_FROM_CLASS_ID),
1191 createInstanceFromClassIdFunction)); 1201 createInstanceFromClassIdFunction));
1192 1202
1193 js.Expression initializeEmptyInstanceFunction = js.js(''' 1203 js.Expression initializeEmptyInstanceFunction = js.js('''
1194 function(name, o, fields) { 1204 function(name, o, fields) {
1195 var constructor = o.constructor; 1205 var constructor = o.constructor;
1196 // By construction the object `o` is an empty object with the same 1206 // By construction the object `o` is an empty object with the same
1197 // keys as the one we used in the extract-fields function. 1207 // keys as the one we used in the extract-fields function.
1198 var fieldNames = Object.keys(o); 1208 var fieldNames = Object.keys(o);
1199 if (fieldNames.length != fields.length) { 1209 if (fieldNames.length != fields.length) {
1200 throw new Error("Mismatch during deserialization."); 1210 throw new Error("Mismatch during deserialization.");
1201 } 1211 }
1202 for (var i = 0; i < fields.length; i++) { 1212 for (var i = 0; i < fields.length; i++) {
1203 o[fieldNames[i]] = fields[i]; 1213 o[fieldNames[i]] = fields[i];
1204 } 1214 }
1205 return o; 1215 return o;
1206 }'''); 1216 }''');
1207 globals.add(new js.Property(js.string(INITIALIZE_EMPTY_INSTANCE), 1217 globals.add(new js.Property(js.string(INITIALIZE_EMPTY_INSTANCE),
1208 initializeEmptyInstanceFunction)); 1218 initializeEmptyInstanceFunction));
1209 } 1219 }
1210 1220
1211 globals.add(emitMangledGlobalNames()); 1221 globals.add(emitMangledGlobalNames());
1212 1222
1213 // The [MANGLED_NAMES] table must contain the mapping for const symbols. 1223 // The [MANGLED_NAMES] table must contain the mapping for const symbols.
1214 // Without const symbols, the table is only relevant for reflection and 1224 // Without const symbols, the table is only relevant for reflection and
1215 // therefore unused in this emitter. 1225 // therefore unused in this emitter.
1216 List<js.Property> mangledNamesProperties = <js.Property>[]; 1226 List<js.Property> mangledNamesProperties = <js.Property>[];
1217 program.symbolsMap.forEach((js.Name mangledName, String unmangledName) { 1227 program.symbolsMap.forEach((js.Name mangledName, String unmangledName) {
1218 mangledNamesProperties.add( 1228 mangledNamesProperties
1219 new js.Property(mangledName, js.string(unmangledName))); 1229 .add(new js.Property(mangledName, js.string(unmangledName)));
1220 }); 1230 });
1221 globals.add(new js.Property( 1231 globals.add(new js.Property(js.string(MANGLED_NAMES),
1222 js.string(MANGLED_NAMES),
1223 new js.ObjectInitializer(mangledNamesProperties))); 1232 new js.ObjectInitializer(mangledNamesProperties)));
1224 1233
1225 globals.add(emitGetTypeFromName()); 1234 globals.add(emitGetTypeFromName());
1226 1235
1227 globals.addAll(emitMetadata(program)); 1236 globals.addAll(emitMetadata(program));
1228 1237
1229 if (program.needsNativeSupport) { 1238 if (program.needsNativeSupport) {
1230 globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG), 1239 globals.add(new js.Property(
1231 new js.LiteralNull())); 1240 js.string(INTERCEPTORS_BY_TAG), new js.LiteralNull()));
1232 globals.add(new js.Property(js.string(LEAF_TAGS), 1241 globals.add(new js.Property(js.string(LEAF_TAGS), new js.LiteralNull()));
1233 new js.LiteralNull()));
1234 } 1242 }
1235 1243
1236 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals); 1244 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
1237 1245
1238 return js.js.statement('var init = #;', globalsObject); 1246 return js.js.statement('var init = #;', globalsObject);
1239 } 1247 }
1240 1248
1241 /// Emits data needed for native classes. 1249 /// Emits data needed for native classes.
1242 /// 1250 ///
1243 /// We don't try to reduce the size of the native data, but rather build 1251 /// We don't try to reduce the size of the native data, but rather build
1244 /// JavaScript object literals that contain all the information directly. 1252 /// JavaScript object literals that contain all the information directly.
1245 /// This means that the output size is bigger, but that the startup is faster. 1253 /// This means that the output size is bigger, but that the startup is faster.
1246 /// 1254 ///
1247 /// This function is the static equivalent of 1255 /// This function is the static equivalent of
1248 /// [NativeGenerator.buildNativeInfoHandler]. 1256 /// [NativeGenerator.buildNativeInfoHandler].
1249 js.Statement emitNativeSupport(Fragment fragment) { 1257 js.Statement emitNativeSupport(Fragment fragment) {
1250 List<js.Statement> statements = <js.Statement>[]; 1258 List<js.Statement> statements = <js.Statement>[];
1251 1259
1252 // The isolate-affinity tag must only be initialized once per program. 1260 // The isolate-affinity tag must only be initialized once per program.
1253 if (fragment.isMainFragment && 1261 if (fragment.isMainFragment &&
1254 NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { 1262 NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
1255 statements.add(NativeGenerator.generateIsolateAffinityTagInitialization( 1263 statements.add(NativeGenerator.generateIsolateAffinityTagInitialization(
1256 backend, 1264 backend,
1257 generateEmbeddedGlobalAccess, 1265 generateEmbeddedGlobalAccess,
1258 js.js(""" 1266 js.js(
1267 """
1259 // On V8, the 'intern' function converts a string to a symbol, which 1268 // On V8, the 'intern' function converts a string to a symbol, which
1260 // makes property access much faster. 1269 // makes property access much faster.
1261 function (s) { 1270 function (s) {
1262 var o = {}; 1271 var o = {};
1263 o[s] = 1; 1272 o[s] = 1;
1264 return Object.keys(convertToFastObject(o))[0]; 1273 return Object.keys(convertToFastObject(o))[0];
1265 }""", []))); 1274 }""",
1275 [])));
1266 } 1276 }
1267 1277
1268 Map<String, js.Expression> interceptorsByTag = <String, js.Expression>{}; 1278 Map<String, js.Expression> interceptorsByTag = <String, js.Expression>{};
1269 Map<String, js.Expression> leafTags = <String, js.Expression>{}; 1279 Map<String, js.Expression> leafTags = <String, js.Expression>{};
1270 js.Statement subclassAssignment = new js.EmptyStatement(); 1280 js.Statement subclassAssignment = new js.EmptyStatement();
1271 1281
1272 for (Library library in fragment.libraries) { 1282 for (Library library in fragment.libraries) {
1273 for (Class cls in library.classes) { 1283 for (Class cls in library.classes) {
1274 if (cls.nativeLeafTags != null) { 1284 if (cls.nativeLeafTags != null) {
1275 for (String tag in cls.nativeLeafTags) { 1285 for (String tag in cls.nativeLeafTags) {
1276 interceptorsByTag[tag] = classReference(cls); 1286 interceptorsByTag[tag] = classReference(cls);
1277 leafTags[tag] = new js.LiteralBool(true); 1287 leafTags[tag] = new js.LiteralBool(true);
1278 } 1288 }
1279 } 1289 }
1280 if (cls.nativeNonLeafTags != null) { 1290 if (cls.nativeNonLeafTags != null) {
1281 for (String tag in cls.nativeNonLeafTags) { 1291 for (String tag in cls.nativeNonLeafTags) {
1282 interceptorsByTag[tag] = classReference(cls); 1292 interceptorsByTag[tag] = classReference(cls);
1283 leafTags[tag] = new js.LiteralBool(false); 1293 leafTags[tag] = new js.LiteralBool(false);
1284 } 1294 }
1285 if (cls.nativeExtensions != null) { 1295 if (cls.nativeExtensions != null) {
1286 List<Class> subclasses = cls.nativeExtensions; 1296 List<Class> subclasses = cls.nativeExtensions;
1287 js.Expression value = js.string(cls.nativeNonLeafTags[0]); 1297 js.Expression value = js.string(cls.nativeNonLeafTags[0]);
1288 for (Class subclass in subclasses) { 1298 for (Class subclass in subclasses) {
1289 value = js.js('#.# = #', 1299 value = js.js('#.# = #', [
1290 [classReference(subclass), 1300 classReference(subclass),
1291 NATIVE_SUPERCLASS_TAG_NAME, 1301 NATIVE_SUPERCLASS_TAG_NAME,
1292 js.string(cls.nativeNonLeafTags[0])]); 1302 js.string(cls.nativeNonLeafTags[0])
1303 ]);
1293 } 1304 }
1294 subclassAssignment = new js.ExpressionStatement(value); 1305 subclassAssignment = new js.ExpressionStatement(value);
1295 } 1306 }
1296 } 1307 }
1297 } 1308 }
1298 } 1309 }
1299 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", 1310 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);",
1300 js.objectLiteral(interceptorsByTag))); 1311 js.objectLiteral(interceptorsByTag)));
1301 statements.add(js.js.statement("setOrUpdateLeafTags(#);", 1312 statements.add(
1302 js.objectLiteral(leafTags))); 1313 js.js.statement("setOrUpdateLeafTags(#);", js.objectLiteral(leafTags)));
1303 statements.add(subclassAssignment); 1314 statements.add(subclassAssignment);
1304 1315
1305 return new js.Block(statements); 1316 return new js.Block(statements);
1306 } 1317 }
1307 } 1318 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698