// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.9

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';

import 'package:args/args.dart';
import 'package:build_integration/file_system/multi_root.dart';
import 'package:front_end/src/api_prototype/file_system.dart';
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:kernel/ast.dart' show Component, Library;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/src/tool/find_referenced_libraries.dart'
    show duplicateLibrariesReachable;
import 'package:kernel/target/targets.dart' show TargetFlags;
import 'package:meta/meta.dart';

import '../../dev_compiler.dart';
import '../compiler/js_names.dart';
import 'asset_file_system.dart';
import 'command.dart';
import 'target.dart' show sdkLibraryEnvironmentDefines;

/// The service that handles expression compilation requests from
/// the debugger.
///
/// See design documentation and discussion in
/// http://go/dart_expression_evaluation_webdev_google3
///
///
/// [ExpressionCompilerWorker] listens to input stream of compile expression
/// requests and outputs responses.
///
/// Debugger can run the service by running the dartdevc main in an isolate,
/// which sets up the request stream and response callback using send ports.
///
/// Debugger also can pass an asset server's host and port so the service
/// can read dill files from the [AssetFileSystem] that talks to the asset
/// server behind the scenes over http.
///
/// Protocol:
///
///  - debugger and dartdevc expression evaluation service perform the initial
///    handshake to establish two-way communication:
///
///    - debugger creates an isolate using dartdevc's main method with
///      '--experimental-expression-compiler' flag and passes a send port
///      to dartdevc for sending responses from the service to the debugger.
///
///    - dartdevc creates a new send port to receive requests on, and sends
///      it back to the debugger, for sending requests to the service.
///
///  - debugger can now send two types of requests to the dartdevc service.
///    The service handles the requests sequentially in a first come, first
///    serve order.
///
///    - [UpdateDepsRequest]:
///      This request is sent on (re-)build, making the dartdevc load all
///      newly built full kernel files for given modules.
///
///    - [CompileExpressionRequest]:
///      This request is sent any time an evaluateInFrame request is made to
///      the debugger's VM service at a breakpoint - for example, on typing
///      in an expression evaluation box, on hover over, evaluation of
///      conditional breakpoints, evaluation of expressions in a watch window.
///
///  - Debugger closes the requests stream on exit, which effectively stops
///    the service
class ExpressionCompilerWorker {
  final Stream<Map<String, dynamic>> requestStream;
  final void Function(Map<String, dynamic>) sendResponse;

  final Map<String, Uri> _fullModules = {};
  final ModuleCache _moduleCache = ModuleCache();

  final ProcessedOptions _processedOptions;
  final CompilerOptions _compilerOptions;
  final ModuleFormat _moduleFormat;
  final Component _sdkComponent;

  void Function() onDone;

  ExpressionCompilerWorker._(
    this._processedOptions,
    this._compilerOptions,
    this._moduleFormat,
    this._sdkComponent,
    this.requestStream,
    this.sendResponse,
    this.onDone,
  );

  /// Create expression compiler worker from [args] and start it.
  ///
  /// If [sendPort] is provided, creates a `receivePort` and sends it to
  /// the consumer to establish communication. Otherwise, uses stdin/stdout
  /// for communication with the consumer.
  ///
  /// Details:
  ///
  /// Consumer uses (`consumerSendPort`, `consumerReceivePort`) pair to
  /// send requests and receive responses:
  ///
  /// `consumerReceivePort.sendport` = [sendPort]
  /// `consumerSendPort = receivePort.sendport`
  ///
  /// Worker uses the opposite ports connected to the consumer ports -
  /// (`receivePort`, [sendPort]) to receive requests and send responses.
  ///
  /// The worker stops on start failure or after the consumer closes its
  /// receive port corresponding to [sendPort].
  static Future<void> createAndStart(List<String> args,
      {SendPort sendPort}) async {
    ExpressionCompilerWorker worker;
    if (sendPort != null) {
      var receivePort = ReceivePort();
      sendPort.send(receivePort.sendPort);
      try {
        worker = await createFromArgs(args,
            requestStream: receivePort.cast<Map<String, dynamic>>(),
            sendResponse: sendPort.send);
        await worker.run();
      } catch (e, s) {
        sendPort
            .send({'exception': '$e', 'stackTrace': '$s', 'succeeded': false});
        rethrow;
      } finally {
        receivePort.close();
        worker?.close();
      }
    } else {
      try {
        worker = await createFromArgs(args);
        await worker.run();
      } finally {
        worker?.close();
      }
    }
  }

