Skip to content

Commit

Permalink
migrate to pkg web (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevmoo authored Nov 22, 2023
1 parent 5241175 commit 9e80b8d
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 15 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
## 2.4.1-wip

- Bump minimum Dart version to 3.2.0
- Update the examples to use `WebSocketChannel.ready` and clarify that
`WebSocketChannel.ready` should be awaited before sending data over the
`WebSocketChannel`.
- Mention `ready` in the docs for `connect`.
- Bump minimum Dart version to 3.2.0
- Move to `pkg:web` to support WebAssembly compilation.

## 2.4.0

Expand Down
40 changes: 29 additions & 11 deletions lib/html.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:html';
import 'dart:js_interop';
import 'dart:typed_data';

import 'package:async/async.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:web/helpers.dart';

import 'src/channel.dart';
import 'src/exception.dart';
import 'src/web_helpers.dart';

/// A [WebSocketChannel] that communicates using a `dart:html` [WebSocket].
class HtmlWebSocketChannel extends StreamChannelMixin
Expand Down Expand Up @@ -73,8 +75,15 @@ class HtmlWebSocketChannel extends StreamChannelMixin
/// [BinaryType.blob], they're delivered as [Blob]s instead.
HtmlWebSocketChannel.connect(Object url,
{Iterable<String>? protocols, BinaryType? binaryType})
: this(WebSocket(url.toString(), protocols)
..binaryType = (binaryType ?? BinaryType.list).value);
: this(
WebSocket(
url.toString(),
(protocols?.toList() ?? const <String>[])
.map((e) => e.toJS)
.toList()
.toJS,
)..binaryType = (binaryType ?? BinaryType.list).value,
);

/// Creates a channel wrapping [innerWebSocket].
HtmlWebSocketChannel(this.innerWebSocket) {
Expand Down Expand Up @@ -109,11 +118,7 @@ class HtmlWebSocketChannel extends StreamChannelMixin
_controller.local.sink.close();
});

innerWebSocket.onMessage.listen((event) {
var data = event.data;
if (data is ByteBuffer) data = data.asUint8List();
_controller.local.sink.add(data);
});
innerWebSocket.onMessage.listen(_innerListen);

// The socket API guarantees that only a single error event will be emitted,
// and that once it is no other events will be emitted.
Expand All @@ -124,16 +129,29 @@ class HtmlWebSocketChannel extends StreamChannelMixin
});
}

void _innerListen(MessageEvent event) {
final eventData = event.data;
Object? data;
if (eventData.typeofEquals('object') &&
(eventData as JSObject).instanceOfString('ArrayBuffer')) {
data = (eventData as JSArrayBuffer).toDart.asUint8List();
} else {
data = event.data;
}
_controller.local.sink.add(data);
}

/// Pipes user events to [innerWebSocket].
void _listen() {
_controller.local.stream.listen(innerWebSocket.send, onDone: () {
_controller.local.stream.listen((obj) => innerWebSocket.send(obj!.jsify()!),
onDone: () {
// On Chrome and possibly other browsers, `null` can't be passed as the
// default here. The actual arity of the function call must be correct or
// it will fail.
if (_localCloseCode != null && _localCloseReason != null) {
innerWebSocket.close(_localCloseCode, _localCloseReason);
innerWebSocket.close(_localCloseCode!, _localCloseReason!);
} else if (_localCloseCode != null) {
innerWebSocket.close(_localCloseCode);
innerWebSocket.close(_localCloseCode!);
} else {
innerWebSocket.close();
}
Expand Down
17 changes: 17 additions & 0 deletions lib/src/web_helpers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:web/helpers.dart';

// TODO(kevmoo): remove when https://github.com/dart-lang/web/commit/4cb5811ed06
// is in a published release and the min constraint on pkg:web is updated
extension WebSocketEvents on WebSocket {
Stream<Event> get onOpen => EventStreamProviders.openEvent.forTarget(this);
Stream<MessageEvent> get onMessage =>
EventStreamProviders.messageEvent.forTarget(this);
Stream<CloseEvent> get onClose =>
EventStreamProviders.closeEvent.forTarget(this);
Stream<Event> get onError =>
EventStreamProviders.errorEventSourceEvent.forTarget(this);
}
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
async: ^2.5.0
crypto: ^3.0.0
stream_channel: ^2.1.0
web: ^0.4.0

dev_dependencies:
dart_flutter_team_lints: ^2.0.0
Expand Down
8 changes: 5 additions & 3 deletions test/html_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
library;

import 'dart:async';
import 'dart:html';
import 'dart:js_interop';
import 'dart:typed_data';

import 'package:async/async.dart';
import 'package:test/test.dart';
import 'package:web/helpers.dart' hide BinaryType;
import 'package:web_socket_channel/html.dart';
import 'package:web_socket_channel/src/web_helpers.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

void main() {
Expand Down Expand Up @@ -176,6 +178,6 @@ void main() {
Future<List<int>> _decodeBlob(Blob blob) async {
final reader = FileReader();
reader.readAsArrayBuffer(blob);
await reader.onLoad.first;
return reader.result as Uint8List;
await reader.onLoadEnd.first;
return (reader.result as JSArrayBuffer).toDart.asUint8List();
}

0 comments on commit 9e80b8d

Please sign in to comment.