LCOV - code coverage report

Current view
top level - src/_impl/native - _channel.dart
Test
lcov.info
Date
2025-03-26
Legend
Lines
hit
not hit
Branches
taken
not taken
# not executed
HitTotalCoverage
Lines546484.4%
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 '../../worker/worker_request.dart';
16import '../../worker/worker_response.dart';
17import '../xplat/_disconnected_channel.dart';
18import '../xplat/_forward_stream_controller.dart';
19import '../xplat/_result_stream.dart';
20import '_typedefs.dart';
21
22part '_channel_forward.dart';
23part '_channel_impl.dart';
24
25// Stub implementations.
26
27/// Starts an [Isolate] using the [entryPoint] and sends a start
28/// [WorkerRequest] with [startArguments]. The future completes after the
29/// worker [Isolate]'s main program has provided the [SendPort] via
30/// [WorkerChannel.connect].
3111Future<Channel> openChannel(
32 EntryPoint entryPoint,
33 ExceptionManager exceptionManager,
34 Logger? logger,
35 List startArguments,
36 PlatformThreadHook? hook,
37) async {
3811 final completer = Completer<_VmChannel>();
39 Channel? channel;
40
4111 void failure(Object error, [StackTrace? stackTrace]) {
4211 if (!completer.isCompleted) {
436 completer.completeError(SquadronException.from(error, stackTrace));
44 }
45 }
46
4710 void success(_VmChannel channel) {
4810 if (!completer.isCompleted) {
4910 completer.complete(channel);
50 }
51 }
52
5311 final receiver = vm.ReceivePort();
5411 final exitPort = vm.ReceivePort();
5511 final errorPort = vm.ReceivePort();
56
5722 exitPort.listen((message) {
5822 failure(SquadronErrorImpl.create('Connection to worker failed'));
596 logger?.t('Isolate terminated with message $message.');
6010 channel?.close();
6111 receiver.close();
6211 errorPort.close();
6311 exitPort.close();
64 });
65
6611 errorPort.listen((message) {
67 SquadronException? error;
68 try {
690 final data = jsonDecode(message[0]);
700 if (data is List) {
710 error = exceptionManager.deserialize(data.cast<String>());
72 }
73 } catch (_) {
74 // not a String representing a SquadronException
75 }
76
770 error ??= WorkerException(
780 message[0],
790 SquadronException.loadStackTrace(message[1]),
80 );
81
820 logger?.d(() => 'Unhandled error from Isolate: ${error?.message}.');
830 failure(error);
84 });
85
8611 final disconnected = DisconnectedChannel(exceptionManager, logger);
87
8821 receiver.listen((message) {
8910 final response = WorkerResponseImpl.from(message);
9010 if (!response.unwrapInPlace(disconnected)) {
91 return;
92 }
93
9410 final error = response.error;
95 if (error != null) {
963 logger?.e(() => 'Connection to Isolate failed: $error');
972 failure(error);
9810 } else if (response.endOfStream) {
991 logger?.w('Disconnecting from Isolate');
1001 channel?.close();
10110 } else if (!completer.isCompleted) {
1023 logger?.t('Connected to Isolate');
103 final platformChannel =
10420 _VmChannel._(response.result, logger, exceptionManager);
105 channel = platformChannel;
10610 success(platformChannel);
107 } else {
1080 logger?.e(() => 'Unexpected response: $response');
109 }
110 });
111
11222 final startRequest = WorkerRequest.start(receiver.sendPort, startArguments);
11311 startRequest.wrapInPlace();
11411 final isolate = await vm.Isolate.spawn(
115 entryPoint,
116 startRequest,
117 errorsAreFatal: false,
11811 onExit: exitPort.sendPort,
11911 onError: errorPort.sendPort,
120 );
121
122 try {
12311 final channel = await completer.future;
12410 channel._thread = isolate;
125 if (hook != null) {
1262 await hook.call(isolate);
127 }
1283 logger?.t('Created Isolate');
129 return channel;
130 } catch (ex) {
1310 logger?.e(() => 'Connection to Isolate failed: $ex');
1323 isolate.kill(priority: vm.Isolate.beforeNextEvent);
133 rethrow;
134 }
135}
136
1371@internal
138void terminateChannel(Channel channel, TaskTerminatedException ex) {
1391 if (channel is _VmChannel) {
1402 channel._thread?.kill(priority: vm.Isolate.immediate);
1411 final pendingConnections = channel._activeConnections;
1422 for (var c in pendingConnections) {
1432 c.subscription?.cancel();
1441 c.addError(ex);
1451 c.close();
146 }
147 }
148}
149
150/// Creates a [_VmChannel] from a [SendPort].
1513Channel? deserialize(
152 PlatformChannel? channelInfo, [
153 Logger? logger,
154 ExceptionManager? exceptionManager,
155]) =>
156 (channelInfo == null)
157 ? null
1583 : _VmChannel._(
159 channelInfo,
160 logger,
1613 exceptionManager ?? ExceptionManager(),
162 );
Choose Features