null safety (#154)
Co-authored-by: Nate Bosch <nbosch@google.com>
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 6d84019..3ddce8c 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -14,7 +14,7 @@
jobs:
# Check code formatting and static analysis on a single OS (linux)
- # against Dart dev and stable.
+ # against Dart dev.
analyze:
runs-on: ubuntu-latest
strategy:
@@ -42,7 +42,8 @@
fail-fast: false
matrix:
os: [ubuntu-latest]
- sdk: [stable, dev]
+ # TODO: beta -> 2.12.0 once it's stable!
+ sdk: [beta, dev]
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v0.5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a83f991..261415e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 2.0.0-dev
+
+- Support null safety.
+- Require Dart 2.12.
+
## 1.2.0
* Add `protocols` argument to `WebSocketChannel.connect`. See the docs for
diff --git a/lib/html.dart b/lib/html.dart
index 7afaf94..1694eb8 100644
--- a/lib/html.dart
+++ b/lib/html.dart
@@ -19,31 +19,31 @@
final WebSocket _webSocket;
@override
- String get protocol => _webSocket.protocol;
+ String? get protocol => _webSocket.protocol;
@override
- int get closeCode => _closeCode;
- int _closeCode;
+ int? get closeCode => _closeCode;
+ int? _closeCode;
@override
- String get closeReason => _closeReason;
- String _closeReason;
+ String? get closeReason => _closeReason;
+ String? _closeReason;
/// The number of bytes of data that have been queued but not yet transmitted
/// to the network.
- int get bufferedAmount => _webSocket.bufferedAmount;
+ int? get bufferedAmount => _webSocket.bufferedAmount;
/// The close code set by the local user.
///
/// To ensure proper ordering, this is stored until we get a done event on
/// [_controller.local.stream].
- int _localCloseCode;
+ int? _localCloseCode;
/// The close reason set by the local user.
///
/// To ensure proper ordering, this is stored until we get a done event on
/// [_controller.local.stream].
- String _localCloseReason;
+ String? _localCloseReason;
@override
Stream get stream => _controller.foreign.stream;
@@ -51,8 +51,7 @@
StreamChannelController(sync: true, allowForeignErrors: false);
@override
- WebSocketSink get sink => _sink;
- WebSocketSink _sink;
+ late final WebSocketSink sink = _HtmlWebSocketSink(this);
/// Creates a new WebSocket connection.
///
@@ -66,14 +65,12 @@
/// binary messages to be delivered as [Uint8List]s. If it's
/// [BinaryType.blob], they're delivered as [Blob]s instead.
HtmlWebSocketChannel.connect(url,
- {Iterable<String> protocols, BinaryType binaryType})
+ {Iterable<String>? protocols, BinaryType? binaryType})
: this(WebSocket(url.toString(), protocols)
..binaryType = (binaryType ?? BinaryType.list).value);
/// Creates a channel wrapping [_webSocket].
HtmlWebSocketChannel(this._webSocket) {
- _sink = _HtmlWebSocketSink(this);
-
if (_webSocket.readyState == WebSocket.OPEN) {
_listen();
} else {
@@ -134,7 +131,7 @@
super(channel._controller.foreign.sink);
@override
- Future close([int closeCode, String closeReason]) {
+ Future close([int? closeCode, String? closeReason]) {
_channel._localCloseCode = closeCode;
_channel._localCloseReason = closeReason;
return super.close();
diff --git a/lib/io.dart b/lib/io.dart
index 0ec108f..f90e103 100644
--- a/lib/io.dart
+++ b/lib/io.dart
@@ -19,16 +19,16 @@
///
/// If the channel was constructed with [IOWebSocketChannel.connect], this is
/// `null` until the [WebSocket.connect] future completes.
- WebSocket _webSocket;
+ WebSocket? _webSocket;
@override
- String get protocol => _webSocket?.protocol;
+ String? get protocol => _webSocket?.protocol;
@override
- int get closeCode => _webSocket?.closeCode;
+ int? get closeCode => _webSocket?.closeCode;
@override
- String get closeReason => _webSocket?.closeReason;
+ String? get closeReason => _webSocket?.closeReason;
@override
final Stream stream;
@@ -55,11 +55,11 @@
/// [WebSocketChannelException] wrapping that error and then closes.
factory IOWebSocketChannel.connect(
Object url, {
- Iterable<String> protocols,
- Map<String, dynamic> headers,
- Duration pingInterval,
+ Iterable<String>? protocols,
+ Map<String, dynamic>? headers,
+ Duration? pingInterval,
}) {
- IOWebSocketChannel channel;
+ late IOWebSocketChannel channel;
final sinkCompleter = WebSocketSinkCompleter();
final stream = StreamCompleter.fromFuture(
WebSocket.connect(url.toString(), headers: headers, protocols: protocols)
@@ -104,6 +104,6 @@
super(webSocket);
@override
- Future close([int closeCode, String closeReason]) =>
+ Future close([int? closeCode, String? closeReason]) =>
_webSocket.close(closeCode, closeReason);
}
diff --git a/lib/src/_connect_api.dart b/lib/src/_connect_api.dart
index c816181..c58910e 100644
--- a/lib/src/_connect_api.dart
+++ b/lib/src/_connect_api.dart
@@ -10,6 +10,6 @@
/// communicate over the resulting socket.
///
/// The optional [protocols] parameter is the same as `WebSocket.connect`.
-WebSocketChannel connect(Uri uri, {Iterable<String> protocols}) {
+WebSocketChannel connect(Uri uri, {Iterable<String>? protocols}) {
throw UnsupportedError('No implementation of the connect api provided');
}
diff --git a/lib/src/_connect_html.dart b/lib/src/_connect_html.dart
index 5839c41..e725d1b 100644
--- a/lib/src/_connect_html.dart
+++ b/lib/src/_connect_html.dart
@@ -12,5 +12,5 @@
/// communicate over the resulting socket.
///
/// The optional [protocols] parameter is the same as `WebSocket.connect`.
-WebSocketChannel connect(Uri uri, {Iterable<String> protocols}) =>
+WebSocketChannel connect(Uri uri, {Iterable<String>? protocols}) =>
HtmlWebSocketChannel.connect(uri, protocols: protocols);
diff --git a/lib/src/_connect_io.dart b/lib/src/_connect_io.dart
index 5e6bcd8..a7a82c4 100644
--- a/lib/src/_connect_io.dart
+++ b/lib/src/_connect_io.dart
@@ -11,5 +11,5 @@
/// communicate over the resulting socket.
///
/// The optional [protocols] parameter is the same as `WebSocket.connect`.
-WebSocketChannel connect(Uri uri, {Iterable<String> protocols}) =>
+WebSocketChannel connect(Uri uri, {Iterable<String>? protocols}) =>
IOWebSocketChannel.connect(uri, protocols: protocols);
diff --git a/lib/src/channel.dart b/lib/src/channel.dart
index 75522a8..fa0cb97 100644
--- a/lib/src/channel.dart
+++ b/lib/src/channel.dart
@@ -35,21 +35,21 @@
/// For a client socket, this is initially `null`. After the WebSocket
/// connection is established the value is set to the subprotocol selected by
/// the server. If no subprotocol is negotiated the value will remain `null`.
- String get protocol => _webSocket.protocol;
+ String? get protocol => _webSocket.protocol;
/// The [close code][] set when the WebSocket connection is closed.
///
/// [close code]: https://tools.ietf.org/html/rfc6455#section-7.1.5
///
/// Before the connection has been closed, this will be `null`.
- int get closeCode => _webSocket.closeCode;
+ int? get closeCode => _webSocket.closeCode;
/// The [close reason][] set when the WebSocket connection is closed.
///
/// [close reason]: https://tools.ietf.org/html/rfc6455#section-7.1.6
///
/// Before the connection has been closed, this will be `null`.
- String get closeReason => _webSocket.closeReason;
+ String? get closeReason => _webSocket.closeReason;
@override
Stream get stream => StreamView(_webSocket);
@@ -96,7 +96,7 @@
///
/// [WebSocket handshake]: https://tools.ietf.org/html/rfc6455#section-4
WebSocketChannel(StreamChannel<List<int>> channel,
- {String protocol, Duration pingInterval, bool serverSide = true})
+ {String? protocol, Duration? pingInterval, bool serverSide = true})
: _webSocket = WebSocketImpl.fromSocket(
channel.stream, channel.sink, protocol, serverSide)
..pingInterval = pingInterval;
@@ -107,7 +107,7 @@
/// communicate over the resulting socket.
///
/// The optional [protocols] parameter is the same as `WebSocket.connect`.
- factory WebSocketChannel.connect(Uri uri, {Iterable<String> protocols}) =>
+ factory WebSocketChannel.connect(Uri uri, {Iterable<String>? protocols}) =>
platform.connect(uri, protocols: protocols);
}
@@ -131,6 +131,6 @@
/// [close code]: https://tools.ietf.org/html/rfc6455#section-7.1.5
/// [reason]: https://tools.ietf.org/html/rfc6455#section-7.1.6
@override
- Future close([int closeCode, String closeReason]) =>
+ Future close([int? closeCode, String? closeReason]) =>
_webSocket.close(closeCode, closeReason);
}
diff --git a/lib/src/copy/io_sink.dart b/lib/src/copy/io_sink.dart
index 0ee0508..2abf999 100644
--- a/lib/src/copy/io_sink.dart
+++ b/lib/src/copy/io_sink.dart
@@ -16,8 +16,8 @@
class StreamSinkImpl<T> implements StreamSink<T> {
final StreamConsumer<T> _target;
final Completer _doneCompleter = Completer();
- StreamController<T> _controllerInstance;
- Completer _controllerCompleter;
+ StreamController<T>? _controllerInstance;
+ Completer? _controllerCompleter;
bool _isClosed = false;
bool _isBound = false;
bool _hasError = false;
@@ -36,7 +36,7 @@
}
@override
- void addError(error, [StackTrace stackTrace]) {
+ void addError(error, [StackTrace? stackTrace]) {
if (_isClosed) {
return;
}
@@ -53,7 +53,7 @@
_isBound = true;
final future = _controllerCompleter == null
? _target.addStream(stream)
- : _controllerCompleter.future.then((_) => _target.addStream(stream));
+ : _controllerCompleter!.future.then((_) => _target.addStream(stream));
_controllerInstance?.close();
// Wait for any pending events in [_controller] to be dispatched before
@@ -71,8 +71,8 @@
// Adding an empty stream-controller will return a future that will complete
// when all data is done.
_isBound = true;
- final future = _controllerCompleter.future;
- _controllerInstance.close();
+ final future = _controllerCompleter!.future;
+ _controllerInstance!.close();
return future.whenComplete(() {
_isBound = false;
});
@@ -86,7 +86,7 @@
if (!_isClosed) {
_isClosed = true;
if (_controllerInstance != null) {
- _controllerInstance.close();
+ _controllerInstance!.close();
} else {
_closeTarget();
}
@@ -107,7 +107,7 @@
}
}
- void _completeDoneError(error, StackTrace stackTrace) {
+ void _completeDoneError(Object error, StackTrace stackTrace) {
if (!_doneCompleter.isCompleted) {
_hasError = true;
_doneCompleter.completeError(error, stackTrace);
@@ -127,17 +127,17 @@
_target.addStream(_controller.stream).then((_) {
if (_isBound) {
// A new stream takes over - forward values to that stream.
- _controllerCompleter.complete(this);
+ _controllerCompleter!.complete(this);
_controllerCompleter = null;
_controllerInstance = null;
} else {
// No new stream, .close was called. Close _target.
_closeTarget();
}
- }, onError: (error, StackTrace stackTrace) {
+ }, onError: (Object error, StackTrace stackTrace) {
if (_isBound) {
// A new stream takes over - forward errors to that stream.
- _controllerCompleter.completeError(error, stackTrace);
+ _controllerCompleter!.completeError(error, stackTrace);
_controllerCompleter = null;
_controllerInstance = null;
} else {
@@ -147,6 +147,6 @@
}
});
}
- return _controllerInstance;
+ return _controllerInstance!;
}
}
diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart
index 14cc542..7c35134 100644
--- a/lib/src/copy/web_socket_impl.dart
+++ b/lib/src/copy/web_socket_impl.dart
@@ -89,7 +89,7 @@
int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
String closeReason = '';
- EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > _eventSink;
+ EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ >? _eventSink;
final bool _serverSide;
final List<int> _maskingBytes = List.filled(4, 0);
@@ -109,13 +109,13 @@
});
@override
- void addError(Object error, [StackTrace stackTrace]) {
- _eventSink.addError(error, stackTrace);
+ void addError(Object error, [StackTrace? stackTrace]) {
+ _eventSink!.addError(error, stackTrace);
}
@override
void close() {
- _eventSink.close();
+ _eventSink!.close();
}
/// Process data received from the underlying communication channel.
@@ -292,13 +292,13 @@
switch (_opcode) {
case _WebSocketOpcode.CLOSE:
_state = CLOSED;
- _eventSink.close();
+ _eventSink!.close();
break;
case _WebSocketOpcode.PING:
- _eventSink.add(_WebSocketPing());
+ _eventSink!.add(_WebSocketPing());
break;
case _WebSocketOpcode.PONG:
- _eventSink.add(_WebSocketPong());
+ _eventSink!.add(_WebSocketPong());
break;
}
_prepareForNextFrame();
@@ -316,10 +316,10 @@
switch (_currentMessageType) {
case _WebSocketMessageType.TEXT:
- _eventSink.add(utf8.decode(bytes));
+ _eventSink!.add(utf8.decode(bytes));
break;
case _WebSocketMessageType.BINARY:
- _eventSink.add(bytes);
+ _eventSink!.add(bytes);
break;
}
_currentMessageType = _WebSocketMessageType.NONE;
@@ -345,15 +345,15 @@
}
}
_state = CLOSED;
- _eventSink.close();
+ _eventSink!.close();
break;
case _WebSocketOpcode.PING:
- _eventSink.add(_WebSocketPing(_payload.takeBytes()));
+ _eventSink!.add(_WebSocketPing(_payload.takeBytes()));
break;
case _WebSocketOpcode.PONG:
- _eventSink.add(_WebSocketPong(_payload.takeBytes()));
+ _eventSink!.add(_WebSocketPong(_payload.takeBytes()));
break;
}
_prepareForNextFrame();
@@ -377,13 +377,13 @@
}
class _WebSocketPing {
- final List<int> payload;
+ final List<int>? payload;
_WebSocketPing([this.payload]);
}
class _WebSocketPong {
- final List<int> payload;
+ final List<int>? payload;
_WebSocketPong([this.payload]);
}
@@ -392,7 +392,7 @@
class _WebSocketOutgoingTransformer
extends StreamTransformerBase<dynamic, List<int>> implements EventSink {
final WebSocketImpl webSocket;
- EventSink<List<int>> _eventSink;
+ EventSink<List<int>>? _eventSink;
_WebSocketOutgoingTransformer(this.webSocket);
@@ -417,7 +417,7 @@
addFrame(_WebSocketOpcode.PING, message.payload);
return;
}
- List<int> data;
+ List<int>? data;
int opcode;
if (message != null) {
if (message is String) {
@@ -436,15 +436,15 @@
}
@override
- void addError(Object error, [StackTrace stackTrace]) {
- _eventSink.addError(error, stackTrace);
+ void addError(Object error, [StackTrace? stackTrace]) {
+ _eventSink!.addError(error, stackTrace);
}
@override
void close() {
final code = webSocket._outCloseCode;
final reason = webSocket._outCloseReason;
- List<int> data;
+ List<int>? data;
if (code != null) {
data = <int>[];
data.add((code >> 8) & 0xFF);
@@ -454,10 +454,10 @@
}
}
addFrame(_WebSocketOpcode.CLOSE, data);
- _eventSink.close();
+ _eventSink!.close();
}
- void addFrame(int opcode, List<int> data) {
+ void addFrame(int opcode, List<int>? data) {
createFrame(
opcode,
data,
@@ -466,12 +466,12 @@
// never be a deflate helper for a cross-platform WebSocket client.
false)
.forEach((e) {
- _eventSink.add(e);
+ _eventSink!.add(e);
});
}
static Iterable<List<int>> createFrame(
- int opcode, List<int> data, bool serverSide, bool compressed) {
+ int opcode, List<int>? data, bool serverSide, bool compressed) {
final mask = !serverSide; // Masking not implemented for server.
final dataLength = data == null ? 0 : data.length;
// Determine the header size.
@@ -566,24 +566,26 @@
class _WebSocketConsumer implements StreamConsumer {
final WebSocketImpl webSocket;
final StreamSink<List<int>> sink;
- StreamController _controller;
- StreamSubscription _subscription;
+ StreamController? _controller;
+
+ // ignore: cancel_subscriptions
+ StreamSubscription? _subscription;
bool _issuedPause = false;
bool _closed = false;
final Completer _closeCompleter = Completer<WebSocketImpl>();
- Completer _completer;
+ Completer<WebSocketImpl>? _completer;
_WebSocketConsumer(this.webSocket, this.sink);
void _onListen() {
if (_subscription != null) {
- _subscription.cancel();
+ _subscription!.cancel();
}
}
void _onPause() {
if (_subscription != null) {
- _subscription.pause();
+ _subscription!.pause();
} else {
_issuedPause = true;
}
@@ -591,7 +593,7 @@
void _onResume() {
if (_subscription != null) {
- _subscription.resume();
+ _subscription!.resume();
} else {
_issuedPause = false;
}
@@ -601,7 +603,7 @@
if (_subscription != null) {
final subscription = _subscription;
_subscription = null;
- subscription.cancel();
+ subscription!.cancel();
}
}
@@ -613,7 +615,7 @@
onResume: _onResume,
onCancel: _onListen);
final stream =
- _WebSocketOutgoingTransformer(webSocket).bind(_controller.stream);
+ _WebSocketOutgoingTransformer(webSocket).bind(_controller!.stream);
sink.addStream(stream).then((_) {
_done();
_closeCompleter.complete(webSocket);
@@ -631,12 +633,12 @@
});
}
- bool _done([error, StackTrace stackTrace]) {
+ bool _done([Object? error, StackTrace? stackTrace]) {
if (_completer == null) return false;
if (error != null) {
- _completer.completeError(error, stackTrace);
+ _completer!.completeError(error, stackTrace);
} else {
- _completer.complete(webSocket);
+ _completer!.complete(webSocket);
}
_completer = null;
return true;
@@ -651,13 +653,13 @@
_ensureController();
_completer = Completer();
_subscription = stream.listen((data) {
- _controller.add(data);
+ _controller!.add(data);
}, onDone: _done, onError: _done, cancelOnError: true);
if (_issuedPause) {
- _subscription.pause();
+ _subscription!.pause();
_issuedPause = false;
}
- return _completer.future;
+ return _completer!.future;
}
@override
@@ -666,14 +668,14 @@
Future closeSocket() =>
sink.close().catchError((_) {}).then((_) => webSocket);
- _controller.close();
+ _controller!.close();
return _closeCompleter.future.then((_) => closeSocket());
}
void add(data) {
if (_closed) return;
_ensureController();
- _controller.add(data);
+ _controller!.add(data);
}
void closeSocket() {
@@ -689,24 +691,26 @@
static const int DEFAULT_WINDOW_BITS = 15;
static const String PER_MESSAGE_DEFLATE = 'permessage-deflate';
- final String protocol;
+ final String? protocol;
- StreamController _controller;
- StreamSubscription _subscription;
- StreamSink _sink;
+ late final StreamController _controller;
+
+ // ignore: cancel_subscriptions
+ StreamSubscription? _subscription;
+ late final StreamSink _sink;
final bool _serverSide;
int _readyState = WebSocket.CONNECTING;
bool _writeClosed = false;
- int _closeCode;
- String _closeReason;
- Duration _pingInterval;
- Timer _pingTimer;
- _WebSocketConsumer _consumer;
+ int? _closeCode;
+ String? _closeReason;
+ Duration? _pingInterval;
+ Timer? _pingTimer;
+ late final _WebSocketConsumer _consumer;
- int _outCloseCode;
- String _outCloseReason;
- Timer _closeTimer;
+ int? _outCloseCode;
+ String? _outCloseReason;
+ Timer? _closeTimer;
WebSocketImpl.fromSocket(
Stream<List<int>> stream, StreamSink<List<int>> sink, this.protocol,
@@ -726,7 +730,7 @@
_controller.add(data);
}
}, onError: (error, stackTrace) {
- if (_closeTimer != null) _closeTimer.cancel();
+ if (_closeTimer != null) _closeTimer!.cancel();
if (error is FormatException) {
_close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA);
} else {
@@ -737,7 +741,7 @@
_closeReason = _outCloseReason;
_controller.close();
}, onDone: () {
- if (_closeTimer != null) _closeTimer.cancel();
+ if (_closeTimer != null) _closeTimer!.cancel();
if (_readyState == WebSocket.OPEN) {
_readyState = WebSocket.CLOSING;
if (!_isReservedStatusCode(transformer.closeCode)) {
@@ -752,39 +756,39 @@
_closeReason = transformer.closeReason;
_controller.close();
}, cancelOnError: true);
- _subscription.pause();
+ _subscription!.pause();
_controller = StreamController(
sync: true,
- onListen: () => _subscription.resume(),
+ onListen: () => _subscription!.resume(),
onCancel: () {
- _subscription.cancel();
+ _subscription!.cancel();
_subscription = null;
},
- onPause: _subscription.pause,
- onResume: _subscription.resume);
+ onPause: _subscription!.pause,
+ onResume: _subscription!.resume);
_webSockets[_serviceId] = this;
}
@override
- StreamSubscription listen(void Function(dynamic) onData,
- {Function onError, void Function() onDone, bool cancelOnError}) =>
+ StreamSubscription listen(void Function(dynamic)? onData,
+ {Function? onError, void Function()? onDone, bool? cancelOnError}) =>
_controller.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
- Duration get pingInterval => _pingInterval;
+ Duration? get pingInterval => _pingInterval;
- set pingInterval(Duration interval) {
+ set pingInterval(Duration? interval) {
if (_writeClosed) return;
- if (_pingTimer != null) _pingTimer.cancel();
+ if (_pingTimer != null) _pingTimer!.cancel();
_pingInterval = interval;
if (_pingInterval == null) return;
- _pingTimer = Timer(_pingInterval, () {
+ _pingTimer = Timer(_pingInterval!, () {
if (_writeClosed) return;
_consumer.add(_WebSocketPing());
- _pingTimer = Timer(_pingInterval, () {
+ _pingTimer = Timer(_pingInterval!, () {
// No pong received.
_close(WebSocketStatus.GOING_AWAY);
});
@@ -793,11 +797,11 @@
int get readyState => _readyState;
- String get extensions => null;
+ String? get extensions => null;
- int get closeCode => _closeCode;
+ int? get closeCode => _closeCode;
- String get closeReason => _closeReason;
+ String? get closeReason => _closeReason;
@override
void add(data) {
@@ -805,7 +809,7 @@
}
@override
- void addError(error, [StackTrace stackTrace]) {
+ void addError(Object error, [StackTrace? stackTrace]) {
_sink.addError(error, stackTrace);
}
@@ -816,7 +820,7 @@
Future get done => _sink.done;
@override
- Future close([int code, String reason]) {
+ Future close([int? code, String? reason]) {
if (_isReservedStatusCode(code)) {
throw WebSocketChannelException('Reserved status code $code');
}
@@ -838,7 +842,7 @@
// Reuse code and reason from the local close.
_closeCode = _outCloseCode;
_closeReason = _outCloseReason;
- if (_subscription != null) _subscription.cancel();
+ if (_subscription != null) _subscription!.cancel();
_controller.close();
_webSockets.remove(_serviceId);
});
@@ -846,7 +850,7 @@
return _sink.close();
}
- void _close([int code, String reason]) {
+ void _close([int? code, String? reason]) {
if (_writeClosed) return;
if (_outCloseCode == null) {
_outCloseCode = code;
@@ -861,7 +865,7 @@
// deleted for web_socket_channel. The methods were unused in WebSocket code
// and produced warnings.
- static bool _isReservedStatusCode(int code) =>
+ static bool _isReservedStatusCode(int? code) =>
code != null &&
(code < WebSocketStatus.NORMAL_CLOSURE ||
code == WebSocketStatus.RESERVED_1004 ||
diff --git a/lib/src/exception.dart b/lib/src/exception.dart
index ece5cfa..11de8ab 100644
--- a/lib/src/exception.dart
+++ b/lib/src/exception.dart
@@ -6,10 +6,10 @@
/// An exception thrown by a [WebSocketChannel].
class WebSocketChannelException implements Exception {
- final String message;
+ final String? message;
/// The exception that caused this one, if available.
- final Object inner;
+ final Object? inner;
WebSocketChannelException([this.message]) : inner = null;
diff --git a/lib/src/sink_completer.dart b/lib/src/sink_completer.dart
index 4d6a2d3..9012d68 100644
--- a/lib/src/sink_completer.dart
+++ b/lib/src/sink_completer.dart
@@ -49,24 +49,24 @@
///
/// Created if the user adds events to this sink before the destination sink
/// is set.
- StreamController _controller;
+ StreamController? _controller;
/// Completer for [done].
///
/// Created if the user requests the [done] future before the destination sink
/// is set.
- Completer _doneCompleter;
+ Completer? _doneCompleter;
/// Destination sink for the events added to this sink.
///
/// Set when [WebSocketSinkCompleter.setDestinationSink] is called.
- WebSocketSink _destinationSink;
+ WebSocketSink? _destinationSink;
/// The close code passed to [close].
- int _closeCode;
+ int? _closeCode;
/// The close reason passed to [close].
- String _closeReason;
+ String? _closeReason;
/// Whether events should be sent directly to [_destinationSink], as opposed
/// to going through [_controller].
@@ -74,59 +74,55 @@
@override
Future get done {
- if (_doneCompleter != null) return _doneCompleter.future;
+ if (_doneCompleter != null) return _doneCompleter!.future;
if (_destinationSink == null) {
_doneCompleter = Completer.sync();
- return _doneCompleter.future;
+ return _doneCompleter!.future;
}
- return _destinationSink.done;
+ return _destinationSink!.done;
}
@override
void add(event) {
if (_canSendDirectly) {
- _destinationSink.add(event);
+ _destinationSink!.add(event);
} else {
- _ensureController();
- _controller.add(event);
+ _ensureController().add(event);
}
}
@override
- void addError(error, [StackTrace stackTrace]) {
+ void addError(Object error, [StackTrace? stackTrace]) {
if (_canSendDirectly) {
- _destinationSink.addError(error, stackTrace);
+ _destinationSink!.addError(error, stackTrace);
} else {
- _ensureController();
- _controller.addError(error, stackTrace);
+ _ensureController().addError(error, stackTrace);
}
}
@override
Future addStream(Stream stream) {
- if (_canSendDirectly) return _destinationSink.addStream(stream);
+ if (_canSendDirectly) return _destinationSink!.addStream(stream);
- _ensureController();
- return _controller.addStream(stream, cancelOnError: false);
+ final controller = _ensureController();
+ return controller.addStream(stream, cancelOnError: false);
}
@override
- Future close([int closeCode, String closeReason]) {
+ Future close([int? closeCode, String? closeReason]) {
if (_canSendDirectly) {
- _destinationSink.close(closeCode, closeReason);
+ _destinationSink!.close(closeCode, closeReason);
} else {
_closeCode = closeCode;
_closeReason = closeReason;
- _ensureController();
- _controller.close();
+ _ensureController().close();
}
return done;
}
/// Create [_controller] if it doesn't yet exist.
- void _ensureController() {
- _controller ??= StreamController(sync: true);
- }
+ StreamController _ensureController() =>
+ _controller ??= StreamController(sync: true);
/// Sets the destination sink to which events from this sink will be provided.
///
@@ -144,7 +140,7 @@
// Catch any error that may come from [addStream] or [sink.close]. They'll
// be reported through [done] anyway.
sink
- .addStream(_controller.stream)
+ .addStream(_controller!.stream)
.whenComplete(() => sink.close(_closeCode, _closeReason))
.catchError((_) {});
}
@@ -152,7 +148,7 @@
// If the user has already asked when the sink is done, connect the sink's
// done callback to that completer.
if (_doneCompleter != null) {
- _doneCompleter.complete(sink.done);
+ _doneCompleter!.complete(sink.done);
}
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 203e709..8b8339a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,20 +1,25 @@
name: web_socket_channel
-version: 1.2.0
+version: 2.0.0-dev
description: >-
StreamChannel wrappers for WebSockets. Provides a cross-platform
WebSocketChannel API, a cross-platform implementation of that API that
communicates over an underlying StreamChannel.
-homepage: https://github.com/dart-lang/web_socket_channel
+repository: https://github.com/dart-lang/web_socket_channel
environment:
- sdk: ">=2.10.0 <3.0.0"
+ sdk: ">=2.12.0-0 <3.0.0"
dependencies:
- async: ">=1.3.0 <3.0.0"
- crypto: ">=0.9.2 <4.0.0"
- stream_channel: ">=1.2.0 <3.0.0"
+ async: ^2.5.0
+ crypto: ^3.0.0
+ stream_channel: ^2.1.0
dev_dependencies:
- pedantic: ^1.0.0
- test: ^1.16.0-nullsafety
+ pedantic: ^1.10.0
+ test: ^1.16.0
+
+dependency_overrides:
+ # Need to update dependencies on these to allow v2 of this package
+ shelf_web_socket: ^0.2.4
+ test: ^1.16.0
diff --git a/test/html_test.dart b/test/html_test.dart
index aa87c36..3a89098 100644
--- a/test/html_test.dart
+++ b/test/html_test.dart
@@ -3,19 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
@TestOn('browser')
-
import 'dart:async';
import 'dart:html';
import 'dart:typed_data';
import 'package:async/async.dart';
import 'package:test/test.dart';
-
import 'package:web_socket_channel/html.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
void main() {
- int port;
+ late int port;
setUpAll(() async {
final channel = spawnHybridCode(r'''
// @dart=2.7
@@ -37,14 +35,10 @@
port = await channel.stream.first as int;
});
- WebSocketChannel channel;
- tearDown(() {
- if (channel != null) channel.sink.close();
- });
-
test('communicates using an existing WebSocket', () async {
final webSocket = WebSocket('ws://localhost:$port');
- channel = HtmlWebSocketChannel(webSocket);
+ final channel = HtmlWebSocketChannel(webSocket);
+ addTearDown(channel.sink.close);
final queue = StreamQueue(channel.stream);
channel.sink.add('foo');
@@ -65,7 +59,8 @@
final webSocket = WebSocket('ws://localhost:$port');
await webSocket.onOpen.first;
- channel = HtmlWebSocketChannel(webSocket);
+ final channel = HtmlWebSocketChannel(webSocket);
+ addTearDown(channel.sink.close);
final queue = StreamQueue(channel.stream);
channel.sink.add('foo');
@@ -73,7 +68,8 @@
});
test('.connect defaults to binary lists', () async {
- channel = HtmlWebSocketChannel.connect('ws://localhost:$port');
+ final channel = HtmlWebSocketChannel.connect('ws://localhost:$port');
+ addTearDown(channel.sink.close);
final queue = StreamQueue(channel.stream);
channel.sink.add('foo');
@@ -85,7 +81,8 @@
test('.connect defaults to binary lists using platform independent api',
() async {
- channel = WebSocketChannel.connect(Uri.parse('ws://localhost:$port'));
+ final channel = WebSocketChannel.connect(Uri.parse('ws://localhost:$port'));
+ addTearDown(channel.sink.close);
final queue = StreamQueue(channel.stream);
channel.sink.add('foo');
@@ -96,8 +93,9 @@
});
test('.connect can use blobs', () async {
- channel = HtmlWebSocketChannel.connect('ws://localhost:$port',
+ final channel = HtmlWebSocketChannel.connect('ws://localhost:$port',
binaryType: BinaryType.blob);
+ addTearDown(channel.sink.close);
final queue = StreamQueue(channel.stream);
channel.sink.add('foo');
diff --git a/test/io_test.dart b/test/io_test.dart
index bb4a017..111abb4 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -11,12 +11,10 @@
void main() {
HttpServer server;
- tearDown(() async {
- if (server != null) await server.close();
- });
test('communicates using existing WebSockets', () async {
server = await HttpServer.bind('localhost', 0);
+ addTearDown(server.close);
server.transform(WebSocketTransformer()).listen((WebSocket webSocket) {
final channel = IOWebSocketChannel(webSocket);
channel.sink.add('hello!');
diff --git a/test/web_socket_test.dart b/test/web_socket_test.dart
index f9873e0..441c628 100644
--- a/test/web_socket_test.dart
+++ b/test/web_socket_test.dart
@@ -65,7 +65,7 @@
..set(
'Sec-WebSocket-Accept',
WebSocketChannel.signKey(
- request.headers.value('Sec-WebSocket-Key')));
+ request.headers.value('Sec-WebSocket-Key')!));
response.contentLength = 0;
final socket = await response.detachSocket();