// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:process/process.dart';
import 'package:uuid/uuid.dart';

import 'artifacts.dart';
import 'base/common.dart';
import 'base/config.dart';
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'base/platform.dart';
import 'base/process.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'bundle.dart';
import 'convert.dart';
import 'dart/package_map.dart';

/// Opt-in changes to the dart compilers.
const kDartCompilerExperiments = <String>[];

/// The target model describes the set of core libraries that are available within
/// the SDK.
class TargetModel {
  /// Parse a [TargetModel] from a raw string.
  ///
  /// Throws an exception if passed a value other than 'flutter',
  /// 'flutter_runner', 'vm', or 'dartdevc'.
  factory TargetModel(String rawValue) {
    return switch (rawValue) {
      'flutter' => flutter,
      'flutter_runner' => flutterRunner,
      'vm' => vm,
      'dartdevc' => dartdevc,
      _ => throw Exception('Unexpected target model $rawValue'),
    };
  }

  const TargetModel._(this._value);

  /// The Flutter patched Dart SDK.
  static const flutter = TargetModel._('flutter');

  /// The Fuchsia patched SDK.
  static const flutterRunner = TargetModel._('flutter_runner');

  /// The Dart VM.
  static const vm = TargetModel._('vm');

  /// The development compiler for JavaScript.
  static const dartdevc = TargetModel._('dartdevc');

  final String _value;

  @override
  String toString() => _value;

  /// Infers the appropriate [TargetModel] from a given [TargetPlatform].
  static TargetModel fromTargetPlatform(TargetPlatform? platform) {
    return switch (platform) {
      TargetPlatform.web_javascript => TargetModel.dartdevc,
      TargetPlatform.fuchsia_arm64 || TargetPlatform.fuchsia_x64 => TargetModel.flutterRunner,
      _ => TargetModel.flutter,
    };
  }
}

class CompilerOutput {
  const CompilerOutput(
    this.outputFilename,
    this.errorCount,
    this.sources, {
    this.expressionData,
    this.errorMessage,
  });

  final String outputFilename;
  final int errorCount;
  final List<Uri> sources;

  /// This field is only non-null for expression compilation requests.
  final Uint8List? expressionData;

  /// This field is only non-null when a compilation error was encountered.
  final String? errorMessage;
}

enum StdoutState { CollectDiagnostic, CollectDependencies }

/// Handles stdin/stdout communication with the frontend server.
class StdoutHandler {
  StdoutHandler({required this._logger, required this._fileSystem}) {
    reset();
  }

  final Logger _logger;
  final FileSystem _fileSystem;

  String? boundaryKey;
  StdoutState state = StdoutState.CollectDiagnostic;
  Completer<CompilerOutput?>? compilerOutput;
  final sources = <Uri>[];

  var _suppressCompilerMessages = false;
  var _expectSources = true;
  var _readFile = false;
  var _errorBuffer = StringBuffer();

  void handler(String message) {
    const kResultPrefix = 'result ';
    if (boundaryKey == null && message.startsWith(kResultPrefix)) {
      boundaryKey = message.substring(kResultPrefix.length);
      return;
    }
    final String? messageBoundaryKey = boundaryKey;
    if (messageBoundaryKey != null && message.startsWith(messageBoundaryKey)) {
      if (_expectSources) {
        if (state == StdoutState.CollectDiagnostic) {
          state = StdoutState.CollectDependencies;
          return;
        }
      }
      if (message.length <= messageBoundaryKey.length) {
        compilerOutput?.complete();
        return;
      }
      final int spaceDelimiter = message.lastIndexOf(' ');
      final String fileName = message.substring(messageBoundaryKey.length + 1, spaceDelimiter);
      final int errorCount = int.parse(message.substring(spaceDelimiter + 1).trim());
      Uint8List? expressionData;
      if (_readFile) {
        expressionData = _fileSystem.file(fileName).readAsBytesSync();
      }
      final output = CompilerOutput(
        fileName,
        errorCount,
        sources,
        expressionData: expressionData,
        errorMessage: _errorBuffer.isNotEmpty ? _errorBuffer.toString() : null,
      );
      compilerOutput?.complete(output);
      return;
    }
    switch (state) {
      case StdoutState.CollectDiagnostic when _suppressCompilerMessages:
        _logger.printTrace(message);
        _errorBuffer.writeln(message);
      case StdoutState.CollectDiagnostic:
        _logger.printError(message);
        _errorBuffer.writeln(message);
      case StdoutState.CollectDependencies:
        switch (message[0]) {
          case '+':
            sources.add(Uri.parse(message.substring(1)));
          case '-':
            sources.remove(Uri.parse(message.substring(1)));
          default:
            _logger.printTrace('Unexpected prefix for $message uri - ignoring');
        }
    }
  }

