Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f3036f4

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
Support supermixins in dart2js
The tests use the old syntax which CFE currently (wrongfully) allows for dart2js. Change-Id: Ia4dde9e6e1444d8ec22905c36209049bd4161faa Reviewed-on: https://dart-review.googlesource.com/72443 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Stephen Adams <sra@google.com>
1 parent 5e26304 commit f3036f4

24 files changed

+530
-113
lines changed

pkg/compiler/lib/src/common_elements.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,10 @@ abstract class ElementEnvironment {
14811481
/// Returns `true` if [cls] is an unnamed mixin application.
14821482
bool isUnnamedMixinApplication(ClassEntity cls);
14831483

1484+
/// Returns `true` if [cls] is a mixin application that mixes in methods with
1485+
/// super calls.
1486+
bool isSuperMixinApplication(ClassEntity cls);
1487+
14841488
/// Returns the 'effective' mixin class if [cls] is a mixin application, and
14851489
/// `null` otherwise.
14861490
///

pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ class ClassEmitter extends CodeEmitterHelper {
4242
superName = namer.className(superclass);
4343
}
4444

45-
if (cls.isMixinApplication) {
46-
MixinApplication mixinApplication = cls;
47-
jsAst.Name mixinName = mixinApplication.mixinClass.name;
45+
if (cls.mixinClass != null) {
46+
jsAst.Name mixinName = cls.mixinClass.name;
4847
superName = new CompoundName([superName, Namer.literalPlus, mixinName]);
4948
emitter.needsMixinSupport = true;
5049
}
@@ -226,7 +225,7 @@ class ClassEmitter extends CodeEmitterHelper {
226225
void emitInstanceMembers(Class cls, ClassBuilder builder) {
227226
ClassEntity classElement = cls.element;
228227

229-
if (cls.onlyForRti || cls.isMixinApplication) return;
228+
if (cls.onlyForRti || cls.isSimpleMixinApplication) return;
230229

231230
// TODO(herhut): This is a no-op. Should it be removed?
232231
for (Field field in cls.fields) {

pkg/compiler/lib/src/js_emitter/model.dart

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ class Class implements FieldContainer {
237237
final js.Name name;
238238
final Holder holder;
239239
Class _superclass;
240+
Class _mixinClass;
240241
final List<Method> methods;
241242
final List<Field> fields;
242243
final List<StubMethod> isChecks;
@@ -259,6 +260,8 @@ class Class implements FieldContainer {
259260
/// A soft-deferred class is only fully initialized at first instantiation.
260261
final bool isSoftDeferred;
261262

263+
final bool isSuperMixinApplication;
264+
262265
// If the class implements a function type, and the type is encoded in the
263266
// metatada table, then this field contains the index into that field.
264267
final js.Expression functionTypeIndex;
@@ -292,20 +295,28 @@ class Class implements FieldContainer {
292295
this.isDirectlyInstantiated,
293296
this.isNative,
294297
this.isClosureBaseClass,
295-
this.isSoftDeferred = false}) {
298+
this.isSoftDeferred = false,
299+
this.isSuperMixinApplication}) {
296300
assert(onlyForRti != null);
297301
assert(isDirectlyInstantiated != null);
298302
assert(isNative != null);
299303
assert(isClosureBaseClass != null);
300304
}
301305

302-
bool get isMixinApplication => false;
306+
bool get isSimpleMixinApplication => false;
307+
303308
Class get superclass => _superclass;
304309

305310
void setSuperclass(Class superclass) {
306311
_superclass = superclass;
307312
}
308313

314+
Class get mixinClass => _mixinClass;
315+
316+
void setMixinClass(Class mixinClass) {
317+
_mixinClass = mixinClass;
318+
}
319+
309320
js.Name get superclassName => superclass == null ? null : superclass.name;
310321

311322
int get superclassHolderIndex =>
@@ -315,8 +326,6 @@ class Class implements FieldContainer {
315326
}
316327

317328
class MixinApplication extends Class {
318-
Class _mixinClass;
319-
320329
MixinApplication(
321330
ClassEntity element,
322331
js.Name name,
@@ -346,14 +355,10 @@ class MixinApplication extends Class {
346355
onlyForRti: onlyForRti,
347356
isDirectlyInstantiated: isDirectlyInstantiated,
348357
isNative: false,
349-
isClosureBaseClass: false);
350-
351-
bool get isMixinApplication => true;
352-
Class get mixinClass => _mixinClass;
358+
isClosureBaseClass: false,
359+
isSuperMixinApplication: false);
353360

354-
void setMixinClass(Class mixinClass) {
355-
_mixinClass = mixinClass;
356-
}
361+
bool get isSimpleMixinApplication => true;
357362

358363
String toString() => 'Mixin(name=${name.key},element=$element)';
359364
}

pkg/compiler/lib/src/js_emitter/native_emitter.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ class NativeEmitter {
257257
return cls.methods.isEmpty &&
258258
cls.isChecks.isEmpty &&
259259
cls.callStubs.isEmpty &&
260-
!cls.superclass.isMixinApplication &&
260+
!cls.superclass.isSimpleMixinApplication &&
261261
!cls.fields.any(needsAccessor);
262262
}
263263

pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class ProgramBuilder {
211211
"No Class for has been created for superclass "
212212
"${superclass} of $c."));
213213
}
214-
if (c is MixinApplication) {
214+
if (c.isSimpleMixinApplication || c.isSuperMixinApplication) {
215215
ClassEntity effectiveMixinClass =
216216
_elementEnvironment.getEffectiveMixinClass(cls);
217217
c.setMixinClass(_classes[effectiveMixinClass]);
@@ -696,12 +696,26 @@ class ProgramBuilder {
696696

697697
// MixinApplications run through the members of their mixin. Here, we are
698698
// only interested in direct members.
699-
if (!onlyForRti && !_elementEnvironment.isMixinApplication(cls)) {
700-
List<MemberEntity> members = <MemberEntity>[];
701-
_elementEnvironment.forEachLocalClassMember(cls, members.add);
702-
_elementEnvironment.forEachInjectedClassMember(cls, members.add);
703-
_elementEnvironment.forEachConstructorBody(cls, members.add);
704-
_sorter.sortMembers(members).forEach(visitMember);
699+
bool isSuperMixinApplication = false;
700+
if (!onlyForRti) {
701+
if (_elementEnvironment.isSuperMixinApplication(cls)) {
702+
List<MemberEntity> members = <MemberEntity>[];
703+
_elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
704+
if (member.enclosingClass == cls) {
705+
members.add(member);
706+
isSuperMixinApplication = true;
707+
}
708+
});
709+
if (members.isNotEmpty) {
710+
_sorter.sortMembers(members).forEach(visitMember);
711+
}
712+
} else if (!_elementEnvironment.isMixinApplication(cls)) {
713+
List<MemberEntity> members = <MemberEntity>[];
714+
_elementEnvironment.forEachLocalClassMember(cls, members.add);
715+
_elementEnvironment.forEachInjectedClassMember(cls, members.add);
716+
_elementEnvironment.forEachConstructorBody(cls, members.add);
717+
_sorter.sortMembers(members).forEach(visitMember);
718+
}
705719
}
706720
bool isInterceptedClass = _interceptorData.isInterceptedClass(cls);
707721
List<Field> instanceFields = onlyForRti
@@ -759,7 +773,9 @@ class ProgramBuilder {
759773
_worldBuilder.directlyInstantiatedClasses.contains(cls);
760774

761775
Class result;
762-
if (_elementEnvironment.isMixinApplication(cls) && !onlyForRti) {
776+
if (_elementEnvironment.isMixinApplication(cls) &&
777+
!onlyForRti &&
778+
!isSuperMixinApplication) {
763779
assert(!_nativeData.isNativeClass(cls));
764780
assert(methods.isEmpty);
765781
assert(!isClosureBaseClass);
@@ -795,7 +811,8 @@ class ProgramBuilder {
795811
onlyForRti: onlyForRti,
796812
isNative: _nativeData.isNativeClass(cls),
797813
isClosureBaseClass: isClosureBaseClass,
798-
isSoftDeferred: _isSoftDeferred(cls));
814+
isSoftDeferred: _isSoftDeferred(cls),
815+
isSuperMixinApplication: isSuperMixinApplication);
799816
}
800817
_classes[cls] = result;
801818
return result;

pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,10 +1018,9 @@ class FragmentEmitter {
10181018
if (cls.isSoftDeferred != softDeferred) continue;
10191019
collect(cls);
10201020

1021-
if (cls.isMixinApplication) {
1022-
MixinApplication mixin = cls;
1021+
if (cls.mixinClass != null) {
10231022
mixinCalls.add(js.js.statement('mixin(#, #)',
1024-
[classReference(cls), classReference(mixin.mixinClass)]));
1023+
[classReference(cls), classReference(cls.mixinClass)]));
10251024
}
10261025
}
10271026
}

pkg/compiler/lib/src/kernel/element_map.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,8 @@ SourceSpan computeSourceSpanFromTreeNode(ir.TreeNode node) {
501501
while (node != null) {
502502
if (node.fileOffset != ir.TreeNode.noOffset) {
503503
offset = node.fileOffset;
504-
uri = node.location.file;
504+
// @patch annotations have no location.
505+
uri = node.location?.file;
505506
break;
506507
}
507508
node = node.parent;

pkg/compiler/lib/src/kernel/element_map_impl.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,13 @@ abstract class KernelToElementMapBase extends KernelToElementMapBaseMixin {
718718
return env.isUnnamedMixinApplication;
719719
}
720720

721+
bool _isSuperMixinApplication(IndexedClass cls) {
722+
assert(checkFamily(cls));
723+
ClassEnv env = _classes.getEnv(cls);
724+
env.ensureMembers(this);
725+
return env.isSuperMixinApplication;
726+
}
727+
721728
void _forEachSupertype(IndexedClass cls, void f(InterfaceType supertype)) {
722729
assert(checkFamily(cls));
723730
ClassData data = _classes.getData(cls);
@@ -1513,6 +1520,11 @@ class KernelElementEnvironment extends ElementEnvironment {
15131520
return elementMap._isUnnamedMixinApplication(cls);
15141521
}
15151522

1523+
@override
1524+
bool isSuperMixinApplication(ClassEntity cls) {
1525+
return elementMap._isSuperMixinApplication(cls);
1526+
}
1527+
15161528
@override
15171529
ClassEntity getEffectiveMixinClass(ClassEntity cls) {
15181530
if (!isMixinApplication(cls)) return null;

0 commit comments

Comments
 (0)