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

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: Minor comment changes and rebase. 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 28 matching lines...) Expand all
39 CodeBuffer boundClosureBuffer; 39 CodeBuffer boundClosureBuffer;
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 final bool useContentSecurityPolicy;
49 50
50 CodeEmitterTask(Compiler compiler, Namer namer, 51 CodeEmitterTask(Compiler compiler, Namer namer,
51 [bool generateSourceMap = false]) 52 this.generateSourceMap,
53 this.useContentSecurityPolicy)
52 : boundClosureBuffer = new CodeBuffer(), 54 : boundClosureBuffer = new CodeBuffer(),
53 mainBuffer = new CodeBuffer(), 55 mainBuffer = new CodeBuffer(),
54 this.namer = namer, 56 this.namer = namer,
55 boundClosureCache = new Map<int, String>(), 57 boundClosureCache = new Map<int, String>(),
56 generateSourceMap = generateSourceMap,
57 constantEmitter = new ConstantEmitter(compiler, namer), 58 constantEmitter = new ConstantEmitter(compiler, namer),
58 super(compiler) { 59 super(compiler) {
59 nativeEmitter = new NativeEmitter(this); 60 nativeEmitter = new NativeEmitter(this);
60 } 61 }
61 62
62 void computeRequiredTypeChecks() { 63 void computeRequiredTypeChecks() {
63 assert(checkedClasses == null); 64 assert(checkedClasses == null);
64 checkedClasses = new Set<ClassElement>(); 65 checkedClasses = new Set<ClassElement>();
65 compiler.codegenWorld.isChecks.forEach((DartType t) { 66 compiler.codegenWorld.isChecks.forEach((DartType t) {
66 if (t is InterfaceType) checkedClasses.add(t.element); 67 if (t is InterfaceType) checkedClasses.add(t.element);
(...skipping 24 matching lines...) Expand all
91 String get supportsProtoName 92 String get supportsProtoName
92 => 'supportsProto'; 93 => 'supportsProto';
93 String get lazyInitializerName 94 String get lazyInitializerName
94 => '${namer.ISOLATE}.\$lazy'; 95 => '${namer.ISOLATE}.\$lazy';
95 96
96 final String GETTER_SUFFIX = "?"; 97 final String GETTER_SUFFIX = "?";
97 final String SETTER_SUFFIX = "!"; 98 final String SETTER_SUFFIX = "!";
98 final String GETTER_SETTER_SUFFIX = "="; 99 final String GETTER_SETTER_SUFFIX = "=";
99 100
100 String get generateGetterSetterFunction { 101 String get generateGetterSetterFunction {
102 if (useContentSecurityPolicy) {
103 compiler.internalError("Dynamic Getters/Setters are unused in CSP");
kasperl 2012/10/17 09:37:11 Getters/Setters -> getters/setters
floitsch 2012/10/17 21:15:01 Refactored.
104 }
105
101 return """ 106 return """
102 function(field, prototype) { 107 function(field, prototype) {
103 var len = field.length; 108 var len = field.length;
104 var lastChar = field[len - 1]; 109 var lastChar = field[len - 1];
105 var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTE R_SUFFIX'; 110 var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTE R_SUFFIX';
106 var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTE R_SUFFIX'; 111 var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTE R_SUFFIX';
107 if (needsGetter || needsSetter) field = field.substring(0, len - 1); 112 if (needsGetter || needsSetter) field = field.substring(0, len - 1);
108 if (needsGetter) { 113 if (needsGetter) {
109 var getterString = "return this." + field + ";"; 114 var getterString = "return this." + field + ";";
110 """ 115 """
111 /* The supportsProtoCheck below depends on the getter/setter convention. 116 /* The supportsProtoCheck below depends on the getter/setter convention.
112 When changing here, update the protoCheck too. */ 117 When changing here, update the protoCheck too. */
113 """ 118 """
114 prototype["get\$" + field] = new Function(getterString); 119 prototype["get\$" + field] = new Function(getterString);
115 } 120 }
116 if (needsSetter) { 121 if (needsSetter) {
117 var setterString = "this." + field + " = v;"; 122 var setterString = "this." + field + " = v;";
118 prototype["set\$" + field] = new Function("v", setterString); 123 prototype["set\$" + field] = new Function("v", setterString);
119 } 124 }
120 return field; 125 return field;
121 }"""; 126 }""";
122 } 127 }
123 128
124 String get defineClassFunction { 129 String get defineClassFunction {
130 if (useContentSecurityPolicy) {
kasperl 2012/10/17 09:37:11 It feels a little bit like subclassing would help
floitsch 2012/10/17 21:15:01 Done.
131 return """
132 function(cls, constructor, prototype) {
133 constructor.prototype = prototype;
134 return constructor;
135 }""";
136 }
125 // First the class name, then the super class name, followed by the fields 137 // First the class name, then the super class name, followed by the fields
126 // (in an array) and the members (inside an Object literal). 138 // (in an array) and the members (inside an Object literal).
127 // The caller can also pass in the constructor as a function if needed. 139 // The caller can also pass in the constructor as a function if needed.
128 // 140 //
129 // Example: 141 // Example:
130 // defineClass("A", "B", ["x", "y"], { 142 // defineClass("A", "B", ["x", "y"], {
131 // foo$1: function(y) { 143 // foo$1: function(y) {
132 // print(this.x + y); 144 // print(this.x + y);
133 // }, 145 // },
134 // bar$2: function(t, v) { 146 // bar$2: function(t, v) {
(...skipping 20 matching lines...) Expand all
155 str += "return " + cls + ";"; 167 str += "return " + cls + ";";
156 constructor = new Function(str)(); 168 constructor = new Function(str)();
157 } 169 }
158 constructor.prototype = prototype; 170 constructor.prototype = prototype;
159 return constructor; 171 return constructor;
160 }"""; 172 }""";
161 } 173 }
162 174
163 /** Needs defineClass to be defined. */ 175 /** Needs defineClass to be defined. */
164 String get protoSupportCheck { 176 String get protoSupportCheck {
177 if (useContentSecurityPolicy) {
178 // We don't modify the prototypes in CSP mode. Therefore we can have an
179 // easier prototype-check.
180 return 'var $supportsProtoName = !!{}.__proto__;';
181 }
165 // On Firefox and Webkit browsers we can manipulate the __proto__ 182 // On Firefox and Webkit browsers we can manipulate the __proto__
166 // directly. Opera claims to have __proto__ support, but it is buggy. 183 // directly. Opera claims to have __proto__ support, but it is buggy.
167 // So we have to do more checks. 184 // So we have to do more checks.
185 // Opera bug was filed as DSK-370158, and fixed as CORE-47615
186 // (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 187 // If the browser does not support __proto__ we need to instantiate an
169 // object with the correct (internal) prototype set up correctly, and then 188 // object with the correct (internal) prototype set up correctly, and then
170 // copy the members. 189 // copy the members.
171 190
172 return ''' 191 return '''
173 var $supportsProtoName = false; 192 var $supportsProtoName = false;
174 var tmp = $defineClassName('c', ['f?'], {}).prototype; 193 var tmp = $defineClassName('c', ['f?'], {}).prototype;
175 if (tmp.__proto__) { 194 if (tmp.__proto__) {
176 tmp.__proto__ = {}; 195 tmp.__proto__ = {};
177 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true; 196 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 newPrototype[member] = prototype[member]; 254 newPrototype[member] = prototype[member];
236 } 255 }
237 } 256 }
238 } 257 }
239 } 258 }
240 for (var cls in pendingClasses) finishClass(cls); 259 for (var cls in pendingClasses) finishClass(cls);
241 }'''; 260 }''';
242 } 261 }
243 262
244 String get finishIsolateConstructorFunction { 263 String get finishIsolateConstructorFunction {
264 if (useContentSecurityPolicy) {
265 // We replace the old Isolate function with a new one that initializes
266 // all its field with the initial (and often final) value of all globals.
267 //
268 // We also copy over old values like the prototype, and the
269 // isolateProperties themselves.
270 return """
271 function(oldIsolate) {
272 var isolateProperties = oldIsolate.${namer.ISOLATE_PROPERTIES};
kasperl 2012/10/17 09:37:11 Isn't there a way to construct the isolate object
floitsch 2012/10/17 21:15:01 There is, but since it's not necessary.
273 function Isolate() {
274 for (var staticName in isolateProperties) {
275 if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
276 this[staticName] = isolateProperties[staticName];
277 }
278 }
279 // Use the newly created object as prototype. In Chrome this creates a
floitsch 2012/10/16 18:15:36 Thanks to Erik Corry for this tip. Without these l
280 // hidden class for the object and makes sure it is fast to access.
281 function t(){}
kasperl 2012/10/17 09:37:11 Maybe give t a better name? Space after ).
floitsch 2012/10/17 21:15:01 Done.
282 t.prototype = this;
283 new t();
284 }
285 Isolate.prototype = oldIsolate.prototype;
286 Isolate.prototype.constructor = Isolate;
287 Isolate.${namer.ISOLATE_PROPERTIES} = isolateProperties;
288 return Isolate;
289 }""";
290 }
291
245 String isolate = namer.ISOLATE; 292 String isolate = namer.ISOLATE;
246 // We replace the old Isolate function with a new one that initializes 293 // We replace the old Isolate function with a new one that initializes
247 // all its field with the initial (and often final) value of all globals. 294 // all its field with the initial (and often final) value of all globals.
248 // This has two advantages: 295 // This has two advantages:
249 // 1. the properties are in the object itself (thus avoiding to go through 296 // 1. the properties are in the object itself (thus avoiding to go through
250 // the prototype when looking up globals. 297 // the prototype when looking up globals.
251 // 2. a new isolate goes through a (usually well optimized) constructor 298 // 2. a new isolate goes through a (usually well optimized) constructor
252 // function of the form: "function() { this.x = ...; this.y = ...; }". 299 // function of the form: "function() { this.x = ...; this.y = ...; }".
253 // 300 //
254 // Example: If [isolateProperties] is an object containing: x = 3 and 301 // Example: If [isolateProperties] is an object containing: x = 3 and
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 if (!parameters.optionalParameters.isEmpty()) { 660 if (!parameters.optionalParameters.isEmpty()) {
614 addParameterStubs(member, defineInstanceMember); 661 addParameterStubs(member, defineInstanceMember);
615 } 662 }
616 } else if (!member.isField()) { 663 } else if (!member.isField()) {
617 compiler.internalError('unexpected kind: "${member.kind}"', 664 compiler.internalError('unexpected kind: "${member.kind}"',
618 element: member); 665 element: member);
619 } 666 }
620 emitExtraAccessors(member, defineInstanceMember); 667 emitExtraAccessors(member, defineInstanceMember);
621 } 668 }
622 669
670 String generateGetter(Element member, String fieldName) {
671 String getterName = namer.getterName(member.getLibrary(), member.name);
672 return "$getterName: function() { return this.$fieldName; }";
673 }
674
675 String generateSetter(Element member, String fieldName) {
676 String setterName = namer.setterName(member.getLibrary(), member.name);
677 return "$setterName: function(v) { this.$fieldName = v; }";
678 }
679
623 String generateCheckedSetter(Element member, String fieldName) { 680 String generateCheckedSetter(Element member, String fieldName) {
624 DartType type = member.computeType(compiler); 681 DartType type = member.computeType(compiler);
625 if (type.element.isTypeVariable() 682 if (type.element.isTypeVariable()
626 || type.element == compiler.dynamicClass 683 || type.element == compiler.dynamicClass
627 || type.element == compiler.objectClass) { 684 || type.element == compiler.objectClass) {
628 // TODO(ngeoffray): Support type checks on type parameters. 685 // TODO(ngeoffray): Support type checks on type parameters.
629 return null; 686 return null;
630 } else { 687 } else {
631 SourceString helper = compiler.backend.getCheckedModeHelper(type); 688 SourceString helper = compiler.backend.getCheckedModeHelper(type);
632 FunctionElement helperElement = compiler.findHelper(helper); 689 FunctionElement helperElement = compiler.findHelper(helper);
633 String helperName = namer.isolateAccess(helperElement); 690 String helperName = namer.isolateAccess(helperElement);
634 String additionalArgument = ''; 691 String additionalArgument = '';
635 if (helperElement.computeSignature(compiler).parameterCount != 1) { 692 if (helperElement.computeSignature(compiler).parameterCount != 1) {
636 additionalArgument = ", '${namer.operatorIs(type.element)}'"; 693 additionalArgument = ", '${namer.operatorIs(type.element)}'";
637 } 694 }
638 return " set\$$fieldName: function(v) { " 695 String setterName = namer.setterName(member.getLibrary(), member.name);
696 return " $setterName: function(v) { "
639 "this.$fieldName = $helperName(v$additionalArgument); }"; 697 "this.$fieldName = $helperName(v$additionalArgument); }";
640 } 698 }
641 } 699 }
642 700
643 /** 701 /**
644 * Documentation wanted -- johnniwinther 702 * Documentation wanted -- johnniwinther
645 * 703 *
646 * Invariant: [classElement] must be a declaration element. 704 * Invariant: [classElement] must be a declaration element.
647 */ 705 */
648 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) { 706 void visitClassFields(ClassElement classElement,
707 void addField(Element member,
708 String name,
709 bool needsGetter,
710 bool needsSetter,
711 bool needsCheckedSetter)) {
649 assert(invariant(classElement, classElement.isDeclaration)); 712 assert(invariant(classElement, classElement.isDeclaration));
650 // If the class is never instantiated we still need to set it up for 713 // If the class is never instantiated we still need to set it up for
651 // inheritance purposes, but we can simplify its JavaScript constructor. 714 // inheritance purposes, but we can simplify its JavaScript constructor.
652 bool isInstantiated = 715 bool isInstantiated =
653 compiler.codegenWorld.instantiatedClasses.contains(classElement); 716 compiler.codegenWorld.instantiatedClasses.contains(classElement);
654 List<String> checkedSetters = <String>[];
655 717
656 bool isFirstField = true; 718 void visitField(ClassElement enclosingClass, Element member) {
657 void addField(ClassElement enclosingClass, Element member) {
658 assert(!member.isNative()); 719 assert(!member.isNative());
659 assert(invariant(classElement, member.isDeclaration)); 720 assert(invariant(classElement, member.isDeclaration));
660 721
661 LibraryElement library = member.getLibrary(); 722 LibraryElement library = member.getLibrary();
662 SourceString name = member.name; 723 SourceString name = member.name;
663 bool isPrivate = name.isPrivate(); 724 bool isPrivate = name.isPrivate();
664 // See if we can dynamically create getters and setters. 725 // See if we can dynamically create getters and setters.
665 // We can only generate getters and setters for [classElement] since 726 // We can only generate getters and setters for [classElement] since
666 // the fields of super classes could be overwritten with getters or 727 // the fields of super classes could be overwritten with getters or
667 // setters. 728 // setters.
668 bool needsDynamicGetter = false; 729 bool needsGetter = false;
669 bool needsDynamicSetter = false; 730 bool needsSetter = false;
670 // We need to name shadowed fields differently, so they don't clash with 731 // We need to name shadowed fields differently, so they don't clash with
671 // the non-shadowed field. 732 // the non-shadowed field.
672 bool isShadowed = false; 733 bool isShadowed = false;
673 if (enclosingClass === classElement) { 734 if (enclosingClass === classElement) {
674 needsDynamicGetter = instanceFieldNeedsGetter(member); 735 needsGetter = instanceFieldNeedsGetter(member);
675 needsDynamicSetter = instanceFieldNeedsSetter(member); 736 needsSetter = instanceFieldNeedsSetter(member);
676 } else { 737 } else {
677 isShadowed = classElement.isShadowedByField(member); 738 isShadowed = classElement.isShadowedByField(member);
678 } 739 }
679 740
680 if ((isInstantiated && !enclosingClass.isNative()) 741 if ((isInstantiated && !enclosingClass.isNative())
681 || needsDynamicGetter 742 || needsGetter
682 || needsDynamicSetter) { 743 || needsSetter) {
683 if (isFirstField) {
684 isFirstField = false;
685 } else {
686 buffer.add(", ");
687 }
688 String fieldName = isShadowed 744 String fieldName = isShadowed
689 ? namer.shadowedFieldName(member) 745 ? namer.shadowedFieldName(member)
690 : namer.getName(member); 746 : namer.getName(member);
691 if (needsDynamicSetter && compiler.enableTypeAssertions) { 747 bool needsCheckedSetter = false;
748 if (needsSetter && compiler.enableTypeAssertions) {
692 String setter = generateCheckedSetter(member, fieldName); 749 String setter = generateCheckedSetter(member, fieldName);
693 if (setter != null) { 750 if (setter != null) {
694 needsDynamicSetter = false; 751 needsSetter = false;
695 checkedSetters.add(setter); 752 needsCheckedSetter = true;
696 } 753 }
697 } 754 }
698 // Getters and setters with suffixes will be generated dynamically. 755 // Getters and setters with suffixes will be generated dynamically.
699 buffer.add('"$fieldName'); 756 addField(member,
700 if (needsDynamicGetter || needsDynamicSetter) { 757 fieldName,
701 if (needsDynamicGetter && needsDynamicSetter) { 758 needsGetter,
702 buffer.add(GETTER_SETTER_SUFFIX); 759 needsSetter,
703 } else if (needsDynamicGetter) { 760 needsCheckedSetter);
704 buffer.add(GETTER_SUFFIX);
705 } else {
706 buffer.add(SETTER_SUFFIX);
707 }
708 }
709 buffer.add('"');
710 } 761 }
711 } 762 }
712 763
713 // If a class is not instantiated then we add the field just so we can 764 // 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 765 // generate the field getter/setter dynamically. Since this is only
715 // allowed on fields that are in [classElement] we don't need to visit 766 // allowed on fields that are in [classElement] we don't need to visit
716 // superclasses for non-instantiated classes. 767 // superclasses for non-instantiated classes.
717 classElement.implementation.forEachInstanceField( 768 classElement.implementation.forEachInstanceField(
718 addField, 769 visitField,
719 includeBackendMembers: true, 770 includeBackendMembers: true,
720 includeSuperMembers: isInstantiated && !classElement.isNative()); 771 includeSuperMembers: isInstantiated && !classElement.isNative());
772 }
773
774 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) {
775 buffer.add(' [');
776 bool isFirstField = true;
777 List<String> checkedSetters = <String>[];
778 visitClassFields(classElement, (Element member,
779 String name,
780 bool needsGetter,
781 bool needsSetter,
782 bool needsCheckedSetter) {
783 if (isFirstField) {
784 isFirstField = false;
785 } else {
786 buffer.add(", ");
787 }
788 if (needsCheckedSetter) {
789 assert(!needsSetter);
790 String setter = generateCheckedSetter(member, name);
791 if (setter !== null) {
792 needsSetter = null;
793 } else {
794 checkedSetters.add(setter);
795 }
796 }
797 buffer.add('"$name');
798 if (needsGetter && needsSetter) {
799 buffer.add(GETTER_SETTER_SUFFIX);
800 } else if (needsGetter) {
801 buffer.add(GETTER_SUFFIX);
802 } else if (needsSetter) {
803 buffer.add(SETTER_SUFFIX);
804 }
805 buffer.add('"');
806 });
807 buffer.add(']');
721 return checkedSetters; 808 return checkedSetters;
722 } 809 }
723 810
724 /** 811 /**
812 * This is the equivalent of [emitClassFields] when running under the
813 * Content-Security Policy.
814 */
815 List<String> emitClassConstructorGettersSetters(ClassElement classElement,
816 CodeBuffer buffer) {
817 // Say we have a class A with fields b, c and d, where c needs a getter and
818 // d needs both a getter and a setter. Then we produce:
819 // - a constructor (directly into the given [buffer]):
820 // function A(b, c, d) { this.b = b, this.c = c, this.d = d; }
821 // - getters and setters (stored in the [explicitGettersSetters] list):
822 // get$c : function() { return this.c; }
823 // get$d : function() { return this.d; }
824 // set$d : function(x) { this.d = x; }
825 List<String> explicitGettersSetters = <String>[];
826 List<String> fields = <String>[];
827 visitClassFields(classElement, (Element member,
828 String name,
829 bool needsGetter,
830 bool needsSetter,
831 bool needsCheckedSetter) {
832 fields.add(name);
833 if (needsCheckedSetter) {
834 assert(!needsSetter);
835 String setter = generateCheckedSetter(member, name);
836 if (setter !== null) {
837 needsSetter = null;
838 } else {
839 explicitGettersSetters.add(setter);
840 }
841 }
842 if (needsGetter) {
843 explicitGettersSetters.add(generateGetter(member, name));
844 }
845 if (needsSetter) {
846 explicitGettersSetters.add(generateSetter(member, name));
847 }
848 });
849
850 String constructorName = namer.safeName(classElement.name.slowToString());
851 // Generate the constructor.
852 buffer.add("function $constructorName(");
853 buffer.add(Strings.join(fields, ", "));
854 buffer.add(") {");
855 for (String field in fields) {
856 buffer.add(" this.$field = $field;");
857 }
858 buffer.add(' }');
859 return explicitGettersSetters;
860 }
861
862 /**
725 * Documentation wanted -- johnniwinther 863 * Documentation wanted -- johnniwinther
726 * 864 *
727 * Invariant: [classElement] must be a declaration element. 865 * Invariant: [classElement] must be a declaration element.
728 */ 866 */
729 void emitInstanceMembers(ClassElement classElement, 867 void emitInstanceMembers(ClassElement classElement,
730 CodeBuffer buffer, 868 CodeBuffer buffer,
731 bool needsLeadingComma) { 869 bool needsLeadingComma) {
732 assert(invariant(classElement, classElement.isDeclaration)); 870 assert(invariant(classElement, classElement.isDeclaration));
733 bool needsComma = needsLeadingComma; 871 bool needsComma = needsLeadingComma;
734 void defineInstanceMember(String name, CodeBuffer memberBuffer) { 872 void defineInstanceMember(String name, CodeBuffer memberBuffer) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 buffer = mainBuffer; 927 buffer = mainBuffer;
790 } 928 }
791 929
792 needsDefineClass = true; 930 needsDefineClass = true;
793 String className = namer.getName(classElement); 931 String className = namer.getName(classElement);
794 ClassElement superclass = classElement.superclass; 932 ClassElement superclass = classElement.superclass;
795 String superName = ""; 933 String superName = "";
796 if (superclass !== null) { 934 if (superclass !== null) {
797 superName = namer.getName(superclass); 935 superName = namer.getName(superclass);
798 } 936 }
799 String constructorName = namer.safeName(classElement.name.slowToString());
800 937
801 buffer.add('$classesCollector.$className = {"":\n'); 938 buffer.add('$classesCollector.$className = {"":\n');
802 buffer.add(' ['); 939 List<String> explicitGettersSetters;
803 List<String> checkedSetters = emitClassFields(classElement, buffer); 940 if (useContentSecurityPolicy) {
804 buffer.add('],\n'); 941 explicitGettersSetters =
942 emitClassConstructorGettersSetters(classElement, buffer);
943 } else {
944 explicitGettersSetters = emitClassFields(classElement, buffer);
945 }
805 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. 946 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'.
806 // That does currently not work because the native classes have a different 947 // That does currently not work because the native classes have a different
807 // syntax. 948 // syntax.
808 buffer.add(' "super": "$superName"'); 949 buffer.add(',\n "super": "$superName"');
809 if (!checkedSetters.isEmpty()) { 950 if (!explicitGettersSetters.isEmpty()) {
810 buffer.add(',\n'); 951 buffer.add(',\n');
811 buffer.add('${Strings.join(checkedSetters, ",\n")}'); 952 buffer.add('${Strings.join(explicitGettersSetters, ",\n")}');
812 } 953 }
813 emitInstanceMembers(classElement, buffer, true); 954 emitInstanceMembers(classElement, buffer, true);
814 buffer.add('\n};\n\n'); 955 buffer.add('\n};\n\n');
815 } 956 }
816 957
817 /** 958 /**
818 * Generate "is tests" for [cls]: itself, and the "is tests" for the 959 * Generate "is tests" for [cls]: itself, and the "is tests" for the
819 * classes it implements. We don't need to add the "is tests" of the 960 * classes it implements. We don't need to add the "is tests" of the
820 * super class because they will be inherited at runtime. 961 * super class because they will be inherited at runtime.
821 */ 962 */
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 // Create a new closure class. 1154 // Create a new closure class.
1014 SourceString name = const SourceString("BoundClosure"); 1155 SourceString name = const SourceString("BoundClosure");
1015 ClassElement closureClassElement = new ClosureClassElement( 1156 ClassElement closureClassElement = new ClosureClassElement(
1016 name, compiler, member, member.getCompilationUnit()); 1157 name, compiler, member, member.getCompilationUnit());
1017 String mangledName = namer.getName(closureClassElement); 1158 String mangledName = namer.getName(closureClassElement);
1018 String superName = namer.getName(closureClassElement.superclass); 1159 String superName = namer.getName(closureClassElement.superclass);
1019 needsClosureClass = true; 1160 needsClosureClass = true;
1020 1161
1021 // Define the constructor with a name so that Object.toString can 1162 // Define the constructor with a name so that Object.toString can
1022 // find the class name of the closure class. 1163 // find the class name of the closure class.
1023 boundClosureBuffer.add(""" 1164 if (useContentSecurityPolicy) {
1165 boundClosureBuffer.add("""
1166 $classesCollector.$mangledName = {'':
1167 function $mangledName(self, target) { this.self = self; this.target = target; },
1168 'super': '$superName',
1169 """);
1170 } else {
1171 boundClosureBuffer.add("""
1024 $classesCollector.$mangledName = {'': 1172 $classesCollector.$mangledName = {'':
1025 ['self', 'target'], 1173 ['self', 'target'],
1026 'super': '$superName', 1174 'super': '$superName',
1027 """); 1175 """);
1176 }
1028 // Now add the methods on the closure class. The instance method does not 1177 // Now add the methods on the closure class. The instance method does not
1029 // have the correct name. Since [addParameterStubs] use the name to create 1178 // have the correct name. Since [addParameterStubs] use the name to create
1030 // its stubs we simply create a fake element with the correct name. 1179 // its stubs we simply create a fake element with the correct name.
1031 // Note: the callElement will not have any enclosingElement. 1180 // Note: the callElement will not have any enclosingElement.
1032 FunctionElement callElement = 1181 FunctionElement callElement =
1033 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); 1182 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
1034 1183
1035 String invocationName = namer.instanceMethodName(callElement); 1184 String invocationName = namer.instanceMethodName(callElement);
1036 List<String> arguments = new List<String>(parameterCount); 1185 List<String> arguments = new List<String>(parameterCount);
1037 for (int i = 0; i < parameterCount; i++) { 1186 for (int i = 0; i < parameterCount; i++) {
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 const String HOOKS_API_USAGE = """ 1662 const String HOOKS_API_USAGE = """
1514 // Generated by dart2js, the Dart to JavaScript compiler. 1663 // Generated by dart2js, the Dart to JavaScript compiler.
1515 // The code supports the following hooks: 1664 // The code supports the following hooks:
1516 // dartPrint(message) - if this function is defined it is called 1665 // dartPrint(message) - if this function is defined it is called
1517 // instead of the Dart [print] method. 1666 // instead of the Dart [print] method.
1518 // dartMainRunner(main) - if this function is defined, the Dart [main] 1667 // dartMainRunner(main) - if this function is defined, the Dart [main]
1519 // method will not be invoked directly. 1668 // method will not be invoked directly.
1520 // Instead, a closure that will invoke [main] is 1669 // Instead, a closure that will invoke [main] is
1521 // passed to [dartMainRunner]. 1670 // passed to [dartMainRunner].
1522 """; 1671 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698