  // This is needed to get ready to process next compilation result output,
  // with its own boundary key and new completer.
  void reset({
    bool suppressCompilerMessages = false,
    bool expectSources = true,
    bool readFile = false,
  }) {
    boundaryKey = null;
    compilerOutput = Completer<CompilerOutput?>();
    _suppressCompilerMessages = suppressCompilerMessages;
    _expectSources = expectSources;
    _readFile = readFile;
    state = StdoutState.CollectDiagnostic;
    _errorBuffer = StringBuffer();
  }
}

/// List the preconfigured build options for a given build mode.
List<String> buildModeOptions(BuildMode mode, List<String> dartDefines) => switch (mode) {
  BuildMode.debug => <String>[
    // These checks allow the CLI to override the value of this define for unit
    // testing the framework.
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.profile')))
      '-Ddart.vm.profile=false',
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.product')))
      '-Ddart.vm.product=false',
    '--enable-asserts',
  ],
  BuildMode.profile => <String>[
    // These checks allow the CLI to override the value of this define for
    // benchmarks with most timeline traces disabled.
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.profile')))
      '-Ddart.vm.profile=true',
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.product')))
      '-Ddart.vm.product=false',
    '--delete-tostring-package-uri=dart:ui',
    '--delete-tostring-package-uri=package:flutter',
    ...kDartCompilerExperiments,
  ],
  BuildMode.release => <String>[
    '-Ddart.vm.profile=false',
    '-Ddart.vm.product=true',
    '--delete-tostring-package-uri=dart:ui',
    '--delete-tostring-package-uri=package:flutter',
    ...kDartCompilerExperiments,
  ],
  _ => throw Exception('Unknown BuildMode: $mode'),
};

final _extraFrontEndOptionsFilterSet = <String>{
  // Don't allow for users to pass --include-unsupported-platform-library-stubs to bypass
  // unsupported library compile time errors as this flag is only safe for use by developer
  // tooling.
  '--include-unsupported-platform-library-stubs',
};

Iterable<String>? _filterExtraFrontEndOptions(List<String>? options) =>
    options?.where((e) => !_extraFrontEndOptionsFilterSet.contains(e));

/// A compiler interface for producing single (non-incremental) kernel files.
class KernelCompiler {
  KernelCompiler({
    required FileSystem fileSystem,
    required Logger logger,
    required this._processManager,
    required this._artifacts,
    required this._fileSystemRoots,
    this._fileSystemScheme,
    @visibleForTesting StdoutHandler? stdoutHandler,
  }) : _logger = logger,
       _fileSystem = fileSystem,
       _stdoutHandler = stdoutHandler ?? StdoutHandler(logger: logger, fileSystem: fileSystem);

  final FileSystem _fileSystem;
  final Artifacts _artifacts;
  final ProcessManager _processManager;
  final Logger _logger;
  final String? _fileSystemScheme;
  final List<String> _fileSystemRoots;
  final StdoutHandler _stdoutHandler;

