Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate to pkg web #294

Merged
merged 4 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
30 changes: 20 additions & 10 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,7 +75,8 @@ 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)
: this(WebSocket(url.toString(),
(protocols ?? <String>[]).toList().map((e) => e.toJS).toList().toJS)
kevmoo marked this conversation as resolved.
Show resolved Hide resolved
..binaryType = (binaryType ?? BinaryType.list).value);

/// Creates a channel wrapping [innerWebSocket].
Expand Down Expand Up @@ -109,11 +112,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 +123,27 @@ class HtmlWebSocketChannel extends StreamChannelMixin
});
}

void _innerListen(MessageEvent event) {
dynamic data = event.data;
kevmoo marked this conversation as resolved.
Show resolved Hide resolved

if ((data as JSAny?).typeofEquals('object') &&
(data as JSObject).instanceOfString('ArrayBuffer')) {
data = (data as JSArrayBuffer).toDart.asUint8List();
}
_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
12 changes: 12 additions & 0 deletions lib/src/web_helpers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:web/helpers.dart';
kevmoo marked this conversation as resolved.
Show resolved Hide resolved

extension WebSocketExtension on WebSocket {
kevmoo marked this conversation as resolved.
Show resolved Hide resolved
Stream<Event> get onOpen =>
const EventStreamProvider<Event>('open').forTarget(this);
Stream<MessageEvent> get onMessage =>
const EventStreamProvider<MessageEvent>('message').forTarget(this);
Stream<CloseEvent> get onClose =>
const EventStreamProvider<CloseEvent>('close').forTarget(this);
Stream<Event> get onError =>
const EventStreamProvider<Event>('error').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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its definitely good to start dogfooding this stuff; does this in any way tie our hands wrt publishing packages that now depend on it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful about Flutter pinning pkg:web. It does make things...interesting...

Copy link
Contributor

@NotTsunami NotTsunami Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to allow the same version range as http (from dart-lang/http#1055) if a release is planned anytime soon (flutter 3.16.x pins web 0.3.0)

EDIT: Just read "I'm not racing to publish this", probably not a bad change to add though still


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();
}