LCOV - code coverage report

Current view
top level - src/_impl/native - _channel.dart
Test
lcov.info
Date
2026-11-07
Legend
Lines
hit
not hit
Branches
taken
not taken
# not executed
HitTotalCoverage
Lines576785.1%
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 '../../build_options.dart';
9import '../../channel.dart';
10import '../../exceptions/exception_manager.dart';
11import '../../exceptions/squadron_error.dart';
12import '../../exceptions/squadron_exception.dart';
13import '../../exceptions/task_terminated_exception.dart';
14import '../../exceptions/worker_exception.dart';
15import '../../tokens/_squadron_cancelation_token.dart';
16import '../../utils.dart';
17import '../../worker/worker_message.dart';
18import '../../worker/worker_request.dart';
19import '../../worker/worker_response.dart';
20import '../xplat/_disconnected_channel.dart';
21import '../xplat/_forward_stream_controller.dart';
22import '../xplat/_result_stream.dart';
23import '_typedefs.dart';
24
25part '_channel_forward.dart';
26part '_channel_impl.dart';
27
28// Stub implementations.
29
30/// Starts an [Isolate] using the [entryPoint] and sends a start
31/// [WorkerRequest] with [startArguments]. The future completes after the
32/// worker [Isolate]'s main program has provided the [SendPort] via
33/// [WorkerChannel.connect].
341Future<Channel> openChannel(
35 EntryPoint entryPoint,
36 ExceptionManager exceptionManager,
37 Logger? logger,
38 List startArguments,
39 PlatformThreadHook? hook,
40) async {
41 if (!BuildOptions.withInternalLogging) {
42 logger = null;
43 }
44
451 final completer = Completer<_VmChannel>();
46 Channel? channel;
47
481 void $failure(Object error, [StackTrace? stackTrace]) {
491 if (!completer.isCompleted) {
502 completer.completeError(SquadronException.from(error, stackTrace));
51 }
52 }
53
541 void $success(_VmChannel channel) {
551 if (!completer.isCompleted) {
561 completer.complete(channel);
57 }
58 }
59
601 final receiver = vm.ReceivePort();
611 final exitPort = vm.ReceivePort();
621 final errorPort = vm.ReceivePort();
63
642 exitPort.listen((message) {
652 $failure(SquadronErrorImpl.create('Connection to worker failed'));
662 logger?.t('Isolate terminated with message $message.');
671 channel?.close();
681 receiver.close();
691 errorPort.close();
701 exitPort.close();
71 });
72
731 errorPort.listen((message) {
74 SquadronException? error;
75 try {
760 final data = jsonDecode(message[0]);
770 if (data is List) {
780 error = exceptionManager.deserialize(data.cast<String>());
79 }
80 } catch (_) {
81 // not a String representing a SquadronException
82 }
83
840 error ??= WorkerException(
850 message[0],
860 SquadronException.loadStackTrace(message[1]),
87 );
88
890 logger?.d(() => 'Unhandled error from Isolate: ${error?.message}.');
900 $failure(error);
91 });
92
931 final disconnected = DisconnectedChannel(exceptionManager, logger);
94
952 receiver.listen((message) {
961 final response = WorkerResponse.from(message);
971 if (!response.unwrapInPlace(disconnected)) {
98 return;
99 }
100
1011 final error = response.error;
102 if (error != null) {
1033 logger?.e(() => 'Connection to Isolate failed: $error');
1041 $failure(error);
1051 } else if (response.endOfStream) {
1061 logger?.w('Disconnecting from Isolate');
1071 channel?.close();
1081 } else if (!completer.isCompleted) {
1091 logger?.t('Connected to Isolate');
110 final platformChannel =
1112 _VmChannel._(response.result, logger, exceptionManager);
112 channel = platformChannel;
1131 $success(platformChannel);
114 } else {
1150 logger?.e(() => 'Unexpected response: $response');
116 }
117 });
118
1192 final startRequest = WorkerRequest.start(receiver.sendPort, startArguments);
1201 startRequest.wrapInPlace();
1211 final isolate = await vm.Isolate.spawn(
122 entryPoint,
123 startRequest,
124 errorsAreFatal: false,
1251 onExit: exitPort.sendPort,
1261 onError: errorPort.sendPort,
127 );
128
129 try {
1301 final channel = await completer.future;
1311 channel._thread = isolate;
132 if (hook != null) {
1331 final res = hook.call(isolate);
1341 if (res is Future) await res;
135 }
1361 logger?.t('Created Isolate');
137 return channel;
138 } catch (ex) {
1390 logger?.e(() => 'Connection to Isolate failed: $ex');
1401 isolate.kill(priority: vm.Isolate.beforeNextEvent);
141 rethrow;
142 }
143}
144
1451@internal
146int getActiveConnections(Channel channel) =>
1473 (channel is _VmChannel) ? channel._activeConnections.length : 0;
148
1491@internal
150void terminateChannel(Channel channel, TaskTerminatedException ex) {
1511 if (channel is _VmChannel) {
1522 channel._thread?.kill(priority: vm.Isolate.immediate);
1531 final pendingConnections = channel._activeConnections;
1542 for (var c in pendingConnections) {
1552 c.subscription?.cancel();
1561 c.safeAddError(ex);
1571 c.close();
158 }
159 }
160}
161
162/// Creates a [_VmChannel] from a [SendPort].
1631Channel? deserialize(
164 PlatformChannel? channelInfo, [
165 Logger? logger,
166 ExceptionManager? exceptionManager,
167]) =>
168 (channelInfo == null)
169 ? null
1701 : _VmChannel._(
171 channelInfo,
172 logger,
1731 exceptionManager ?? ExceptionManager(),
174 );
Choose Features