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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 12051056: Allow native classes to mixin behavior from an ordinary Dart class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Refactor. Created 7 years, 11 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: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 07fc08d3836c875a644cbf766d3a7902ff002647..55e4e99b3f51d8d89897a60713890fa98b2ec1af 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -735,14 +735,32 @@ $lazyInitializerLogic
return;
}
+ void visitMember(ClassElement enclosing, Element member) {
+ assert(invariant(classElement, member.isDeclaration));
+ if (member.isInstanceMember()) {
+ addInstanceMember(member, builder);
+ }
+ }
+
+ // TODO(kasperl): We should make sure to only emit one version of
+ // overridden methods. Right now, we rely on the ordering so the
+ // methods pulled in from mixins are replaced with the members
+ // from the class definition.
+
+ // If the class is a native class, we have to add the instance
+ // members defined in the non-native mixin applications used by
+ // the class.
+ visitNativeMixins(classElement, (MixinApplicationElement mixin) {
ngeoffray 2013/01/24 11:55:53 visitMixinsOfNativeClasses?
+ mixin.forEachMember(
+ visitMember,
+ includeBackendMembers: true,
+ includeSuperMembers: false);
+ });
+
classElement.implementation.forEachMember(
- (ClassElement enclosing, Element member) {
- assert(invariant(classElement, member.isDeclaration));
- if (member.isInstanceMember()) {
- addInstanceMember(member, builder);
- }
- },
- includeBackendMembers: true);
+ visitMember,
+ includeBackendMembers: true,
+ includeSuperMembers: false);
generateIsTestsOn(classElement, (Element other) {
js.Expression code;
@@ -826,6 +844,22 @@ $lazyInitializerLogic
}
}
+ void visitNativeMixins(ClassElement classElement,
+ void visit(MixinApplicationElement mixinApplication)) {
+ if (!classElement.isNative()) return;
+ // Use recursion to make sure to visit the superclasses before the
+ // subclasses. Once we start keeping track of the emitted fields
+ // and members, we're going to want to visit these in the other
+ // order so we get the most specialized definition first.
+ void recurse(ClassElement cls) {
+ if (cls == null || !cls.isMixinApplication) return;
+ recurse(cls.superclass);
+ assert(!cls.isNative());
+ visit(cls);
+ }
+ recurse(classElement.superclass);
+ }
+
/**
* Documentation wanted -- johnniwinther
*
@@ -891,6 +925,20 @@ $lazyInitializerLogic
}
}
+ // TODO(kasperl): We should make sure to only emit one version of
+ // overridden fields. Right now, we rely on the ordering so the
+ // fields pulled in from mixins are replaced with the fields from
+ // the class definition.
+
+ // If the class is a native class, we have to add the fields
+ // defined in the non-native mixin applications used by the class.
+ visitNativeMixins(classElement, (MixinApplicationElement mixin) {
+ mixin.forEachInstanceField(
+ visitField,
+ includeBackendMembers: true,
+ includeSuperMembers: false);
+ });
+
// If a class is not instantiated then we add the field just so we can
// generate the field getter/setter dynamically. Since this is only
// allowed on fields that are in [classElement] we don't need to visit
@@ -1068,7 +1116,13 @@ $lazyInitializerLogic
needsDefineClass = true;
String className = namer.getName(classElement);
+
+ // Find the first non-native superclass.
ClassElement superclass = classElement.superclass;
+ while (superclass != null && superclass.isNative()) {
+ superclass = superclass.superclass;
+ }
+
String superName = "";
if (superclass != null) {
superName = namer.getName(superclass);
@@ -1162,9 +1216,20 @@ $lazyInitializerLogic
getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest);
}
}
+
for (DartType interfaceType in cls.interfaces) {
generateInterfacesIsTests(interfaceType.element, emitIsTest, generated);
}
+
+ // For native classes, we also have to run through their mixin
+ // applications and make sure we deal with 'is' tests correctly
+ // for those.
+ visitNativeMixins(cls, (MixinApplicationElement mixin) {
+ for (DartType interfaceType in mixin.interfaces) {
+ ClassElement interfaceElement = interfaceType.element;
+ generateInterfacesIsTests(interfaceType.element, emitIsTest, generated);
+ }
+ });
}
/**

Powered by Google App Engine
This is Rietveld 408576698