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

Unified 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: More fixes. 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 side-by-side diff with in-line comments
Download patch
Index: lib/compiler/implementation/js_backend/emitter.dart
diff --git a/lib/compiler/implementation/js_backend/emitter.dart b/lib/compiler/implementation/js_backend/emitter.dart
index af68123c4b5a77d3b770b5fa4bc0ee1a0cf6b6d7..a3d32c512e7addf0d13304ade868e5ca9d6f2c51 100644
--- a/lib/compiler/implementation/js_backend/emitter.dart
+++ b/lib/compiler/implementation/js_backend/emitter.dart
@@ -47,13 +47,11 @@ class CodeEmitterTask extends CompilerTask {
final bool generateSourceMap;
- CodeEmitterTask(Compiler compiler, Namer namer,
- [bool generateSourceMap = false])
+ CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap)
: boundClosureBuffer = new CodeBuffer(),
mainBuffer = new CodeBuffer(),
this.namer = namer,
boundClosureCache = new Map<int, String>(),
- generateSourceMap = generateSourceMap,
constantEmitter = new ConstantEmitter(compiler, namer),
super(compiler) {
nativeEmitter = new NativeEmitter(this);
@@ -165,6 +163,8 @@ function(cls, fields, prototype) {
// On Firefox and Webkit browsers we can manipulate the __proto__
// directly. Opera claims to have __proto__ support, but it is buggy.
// So we have to do more checks.
+ // Opera bug was filed as DSK-370158, and fixed as CORE-47615
+ // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes).
// If the browser does not support __proto__ we need to instantiate an
// object with the correct (internal) prototype set up correctly, and then
// copy the members.
@@ -620,23 +620,55 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
emitExtraAccessors(member, defineInstanceMember);
}
- String generateCheckedSetter(Element member, String fieldName) {
- DartType type = member.computeType(compiler);
- if (type.element.isTypeVariable()
- || type.element == compiler.dynamicClass
- || type.element == compiler.objectClass) {
- // TODO(ngeoffray): Support type checks on type parameters.
- return null;
- } else {
- SourceString helper = compiler.backend.getCheckedModeHelper(type);
- FunctionElement helperElement = compiler.findHelper(helper);
- String helperName = namer.isolateAccess(helperElement);
- String additionalArgument = '';
- if (helperElement.computeSignature(compiler).parameterCount != 1) {
- additionalArgument = ", '${namer.operatorIs(type.element)}'";
+ /**
+ * Documentation wanted -- johnniwinther
+ *
+ * Invariant: [classElement] must be a declaration element.
+ */
+ void emitInstanceMembers(ClassElement classElement,
+ CodeBuffer buffer,
+ bool needsLeadingComma) {
+ assert(invariant(classElement, classElement.isDeclaration));
+ bool needsComma = needsLeadingComma;
+ void defineInstanceMember(String name, CodeBuffer memberBuffer) {
+ if (needsComma) buffer.add(',');
+ needsComma = true;
+ buffer.add('\n');
+ buffer.add(' $name: ');
+ buffer.add(memberBuffer);
+ }
+
+ classElement.implementation.forEachMember(
+ (ClassElement enclosing, Element member) {
+ assert(invariant(classElement, member.isDeclaration));
+ if (member.isInstanceMember()) {
+ addInstanceMember(member, defineInstanceMember);
+ }
+ },
+ includeBackendMembers: true);
+
+ generateIsTestsOn(classElement, (ClassElement other) {
+ String code;
+ if (other.isObject(compiler)) return;
+ if (nativeEmitter.requiresNativeIsCheck(other)) {
+ code = 'function() { return true; }';
+ } else {
+ code = 'true';
+ }
+ CodeBuffer typeTestBuffer = new CodeBuffer();
+ typeTestBuffer.add(code);
+ defineInstanceMember(namer.operatorIs(other), typeTestBuffer);
+ });
+
+ if (identical(classElement, compiler.objectClass)
+ && compiler.enabledNoSuchMethod) {
+ // Emit the noSuchMethod handlers on the Object prototype now,
+ // so that the code in the dynamicFunction helper can find
+ // them. Note that this helper is invoked before analyzing the
+ // full JS script.
+ if (!nativeEmitter.handleNoSuchMethod) {
+ emitNoSuchMethodHandlers(defineInstanceMember);
}
- return " set\$$fieldName: function(v) { "
- "this.$fieldName = $helperName(v$additionalArgument); }";
}
}
@@ -645,16 +677,19 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
*
* Invariant: [classElement] must be a declaration element.
*/
- List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) {
+ void visitClassFields(ClassElement classElement,
+ void addField(Element member,
+ String name,
+ bool needsGetter,
+ bool needsSetter,
+ bool needsCheckedSetter)) {
assert(invariant(classElement, classElement.isDeclaration));
// If the class is never instantiated we still need to set it up for
// inheritance purposes, but we can simplify its JavaScript constructor.
bool isInstantiated =
compiler.codegenWorld.instantiatedClasses.contains(classElement);
- List<String> checkedSetters = <String>[];
- bool isFirstField = true;
- void addField(ClassElement enclosingClass, Element member) {
+ void visitField(ClassElement enclosingClass, Element member) {
assert(!member.isNative());
assert(invariant(classElement, member.isDeclaration));
@@ -665,48 +700,36 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
// We can only generate getters and setters for [classElement] since
// the fields of super classes could be overwritten with getters or
// setters.
- bool needsDynamicGetter = false;
- bool needsDynamicSetter = false;
+ bool needsGetter = false;
+ bool needsSetter = false;
// We need to name shadowed fields differently, so they don't clash with
// the non-shadowed field.
bool isShadowed = false;
if (identical(enclosingClass, classElement)) {
- needsDynamicGetter = instanceFieldNeedsGetter(member);
- needsDynamicSetter = instanceFieldNeedsSetter(member);
+ needsGetter = instanceFieldNeedsGetter(member);
+ needsSetter = instanceFieldNeedsSetter(member);
} else {
isShadowed = classElement.isShadowedByField(member);
}
if ((isInstantiated && !enclosingClass.isNative())
- || needsDynamicGetter
- || needsDynamicSetter) {
- if (isFirstField) {
- isFirstField = false;
- } else {
- buffer.add(", ");
- }
+ || needsGetter
+ || needsSetter) {
String fieldName = isShadowed
? namer.shadowedFieldName(member)
: namer.getName(member);
- if (needsDynamicSetter && compiler.enableTypeAssertions) {
- String setter = generateCheckedSetter(member, fieldName);
- if (setter != null) {
- needsDynamicSetter = false;
- checkedSetters.add(setter);
- }
+ bool needsCheckedSetter = false;
+ if (needsSetter && compiler.enableTypeAssertions
+ && canGenerateCheckedSetter(member)) {
+ needsCheckedSetter = true;
+ needsSetter = false;
}
// Getters and setters with suffixes will be generated dynamically.
- buffer.add('"$fieldName');
- if (needsDynamicGetter || needsDynamicSetter) {
- if (needsDynamicGetter && needsDynamicSetter) {
- buffer.add(GETTER_SETTER_SUFFIX);
- } else if (needsDynamicGetter) {
- buffer.add(GETTER_SUFFIX);
- } else {
- buffer.add(SETTER_SUFFIX);
- }
- }
- buffer.add('"');
+ addField(member,
+ fieldName,
+ needsGetter,
+ needsSetter,
+ needsCheckedSetter);
}
}
@@ -715,62 +738,97 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
// allowed on fields that are in [classElement] we don't need to visit
// superclasses for non-instantiated classes.
classElement.implementation.forEachInstanceField(
- addField,
+ visitField,
includeBackendMembers: true,
includeSuperMembers: isInstantiated && !classElement.isNative());
- return checkedSetters;
}
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [classElement] must be a declaration element.
- */
- void emitInstanceMembers(ClassElement classElement,
- CodeBuffer buffer,
- bool needsLeadingComma) {
- assert(invariant(classElement, classElement.isDeclaration));
- bool needsComma = needsLeadingComma;
- void defineInstanceMember(String name, CodeBuffer memberBuffer) {
- if (needsComma) buffer.add(',');
- needsComma = true;
- buffer.add('\n');
- buffer.add(' $name: ');
- buffer.add(memberBuffer);
+ void generateGetter(Element member, String fieldName, CodeBuffer buffer) {
+ String getterName = namer.getterName(member.getLibrary(), member.name);
+ buffer.add("$getterName: function() { return this.$fieldName; }");
+ }
+
+ void generateSetter(Element member, String fieldName, CodeBuffer buffer) {
+ String setterName = namer.setterName(member.getLibrary(), member.name);
+ buffer.add("$setterName: function(v) { this.$fieldName = v; }");
+ }
+
+ bool canGenerateCheckedSetter(Element member) {
+ DartType type = member.computeType(compiler);
+ if (type.element.isTypeVariable()
+ || type.element == compiler.dynamicClass
+ || type.element == compiler.objectClass) {
+ // TODO(ngeoffray): Support type checks on type parameters.
+ return false;
}
+ return true;
+ }
- classElement.implementation.forEachMember(
- (ClassElement enclosing, Element member) {
- assert(invariant(classElement, member.isDeclaration));
- if (member.isInstanceMember()) {
- addInstanceMember(member, defineInstanceMember);
- }
- },
- includeBackendMembers: true);
+ void generateCheckedSetter(Element member,
+ String fieldName,
+ CodeBuffer buffer) {
+ assert(canGenerateCheckedSetter(member));
+ DartType type = member.computeType(compiler);
+ SourceString helper = compiler.backend.getCheckedModeHelper(type);
+ FunctionElement helperElement = compiler.findHelper(helper);
+ String helperName = namer.isolateAccess(helperElement);
+ String additionalArgument = '';
+ if (helperElement.computeSignature(compiler).parameterCount != 1) {
+ additionalArgument = ", '${namer.operatorIs(type.element)}'";
+ }
+ String setterName = namer.setterName(member.getLibrary(), member.name);
+ buffer.add("$setterName: function(v) { "
+ "this.$fieldName = $helperName(v$additionalArgument); }");
+ }
- generateIsTestsOn(classElement, (ClassElement other) {
- String code;
- if (other.isObject(compiler)) return;
- if (nativeEmitter.requiresNativeIsCheck(other)) {
- code = 'function() { return true; }';
+ void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) {
+ /* Do nothing. */
+ }
+
+ void emitClassFields(ClassElement classElement, CodeBuffer buffer) {
+ buffer.add('"": [');
+ bool isFirstField = true;
+ visitClassFields(classElement, (Element member,
+ String name,
+ bool needsGetter,
+ bool needsSetter,
+ bool needsCheckedSetter) {
+ if (isFirstField) {
+ isFirstField = false;
} else {
- code = 'true';
+ buffer.add(", ");
}
- CodeBuffer typeTestBuffer = new CodeBuffer();
- typeTestBuffer.add(code);
- defineInstanceMember(namer.operatorIs(other), typeTestBuffer);
+ buffer.add('"$name');
+ if (needsGetter && needsSetter) {
+ buffer.add(GETTER_SETTER_SUFFIX);
+ } else if (needsGetter) {
+ buffer.add(GETTER_SUFFIX);
+ } else if (needsSetter) {
+ buffer.add(SETTER_SUFFIX);
+ }
+ buffer.add('"');
});
+ buffer.add(']');
+ }
- if (identical(classElement, compiler.objectClass)
- && compiler.enabledNoSuchMethod) {
- // Emit the noSuchMethod handlers on the Object prototype now,
- // so that the code in the dynamicFunction helper can find
- // them. Note that this helper is invoked before analyzing the
- // full JS script.
- if (!nativeEmitter.handleNoSuchMethod) {
- emitNoSuchMethodHandlers(defineInstanceMember);
+ /** Each getter/setter must be prefixed with a ",\n ". */
+ void emitClassGettersSetters(ClassElement classElement, CodeBuffer buffer,
+ {bool omitLeadingComma: false}) {
+ visitClassFields(classElement, (Element member,
+ String name,
+ bool needsGetter,
+ bool needsSetter,
+ bool needsCheckedSetter) {
+ if (needsCheckedSetter) {
+ assert(!needsSetter);
+ if (!omitLeadingComma) {
+ buffer.add(",\n ");
+ } else {
+ omitLeadingComma = false;
+ }
+ generateCheckedSetter(member, name, buffer);
}
- }
+ });
}
/**
@@ -797,20 +855,15 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
if (superclass != null) {
superName = namer.getName(superclass);
}
- String constructorName = namer.safeName(classElement.name.slowToString());
- buffer.add('$classesCollector.$className = {"":\n');
- buffer.add(' [');
- List<String> checkedSetters = emitClassFields(classElement, buffer);
- buffer.add('],\n');
+ buffer.add('$classesCollector.$className = {');
+ emitClassConstructor(classElement, buffer);
+ emitClassFields(classElement, buffer);
// TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'.
// That does currently not work because the native classes have a different
// syntax.
- buffer.add(' "super": "$superName"');
- if (!checkedSetters.isEmpty()) {
- buffer.add(',\n');
- buffer.add('${Strings.join(checkedSetters, ",\n")}');
- }
+ buffer.add(',\n "super": "$superName"');
+ emitClassGettersSetters(classElement, buffer);
emitInstanceMembers(classElement, buffer, true);
buffer.add('\n};\n\n');
}
@@ -975,6 +1028,16 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
}
}
+ void emitBoundClosureClassHeader(String mangledName,
+ String superName,
+ CodeBuffer buffer) {
+ buffer.add("""
+$classesCollector.$mangledName = {'':
+['self', 'target'],
+'super': '$superName',
+""");
+ }
+
/**
* Documentation wanted -- johnniwinther
*
@@ -1021,11 +1084,7 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
// Define the constructor with a name so that Object.toString can
// find the class name of the closure class.
- boundClosureBuffer.add("""
-$classesCollector.$mangledName = {'':
- ['self', 'target'],
- 'super': '$superName',
-""");
+ emitBoundClosureClassHeader(mangledName, superName, boundClosureBuffer);
// Now add the methods on the closure class. The instance method does not
// have the correct name. Since [addParameterStubs] use the name to create
// its stubs we simply create a fake element with the correct name.
« no previous file with comments | « lib/compiler/implementation/js_backend/backend.dart ('k') | lib/compiler/implementation/js_backend/emitter_no_eval.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698