run method

Future<void> run(
  1. Iterable<String> args
)

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();
}