Chromium Code Reviews| Index: sdk/lib/io/websocket_impl.dart |
| diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart |
| index 0da50b2dfaa6116bcf850c17f690ec0a30255881..6e2137f0543157646389b7c87cf2ea8edc1c7456 100644 |
| --- a/sdk/lib/io/websocket_impl.dart |
| +++ b/sdk/lib/io/websocket_impl.dart |
| @@ -69,7 +69,7 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
| final bool _serverSide; |
| final List _maskingBytes = new List(4); |
| - final BytesBuilder _payload = new BytesBuilder(); |
| + final List<Uint8List> _payloads = new List<Uint8List>(); |
| _WebSocketProtocolTransformer([this._serverSide = false]); |
| @@ -90,6 +90,27 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
| void close() => _eventSink.close(); |
| + Uint8List _takePayload() { |
| + if (_payloads.length == 0) return new Uint8List(0); |
|
kasperl
2014/01/29 11:10:44
Do you have to create a new one here? Cache an emp
Anders Johnsen
2014/01/29 14:23:40
The empty-list case is very rare, and not somethin
|
| + if (_payloads.length == 1) { |
| + Uint8List result = _payloads.single; |
| + _payloads.clear(); |
| + return result; |
| + } |
| + int length = 0; |
| + for (Uint8List payload in _payloads) { |
| + length += payload.length; |
| + } |
| + Uint8List result = new Uint8List(length); |
| + int offset = 0; |
| + for (Uint8List payload in _payloads) { |
| + result.setRange(offset, offset + payload.length, payload); |
| + offset += payload.length; |
| + } |
| + _payloads.clear(); |
| + return result; |
| + } |
| + |
| /** |
| * Process data received from the underlying communication channel. |
| */ |
| @@ -175,8 +196,9 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
| if (_masked) { |
| _unmask(index, payloadLength, buffer); |
| } |
| - // Control frame and data frame share _payload builder. |
| - _payload.add(new Uint8List.view(buffer.buffer, index, payloadLength)); |
| + // Control frame and data frame share _payloads. |
| + _payloads.add( |
| + new Uint8List.view(buffer.buffer, index, payloadLength)); |
| index += payloadLength; |
| if (_isControlFrame()) { |
| if (_remainingPayloadBytes == 0) _controlFrameEnd(); |
| @@ -285,10 +307,10 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
| if (_fin) { |
| switch (_currentMessageType) { |
| case _WebSocketMessageType.TEXT: |
| - _eventSink.add(UTF8.decode(_payload.takeBytes())); |
| + _eventSink.add(UTF8.decode(_takePayload())); |
| break; |
| case _WebSocketMessageType.BINARY: |
| - _eventSink.add(_payload.takeBytes()); |
| + _eventSink.add(_takePayload()); |
| break; |
| } |
| _currentMessageType = _WebSocketMessageType.NONE; |
| @@ -300,17 +322,17 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
| switch (_opcode) { |
| case _WebSocketOpcode.CLOSE: |
| closeCode = WebSocketStatus.NO_STATUS_RECEIVED; |
| - if (_payload.length > 0) { |
| - var bytes = _payload.takeBytes(); |
| - if (bytes.length == 1) { |
| + var payload = _takePayload(); |
| + if (payload.length > 0) { |
| + if (payload.length == 1) { |
| throw new WebSocketException("Protocol error"); |
| } |
| - closeCode = bytes[0] << 8 | bytes[1]; |
| + closeCode = payload[0] << 8 | payload[1]; |
| if (closeCode == WebSocketStatus.NO_STATUS_RECEIVED) { |
| throw new WebSocketException("Protocol error"); |
| } |
| - if (bytes.length > 2) { |
| - closeReason = UTF8.decode(bytes.sublist(2)); |
| + if (payload.length > 2) { |
| + closeReason = UTF8.decode(payload.sublist(2)); |
| } |
| } |
| _state = CLOSED; |
| @@ -318,11 +340,11 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
| break; |
| case _WebSocketOpcode.PING: |
| - _eventSink.add(new _WebSocketPing(_payload.takeBytes())); |
| + _eventSink.add(new _WebSocketPing(_takePayload())); |
| break; |
| case _WebSocketOpcode.PONG: |
| - _eventSink.add(new _WebSocketPong(_payload.takeBytes())); |
| + _eventSink.add(new _WebSocketPong(_takePayload())); |
| break; |
| } |
| _prepareForNextFrame(); |