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

Unified Diff: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart

Issue 752553004: dart2js: Support mixins in the new emitter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 6 years, 1 month 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
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
index 1df89ae5f815765aab7f02782a67071917199734..6a34fbbea4f37feb54d6e633d3809882628260e6 100644
--- a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
@@ -256,11 +256,20 @@ class ModelEmitter {
js.Expression _generateConstructor(Class cls) {
List<String> allFieldNames = <String>[];
- Class currentClass = cls;
- while (currentClass != null) {
- allFieldNames.addAll(
- currentClass.fields.map((InstanceField field) => field.name));
- currentClass = currentClass.superclass;
+
+ // If the class is not directly instantiated we only need it for inheritance
+ // or RTI. In either case we don't need its fields.
+ if (cls.isDirectlyInstantiated) {
+ Class currentClass = cls;
+ while (currentClass != null) {
+ // Mixins are not allowed to inject fields.
+ assert(!currentClass.isMixinApplication ||
+ (currentClass as MixinApplication).mixinClass.fields.isEmpty);
+
+ allFieldNames.addAll(
+ currentClass.fields.map((InstanceField field) => field.name));
+ currentClass = currentClass.superclass;
+ }
}
String name = cls.name;
String parameters = allFieldNames.join(', ');
@@ -316,13 +325,28 @@ class ModelEmitter {
}
js.Expression emitClass(Class cls) {
- List elements = [ js.string(cls.superclassName),
- js.number(cls.superclassHolderIndex),
- _generateConstructor(cls) ];
+ if (cls.isMixinApplication) return emitMixinApplication(cls);
+
+ List elements = [js.string(cls.superclassName),
+ js.number(cls.superclassHolderIndex),
+ _generateConstructor(cls)];
Iterable<Method> methods = cls.methods;
Iterable<Method> gettersSetters = _generateGettersSetters(cls);
Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x);
- elements.addAll(allMethods.expand((e) => [ js.string(e.name), e.code ]));
+ elements.addAll(allMethods.expand((e) => [js.string(e.name), e.code]));
+ return unparse(compiler, new js.ArrayInitializer.from(elements));
+ }
+
+ // This string should be referenced wherever JavaScript code makes assumptions
+ // on the mixin format.
+ static final String mixinFormatDescription =
+ "Mixins have no constructor, but a reference to their mixin class.";
+
+ js.Expression emitMixinApplication(MixinApplication cls) {
+ List elements = [js.string(cls.superclassName),
+ js.number(cls.superclassHolderIndex),
+ js.string(cls.mixinClass.name),
+ js.number(cls.mixinClass.holder.index)];
return unparse(compiler, new js.ArrayInitializer.from(elements));
}
@@ -334,9 +358,8 @@ class ModelEmitter {
js.Expression emitStaticMethod(StaticMethod method) {
return unparse(compiler, method.code);
}
-}
-final String boilerplate = r"""
+ static final String boilerplate = """
{
// Declare deferred-initializer global.
#;
@@ -434,6 +457,10 @@ final String boilerplate = r"""
function compileConstructor(name, descriptor) {
descriptor = compile(name, descriptor);
var prototype = determinePrototype(descriptor);
+ // $mixinFormatDescription.
+ if (typeof descriptor[2] !== 'function') {
+ return compileMixinConstructor(name, prototype, descriptor);
+ }
var constructor = descriptor[2];
for (var i = 3; i < descriptor.length; i += 2) {
prototype[descriptor[i]] = descriptor[i + 1];
@@ -442,6 +469,27 @@ final String boilerplate = r"""
return constructor;
}
+ function compileMixinConstructor(name, prototype, descriptor) {
+ // $mixinFormatDescription.
+ var mixinName = descriptor[2];
+ var mixinHolderIndex = descriptor[3];
+ var mixin = holders[mixinHolderIndex][mixinName];
+ if (mixin.resolve) mixin = mixin.resolve();
+ var mixinPrototype = mixin.prototype;
+
+ // Fill the prototype with the mixin's properties.
+ var mixinProperties = Object.keys(mixinPrototype);
+ for (var i = 0; i < mixinProperties.length; i++) {
+ var p = mixinProperties[i];
+ prototype[p] = mixinPrototype[p];
+ }
+ // Since this is a mixin application the constructor will actually never
+ // be invoked. We only use its prototype for the application's subclasses.
+ var constructor = function() {};
+ constructor.prototype = prototype;
+ return constructor;
+ }
+
function determinePrototype(descriptor) {
var superclassName = descriptor[0];
if (!superclassName) return { };
@@ -461,7 +509,7 @@ final String boilerplate = r"""
'use strict';
// TODO(floitsch): evaluate the performance impact of the string
// concatenations.
- return eval(__s__ + "\n//# sourceURL=" + __name__ + ".js");
+ return eval(__s__ + "\\n//# sourceURL=" + __name__ + ".js");
}
if (#) { // outputContainsConstantList
@@ -469,8 +517,8 @@ final String boilerplate = r"""
// By assigning a function to the properties they become part of the
// hidden class. The actual values of the fields don't matter, since we
// only check if they exist.
- list.immutable$list = Array;
- list.fixed$length = Array;
+ list.immutable\$list = Array;
+ list.fixed\$length = Array;
return list;
}
}
@@ -496,3 +544,5 @@ final String boilerplate = r"""
}(Date.now(), #)
}""";
+
+}
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698