|  | // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | /// This file serves as the single point of entry into the `dart:io` APIs | 
|  | /// within Flutter tools. | 
|  | /// | 
|  | /// In order to make Flutter tools more testable, we use the `FileSystem` APIs | 
|  | /// in `package:file` rather than using the `dart:io` file APIs directly (see | 
|  | /// `file_system.dart`). Doing so allows us to swap out local file system | 
|  | /// access with mockable (or in-memory) file systems, making our tests hermetic | 
|  | /// vis-a-vis file system access. | 
|  | /// | 
|  | /// We also use `package:platform` to provide an abstraction away from the | 
|  | /// static methods in the `dart:io` `Platform` class (see `platform.dart`). As | 
|  | /// such, do not export Platform from this file! | 
|  | /// | 
|  | /// To ensure that all file system and platform API access within Flutter tools | 
|  | /// goes through the proper APIs, we forbid direct imports of `dart:io` (via a | 
|  | /// test), forcing all callers to instead import this file, which exports the | 
|  | /// blessed subset of `dart:io` that is legal to use in Flutter tools. | 
|  | /// | 
|  | /// Because of the nature of this file, it is important that **platform and file | 
|  | /// APIs not be exported from `dart:io` in this file**! Moreover, be careful | 
|  | /// about any additional exports that you add to this file, as doing so will | 
|  | /// increase the API surface that we have to test in Flutter tools, and the APIs | 
|  | /// in `dart:io` can sometimes be hard to use in tests. | 
|  | import 'dart:async'; | 
|  | import 'dart:io' as io show exit, IOSink, ProcessSignal, stderr, stdin, stdout; | 
|  |  | 
|  | import 'package:meta/meta.dart'; | 
|  |  | 
|  | import 'context.dart'; | 
|  | import 'platform.dart'; | 
|  | import 'process.dart'; | 
|  |  | 
|  | export 'dart:io' | 
|  | show | 
|  | BytesBuilder, | 
|  | // Directory         NO! Use `file_system.dart` | 
|  | exitCode, | 
|  | // File              NO! Use `file_system.dart` | 
|  | // FileSystemEntity  NO! Use `file_system.dart` | 
|  | gzip, | 
|  | HandshakeException, | 
|  | HttpClient, | 
|  | HttpClientRequest, | 
|  | HttpClientResponse, | 
|  | HttpHeaders, | 
|  | HttpRequest, | 
|  | HttpServer, | 
|  | HttpStatus, | 
|  | InternetAddress, | 
|  | InternetAddressType, | 
|  | IOException, | 
|  | IOSink, | 
|  | // Link              NO! Use `file_system.dart` | 
|  | pid, | 
|  | // Platform          NO! use `platform.dart` | 
|  | Process, | 
|  | ProcessException, | 
|  | ProcessResult, | 
|  | // ProcessSignal     NO! Use [ProcessSignal] below. | 
|  | ProcessStartMode, | 
|  | // RandomAccessFile  NO! Use `file_system.dart` | 
|  | ServerSocket, | 
|  | // stderr,           NO! Use `io.dart` | 
|  | // stdin,            NO! Use `io.dart` | 
|  | Stdin, | 
|  | StdinException, | 
|  | // stdout,           NO! Use `io.dart` | 
|  | Socket, | 
|  | SocketException, | 
|  | systemEncoding, | 
|  | WebSocket, | 
|  | WebSocketException, | 
|  | WebSocketTransformer; | 
|  |  | 
|  | /// Exits the process with the given [exitCode]. | 
|  | typedef ExitFunction = void Function(int exitCode); | 
|  |  | 
|  | const ExitFunction _defaultExitFunction = io.exit; | 
|  |  | 
|  | ExitFunction _exitFunction = _defaultExitFunction; | 
|  |  | 
|  | /// Exits the process. | 
|  | /// | 
|  | /// This is analogous to the `exit` function in `dart:io`, except that this | 
|  | /// function may be set to a testing-friendly value by calling | 
|  | /// [setExitFunctionForTests] (and then restored to its default implementation | 
|  | /// with [restoreExitFunction]). The default implementation delegates to | 
|  | /// `dart:io`. | 
|  | ExitFunction get exit => _exitFunction; | 
|  |  | 
|  | /// Sets the [exit] function to a function that throws an exception rather | 
|  | /// than exiting the process; this is intended for testing purposes. | 
|  | @visibleForTesting | 
|  | void setExitFunctionForTests([ExitFunction exitFunction]) { | 
|  | _exitFunction = exitFunction ?? (int exitCode) { | 
|  | throw ProcessExit(exitCode, immediate: true); | 
|  | }; | 
|  | } | 
|  |  | 
|  | /// Restores the [exit] function to the `dart:io` implementation. | 
|  | @visibleForTesting | 
|  | void restoreExitFunction() { | 
|  | _exitFunction = _defaultExitFunction; | 
|  | } | 
|  |  | 
|  | /// A portable version of [io.ProcessSignal]. | 
|  | /// | 
|  | /// Listening on signals that don't exist on the current platform is just a | 
|  | /// no-op. This is in contrast to [io.ProcessSignal], where listening to | 
|  | /// non-existent signals throws an exception. | 
|  | class ProcessSignal implements io.ProcessSignal { | 
|  | @visibleForTesting | 
|  | const ProcessSignal(this._delegate); | 
|  |  | 
|  | static const ProcessSignal SIGWINCH = _PosixProcessSignal._(io.ProcessSignal.sigwinch); | 
|  | static const ProcessSignal SIGTERM = _PosixProcessSignal._(io.ProcessSignal.sigterm); | 
|  | static const ProcessSignal SIGUSR1 = _PosixProcessSignal._(io.ProcessSignal.sigusr1); | 
|  | static const ProcessSignal SIGUSR2 = _PosixProcessSignal._(io.ProcessSignal.sigusr2); | 
|  | static const ProcessSignal SIGINT =  ProcessSignal(io.ProcessSignal.sigint); | 
|  | static const ProcessSignal SIGKILL =  ProcessSignal(io.ProcessSignal.sigkill); | 
|  |  | 
|  | final io.ProcessSignal _delegate; | 
|  |  | 
|  | @override | 
|  | Stream<ProcessSignal> watch() { | 
|  | return _delegate.watch().map<ProcessSignal>((io.ProcessSignal signal) => this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | String toString() => _delegate.toString(); | 
|  | } | 
|  |  | 
|  | /// A [ProcessSignal] that is only available on Posix platforms. | 
|  | /// | 
|  | /// Listening to a [_PosixProcessSignal] is a no-op on Windows. | 
|  | class _PosixProcessSignal extends ProcessSignal { | 
|  |  | 
|  | const _PosixProcessSignal._(io.ProcessSignal wrappedSignal) : super(wrappedSignal); | 
|  |  | 
|  | @override | 
|  | Stream<ProcessSignal> watch() { | 
|  | if (platform.isWindows) | 
|  | return const Stream<ProcessSignal>.empty(); | 
|  | return super.watch(); | 
|  | } | 
|  | } | 
|  |  | 
|  | class Stdio { | 
|  | const Stdio(); | 
|  |  | 
|  | Stream<List<int>> get stdin => io.stdin; | 
|  | io.IOSink get stdout => io.stdout; | 
|  | io.IOSink get stderr => io.stderr; | 
|  |  | 
|  | bool get hasTerminal => io.stdout.hasTerminal; | 
|  | int get terminalColumns => hasTerminal ? io.stdout.terminalColumns : null; | 
|  | int get terminalLines => hasTerminal ? io.stdout.terminalLines : null; | 
|  | bool get supportsAnsiEscapes => hasTerminal ? io.stdout.supportsAnsiEscapes : false; | 
|  | } | 
|  |  | 
|  | io.IOSink get stderr => context[Stdio].stderr; | 
|  |  | 
|  | Stream<List<int>> get stdin => context[Stdio].stdin; | 
|  |  | 
|  | io.IOSink get stdout => context[Stdio].stdout; | 
|  |  | 
|  | Stdio get stdio => context[Stdio]; |