  Future<CompilerOutput?> compile({
    required String sdkRoot,
    String? mainPath,
    String? outputFilePath,
    String? depFilePath,
    TargetModel targetModel = TargetModel.flutter,
    bool linkPlatformKernelIn = false,
    bool aot = false,
    String? frontendServerStarterPath,
    List<String>? extraFrontEndOptions,
    List<String>? fileSystemRoots,
    String? fileSystemScheme,
    String? initializeFromDill,
    String? platformDill,
    Directory? buildDir,
    String? targetOS,
    bool checkDartPluginRegistry = false,
    required String? packagesPath,
    required BuildMode buildMode,
    required bool trackWidgetCreation,
    required List<String> dartDefines,
    required PackageConfig packageConfig,
    String? nativeAssets,
  }) async {
    final TargetPlatform? platform = targetModel == TargetModel.dartdevc
        ? TargetPlatform.web_javascript
        : null;
    // This is a URI, not a file path, so the forward slash is correct even on Windows.
    if (!sdkRoot.endsWith('/')) {
      sdkRoot = '$sdkRoot/';
    }
    String? mainUri;
    if (mainPath != null) {
      final File mainFile = _fileSystem.file(mainPath);
      final Uri mainFileUri = mainFile.uri;
      if (packagesPath != null) {
        mainUri = packageConfig.toPackageUriForWorkspace(mainFileUri)?.toString();
      }
      mainUri ??= toMultiRootPath(
        mainFileUri,
        _fileSystemScheme,
        _fileSystemRoots,
        _fileSystem.path.separator == r'\',
      );
    }
    if (outputFilePath != null && !_fileSystem.isFileSync(outputFilePath)) {
      _fileSystem.file(outputFilePath).createSync(recursive: true);
    }

    // Check if there's a Dart plugin registrant.
    // This is contained in the file `dart_plugin_registrant.dart` under `.dart_tools/flutter_build/`.
    final File? dartPluginRegistrant = checkDartPluginRegistry
        ? buildDir?.parent.childFile('dart_plugin_registrant.dart')
        : null;

    String? dartPluginRegistrantUri;
    if (dartPluginRegistrant != null && dartPluginRegistrant.existsSync()) {
      final Uri dartPluginRegistrantFileUri = dartPluginRegistrant.uri;
      dartPluginRegistrantUri =
          packageConfig.toPackageUriForWorkspace(dartPluginRegistrantFileUri)?.toString() ??
          toMultiRootPath(
            dartPluginRegistrantFileUri,
            _fileSystemScheme,
            _fileSystemRoots,
            _fileSystem.path.separator == r'\',
          );
    }

    final List<String> commandToStartFrontendServer;
    if (frontendServerStarterPath != null && frontendServerStarterPath.isNotEmpty) {
      final String engineDartPath = _artifacts.getArtifactPath(
        Artifact.engineDartBinary,
        platform: platform,
      );
      if (!_processManager.canRun(engineDartPath)) {
        throwToolExit('Unable to find Dart binary at $engineDartPath');
      }
      commandToStartFrontendServer = <String>[engineDartPath, frontendServerStarterPath];
    } else {
      final String engineDartAotRuntimePath = _artifacts.getArtifactPath(
        Artifact.engineDartAotRuntime,
        platform: platform,
      );
      if (!_processManager.canRun(engineDartAotRuntimePath)) {
        throwToolExit('Unable to find dartaotruntime binary at $engineDartAotRuntimePath');
      }
      commandToStartFrontendServer = <String>[
        engineDartAotRuntimePath,
        _artifacts.getArtifactPath(
          Artifact.frontendServerSnapshotForEngineDartSdk,
          platform: platform,
        ),
      ];
    }

    final List<String> command =
        commandToStartFrontendServer +
        <String>[
          '--sdk-root',
          sdkRoot,
          '--target=$targetModel',
          '--no-print-incremental-dependencies',
          for (final Object dartDefine in dartDefines) '-D$dartDefine',
          ...buildModeOptions(buildMode, dartDefines),
          if (trackWidgetCreation) '--track-creation-locations',
          if (!linkPlatformKernelIn) '--no-link-platform',
          if (aot) ...<String>[
            '--aot',
            '--tfa',
            // The --target-os flag only makes sense for whole program compilation.
            if (targetOS != null) ...<String>['--target-os', targetOS],
          ],
          if (packagesPath != null) ...<String>['--packages', packagesPath],
          if (outputFilePath != null) ...<String>['--output-dill', outputFilePath],
          if (depFilePath != null &&
              (fileSystemRoots == null || fileSystemRoots.isEmpty)) ...<String>[
            '--depfile',
            depFilePath,
          ],
          if (fileSystemRoots != null)
            for (final String root in fileSystemRoots) ...<String>['--filesystem-root', root],
          if (fileSystemScheme != null) ...<String>['--filesystem-scheme', fileSystemScheme],
          if (initializeFromDill != null) ...<String>[
            '--incremental',
            '--initialize-from-dill',
            initializeFromDill,
          ],
          if (platformDill != null) ...<String>['--platform', platformDill],
          if (dartPluginRegistrantUri != null) ...<String>[
            '--source',
            dartPluginRegistrantUri,
            '--source',
            'package:flutter/src/dart_plugin_registrant.dart',
            '-Dflutter.dart_plugin_registrant=$dartPluginRegistrantUri',
          ],
          if (nativeAssets != null) ...<String>['--native-assets', nativeAssets],
          // See: https://github.com/flutter/flutter/issues/103994
          '--verbosity=error',
          ...?_filterExtraFrontEndOptions(extraFrontEndOptions),
          mainUri ?? '--native-assets-only',
        ];

    _logger.printTrace(command.join(' '));
    final Process server = await _processManager.start(command);

    // Use permissive decoder for compiler stderr which may contain invalid UTF-8
    server.stderr.transform<String>(utf8AllowMalformed.decoder).listen(_logger.printError);
    server.stdout.transform(utf8LineDecoder).listen(_stdoutHandler.handler);
    final int exitCode = await server.exitCode;
    if (exitCode == 0) {
      return _stdoutHandler.compilerOutput?.future;
    }
    return null;
  }
}

/// Class that allows to serialize compilation requests to the compiler.
abstract class _CompilationRequest {
  _CompilationRequest(this.completer);

  Completer<CompilerOutput?> completer;

  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler);

  Future<void> run(DefaultResidentCompiler compiler) async {
    completer.complete(await _run(compiler));
  }
}

class _RecompileRequest extends _CompilationRequest {
  _RecompileRequest(
    super.completer,
    this.mainUri,
    this.invalidatedFiles,
    this.outputPath,
    this.packageConfig,
    this.suppressErrors, {
    this.additionalSourceUri,
    this.nativeAssetsYamlUri,
    required this.recompileRestart,
  });

  Uri mainUri;
  List<Uri>? invalidatedFiles;
  String outputPath;
  PackageConfig packageConfig;
  bool suppressErrors;
  final Uri? additionalSourceUri;
  final Uri? nativeAssetsYamlUri;
  final bool recompileRestart;

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async => compiler._recompile(this);
}

