// 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';

/// 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,
      }
      ..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.isScheme('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.isScheme('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 = incrementalCompilerResult.coreTypes;
    var hierarchy = incrementalCompilerResult.classHierarchy;

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