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 6e7d350384f5fb4d56a852fe8788bd47e0b0173c..70e6a95c97f148c9c829c674794f72ae26826bea 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 |
@@ -329,29 +329,26 @@ class ModelEmitter { |
return [getters, setters].expand((x) => x); |
} |
- js.Expression emitClass(Class 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])); |
- return unparse(compiler, new js.ArrayInitializer(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) { |
+ js.Expression emitClass(Class cls) { |
List elements = [js.string(cls.superclassName), |
- js.number(cls.superclassHolderIndex), |
- js.string(cls.mixinClass.name), |
- js.number(cls.mixinClass.holder.index)]; |
+ js.number(cls.superclassHolderIndex)]; |
+ |
+ if (cls.isMixinApplication) { |
+ MixinApplication mixin = cls; |
+ elements.add(js.string(mixin.mixinClass.name)); |
+ elements.add(js.number(mixin.mixinClass.holder.index)); |
+ } else { |
+ elements.add(_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])); |
return unparse(compiler, new js.ArrayInitializer(elements)); |
} |
@@ -438,39 +435,45 @@ class ModelEmitter { |
} |
function setupClass(name, holder, descriptor) { |
- var resolve = function() { |
+ var ensureResolved = function() { |
var constructor = compileConstructor(name, descriptor); |
holder[name] = constructor; |
+ constructor.ensureResolved = function() { return this; }; |
return constructor; |
}; |
var patch = function() { |
- var constructor = resolve(); |
+ var constructor = ensureResolved(); |
var object = new constructor(); |
constructor.apply(object, arguments); |
return object; |
}; |
- // We store the resolve function on the patch function to make it possible |
- // to resolve superclass references without constructing instances. The |
- // resolve property also serves as a marker that indicates whether or not |
- // a class has been resolved yet. |
- patch.resolve = resolve; |
+ // We store the ensureResolved function on the patch function to make it |
+ // possible to resolve superclass references without constructing instances. |
+ patch.ensureResolved = ensureResolved; |
holder[name] = patch; |
} |
function compileConstructor(name, descriptor) { |
descriptor = compile(name, descriptor); |
var prototype = determinePrototype(descriptor); |
+ var constructor; |
// $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]; |
+ constructor = compileMixinConstructor(name, prototype, descriptor); |
+ for (var i = 4; i < descriptor.length; i += 2) { |
+ prototype[descriptor[i]] = descriptor[i + 1]; |
+ } |
+ } else { |
+ constructor = descriptor[2]; |
+ for (var i = 3; i < descriptor.length; i += 2) { |
+ prototype[descriptor[i]] = descriptor[i + 1]; |
+ } |
} |
+ constructor.builtin\$cls = name; // Needed for RTI. |
constructor.prototype = prototype; |
+ prototype.constructor = constructor; |
return constructor; |
} |
@@ -478,8 +481,7 @@ class ModelEmitter { |
// $mixinFormatDescription. |
var mixinName = descriptor[2]; |
var mixinHolderIndex = descriptor[3]; |
- var mixin = holders[mixinHolderIndex][mixinName]; |
- if (mixin.resolve) mixin = mixin.resolve(); |
+ var mixin = holders[mixinHolderIndex][mixinName].ensureResolved(); |
var mixinPrototype = mixin.prototype; |
// Fill the prototype with the mixin's properties. |
@@ -491,7 +493,6 @@ class ModelEmitter { |
// 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; |
} |
@@ -501,8 +502,7 @@ class ModelEmitter { |
// Look up the superclass constructor function in the right holder. |
var holderIndex = descriptor[1]; |
- var superclass = holders[holderIndex][superclassName]; |
- if (superclass.resolve) superclass = superclass.resolve(); |
+ var superclass = holders[holderIndex][superclassName].ensureResolved(); |
// Create a new prototype object chained to the superclass prototype. |
var intermediate = function() { }; |