class _CompileExpressionRequest extends _CompilationRequest {
  _CompileExpressionRequest(
    super.completer,
    this.expression,
    this.definitions,
    this.definitionTypes,
    this.typeDefinitions,
    this.typeBounds,
    this.typeDefaults,
    this.libraryUri,
    this.klass,
    this.method,
    this.isStatic,
  );

  String expression;
  List<String>? definitions;
  List<String>? definitionTypes;
  List<String>? typeDefinitions;
  List<String>? typeBounds;
  List<String>? typeDefaults;
  String? libraryUri;
  String? klass;
  String? method;
  bool isStatic;

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
      compiler._compileExpression(this);
}

class _CompileExpressionToJsRequest extends _CompilationRequest {
  _CompileExpressionToJsRequest(
    super.completer,
    this.libraryUri,
    this.scriptUri,
    this.line,
    this.column,
    this.jsModules,
    this.jsFrameValues,
    this.moduleName,
    this.expression,
  );

  final String? libraryUri;
  final String? scriptUri;
  final int line;
  final int column;
  final Map<String, String>? jsModules;
  final Map<String, String>? jsFrameValues;
  final String? moduleName;
  final String? expression;

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
      compiler._compileExpressionToJs(this);
}

class _RejectRequest extends _CompilationRequest {
  _RejectRequest(super.completer);

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async => compiler._reject();
}

ResidentCompilerFactory get residentCompilerFactory =>
    context.get<ResidentCompilerFactory>() ?? const ResidentCompilerFactory();

/// A factory for generating [ResidentCompiler] instances.
class ResidentCompilerFactory {
  const ResidentCompilerFactory();

  ResidentCompiler create({
    required TargetPlatform targetPlatform,
    required BuildInfo buildInfo,
    required Logger logger,
    required ProcessManager processManager,
    required Artifacts artifacts,
    required Platform platform,
    required FileSystem fileSystem,
    required ShutdownHooks shutdownHooks,
    required Config config,
    bool testCompilation = false,
    TargetModel? targetModelOverride,
  }) {
    String sdkRoot = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: targetPlatform,
      mode: buildInfo.mode,
    );
    String? platformDillPath;
    String? librariesSpec;
    TargetModel targetModel = targetModelOverride ?? .flutter;

    // Configure the compiler to target the DDC runtime.
    if (targetPlatform case .web_javascript) {
      sdkRoot = artifacts.getHostArtifact(HostArtifact.flutterWebSdk).path;
      targetModel = .dartdevc;

      const platformDillName = 'ddc_outline.dill';
      platformDillPath = fileSystem
          .file(
            fileSystem.path.join(
              artifacts.getHostArtifact(.webPlatformKernelFolder).path,
              platformDillName,
            ),
          )
          .absolute
          .uri
          .toString();

      librariesSpec = fileSystem
          .file(artifacts.getHostArtifact(.flutterWebLibrariesJson))
          .uri
          .toString();

      buildInfo = buildInfo.copyWith(
        // Override the filesystem scheme so that the frontend_server can find
        // the generated entrypoint code.
        fileSystemScheme: 'org-dartlang-app',
        extraFrontEndOptions: [
          ...buildInfo.extraFrontEndOptions,
          if (buildInfo.webEnableHotReload)
          // These flags are only valid to be passed when compiling with DDC.
          ...<String>['--dartdevc-canary', '--dartdevc-module-format=ddc'],
        ],
      );
    } else {
      if (targetPlatform case .fuchsia_arm64 || .fuchsia_x64) {
        targetModel = .flutterRunner;
      }
      buildInfo = buildInfo.copyWith(
        extraFrontEndOptions: [
          ...buildInfo.extraFrontEndOptions,
          '--enable-experiment=alternative-invalidation-strategy',
        ],
      );
    }

    return DefaultResidentCompiler(
      sdkRoot,
      buildInfo: buildInfo,
      logger: logger,
      processManager: processManager,
      artifacts: artifacts,
      platform: platform,
      fileSystem: fileSystem,
      shutdownHooks: shutdownHooks,
      config: config,
      targetModel: targetModel,
      platformDill: platformDillPath,
      librariesSpec: librariesSpec,
      testCompilation: testCompilation,
    );
  }
}

/// Wrapper around incremental frontend server compiler, that communicates with
/// server via stdin/stdout.
///
/// The wrapper is intended to stay resident in memory as user changes, reloads,
/// restarts the Flutter app.
abstract interface class ResidentCompiler {
  // TODO(zanderso): find a better way to configure additional file system
  // roots from the runner.
  // See: https://github.com/flutter/flutter/issues/50494
  void addFileSystemRoot(String root);

