Revert "Revert "Make stdout/stderr async""
This reverts commit r42909 TBR=ricow@google.com BUG= Review URL: https://codereview.chromium.org//850333002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42910 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -36,7 +36,7 @@ class StdioAnalysisServer {
|
||||
Future serveStdio() {
|
||||
ByteStreamServerChannel serverChannel = new ByteStreamServerChannel(
|
||||
stdin,
|
||||
stdout.nonBlocking,
|
||||
stdout,
|
||||
socketServer.instrumentationService);
|
||||
socketServer.createAnalysisServer(serverChannel);
|
||||
return serverChannel.closed;
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace bin {
|
||||
V(Stdin_SetEchoMode, 1) \
|
||||
V(Stdin_GetLineMode, 0) \
|
||||
V(Stdin_SetLineMode, 1) \
|
||||
V(Stdout_GetTerminalSize, 1) \
|
||||
V(Stdout_GetTerminalSize, 0) \
|
||||
V(StringToSystemEncoding, 1) \
|
||||
V(SystemEncodingToString, 1)
|
||||
|
||||
|
||||
@@ -45,13 +45,8 @@ void FUNCTION_NAME(Stdin_SetLineMode)(Dart_NativeArguments args) {
|
||||
|
||||
|
||||
void FUNCTION_NAME(Stdout_GetTerminalSize)(Dart_NativeArguments args) {
|
||||
intptr_t fd = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
|
||||
if (fd != 1 && fd != 2) {
|
||||
Dart_PropagateError(Dart_NewApiError("Terminal fd must be 1 or 2"));
|
||||
}
|
||||
|
||||
int size[2];
|
||||
if (Stdout::GetTerminalSize(fd, size)) {
|
||||
if (Stdout::GetTerminalSize(size)) {
|
||||
Dart_Handle list = Dart_NewList(2);
|
||||
Dart_ListSetAt(list, 0, Dart_NewInteger(size[0]));
|
||||
Dart_ListSetAt(list, 1, Dart_NewInteger(size[1]));
|
||||
|
||||
+2
-1
@@ -32,7 +32,7 @@ class Stdin {
|
||||
|
||||
class Stdout {
|
||||
public:
|
||||
static bool GetTerminalSize(intptr_t fd, int size[2]);
|
||||
static bool GetTerminalSize(int size[2]);
|
||||
|
||||
private:
|
||||
DISALLOW_ALLOCATION();
|
||||
@@ -43,3 +43,4 @@ class Stdout {
|
||||
} // namespace dart
|
||||
|
||||
#endif // BIN_STDIO_H_
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ void Stdin::SetLineMode(bool enabled) {
|
||||
}
|
||||
|
||||
|
||||
bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
|
||||
bool Stdout::GetTerminalSize(int size[2]) {
|
||||
struct winsize w;
|
||||
if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w)) == 0 &&
|
||||
if (NO_RETRY_EXPECTED(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)) == 0 &&
|
||||
(w.ws_col != 0 || w.ws_row != 0)) {
|
||||
size[0] = w.ws_col;
|
||||
size[1] = w.ws_row;
|
||||
@@ -80,3 +80,4 @@ bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_LINUX)
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ void Stdin::SetLineMode(bool enabled) {
|
||||
}
|
||||
|
||||
|
||||
bool Stdout::GetTerminalSize(int fd, int size[2]) {
|
||||
bool Stdout::GetTerminalSize(int size[2]) {
|
||||
struct winsize w;
|
||||
if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w) == 0) &&
|
||||
if (NO_RETRY_EXPECTED(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) &&
|
||||
(w.ws_col != 0 || w.ws_row != 0)) {
|
||||
size[0] = w.ws_col;
|
||||
size[1] = w.ws_row;
|
||||
|
||||
@@ -17,13 +17,20 @@ patch class _StdIOUtils {
|
||||
}
|
||||
|
||||
static _getStdioOutputStream(int fd) {
|
||||
wrap(sink) {
|
||||
if (fd == 1) {
|
||||
return new Stdout._(sink);
|
||||
} else {
|
||||
return new _StdSink(sink);
|
||||
}
|
||||
}
|
||||
assert(fd == 1 || fd == 2);
|
||||
switch (_getStdioHandleType(fd)) {
|
||||
case _STDIO_HANDLE_TYPE_TERMINAL:
|
||||
case _STDIO_HANDLE_TYPE_PIPE:
|
||||
case _STDIO_HANDLE_TYPE_SOCKET:
|
||||
case _STDIO_HANDLE_TYPE_FILE:
|
||||
return new Stdout._(new IOSink(new _StdConsumer(fd)), fd);
|
||||
return wrap(new IOSink(new _FileStreamConsumer.fromStdio(fd)));
|
||||
default:
|
||||
throw new FileSystemException("Unsupported stdin type");
|
||||
}
|
||||
@@ -56,27 +63,27 @@ patch class Stdin {
|
||||
}
|
||||
|
||||
patch class Stdout {
|
||||
/* patch */ bool _hasTerminal(int fd) {
|
||||
/* patch */ bool get hasTerminal {
|
||||
try {
|
||||
_terminalSize(fd);
|
||||
_terminalSize;
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* patch */ int _terminalColumns(int fd) => _terminalSize(fd)[0];
|
||||
/* patch */ int _terminalLines(int fd) => _terminalSize(fd)[1];
|
||||
/* patch */ int get terminalColumns => _terminalSize[0];
|
||||
/* patch */ int get terminalLines => _terminalSize[1];
|
||||
|
||||
static List _terminalSize(int fd) {
|
||||
var size = _getTerminalSize(fd);
|
||||
static List get _terminalSize {
|
||||
var size = _getTerminalSize();
|
||||
if (size is! List) {
|
||||
throw new StdoutException("Could not get terminal size", size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static _getTerminalSize(int fd) native "Stdout_GetTerminalSize";
|
||||
static _getTerminalSize() native "Stdout_GetTerminalSize";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -65,13 +65,8 @@ void Stdin::SetLineMode(bool enabled) {
|
||||
}
|
||||
|
||||
|
||||
bool Stdout::GetTerminalSize(int fd, int size[2]) {
|
||||
HANDLE h;
|
||||
if (fd == 1) {
|
||||
h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
} else {
|
||||
h = GetStdHandle(STD_ERROR_HANDLE);
|
||||
}
|
||||
bool Stdout::GetTerminalSize(int size[2]) {
|
||||
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
if (!GetConsoleScreenBufferInfo(h, &info)) return false;
|
||||
size[0] = info.srWindow.Right - info.srWindow.Left + 1;
|
||||
|
||||
@@ -495,15 +495,15 @@ class Stdin {
|
||||
@patch
|
||||
class Stdout {
|
||||
@patch
|
||||
bool _hasTerminal(int fd) {
|
||||
bool get hasTerminal {
|
||||
throw new UnsupportedError("Stdout.hasTerminal");
|
||||
}
|
||||
@patch
|
||||
int _terminalColumns(int fd) {
|
||||
int get terminalColumns {
|
||||
throw new UnsupportedError("Stdout.terminalColumns");
|
||||
}
|
||||
@patch
|
||||
int _terminalLines(int fd) {
|
||||
int get terminalLines {
|
||||
throw new UnsupportedError("Stdout.terminalLines");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2013, 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.
|
||||
|
||||
part of dart.io;
|
||||
|
||||
Console _console;
|
||||
|
||||
Console get console {
|
||||
if (_console == null) {
|
||||
_console = new Console._();
|
||||
}
|
||||
return _console;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Console] provides synchronous write access to stdout and stderr.
|
||||
*
|
||||
* The direct access to stdout and stderr through [stdout] and [stderr]
|
||||
* provides non-blocking async operations.
|
||||
*/
|
||||
class Console {
|
||||
final ConsoleSink _stdout;
|
||||
final ConsoleSink _stderr;
|
||||
|
||||
Console._()
|
||||
: _stdout = new ConsoleSink._(1),
|
||||
_stderr = new ConsoleSink._(2);
|
||||
|
||||
/**
|
||||
* Write to stdout.
|
||||
*/
|
||||
ConsoleSink get log => _stdout;
|
||||
|
||||
/**
|
||||
* Write to stderr.
|
||||
*/
|
||||
ConsoleSink get error => _stderr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sink class used for console writing.
|
||||
*
|
||||
* This class has a call method so you can call it directly. Calling
|
||||
* it directly is the same as calling its `writeln` method.
|
||||
*/
|
||||
class ConsoleSink implements Sink<List<int>>, StringSink {
|
||||
IOSink _sink;
|
||||
|
||||
ConsoleSink._(int fd) {
|
||||
_sink = new IOSink(new _ConsoleConsumer(fd));
|
||||
}
|
||||
|
||||
void call([Object message = ""]) => _sink.writeln(message);
|
||||
|
||||
void add(List<int> data) => _sink.add(data);
|
||||
|
||||
void close() {}
|
||||
|
||||
void write(Object obj) => _sink.write(obj);
|
||||
|
||||
void writeAll(Iterable objects, [String separator=""]) =>
|
||||
_sink.writeAll(objects, separator);
|
||||
|
||||
void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
|
||||
|
||||
void writeln([Object obj=""]) => _sink.writeln(obj);
|
||||
}
|
||||
|
||||
class _ConsoleConsumer implements StreamConsumer<List<int>> {
|
||||
final _file;
|
||||
|
||||
_ConsoleConsumer(int fd) : _file = _File._openStdioSync(fd);
|
||||
|
||||
Future addStream(Stream<List<int>> stream) {
|
||||
var completer = new Completer();
|
||||
var sub;
|
||||
sub = stream.listen(
|
||||
(data) {
|
||||
try {
|
||||
_file.writeFromSync(data);
|
||||
} catch (e, s) {
|
||||
sub.cancel();
|
||||
completer.completeError(e, s);
|
||||
}
|
||||
},
|
||||
onError: completer.completeError,
|
||||
onDone: completer.complete,
|
||||
cancelOnError: true);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future close() {
|
||||
_file.closeSync();
|
||||
return new Future.value();
|
||||
}
|
||||
}
|
||||
@@ -212,6 +212,7 @@ import 'dart:typed_data';
|
||||
|
||||
part 'bytes_builder.dart';
|
||||
part 'common.dart';
|
||||
part 'console.dart';
|
||||
part 'crypto.dart';
|
||||
part 'data_transformer.dart';
|
||||
part 'directory.dart';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'sources': [
|
||||
'bytes_builder.dart',
|
||||
'common.dart',
|
||||
'console.dart',
|
||||
'crypto.dart',
|
||||
'data_transformer.dart',
|
||||
'directory.dart',
|
||||
|
||||
+8
-62
@@ -149,29 +149,17 @@ class Stdin extends _StdStream implements Stream<List<int>> {
|
||||
|
||||
|
||||
/**
|
||||
* [Stdout] represents the [IOSink] for either `stdout` or `stderr`.
|
||||
* [Stdout] exposes methods to query the terminal for properties.
|
||||
*
|
||||
* It provides a *blocking* `IOSink`, so using this to write will block until
|
||||
* the output is written.
|
||||
*
|
||||
* In some situations this blocking behavior is undesirable as it does not
|
||||
* provide the same non-blocking behavior as dart:io in general exposes.
|
||||
* Use the property [nonBlocking] to get an `IOSink` which has the non-blocking
|
||||
* behavior.
|
||||
*
|
||||
* This class can also be used to check whether `stdout` or `stderr` is
|
||||
* connected to a terminal and query some terminal properties.
|
||||
* Use [hasTerminal] to test if there is a terminal associated to stdout.
|
||||
*/
|
||||
class Stdout extends _StdSink implements IOSink {
|
||||
final int _fd;
|
||||
IOSink _nonBlocking;
|
||||
|
||||
Stdout._(IOSink sink, this._fd) : super(sink);
|
||||
Stdout._(IOSink sink) : super(sink);
|
||||
|
||||
/**
|
||||
* Returns true if there is a terminal attached to stdout.
|
||||
*/
|
||||
bool get hasTerminal => _hasTerminal(_fd);
|
||||
external bool get hasTerminal;
|
||||
|
||||
/**
|
||||
* Get the number of columns of the terminal.
|
||||
@@ -179,7 +167,7 @@ class Stdout extends _StdSink implements IOSink {
|
||||
* If no terminal is attached to stdout, a [StdoutException] is thrown. See
|
||||
* [hasTerminal] for more info.
|
||||
*/
|
||||
int get terminalColumns => _terminalColumns(_fd);
|
||||
external int get terminalColumns;
|
||||
|
||||
/**
|
||||
* Get the number of lines of the terminal.
|
||||
@@ -187,21 +175,7 @@ class Stdout extends _StdSink implements IOSink {
|
||||
* If no terminal is attached to stdout, a [StdoutException] is thrown. See
|
||||
* [hasTerminal] for more info.
|
||||
*/
|
||||
int get terminalLines => _terminalLines(_fd);
|
||||
|
||||
external bool _hasTerminal(int fd);
|
||||
external int _terminalColumns(int fd);
|
||||
external int _terminalLines(int fd);
|
||||
|
||||
/**
|
||||
* Get a non-blocking `IOSink`.
|
||||
*/
|
||||
IOSink get nonBlocking {
|
||||
if (_nonBlocking == null) {
|
||||
_nonBlocking = new IOSink(new _FileStreamConsumer.fromStdio(_fd));
|
||||
}
|
||||
return _nonBlocking;
|
||||
}
|
||||
external int get terminalLines;
|
||||
}
|
||||
|
||||
|
||||
@@ -216,34 +190,6 @@ class StdoutException implements IOException {
|
||||
}
|
||||
}
|
||||
|
||||
class _StdConsumer implements StreamConsumer<List<int>> {
|
||||
final _file;
|
||||
|
||||
_StdConsumer(int fd) : _file = _File._openStdioSync(fd);
|
||||
|
||||
Future addStream(Stream<List<int>> stream) {
|
||||
var completer = new Completer();
|
||||
var sub;
|
||||
sub = stream.listen(
|
||||
(data) {
|
||||
try {
|
||||
_file.writeFromSync(data);
|
||||
} catch (e, s) {
|
||||
sub.cancel();
|
||||
completer.completeError(e, s);
|
||||
}
|
||||
},
|
||||
onError: completer.completeError,
|
||||
onDone: completer.complete,
|
||||
cancelOnError: true);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future close() {
|
||||
_file.closeSync();
|
||||
return new Future.value();
|
||||
}
|
||||
}
|
||||
|
||||
class _StdSink implements IOSink {
|
||||
final IOSink _sink;
|
||||
@@ -281,7 +227,7 @@ class StdioType {
|
||||
|
||||
Stdin _stdin;
|
||||
Stdout _stdout;
|
||||
Stdout _stderr;
|
||||
IOSink _stderr;
|
||||
|
||||
|
||||
/// The standard input stream of data read by this program.
|
||||
@@ -303,7 +249,7 @@ Stdout get stdout {
|
||||
|
||||
|
||||
/// The standard output stream of errors written by this program.
|
||||
Stdout get stderr {
|
||||
IOSink get stderr {
|
||||
if (_stderr == null) {
|
||||
_stderr = _StdIOUtils._getStdioOutputStream(2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2014, 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.
|
||||
|
||||
import "dart:io";
|
||||
|
||||
class Message {
|
||||
final message;
|
||||
Message(this.message);
|
||||
toString() => message;
|
||||
}
|
||||
|
||||
void test(ConsoleSink sink) {
|
||||
sink.add([65, 66, 67]);
|
||||
sink.write('DEF');
|
||||
sink.writeAll(['GH', 'I']);
|
||||
sink.writeCharCode(74);
|
||||
sink.writeln('KLM');
|
||||
}
|
||||
|
||||
void main(List<String> arguments) {
|
||||
console.log('stdout');
|
||||
console.error('stderr');
|
||||
console.log();
|
||||
console.error();
|
||||
console.log(new Message('tuodts'));
|
||||
console.error(new Message('rredts'));
|
||||
test(console.log);
|
||||
test(console.error);
|
||||
exit(1);
|
||||
}
|
||||
+2
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2013, 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.
|
||||
|
||||
@@ -8,8 +8,7 @@ import "dart:io";
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
void main() {
|
||||
var script =
|
||||
Platform.script.resolve("stdio_nonblocking_script.dart").toFilePath();
|
||||
var script = Platform.script.resolve("console_script.dart").toFilePath();
|
||||
Process.run(Platform.executable,
|
||||
['--checked', script],
|
||||
stdoutEncoding: ASCII,
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) 2015, 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.
|
||||
|
||||
import "dart:async";
|
||||
import "dart:io";
|
||||
|
||||
class Message {
|
||||
final message;
|
||||
Message(this.message);
|
||||
toString() => message;
|
||||
}
|
||||
|
||||
void test(IOSink sink) {
|
||||
sink.add([65, 66, 67]);
|
||||
sink.write('DEF');
|
||||
sink.writeAll(['GH', 'I']);
|
||||
sink.writeCharCode(74);
|
||||
sink.writeln('KLM');
|
||||
}
|
||||
|
||||
void main(List<String> arguments) {
|
||||
stdout.nonBlocking.writeln('stdout');
|
||||
stderr.nonBlocking.writeln('stderr');
|
||||
stdout.nonBlocking.writeln();
|
||||
stderr.nonBlocking.writeln();
|
||||
stdout.nonBlocking.writeln(new Message('tuodts'));
|
||||
stderr.nonBlocking.writeln(new Message('rredts'));
|
||||
test(stdout.nonBlocking);
|
||||
test(stderr.nonBlocking);
|
||||
Future.wait([stdout.nonBlocking.close(),
|
||||
stderr.nonBlocking.close()])
|
||||
.then((_) => exit(1));
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright (c) 2014, 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.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:async";
|
||||
import "dart:convert";
|
||||
import "dart:io";
|
||||
|
||||
callIOSink(IOSink sink) {
|
||||
// Call all methods on IOSink.
|
||||
sink.encoding = ASCII;
|
||||
Expect.equals(ASCII, sink.encoding);
|
||||
sink.write("Hello\n");
|
||||
sink.writeln("Hello");
|
||||
sink.writeAll(["H", "e", "l", "lo\n"]);
|
||||
sink.writeCharCode(72);
|
||||
sink.add([101, 108, 108, 111, 10]);
|
||||
|
||||
var controller = new StreamController(sync: true);
|
||||
var future = sink.addStream(controller.stream);
|
||||
controller.add([72, 101, 108]);
|
||||
controller.add([108, 111, 10]);
|
||||
controller.close();
|
||||
|
||||
future.then((_) {
|
||||
controller = new StreamController(sync: true);
|
||||
controller.stream.pipe(sink);
|
||||
controller.add([72, 101, 108]);
|
||||
controller.add([108, 111, 10]);
|
||||
controller.close();
|
||||
});
|
||||
}
|
||||
|
||||
main() {
|
||||
callIOSink(stdout.nonBlocking);
|
||||
stdout.nonBlocking.done.then((_) {
|
||||
callIOSink(stderr.nonBlocking);
|
||||
stderr.nonBlocking.done.then((_) {
|
||||
stdout.close();
|
||||
stderr.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) 2013, 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.
|
||||
|
||||
import "dart:io";
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
void testTerminalSize(std) {
|
||||
if (std.hasTerminal) {
|
||||
Expect.notEquals(0, std.terminalColumns);
|
||||
Expect.notEquals(0, std.terminalLines);
|
||||
} else {
|
||||
Expect.throws(() => std.terminalColumns, (e) => e is StdoutException);
|
||||
Expect.throws(() => std.terminalLines, (e) => e is StdoutException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
testTerminalSize(stdout);
|
||||
testTerminalSize(stderr);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2013, 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.
|
||||
|
||||
import "dart:io";
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
void testTerminalSize() {
|
||||
if (stdout.hasTerminal) {
|
||||
Expect.notEquals(0, stdout.terminalColumns);
|
||||
Expect.notEquals(0, stdout.terminalLines);
|
||||
} else {
|
||||
Expect.throws(() => stdout.terminalColumns, (e) => e is StdoutException);
|
||||
Expect.throws(() => stdout.terminalLines, (e) => e is StdoutException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
testTerminalSize();
|
||||
}
|
||||
Reference in New Issue
Block a user