diff --git a/bin/sass.dart b/bin/sass.dart index b49cdd4e2..bc8bcebe9 100644 --- a/bin/sass.dart +++ b/bin/sass.dart @@ -54,6 +54,7 @@ Future main(List args) async { var graph = StylesheetGraph( ImportCache(loadPaths: options.loadPaths, logger: options.logger)); if (options.watch) { + ensureWatchWillExit(); await watch(options, graph); return; } diff --git a/lib/src/io/interface.dart b/lib/src/io/interface.dart index 0ee35bc53..4784b0d41 100644 --- a/lib/src/io/interface.dart +++ b/lib/src/io/interface.dart @@ -94,6 +94,14 @@ String? getEnvironmentVariable(String name) => throw ''; int get exitCode => throw ''; set exitCode(int value) => throw ''; +/// Attaches a listener to exit when stdin closes. +/// +/// The listener is *not* attached when stdin is a TTY because it would +/// interfere with the Unix background job system. If we read from stdin and +/// then Ctrl+Z to move the process to the background, it will incorrectly +/// cause the job to stop. See: https://github.com/brunch/brunch/issues/998. +void ensureWatchWillExit() => throw ''; + /// Recursively watches the directory at [path] for modifications. /// /// Returns a future that completes with a single-subscription stream once the diff --git a/lib/src/io/node.dart b/lib/src/io/node.dart index f8ac7f129..62896488e 100644 --- a/lib/src/io/node.dart +++ b/lib/src/io/node.dart @@ -196,6 +196,9 @@ final stderr = Stderr(process.stderr); @JS('process.stdout.isTTY') external bool? get isTTY; +@JS('process.stdin.isTTY') +external bool? get isStdinTTY; + bool get hasTerminal => isTTY == true; bool get isWindows => process.platform == 'win32'; @@ -213,6 +216,12 @@ int get exitCode => process.exitCode; set exitCode(int code) => process.exitCode = code; +void ensureWatchWillExit() { + if (isStdinTTY == true) { + process.stdin.on('end', allowInterop(() => process.exit(0))); + } +} + Future> watchDir(String path, {bool poll = false}) { var watcher = chokidar.watch( path, ChokidarOptions(disableGlobbing: true, usePolling: poll)); diff --git a/lib/src/io/vm.dart b/lib/src/io/vm.dart index d6ab96c1c..f82315254 100644 --- a/lib/src/io/vm.dart +++ b/lib/src/io/vm.dart @@ -87,6 +87,10 @@ DateTime modificationTime(String path) { String? getEnvironmentVariable(String name) => io.Platform.environment[name]; +void ensureWatchWillExit() { + if (!io.stdin.hasTerminal) io.stdin.listen(null, onDone: () => io.exit(0)); +} + Future> watchDir(String path, {bool poll = false}) async { var watcher = poll ? PollingDirectoryWatcher(path) : DirectoryWatcher(path);