  /// Parse args and create the worker, hook cleanup code to run when done.
  static Future<ExpressionCompilerWorker> createFromArgs(
    List<String> args, {
    Stream<Map<String, dynamic>> requestStream,
    void Function(Map<String, dynamic>) sendResponse,
  }) {
    // We are destructive on `args`, so make a copy.
    args = args.toList();
    var environmentDefines = parseAndRemoveDeclaredVariables(args);
    var parsedArgs = argParser.parse(args);

    FileSystem fileSystem = StandardFileSystem.instance;
    var multiRoots = (parsedArgs['multi-root'] as Iterable<String>)
        .map(Uri.base.resolve)
        .toList();
    var multiRootScheme = parsedArgs['multi-root-scheme'] as String;
    if (multiRoots.isNotEmpty) {
      fileSystem = MultiRootFileSystem(multiRootScheme, multiRoots, fileSystem);
    }
    var assetServerAddress = parsedArgs['asset-server-address'] as String;
    if (assetServerAddress != null) {
      var assetServerPort = parsedArgs['asset-server-port'] as String;
      fileSystem = AssetFileSystem(
          fileSystem, assetServerAddress, assetServerPort ?? '8080');
    }
    var explicitExperimentalFlags = parseExperimentalFlags(
        parseExperimentalArguments(
            parsedArgs['enable-experiment'] as List<String>),
        onError: (e) => throw e);

    var moduleFormat = parseModuleFormat(parsedArgs['module-format'] as String);

    return create(
      librariesSpecificationUri:
          _argToUri(parsedArgs['libraries-file'] as String),
      packagesFile: _argToUri(parsedArgs['packages-file'] as String),
      sdkSummary: _argToUri(parsedArgs['dart-sdk-summary'] as String),
      fileSystem: fileSystem,
      environmentDefines: environmentDefines,
      explicitExperimentalFlags: explicitExperimentalFlags,
      sdkRoot: _argToUri(parsedArgs['sdk-root'] as String),
      trackWidgetCreation: parsedArgs['track-widget-creation'] as bool,
      soundNullSafety: parsedArgs['sound-null-safety'] as bool,
      moduleFormat: moduleFormat,
      verbose: parsedArgs['verbose'] as bool,
      requestStream: requestStream,
      sendResponse: sendResponse,
      onDone: () {
        if (fileSystem is AssetFileSystem) fileSystem.close();
      },
    );
  }

  static List<String> errors = <String>[];
  static List<String> warnings = <String>[];
  static List<String> infos = <String>[];

  /// Create the worker and load the sdk outlines.
  static Future<ExpressionCompilerWorker> create({
    @required Uri librariesSpecificationUri,
    @required Uri sdkSummary,
    @required FileSystem fileSystem,
    Uri packagesFile,
    Map<String, String> environmentDefines,
    Map<ExperimentalFlag, bool> explicitExperimentalFlags = const {},
    Uri sdkRoot,
    bool trackWidgetCreation = false,
    bool soundNullSafety = false,
    ModuleFormat moduleFormat = ModuleFormat.amd,
    bool verbose = false,
    Stream<Map<String, dynamic>> requestStream, // Defaults to read from stdin
    void Function(Map<String, dynamic>)
        sendResponse, // Defaults to write to stdout
    void Function() onDone,
  }) async {
    var compilerOptions = CompilerOptions()
      ..compileSdk = false
      ..sdkRoot = sdkRoot
      ..sdkSummary = sdkSummary
      ..packagesFileUri = packagesFile
      ..librariesSpecificationUri = librariesSpecificationUri
      ..target = DevCompilerTarget(
          TargetFlags(trackWidgetCreation: trackWidgetCreation))
      ..fileSystem = fileSystem
      ..omitPlatform = true
      ..environmentDefines = {
        if (environmentDefines != null) ...environmentDefines,
        // TODO(47243) Remove when all code paths read these from the `Target`.
        ...sdkLibraryEnvironmentDefines
      }
      ..explicitExperimentalFlags = explicitExperimentalFlags
      ..onDiagnostic = _onDiagnosticHandler(errors, warnings, infos)
      ..nnbdMode = soundNullSafety ? NnbdMode.Strong : NnbdMode.Weak
      ..verbose = verbose;
    requestStream ??= stdin
        .transform(utf8.decoder.fuse(json.decoder))
        .cast<Map<String, dynamic>>();
    sendResponse ??= (Map<String, dynamic> response) =>
        stdout.writeln(json.encode(response));
    var processedOptions = ProcessedOptions(options: compilerOptions);

    var sdkComponent = await CompilerContext(processedOptions)
        .runInContext<Component>((CompilerContext c) async {
      return processedOptions.loadSdkSummary(null);
    });

    if (sdkComponent == null) {
      throw Exception('Could not load SDK component: $sdkSummary');
    }
    return ExpressionCompilerWorker._(processedOptions, compilerOptions,
        moduleFormat, sdkComponent, requestStream, sendResponse, onDone)
      .._updateCache(sdkComponent, dartSdkModule, true);
  }

