[dart2wasm] Skip constructor entrypoints of dynamic callable anonymous mixins constructors. These mixin constructors are now marked callable by the dynamic interface annotator: https://dart-review.googlesource.com/c/sdk/+/430002 However, they are not directly invokeable and trying to compile the constructor entrypoints causes dart2wasm to crash. So we explicitly skip them when considering dynamic callable constructors. Note: This is blocking internal rolls as code patterns like this show up in our internal codebase. Change-Id: I76383aec07bc53a0dbd1581c0577cba370d956f9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430801 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com> Auto-Submit: Nate Biggs <natebiggs@google.com>
diff --git a/pkg/dart2wasm/lib/dynamic_modules.dart b/pkg/dart2wasm/lib/dynamic_modules.dart index b7001aa..67ab4047 100644 --- a/pkg/dart2wasm/lib/dynamic_modules.dart +++ b/pkg/dart2wasm/lib/dynamic_modules.dart
@@ -605,7 +605,9 @@ // These types do not have directly invokable constructors. translator.classInfo[member.enclosingClass]!.struct .isSubtypeOf(translator.objectInfo.struct)) { - passReference(member.reference); + if (!member.enclosingClass.isAnonymousMixin) { + passReference(member.reference); + } passReference(member.initializerReference); passReference(member.constructorBodyReference); }
diff --git a/pkg/dynamic_modules/test/data/const_mixin_class/dynamic_interface.yaml b/pkg/dynamic_modules/test/data/const_mixin_class/dynamic_interface.yaml new file mode 100644 index 0000000..43360b9 --- /dev/null +++ b/pkg/dynamic_modules/test/data/const_mixin_class/dynamic_interface.yaml
@@ -0,0 +1,7 @@ +# Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +callable: + - library: 'shared/shared.dart' + class: 'Foo'
diff --git a/pkg/dynamic_modules/test/data/const_mixin_class/main.dart b/pkg/dynamic_modules/test/data/const_mixin_class/main.dart new file mode 100644 index 0000000..3910617 --- /dev/null +++ b/pkg/dynamic_modules/test/data/const_mixin_class/main.dart
@@ -0,0 +1,16 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../../common/testing.dart' as helper; +import 'package:expect/expect.dart'; + +import 'shared/shared.dart' show Foo; + +/// A dynamic module is allowed to extend a class in the dynamic interface and +/// override its members. +void main() async { + final o = (await helper.load('entry1.dart')); + Expect.equals(const Foo(), o); + helper.done(); +}
diff --git a/pkg/dynamic_modules/test/data/const_mixin_class/modules/entry1.dart b/pkg/dynamic_modules/test/data/const_mixin_class/modules/entry1.dart new file mode 100644 index 0000000..ec027e2 --- /dev/null +++ b/pkg/dynamic_modules/test/data/const_mixin_class/modules/entry1.dart
@@ -0,0 +1,8 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../shared/shared.dart'; + +@pragma('dyn-module:entry-point') +Object? dynamicModuleEntrypoint() => const Foo();
diff --git a/pkg/dynamic_modules/test/data/const_mixin_class/shared/shared.dart b/pkg/dynamic_modules/test/data/const_mixin_class/shared/shared.dart new file mode 100644 index 0000000..c9402b4 --- /dev/null +++ b/pkg/dynamic_modules/test/data/const_mixin_class/shared/shared.dart
@@ -0,0 +1,9 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +mixin Mixin {} + +class Foo with Mixin { + const Foo(); +}