From ac3144083ad65ffa83875adeb22ef79a7894e203 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 4 Aug 2017 10:33:22 -0700 Subject: [PATCH 1/5] enable travis --- .travis.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a24a813 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,25 @@ +language: dart +sudo: false +dart: + - dev + - stable + +dart_task: + - test: --platform vm + - test: --platform firefox -j 1 + - test: --platform dartium + install_dartium: true + - dartanalyzer + +matrix: + include: + - dart: dev + dart_task: dartfmt + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache From b666e7e01f32be311e52fa886502722c7410badb Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 4 Aug 2017 10:33:53 -0700 Subject: [PATCH 2/5] dartfmt --- lib/html.dart | 10 +++---- lib/io.dart | 14 ++++++---- lib/src/channel.dart | 6 ++-- lib/src/copy/bytes_builder.dart | 10 ++++--- lib/src/copy/io_sink.dart | 10 +++---- lib/src/copy/web_socket_impl.dart | 46 +++++++++++++++++++------------ lib/src/exception.dart | 4 +-- lib/src/sink_completer.dart | 2 +- test/html_test.dart | 4 +-- test/io_test.dart | 22 ++++++++------- test/web_socket_test.dart | 6 ++-- 11 files changed, 77 insertions(+), 57 deletions(-) diff --git a/lib/html.dart b/lib/html.dart index f9daadc..6d5007a 100644 --- a/lib/html.dart +++ b/lib/html.dart @@ -45,8 +45,8 @@ class HtmlWebSocketChannel extends StreamChannelMixin String _localCloseReason; Stream get stream => _controller.foreign.stream; - final _controller = new StreamChannelController( - sync: true, allowForeignErrors: false); + final _controller = + new StreamChannelController(sync: true, allowForeignErrors: false); WebSocketSink get sink => _sink; WebSocketSink _sink; @@ -62,13 +62,13 @@ class HtmlWebSocketChannel extends StreamChannelMixin /// received by this socket. It defaults to [BinaryType.list], which causes /// binary messages to be delivered as [Uint8List]s. If it's /// [BinaryType.blob], they're delivered as [Blob]s instead. - HtmlWebSocketChannel.connect(url, {Iterable protocols, - BinaryType binaryType}) + HtmlWebSocketChannel.connect(url, + {Iterable protocols, BinaryType binaryType}) : this(new WebSocket(url.toString(), protocols) ..binaryType = (binaryType ?? BinaryType.list).value); /// Creates a channel wrapping [webSocket]. - HtmlWebSocketChannel(this._webSocket){ + HtmlWebSocketChannel(this._webSocket) { _sink = new _HtmlWebSocketSink(this); if (_webSocket.readyState == WebSocket.OPEN) { diff --git a/lib/io.dart b/lib/io.dart index 0764acf..607d225 100644 --- a/lib/io.dart +++ b/lib/io.dart @@ -48,8 +48,10 @@ class IOWebSocketChannel extends StreamChannelMixin /// /// If there's an error connecting, the channel's stream emits a /// [WebSocketChannelException] wrapping that error and then closes. - factory IOWebSocketChannel.connect(url, {Iterable protocols, - Map headers, Duration pingInterval}) { + factory IOWebSocketChannel.connect(url, + {Iterable protocols, + Map headers, + Duration pingInterval}) { var channel; var sinkCompleter = new WebSocketSinkCompleter(); var stream = StreamCompleter.fromFuture( @@ -67,8 +69,8 @@ class IOWebSocketChannel extends StreamChannelMixin /// Creates a channel wrapping [socket]. IOWebSocketChannel(WebSocket socket) : _webSocket = socket, - stream = socket.handleError((error) => - throw new WebSocketChannelException.from(error)), + stream = socket.handleError( + (error) => throw new WebSocketChannelException.from(error)), sink = new _IOWebSocketSink(socket); /// Creates a channel without a socket. @@ -77,8 +79,8 @@ class IOWebSocketChannel extends StreamChannelMixin /// has a socket added. IOWebSocketChannel._withoutSocket(Stream stream, this.sink) : _webSocket = null, - stream = stream.handleError((error) => - throw new WebSocketChannelException.from(error)); + stream = stream.handleError( + (error) => throw new WebSocketChannelException.from(error)); } /// A [WebSocketSink] that forwards [close] calls to a `dart:io` [WebSocket]. diff --git a/lib/src/channel.dart b/lib/src/channel.dart index 6aff42c..4cd368c 100644 --- a/lib/src/channel.dart +++ b/lib/src/channel.dart @@ -65,8 +65,8 @@ class WebSocketChannel extends StreamChannelMixin { static String signKey(String key) { // We use [codeUnits] here rather than UTF-8-decoding the string because // [key] is expected to be base64 encoded, and so will be pure ASCII. - return convert.BASE64.encode( - sha1.convert((key + webSocketGUID).codeUnits).bytes); + return convert.BASE64 + .encode(sha1.convert((key + webSocketGUID).codeUnits).bytes); } /// Creates a new WebSocket handling messaging across an existing [channel]. @@ -90,7 +90,7 @@ class WebSocketChannel extends StreamChannelMixin { /// /// [WebSocket handshake]: https://tools.ietf.org/html/rfc6455#section-4 WebSocketChannel(StreamChannel> channel, - {String protocol, Duration pingInterval, bool serverSide: true}) + {String protocol, Duration pingInterval, bool serverSide: true}) : _webSocket = new WebSocketImpl.fromSocket( channel.stream, channel.sink, protocol, serverSide) ..pingInterval = pingInterval; diff --git a/lib/src/copy/bytes_builder.dart b/lib/src/copy/bytes_builder.dart index 573eed5..1d88199 100644 --- a/lib/src/copy/bytes_builder.dart +++ b/lib/src/copy/bytes_builder.dart @@ -88,7 +88,6 @@ abstract class BytesBuilder { void clear(); } - class _CopyingBytesBuilder implements BytesBuilder { // Start with 1024 bytes. static const int _INIT_SIZE = 1024; @@ -123,7 +122,9 @@ class _CopyingBytesBuilder implements BytesBuilder { _length = required; } - void addByte(int byte) { add([byte]); } + void addByte(int byte) { + add([byte]); + } List takeBytes() { if (_buffer == null) return new Uint8List(0); @@ -160,7 +161,6 @@ class _CopyingBytesBuilder implements BytesBuilder { } } - class _BytesBuilder implements BytesBuilder { int _length = 0; final _chunks = >[]; @@ -173,7 +173,9 @@ class _BytesBuilder implements BytesBuilder { _length += bytes.length; } - void addByte(int byte) { add([byte]); } + void addByte(int byte) { + add([byte]); + } List takeBytes() { if (_chunks.length == 0) return new Uint8List(0); diff --git a/lib/src/copy/io_sink.dart b/lib/src/copy/io_sink.dart index 34abcad..dafd86b 100644 --- a/lib/src/copy/io_sink.dart +++ b/lib/src/copy/io_sink.dart @@ -41,11 +41,11 @@ class StreamSinkImpl implements StreamSink { if (_hasError) return done; // Wait for any sync operations to complete. Future targetAddStream() { - return _target.addStream(stream) - .whenComplete(() { - _isBound = false; - }); + return _target.addStream(stream).whenComplete(() { + _isBound = false; + }); } + if (_controllerInstance == null) return targetAddStream(); var future = _controllerCompleter.future; _controllerInstance.close(); @@ -133,7 +133,7 @@ class StreamSinkImpl implements StreamSink { _completeDoneError(error, stackTrace); } }); - } + } return _controllerInstance; } } diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart index e26e1b3..260a341 100644 --- a/lib/src/copy/web_socket_impl.dart +++ b/lib/src/copy/web_socket_impl.dart @@ -118,7 +118,9 @@ class _WebSocketProtocolTransformer _eventSink.addError(error, stackTrace); } - void close() { _eventSink.close(); } + void close() { + _eventSink.close(); + } /** * Process data received from the underlying communication channel. @@ -139,7 +141,7 @@ class _WebSocketProtocolTransformer if (_state == START) { _fin = (byte & FIN) != 0; - if((byte & (RSV2 | RSV3)) != 0) { + if ((byte & (RSV2 | RSV3)) != 0) { // The RSV2, RSV3 bits must both be zero. throw new WebSocketChannelException("Protocol error"); } @@ -468,11 +470,8 @@ class _WebSocketOutgoingTransformer _eventSink.close(); } - void addFrame(int opcode, List data) => createFrame( - opcode, - data, - webSocket._serverSide, - false).forEach((e) { + void addFrame(int opcode, List data) => + createFrame(opcode, data, webSocket._serverSide, false).forEach((e) { _eventSink.add(e); }); @@ -491,9 +490,9 @@ class _WebSocketOutgoingTransformer int index = 0; // Set FIN and opcode. - var hoc = _WebSocketProtocolTransformer.FIN - | (compressed ? _WebSocketProtocolTransformer.RSV1 : 0) - | (opcode & _WebSocketProtocolTransformer.OPCODE); + var hoc = _WebSocketProtocolTransformer.FIN | + (compressed ? _WebSocketProtocolTransformer.RSV1 : 0) | + (opcode & _WebSocketProtocolTransformer.OPCODE); header[index++] = hoc; // Determine size and position of length field. @@ -511,8 +510,12 @@ class _WebSocketOutgoingTransformer } if (mask) { header[1] |= 1 << 7; - var maskBytes = [_random.nextInt(256), _random.nextInt(256), - _random.nextInt(256), _random.nextInt(256)]; + var maskBytes = [ + _random.nextInt(256), + _random.nextInt(256), + _random.nextInt(256), + _random.nextInt(256) + ]; header.setRange(index, index + 4, maskBytes); index += 4; if (data != null) { @@ -667,6 +670,7 @@ class _WebSocketConsumer implements StreamConsumer { Future closeSocket() { return sink.close().catchError((_) {}).then((_) => webSocket); } + _controller.close(); return _closeCompleter.future.then((_) => closeSocket()); } @@ -755,10 +759,14 @@ class WebSocketImpl extends Stream with _ServiceObject implements StreamSink { }, cancelOnError: true); _subscription.pause(); _controller = new StreamController( - sync: true, onListen: () => _subscription.resume(), onCancel: () { - _subscription.cancel(); - _subscription = null; - }, onPause: _subscription.pause, onResume: _subscription.resume); + sync: true, + onListen: () => _subscription.resume(), + onCancel: () { + _subscription.cancel(); + _subscription = null; + }, + onPause: _subscription.pause, + onResume: _subscription.resume); _webSockets[_serviceId] = this; } @@ -794,10 +802,14 @@ class WebSocketImpl extends Stream with _ServiceObject implements StreamSink { int get closeCode => _closeCode; String get closeReason => _closeReason; - void add(data) { _sink.add(data); } + void add(data) { + _sink.add(data); + } + void addError(error, [StackTrace stackTrace]) { _sink.addError(error, stackTrace); } + Future addStream(Stream stream) => _sink.addStream(stream); Future get done => _sink.done; diff --git a/lib/src/exception.dart b/lib/src/exception.dart index 47545ed..6cb8836 100644 --- a/lib/src/exception.dart +++ b/lib/src/exception.dart @@ -18,6 +18,6 @@ class WebSocketChannelException implements Exception { inner = inner; 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 d932fd7..04a915c 100644 --- a/lib/src/sink_completer.dart +++ b/lib/src/sink_completer.dart @@ -150,4 +150,4 @@ class _CompleterSink implements WebSocketSink { _doneCompleter.complete(sink.done); } } -} \ No newline at end of file +} diff --git a/test/html_test.dart b/test/html_test.dart index 8c9f44e..83f112f 100644 --- a/test/html_test.dart +++ b/test/html_test.dart @@ -80,8 +80,8 @@ void main() { }); test(".connect can use blobs", () async { - channel = new HtmlWebSocketChannel.connect( - "ws://localhost:$port", binaryType: BinaryType.blob); + channel = new HtmlWebSocketChannel.connect("ws://localhost:$port", + binaryType: BinaryType.blob); var queue = new StreamQueue(channel.stream); channel.sink.add("foo"); diff --git a/test/io_test.dart b/test/io_test.dart index fcf8c7c..a277d79 100644 --- a/test/io_test.dart +++ b/test/io_test.dart @@ -59,14 +59,16 @@ void main() { }); }); - var channel = new IOWebSocketChannel.connect( - "ws://localhost:${server.port}"); + var channel = + new IOWebSocketChannel.connect("ws://localhost:${server.port}"); channel.sink.add("ping"); - channel.stream.listen(expectAsync((message) { - expect(message, equals("pong")); - channel.sink.close(5678, "raisin"); - }, count: 1), onDone: expectAsync(() {})); + channel.stream.listen( + expectAsync((message) { + expect(message, equals("pong")); + channel.sink.close(5678, "raisin"); + }, count: 1), + onDone: expectAsync(() {})); }); test(".connect with an immediate call to close", () async { @@ -80,8 +82,8 @@ void main() { }(), completes); }); - var channel = new IOWebSocketChannel.connect( - "ws://localhost:${server.port}"); + var channel = + new IOWebSocketChannel.connect("ws://localhost:${server.port}"); channel.sink.close(5678, "raisin"); }); @@ -93,8 +95,8 @@ void main() { request.response.close(); }); - var channel = new IOWebSocketChannel.connect( - "ws://localhost:${server.port}"); + var channel = + new IOWebSocketChannel.connect("ws://localhost:${server.port}"); expect(channel.stream.toList(), throwsA(new isInstanceOf())); }); diff --git a/test/web_socket_test.dart b/test/web_socket_test.dart index 217df13..68d6b35 100644 --- a/test/web_socket_test.dart +++ b/test/web_socket_test.dart @@ -62,8 +62,10 @@ void main() { response.headers ..set("Connection", "Upgrade") ..set("Upgrade", "websocket") - ..set("Sec-WebSocket-Accept", WebSocketChannel - .signKey(request.headers.value('Sec-WebSocket-Key'))); + ..set( + "Sec-WebSocket-Accept", + WebSocketChannel + .signKey(request.headers.value('Sec-WebSocket-Key'))); response.contentLength = 0; var socket = await response.detachSocket(); From 9acbba98a0898cb2e44b340efe998fee18fdbec6 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 4 Aug 2017 10:36:19 -0700 Subject: [PATCH 3/5] Fix analysis warnings --- lib/src/copy/web_socket_impl.dart | 9 --------- pubspec.yaml | 2 +- test/io_test.dart | 6 +++--- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart index 260a341..e1c4d88 100644 --- a/lib/src/copy/web_socket_impl.dart +++ b/lib/src/copy/web_socket_impl.dart @@ -84,7 +84,6 @@ class _WebSocketProtocolTransformer int _state = START; bool _fin = false; - bool _compressed = false; int _opcode = -1; int _len = -1; bool _masked = false; @@ -148,14 +147,6 @@ class _WebSocketProtocolTransformer _opcode = (byte & OPCODE); - if (_opcode != _WebSocketOpcode.CONTINUATION) { - if ((byte & RSV1) != 0) { - _compressed = true; - } else { - _compressed = false; - } - } - if (_opcode <= _WebSocketOpcode.BINARY) { if (_opcode == _WebSocketOpcode.CONTINUATION) { if (_currentMessageType == _WebSocketMessageType.NONE) { diff --git a/pubspec.yaml b/pubspec.yaml index 0f04ff6..31d3a8f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: web_socket_channel -version: 1.0.5 +version: 1.0.6-dev description: StreamChannel wrappers for WebSockets. author: Dart Team homepage: https://github.com/dart-lang/web_socket_channel diff --git a/test/io_test.dart b/test/io_test.dart index a277d79..dfa718d 100644 --- a/test/io_test.dart +++ b/test/io_test.dart @@ -43,7 +43,7 @@ void main() { fail("Only expected two messages."); } n++; - }, onDone: expectAsync(() { + }, onDone: expectAsync0(() { expect(channel.closeCode, equals(5678)); expect(channel.closeReason, equals("raisin")); })); @@ -64,11 +64,11 @@ void main() { channel.sink.add("ping"); channel.stream.listen( - expectAsync((message) { + expectAsync1((message) { expect(message, equals("pong")); channel.sink.close(5678, "raisin"); }, count: 1), - onDone: expectAsync(() {})); + onDone: expectAsync0(() {})); }); test(".connect with an immediate call to close", () async { From bc2dcd42ab593b83733aa0bcf81761d4340de7ce Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 4 Aug 2017 10:39:39 -0700 Subject: [PATCH 4/5] cleanup gitignore --- .gitignore | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 25a1df3..52f0c5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ -.buildlog -.DS_Store -.idea -.pub/ -.settings/ -build/ -packages .packages +.pub/ pubspec.lock From 441883bcd8d434a13835a4dfc8983193cabfb195 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 4 Aug 2017 10:45:58 -0700 Subject: [PATCH 5/5] Lint cleanup: initialize to null, return values on setter, comment syntax --- lib/src/copy/bytes_builder.dart | 76 ++++++++++++------------------- lib/src/copy/web_socket.dart | 8 +--- lib/src/copy/web_socket_impl.dart | 31 ++++++------- 3 files changed, 44 insertions(+), 71 deletions(-) diff --git a/lib/src/copy/bytes_builder.dart b/lib/src/copy/bytes_builder.dart index 1d88199..429e6d1 100644 --- a/lib/src/copy/bytes_builder.dart +++ b/lib/src/copy/bytes_builder.dart @@ -14,21 +14,17 @@ import 'dart:math'; import 'dart:typed_data'; -/** - * Builds a list of bytes, allowing bytes and lists of bytes to be added at the - * end. - * - * Used to efficiently collect bytes and lists of bytes. - */ +/// Builds a list of bytes, allowing bytes and lists of bytes to be added at the +/// end. +/// +/// Used to efficiently collect bytes and lists of bytes. abstract class BytesBuilder { - /** - * Construct a new empty [BytesBuilder]. - * - * If [copy] is true, the data is always copied when added to the list. If - * it [copy] is false, the data is only copied if needed. That means that if - * the lists are changed after added to the [BytesBuilder], it may effect the - * output. Default is `true`. - */ + /// Construct a new empty [BytesBuilder]. + /// + /// If [copy] is true, the data is always copied when added to the list. If + /// it [copy] is false, the data is only copied if needed. That means that if + /// the lists are changed after added to the [BytesBuilder], it may effect the + /// output. Default is `true`. factory BytesBuilder({bool copy: true}) { if (copy) { return new _CopyingBytesBuilder(); @@ -37,54 +33,38 @@ abstract class BytesBuilder { } } - /** - * Appends [bytes] to the current contents of the builder. - * - * Each value of [bytes] will be bit-representation truncated to the range - * 0 .. 255. - */ + /// Appends [bytes] to the current contents of the builder. + /// + /// Each value of [bytes] will be bit-representation truncated to the range + /// 0 .. 255. void add(List bytes); - /** - * Append [byte] to the current contents of the builder. - * - * The [byte] will be bit-representation truncated to the range 0 .. 255. - */ + /// Append [byte] to the current contents of the builder. + /// + /// The [byte] will be bit-representation truncated to the range 0 .. 255. void addByte(int byte); - /** - * Returns the contents of `this` and clears `this`. - * - * The list returned is a view of the the internal buffer, limited to the - * [length]. - */ + /// Returns the contents of `this` and clears `this`. + /// + /// The list returned is a view of the the internal buffer, limited to the + /// [length]. List takeBytes(); - /** - * Returns a copy of the current contents of the builder. - * - * Leaves the contents of the builder intact. - */ + /// Returns a copy of the current contents of the builder. + /// + /// Leaves the contents of the builder intact. List toBytes(); - /** - * The number of bytes in the builder. - */ + /// The number of bytes in the builder. int get length; - /** - * Returns `true` if the buffer is empty. - */ + /// Returns `true` if the buffer is empty. bool get isEmpty; - /** - * Returns `true` if the buffer is not empty. - */ + /// Returns `true` if the buffer is not empty. bool get isNotEmpty; - /** - * Clear the contents of the builder. - */ + /// Clear the contents of the builder. void clear(); } diff --git a/lib/src/copy/web_socket.dart b/lib/src/copy/web_socket.dart index c77dc2f..c08b9ac 100644 --- a/lib/src/copy/web_socket.dart +++ b/lib/src/copy/web_socket.dart @@ -11,9 +11,7 @@ // This is up-to-date as of sdk revision // e41fb4cafd6052157dbc1490d437045240f4773f. -/** - * Web socket status codes used when closing a web socket connection. - */ +/// Web socket status codes used when closing a web socket connection. abstract class WebSocketStatus { static const int NORMAL_CLOSURE = 1000; static const int GOING_AWAY = 1001; @@ -31,9 +29,7 @@ abstract class WebSocketStatus { } abstract class WebSocket { - /** - * Possible states of the connection. - */ + /// Possible states of the connection. static const int CONNECTING = 0; static const int OPEN = 1; static const int CLOSING = 2; diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart index e1c4d88..8996619 100644 --- a/lib/src/copy/web_socket_impl.dart +++ b/lib/src/copy/web_socket_impl.dart @@ -57,15 +57,13 @@ class _WebSocketOpcode { static const int RESERVED_F = 15; } -/** - * The web socket protocol transformer handles the protocol byte stream - * which is supplied through the [:handleData:]. As the protocol is processed, - * it'll output frame data as either a List or String. - * - * Important information about usage: Be sure you use cancelOnError, so the - * socket will be closed when the processor encounter an error. Not using it - * will lead to undefined behaviour. - */ +/// The web socket protocol transformer handles the protocol byte stream +/// which is supplied through the [:handleData:]. As the protocol is processed, +/// it'll output frame data as either a List or String. +/// +/// Important information about usage: Be sure you use cancelOnError, so the +/// socket will be closed when the processor encounter an error. Not using it +/// will lead to undefined behaviour. // TODO(ajohnsen): make this transformer reusable? class _WebSocketProtocolTransformer implements StreamTransformer, dynamic>, EventSink> { @@ -121,9 +119,7 @@ class _WebSocketProtocolTransformer _eventSink.close(); } - /** - * Process data received from the underlying communication channel. - */ + /// Process data received from the underlying communication channel. void add(List bytes) { var buffer = bytes is Uint8List ? bytes : new Uint8List.fromList(bytes); int index = 0; @@ -386,12 +382,12 @@ class _WebSocketProtocolTransformer class _WebSocketPing { final List payload; - _WebSocketPing([this.payload = null]); + _WebSocketPing([this.payload]); } class _WebSocketPong { final List payload; - _WebSocketPong([this.payload = null]); + _WebSocketPong([this.payload]); } // TODO(ajohnsen): Make this transformer reusable. @@ -567,7 +563,7 @@ class _WebSocketConsumer implements StreamConsumer { StreamSubscription _subscription; bool _issuedPause = false; bool _closed = false; - Completer _closeCompleter = new Completer(); + final Completer _closeCompleter = new Completer(); Completer _completer; _WebSocketConsumer(this.webSocket, this.sink); @@ -681,7 +677,8 @@ class _WebSocketConsumer implements StreamConsumer { class WebSocketImpl extends Stream with _ServiceObject implements StreamSink { // Use default Map so we keep order. - static Map _webSockets = new Map(); + static final Map _webSockets = + new Map(); static const int DEFAULT_WINDOW_BITS = 15; static const String PER_MESSAGE_DEFLATE = "permessage-deflate"; @@ -770,7 +767,7 @@ class WebSocketImpl extends Stream with _ServiceObject implements StreamSink { Duration get pingInterval => _pingInterval; - void set pingInterval(Duration interval) { + set pingInterval(Duration interval) { if (_writeClosed) return; if (_pingTimer != null) _pingTimer.cancel(); _pingInterval = interval;