Skip to content

Commit 0f37053

Browse files
authored
Bring in code from the latest SDK (flutter#12)
1 parent 910bd47 commit 0f37053

File tree

6 files changed

+118
-68
lines changed

6 files changed

+118
-68
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.0.7
2+
3+
* Support the latest dev SDK.
4+
15
## 1.0.6
26

37
* Declare support for `async` 2.0.0.

lib/src/copy/bytes_builder.dart

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
// Because it's copied directly, there are no modifications from the original.
1010
//
1111
// This is up-to-date as of sdk revision
12-
// e41fb4cafd6052157dbc1490d437045240f4773f.
12+
// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
1313

14-
import 'dart:math';
1514
import 'dart:typed_data';
1615

1716
/// Builds a list of bytes, allowing bytes and lists of bytes to be added at the
@@ -46,7 +45,7 @@ abstract class BytesBuilder {
4645

4746
/// Returns the contents of `this` and clears `this`.
4847
///
49-
/// The list returned is a view of the the internal buffer, limited to the
48+
/// The list returned is a view of the internal buffer, limited to the
5049
/// [length].
5150
List<int> takeBytes();
5251

@@ -72,24 +71,22 @@ class _CopyingBytesBuilder implements BytesBuilder {
7271
// Start with 1024 bytes.
7372
static const int _INIT_SIZE = 1024;
7473

74+
static final _emptyList = new Uint8List(0);
75+
7576
int _length = 0;
7677
Uint8List _buffer;
7778

79+
_CopyingBytesBuilder([int initialCapacity = 0])
80+
: _buffer = (initialCapacity <= 0)
81+
? _emptyList
82+
: new Uint8List(_pow2roundup(initialCapacity));
83+
7884
void add(List<int> bytes) {
7985
int bytesLength = bytes.length;
8086
if (bytesLength == 0) return;
8187
int required = _length + bytesLength;
82-
if (_buffer == null) {
83-
int size = _pow2roundup(required);
84-
size = max(size, _INIT_SIZE);
85-
_buffer = new Uint8List(size);
86-
} else if (_buffer.length < required) {
87-
// We will create a list in the range of 2-4 times larger than
88-
// required.
89-
int size = _pow2roundup(required) * 2;
90-
var newBuffer = new Uint8List(size);
91-
newBuffer.setRange(0, _buffer.length, _buffer);
92-
_buffer = newBuffer;
88+
if (_buffer.length < required) {
89+
_grow(required);
9390
}
9491
assert(_buffer.length >= required);
9592
if (bytes is Uint8List) {
@@ -103,18 +100,39 @@ class _CopyingBytesBuilder implements BytesBuilder {
103100
}
104101

105102
void addByte(int byte) {
106-
add([byte]);
103+
if (_buffer.length == _length) {
104+
// The grow algorithm always at least doubles.
105+
// If we added one to _length it would quadruple unnecessarily.
106+
_grow(_length);
107+
}
108+
assert(_buffer.length > _length);
109+
_buffer[_length] = byte;
110+
_length++;
111+
}
112+
113+
void _grow(int required) {
114+
// We will create a list in the range of 2-4 times larger than
115+
// required.
116+
int newSize = required * 2;
117+
if (newSize < _INIT_SIZE) {
118+
newSize = _INIT_SIZE;
119+
} else {
120+
newSize = _pow2roundup(newSize);
121+
}
122+
var newBuffer = new Uint8List(newSize);
123+
newBuffer.setRange(0, _buffer.length, _buffer);
124+
_buffer = newBuffer;
107125
}
108126

109127
List<int> takeBytes() {
110-
if (_buffer == null) return new Uint8List(0);
128+
if (_length == 0) return _emptyList;
111129
var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
112130
clear();
113131
return buffer;
114132
}
115133

116134
List<int> toBytes() {
117-
if (_buffer == null) return new Uint8List(0);
135+
if (_length == 0) return _emptyList;
118136
return new Uint8List.fromList(
119137
new Uint8List.view(_buffer.buffer, 0, _length));
120138
}
@@ -127,10 +145,11 @@ class _CopyingBytesBuilder implements BytesBuilder {
127145

128146
void clear() {
129147
_length = 0;
130-
_buffer = null;
148+
_buffer = _emptyList;
131149
}
132150

133-
int _pow2roundup(int x) {
151+
static int _pow2roundup(int x) {
152+
assert(x > 0);
134153
--x;
135154
x |= x >> 1;
136155
x |= x >> 2;
@@ -143,24 +162,28 @@ class _CopyingBytesBuilder implements BytesBuilder {
143162

144163
class _BytesBuilder implements BytesBuilder {
145164
int _length = 0;
146-
final _chunks = <List<int>>[];
165+
final List<Uint8List> _chunks = [];
147166

148167
void add(List<int> bytes) {
149-
if (bytes is! Uint8List) {
150-
bytes = new Uint8List.fromList(bytes);
168+
Uint8List typedBytes;
169+
if (bytes is Uint8List) {
170+
typedBytes = bytes;
171+
} else {
172+
typedBytes = new Uint8List.fromList(bytes);
151173
}
152-
_chunks.add(bytes);
153-
_length += bytes.length;
174+
_chunks.add(typedBytes);
175+
_length += typedBytes.length;
154176
}
155177

156178
void addByte(int byte) {
157-
add([byte]);
179+
_chunks.add(new Uint8List(1)..[0] = byte);
180+
_length++;
158181
}
159182

160183
List<int> takeBytes() {
161-
if (_chunks.length == 0) return new Uint8List(0);
184+
if (_length == 0) return _CopyingBytesBuilder._emptyList;
162185
if (_chunks.length == 1) {
163-
var buffer = _chunks.single;
186+
var buffer = _chunks[0];
164187
clear();
165188
return buffer;
166189
}
@@ -175,7 +198,7 @@ class _BytesBuilder implements BytesBuilder {
175198
}
176199

177200
List<int> toBytes() {
178-
if (_chunks.length == 0) return new Uint8List(0);
201+
if (_length == 0) return _CopyingBytesBuilder._emptyList;
179202
var buffer = new Uint8List(_length);
180203
int offset = 0;
181204
for (var chunk in _chunks) {

lib/src/copy/io_sink.dart

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// desired public API and to remove "dart:io" dependencies have been made.
1010
//
1111
// This is up-to-date as of sdk revision
12-
// e41fb4cafd6052157dbc1490d437045240f4773f.
12+
// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
1313

1414
import 'dart:async';
1515

@@ -24,32 +24,40 @@ class StreamSinkImpl<T> implements StreamSink<T> {
2424

2525
StreamSinkImpl(this._target);
2626

27+
// The _reportClosedSink method has been deleted for web_socket_channel. This
28+
// method did nothing but print to stderr, which is unavailable here.
29+
2730
void add(T data) {
28-
if (_isClosed) return;
31+
if (_isClosed) {
32+
return;
33+
}
2934
_controller.add(data);
3035
}
3136

3237
void addError(error, [StackTrace stackTrace]) {
38+
if (_isClosed) {
39+
return;
40+
}
3341
_controller.addError(error, stackTrace);
3442
}
3543

3644
Future addStream(Stream<T> stream) {
3745
if (_isBound) {
3846
throw new StateError("StreamSink is already bound to a stream");
3947
}
40-
_isBound = true;
4148
if (_hasError) return done;
42-
// Wait for any sync operations to complete.
43-
Future targetAddStream() {
44-
return _target.addStream(stream).whenComplete(() {
45-
_isBound = false;
46-
});
47-
}
4849

49-
if (_controllerInstance == null) return targetAddStream();
50-
var future = _controllerCompleter.future;
51-
_controllerInstance.close();
52-
return future.then((_) => targetAddStream());
50+
_isBound = true;
51+
var future = _controllerCompleter == null
52+
? _target.addStream(stream)
53+
: _controllerCompleter.future.then((_) => _target.addStream(stream));
54+
_controllerInstance?.close();
55+
56+
// Wait for any pending events in [_controller] to be dispatched before
57+
// adding [stream].
58+
return future.whenComplete(() {
59+
_isBound = false;
60+
});
5361
}
5462

5563
Future flush() {

lib/src/copy/web_socket.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// desired public API and to remove "dart:io" dependencies have been made.
1010
//
1111
// This is up-to-date as of sdk revision
12-
// e41fb4cafd6052157dbc1490d437045240f4773f.
12+
// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
1313

1414
/// Web socket status codes used when closing a web socket connection.
1515
abstract class WebSocketStatus {

lib/src/copy/web_socket_impl.dart

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// desired public API and to remove "dart:io" dependencies have been made.
1111
//
1212
// This is up-to-date as of sdk revision
13-
// e41fb4cafd6052157dbc1490d437045240f4773f.
13+
// 365f7b5a8b6ef900a5ee23913b7203569b81b175.
1414

1515
import 'dart:async';
1616
import 'dart:convert';
@@ -57,16 +57,21 @@ class _WebSocketOpcode {
5757
static const int RESERVED_F = 15;
5858
}
5959

60+
class _EncodedString {
61+
final List<int> bytes;
62+
_EncodedString(this.bytes);
63+
}
64+
6065
/// The web socket protocol transformer handles the protocol byte stream
61-
/// which is supplied through the [:handleData:]. As the protocol is processed,
66+
/// which is supplied through the `handleData`. As the protocol is processed,
6267
/// it'll output frame data as either a List<int> or String.
6368
///
6469
/// Important information about usage: Be sure you use cancelOnError, so the
6570
/// socket will be closed when the processor encounter an error. Not using it
6671
/// will lead to undefined behaviour.
67-
// TODO(ajohnsen): make this transformer reusable?
68-
class _WebSocketProtocolTransformer
69-
implements StreamTransformer<List<int>, dynamic>, EventSink<List<int>> {
72+
class _WebSocketProtocolTransformer extends StreamTransformerBase<List<int>,
73+
dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ >
74+
implements EventSink<List<int>> {
7075
static const int START = 0;
7176
static const int LEN_FIRST = 1;
7277
static const int LEN_REST = 2;
@@ -93,15 +98,16 @@ class _WebSocketProtocolTransformer
9398
int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
9499
String closeReason = "";
95100

96-
EventSink _eventSink;
101+
EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > _eventSink;
97102

98103
final bool _serverSide;
99104
final List _maskingBytes = new List(4);
100105
final BytesBuilder _payload = new BytesBuilder(copy: false);
101106

102107
_WebSocketProtocolTransformer([this._serverSide = false]);
103108

104-
Stream bind(Stream stream) {
109+
Stream<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > bind(
110+
Stream<List<int>> stream) {
105111
return new Stream.eventTransformed(stream, (EventSink eventSink) {
106112
if (_eventSink != null) {
107113
throw new StateError("WebSocket transformer already used.");
@@ -319,7 +325,7 @@ class _WebSocketProtocolTransformer
319325

320326
switch (_currentMessageType) {
321327
case _WebSocketMessageType.TEXT:
322-
_eventSink.add(UTF8.decode(bytes));
328+
_eventSink.add(utf8.decode(bytes));
323329
break;
324330
case _WebSocketMessageType.BINARY:
325331
_eventSink.add(bytes);
@@ -344,7 +350,7 @@ class _WebSocketProtocolTransformer
344350
throw new WebSocketChannelException("Protocol error");
345351
}
346352
if (payload.length > 2) {
347-
closeReason = UTF8.decode(payload.sublist(2));
353+
closeReason = utf8.decode(payload.sublist(2));
348354
}
349355
}
350356
_state = CLOSED;
@@ -392,14 +398,15 @@ class _WebSocketPong {
392398

393399
// TODO(ajohnsen): Make this transformer reusable.
394400
class _WebSocketOutgoingTransformer
395-
implements StreamTransformer<dynamic, List<int>>, EventSink {
401+
extends StreamTransformerBase<dynamic, List<int>> implements EventSink {
396402
final WebSocketImpl webSocket;
397403
EventSink<List<int>> _eventSink;
398404

399405
_WebSocketOutgoingTransformer(this.webSocket);
400406

401407
Stream<List<int>> bind(Stream stream) {
402-
return new Stream.eventTransformed(stream, (eventSink) {
408+
return new Stream<List<int>>.eventTransformed(stream,
409+
(EventSink<List<int>> eventSink) {
403410
if (_eventSink != null) {
404411
throw new StateError("WebSocket transformer already used");
405412
}
@@ -422,14 +429,15 @@ class _WebSocketOutgoingTransformer
422429
if (message != null) {
423430
if (message is String) {
424431
opcode = _WebSocketOpcode.TEXT;
425-
data = UTF8.encode(message);
432+
data = utf8.encode(message);
433+
} else if (message is List<int>) {
434+
opcode = _WebSocketOpcode.BINARY;
435+
data = message;
436+
} else if (message is _EncodedString) {
437+
opcode = _WebSocketOpcode.TEXT;
438+
data = message.bytes;
426439
} else {
427-
if (message is List<int>) {
428-
data = message;
429-
opcode = _WebSocketOpcode.BINARY;
430-
} else {
431-
throw new ArgumentError(message);
432-
}
440+
throw new ArgumentError(message);
433441
}
434442
} else {
435443
opcode = _WebSocketOpcode.TEXT;
@@ -450,17 +458,24 @@ class _WebSocketOutgoingTransformer
450458
data.add((code >> 8) & 0xFF);
451459
data.add(code & 0xFF);
452460
if (reason != null) {
453-
data.addAll(UTF8.encode(reason));
461+
data.addAll(utf8.encode(reason));
454462
}
455463
}
456464
addFrame(_WebSocketOpcode.CLOSE, data);
457465
_eventSink.close();
458466
}
459467

460-
void addFrame(int opcode, List<int> data) =>
461-
createFrame(opcode, data, webSocket._serverSide, false).forEach((e) {
462-
_eventSink.add(e);
463-
});
468+
void addFrame(int opcode, List<int> data) {
469+
createFrame(
470+
opcode,
471+
data,
472+
webSocket._serverSide,
473+
// Logic around _deflateHelper was removed here, since ther ewill never
474+
// be a deflate helper for a cross-platform WebSocket client.
475+
false).forEach((e) {
476+
_eventSink.add(e);
477+
});
478+
}
464479

465480
static Iterable<List<int>> createFrame(
466481
int opcode, List<int> data, bool serverSide, bool compressed) {
@@ -563,7 +578,7 @@ class _WebSocketConsumer implements StreamConsumer {
563578
StreamSubscription _subscription;
564579
bool _issuedPause = false;
565580
bool _closed = false;
566-
final Completer _closeCompleter = new Completer();
581+
final Completer _closeCompleter = new Completer<WebSocketImpl>();
567582
Completer _completer;
568583

569584
_WebSocketConsumer(this.webSocket, this.sink);

0 commit comments

Comments
 (0)