Merge remote-tracking branch 'origin/corelib_2_2_1_branch'
This doesn't change the state of master. An old version of the Dart
SDK depended on a commit from the branch that's being merged in, and
this ensures that that commit remains reachable so that version can
still be built.
diff --git a/.travis.yml b/.travis.yml
index a24a813..3ef6c26 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,14 +1,10 @@
language: dart
sudo: false
-dart:
- - dev
- - stable
+dart: dev
dart_task:
- test: --platform vm
- test: --platform firefox -j 1
- - test: --platform dartium
- install_dartium: true
- dartanalyzer
matrix:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49b2eec..d50f8d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,6 @@
## 1.0.7
-* Updates to support Dart 2.0 core library changes (wave 2.2).
- See [issue 31847][sdk#31847] for details.
-
- [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847
+* Support the latest dev SDK.
## 1.0.6
diff --git a/lib/src/copy/bytes_builder.dart b/lib/src/copy/bytes_builder.dart
index 429e6d1..1e37093 100644
--- a/lib/src/copy/bytes_builder.dart
+++ b/lib/src/copy/bytes_builder.dart
@@ -9,9 +9,8 @@
// Because it's copied directly, there are no modifications from the original.
//
// This is up-to-date as of sdk revision
-// e41fb4cafd6052157dbc1490d437045240f4773f.
+// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
-import 'dart:math';
import 'dart:typed_data';
/// Builds a list of bytes, allowing bytes and lists of bytes to be added at the
@@ -46,7 +45,7 @@
/// Returns the contents of `this` and clears `this`.
///
- /// The list returned is a view of the the internal buffer, limited to the
+ /// The list returned is a view of the internal buffer, limited to the
/// [length].
List<int> takeBytes();
@@ -72,24 +71,22 @@
// Start with 1024 bytes.
static const int _INIT_SIZE = 1024;
+ static final _emptyList = new Uint8List(0);
+
int _length = 0;
Uint8List _buffer;
+ _CopyingBytesBuilder([int initialCapacity = 0])
+ : _buffer = (initialCapacity <= 0)
+ ? _emptyList
+ : new Uint8List(_pow2roundup(initialCapacity));
+
void add(List<int> bytes) {
int bytesLength = bytes.length;
if (bytesLength == 0) return;
int required = _length + bytesLength;
- if (_buffer == null) {
- int size = _pow2roundup(required);
- size = max(size, _INIT_SIZE);
- _buffer = new Uint8List(size);
- } else if (_buffer.length < required) {
- // We will create a list in the range of 2-4 times larger than
- // required.
- int size = _pow2roundup(required) * 2;
- var newBuffer = new Uint8List(size);
- newBuffer.setRange(0, _buffer.length, _buffer);
- _buffer = newBuffer;
+ if (_buffer.length < required) {
+ _grow(required);
}
assert(_buffer.length >= required);
if (bytes is Uint8List) {
@@ -103,18 +100,39 @@
}
void addByte(int byte) {
- add([byte]);
+ if (_buffer.length == _length) {
+ // The grow algorithm always at least doubles.
+ // If we added one to _length it would quadruple unnecessarily.
+ _grow(_length);
+ }
+ assert(_buffer.length > _length);
+ _buffer[_length] = byte;
+ _length++;
+ }
+
+ void _grow(int required) {
+ // We will create a list in the range of 2-4 times larger than
+ // required.
+ int newSize = required * 2;
+ if (newSize < _INIT_SIZE) {
+ newSize = _INIT_SIZE;
+ } else {
+ newSize = _pow2roundup(newSize);
+ }
+ var newBuffer = new Uint8List(newSize);
+ newBuffer.setRange(0, _buffer.length, _buffer);
+ _buffer = newBuffer;
}
List<int> takeBytes() {
- if (_buffer == null) return new Uint8List(0);
+ if (_length == 0) return _emptyList;
var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
clear();
return buffer;
}
List<int> toBytes() {
- if (_buffer == null) return new Uint8List(0);
+ if (_length == 0) return _emptyList;
return new Uint8List.fromList(
new Uint8List.view(_buffer.buffer, 0, _length));
}
@@ -127,10 +145,11 @@
void clear() {
_length = 0;
- _buffer = null;
+ _buffer = _emptyList;
}
- int _pow2roundup(int x) {
+ static int _pow2roundup(int x) {
+ assert(x > 0);
--x;
x |= x >> 1;
x |= x >> 2;
@@ -143,24 +162,28 @@
class _BytesBuilder implements BytesBuilder {
int _length = 0;
- final _chunks = <List<int>>[];
+ final List<Uint8List> _chunks = [];
void add(List<int> bytes) {
- if (bytes is! Uint8List) {
- bytes = new Uint8List.fromList(bytes);
+ Uint8List typedBytes;
+ if (bytes is Uint8List) {
+ typedBytes = bytes;
+ } else {
+ typedBytes = new Uint8List.fromList(bytes);
}
- _chunks.add(bytes);
- _length += bytes.length;
+ _chunks.add(typedBytes);
+ _length += typedBytes.length;
}
void addByte(int byte) {
- add([byte]);
+ _chunks.add(new Uint8List(1)..[0] = byte);
+ _length++;
}
List<int> takeBytes() {
- if (_chunks.length == 0) return new Uint8List(0);
+ if (_length == 0) return _CopyingBytesBuilder._emptyList;
if (_chunks.length == 1) {
- var buffer = _chunks.single;
+ var buffer = _chunks[0];
clear();
return buffer;
}
@@ -175,7 +198,7 @@
}
List<int> toBytes() {
- if (_chunks.length == 0) return new Uint8List(0);
+ if (_length == 0) return _CopyingBytesBuilder._emptyList;
var buffer = new Uint8List(_length);
int offset = 0;
for (var chunk in _chunks) {
diff --git a/lib/src/copy/io_sink.dart b/lib/src/copy/io_sink.dart
index dafd86b..3a51ff1 100644
--- a/lib/src/copy/io_sink.dart
+++ b/lib/src/copy/io_sink.dart
@@ -9,7 +9,7 @@
// desired public API and to remove "dart:io" dependencies have been made.
//
// This is up-to-date as of sdk revision
-// e41fb4cafd6052157dbc1490d437045240f4773f.
+// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
import 'dart:async';
@@ -24,12 +24,20 @@
StreamSinkImpl(this._target);
+ // The _reportClosedSink method has been deleted for web_socket_channel. This
+ // method did nothing but print to stderr, which is unavailable here.
+
void add(T data) {
- if (_isClosed) return;
+ if (_isClosed) {
+ return;
+ }
_controller.add(data);
}
void addError(error, [StackTrace stackTrace]) {
+ if (_isClosed) {
+ return;
+ }
_controller.addError(error, stackTrace);
}
@@ -37,19 +45,19 @@
if (_isBound) {
throw new StateError("StreamSink is already bound to a stream");
}
- _isBound = true;
if (_hasError) return done;
- // Wait for any sync operations to complete.
- Future targetAddStream() {
- return _target.addStream(stream).whenComplete(() {
- _isBound = false;
- });
- }
- if (_controllerInstance == null) return targetAddStream();
- var future = _controllerCompleter.future;
- _controllerInstance.close();
- return future.then((_) => targetAddStream());
+ _isBound = true;
+ var future = _controllerCompleter == null
+ ? _target.addStream(stream)
+ : _controllerCompleter.future.then((_) => _target.addStream(stream));
+ _controllerInstance?.close();
+
+ // Wait for any pending events in [_controller] to be dispatched before
+ // adding [stream].
+ return future.whenComplete(() {
+ _isBound = false;
+ });
}
Future flush() {
diff --git a/lib/src/copy/web_socket.dart b/lib/src/copy/web_socket.dart
index c08b9ac..1928a34 100644
--- a/lib/src/copy/web_socket.dart
+++ b/lib/src/copy/web_socket.dart
@@ -9,7 +9,7 @@
// desired public API and to remove "dart:io" dependencies have been made.
//
// This is up-to-date as of sdk revision
-// e41fb4cafd6052157dbc1490d437045240f4773f.
+// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
/// Web socket status codes used when closing a web socket connection.
abstract class WebSocketStatus {
diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart
index 5c8e1b3..58bcaba 100644
--- a/lib/src/copy/web_socket_impl.dart
+++ b/lib/src/copy/web_socket_impl.dart
@@ -10,7 +10,7 @@
// desired public API and to remove "dart:io" dependencies have been made.
//
// This is up-to-date as of sdk revision
-// e41fb4cafd6052157dbc1490d437045240f4773f.
+// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
import 'dart:async';
import 'dart:convert';
@@ -57,16 +57,20 @@
static const int RESERVED_F = 15;
}
+class _EncodedString {
+ final List<int> bytes;
+ _EncodedString(this.bytes);
+}
+
/// The web socket protocol transformer handles the protocol byte stream
-/// which is supplied through the [:handleData:]. As the protocol is processed,
+/// which is supplied through the `handleData`. As the protocol is processed,
/// it'll output frame data as either a List<int> 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
- extends StreamTransformerBase<List<int>, dynamic>
+class _WebSocketProtocolTransformer extends StreamTransformerBase<List<int>,
+ dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ >
implements EventSink<List<int>> {
static const int START = 0;
static const int LEN_FIRST = 1;
@@ -94,7 +98,7 @@
int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
String closeReason = "";
- EventSink _eventSink;
+ EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > _eventSink;
final bool _serverSide;
final List _maskingBytes = new List(4);
@@ -102,7 +106,8 @@
_WebSocketProtocolTransformer([this._serverSide = false]);
- Stream bind(Stream stream) {
+ Stream<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > bind(
+ Stream<List<int>> stream) {
return new Stream.eventTransformed(stream, (EventSink eventSink) {
if (_eventSink != null) {
throw new StateError("WebSocket transformer already used.");
@@ -320,7 +325,7 @@
switch (_currentMessageType) {
case _WebSocketMessageType.TEXT:
- _eventSink.add(UTF8.decode(bytes));
+ _eventSink.add(utf8.decode(bytes));
break;
case _WebSocketMessageType.BINARY:
_eventSink.add(bytes);
@@ -345,7 +350,7 @@
throw new WebSocketChannelException("Protocol error");
}
if (payload.length > 2) {
- closeReason = UTF8.decode(payload.sublist(2));
+ closeReason = utf8.decode(payload.sublist(2));
}
}
_state = CLOSED;
@@ -400,7 +405,8 @@
_WebSocketOutgoingTransformer(this.webSocket);
Stream<List<int>> bind(Stream stream) {
- return new Stream.eventTransformed(stream, (eventSink) {
+ return new Stream<List<int>>.eventTransformed(stream,
+ (EventSink<List<int>> eventSink) {
if (_eventSink != null) {
throw new StateError("WebSocket transformer already used");
}
@@ -423,14 +429,15 @@
if (message != null) {
if (message is String) {
opcode = _WebSocketOpcode.TEXT;
- data = UTF8.encode(message);
+ data = utf8.encode(message);
+ } else if (message is List<int>) {
+ opcode = _WebSocketOpcode.BINARY;
+ data = message;
+ } else if (message is _EncodedString) {
+ opcode = _WebSocketOpcode.TEXT;
+ data = message.bytes;
} else {
- if (message is List<int>) {
- data = message;
- opcode = _WebSocketOpcode.BINARY;
- } else {
- throw new ArgumentError(message);
- }
+ throw new ArgumentError(message);
}
} else {
opcode = _WebSocketOpcode.TEXT;
@@ -451,17 +458,24 @@
data.add((code >> 8) & 0xFF);
data.add(code & 0xFF);
if (reason != null) {
- data.addAll(UTF8.encode(reason));
+ data.addAll(utf8.encode(reason));
}
}
addFrame(_WebSocketOpcode.CLOSE, data);
_eventSink.close();
}
- void addFrame(int opcode, List<int> data) =>
- createFrame(opcode, data, webSocket._serverSide, false).forEach((e) {
- _eventSink.add(e);
- });
+ void addFrame(int opcode, List<int> data) {
+ createFrame(
+ opcode,
+ data,
+ webSocket._serverSide,
+ // Logic around _deflateHelper was removed here, since ther ewill never
+ // be a deflate helper for a cross-platform WebSocket client.
+ false).forEach((e) {
+ _eventSink.add(e);
+ });
+ }
static Iterable<List<int>> createFrame(
int opcode, List<int> data, bool serverSide, bool compressed) {
@@ -564,7 +578,7 @@
StreamSubscription _subscription;
bool _issuedPause = false;
bool _closed = false;
- final Completer _closeCompleter = new Completer();
+ final Completer _closeCompleter = new Completer<WebSocketImpl>();
Completer _completer;
_WebSocketConsumer(this.webSocket, this.sink);
diff --git a/pubspec.yaml b/pubspec.yaml
index 08dde58..dd70f7e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -5,7 +5,7 @@
homepage: https://github.com/dart-lang/web_socket_channel
environment:
- sdk: '>=2.0.0-dev.20.0 <2.0.0'
+ sdk: '>=2.0.0-dev.23.0 <2.0.0'
dependencies:
async: '>=1.3.0 <3.0.0'