  /// Starts listening and responding to commands.
  ///
  /// Completes when the [requestStream] closes and we finish handling the
  /// requests.
  Future<void> run() async {
    await for (var request in requestStream) {
      try {
        var command = request['command'] as String;
        if (command == 'Shutdown') break;
        switch (command) {
          case 'UpdateDeps':
            sendResponse(await _updateDependencies(
                UpdateDependenciesRequest.fromJson(request)));
            break;
          case 'CompileExpression':
            sendResponse(await _compileExpression(
                CompileExpressionRequest.fromJson(request)));
            break;
          default:
            throw ArgumentError(
                'Unrecognized command `$command`, full request was `$request`');
        }
      } catch (e, s) {
        var command = request['command'] as String;
        _processedOptions.ticker
            .logMs('Expression compiler worker request $command failed: $e:$s');
        sendResponse({
          'exception': '$e',
          'stackTrace': '$s',
          'succeeded': false,
        });
      }
    }
    _processedOptions.ticker.logMs('Stopped expression compiler worker.');
  }

  void close() => onDone?.call();

  /// Handles a `CompileExpression` request.
  Future<Map<String, dynamic>> _compileExpression(
      CompileExpressionRequest request) async {
    var libraryUri = Uri.parse(request.libraryUri);
    var moduleName = request.moduleName;

    if (libraryUri.scheme == 'dart') {
      // compiling expressions inside the SDK currently fails because
      // SDK kernel outlines do not contain information that is needed
      // to detect the scope for expression evaluation - such as local
      // symbols and source file line starts.
      throw Exception('Expression compilation inside SDK is not supported yet');
    }

    _processedOptions.ticker
        .logMs('Compiling expression to JavaScript in module $moduleName');

    // Reset linking of libraries to the original state,
    // so any newly loaded components are linked to the
    // libraries in the cache.
    _resetCacheLinks();

    if (!_fullModules.containsKey(moduleName)) {
      throw StateError('No full dill path available for $moduleName');
    }

    // Note that this doesn't actually re-load it if it's already fully loaded.
    if (!await _loadAndUpdateComponent(
        _fullModules[moduleName], moduleName, false)) {
      throw ArgumentError('Failed to load full dill for module $moduleName: '
          '${_fullModules[moduleName]}');
    }

    var originalComponent = _moduleCache.componentForModuleName[moduleName];

    var component = _sdkComponent;
    if (libraryUri.scheme != 'dart') {
      _processedOptions.ticker.logMs('Collecting libraries for $moduleName');

      var libraries =
          _collectTransitiveDependencies(originalComponent, _sdkComponent);

      assert(!duplicateLibrariesReachable(libraries));

      component = Component(
        libraries: libraries,
        nameRoot: originalComponent.root,
        uriToSource: originalComponent.uriToSource,
      )..setMainMethodAndMode(
          originalComponent.mainMethodName, true, originalComponent.mode);
    }

    _processedOptions.ticker.logMs('Collected libraries for $moduleName');

    errors.clear();
    warnings.clear();
    infos.clear();

    var incrementalCompiler = IncrementalCompiler.forExpressionCompilationOnly(
        CompilerContext(_processedOptions), component, /*resetTicker*/ false);

    var incrementalCompilerResult = await incrementalCompiler
        .computeDelta(entryPoints: [libraryUri], fullComponent: true);
    var finalComponent = incrementalCompilerResult.component;
    assert(!duplicateLibrariesReachable(finalComponent.libraries));
    assert(_canSerialize(finalComponent));

    _processedOptions.ticker.logMs('Computed delta for expression');

    if (errors.isNotEmpty) {
      return {
        'errors': errors,
        'warnings': warnings,
        'infos': infos,
        'compiledProcedure': null,
        'succeeded': errors.isEmpty,
      };
    }

    var coreTypes = incrementalCompiler.getCoreTypes();
    var hierarchy = incrementalCompiler.getClassHierarchy();

    var kernel2jsCompiler = ProgramCompiler(
      finalComponent,
      hierarchy,
      SharedCompilerOptions(
          sourceMap: true,
          summarizeApi: false,
          moduleName: moduleName,
          soundNullSafety: _compilerOptions.nnbdMode == NnbdMode.Strong,
          // Disable asserts due to failures to load source and
          // locations on kernel loaded from dill files in DDC.
          // https://github.com/dart-lang/sdk/issues/43986
          enableAsserts: false),
      _moduleCache.componentForLibrary,
      _moduleCache.moduleNameForComponent,
      coreTypes: coreTypes,
    );

    assert(originalComponent.libraries.toSet().length ==
        originalComponent.libraries.length);

    // Pick the libraries from finalComponent that's also in originalComponent.
    // This is needed because originalComponent can contain unreachable things
    // (i.e. unreachable from the entry point used here).
    var names = originalComponent.libraries.map((e) => e.importUri).toSet();
    var librariesToEmit = finalComponent.libraries
        .where((e) => names.contains(e.importUri))
        .toList();
    assert(_librariesAreKnown(hierarchy, librariesToEmit));

    var componentToEmit = Component(
        libraries: librariesToEmit,
        nameRoot: finalComponent.root,
        uriToSource: finalComponent.uriToSource)
      ..setMainMethodAndMode(
          originalComponent.mainMethodName, true, originalComponent.mode);

    kernel2jsCompiler.emitModule(componentToEmit);
    _processedOptions.ticker.logMs('Emitted module for expression');

    var expressionCompiler = ExpressionCompiler(
      _compilerOptions,
      _moduleFormat,
      errors,
      incrementalCompiler,
      kernel2jsCompiler,
      finalComponent,
    );

    var compiledProcedure = await expressionCompiler.compileExpressionToJs(
        request.libraryUri,
        request.line,
        request.column,
        request.jsScope,
        request.expression);

    _processedOptions.ticker.logMs('Compiled expression to JavaScript');

    return {
      'errors': errors,
      'warnings': warnings,
      'infos': infos,
      'compiledProcedure': compiledProcedure,
      'succeeded': errors.isEmpty,
    };
  }

