LCOV - code coverage report

Current view
top level - src/_impl/native - _channel.dart
Test
lcov.info
Date
2026-02-21
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_request.dart';
17import '../../worker/worker_response.dart';
18import '../xplat/_disconnected_channel.dart';
19import '../xplat/_forward_stream_controller.dart';
20import '../xplat/_result_stream.dart';
21import '_typedefs.dart';
22
23part '_channel_forward.dart';
24part '_channel_impl.dart';
25
26// Stub implementations.
27
28/// Starts an [Isolate] using the [entryPoint] and sends a start
29/// [WorkerRequest] with [startArguments]. The future completes after the
30/// worker [Isolate]'s main program has provided the [SendPort] via
31/// [WorkerChannel.connect].
3211Future<Channel> openChannel(
33 EntryPoint entryPoint,
34 ExceptionManager exceptionManager,
35 Logger? logger,
36 List startArguments,
37 PlatformThreadHook? hook,
38) async {
3911 final completer = Completer<_VmChannel>();
40 Channel? channel;
41
4211 void $failure(Object error, [StackTrace? stackTrace]) {
4311 if (!completer.isCompleted) {
446 completer.completeError(SquadronException.from(error, stackTrace));
45 }
46 }
47
4810 void $success(_VmChannel channel) {
4910 if (!completer.isCompleted) {
5010 completer.complete(channel);
51 }
52 }
53
5411 final receiver = vm.ReceivePort();
5511 final exitPort = vm.ReceivePort();
5611 final errorPort = vm.ReceivePort();
57
5822 exitPort.listen((message) {
5922 $failure(SquadronErrorImpl.create('Connection to worker failed'));
606 logger?.t('Isolate terminated with message $message.');
6110 channel?.close();
6211 receiver.close();
6311 errorPort.close();
6411 exitPort.close();
65 });
66
6711 errorPort.listen((message) {
68 SquadronException? error;
69 try {
700 final data = jsonDecode(message[0]);
710 if (data is List) {
720 error = exceptionManager.deserialize(data.cast<String>());
73 }
74 } catch (_) {
75 // not a String representing a SquadronException
76 }
77
780 error ??= WorkerException(
790 message[0],
800 SquadronException.loadStackTrace(message[1]),
81 );
82
830 logger?.d(() => 'Unhandled error from Isolate: ${error?.message}.');
840 $failure(error);
85 });
86
8711 final disconnected = DisconnectedChannel(exceptionManager, logger);
88
8921 receiver.listen((message) {
9010 final response = WorkerResponse.from(message);
9110 if (!response.unwrapInPlace(disconnected)) {
92 return;
93 }
94
9510 final error = response.error;
96 if (error != null) {
973 logger?.e(() => 'Connection to Isolate failed: $error');
982 $failure(error);
9910 } else if (response.endOfStream) {
1001 logger?.w('Disconnecting from Isolate');
1011 channel?.close();
10210 } else if (!completer.isCompleted) {
1033 logger?.t('Connected to Isolate');
104 final platformChannel =
10520 _VmChannel._(response.result, logger, exceptionManager);
106 channel = platformChannel;
10710 $success(platformChannel);
108 } else {
1090 logger?.e(() => 'Unexpected response: $response');
110 }
111 });
112
11322 final startRequest = WorkerRequest.start(receiver.sendPort, startArguments);
11411 startRequest.wrapInPlace();
11511 final isolate = await vm.Isolate.spawn(
116 entryPoint,
117 startRequest,
118 errorsAreFatal: false,
11911 onExit: exitPort.sendPort,
12011 onError: errorPort.sendPort,
121 );
122
123 try {
12411 final channel = await completer.future;
12510 channel._thread = isolate;
126 if (hook != null) {
1272 await hook.call(isolate);
128 }
1293 logger?.t('Created Isolate');
130 return channel;
131 } catch (ex) {
1320 logger?.e(() => 'Connection to Isolate failed: $ex');
1333 isolate.kill(priority: vm.Isolate.beforeNextEvent);
134 rethrow;
135 }
136}
137
1386@internal
139int getActiveConnections(Channel channel) =>
14018 (channel is _VmChannel) ? channel._activeConnections.length : 0;
141
1422@internal
143void terminateChannel(Channel channel, TaskTerminatedException ex) {
1442 if (channel is _VmChannel) {
1454 channel._thread?.kill(priority: vm.Isolate.immediate);
1462 final pendingConnections = channel._activeConnections;
1474 for (var c in pendingConnections) {
1484 c.subscription?.cancel();
1492 c.safeAddError(ex);
1502 c.close();
151 }
152 }
153}
154
155/// Creates a [_VmChannel] from a [SendPort].
1563Channel? deserialize(
157 PlatformChannel? channelInfo, [
158 Logger? logger,
159 ExceptionManager? exceptionManager,
160]) =>
161 (channelInfo == null)
162 ? null
1633 : _VmChannel._(
164 channelInfo,
165 logger,
1663 exceptionManager ?? ExceptionManager(),
167 );
Choose Features