run method
Implementation
Future<void> run(Iterable<String> args) async {
ReceivePort? exitPort;
ReceivePort? errorPort;
ReceivePort? messagePort;
StreamSubscription<dynamic>? errorListener;
int? scriptExitCode;
final root = await rootOf(initialDirectory);
final file = await root.getInternalRevaliFile(kernelFile);
if (!await file.exists()) {
throw StateError('Script file does not exist');
}
var tryCount = 0;
var succeeded = false;
while (tryCount < 2 && !succeeded) {
tryCount++;
exitPort?.close();
errorPort?.close();
messagePort?.close();
await errorListener?.cancel();
exitPort = ReceivePort();
errorPort = ReceivePort();
messagePort = ReceivePort();
errorListener = errorPort.listen((e) {
e = e as List<Object?>;
final error = e[0] ?? TypeError();
final trace = Trace.parse(e[1] as String? ?? '').terse;
logger
..err('Error in script:\n$error')
..detail(trace.toString());
if (scriptExitCode == 0) scriptExitCode = 1;
});
try {
await Isolate.spawnUri(
Uri.file(file.path),
switch (args) {
List() => args,
_ => args.toList(),
},
messagePort.sendPort,
onExit: exitPort.sendPort,
onError: errorPort.sendPort,
);
succeeded = true;
} on IsolateSpawnException catch (e) {
if (tryCount > 1) {
logger.err(
'Failed to spawn build script after retry. '
'This is likely due to a misconfigured construct definition.\n'
'$e',
);
messagePort.sendPort.send(1);
exitPort.sendPort.send(null);
} else {
logger.err(
'Error spawning build script isolate, '
'this is likely due to a Dart '
'SDK update. Deleting precompiled script and retrying...',
);
}
try {
await file.delete();
} catch (e) {
logger.err('Failed to delete precompiled script: $e');
}
}
}
StreamSubscription<dynamic>? exitCodeListener;
exitCodeListener = messagePort!.listen((isolateExitCode) {
if (isolateExitCode is int) {
scriptExitCode = isolateExitCode;
} else {
throw StateError(
'Bad response from isolate, expected an exit code but got '
'$isolateExitCode');
}
exitCodeListener!.cancel();
exitCodeListener = null;
});
await exitPort?.first;
await errorListener?.cancel();
await exitCodeListener?.cancel();
}