blob: a431173f3612616ba20a7096509ac3ff49328f63 [file] [log] [blame]
// Copyright (c) 2023, 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 'dart:async';
import 'dart:isolate';
import 'dart:nativewrappers';
import 'package:expect/async_helper.dart';
import 'package:expect/expect.dart';
class Foo {
int i = 42;
}
class Bar {
Foo foo = Foo();
}
@pragma('vm:entry-point') // prevent obfuscation
base class NativeClass extends NativeFieldWrapperClass1 {}
class Baz {
@pragma('vm:entry-point') // prevent tree-shaking of the field.
NativeClass? nativeClass;
Baz();
}
@pragma('vm:entry-point') // prevent obfuscation
class Fu {
String label;
Bar bar = Bar();
Baz baz = Baz();
Fu(this.label);
Fu.unsendable(this.label) {
baz.nativeClass = NativeClass();
}
}
@pragma('vm:entry-point') // prevent obfuscation
@pragma("vm:isolate-unsendable")
class Locked {}
@pragma('vm:entry-point') // prevent obfuscation
class ExtendsLocked extends Locked {}
@pragma('vm:entry-point') // prevent obfuscation
class ImplementsLocked implements Locked {}
Future<T> sendAndReceive<T>(T object) async {
final rp = ReceivePort();
rp.sendPort.send(object);
return await rp.first;
}
bool checkForRetainingPath(Object? e, List<String> list) {
if (e is! ArgumentError) {
return false;
}
final msg = e.toString();
return list.every((s) => msg.contains(s));
}
main() async {
asyncStart();
final rp = ReceivePort();
for (final pair in [
[
() => Fu.unsendable('fu'),
["NativeClass", "Baz", "Fu"],
],
[
() => Future.value(123),
["Future"],
],
[
Locked.new,
["Locked"],
],
[
ExtendsLocked.new,
["ExtendsLocked"],
],
[
ImplementsLocked.new,
["ImplementsLocked"],
],
]) {
Expect.throws(
() => rp.sendPort.send((pair[0] as Function)()),
(e) => checkForRetainingPath(e, pair[1] as List<String>),
);
}
try {
await Isolate.spawn((_) {}, Locked());
Expect.fail('spawn should have failed');
} catch (e) {
Expect.isTrue(e is ArgumentError && e.toString().contains("Locked"));
}
runZoned(() {
Expect.throws(() {
final z = Zone.current;
rp.sendPort.send(Zone.current);
}, (e) => e is ArgumentError);
}, zoneValues: {0: 1});
rp.close();
asyncEnd();
}