  /// Collect libraries reachable from component.
  List<Library> _collectTransitiveDependencies(
      Component component, Component sdk) {
    var visited = <Uri>{};
    var libraries = <Library>[];
    var toVisit = <Uri>[];

    toVisit.addAll(sdk.libraries.map((e) => e.importUri));
    toVisit.addAll(component.libraries.map((e) => e.importUri));

    while (toVisit.isNotEmpty) {
      var uri = toVisit.removeLast();
      if (!visited.contains(uri)) {
        visited.add(uri);
        if (_moduleCache.libraryForUri.containsKey(uri)) {
          var lib = _moduleCache.libraryForUri[uri];
          libraries.add(lib);
          for (var dep in lib.dependencies) {
            if (dep.importedLibraryReference.node != null) {
              toVisit.add(dep.importedLibraryReference.asLibrary.importUri);
            } else {
              _processedOptions.ticker.logMs(
                  'Missing link for ${dep.importedLibraryReference.canonicalName}'
                  ' in ${lib.importUri}');
            }
          }
        } else {
          _processedOptions.ticker.logMs('No summary found for library: $uri');
        }
      }
    }

    return libraries;
  }

  /// Loads in the specified dill files and invalidates any existing ones.
  Future<Map<String, dynamic>> _updateDependencies(
      UpdateDependenciesRequest request) async {
    _processedOptions.ticker
        .logMs('Updating dependencies for expression evaluation');

    for (var input in request.inputs) {
      _clearCache(input.moduleName);
    }

    // Reset linking of libraries to the original state,
    // so any newly loaded components are linked to the
    // libraries in the cache.
    _resetCacheLinks();

    // Load summaries and store paths for full kernel files.
    // Note that we intentionally ignore loading failures here
    // as not all of them are fatal. We report missing dependencies
    // instead on expression evaluation.
    // TODO(annagrin): throw on load failures when blaze build starts
    // producing all summaries.
    var futures = <Future>[];
    for (var input in request.inputs) {
      // Support older debugger versions that do not provide summary
      // path by loading full dill kernel instead.
      var hasSummary = input.summaryPath != null;
      if (!hasSummary) {
        _processedOptions.ticker
            .logMs('Summary path is not provided for ${input.moduleName}.'
                ' Loading full dill instead.');
      }
      var summaryPath = input.summaryPath ?? input.path;
      _fullModules[input.moduleName] = Uri.parse(input.path);
      futures.add(_loadAndUpdateComponent(
          Uri.parse(summaryPath), input.moduleName, hasSummary));
    }
    await Future.wait(futures);

    _processedOptions.ticker
        .logMs('Updated dependencies for expression evaluation');
    return {'succeeded': true};
  }

