Files
sdk/tests/web/wasm/deferred_dynamic_table_test.dart
Nate Biggs 63d042fe0d [dart2wasm] Fix dynamic dispatch table population for multiple modules.
When deferred loading was enabled the dynamic dispatch class ID table
was incorrectly assigning class IDs to the wrong module. If a contiguous
target segment included classes/targets from different modules, all of
them were getting assigned to the module of the first class/target in
that segment.

This was causing spurious NSM exceptions as the necessary rows in the
table might not be populated for a dynamic call if the module the
segment was assigned to wasn't loaded yet.

To fix this we end the segment if the next target does not belong to the
same module as the active segment.

The new test fails with an NSM exception prior to this fix.

Change-Id: I07bc4fdb5a8bff1bfad5fe17f45c8076a965a775
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/502860
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2026-05-12 12:54:38 -07:00

66 lines
1.1 KiB
Dart

///// Copyright (c) 2026, 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.
//
// dart2wasmOptions=--enable-deferred-loading
import '' deferred as lib0;
import '' deferred as lib1;
class A {
void foo() {
print('A.foo');
}
}
class B {
void foo() {
print('B.foo');
}
}
class C {
void foo() {
print('C.foo');
}
}
class D {
void foo() {
print('D.foo');
}
}
class E {
void foo() {
print('E.foo');
}
}
class F {
void foo() {
print('F.foo');
}
}
dynamic confuse(dynamic x) {
return x;
}
Future<void> main() async {
dynamic a = confuse(A());
dynamic b = confuse(B());
confuse(a).foo();
confuse(b).foo();
await lib0.loadLibrary();
dynamic c = confuse(lib0.C());
dynamic d = confuse(lib0.D());
confuse(c).foo();
confuse(d).foo();
await lib1.loadLibrary();
dynamic e = confuse(lib1.E());
dynamic f = confuse(lib1.F());
confuse(e).foo();
confuse(f).foo();
}