Fix newly enforce package:pedantic lints (#91)
- always_declare_return_types
- annotate_overrides
- omit_local_variable_types
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_single_quotes
- use_function_type_syntax_for_parameters
diff --git a/example/example.dart b/example/example.dart
index b641fd0..af7bd4d 100644
--- a/example/example.dart
+++ b/example/example.dart
@@ -6,10 +6,10 @@
import 'package:web_socket_channel/status.dart' as status;
void main() async {
- final channel = await IOWebSocketChannel.connect("ws://localhost:1234");
+ final channel = await IOWebSocketChannel.connect('ws://localhost:1234');
channel.stream.listen((message) {
- channel.sink.add("received!");
+ channel.sink.add('received!');
channel.sink.close(status.goingAway);
});
}
diff --git a/lib/html.dart b/lib/html.dart
index e2dc145..db42d5d 100644
--- a/lib/html.dart
+++ b/lib/html.dart
@@ -20,11 +20,14 @@
/// The underlying `dart:html` [WebSocket].
final WebSocket _webSocket;
+ @override
String get protocol => _webSocket.protocol;
+ @override
int get closeCode => _closeCode;
int _closeCode;
+ @override
String get closeReason => _closeReason;
String _closeReason;
@@ -44,10 +47,12 @@
/// [_controller.local.stream].
String _localCloseReason;
+ @override
Stream get stream => _controller.foreign.stream;
final _controller =
StreamChannelController(sync: true, allowForeignErrors: false);
+ @override
WebSocketSink get sink => _sink;
WebSocketSink _sink;
@@ -85,7 +90,7 @@
// and that once it is no open or message events will be emitted.
_webSocket.onError.first.then((_) {
_controller.local.sink
- .addError(WebSocketChannelException("WebSocket connection failed."));
+ .addError(WebSocketChannelException('WebSocket connection failed.'));
_controller.local.sink.close();
});
@@ -131,6 +136,7 @@
: _channel = channel,
super(channel._controller.foreign.sink);
+ @override
Future close([int closeCode, String closeReason]) {
_channel._localCloseCode = closeCode;
_channel._localCloseReason = closeReason;
@@ -142,10 +148,10 @@
/// messages.
class BinaryType {
/// Tells the channel to emit binary messages as [Blob]s.
- static const blob = BinaryType._("blob", "blob");
+ static const blob = BinaryType._('blob', 'blob');
/// Tells the channel to emit binary messages as [Uint8List]s.
- static const list = BinaryType._("list", "arraybuffer");
+ static const list = BinaryType._('list', 'arraybuffer');
/// The name of the binary type, which matches its variable name.
final String name;
@@ -155,5 +161,6 @@
const BinaryType._(this.name, this.value);
+ @override
String toString() => name;
}
diff --git a/lib/io.dart b/lib/io.dart
index 861b79f..e2a7ce4 100644
--- a/lib/io.dart
+++ b/lib/io.dart
@@ -23,11 +23,16 @@
/// `null` until the [WebSocket.connect] future completes.
WebSocket _webSocket;
+ @override
String get protocol => _webSocket?.protocol;
+ @override
int get closeCode => _webSocket?.closeCode;
+ @override
String get closeReason => _webSocket?.closeReason;
+ @override
final Stream stream;
+ @override
final WebSocketSink sink;
// TODO(nweiz): Add a compression parameter after the initial release.
@@ -93,6 +98,7 @@
: _webSocket = webSocket,
super(webSocket);
+ @override
Future close([int closeCode, String closeReason]) =>
_webSocket.close(closeCode, closeReason);
}
diff --git a/lib/src/channel.dart b/lib/src/channel.dart
index cee27f2..8fcee55 100644
--- a/lib/src/channel.dart
+++ b/lib/src/channel.dart
@@ -51,12 +51,14 @@
/// Before the connection has been closed, this will be `null`.
String get closeReason => _webSocket.closeReason;
+ @override
Stream get stream => StreamView(_webSocket);
/// The sink for sending values to the other endpoint.
///
/// This supports additional arguments to [WebSocketSink.close] that provide
/// the remote endpoint reasons for closing the connection.
+ @override
WebSocketSink get sink => WebSocketSink._(_webSocket);
/// Signs a `Sec-WebSocket-Key` header sent by a WebSocket client as part of
@@ -125,6 +127,7 @@
///
/// [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]) =>
_webSocket.close(closeCode, closeReason);
}
diff --git a/lib/src/copy/bytes_builder.dart b/lib/src/copy/bytes_builder.dart
index f34df48..4cbd6d7 100644
--- a/lib/src/copy/bytes_builder.dart
+++ b/lib/src/copy/bytes_builder.dart
@@ -81,10 +81,11 @@
? _emptyList
: Uint8List(_pow2roundup(initialCapacity));
+ @override
void add(List<int> bytes) {
- int bytesLength = bytes.length;
+ var bytesLength = bytes.length;
if (bytesLength == 0) return;
- int required = _length + bytesLength;
+ var required = _length + bytesLength;
if (_buffer.length < required) {
_grow(required);
}
@@ -92,13 +93,14 @@
if (bytes is Uint8List) {
_buffer.setRange(_length, required, bytes);
} else {
- for (int i = 0; i < bytesLength; i++) {
+ for (var i = 0; i < bytesLength; i++) {
_buffer[_length + i] = bytes[i];
}
}
_length = required;
}
+ @override
void addByte(int byte) {
if (_buffer.length == _length) {
// The grow algorithm always at least doubles.
@@ -113,7 +115,7 @@
void _grow(int required) {
// We will create a list in the range of 2-4 times larger than
// required.
- int newSize = required * 2;
+ var newSize = required * 2;
if (newSize < _INIT_SIZE) {
newSize = _INIT_SIZE;
} else {
@@ -124,6 +126,7 @@
_buffer = newBuffer;
}
+ @override
Uint8List takeBytes() {
if (_length == 0) return _emptyList;
var buffer = Uint8List.view(_buffer.buffer, 0, _length);
@@ -131,17 +134,22 @@
return buffer;
}
+ @override
Uint8List toBytes() {
if (_length == 0) return _emptyList;
return Uint8List.fromList(Uint8List.view(_buffer.buffer, 0, _length));
}
+ @override
int get length => _length;
+ @override
bool get isEmpty => _length == 0;
+ @override
bool get isNotEmpty => _length != 0;
+ @override
void clear() {
_length = 0;
_buffer = _emptyList;
@@ -163,6 +171,7 @@
int _length = 0;
final List<Uint8List> _chunks = [];
+ @override
void add(List<int> bytes) {
Uint8List typedBytes;
if (bytes is Uint8List) {
@@ -174,11 +183,13 @@
_length += typedBytes.length;
}
+ @override
void addByte(int byte) {
_chunks.add(Uint8List(1)..[0] = byte);
_length++;
}
+ @override
Uint8List takeBytes() {
if (_length == 0) return _CopyingBytesBuilder._emptyList;
if (_chunks.length == 1) {
@@ -187,7 +198,7 @@
return buffer;
}
var buffer = Uint8List(_length);
- int offset = 0;
+ var offset = 0;
for (var chunk in _chunks) {
buffer.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
@@ -196,10 +207,11 @@
return buffer;
}
+ @override
Uint8List toBytes() {
if (_length == 0) return _CopyingBytesBuilder._emptyList;
var buffer = Uint8List(_length);
- int offset = 0;
+ var offset = 0;
for (var chunk in _chunks) {
buffer.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
@@ -207,12 +219,16 @@
return buffer;
}
+ @override
int get length => _length;
+ @override
bool get isEmpty => _length == 0;
+ @override
bool get isNotEmpty => _length != 0;
+ @override
void clear() {
_length = 0;
_chunks.clear();
diff --git a/lib/src/copy/io_sink.dart b/lib/src/copy/io_sink.dart
index 9e9b7b9..8da7f12 100644
--- a/lib/src/copy/io_sink.dart
+++ b/lib/src/copy/io_sink.dart
@@ -27,6 +27,7 @@
// The _reportClosedSink method has been deleted for web_socket_channel. This
// method did nothing but print to stderr, which is unavailable here.
+ @override
void add(T data) {
if (_isClosed) {
return;
@@ -34,6 +35,7 @@
_controller.add(data);
}
+ @override
void addError(error, [StackTrace stackTrace]) {
if (_isClosed) {
return;
@@ -41,9 +43,10 @@
_controller.addError(error, stackTrace);
}
+ @override
Future addStream(Stream<T> stream) {
if (_isBound) {
- throw StateError("StreamSink is already bound to a stream");
+ throw StateError('StreamSink is already bound to a stream');
}
if (_hasError) return done;
@@ -62,7 +65,7 @@
Future flush() {
if (_isBound) {
- throw StateError("StreamSink is bound to a stream");
+ throw StateError('StreamSink is bound to a stream');
}
if (_controllerInstance == null) return Future.value(this);
// Adding an empty stream-controller will return a future that will complete
@@ -75,9 +78,10 @@
});
}
+ @override
Future close() {
if (_isBound) {
- throw StateError("StreamSink is bound to a stream");
+ throw StateError('StreamSink is bound to a stream');
}
if (!_isClosed) {
_isClosed = true;
@@ -94,6 +98,7 @@
_target.close().then(_completeDoneValue, onError: _completeDoneError);
}
+ @override
Future get done => _doneCompleter.future;
void _completeDoneValue(value) {
@@ -111,10 +116,10 @@
StreamController<T> get _controller {
if (_isBound) {
- throw StateError("StreamSink is bound to a stream");
+ throw StateError('StreamSink is bound to a stream');
}
if (_isClosed) {
- throw StateError("StreamSink is closed");
+ throw StateError('StreamSink is closed');
}
if (_controllerInstance == null) {
_controllerInstance = StreamController<T>(sync: true);
diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart
index 552b3e4..21464a2 100644
--- a/lib/src/copy/web_socket_impl.dart
+++ b/lib/src/copy/web_socket_impl.dart
@@ -22,7 +22,7 @@
import 'io_sink.dart';
import 'web_socket.dart';
-const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+const String webSocketGUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
final _random = Random();
@@ -86,7 +86,7 @@
int _unmaskingIndex = 0;
int _currentMessageType = _WebSocketMessageType.NONE;
int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
- String closeReason = "";
+ String closeReason = '';
EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > _eventSink;
@@ -96,45 +96,49 @@
_WebSocketProtocolTransformer([this._serverSide = false]);
+ @override
Stream<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > bind(
Stream<List<int>> stream) {
return Stream.eventTransformed(stream, (EventSink eventSink) {
if (_eventSink != null) {
- throw StateError("WebSocket transformer already used.");
+ throw StateError('WebSocket transformer already used.');
}
_eventSink = eventSink;
return this;
});
}
+ @override
void addError(Object error, [StackTrace stackTrace]) {
_eventSink.addError(error, stackTrace);
}
+ @override
void close() {
_eventSink.close();
}
/// Process data received from the underlying communication channel.
+ @override
void add(List<int> bytes) {
var buffer = bytes is Uint8List ? bytes : Uint8List.fromList(bytes);
- int index = 0;
- int lastIndex = buffer.length;
+ var index = 0;
+ var lastIndex = buffer.length;
if (_state == CLOSED) {
- throw WebSocketChannelException("Data on closed connection");
+ throw WebSocketChannelException('Data on closed connection');
}
if (_state == FAILURE) {
- throw WebSocketChannelException("Data on failed connection");
+ throw WebSocketChannelException('Data on failed connection');
}
while ((index < lastIndex) && _state != CLOSED && _state != FAILURE) {
- int byte = buffer[index];
+ var byte = buffer[index];
if (_state <= LEN_REST) {
if (_state == START) {
_fin = (byte & FIN) != 0;
if ((byte & (RSV2 | RSV3)) != 0) {
// The RSV2, RSV3 bits must both be zero.
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
_opcode = (byte & OPCODE);
@@ -142,29 +146,29 @@
if (_opcode <= _WebSocketOpcode.BINARY) {
if (_opcode == _WebSocketOpcode.CONTINUATION) {
if (_currentMessageType == _WebSocketMessageType.NONE) {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
} else {
assert(_opcode == _WebSocketOpcode.TEXT ||
_opcode == _WebSocketOpcode.BINARY);
if (_currentMessageType != _WebSocketMessageType.NONE) {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
_currentMessageType = _opcode;
}
} else if (_opcode >= _WebSocketOpcode.CLOSE &&
_opcode <= _WebSocketOpcode.PONG) {
// Control frames cannot be fragmented.
- if (!_fin) throw WebSocketChannelException("Protocol error");
+ if (!_fin) throw WebSocketChannelException('Protocol error');
} else {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
_state = LEN_FIRST;
} else if (_state == LEN_FIRST) {
_masked = (byte & 0x80) != 0;
_len = byte & 0x7F;
if (_isControlFrame() && _len > 125) {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
if (_len == 126) {
_len = 0;
@@ -195,7 +199,7 @@
} else {
assert(_state == PAYLOAD);
// The payload is not handled one byte at a time but in blocks.
- int payloadLength = min(lastIndex - index, _remainingPayloadBytes);
+ var payloadLength = min(lastIndex - index, _remainingPayloadBytes);
_remainingPayloadBytes -= payloadLength;
// Unmask payload if masked.
if (_masked) {
@@ -209,7 +213,7 @@
} else {
if (_currentMessageType != _WebSocketMessageType.TEXT &&
_currentMessageType != _WebSocketMessageType.BINARY) {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
if (_remainingPayloadBytes == 0) _messageFrameEnd();
}
@@ -225,38 +229,37 @@
}
void _unmask(int index, int length, Uint8List buffer) {
- const int BLOCK_SIZE = 16;
+ const BLOCK_SIZE = 16;
// Skip Int32x4-version if message is small.
if (length >= BLOCK_SIZE) {
// Start by aligning to 16 bytes.
- final int startOffset = BLOCK_SIZE - (index & 15);
- final int end = index + startOffset;
- for (int i = index; i < end; i++) {
+ final startOffset = BLOCK_SIZE - (index & 15);
+ final end = index + startOffset;
+ for (var i = index; i < end; i++) {
buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
}
index += startOffset;
length -= startOffset;
- final int blockCount = length ~/ BLOCK_SIZE;
+ final blockCount = length ~/ BLOCK_SIZE;
if (blockCount > 0) {
// Create mask block.
- int mask = 0;
- for (int i = 3; i >= 0; i--) {
+ var mask = 0;
+ for (var i = 3; i >= 0; i--) {
mask = (mask << 8) | _maskingBytes[(_unmaskingIndex + i) & 3];
}
- Int32x4 blockMask = Int32x4(mask, mask, mask, mask);
- Int32x4List blockBuffer =
- Int32x4List.view(buffer.buffer, index, blockCount);
- for (int i = 0; i < blockBuffer.length; i++) {
+ var blockMask = Int32x4(mask, mask, mask, mask);
+ var blockBuffer = Int32x4List.view(buffer.buffer, index, blockCount);
+ for (var i = 0; i < blockBuffer.length; i++) {
blockBuffer[i] ^= blockMask;
}
- final int bytes = blockCount * BLOCK_SIZE;
+ final bytes = blockCount * BLOCK_SIZE;
index += bytes;
length -= bytes;
}
}
// Handle end.
- final int end = index + length;
- for (int i = index; i < end; i++) {
+ final end = index + length;
+ for (var i = index; i < end; i++) {
buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
}
}
@@ -264,12 +267,12 @@
void _lengthDone() {
if (_masked) {
if (!_serverSide) {
- throw WebSocketChannelException("Received masked frame from server");
+ throw WebSocketChannelException('Received masked frame from server');
}
_state = MASK;
} else {
if (_serverSide) {
- throw WebSocketChannelException("Received unmasked frame from client");
+ throw WebSocketChannelException('Received unmasked frame from client');
}
_remainingPayloadBytes = _len;
_startPayload();
@@ -331,11 +334,11 @@
var payload = _payload.takeBytes();
if (payload.isNotEmpty) {
if (payload.length == 1) {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
closeCode = payload[0] << 8 | payload[1];
if (closeCode == WebSocketStatus.NO_STATUS_RECEIVED) {
- throw WebSocketChannelException("Protocol error");
+ throw WebSocketChannelException('Protocol error');
}
if (payload.length > 2) {
closeReason = utf8.decode(payload.sublist(2));
@@ -392,17 +395,19 @@
_WebSocketOutgoingTransformer(this.webSocket);
+ @override
Stream<List<int>> bind(Stream stream) {
return Stream<List<int>>.eventTransformed(stream,
(EventSink<List<int>> eventSink) {
if (_eventSink != null) {
- throw StateError("WebSocket transformer already used");
+ throw StateError('WebSocket transformer already used');
}
_eventSink = eventSink;
return this;
});
}
+ @override
void add(message) {
if (message is _WebSocketPong) {
addFrame(_WebSocketOpcode.PONG, message.payload);
@@ -430,16 +435,18 @@
addFrame(opcode, data);
}
+ @override
void addError(Object error, [StackTrace stackTrace]) {
_eventSink.addError(error, stackTrace);
}
+ @override
void close() {
- int code = webSocket._outCloseCode;
- String reason = webSocket._outCloseReason;
+ var code = webSocket._outCloseCode;
+ var reason = webSocket._outCloseReason;
List<int> data;
if (code != null) {
- data = List<int>();
+ data = <int>[];
data.add((code >> 8) & 0xFF);
data.add(code & 0xFF);
if (reason != null) {
@@ -465,17 +472,17 @@
static Iterable<List<int>> createFrame(
int opcode, List<int> data, bool serverSide, bool compressed) {
- bool mask = !serverSide; // Masking not implemented for server.
- int dataLength = data == null ? 0 : data.length;
+ var mask = !serverSide; // Masking not implemented for server.
+ var dataLength = data == null ? 0 : data.length;
// Determine the header size.
- int headerSize = (mask) ? 6 : 2;
+ var headerSize = (mask) ? 6 : 2;
if (dataLength > 65535) {
headerSize += 8;
} else if (dataLength > 125) {
headerSize += 2;
}
- Uint8List header = Uint8List(headerSize);
- int index = 0;
+ var header = Uint8List(headerSize);
+ var index = 0;
// Set FIN and opcode.
var hoc = _WebSocketProtocolTransformer.FIN |
@@ -484,7 +491,7 @@
header[index++] = hoc;
// Determine size and position of length field.
- int lengthBytes = 1;
+ var lengthBytes = 1;
if (dataLength > 65535) {
header[index++] = 127;
lengthBytes = 8;
@@ -493,7 +500,7 @@
lengthBytes = 2;
}
// Write the length in network byte order into the header.
- for (int i = 0; i < lengthBytes; i++) {
+ for (var i = 0; i < lengthBytes; i++) {
header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF;
}
if (mask) {
@@ -517,32 +524,31 @@
list = Uint8List.fromList(data);
} else {
list = Uint8List(data.length);
- for (int i = 0; i < data.length; i++) {
+ for (var i = 0; i < data.length; i++) {
if (data[i] < 0 || 255 < data[i]) {
- throw ArgumentError("List element is not a byte value "
- "(value ${data[i]} at index $i)");
+ throw ArgumentError('List element is not a byte value '
+ '(value ${data[i]} at index $i)');
}
list[i] = data[i];
}
}
}
- const int BLOCK_SIZE = 16;
- int blockCount = list.length ~/ BLOCK_SIZE;
+ const BLOCK_SIZE = 16;
+ var blockCount = list.length ~/ BLOCK_SIZE;
if (blockCount > 0) {
// Create mask block.
- int mask = 0;
- for (int i = 3; i >= 0; i--) {
+ var mask = 0;
+ for (var i = 3; i >= 0; i--) {
mask = (mask << 8) | maskBytes[i];
}
- Int32x4 blockMask = Int32x4(mask, mask, mask, mask);
- Int32x4List blockBuffer =
- Int32x4List.view(list.buffer, 0, blockCount);
- for (int i = 0; i < blockBuffer.length; i++) {
+ var blockMask = Int32x4(mask, mask, mask, mask);
+ var blockBuffer = Int32x4List.view(list.buffer, 0, blockCount);
+ for (var i = 0; i < blockBuffer.length; i++) {
blockBuffer[i] ^= blockMask;
}
}
// Handle end.
- for (int i = blockCount * BLOCK_SIZE; i < list.length; i++) {
+ for (var i = blockCount * BLOCK_SIZE; i < list.length; i++) {
list[i] ^= maskBytes[i & 3];
}
data = list;
@@ -599,7 +605,7 @@
}
}
- _ensureController() {
+ void _ensureController() {
if (_controller != null) return;
_controller = StreamController(
sync: true,
@@ -636,6 +642,7 @@
return true;
}
+ @override
Future addStream(var stream) {
if (_closed) {
stream.listen(null).cancel();
@@ -653,6 +660,7 @@
return _completer.future;
}
+ @override
Future close() {
_ensureController();
Future closeSocket() {
@@ -678,9 +686,9 @@
class WebSocketImpl extends Stream with _ServiceObject implements StreamSink {
// Use default Map so we keep order.
- static final Map<int, WebSocketImpl> _webSockets = Map<int, WebSocketImpl>();
+ static final Map<int, WebSocketImpl> _webSockets = <int, WebSocketImpl>{};
static const int DEFAULT_WINDOW_BITS = 15;
- static const String PER_MESSAGE_DEFLATE = "permessage-deflate";
+ static const String PER_MESSAGE_DEFLATE = 'permessage-deflate';
final String protocol;
@@ -759,8 +767,9 @@
_webSockets[_serviceId] = this;
}
- StreamSubscription listen(void onData(message),
- {Function onError, void onDone(), bool cancelOnError}) {
+ @override
+ StreamSubscription listen(void Function(dynamic) onData,
+ {Function onError, void Function() onDone, bool cancelOnError}) {
return _controller.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
}
@@ -790,20 +799,25 @@
int get closeCode => _closeCode;
String get closeReason => _closeReason;
+ @override
void add(data) {
_sink.add(data);
}
+ @override
void addError(error, [StackTrace stackTrace]) {
_sink.addError(error, stackTrace);
}
+ @override
Future addStream(Stream stream) => _sink.addStream(stream);
+ @override
Future get done => _sink.done;
+ @override
Future close([int code, String reason]) {
if (_isReservedStatusCode(code)) {
- throw WebSocketChannelException("Reserved status code $code");
+ throw WebSocketChannelException('Reserved status code $code');
}
if (_outCloseCode == null) {
_outCloseCode = code;
@@ -818,17 +832,15 @@
if (!_controller.hasListener && _subscription != null) {
_controller.stream.drain().catchError((_) => {});
}
- if (_closeTimer == null) {
- // When closing the web-socket, we no longer accept data.
- _closeTimer = Timer(const Duration(seconds: 5), () {
- // Reuse code and reason from the local close.
- _closeCode = _outCloseCode;
- _closeReason = _outCloseReason;
- if (_subscription != null) _subscription.cancel();
- _controller.close();
- _webSockets.remove(_serviceId);
- });
- }
+ // When closing the web-socket, we no longer accept data.
+ _closeTimer ??= Timer(const Duration(seconds: 5), () {
+ // Reuse code and reason from the local close.
+ _closeCode = _outCloseCode;
+ _closeReason = _outCloseReason;
+ if (_subscription != null) _subscription.cancel();
+ _controller.close();
+ _webSockets.remove(_serviceId);
+ });
}
return _sink.close();
}
diff --git a/lib/src/exception.dart b/lib/src/exception.dart
index 6cb8836..d166e6a 100644
--- a/lib/src/exception.dart
+++ b/lib/src/exception.dart
@@ -17,7 +17,8 @@
: message = inner.toString(),
inner = inner;
+ @override
String toString() => message == null
- ? "WebSocketChannelException"
- : "WebSocketChannelException: $message";
+ ? 'WebSocketChannelException'
+ : 'WebSocketChannelException: $message';
}
diff --git a/lib/src/sink_completer.dart b/lib/src/sink_completer.dart
index ae6e64e..c6204d6 100644
--- a/lib/src/sink_completer.dart
+++ b/lib/src/sink_completer.dart
@@ -37,7 +37,7 @@
/// A destination sink may be set at most once.
void setDestinationSink(WebSocketSink destinationSink) {
if (_sink._destinationSink != null) {
- throw StateError("Destination sink already set");
+ throw StateError('Destination sink already set');
}
_sink._setDestinationSink(destinationSink);
}
@@ -72,6 +72,7 @@
/// to going through [_controller].
bool get _canSendDirectly => _controller == null && _destinationSink != null;
+ @override
Future get done {
if (_doneCompleter != null) return _doneCompleter.future;
if (_destinationSink == null) {
@@ -81,6 +82,7 @@
return _destinationSink.done;
}
+ @override
void add(event) {
if (_canSendDirectly) {
_destinationSink.add(event);
@@ -90,6 +92,7 @@
}
}
+ @override
void addError(error, [StackTrace stackTrace]) {
if (_canSendDirectly) {
_destinationSink.addError(error, stackTrace);
@@ -99,6 +102,7 @@
}
}
+ @override
Future addStream(Stream stream) {
if (_canSendDirectly) return _destinationSink.addStream(stream);
@@ -106,6 +110,7 @@
return _controller.addStream(stream, cancelOnError: false);
}
+ @override
Future close([int closeCode, String closeReason]) {
if (_canSendDirectly) {
_destinationSink.close(closeCode, closeReason);
@@ -120,7 +125,7 @@
/// Create [_controller] if it doesn't yet exist.
void _ensureController() {
- if (_controller == null) _controller = StreamController(sync: true);
+ _controller ??= StreamController(sync: true);
}
/// Sets the destination sink to which events from this sink will be provided.
diff --git a/pubspec.yaml b/pubspec.yaml
index e5a2b35..8b79da0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: web_socket_channel
-version: 1.1.0
+version: 1.1.1-dev
description: >-
StreamChannel wrappers for WebSockets. Provides a cross-platform
diff --git a/test/html_test.dart b/test/html_test.dart
index b05c8ec..54df7cb 100644
--- a/test/html_test.dart
+++ b/test/html_test.dart
@@ -17,7 +17,7 @@
void main() {
int port;
setUpAll(() async {
- var channel = spawnHybridCode(r"""
+ var channel = spawnHybridCode(r'''
import 'dart:io';
import 'package:stream_channel/stream_channel.dart';
@@ -31,7 +31,7 @@
});
channel.sink.add(server.port);
}
- """, stayAlive: true);
+ ''', stayAlive: true);
port = await channel.stream.first;
});
@@ -41,72 +41,72 @@
if (channel != null) channel.sink.close();
});
- test("communicates using an existing WebSocket", () async {
- var webSocket = WebSocket("ws://localhost:$port");
+ test('communicates using an existing WebSocket', () async {
+ var webSocket = WebSocket('ws://localhost:$port');
channel = HtmlWebSocketChannel(webSocket);
var queue = StreamQueue(channel.stream);
- channel.sink.add("foo");
- expect(await queue.next, equals("foo"));
+ channel.sink.add('foo');
+ expect(await queue.next, equals('foo'));
channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
expect(await _decodeBlob(await queue.next), equals([1, 2, 3, 4, 5]));
- webSocket.binaryType = "arraybuffer";
+ webSocket.binaryType = 'arraybuffer';
channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
expect(await queue.next, equals([1, 2, 3, 4, 5]));
});
- test("communicates using an existing open WebSocket", () async {
- var webSocket = WebSocket("ws://localhost:$port");
+ test('communicates using an existing open WebSocket', () async {
+ var webSocket = WebSocket('ws://localhost:$port');
await webSocket.onOpen.first;
channel = HtmlWebSocketChannel(webSocket);
var queue = StreamQueue(channel.stream);
- channel.sink.add("foo");
- expect(await queue.next, equals("foo"));
+ channel.sink.add('foo');
+ expect(await queue.next, equals('foo'));
});
- test(".connect defaults to binary lists", () async {
- channel = HtmlWebSocketChannel.connect("ws://localhost:$port");
+ test('.connect defaults to binary lists', () async {
+ channel = HtmlWebSocketChannel.connect('ws://localhost:$port');
var queue = StreamQueue(channel.stream);
- channel.sink.add("foo");
- expect(await queue.next, equals("foo"));
+ channel.sink.add('foo');
+ expect(await queue.next, equals('foo'));
channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
expect(await queue.next, equals([1, 2, 3, 4, 5]));
});
- test(".connect defaults to binary lists using platform independent api",
+ test('.connect defaults to binary lists using platform independent api',
() async {
- channel = WebSocketChannel.connect(Uri.parse("ws://localhost:$port"));
+ channel = WebSocketChannel.connect(Uri.parse('ws://localhost:$port'));
var queue = StreamQueue(channel.stream);
- channel.sink.add("foo");
- expect(await queue.next, equals("foo"));
+ channel.sink.add('foo');
+ expect(await queue.next, equals('foo'));
channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
expect(await queue.next, equals([1, 2, 3, 4, 5]));
});
- test(".connect can use blobs", () async {
- channel = HtmlWebSocketChannel.connect("ws://localhost:$port",
+ test('.connect can use blobs', () async {
+ channel = HtmlWebSocketChannel.connect('ws://localhost:$port',
binaryType: BinaryType.blob);
var queue = StreamQueue(channel.stream);
- channel.sink.add("foo");
- expect(await queue.next, equals("foo"));
+ channel.sink.add('foo');
+ expect(await queue.next, equals('foo'));
channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
expect(await _decodeBlob(await queue.next), equals([1, 2, 3, 4, 5]));
});
- test(".connect wraps a connection error in WebSocketChannelException",
+ test('.connect wraps a connection error in WebSocketChannelException',
() async {
// Spawn a server that will immediately reject the connection.
- var serverChannel = spawnHybridCode(r"""
+ var serverChannel = spawnHybridCode(r'''
import 'dart:io';
import 'package:stream_channel/stream_channel.dart';
@@ -118,12 +118,12 @@
});
channel.sink.add(server.port);
}
- """);
+ ''');
// TODO(nweiz): Make this channel use a port number that's guaranteed to be
// invalid.
var channel = HtmlWebSocketChannel.connect(
- "ws://localhost:${await serverChannel.stream.first}");
+ 'ws://localhost:${await serverChannel.stream.first}');
expect(channel.stream.toList(),
throwsA(TypeMatcher<WebSocketChannelException>()));
});
diff --git a/test/io_test.dart b/test/io_test.dart
index 4d4b1a9..7d87c3f 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -17,111 +17,111 @@
if (server != null) await server.close();
});
- test("communicates using existing WebSockets", () async {
- server = await HttpServer.bind("localhost", 0);
+ test('communicates using existing WebSockets', () async {
+ server = await HttpServer.bind('localhost', 0);
server.transform(WebSocketTransformer()).listen((webSocket) {
var channel = IOWebSocketChannel(webSocket);
- channel.sink.add("hello!");
+ channel.sink.add('hello!');
channel.stream.listen((request) {
- expect(request, equals("ping"));
- channel.sink.add("pong");
- channel.sink.close(5678, "raisin");
+ expect(request, equals('ping'));
+ channel.sink.add('pong');
+ channel.sink.close(5678, 'raisin');
});
});
- var webSocket = await WebSocket.connect("ws://localhost:${server.port}");
+ var webSocket = await WebSocket.connect('ws://localhost:${server.port}');
var channel = IOWebSocketChannel(webSocket);
var n = 0;
channel.stream.listen((message) {
if (n == 0) {
- expect(message, equals("hello!"));
- channel.sink.add("ping");
+ expect(message, equals('hello!'));
+ channel.sink.add('ping');
} else if (n == 1) {
- expect(message, equals("pong"));
+ expect(message, equals('pong'));
} else {
- fail("Only expected two messages.");
+ fail('Only expected two messages.');
}
n++;
}, onDone: expectAsync0(() {
expect(channel.closeCode, equals(5678));
- expect(channel.closeReason, equals("raisin"));
+ expect(channel.closeReason, equals('raisin'));
}));
});
- test(".connect communicates immediately", () async {
- server = await HttpServer.bind("localhost", 0);
+ test('.connect communicates immediately', () async {
+ server = await HttpServer.bind('localhost', 0);
server.transform(WebSocketTransformer()).listen((webSocket) {
var channel = IOWebSocketChannel(webSocket);
channel.stream.listen((request) {
- expect(request, equals("ping"));
- channel.sink.add("pong");
+ expect(request, equals('ping'));
+ channel.sink.add('pong');
});
});
- var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}");
- channel.sink.add("ping");
+ var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
+ channel.sink.add('ping');
channel.stream.listen(
expectAsync1((message) {
- expect(message, equals("pong"));
- channel.sink.close(5678, "raisin");
+ expect(message, equals('pong'));
+ channel.sink.close(5678, 'raisin');
}, count: 1),
onDone: expectAsync0(() {}));
});
- test(".connect communicates immediately using platform independent api",
+ test('.connect communicates immediately using platform independent api',
() async {
- server = await HttpServer.bind("localhost", 0);
+ server = await HttpServer.bind('localhost', 0);
server.transform(WebSocketTransformer()).listen((webSocket) {
var channel = IOWebSocketChannel(webSocket);
channel.stream.listen((request) {
- expect(request, equals("ping"));
- channel.sink.add("pong");
+ expect(request, equals('ping'));
+ channel.sink.add('pong');
});
});
var channel =
- WebSocketChannel.connect(Uri.parse("ws://localhost:${server.port}"));
- channel.sink.add("ping");
+ WebSocketChannel.connect(Uri.parse('ws://localhost:${server.port}'));
+ channel.sink.add('ping');
channel.stream.listen(
expectAsync1((message) {
- expect(message, equals("pong"));
- channel.sink.close(5678, "raisin");
+ expect(message, equals('pong'));
+ channel.sink.close(5678, 'raisin');
}, count: 1),
onDone: expectAsync0(() {}));
});
- test(".connect with an immediate call to close", () async {
- server = await HttpServer.bind("localhost", 0);
+ test('.connect with an immediate call to close', () async {
+ server = await HttpServer.bind('localhost', 0);
server.transform(WebSocketTransformer()).listen((webSocket) {
expect(() async {
var channel = IOWebSocketChannel(webSocket);
await channel.stream.drain();
expect(channel.closeCode, equals(5678));
- expect(channel.closeReason, equals("raisin"));
+ expect(channel.closeReason, equals('raisin'));
}(), completes);
});
- var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}");
- await channel.sink.close(5678, "raisin");
+ var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
+ await channel.sink.close(5678, 'raisin');
});
- test(".connect wraps a connection error in WebSocketChannelException",
+ test('.connect wraps a connection error in WebSocketChannelException',
() async {
- server = await HttpServer.bind("localhost", 0);
+ server = await HttpServer.bind('localhost', 0);
server.listen((request) {
request.response.statusCode = 404;
request.response.close();
});
- var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}");
+ var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
expect(channel.stream.drain(),
throwsA(TypeMatcher<WebSocketChannelException>()));
});
- test(".protocols fail", () async {
+ test('.protocols fail', () async {
var passedProtocol = 'passed-protocol';
var failedProtocol = 'failed-protocol';
var selector = (List<String> receivedProtocols) => passedProtocol;
@@ -132,13 +132,13 @@
throwsException);
});
- var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}",
+ var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}',
protocols: [failedProtocol]);
expect(channel.stream.drain(),
throwsA(TypeMatcher<WebSocketChannelException>()));
});
- test(".protocols pass", () async {
+ test('.protocols pass', () async {
var passedProtocol = 'passed-protocol';
var selector = (List<String> receivedProtocols) => passedProtocol;
@@ -150,7 +150,7 @@
await webSocket.close();
});
- var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}",
+ var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}',
protocols: [passedProtocol]);
await channel.stream.drain();
expect(channel.protocol, passedProtocol);
diff --git a/test/web_socket_test.dart b/test/web_socket_test.dart
index 0d63323..be22850 100644
--- a/test/web_socket_test.dart
+++ b/test/web_socket_test.dart
@@ -12,26 +12,26 @@
import 'package:web_socket_channel/web_socket_channel.dart';
void main() {
- group("using WebSocketChannel", () {
- test("a client can communicate with a WebSocket server", () async {
- var server = await HttpServer.bind("localhost", 0);
+ group('using WebSocketChannel', () {
+ test('a client can communicate with a WebSocket server', () async {
+ var server = await HttpServer.bind('localhost', 0);
server.transform(WebSocketTransformer()).listen((webSocket) {
- webSocket.add("hello!");
+ webSocket.add('hello!');
webSocket.listen((request) {
- expect(request, equals("ping"));
- webSocket.add("pong");
+ expect(request, equals('ping'));
+ webSocket.add('pong');
webSocket.close();
});
});
var client = HttpClient();
var request = await client.openUrl(
- "GET", Uri.parse("http://localhost:${server.port}"));
+ 'GET', Uri.parse('http://localhost:${server.port}'));
request.headers
- ..set("Connection", "Upgrade")
- ..set("Upgrade", "websocket")
- ..set("Sec-WebSocket-Key", "x3JJHMbDL1EzLkh9GBhXDw==")
- ..set("Sec-WebSocket-Version", "13");
+ ..set('Connection', 'Upgrade')
+ ..set('Upgrade', 'websocket')
+ ..set('Sec-WebSocket-Key', 'x3JJHMbDL1EzLkh9GBhXDw==')
+ ..set('Sec-WebSocket-Version', '13');
var response = await request.close();
var socket = await response.detachSocket();
@@ -41,29 +41,29 @@
var n = 0;
await webSocket.stream.listen((message) {
if (n == 0) {
- expect(message, equals("hello!"));
- webSocket.sink.add("ping");
+ expect(message, equals('hello!'));
+ webSocket.sink.add('ping');
} else if (n == 1) {
- expect(message, equals("pong"));
+ expect(message, equals('pong'));
webSocket.sink.close();
server.close();
} else {
- fail("Only expected two messages.");
+ fail('Only expected two messages.');
}
n++;
}).asFuture();
});
- test("a server can communicate with a WebSocket client", () async {
- var server = await HttpServer.bind("localhost", 0);
+ test('a server can communicate with a WebSocket client', () async {
+ var server = await HttpServer.bind('localhost', 0);
server.listen((request) async {
var response = request.response;
response.statusCode = 101;
response.headers
- ..set("Connection", "Upgrade")
- ..set("Upgrade", "websocket")
+ ..set('Connection', 'Upgrade')
+ ..set('Upgrade', 'websocket')
..set(
- "Sec-WebSocket-Accept",
+ 'Sec-WebSocket-Accept',
WebSocketChannel.signKey(
request.headers.value('Sec-WebSocket-Key')));
response.contentLength = 0;
@@ -71,11 +71,11 @@
var socket = await response.detachSocket();
var innerChannel = StreamChannel<List<int>>(socket, socket);
var webSocket = WebSocketChannel(innerChannel);
- webSocket.sink.add("hello!");
+ webSocket.sink.add('hello!');
var message = await webSocket.stream.first;
- expect(message, equals("ping"));
- webSocket.sink.add("pong");
+ expect(message, equals('ping'));
+ webSocket.sink.add('pong');
await webSocket.sink.close();
});
@@ -83,14 +83,14 @@
var n = 0;
await webSocket.listen((message) {
if (n == 0) {
- expect(message, equals("hello!"));
- webSocket.add("ping");
+ expect(message, equals('hello!'));
+ webSocket.add('ping');
} else if (n == 1) {
- expect(message, equals("pong"));
+ expect(message, equals('pong'));
webSocket.close();
server.close();
} else {
- fail("Only expected two messages.");
+ fail('Only expected two messages.');
}
n++;
}).asFuture();