Skip to content

Commit

Permalink
Add WebSocket.addUtf8Text to allow sending pre-encoded text without a…
Browse files Browse the repository at this point in the history
… round-trip UTF-8 conversion.

Use it to implement the vm-service, where in particular we are concerned about the space overhead of the conversion leading to the process being killed on iOS.

Closes #27129

R=johnmccutchan@google.com, lrn@google.com

Review URL: https://codereview.chromium.org/2260073002 .
  • Loading branch information
rmacnak-google committed Aug 24, 2016
1 parent 97da42b commit aa38062
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,9 @@
* `dart:async`
* `Future.wait` now catches synchronous errors and returns them in the
returned Future.
* `dart:io`
* Added `WebSocket.addUtf8Text` to allow sending a pre-encoded text message
without a round-trip UTF-8 conversion.

## 1.19.0

Expand Down
5 changes: 1 addition & 4 deletions runtime/bin/vmservice/server.dart
Expand Up @@ -57,10 +57,7 @@ class WebSocketClient extends Client {
// String message as external Uint8List.
assert(result is List);
Uint8List cstring = result[0];
// TODO(rmacnak): cstring may be large. Add a way to pass an encoded
// string to a web socket that will be sent as a text message to avoid
// the space overhead of converting cstring to a Dart string.
socket.add(UTF8.decode(cstring));
socket.addUtf8Text(cstring);
}
} catch (_) {
print("Ignoring error posting over WebSocket.");
Expand Down
8 changes: 8 additions & 0 deletions sdk/lib/io/websocket.dart
Expand Up @@ -402,6 +402,14 @@ abstract class WebSocket
* must be either `String`s, or `List<int>`s holding bytes.
*/
Future addStream(Stream stream);

/**
* Sends a text message with the text represented by [bytes].
*
* The [bytes] should be valid UTF-8 encoded Unicode characters. If they are
* not, the receiving end will close the connection.
*/
void addUtf8Text(List<int> bytes);
}

class WebSocketException implements IOException {
Expand Down
24 changes: 18 additions & 6 deletions sdk/lib/io/websocket_impl.dart
Expand Up @@ -36,6 +36,11 @@ class _WebSocketOpcode {
static const int RESERVED_F = 15;
}

class _EncodedString {
final List<int> bytes;
_EncodedString(this.bytes);
}

/**
* Stores the header and integer value derived from negotiation of
* client_max_window_bits and server_max_window_bits. headerValue will be
Expand Down Expand Up @@ -670,13 +675,14 @@ class _WebSocketOutgoingTransformer
if (message is String) {
opcode = _WebSocketOpcode.TEXT;
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>) {
opcode = _WebSocketOpcode.BINARY;
data = message;
} else {
throw new ArgumentError(message);
}
throw new ArgumentError(message);
}

if (_deflateHelper != null) {
Expand Down Expand Up @@ -1176,6 +1182,12 @@ class _WebSocketImpl extends Stream with _ServiceObject implements WebSocket {
String get closeReason => _closeReason;

void add(data) { _sink.add(data); }
void addUtf8Text(List<int> bytes) {
if (bytes is! List<int>) {
throw new ArgumentError(bytes, "bytes", "Is not a list of bytes");
}
_sink.add(new _EncodedString(bytes));
}
void addError(error, [StackTrace stackTrace]) {
_sink.addError(error, stackTrace);
}
Expand Down

0 comments on commit aa38062

Please sign in to comment.