blob: a8058325d064b65fd0fa9a715a2e3a97a49bcf21 [file]
// 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.
import 'package:expect/expect.dart';
import '../shared/lib.dart';
@pragma('dyn-module:entry-point')
Future<bool> dynamicModuleEntrypoint() async {
dynamic a1 = sharedA1;
// Dynamic method, getter, and setter calls.
Expect.equals(a1.m4(14), 4);
a1.m1();
a1.s3 = 'hello';
Expect.equals(a1.g2, 'hello');
Expect.equals(a1.m4(14), 4);
// Dynamic use of fields.
Expect.equals(a1.f1, null);
a1.f1 = 2;
Expect.equals(a1.f1, 2);
Expect.equals(a1.f2, 3);
if (const String.fromEnvironment('dynamic.modules.test.mode') == 'aot') {
// TODO(b/448095881): the tearoff operation currently fails in JIT
// Dynamic call via getter tearoff.
dynamic m4to = a1.m4;
Expect.equals(m4to(14), 4);
}
// Ensure we don't accidentally call the target without a dynamic forwarder,
// otherwise parameter checks are omitted accidentally.
Expect.throws(
() => a1.m4('str-value'),
(e) => e is ArgumentError || e is TypeError,
'missing error in dynamic call to host',
);
// Members defined in a dynamic module are dynamically-callable.
dynamic b = B();
Expect.equals(b.m4(14), 13);
Expect.equals(b.m5(14), 16);
// Members defined in a dynamic module also properly check their parameters.
Expect.throws(
() => b.m4('str-value'),
(e) => e is ArgumentError || e is TypeError,
'missing error in dynamic call within dynamic module',
);
Expect.throws(
() => b.m5('str-value'),
(e) => e is ArgumentError || e is TypeError,
'missing error in dynamic call within dynamic module',
);
// A1.m6 was not exposed, even though m6 is an allowed selector.
Expect.throws(
() => a1.m6(),
(e) => e is NoSuchMethodError,
'missing error in dynamic call to unexposed allowed method m6',
);
// A2.m1 was not exposed, but A1.m1 was, so the selector is allowed.
dynamic a2 = sharedA2;
Expect.throws(
() => a2.m1(),
(e) => e is NoSuchMethodError,
'missing error in dynamic call to unexposed class C.m1',
);
// A1.m7 is exposed in other ways, but not dynamically-callable.
Expect.throws(
() => a1.m7(),
(e) => e is NoSuchMethodError,
'missing error in dynamic call to callable but not dynamically-callable method m7',
);
dynamic a3 = sharedA4;
// Interface class A3, where A3.m9 is exposed, but A3.m6 is not.
Expect.equals(a3.m9(1), 11);
Expect.throws(
() => a3.m6(),
(e) => e is NoSuchMethodError,
'missing error in dynamic call to not dynamically-callable host method',
);
// Dynamic module class, base class only partially exposed.
dynamic b5 = B5();
Expect.throws(
() => b5.m10(), // target is unexposed host
(e) => e is NoSuchMethodError,
'missing error in dynamic call to not dynamically-callable host method',
);
Expect.equals(b5.m11(), 4); // target in dynamic module
Expect.equals(b5.m12(), 1); // target is exposed in host
Expect.equals(b5.m13(), 4); // target in dynamic module
sharedB6 = B6();
sharedB7 = B7();
return true;
}
class B {
// m4 matches an exposed selector name from the host.
int m4(int value) {
return value - 1;
}
// m5 matches a selector name in the allowlist flag.
int m5(int value) {
return value + 2;
}
}
class B5 extends A5 {
@override
int m11() => 4;
@override
int m13() => 4;
}
class B6 {
int m14() => 14;
}
class B7 extends A7 {
@override
int m16() => 4;
@override
int m18() => 4;
}