  /// If invoked for the first time, it compiles the Dart script identified by
  /// [mainUri], [invalidatedFiles] list is ignored.
  /// On successive runs [invalidatedFiles] indicates which files need to be
  /// recompiled.
  ///
  /// Binary file name is returned if compilation was successful, otherwise
  /// null is returned.
  ///
  /// If [checkDartPluginRegistry] is true, it is the caller's responsibility
  /// to ensure that the generated registrant file has been updated such that
  /// it is wrapping [mainUri].
  ///
  /// If [recompileRestart] is true, uses the `recompile-restart` instruction
  /// intended for a hot restart instead.
  Future<CompilerOutput?> recompile(
    Uri mainUri,
    List<Uri>? invalidatedFiles, {
    required String outputPath,
    required PackageConfig packageConfig,
    required FileSystem fs,
    String? projectRootPath,
    bool suppressErrors = false,
    bool checkDartPluginRegistry = false,
    File? dartPluginRegistrant,
    Uri? nativeAssetsYaml,
    bool recompileRestart = false,
  });

  Future<CompilerOutput?> compileExpression(
    String expression,
    List<String>? definitions,
    List<String>? definitionTypes,
    List<String>? typeDefinitions,
    List<String>? typeBounds,
    List<String>? typeDefaults,
    String? libraryUri,
    String? klass,
    String? method,
    bool isStatic,
  );

  /// Compiles [expression] in [libraryUri] at [line]:[column] to JavaScript
  /// in [moduleName].
  ///
  /// Values listed in [jsFrameValues] are substituted for their names in the
  /// [expression].
  ///
  /// Ensures that all [jsModules] are loaded and accessible inside the
  /// expression.
  ///
  /// Example values of parameters:
  /// [moduleName] is of the form '/packages/hello_world_main.dart'
  /// [jsFrameValues] is a map from js variable name to its primitive value
  /// or another variable name, for example
  /// { 'x': '1', 'y': 'y', 'o': 'null' }
  /// [jsModules] is a map from variable name to the module name, where
  /// variable name is the name originally used in JavaScript to contain the
  /// module object, for example:
  /// { 'dart':'dart_sdk', 'main': '/packages/hello_world_main.dart' }
  /// Returns a [CompilerOutput] including the name of the file containing the
  /// compilation result and a number of errors.
  Future<CompilerOutput?> compileExpressionToJs(
    String libraryUri,
    String scriptUri,
    int line,
    int column,
    Map<String, String> jsModules,
    Map<String, String> jsFrameValues,
    String moduleName,
    String expression,
  );

  /// Should be invoked when results of compilation are accepted by the client.
  ///
  /// Either [accept] or [reject] should be called after every [recompile] call.
  void accept();

  /// Should be invoked when results of compilation are rejected by the client.
  ///
  /// Either [accept] or [reject] should be called after every [recompile] call.
  Future<CompilerOutput?> reject();

  /// Should be invoked when frontend server compiler should forget what was
  /// accepted previously so that next call to [recompile] produces complete
  /// kernel file.
  void reset();

  Future<Object> shutdown();
}

@visibleForTesting
class DefaultResidentCompiler implements ResidentCompiler {
  DefaultResidentCompiler(
    String sdkRoot, {
    required BuildInfo buildInfo,
    required Logger logger,
    required this._processManager,
    required this.artifacts,
    required this._platform,
    required FileSystem fileSystem,
    required this._shutdownHooks,
    required Config config,
    this.testCompilation = false,
    this.targetModel = TargetModel.flutter,
    this.platformDill,
    this.librariesSpec,
    @visibleForTesting StdoutHandler? stdoutHandler,
  }) : buildMode = buildInfo.mode,
       trackWidgetCreation = buildInfo.trackWidgetCreation,
       includeUnsupportedPlatformLibraryStubs = buildInfo.includeUnsupportedPlatformLibraryStubs,
       packagesPath = buildInfo.packageConfigPath,
       initializeFromDill =
           buildInfo.initializeFromDill ??
           getDefaultCachedKernelPath(
             config: config,
             fileSystem: fileSystem,
             trackWidgetCreation: buildInfo.trackWidgetCreation,
             dartDefines: buildInfo.dartDefines,
             targetModel: targetModel,
             extraFrontEndOptions: buildInfo.extraFrontEndOptions,
           ),
       extraFrontEndOptions = buildInfo.extraFrontEndOptions,
       fileSystemScheme = buildInfo.fileSystemScheme,
       assumeInitializeFromDillUpToDate = buildInfo.assumeInitializeFromDillUpToDate,
       frontendServerStarterPath = buildInfo.frontendServerStarterPath,
       _logger = logger,
       _stdoutHandler = stdoutHandler ?? StdoutHandler(logger: logger, fileSystem: fileSystem),
       dartDefines = buildInfo.dartDefines,
       // This is a URI, not a file path, so the forward slash is correct even on Windows.
       sdkRoot = sdkRoot.endsWith('/') ? sdkRoot : '$sdkRoot/',
       // Make a copy, we might need to modify it later.
       fileSystemRoots = List<String>.from(buildInfo.fileSystemRoots) {
    // Currently, the only developer tooling that requires support for importing unsupported
    // platform libraries at compile time is the widget previewer. Only developer tooling use cases
    // should support this, so this is restricted to the widget previewer's runtime target for now.
    if (includeUnsupportedPlatformLibraryStubs && targetModel != TargetModel.dartdevc) {
      throw StateError(
        'includeUnsupportedPlatformLibraryStubs should only be used by the widget-preview '
        'command.',
      );
    }
  }

