mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
[dart:io] Backport semantic changes from the dart:io NNBD migration.
The NNBD migration required making subtle changes to some dart:io semantics in order to provide a better API. This change backports these semantic changes to the unmigrated SDK so any issues can be discovered now instead of blocking the future SDK unfork. The Process class will now throw a StateError if the process is detached upon accessing the stdin, stdout, stderr, and exitCode getters. The Socket class will now throw a SocketException if the socket has been destroyed or upgraded to a secure socket upon setting or getting socket options. Change-Id: I956fd07e713e51ebd479ebbfe4790d8d2fdf0744 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133989 Commit-Queue: Jonas Termansen <sortie@google.com> Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
This commit is contained in:
parent
4d32ec8d21
commit
4cd6243d77
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -17,6 +17,16 @@ used (see Issue [39627][]).
|
||||||
|
|
||||||
#### `dart:io`
|
#### `dart:io`
|
||||||
|
|
||||||
|
* The `Process` class will now throw a `StateError` if the process is detached
|
||||||
|
upon accessing the `exitCode` getter. It also now throws when the process is
|
||||||
|
detached without stdio upon accessing the `stdin`, `stdout`, and `stderr`
|
||||||
|
getters. Previously these getters would all return `null`.
|
||||||
|
|
||||||
|
* The `Socket` class will now throw a `SocketException` if the socket has been
|
||||||
|
destroyed or upgraded to a secure socket upon setting or getting socket
|
||||||
|
options. Previously setting a socket options would be ignored and getting a
|
||||||
|
socket option would return `null`.
|
||||||
|
|
||||||
### Dart VM
|
### Dart VM
|
||||||
|
|
||||||
### Tools
|
### Tools
|
||||||
|
|
|
@ -534,19 +534,16 @@ class _ProcessImpl extends _ProcessImplNativeWrapper implements Process {
|
||||||
_wait(_NativeSocket stdin, _NativeSocket stdout, _NativeSocket stderr,
|
_wait(_NativeSocket stdin, _NativeSocket stdout, _NativeSocket stderr,
|
||||||
_NativeSocket exitHandler) native "Process_Wait";
|
_NativeSocket exitHandler) native "Process_Wait";
|
||||||
|
|
||||||
Stream<List<int>> get stdout {
|
Stream<List<int>> get stdout =>
|
||||||
return _stdout;
|
_stdout ?? (throw StateError("Process is detached"));
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<int>> get stderr {
|
Stream<List<int>> get stderr =>
|
||||||
return _stderr;
|
_stderr ?? (throw StateError("Process is detached"));
|
||||||
}
|
|
||||||
|
|
||||||
IOSink get stdin {
|
IOSink get stdin => _stdin ?? (throw StateError("Process is detached"));
|
||||||
return _stdin;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int> get exitCode => _exitCode != null ? _exitCode.future : null;
|
Future<int> get exitCode =>
|
||||||
|
_exitCode?.future ?? (throw StateError("Process is detached"));
|
||||||
|
|
||||||
bool kill([ProcessSignal signal = ProcessSignal.sigterm]) {
|
bool kill([ProcessSignal signal = ProcessSignal.sigterm]) {
|
||||||
if (signal is! ProcessSignal) {
|
if (signal is! ProcessSignal) {
|
||||||
|
|
|
@ -1779,40 +1779,37 @@ class _Socket extends Stream<Uint8List> implements Socket {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setOption(SocketOption option, bool enabled) {
|
bool setOption(SocketOption option, bool enabled) {
|
||||||
if (_raw == null) return false;
|
if (_raw == null) throw const SocketException.closed();
|
||||||
return _raw.setOption(option, enabled);
|
return _raw.setOption(option, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List getRawOption(RawSocketOption option) {
|
Uint8List getRawOption(RawSocketOption option) {
|
||||||
if (_raw == null) return null;
|
if (_raw == null) throw const SocketException.closed();
|
||||||
return _raw.getRawOption(option);
|
return _raw.getRawOption(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRawOption(RawSocketOption option) {
|
void setRawOption(RawSocketOption option) {
|
||||||
_raw?.setRawOption(option);
|
if (_raw == null) throw const SocketException.closed();
|
||||||
|
_raw.setRawOption(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get port {
|
int get port {
|
||||||
if (_raw == null) throw const SocketException.closed();
|
if (_raw == null) throw const SocketException.closed();
|
||||||
;
|
|
||||||
return _raw.port;
|
return _raw.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternetAddress get address {
|
InternetAddress get address {
|
||||||
if (_raw == null) throw const SocketException.closed();
|
if (_raw == null) throw const SocketException.closed();
|
||||||
;
|
|
||||||
return _raw.address;
|
return _raw.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get remotePort {
|
int get remotePort {
|
||||||
if (_raw == null) throw const SocketException.closed();
|
if (_raw == null) throw const SocketException.closed();
|
||||||
;
|
|
||||||
return _raw.remotePort;
|
return _raw.remotePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternetAddress get remoteAddress {
|
InternetAddress get remoteAddress {
|
||||||
if (_raw == null) throw const SocketException.closed();
|
if (_raw == null) throw const SocketException.closed();
|
||||||
;
|
|
||||||
return _raw.remoteAddress;
|
return _raw.remoteAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -652,21 +652,29 @@ abstract class RawSocket implements Stream<RawSocketEvent> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the port used by this socket.
|
* Returns the port used by this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
int get port;
|
int get port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remote port connected to by this socket.
|
* Returns the remote port connected to by this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
int get remotePort;
|
int get remotePort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the [InternetAddress] used to connect this socket.
|
* Returns the [InternetAddress] used to connect this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
InternetAddress get address;
|
InternetAddress get address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remote [InternetAddress] connected to by this socket.
|
* Returns the remote [InternetAddress] connected to by this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
InternetAddress get remoteAddress;
|
InternetAddress get remoteAddress;
|
||||||
|
|
||||||
|
@ -791,6 +799,9 @@ abstract class Socket implements Stream<Uint8List>, IOSink {
|
||||||
* available options.
|
* available options.
|
||||||
*
|
*
|
||||||
* Returns [:true:] if the option was set successfully, false otherwise.
|
* Returns [:true:] if the option was set successfully, false otherwise.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket has been destroyed or upgraded to
|
||||||
|
* a secure socket.
|
||||||
*/
|
*/
|
||||||
bool setOption(SocketOption option, bool enabled);
|
bool setOption(SocketOption option, bool enabled);
|
||||||
|
|
||||||
|
@ -800,7 +811,8 @@ abstract class Socket implements Stream<Uint8List>, IOSink {
|
||||||
*
|
*
|
||||||
* Returns the [RawSocketOption.value] on success.
|
* Returns the [RawSocketOption.value] on success.
|
||||||
*
|
*
|
||||||
* Throws an [OSError] on failure.
|
* Throws an [OSError] on failure and a [SocketException] if the socket has
|
||||||
|
* been destroyed or upgraded to a secure socket.
|
||||||
*/
|
*/
|
||||||
Uint8List getRawOption(RawSocketOption option);
|
Uint8List getRawOption(RawSocketOption option);
|
||||||
|
|
||||||
|
@ -808,27 +820,36 @@ abstract class Socket implements Stream<Uint8List>, IOSink {
|
||||||
* Use [setRawOption] to customize the [RawSocket]. See [RawSocketOption] for
|
* Use [setRawOption] to customize the [RawSocket]. See [RawSocketOption] for
|
||||||
* available options.
|
* available options.
|
||||||
*
|
*
|
||||||
* Throws an [OSError] on failure.
|
* Throws an [OSError] on failure and a [SocketException] if the socket has
|
||||||
|
* been destroyed or upgraded to a secure socket.
|
||||||
*/
|
*/
|
||||||
void setRawOption(RawSocketOption option);
|
void setRawOption(RawSocketOption option);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the port used by this socket.
|
* Returns the port used by this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
int get port;
|
int get port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remote port connected to by this socket.
|
* Returns the remote port connected to by this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
int get remotePort;
|
int get remotePort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the [InternetAddress] used to connect this socket.
|
* Returns the [InternetAddress] used to connect this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
InternetAddress get address;
|
InternetAddress get address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remote [InternetAddress] connected to by this socket.
|
* Returns the remote [InternetAddress] connected to by this socket.
|
||||||
|
*
|
||||||
|
* Throws a [SocketException] if the socket is closed.
|
||||||
*/
|
*/
|
||||||
InternetAddress get remoteAddress;
|
InternetAddress get remoteAddress;
|
||||||
|
|
||||||
|
|
|
@ -510,7 +510,7 @@ class _ProcessImpl extends _ProcessImplNativeWrapper implements Process {
|
||||||
_stdout ?? (throw StateError("Process is detached"));
|
_stdout ?? (throw StateError("Process is detached"));
|
||||||
|
|
||||||
Stream<List<int>> get stderr =>
|
Stream<List<int>> get stderr =>
|
||||||
_stdout ?? (throw StateError("Process is detached"));
|
_stderr ?? (throw StateError("Process is detached"));
|
||||||
|
|
||||||
IOSink get stdin => _stdin ?? (throw StateError("Process is detached"));
|
IOSink get stdin => _stdin ?? (throw StateError("Process is detached"));
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@ import 'dart:io';
|
||||||
import "package:async_helper/async_helper.dart";
|
import "package:async_helper/async_helper.dart";
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
import "process_test_util.dart";
|
|
||||||
|
|
||||||
void test() {
|
void test() {
|
||||||
asyncStart();
|
asyncStart();
|
||||||
var script =
|
var script =
|
||||||
|
@ -27,10 +25,10 @@ void test() {
|
||||||
future.then((process) {
|
future.then((process) {
|
||||||
Expect.isNotNull(process.pid);
|
Expect.isNotNull(process.pid);
|
||||||
Expect.isTrue(process.pid is int);
|
Expect.isTrue(process.pid is int);
|
||||||
Expect.isNull(process.exitCode);
|
Expect.throwsStateError(() => process.exitCode);
|
||||||
Expect.isNull(process.stderr);
|
Expect.throwsStateError(() => process.stderr);
|
||||||
Expect.isNull(process.stdin);
|
Expect.throwsStateError(() => process.stdin);
|
||||||
Expect.isNull(process.stdout);
|
Expect.throwsStateError(() => process.stdout);
|
||||||
Expect.isTrue(process.kill());
|
Expect.isTrue(process.kill());
|
||||||
}).whenComplete(() {
|
}).whenComplete(() {
|
||||||
asyncEnd();
|
asyncEnd();
|
||||||
|
@ -47,7 +45,7 @@ void testWithStdio() {
|
||||||
future.then((process) {
|
future.then((process) {
|
||||||
Expect.isNotNull(process.pid);
|
Expect.isNotNull(process.pid);
|
||||||
Expect.isTrue(process.pid is int);
|
Expect.isTrue(process.pid is int);
|
||||||
Expect.isNull(process.exitCode);
|
Expect.throwsStateError(() => process.exitCode);
|
||||||
var message = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
var message = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
process.stdin.add(message);
|
process.stdin.add(message);
|
||||||
process.stdin.flush().then((_) => process.stdin.close());
|
process.stdin.flush().then((_) => process.stdin.close());
|
||||||
|
|
Loading…
Reference in a new issue