LCOV - code coverage report

Current view
top level - src/_impl/native - _channel.dart
Test
lcov.info
Date
2026-03-04
Legend
Lines
hit
not hit
Branches
taken
not taken
# not executed
HitTotalCoverage
Lines566684.8%
Functions00-
Branches00-
Each row represents a line of source code
LineBranchHitsSource code
1import 'dart:async';
2import 'dart:convert';
3import 'dart:isolate' as vm;
4
5import 'package:logger/web.dart';
6import 'package:meta/meta.dart';
7
8import '../../channel.dart';
9import '../../exceptions/exception_manager.dart';
10import '../../exceptions/squadron_error.dart';
11import '../../exceptions/squadron_exception.dart';
12import '../../exceptions/task_terminated_exception.dart';
13import '../../exceptions/worker_exception.dart';
14import '../../tokens/_squadron_cancelation_token.dart';
15import '../../utils.dart';
16import '../../worker/worker_message.dart';
17import '../../worker/worker_request.dart';
18import '../../worker/worker_response.dart';
19import '../xplat/_disconnected_channel.dart';
20import '../xplat/_forward_stream_controller.dart';
21import '../xplat/_result_stream.dart';
22import '_typedefs.dart';
23
24part '_channel_forward.dart';
25part '_channel_impl.dart';
26
27// Stub implementations.
28
29/// Starts an [Isolate] using the [entryPoint] and sends a start
30/// [WorkerRequest] with [startArguments]. The future completes after the
31/// worker [Isolate]'s main program has provided the [SendPort] via
32/// [WorkerChannel.connect].
3311Future<Channel> openChannel(
34 EntryPoint entryPoint,
35 ExceptionManager exceptionManager,
36 Logger? logger,
37 List startArguments,
38 PlatformThreadHook? hook,
39) async {
4011 final completer = Completer<_VmChannel>();
41 Channel? channel;
42
4311 void $failure(Object error, [StackTrace? stackTrace]) {
4411 if (!completer.isCompleted) {
456 completer.completeError(SquadronException.from(error, stackTrace));
46 }
47 }
48
4910 void $success(_VmChannel channel) {
5010 if (!completer.isCompleted) {
5110 completer.complete(channel);
52 }
53 }
54
5511 final receiver = vm.ReceivePort();
5611 final exitPort = vm.ReceivePort();
5711 final errorPort = vm.ReceivePort();
58
5922 exitPort.listen((message) {
6022 $failure(SquadronErrorImpl.create('Connection to worker failed'));
616 logger?.t('Isolate terminated with message $message.');
6210 channel?.close();
6311 receiver.close();
6411 errorPort.close();
6511 exitPort.close();
66 });
67
6811 errorPort.listen((message) {
69 SquadronException? error;
70 try {
710 final data = jsonDecode(message[0]);
720 if (data is List) {
730 error = exceptionManager.deserialize(data.cast<String>());
74 }
75 } catch (_) {
76 // not a String representing a SquadronException
77 }
78
790 error ??= WorkerException(
800 message[0],
810 SquadronException.loadStackTrace(message[1]),
82 );
83
840 logger?.d(() => 'Unhandled error from Isolate: ${error?.message}.');
850 $failure(error);
86 });
87
8811 final disconnected = DisconnectedChannel(exceptionManager, logger);
89
9021 receiver.listen((message) {
9110 final response = WorkerResponse.from(message);
9210 if (!response.unwrapInPlace(disconnected)) {
93 return;
94 }
95
9610 final error = response.error;
97 if (error != null) {
983 logger?.e(() => 'Connection to Isolate failed: $error');
992 $failure(error);
10010 } else if (response.endOfStream) {
1011 logger?.w('Disconnecting from Isolate');
1021 channel?.close();
10310 } else if (!completer.isCompleted) {
1043 logger?.t('Connected to Isolate');
105 final platformChannel =
10620 _VmChannel._(response.result, logger, exceptionManager);
107 channel = platformChannel;
10810 $success(platformChannel);
109 } else {
1100 logger?.e(() => 'Unexpected response: $response');
111 }
112 });
113
11422 final startRequest = WorkerRequest.start(receiver.sendPort, startArguments);
11511 startRequest.wrapInPlace();
11611 final isolate = await vm.Isolate.spawn(
117 entryPoint,
118 startRequest,
119 errorsAreFatal: false,
12011 onExit: exitPort.sendPort,
12111 onError: errorPort.sendPort,
122 );
123
124 try {
12511 final channel = await completer.future;
12610 channel._thread = isolate;
127 if (hook != null) {
1282 await hook.call(isolate);
129 }
1303 logger?.t('Created Isolate');
131 return channel;
132 } catch (ex) {
1330 logger?.e(() => 'Connection to Isolate failed: $ex');
1343 isolate.kill(priority: vm.Isolate.beforeNextEvent);
135 rethrow;
136 }
137}
138
1396@internal
140int getActiveConnections(Channel channel) =>
14118 (channel is _VmChannel) ? channel._activeConnections.length : 0;
142
1432@internal
144void terminateChannel(Channel channel, TaskTerminatedException ex) {
1452 if (channel is _VmChannel) {
1464 channel._thread?.kill(priority: vm.Isolate.immediate);
1472 final pendingConnections = channel._activeConnections;
1484 for (var c in pendingConnections) {
1494 c.subscription?.cancel();
1502 c.safeAddError(ex);
1512 c.close();
152 }
153 }
154}
155
156/// Creates a [_VmChannel] from a [SendPort].
1573Channel? deserialize(
158 PlatformChannel? channelInfo, [
159 Logger? logger,
160 ExceptionManager? exceptionManager,
161]) =>
162 (channelInfo == null)
163 ? null
1643 : _VmChannel._(
165 channelInfo,
166 logger,
1673 exceptionManager ?? ExceptionManager(),
168 );
Choose Features