  /// Load component and update cache.
  Future<bool> _loadAndUpdateComponent(
      Uri uri, String moduleName, bool isSummary) async {
    if (isSummary && _moduleCache.isModuleLoaded(moduleName)) return true;
    if (!isSummary && _moduleCache.isModuleFullyLoaded(moduleName)) return true;

    var component = await _loadComponent(uri);
    if (component == null) {
      var componentKind = isSummary ? 'summary' : 'full kernel';
      _processedOptions.ticker
          .logMs('Failed to load $componentKind for $moduleName');
      return false;
    }
    _updateCache(component, moduleName, isSummary);
    return true;
  }

  Future<Component> _loadComponent(Uri uri) async {
    var file = _processedOptions.fileSystem.entityForUri(uri);
    if (await file.existsAsyncIfPossible()) {
      var bytes = await file.readAsBytesAsyncIfPossible();
      var component = _processedOptions.loadComponent(bytes, _sdkComponent.root,
          alwaysCreateNewNamedNodes: true);
      return component;
    }
    return null;
  }

  void _updateCache(Component component, String moduleName, bool isSummary) {
    // Do not update dart sdk as we don't expect it to change.
    if (moduleName == dartSdkModule &&
        _moduleCache.isModuleLoaded(moduleName)) {
      return;
    }
    _moduleCache.addModule(moduleName, component, isSummary);
  }

  void _clearCache(String moduleName) {
    // Do not remove dart sdk as we don't expect it to change.
    if (moduleName == dartSdkModule) return;
    _moduleCache.removeModule(moduleName);
  }

  /// Reset library links and canonical name trees.
  void _resetCacheLinks() {
    // Adopting children for the sdk and all already loaded components means
    // that the root knows about all of it so anything new that is loaded will
    // link correctly.
    _sdkComponent.adoptChildren();
    for (var component in _moduleCache.componentForModuleName.values) {
      component.adoptChildren();
    }
  }

  bool _librariesAreKnown(ClassHierarchy hierarchy, List<Library> libraries) {
    for (var library in libraries) {
      if (!hierarchy.knownLibraries.contains(library)) return false;
    }
    return true;
  }

  bool _canSerialize(Component component) {
    var byteSink = _ByteSink();
    var printer = BinaryPrinter(byteSink);
    printer.writeComponentFile(component);
    return true;
  }
}

/// Module cache used to load modules and look up loaded libraries.
///
/// After each build, the cache is updated with summaries for
/// new or updated modules. The summaries can be replaced by
/// full dill kernel during a later expression evaluation in
/// the corresponding module.
class ModuleCache {
  final Map<Uri, Library> libraryForUri = {};
  final Map<Library, Component> componentForLibrary = {};
  final Map<String, Component> componentForModuleName = {};
  final Map<Component, String> moduleNameForComponent = {};
  final Set<String> fullyLoadedModules = {};

  bool isModuleLoaded(String moduleName) =>
      componentForModuleName.containsKey(moduleName);

  bool isModuleFullyLoaded(String moduleName) =>
      fullyLoadedModules.contains(moduleName);

  bool isLibraryLoaded(Library library) =>
      componentForLibrary.containsKey(library);