  final Logger _logger;
  final ProcessManager _processManager;
  final Artifacts artifacts;
  final Platform _platform;
  final ShutdownHooks _shutdownHooks;

  final bool testCompilation;
  final BuildMode buildMode;
  final bool trackWidgetCreation;
  final bool includeUnsupportedPlatformLibraryStubs;
  final String? packagesPath;
  final TargetModel targetModel;
  final List<String> fileSystemRoots;
  final String? fileSystemScheme;
  final String? initializeFromDill;
  final bool assumeInitializeFromDillUpToDate;
  final String? frontendServerStarterPath;
  final List<String>? extraFrontEndOptions;
  final List<String> dartDefines;
  final String? librariesSpec;

  @override
  void addFileSystemRoot(String root) {
    fileSystemRoots.add(root);
  }

  /// The path to the root of the Dart SDK used to compile.
  ///
  /// This is used to resolve the [platformDill].
  final String sdkRoot;

  /// The path to the platform dill file.
  ///
  /// This does not need to be provided for the normal Flutter workflow.
  final String? platformDill;

  Process? _server;
  final StdoutHandler _stdoutHandler;
  var _compileRequestNeedsConfirmation = false;

  final _controller = StreamController<_CompilationRequest>();

  @override
  Future<CompilerOutput?> recompile(
    Uri mainUri,
    List<Uri>? invalidatedFiles, {
    required String outputPath,
    required PackageConfig packageConfig,
    bool suppressErrors = false,
    bool checkDartPluginRegistry = false,
    File? dartPluginRegistrant,
    String? projectRootPath,
    FileSystem? fs,
    Uri? nativeAssetsYaml,
    bool recompileRestart = false,
  }) async {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }
    Uri? additionalSourceUri;
    // `dart_plugin_registrant.dart` contains the Dart plugin registry.
    if (checkDartPluginRegistry &&
        dartPluginRegistrant != null &&
        dartPluginRegistrant.existsSync()) {
      additionalSourceUri = dartPluginRegistrant.uri;
    }
    final completer = Completer<CompilerOutput?>();
    _controller.add(
      _RecompileRequest(
        completer,
        mainUri,
        invalidatedFiles,
        outputPath,
        packageConfig,
        suppressErrors,
        additionalSourceUri: additionalSourceUri,
        nativeAssetsYamlUri: nativeAssetsYaml,
        recompileRestart: recompileRestart,
      ),
    );
    return completer.future;
  }

  Future<CompilerOutput?> _recompile(_RecompileRequest request) async {
    _stdoutHandler.reset();
    _compileRequestNeedsConfirmation = true;
    _stdoutHandler._suppressCompilerMessages = request.suppressErrors;

    final String mainUri =
        request.packageConfig.toPackageUriForWorkspace(request.mainUri)?.toString() ??
        toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);

    String? additionalSourceUri;
    if (request.additionalSourceUri != null) {
      additionalSourceUri =
          request.packageConfig
              .toPackageUriForWorkspace(request.additionalSourceUri!)
              ?.toString() ??
          toMultiRootPath(
            request.additionalSourceUri!,
            fileSystemScheme,
            fileSystemRoots,
            _platform.isWindows,
          );
    }

    final nativeAssets = request.nativeAssetsYamlUri?.toString();
    final Process? server = _server;
    if (server == null) {
      return _compile(
        mainUri,
        request.outputPath,
        additionalSourceUri: additionalSourceUri,
        nativeAssetsUri: nativeAssets,
      );
    }
    final String inputKey = const Uuid().v4();

    if (nativeAssets != null && nativeAssets.isNotEmpty) {
      server.stdin.writeln('native-assets $nativeAssets');
      _logger.printTrace('<- native-assets $nativeAssets');
    }
    if (request.recompileRestart) {
      server.stdin.writeln('recompile-restart $mainUri $inputKey');
    } else {
      server.stdin.writeln('recompile $mainUri $inputKey');
    }
    _logger.printTrace('<- recompile $mainUri $inputKey');
    final List<Uri>? invalidatedFiles = request.invalidatedFiles;
    if (invalidatedFiles != null) {
      for (final Uri fileUri in invalidatedFiles) {
        String message;
        if (fileUri.scheme == 'package') {
          message = fileUri.toString();
        } else {
          message =
              request.packageConfig.toPackageUriForWorkspace(fileUri)?.toString() ??
              toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);
        }
        server.stdin.writeln(message);
        _logger.printTrace(message);
      }
    }
    server.stdin.writeln(inputKey);
    _logger.printTrace('<- $inputKey');

    return _stdoutHandler.compilerOutput?.future;
  }

  final _compilationQueue = <_CompilationRequest>[];

  Future<void> _handleCompilationRequest(_CompilationRequest request) async {
    final bool isEmpty = _compilationQueue.isEmpty;
    _compilationQueue.add(request);
    // Only trigger processing if queue was empty - i.e. no other requests
    // are currently being processed. This effectively enforces "one
    // compilation request at a time".
    if (isEmpty) {
      while (_compilationQueue.isNotEmpty) {
        final _CompilationRequest request = _compilationQueue.first;
        await request.run(this);
        _compilationQueue.removeAt(0);
      }
    }
  }

  Future<CompilerOutput?> _compile(
    String scriptUri,
    String? outputPath, {
    String? additionalSourceUri,
    String? nativeAssetsUri,
  }) async {
    final TargetPlatform? platform = (targetModel == TargetModel.dartdevc)
        ? TargetPlatform.web_javascript
        : null;
    late final List<String> commandToStartFrontendServer;
    if (frontendServerStarterPath != null && frontendServerStarterPath!.isNotEmpty) {
      commandToStartFrontendServer = <String>[
        artifacts.getArtifactPath(Artifact.engineDartBinary, platform: platform),
        frontendServerStarterPath!,
      ];
    } else {
      commandToStartFrontendServer = <String>[
        artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: platform),
        artifacts.getArtifactPath(
          Artifact.frontendServerSnapshotForEngineDartSdk,
          platform: platform,
        ),
      ];
    }

    final command = <String>[
      ...commandToStartFrontendServer,
      '--sdk-root',
      sdkRoot,
      '--incremental',
      if (testCompilation) '--no-print-incremental-dependencies',
      '--target=$targetModel',
      // TODO(annagrin): remove once this becomes the default behavior
      // in the frontend_server.
      // https://github.com/flutter/flutter/issues/59902
      '--experimental-emit-debug-metadata',
      for (final Object dartDefine in dartDefines) '-D$dartDefine',
      if (outputPath != null) ...<String>['--output-dill', outputPath],
      // If we have a platform dill, we don't need to pass the libraries spec,
      // since the information is embedded in the .dill file.
      if (librariesSpec != null && platformDill == null) ...<String>[
        '--libraries-spec',
        librariesSpec!,
      ],
      if (packagesPath != null) ...<String>['--packages', packagesPath!],
      ...buildModeOptions(buildMode, dartDefines),
      if (trackWidgetCreation) '--track-creation-locations',
      if (includeUnsupportedPlatformLibraryStubs) '--include-unsupported-platform-library-stubs',
      for (final String root in fileSystemRoots) ...<String>['--filesystem-root', root],
      if (fileSystemScheme != null) ...<String>['--filesystem-scheme', fileSystemScheme!],
      if (initializeFromDill != null) ...<String>['--initialize-from-dill', initializeFromDill!],
      if (assumeInitializeFromDillUpToDate) '--assume-initialize-from-dill-up-to-date',
      if (additionalSourceUri != null) ...<String>[
        '--source',
        additionalSourceUri,
        '--source',
        'package:flutter/src/dart_plugin_registrant.dart',
        '-Dflutter.dart_plugin_registrant=$additionalSourceUri',
      ],
      if (nativeAssetsUri != null) ...<String>['--native-assets', nativeAssetsUri],
      if (platformDill != null) ...<String>['--platform', platformDill!],
      // See: https://github.com/flutter/flutter/issues/103994
      '--verbosity=error',
      ...?_filterExtraFrontEndOptions(extraFrontEndOptions),
    ];
    _logger.printTrace(command.join(' '));
    _server = await _processManager.start(command);
    _server?.stdout
        .transform(utf8LineDecoder)
        .listen(
          _stdoutHandler.handler,
          onDone: () {
            // when outputFilename future is not completed, but stdout is closed
            // process has died unexpectedly.
            if (_stdoutHandler.compilerOutput?.isCompleted == false &&
                !_shutdownHooks.isShuttingDown) {
              _stdoutHandler.compilerOutput?.complete();
              throwToolExit('The Dart compiler exited unexpectedly.');
            }
          },
        );

    // Use permissive decoder for compiler stderr which may contain invalid UTF-8
    _server?.stderr.transform(utf8AllowMalformedLineDecoder).listen(_logger.printError);

    unawaited(
      _server?.exitCode.then((int code) {
        // The frontend server exits with a 253 error code when we shutdown due to a signal.
        // Don't treat this as an error if we're in the middle of the shutdown sequence.
        if (code != 0 && !_shutdownHooks.isShuttingDown) {
          throwToolExit('The Dart compiler exited unexpectedly.');
        }
      }),
    );

    if (nativeAssetsUri != null && nativeAssetsUri.isNotEmpty) {
      _server?.stdin.writeln('native-assets $nativeAssetsUri');
      _logger.printTrace('<- native-assets $nativeAssetsUri');
    }

    _server?.stdin.writeln('compile $scriptUri');
    _logger.printTrace('<- compile $scriptUri');

    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  Future<CompilerOutput?> compileExpression(
    String expression,
    List<String>? definitions,
    List<String>? definitionTypes,
    List<String>? typeDefinitions,
    List<String>? typeBounds,
    List<String>? typeDefaults,
    String? libraryUri,
    String? klass,
    String? method,
    bool isStatic,
  ) async {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }

    final completer = Completer<CompilerOutput?>();
    final request = _CompileExpressionRequest(
      completer,
      expression,
      definitions,
      definitionTypes,
      typeDefinitions,
      typeBounds,
      typeDefaults,
      libraryUri,
      klass,
      method,
      isStatic,
    );
    _controller.add(request);
    return completer.future;
  }

  Future<CompilerOutput?> _compileExpression(_CompileExpressionRequest request) async {
    _stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false, readFile: true);

    // 'compile-expression' should be invoked after compiler has been started,
    // program was compiled.
    final Process? server = _server;
    if (server == null) {
      return null;
    }

    server.stdin
      ..writeln('JSON_INPUT')
      ..writeln(
        json.encode(<String, Object?>{
          'type': 'COMPILE_EXPRESSION',
          'data': <String, Object?>{
            'expression': request.expression,
            'definitions': request.definitions ?? <String>[],
            'definitionTypes': request.definitionTypes ?? <String>[],
            'typeDefinitions': request.typeDefinitions ?? <String>[],
            'typeBounds': request.typeBounds ?? <String>[],
            'typeDefaults': request.typeDefaults ?? <String>[],
            'libraryUri': request.libraryUri ?? '',
            'class': request.klass,
            'method': request.method,
            'static': request.isStatic,
          },
        }),
      );

    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  Future<CompilerOutput?> compileExpressionToJs(
    String libraryUri,
    String scriptUri,
    int line,
    int column,
    Map<String, String> jsModules,
    Map<String, String> jsFrameValues,
    String moduleName,
    String expression,
  ) {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }

    final completer = Completer<CompilerOutput?>();
    _controller.add(
      _CompileExpressionToJsRequest(
        completer,
        libraryUri,
        scriptUri,
        line,
        column,
        jsModules,
        jsFrameValues,
        moduleName,
        expression,
      ),
    );
    return completer.future;
  }

  Future<CompilerOutput?> _compileExpressionToJs(_CompileExpressionToJsRequest request) async {
    _stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false);

    // 'compile-expression-to-js' should be invoked after compiler has been started,
    // program was compiled.
    final Process? server = _server;
    if (server == null) {
      return null;
    }

    server.stdin
      ..writeln('JSON_INPUT')
      ..writeln(
        json.encode({
          'type': 'COMPILE_EXPRESSION_JS',
          'data': {
            'expression': request.expression,
            'libraryUri': request.libraryUri,
            'scriptUri': request.scriptUri,
            'line': request.line,
            'column': request.column,
            'jsModules': request.jsModules,
            'jsFrameValues': request.jsFrameValues,
            'moduleName': request.moduleName,
          },
        }),
      );

    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  void accept() {
    if (_compileRequestNeedsConfirmation) {
      _server?.stdin.writeln('accept');
      _logger.printTrace('<- accept');
    }
    _compileRequestNeedsConfirmation = false;
  }

  @override
  Future<CompilerOutput?> reject() {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }

    final completer = Completer<CompilerOutput?>();
    _controller.add(_RejectRequest(completer));
    return completer.future;
  }

  Future<CompilerOutput?> _reject() async {
    if (!_compileRequestNeedsConfirmation) {
      return Future<CompilerOutput?>.value();
    }
    _stdoutHandler.reset(expectSources: false);
    _server?.stdin.writeln('reject');
    _logger.printTrace('<- reject');
    _compileRequestNeedsConfirmation = false;
    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  void reset() {
    _server?.stdin.writeln('reset');
    _logger.printTrace('<- reset');
  }

  @override
  Future<Object> shutdown() async {
    // Server was never successfully created.
    final Process? server = _server;
    if (server == null) {
      return 0;
    }
    _logger.printTrace('killing pid ${server.pid}');
    server.kill();
    return server.exitCode;
  }
}

/// Convert a file URI into a multi-root scheme URI if provided, otherwise
/// return unmodified.
@visibleForTesting
String toMultiRootPath(Uri fileUri, String? scheme, List<String> fileSystemRoots, bool windows) {
  if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') {
    return fileUri.toString();
  }
  final String filePath = fileUri.toFilePath(windows: windows);
  for (final fileSystemRoot in fileSystemRoots) {
    if (filePath.startsWith(fileSystemRoot)) {
      return '$scheme://${filePath.substring(fileSystemRoot.length)}';
    }
  }
  return fileUri.toString();
}
