| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart2js.new_js_emitter.model_emitter; | 5 library dart2js.new_js_emitter.model_emitter; |
| 6 | 6 |
| 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; | 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; |
| 8 import '../../dart2jslib.dart' show Compiler; | 8 import '../../dart2jslib.dart' show Compiler; |
| 9 import '../../elements/elements.dart' show ClassElement, FunctionElement; | 9 import '../../elements/elements.dart' show ClassElement, FunctionElement; |
| 10 import '../../js/js.dart' as js; | 10 import '../../js/js.dart' as js; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 static const String deferredInitializersGlobal = | 86 static const String deferredInitializersGlobal = |
| 87 r"$__dart_deferred_initializers__"; | 87 r"$__dart_deferred_initializers__"; |
| 88 | 88 |
| 89 static const String deferredExtension = "part.js"; | 89 static const String deferredExtension = "part.js"; |
| 90 | 90 |
| 91 static const String typeNameProperty = r"builtin$cls"; | 91 static const String typeNameProperty = r"builtin$cls"; |
| 92 | 92 |
| 93 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) | 93 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) |
| 94 : this.compiler = compiler, | 94 : this.compiler = compiler, |
| 95 this.namer = namer { | 95 this.namer = namer { |
| 96 // TODO(floitsch): remove hard-coded name. | |
| 97 // TODO(floitsch): there is no harm in caching the template. | |
| 98 js.Template makeConstantListTemplate = | |
| 99 js.js.uncachedExpressionTemplate('makeConstList(#)'); | |
| 100 | 96 |
| 101 this.constantEmitter = new ConstantEmitter( | 97 this.constantEmitter = new ConstantEmitter( |
| 102 compiler, namer, this.generateConstantReference, | 98 compiler, namer, this.generateConstantReference, |
| 103 makeConstantListTemplate); | 99 constantListGenerator); |
| 100 } |
| 101 |
| 102 js.Expression constantListGenerator(js.Expression array) { |
| 103 // TODO(floitsch): remove hard-coded name. |
| 104 return js.js('makeConstList(#)', [array]); |
| 104 } | 105 } |
| 105 | 106 |
| 106 js.Expression generateEmbeddedGlobalAccess(String global) { | 107 js.Expression generateEmbeddedGlobalAccess(String global) { |
| 107 return js.js(generateEmbeddedGlobalAccessString(global)); | 108 return js.js(generateEmbeddedGlobalAccessString(global)); |
| 108 } | 109 } |
| 109 | 110 |
| 110 String generateEmbeddedGlobalAccessString(String global) { | 111 String generateEmbeddedGlobalAccessString(String global) { |
| 111 // TODO(floitsch): don't use 'init' as global embedder storage. | 112 // TODO(floitsch): don't use 'init' as global embedder storage. |
| 112 return 'init.$global'; | 113 return 'init.$global'; |
| 113 } | 114 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 js.Property emitMangledGlobalNames() { | 378 js.Property emitMangledGlobalNames() { |
| 378 List<js.Property> names = <js.Property>[]; | 379 List<js.Property> names = <js.Property>[]; |
| 379 | 380 |
| 380 // We want to keep the original names for the most common core classes when | 381 // We want to keep the original names for the most common core classes when |
| 381 // calling toString on them. | 382 // calling toString on them. |
| 382 List<ClassElement> nativeClassesNeedingUnmangledName = | 383 List<ClassElement> nativeClassesNeedingUnmangledName = |
| 383 [compiler.intClass, compiler.doubleClass, compiler.numClass, | 384 [compiler.intClass, compiler.doubleClass, compiler.numClass, |
| 384 compiler.stringClass, compiler.boolClass, compiler.nullClass, | 385 compiler.stringClass, compiler.boolClass, compiler.nullClass, |
| 385 compiler.listClass]; | 386 compiler.listClass]; |
| 386 nativeClassesNeedingUnmangledName.forEach((element) { | 387 nativeClassesNeedingUnmangledName.forEach((element) { |
| 387 names.add(new js.Property(js.string(namer.className(element)), | 388 names.add(new js.Property(js.quoteName(namer.className(element)), |
| 388 js.string(element.name))); | 389 js.string(element.name))); |
| 389 }); | 390 }); |
| 390 | 391 |
| 391 return new js.Property(js.string(MANGLED_GLOBAL_NAMES), | 392 return new js.Property(js.string(MANGLED_GLOBAL_NAMES), |
| 392 new js.ObjectInitializer(names)); | 393 new js.ObjectInitializer(names)); |
| 393 } | 394 } |
| 394 | 395 |
| 395 js.Statement emitDeferredInitializerGlobal(Map loadMap) { | 396 js.Statement emitDeferredInitializerGlobal(Map loadMap) { |
| 396 if (loadMap.isEmpty) return new js.Block.empty(); | 397 if (loadMap.isEmpty) return new js.Block.empty(); |
| 397 | 398 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 "The array is completely empty if there is no constant at all."; | 573 "The array is completely empty if there is no constant at all."; |
| 573 | 574 |
| 574 js.ArrayInitializer emitConstants(List<Constant> constants) { | 575 js.ArrayInitializer emitConstants(List<Constant> constants) { |
| 575 List<js.Expression> data = <js.Expression>[]; | 576 List<js.Expression> data = <js.Expression>[]; |
| 576 if (constants.isNotEmpty) { | 577 if (constants.isNotEmpty) { |
| 577 int holderIndex = constants.first.holder.index; | 578 int holderIndex = constants.first.holder.index; |
| 578 data.add(js.number(holderIndex)); | 579 data.add(js.number(holderIndex)); |
| 579 data.addAll(constants.expand((Constant constant) { | 580 data.addAll(constants.expand((Constant constant) { |
| 580 assert(constant.holder.index == holderIndex); | 581 assert(constant.holder.index == holderIndex); |
| 581 js.Expression code = constantEmitter.generate(constant.value); | 582 js.Expression code = constantEmitter.generate(constant.value); |
| 582 return [js.string(constant.name), unparse(compiler, code)]; | 583 return [js.quoteName(constant.name), unparse(compiler, code)]; |
| 583 })); | 584 })); |
| 584 } | 585 } |
| 585 return new js.ArrayInitializer(data); | 586 return new js.ArrayInitializer(data); |
| 586 } | 587 } |
| 587 | 588 |
| 588 js.Block emitStaticNonFinalFields(List<StaticField> fields) { | 589 js.Block emitStaticNonFinalFields(List<StaticField> fields) { |
| 589 Iterable<js.Statement> statements = fields.map((StaticField field) { | 590 Iterable<js.Statement> statements = fields.map((StaticField field) { |
| 590 return js.js.statement("#.# = #;", | 591 return js.js.statement("#.# = #;", |
| 591 [field.holder.name, field.name, field.code]); | 592 [field.holder.name, field.name, field.code]); |
| 592 }); | 593 }); |
| 593 return new js.Block(statements.toList()); | 594 return new js.Block(statements.toList()); |
| 594 } | 595 } |
| 595 | 596 |
| 596 js.Expression emitLazilyInitializedStatics(List<StaticField> fields) { | 597 js.Expression emitLazilyInitializedStatics(List<StaticField> fields) { |
| 597 Iterable fieldDescriptors = fields.expand((field) => | 598 Iterable fieldDescriptors = fields.expand((field) => |
| 598 [ js.string(field.name), | 599 [ js.quoteName(field.name), |
| 599 js.string("${namer.getterPrefix}${field.name}"), | 600 js.quoteName(namer.deriveLazyInitializerName(field.name)), |
| 600 js.number(field.holder.index), | 601 js.number(field.holder.index), |
| 601 emitLazyInitializer(field) ]); | 602 emitLazyInitializer(field) ]); |
| 602 return new js.ArrayInitializer(fieldDescriptors.toList(growable: false)); | 603 return new js.ArrayInitializer(fieldDescriptors.toList(growable: false)); |
| 603 } | 604 } |
| 604 | 605 |
| 605 js.Block emitEagerClassInitializations(List<Library> libraries) { | 606 js.Block emitEagerClassInitializations(List<Library> libraries) { |
| 606 js.Statement createInstantiation(Class cls) { | 607 js.Statement createInstantiation(Class cls) { |
| 607 return js.js.statement('new #.#()', [cls.holder.name, cls.name]); | 608 return js.js.statement('new #.#()', [cls.holder.name, cls.name]); |
| 608 } | 609 } |
| 609 | 610 |
| 610 List<js.Statement> instantiations = | 611 List<js.Statement> instantiations = |
| 611 libraries.expand((Library library) => library.classes) | 612 libraries.expand((Library library) => library.classes) |
| 612 .where((Class cls) => cls.isEager) | 613 .where((Class cls) => cls.isEager) |
| 613 .map(createInstantiation) | 614 .map(createInstantiation) |
| 614 .toList(growable: false); | 615 .toList(growable: false); |
| 615 return new js.Block(instantiations); | 616 return new js.Block(instantiations); |
| 616 } | 617 } |
| 617 | 618 |
| 618 // This string should be referenced wherever JavaScript code makes assumptions | 619 // This string should be referenced wherever JavaScript code makes assumptions |
| 619 // on the mixin format. | 620 // on the mixin format. |
| 620 static final String nativeInfoDescription = | 621 static final String nativeInfoDescription = |
| 621 "A class is encoded as follows:" | 622 "A class is encoded as follows:" |
| 622 " [name, class-code, holder-index], or " | 623 " [name, class-code, holder-index], or " |
| 623 " [name, class-code, native-info, holder-index]."; | 624 " [name, class-code, native-info, holder-index]."; |
| 624 | 625 |
| 625 js.Expression emitLibrary(Library library) { | 626 js.Expression emitLibrary(Library library) { |
| 626 Iterable staticDescriptors = library.statics.expand(emitStaticMethod); | 627 Iterable staticDescriptors = library.statics.expand(emitStaticMethod); |
| 627 | 628 |
| 628 Iterable classDescriptors = library.classes.expand((Class cls) { | 629 Iterable classDescriptors = library.classes.expand((Class cls) { |
| 629 js.LiteralString name = js.string(cls.name); | 630 js.Literal name = js.quoteName(cls.name); |
| 630 js.LiteralNumber holderIndex = js.number(cls.holder.index); | 631 js.LiteralNumber holderIndex = js.number(cls.holder.index); |
| 631 js.Expression emittedClass = emitClass(cls); | 632 js.Expression emittedClass = emitClass(cls); |
| 632 if (cls.nativeInfo == null) { | 633 if (cls.nativeInfo == null) { |
| 633 return [name, emittedClass, holderIndex]; | 634 return [name, emittedClass, holderIndex]; |
| 634 } else { | 635 } else { |
| 635 return [name, emittedClass, js.string(cls.nativeInfo), holderIndex]; | 636 return [name, emittedClass, cls.nativeInfo, holderIndex]; |
| 636 } | 637 } |
| 637 }); | 638 }); |
| 638 | 639 |
| 639 js.Expression staticArray = | 640 js.Expression staticArray = |
| 640 new js.ArrayInitializer(staticDescriptors.toList(growable: false)); | 641 new js.ArrayInitializer(staticDescriptors.toList(growable: false)); |
| 641 js.Expression classArray = | 642 js.Expression classArray = |
| 642 new js.ArrayInitializer(classDescriptors.toList(growable: false)); | 643 new js.ArrayInitializer(classDescriptors.toList(growable: false)); |
| 643 | 644 |
| 644 return new js.ArrayInitializer([staticArray, classArray]); | 645 return new js.ArrayInitializer([staticArray, classArray]); |
| 645 } | 646 } |
| 646 | 647 |
| 647 js.Expression _generateConstructor(Class cls) { | 648 js.Expression _generateConstructor(Class cls) { |
| 648 List<String> fieldNames = <String>[]; | 649 List<js.Name> fieldNames = const <js.Name>[]; |
| 649 | 650 |
| 650 // If the class is not directly instantiated we only need it for inheritance | 651 // If the class is not directly instantiated we only need it for inheritance |
| 651 // or RTI. In either case we don't need its fields. | 652 // or RTI. In either case we don't need its fields. |
| 652 if (cls.isDirectlyInstantiated && !cls.isNative) { | 653 if (cls.isDirectlyInstantiated && !cls.isNative) { |
| 653 fieldNames = cls.fields.map((Field field) => field.name).toList(); | 654 fieldNames = cls.fields.map((Field field) => field.name).toList(); |
| 654 } | 655 } |
| 655 String name = cls.name; | 656 js.Name name = cls.name; |
| 656 String parameters = fieldNames.join(', '); | 657 |
| 657 String assignments = fieldNames | 658 Iterable<js.Name> assignments = fieldNames.map((js.Name field) { |
| 658 .map((String field) => "this.$field = $field;\n") | 659 return js.js("this.#field = #field", {"field": field}); |
| 659 .join(); | 660 }); |
| 660 String code = 'function $name($parameters) { $assignments }'; | 661 |
| 661 js.Template template = js.js.uncachedExpressionTemplate(code); | 662 return js.js('function #(#) { # }', [name, fieldNames, assignments]); |
| 662 return template.instantiate(const []); | |
| 663 } | 663 } |
| 664 | 664 |
| 665 Method _generateGetter(Field field) { | 665 Method _generateGetter(Field field) { |
| 666 String getterTemplateFor(int flags) { | 666 String getterTemplateFor(int flags) { |
| 667 switch (flags) { | 667 switch (flags) { |
| 668 case 1: return "function() { return this[#]; }"; | 668 case 1: return "function() { return this[#]; }"; |
| 669 case 2: return "function(receiver) { return receiver[#]; }"; | 669 case 2: return "function(receiver) { return receiver[#]; }"; |
| 670 case 3: return "function(receiver) { return this[#]; }"; | 670 case 3: return "function(receiver) { return this[#]; }"; |
| 671 } | 671 } |
| 672 return null; | 672 return null; |
| 673 } | 673 } |
| 674 | 674 |
| 675 js.Expression fieldName = js.string(field.name); | 675 js.Expression fieldName = js.quoteName(field.name); |
| 676 js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName); | 676 js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName); |
| 677 String getterName = "${namer.getterPrefix}${field.accessorName}"; | 677 js.Name getterName = namer.deriveGetterName(field.accessorName); |
| 678 return new StubMethod(getterName, code); | 678 return new StubMethod(getterName, code); |
| 679 } | 679 } |
| 680 | 680 |
| 681 Method _generateSetter(Field field) { | 681 Method _generateSetter(Field field) { |
| 682 String setterTemplateFor(int flags) { | 682 String setterTemplateFor(int flags) { |
| 683 switch (flags) { | 683 switch (flags) { |
| 684 case 1: return "function(val) { return this[#] = val; }"; | 684 case 1: return "function(val) { return this[#] = val; }"; |
| 685 case 2: return "function(receiver, val) { return receiver[#] = val; }"; | 685 case 2: return "function(receiver, val) { return receiver[#] = val; }"; |
| 686 case 3: return "function(receiver, val) { return this[#] = val; }"; | 686 case 3: return "function(receiver, val) { return this[#] = val; }"; |
| 687 } | 687 } |
| 688 return null; | 688 return null; |
| 689 } | 689 } |
| 690 js.Expression fieldName = js.string(field.name); | 690 js.Expression fieldName = js.quoteName(field.name); |
| 691 js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName); | 691 js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName); |
| 692 String setterName = "${namer.setterPrefix}${field.accessorName}"; | 692 js.Name setterName = namer.deriveSetterName(field.accessorName); |
| 693 return new StubMethod(setterName, code); | 693 return new StubMethod(setterName, code); |
| 694 } | 694 } |
| 695 | 695 |
| 696 Iterable<Method> _generateGettersSetters(Class cls) { | 696 Iterable<Method> _generateGettersSetters(Class cls) { |
| 697 Iterable<Method> getters = cls.fields | 697 Iterable<Method> getters = cls.fields |
| 698 .where((Field field) => field.needsGetter) | 698 .where((Field field) => field.needsGetter) |
| 699 .map(_generateGetter); | 699 .map(_generateGetter); |
| 700 | 700 |
| 701 Iterable<Method> setters = cls.fields | 701 Iterable<Method> setters = cls.fields |
| 702 .where((Field field) => field.needsUncheckedSetter) | 702 .where((Field field) => field.needsUncheckedSetter) |
| 703 .map(_generateSetter); | 703 .map(_generateSetter); |
| 704 | 704 |
| 705 return [getters, setters].expand((x) => x); | 705 return [getters, setters].expand((x) => x); |
| 706 } | 706 } |
| 707 | 707 |
| 708 // This string should be referenced wherever JavaScript code makes assumptions | 708 // This string should be referenced wherever JavaScript code makes assumptions |
| 709 // on the mixin format. | 709 // on the mixin format. |
| 710 static final String mixinFormatDescription = | 710 static final String mixinFormatDescription = |
| 711 "Mixins have a reference to their mixin class at the place of the usual" | 711 "Mixins have a reference to their mixin class at the place of the usual" |
| 712 "constructor. If they are instantiated the constructor follows the" | 712 "constructor. If they are instantiated the constructor follows the" |
| 713 "reference."; | 713 "reference."; |
| 714 | 714 |
| 715 js.Expression emitClass(Class cls) { | 715 js.Expression emitClass(Class cls) { |
| 716 List elements = [js.string(cls.superclassName), | 716 List elements = [js.quoteName(cls.superclassName, allowNull: true), |
| 717 js.number(cls.superclassHolderIndex)]; | 717 js.number(cls.superclassHolderIndex)]; |
| 718 | 718 |
| 719 if (cls.isMixinApplication) { | 719 if (cls.isMixinApplication) { |
| 720 MixinApplication mixin = cls; | 720 MixinApplication mixin = cls; |
| 721 elements.add(js.string(mixin.mixinClass.name)); | 721 elements.add(js.quoteName(mixin.mixinClass.name)); |
| 722 elements.add(js.number(mixin.mixinClass.holder.index)); | 722 elements.add(js.number(mixin.mixinClass.holder.index)); |
| 723 if (cls.isDirectlyInstantiated) { | 723 if (cls.isDirectlyInstantiated) { |
| 724 elements.add(_generateConstructor(cls)); | 724 elements.add(_generateConstructor(cls)); |
| 725 } | 725 } |
| 726 } else { | 726 } else { |
| 727 elements.add(_generateConstructor(cls)); | 727 elements.add(_generateConstructor(cls)); |
| 728 } | 728 } |
| 729 Iterable<Method> methods = cls.methods; | 729 Iterable<Method> methods = cls.methods; |
| 730 Iterable<Method> isChecks = cls.isChecks; | 730 Iterable<Method> isChecks = cls.isChecks; |
| 731 Iterable<Method> callStubs = cls.callStubs; | 731 Iterable<Method> callStubs = cls.callStubs; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 properties.add(new js.Property(js.string(name), | 840 properties.add(new js.Property(js.string(name), |
| 841 generateConstantReference(value))); | 841 generateConstantReference(value))); |
| 842 }); | 842 }); |
| 843 return new js.ObjectInitializer(properties); | 843 return new js.ObjectInitializer(properties); |
| 844 } | 844 } |
| 845 } | 845 } |
| 846 | 846 |
| 847 Iterable<js.Expression> emitInstanceMethod(Method method) { | 847 Iterable<js.Expression> emitInstanceMethod(Method method) { |
| 848 | 848 |
| 849 List<js.Expression> makeNameCodePair(Method method) { | 849 List<js.Expression> makeNameCodePair(Method method) { |
| 850 return [js.string(method.name), method.code]; | 850 return [js.quoteName(method.name), method.code]; |
| 851 } | 851 } |
| 852 | 852 |
| 853 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { | 853 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { |
| 854 js.Expression callName = stub.callName == null | 854 js.Expression callName = stub.callName == null |
| 855 ? new js.LiteralNull() | 855 ? new js.LiteralNull() |
| 856 : js.string(stub.callName); | 856 : js.quoteName(stub.callName); |
| 857 return [js.string(stub.name), callName, stub.code]; | 857 return [js.quoteName(stub.name), callName, stub.code]; |
| 858 } | 858 } |
| 859 | 859 |
| 860 if (method is InstanceMethod) { | 860 if (method is InstanceMethod) { |
| 861 if (method.needsTearOff || method.aliasName != null) { | 861 if (method.needsTearOff || method.aliasName != null) { |
| 862 /// See [parseFunctionDescriptorBoilerplate] for a full description of | 862 /// See [parseFunctionDescriptorBoilerplate] for a full description of |
| 863 /// the format. | 863 /// the format. |
| 864 // [name, [aliasName, function, callName, isIntercepted, tearOffName, | 864 // [name, [aliasName, function, callName, isIntercepted, tearOffName, |
| 865 // functionType, stub1_name, stub1_callName, stub1_code, ...] | 865 // functionType, stub1_name, stub1_callName, stub1_code, ...] |
| 866 var data = []; | 866 var data = []; |
| 867 if (method.aliasName != null) { | 867 if (method.aliasName != null) { |
| 868 data.add(js.string(method.aliasName)); | 868 data.add(js.quoteName(method.aliasName)); |
| 869 } | 869 } |
| 870 data.add(method.code); | 870 data.add(method.code); |
| 871 data.add(js.string(method.callName)); | 871 data.add(js.quoteName(method.callName, allowNull: true)); |
| 872 | 872 |
| 873 if (method.needsTearOff) { | 873 if (method.needsTearOff) { |
| 874 bool isIntercepted = backend.isInterceptedMethod(method.element); | 874 bool isIntercepted = backend.isInterceptedMethod(method.element); |
| 875 data.add(new js.LiteralBool(isIntercepted)); | 875 data.add(new js.LiteralBool(isIntercepted)); |
| 876 data.add(js.string(method.tearOffName)); | 876 data.add(js.quoteName(method.tearOffName)); |
| 877 data.add((method.functionType)); | 877 data.add((method.functionType)); |
| 878 } | 878 } |
| 879 | 879 |
| 880 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | 880 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); |
| 881 if (method.canBeApplied) { | 881 if (method.canBeApplied) { |
| 882 data.add(js.number(method.requiredParameterCount)); | 882 data.add(js.number(method.requiredParameterCount)); |
| 883 data.add(_encodeOptionalParameterDefaultValues(method)); | 883 data.add(_encodeOptionalParameterDefaultValues(method)); |
| 884 } | 884 } |
| 885 return [js.string(method.name), new js.ArrayInitializer(data)]; | 885 return [js.quoteName(method.name), new js.ArrayInitializer(data)]; |
| 886 } else { | 886 } else { |
| 887 // TODO(floitsch): not the most efficient way... | 887 // TODO(floitsch): not the most efficient way... |
| 888 return ([method]..addAll(method.parameterStubs)) | 888 return ([method]..addAll(method.parameterStubs)) |
| 889 .expand(makeNameCodePair); | 889 .expand(makeNameCodePair); |
| 890 } | 890 } |
| 891 } else { | 891 } else { |
| 892 return makeNameCodePair(method); | 892 return makeNameCodePair(method); |
| 893 } | 893 } |
| 894 } | 894 } |
| 895 | 895 |
| 896 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { | 896 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { |
| 897 js.Expression holderIndex = js.number(method.holder.index); | 897 js.Expression holderIndex = js.number(method.holder.index); |
| 898 List<js.Expression> output = <js.Expression>[]; | 898 List<js.Expression> output = <js.Expression>[]; |
| 899 | 899 |
| 900 void _addMethod(Method method) { | 900 void _addMethod(Method method) { |
| 901 js.Expression unparsed = unparse(compiler, method.code); | 901 js.Expression unparsed = unparse(compiler, method.code); |
| 902 output.add(js.string(method.name)); | 902 output.add(js.quoteName(method.name)); |
| 903 output.add(holderIndex); | 903 output.add(holderIndex); |
| 904 output.add(unparsed); | 904 output.add(unparsed); |
| 905 } | 905 } |
| 906 | 906 |
| 907 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { | 907 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { |
| 908 js.Expression callName = stub.callName == null | 908 js.Expression callName = stub.callName == null |
| 909 ? new js.LiteralNull() | 909 ? new js.LiteralNull() |
| 910 : js.string(stub.callName); | 910 : js.quoteName(stub.callName); |
| 911 return [js.string(stub.name), callName, unparse(compiler, stub.code)]; | 911 return [js.quoteName(stub.name), callName, unparse(compiler, stub.code)]; |
| 912 } | 912 } |
| 913 | 913 |
| 914 _addMethod(method); | 914 _addMethod(method); |
| 915 // TODO(floitsch): can there be anything else than a StaticDartMethod? | 915 // TODO(floitsch): can there be anything else than a StaticDartMethod? |
| 916 if (method is StaticDartMethod) { | 916 if (method is StaticDartMethod) { |
| 917 if (method.needsTearOff) { | 917 if (method.needsTearOff) { |
| 918 /// The format emitted is the same as for the parser specified at | 918 /// The format emitted is the same as for the parser specified at |
| 919 /// [parseFunctionDescriptorBoilerplate] except for the missing | 919 /// [parseFunctionDescriptorBoilerplate] except for the missing |
| 920 /// field whether the method is intercepted. | 920 /// field whether the method is intercepted. |
| 921 // [name, [function, callName, tearOffName, functionType, | 921 // [name, [function, callName, tearOffName, functionType, |
| 922 // stub1_name, stub1_callName, stub1_code, ...] | 922 // stub1_name, stub1_callName, stub1_code, ...] |
| 923 var data = [unparse(compiler, method.code)]; | 923 var data = [unparse(compiler, method.code)]; |
| 924 data.add(js.string(method.callName)); | 924 data.add(js.quoteName(method.callName)); |
| 925 data.add(js.string(method.tearOffName)); | 925 data.add(js.quoteName(method.tearOffName)); |
| 926 data.add(method.functionType); | 926 data.add(method.functionType); |
| 927 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | 927 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); |
| 928 if (method.canBeApplied) { | 928 if (method.canBeApplied) { |
| 929 data.add(js.number(method.requiredParameterCount)); | 929 data.add(js.number(method.requiredParameterCount)); |
| 930 data.add(_encodeOptionalParameterDefaultValues(method)); | 930 data.add(_encodeOptionalParameterDefaultValues(method)); |
| 931 } | 931 } |
| 932 return [js.string(method.name), holderIndex, | 932 return [js.quoteName(method.name), holderIndex, |
| 933 new js.ArrayInitializer(data)]; | 933 new js.ArrayInitializer(data)]; |
| 934 } else { | 934 } else { |
| 935 method.parameterStubs.forEach(_addMethod); | 935 method.parameterStubs.forEach(_addMethod); |
| 936 } | 936 } |
| 937 } | 937 } |
| 938 return output; | 938 return output; |
| 939 } | 939 } |
| 940 | 940 |
| 941 static final String setupProgramName = "setupProgram"; | 941 static final String setupProgramName = "setupProgram"; |
| 942 | 942 |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1276 | 1276 |
| 1277 var end = Date.now(); | 1277 var end = Date.now(); |
| 1278 // print('Setup: ' + (end - start) + ' ms.'); | 1278 // print('Setup: ' + (end - start) + ' ms.'); |
| 1279 | 1279 |
| 1280 #invokeMain; // Start main. | 1280 #invokeMain; // Start main. |
| 1281 | 1281 |
| 1282 })(Date.now(), #code) | 1282 })(Date.now(), #code) |
| 1283 }"""; | 1283 }"""; |
| 1284 | 1284 |
| 1285 } | 1285 } |
| OLD | NEW |