  void addModule(String moduleName, Component component, bool isSummary) {
    moduleNameForComponent[component] = moduleName;
    componentForModuleName[moduleName] = component;
    if (!isSummary) fullyLoadedModules.add(moduleName);

    for (var lib in component.libraries) {
      if (isLibraryLoaded(lib)) {
        throw Exception('library ${lib.importUri} is already loaded in '
            '${moduleNameForComponent[componentForLibrary[lib]]}');
      }
      componentForLibrary[lib] = component;
      libraryForUri[lib.importUri] = lib;
    }
  }

  void removeModule(String moduleName) {
    if (isModuleLoaded(moduleName)) {
      var oldComponent = componentForModuleName[moduleName];
      for (var lib in oldComponent.libraries) {
        componentForLibrary.remove(lib);
        libraryForUri.remove(lib.importUri);
      }

      moduleNameForComponent.remove(oldComponent);
      componentForModuleName.remove(moduleName);
      fullyLoadedModules.remove(moduleName);
    }
  }
}

/// Expression compilation request to the expression compilation worker.
class CompileExpressionRequest {
  final int column;
  final String expression;
  final Map<String, String> jsModules;
  final Map<String, String> jsScope;
  final String libraryUri;
  final int line;
  final String moduleName;

  CompileExpressionRequest({
    @required this.expression,
    @required this.column,
    @required this.jsModules,
    @required this.jsScope,
    @required this.libraryUri,
    @required this.line,
    @required this.moduleName,
  });

  factory CompileExpressionRequest.fromJson(Map<String, dynamic> json) =>
      CompileExpressionRequest(
        expression: json['expression'] as String,
        line: json['line'] as int,
        column: json['column'] as int,
        jsModules: Map<String, String>.from(json['jsModules'] as Map),
        jsScope: Map<String, String>.from(json['jsScope'] as Map),
        libraryUri: json['libraryUri'] as String,
        moduleName: json['moduleName'] as String,
      );
}

/// Module update request to the expression compilation worker.
class UpdateDependenciesRequest {
  final List<InputDill> inputs;

  UpdateDependenciesRequest(this.inputs);

  factory UpdateDependenciesRequest.fromJson(Map<String, dynamic> json) =>
      UpdateDependenciesRequest([
        for (var input in json['inputs'] as List)
          InputDill(input['path'] as String, input['summaryPath'] as String,
              input['moduleName'] as String),
      ]);
}

class InputDill {
  final String moduleName;
  final String path;
  final String summaryPath;

  InputDill(this.path, this.summaryPath, this.moduleName);
}

void Function(DiagnosticMessage) _onDiagnosticHandler(
        List<String> errors, List<String> warnings, List<String> infos) =>
    (DiagnosticMessage message) {
      switch (message.severity) {
        case Severity.error:
        case Severity.internalProblem:
          errors.add(message.plainTextFormatted.join('\n'));
          break;
        case Severity.warning:
          warnings.add(message.plainTextFormatted.join('\n'));
          break;
        case Severity.info:
          infos.add(message.plainTextFormatted.join('\n'));
          break;
        case Severity.context:
        case Severity.ignored:
          throw 'Unexpected severity: ${message.severity}';
      }
    };

final argParser = ArgParser()
  ..addOption('dart-sdk-summary')
  ..addMultiOption('enable-experiment',
      help: 'Enable a language experiment when invoking the CFE.')
  ..addOption('libraries-file')
  ..addMultiOption('multi-root')
  ..addOption('multi-root-scheme', defaultsTo: 'org-dartlang-app')
  ..addOption('packages-file')
  ..addOption('sdk-root')
  ..addOption('asset-server-address')
  ..addOption('asset-server-port')
  ..addOption('module-format', defaultsTo: 'amd')
  ..addFlag('track-widget-creation', defaultsTo: false)
  ..addFlag('sound-null-safety', defaultsTo: false)
  ..addFlag('verbose', defaultsTo: false);

Uri _argToUri(String uriArg) =>
    uriArg == null ? null : Uri.base.resolve(uriArg.replaceAll('\\', '/'));

class _ByteSink implements Sink<List<int>> {
  final BytesBuilder builder = BytesBuilder();

  @override
  void add(List<int> data) {
    builder.add(data);
  }

  @override
  void close() {}
}
