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

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

Issue 11188004: Add a content-security-policy (CSP) flag. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Split CSP code into separate class. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 29 matching lines...) Expand all
40 CodeBuffer mainBuffer; 40 CodeBuffer mainBuffer;
41 /** Shorter access to [isolatePropertiesName]. Both here in the code, as 41 /** Shorter access to [isolatePropertiesName]. Both here in the code, as
42 well as in the generated code. */ 42 well as in the generated code. */
43 String isolateProperties; 43 String isolateProperties;
44 String classesCollector; 44 String classesCollector;
45 final Map<int, String> boundClosureCache; 45 final Map<int, String> boundClosureCache;
46 Set<ClassElement> checkedClasses; 46 Set<ClassElement> checkedClasses;
47 47
48 final bool generateSourceMap; 48 final bool generateSourceMap;
49 49
50 CodeEmitterTask(Compiler compiler, Namer namer, 50 CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap)
51 [bool generateSourceMap = false])
52 : boundClosureBuffer = new CodeBuffer(), 51 : boundClosureBuffer = new CodeBuffer(),
53 mainBuffer = new CodeBuffer(), 52 mainBuffer = new CodeBuffer(),
54 this.namer = namer, 53 this.namer = namer,
55 boundClosureCache = new Map<int, String>(), 54 boundClosureCache = new Map<int, String>(),
56 generateSourceMap = generateSourceMap,
57 constantEmitter = new ConstantEmitter(compiler, namer), 55 constantEmitter = new ConstantEmitter(compiler, namer),
58 super(compiler) { 56 super(compiler) {
59 nativeEmitter = new NativeEmitter(this); 57 nativeEmitter = new NativeEmitter(this);
60 } 58 }
61 59
62 void computeRequiredTypeChecks() { 60 void computeRequiredTypeChecks() {
63 assert(checkedClasses == null); 61 assert(checkedClasses == null);
64 checkedClasses = new Set<ClassElement>(); 62 checkedClasses = new Set<ClassElement>();
65 compiler.codegenWorld.isChecks.forEach((DartType t) { 63 compiler.codegenWorld.isChecks.forEach((DartType t) {
66 if (t is InterfaceType) checkedClasses.add(t.element); 64 if (t is InterfaceType) checkedClasses.add(t.element);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 constructor.prototype = prototype; 156 constructor.prototype = prototype;
159 return constructor; 157 return constructor;
160 }"""; 158 }""";
161 } 159 }
162 160
163 /** Needs defineClass to be defined. */ 161 /** Needs defineClass to be defined. */
164 String get protoSupportCheck { 162 String get protoSupportCheck {
165 // On Firefox and Webkit browsers we can manipulate the __proto__ 163 // On Firefox and Webkit browsers we can manipulate the __proto__
166 // directly. Opera claims to have __proto__ support, but it is buggy. 164 // directly. Opera claims to have __proto__ support, but it is buggy.
167 // So we have to do more checks. 165 // So we have to do more checks.
166 // Opera bug was filed as DSK-370158, and fixed as CORE-47615
167 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes).
168 // If the browser does not support __proto__ we need to instantiate an 168 // If the browser does not support __proto__ we need to instantiate an
169 // object with the correct (internal) prototype set up correctly, and then 169 // object with the correct (internal) prototype set up correctly, and then
170 // copy the members. 170 // copy the members.
171 171
172 return ''' 172 return '''
173 var $supportsProtoName = false; 173 var $supportsProtoName = false;
174 var tmp = $defineClassName('c', ['f?'], {}).prototype; 174 var tmp = $defineClassName('c', ['f?'], {}).prototype;
175 if (tmp.__proto__) { 175 if (tmp.__proto__) {
176 tmp.__proto__ = {}; 176 tmp.__proto__ = {};
177 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true; 177 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true;
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 if (!parameters.optionalParameters.isEmpty()) { 613 if (!parameters.optionalParameters.isEmpty()) {
614 addParameterStubs(member, defineInstanceMember); 614 addParameterStubs(member, defineInstanceMember);
615 } 615 }
616 } else if (!member.isField()) { 616 } else if (!member.isField()) {
617 compiler.internalError('unexpected kind: "${member.kind}"', 617 compiler.internalError('unexpected kind: "${member.kind}"',
618 element: member); 618 element: member);
619 } 619 }
620 emitExtraAccessors(member, defineInstanceMember); 620 emitExtraAccessors(member, defineInstanceMember);
621 } 621 }
622 622
623 String generateCheckedSetter(Element member, String fieldName) { 623 /**
624 DartType type = member.computeType(compiler); 624 * Documentation wanted -- johnniwinther
625 if (type.element.isTypeVariable() 625 *
626 || type.element == compiler.dynamicClass 626 * Invariant: [classElement] must be a declaration element.
627 || type.element == compiler.objectClass) { 627 */
628 // TODO(ngeoffray): Support type checks on type parameters. 628 void emitInstanceMembers(ClassElement classElement,
floitsch 2012/10/17 21:15:01 emitInstanceMembers was just moved.
629 return null; 629 CodeBuffer buffer,
630 } else { 630 bool needsLeadingComma) {
631 SourceString helper = compiler.backend.getCheckedModeHelper(type); 631 assert(invariant(classElement, classElement.isDeclaration));
632 FunctionElement helperElement = compiler.findHelper(helper); 632 bool needsComma = needsLeadingComma;
633 String helperName = namer.isolateAccess(helperElement); 633 void defineInstanceMember(String name, CodeBuffer memberBuffer) {
634 String additionalArgument = ''; 634 if (needsComma) buffer.add(',');
635 if (helperElement.computeSignature(compiler).parameterCount != 1) { 635 needsComma = true;
636 additionalArgument = ", '${namer.operatorIs(type.element)}'"; 636 buffer.add('\n');
637 buffer.add(' $name: ');
638 buffer.add(memberBuffer);
639 }
640
641 classElement.implementation.forEachMember(
642 (ClassElement enclosing, Element member) {
643 assert(invariant(classElement, member.isDeclaration));
644 if (member.isInstanceMember()) {
645 addInstanceMember(member, defineInstanceMember);
646 }
647 },
648 includeBackendMembers: true);
649
650 generateIsTestsOn(classElement, (ClassElement other) {
651 String code;
652 if (other.isObject(compiler)) return;
653 if (nativeEmitter.requiresNativeIsCheck(other)) {
654 code = 'function() { return true; }';
655 } else {
656 code = 'true';
637 } 657 }
638 return " set\$$fieldName: function(v) { " 658 CodeBuffer typeTestBuffer = new CodeBuffer();
639 "this.$fieldName = $helperName(v$additionalArgument); }"; 659 typeTestBuffer.add(code);
660 defineInstanceMember(namer.operatorIs(other), typeTestBuffer);
661 });
662
663 if (identical(classElement, compiler.objectClass)
664 && compiler.enabledNoSuchMethod) {
665 // Emit the noSuchMethod handlers on the Object prototype now,
666 // so that the code in the dynamicFunction helper can find
667 // them. Note that this helper is invoked before analyzing the
668 // full JS script.
669 if (!nativeEmitter.handleNoSuchMethod) {
670 emitNoSuchMethodHandlers(defineInstanceMember);
671 }
640 } 672 }
641 } 673 }
642 674
643 /** 675 /**
644 * Documentation wanted -- johnniwinther 676 * Documentation wanted -- johnniwinther
645 * 677 *
646 * Invariant: [classElement] must be a declaration element. 678 * Invariant: [classElement] must be a declaration element.
647 */ 679 */
648 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) { 680 void visitClassFields(ClassElement classElement,
681 void addField(Element member,
682 String name,
683 bool needsGetter,
684 bool needsSetter,
685 bool needsCheckedSetter)) {
649 assert(invariant(classElement, classElement.isDeclaration)); 686 assert(invariant(classElement, classElement.isDeclaration));
650 // If the class is never instantiated we still need to set it up for 687 // If the class is never instantiated we still need to set it up for
651 // inheritance purposes, but we can simplify its JavaScript constructor. 688 // inheritance purposes, but we can simplify its JavaScript constructor.
652 bool isInstantiated = 689 bool isInstantiated =
653 compiler.codegenWorld.instantiatedClasses.contains(classElement); 690 compiler.codegenWorld.instantiatedClasses.contains(classElement);
654 List<String> checkedSetters = <String>[];
655 691
656 bool isFirstField = true; 692 void visitField(ClassElement enclosingClass, Element member) {
657 void addField(ClassElement enclosingClass, Element member) {
658 assert(!member.isNative()); 693 assert(!member.isNative());
659 assert(invariant(classElement, member.isDeclaration)); 694 assert(invariant(classElement, member.isDeclaration));
660 695
661 LibraryElement library = member.getLibrary(); 696 LibraryElement library = member.getLibrary();
662 SourceString name = member.name; 697 SourceString name = member.name;
663 bool isPrivate = name.isPrivate(); 698 bool isPrivate = name.isPrivate();
664 // See if we can dynamically create getters and setters. 699 // See if we can dynamically create getters and setters.
665 // We can only generate getters and setters for [classElement] since 700 // We can only generate getters and setters for [classElement] since
666 // the fields of super classes could be overwritten with getters or 701 // the fields of super classes could be overwritten with getters or
667 // setters. 702 // setters.
668 bool needsDynamicGetter = false; 703 bool needsGetter = false;
669 bool needsDynamicSetter = false; 704 bool needsSetter = false;
670 // We need to name shadowed fields differently, so they don't clash with 705 // We need to name shadowed fields differently, so they don't clash with
671 // the non-shadowed field. 706 // the non-shadowed field.
672 bool isShadowed = false; 707 bool isShadowed = false;
673 if (identical(enclosingClass, classElement)) { 708 if (identical(enclosingClass, classElement)) {
674 needsDynamicGetter = instanceFieldNeedsGetter(member); 709 needsGetter = instanceFieldNeedsGetter(member);
675 needsDynamicSetter = instanceFieldNeedsSetter(member); 710 needsSetter = instanceFieldNeedsSetter(member);
676 } else { 711 } else {
677 isShadowed = classElement.isShadowedByField(member); 712 isShadowed = classElement.isShadowedByField(member);
678 } 713 }
679 714
680 if ((isInstantiated && !enclosingClass.isNative()) 715 if ((isInstantiated && !enclosingClass.isNative())
681 || needsDynamicGetter 716 || needsGetter
682 || needsDynamicSetter) { 717 || needsSetter) {
683 if (isFirstField) {
684 isFirstField = false;
685 } else {
686 buffer.add(", ");
687 }
688 String fieldName = isShadowed 718 String fieldName = isShadowed
689 ? namer.shadowedFieldName(member) 719 ? namer.shadowedFieldName(member)
690 : namer.getName(member); 720 : namer.getName(member);
691 if (needsDynamicSetter && compiler.enableTypeAssertions) { 721 bool needsCheckedSetter = false;
692 String setter = generateCheckedSetter(member, fieldName); 722 if (needsSetter && compiler.enableTypeAssertions
693 if (setter != null) { 723 && canGenerateCheckedSetter(member)) {
694 needsDynamicSetter = false; 724 needsCheckedSetter = true;
695 checkedSetters.add(setter); 725 needsSetter = false;
696 }
697 } 726 }
698 // Getters and setters with suffixes will be generated dynamically. 727 // Getters and setters with suffixes will be generated dynamically.
699 buffer.add('"$fieldName'); 728 addField(member,
700 if (needsDynamicGetter || needsDynamicSetter) { 729 fieldName,
701 if (needsDynamicGetter && needsDynamicSetter) { 730 needsGetter,
702 buffer.add(GETTER_SETTER_SUFFIX); 731 needsSetter,
703 } else if (needsDynamicGetter) { 732 needsCheckedSetter);
704 buffer.add(GETTER_SUFFIX);
705 } else {
706 buffer.add(SETTER_SUFFIX);
707 }
708 }
709 buffer.add('"');
710 } 733 }
711 } 734 }
712 735
713 // If a class is not instantiated then we add the field just so we can 736 // If a class is not instantiated then we add the field just so we can
714 // generate the field getter/setter dynamically. Since this is only 737 // generate the field getter/setter dynamically. Since this is only
715 // allowed on fields that are in [classElement] we don't need to visit 738 // allowed on fields that are in [classElement] we don't need to visit
716 // superclasses for non-instantiated classes. 739 // superclasses for non-instantiated classes.
717 classElement.implementation.forEachInstanceField( 740 classElement.implementation.forEachInstanceField(
718 addField, 741 visitField,
719 includeBackendMembers: true, 742 includeBackendMembers: true,
720 includeSuperMembers: isInstantiated && !classElement.isNative()); 743 includeSuperMembers: isInstantiated && !classElement.isNative());
721 return checkedSetters; 744 }
745
746 void generateGetter(Element member, String fieldName, CodeBuffer buffer) {
747 String getterName = namer.getterName(member.getLibrary(), member.name);
748 buffer.add("$getterName: function() { return this.$fieldName; }");
749 }
750
751 void generateSetter(Element member, String fieldName, CodeBuffer buffer) {
752 String setterName = namer.setterName(member.getLibrary(), member.name);
753 buffer.add("$setterName: function(v) { this.$fieldName = v; }");
754 }
755
756 bool canGenerateCheckedSetter(Element member) {
757 DartType type = member.computeType(compiler);
758 if (type.element.isTypeVariable()
759 || type.element == compiler.dynamicClass
760 || type.element == compiler.objectClass) {
761 // TODO(ngeoffray): Support type checks on type parameters.
762 return false;
763 }
764 return true;
765 }
766
767 void generateCheckedSetter(Element member,
floitsch 2012/10/17 21:15:01 generateCheckedSetter lost the boolean check which
768 String fieldName,
769 CodeBuffer buffer) {
770 assert(canGenerateCheckedSetter(member));
771 DartType type = member.computeType(compiler);
772 SourceString helper = compiler.backend.getCheckedModeHelper(type);
773 FunctionElement helperElement = compiler.findHelper(helper);
774 String helperName = namer.isolateAccess(helperElement);
775 String additionalArgument = '';
776 if (helperElement.computeSignature(compiler).parameterCount != 1) {
777 additionalArgument = ", '${namer.operatorIs(type.element)}'";
778 }
779 String setterName = namer.setterName(member.getLibrary(), member.name);
780 buffer.add("$setterName: function(v) { "
781 "this.$fieldName = $helperName(v$additionalArgument); }");
782 }
783
784 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) {
785 /* Do nothing. */
786 }
787
788 void emitClassFields(ClassElement classElement, CodeBuffer buffer) {
789 buffer.add('"": [');
790 bool isFirstField = true;
791 visitClassFields(classElement, (Element member,
792 String name,
793 bool needsGetter,
794 bool needsSetter,
795 bool needsCheckedSetter) {
796 if (isFirstField) {
797 isFirstField = false;
798 } else {
799 buffer.add(", ");
800 }
801 buffer.add('"$name');
802 if (needsGetter && needsSetter) {
803 buffer.add(GETTER_SETTER_SUFFIX);
804 } else if (needsGetter) {
805 buffer.add(GETTER_SUFFIX);
806 } else if (needsSetter) {
807 buffer.add(SETTER_SUFFIX);
808 }
809 buffer.add('"');
810 });
811 buffer.add(']');
812 }
813
814 /** Each getter/setter must be prefixed with a ",\n ". */
815 void emitClassGettersSetters(ClassElement classElement, CodeBuffer buffer,
816 {bool omitLeadingComma: false}) {
817 visitClassFields(classElement, (Element member,
818 String name,
819 bool needsGetter,
820 bool needsSetter,
821 bool needsCheckedSetter) {
822 if (needsCheckedSetter) {
823 assert(!needsSetter);
824 if (!omitLeadingComma) {
825 buffer.add(",\n ");
826 } else {
827 omitLeadingComma = false;
828 }
829 generateCheckedSetter(member, name, buffer);
830 }
831 });
722 } 832 }
723 833
724 /** 834 /**
725 * Documentation wanted -- johnniwinther
726 *
727 * Invariant: [classElement] must be a declaration element.
728 */
729 void emitInstanceMembers(ClassElement classElement,
floitsch 2012/10/17 21:15:01 has been moved to above. No changes in this functi
730 CodeBuffer buffer,
731 bool needsLeadingComma) {
732 assert(invariant(classElement, classElement.isDeclaration));
733 bool needsComma = needsLeadingComma;
734 void defineInstanceMember(String name, CodeBuffer memberBuffer) {
735 if (needsComma) buffer.add(',');
736 needsComma = true;
737 buffer.add('\n');
738 buffer.add(' $name: ');
739 buffer.add(memberBuffer);
740 }
741
742 classElement.implementation.forEachMember(
743 (ClassElement enclosing, Element member) {
744 assert(invariant(classElement, member.isDeclaration));
745 if (member.isInstanceMember()) {
746 addInstanceMember(member, defineInstanceMember);
747 }
748 },
749 includeBackendMembers: true);
750
751 generateIsTestsOn(classElement, (ClassElement other) {
752 String code;
753 if (other.isObject(compiler)) return;
754 if (nativeEmitter.requiresNativeIsCheck(other)) {
755 code = 'function() { return true; }';
756 } else {
757 code = 'true';
758 }
759 CodeBuffer typeTestBuffer = new CodeBuffer();
760 typeTestBuffer.add(code);
761 defineInstanceMember(namer.operatorIs(other), typeTestBuffer);
762 });
763
764 if (identical(classElement, compiler.objectClass)
765 && compiler.enabledNoSuchMethod) {
766 // Emit the noSuchMethod handlers on the Object prototype now,
767 // so that the code in the dynamicFunction helper can find
768 // them. Note that this helper is invoked before analyzing the
769 // full JS script.
770 if (!nativeEmitter.handleNoSuchMethod) {
771 emitNoSuchMethodHandlers(defineInstanceMember);
772 }
773 }
774 }
775
776 /**
777 * Documentation wanted -- johnniwinther 835 * Documentation wanted -- johnniwinther
778 * 836 *
779 * Invariant: [classElement] must be a declaration element. 837 * Invariant: [classElement] must be a declaration element.
780 */ 838 */
781 void generateClass(ClassElement classElement, CodeBuffer buffer) { 839 void generateClass(ClassElement classElement, CodeBuffer buffer) {
782 assert(invariant(classElement, classElement.isDeclaration)); 840 assert(invariant(classElement, classElement.isDeclaration));
783 if (classElement.isNative()) { 841 if (classElement.isNative()) {
784 nativeEmitter.generateNativeClass(classElement); 842 nativeEmitter.generateNativeClass(classElement);
785 return; 843 return;
786 } else { 844 } else {
787 // TODO(ngeoffray): Instead of switching between buffer, we 845 // TODO(ngeoffray): Instead of switching between buffer, we
788 // should create code sections, and decide where to emit them at 846 // should create code sections, and decide where to emit them at
789 // the end. 847 // the end.
790 buffer = mainBuffer; 848 buffer = mainBuffer;
791 } 849 }
792 850
793 needsDefineClass = true; 851 needsDefineClass = true;
794 String className = namer.getName(classElement); 852 String className = namer.getName(classElement);
795 ClassElement superclass = classElement.superclass; 853 ClassElement superclass = classElement.superclass;
796 String superName = ""; 854 String superName = "";
797 if (superclass != null) { 855 if (superclass != null) {
798 superName = namer.getName(superclass); 856 superName = namer.getName(superclass);
799 } 857 }
800 String constructorName = namer.safeName(classElement.name.slowToString());
801 858
802 buffer.add('$classesCollector.$className = {"":\n'); 859 buffer.add('$classesCollector.$className = {');
803 buffer.add(' ['); 860 emitClassConstructor(classElement, buffer);
804 List<String> checkedSetters = emitClassFields(classElement, buffer); 861 emitClassFields(classElement, buffer);
805 buffer.add('],\n');
806 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. 862 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'.
807 // That does currently not work because the native classes have a different 863 // That does currently not work because the native classes have a different
808 // syntax. 864 // syntax.
809 buffer.add(' "super": "$superName"'); 865 buffer.add(',\n "super": "$superName"');
810 if (!checkedSetters.isEmpty()) { 866 emitClassGettersSetters(classElement, buffer);
811 buffer.add(',\n');
812 buffer.add('${Strings.join(checkedSetters, ",\n")}');
813 }
814 emitInstanceMembers(classElement, buffer, true); 867 emitInstanceMembers(classElement, buffer, true);
815 buffer.add('\n};\n\n'); 868 buffer.add('\n};\n\n');
816 } 869 }
817 870
818 /** 871 /**
819 * Generate "is tests" for [cls]: itself, and the "is tests" for the 872 * Generate "is tests" for [cls]: itself, and the "is tests" for the
820 * classes it implements. We don't need to add the "is tests" of the 873 * classes it implements. We don't need to add the "is tests" of the
821 * super class because they will be inherited at runtime. 874 * super class because they will be inherited at runtime.
822 */ 875 */
823 void generateIsTestsOn(ClassElement cls, 876 void generateIsTestsOn(ClassElement cls,
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 addParameterStubs(callElement, (String name, CodeBuffer value) { 1021 addParameterStubs(callElement, (String name, CodeBuffer value) {
969 buffer.add('$fieldAccess.$name = $value;\n'); 1022 buffer.add('$fieldAccess.$name = $value;\n');
970 }); 1023 });
971 // If a static function is used as a closure we need to add its name 1024 // If a static function is used as a closure we need to add its name
972 // in case it is used in spawnFunction. 1025 // in case it is used in spawnFunction.
973 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; 1026 String fieldName = namer.STATIC_CLOSURE_NAME_NAME;
974 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); 1027 buffer.add('$fieldAccess.$fieldName = "$staticName";\n');
975 } 1028 }
976 } 1029 }
977 1030
1031 void emitBoundClosureClassHeader(String mangledName,
1032 String superName,
1033 CodeBuffer buffer) {
1034 buffer.add("""
1035 $classesCollector.$mangledName = {'':
1036 ['self', 'target'],
1037 'super': '$superName',
1038 """);
1039 }
1040
978 /** 1041 /**
979 * Documentation wanted -- johnniwinther 1042 * Documentation wanted -- johnniwinther
980 * 1043 *
981 * Invariant: [member] must be a declaration element. 1044 * Invariant: [member] must be a declaration element.
982 */ 1045 */
983 void emitDynamicFunctionGetter(FunctionElement member, 1046 void emitDynamicFunctionGetter(FunctionElement member,
984 DefineMemberFunction defineInstanceMember) { 1047 DefineMemberFunction defineInstanceMember) {
985 assert(invariant(member, member.isDeclaration)); 1048 assert(invariant(member, member.isDeclaration));
986 // For every method that has the same name as a property-get we create a 1049 // For every method that has the same name as a property-get we create a
987 // getter that returns a bound closure. Say we have a class 'A' with method 1050 // getter that returns a bound closure. Say we have a class 'A' with method
(...skipping 26 matching lines...) Expand all
1014 // Create a new closure class. 1077 // Create a new closure class.
1015 SourceString name = const SourceString("BoundClosure"); 1078 SourceString name = const SourceString("BoundClosure");
1016 ClassElement closureClassElement = new ClosureClassElement( 1079 ClassElement closureClassElement = new ClosureClassElement(
1017 name, compiler, member, member.getCompilationUnit()); 1080 name, compiler, member, member.getCompilationUnit());
1018 String mangledName = namer.getName(closureClassElement); 1081 String mangledName = namer.getName(closureClassElement);
1019 String superName = namer.getName(closureClassElement.superclass); 1082 String superName = namer.getName(closureClassElement.superclass);
1020 needsClosureClass = true; 1083 needsClosureClass = true;
1021 1084
1022 // Define the constructor with a name so that Object.toString can 1085 // Define the constructor with a name so that Object.toString can
1023 // find the class name of the closure class. 1086 // find the class name of the closure class.
1024 boundClosureBuffer.add(""" 1087 emitBoundClosureClassHeader(mangledName, superName, boundClosureBuffer);
1025 $classesCollector.$mangledName = {'':
1026 ['self', 'target'],
1027 'super': '$superName',
1028 """);
1029 // Now add the methods on the closure class. The instance method does not 1088 // Now add the methods on the closure class. The instance method does not
1030 // have the correct name. Since [addParameterStubs] use the name to create 1089 // have the correct name. Since [addParameterStubs] use the name to create
1031 // its stubs we simply create a fake element with the correct name. 1090 // its stubs we simply create a fake element with the correct name.
1032 // Note: the callElement will not have any enclosingElement. 1091 // Note: the callElement will not have any enclosingElement.
1033 FunctionElement callElement = 1092 FunctionElement callElement =
1034 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); 1093 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
1035 1094
1036 String invocationName = namer.instanceMethodName(callElement); 1095 String invocationName = namer.instanceMethodName(callElement);
1037 List<String> arguments = new List<String>(parameterCount); 1096 List<String> arguments = new List<String>(parameterCount);
1038 for (int i = 0; i < parameterCount; i++) { 1097 for (int i = 0; i < parameterCount; i++) {
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 const String HOOKS_API_USAGE = """ 1573 const String HOOKS_API_USAGE = """
1515 // Generated by dart2js, the Dart to JavaScript compiler. 1574 // Generated by dart2js, the Dart to JavaScript compiler.
1516 // The code supports the following hooks: 1575 // The code supports the following hooks:
1517 // dartPrint(message) - if this function is defined it is called 1576 // dartPrint(message) - if this function is defined it is called
1518 // instead of the Dart [print] method. 1577 // instead of the Dart [print] method.
1519 // dartMainRunner(main) - if this function is defined, the Dart [main] 1578 // dartMainRunner(main) - if this function is defined, the Dart [main]
1520 // method will not be invoked directly. 1579 // method will not be invoked directly.
1521 // Instead, a closure that will invoke [main] is 1580 // Instead, a closure that will invoke [main] is
1522 // passed to [dartMainRunner]. 1581 // passed to [dartMainRunner].
1523 """; 1582 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698