Skip to content

Commit db79c37

Browse files
sabin26PlugFox
andauthored
Migrate from dart:html to package:web (#15)
* Migrate to package:web & dart:js_interop * Update pubspec.yaml * Update web interops * Refactor WebSocketClient$JS to simplify data handling * chore: update meta dependency to version 1.9.1 * chore: Migrate to package:web and dart:js_interop * chore: Add health checks to server startup --------- Co-authored-by: Plague Fox <[email protected]>
1 parent 5906239 commit db79c37

File tree

7 files changed

+71
-81
lines changed

7 files changed

+71
-81
lines changed

.vscode/launch.json

+9-5
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
"ENVIRONMENT": "test"
3838
},
3939
"console": "debugConsole",
40-
"runTestsOnDevice": false,
4140
"templateFor": "test",
4241
"toolArgs": [
4342
"--color",
@@ -47,8 +46,9 @@
4746
"--platform=chrome",
4847
"--file-reporter=json:.coverage/tests.json",
4948
"--timeout=30s",
50-
"--concurrency=12"
51-
/* "--name=can send binary data" */
49+
"--concurrency=12",
50+
"--chain-stack-traces"
51+
/* "--name=can send List<int> data" */
5252
],
5353
"args": []
5454
},
@@ -66,7 +66,11 @@
6666
"runTestsOnDevice": false,
6767
"templateFor": "test",
6868
"toolArgs": [],
69-
"args": ["--port=8080", "--isolates=2", "--verbose=4"]
69+
"args": [
70+
"--port=8080",
71+
"--isolates=2",
72+
"--verbose=4"
73+
]
7074
}
7175
]
72-
}
76+
}

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.1.0-dev.1
2+
3+
- Migration from 'dart:html' to 'package:web'
4+
15
## 1.0.0
26

37
- Stable release

analysis_options.yaml

-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ linter:
6464
avoid_js_rounded_ints: true
6565
avoid_print: true
6666
avoid_renaming_method_parameters: true
67-
avoid_returning_null_for_future: true
6867
avoid_returning_null_for_void: true
6968
avoid_single_cascade_in_expression_statements: true
7069
avoid_slow_async_io: true
@@ -128,7 +127,6 @@ linter:
128127

129128
# Pedantic 1.9.0
130129
always_declare_return_types: true
131-
always_require_non_null_named_parameters: true
132130
annotate_overrides: true
133131
avoid_empty_else: true
134132
avoid_init_to_null: true
@@ -193,7 +191,6 @@ linter:
193191
prefer_mixin: true
194192
use_setters_to_change_properties: true
195193
avoid_setters_without_getters: true
196-
avoid_returning_null: true
197194
avoid_returning_this: true
198195
type_annotate_public_apis: true
199196
avoid_types_on_closure_parameters: true

lib/src/client/ws_client_js.dart

+52-69
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// coverage:ignore-file
33
import 'dart:async';
44
import 'dart:convert';
5-
import 'dart:html' as html show WebSocket, Blob, Event, CloseEvent, FileReader;
5+
import 'dart:js_interop' as js;
66
import 'dart:typed_data';
77

88
import 'package:meta/meta.dart';
9+
import 'package:web/web.dart' as web
10+
show Blob, CloseEvent, Event, WebSocket, WebSocketEvents;
911
import 'package:ws/src/client/web_socket_ready_state.dart';
1012
import 'package:ws/src/client/websocket_exception.dart';
1113
import 'package:ws/src/client/ws_client_base.dart';
@@ -47,7 +49,7 @@ final class WebSocketClient$JS extends WebSocketClientBase {
4749
final $WebSocketOptions$JS? _options;
4850

4951
/// Native WebSocket client.
50-
html.WebSocket? _client;
52+
web.WebSocket? _client;
5153

5254
/// Blob codec for `Blob <-> List<int>` conversion.
5355
late final _BlobCodec _blobCodec = _BlobCodec();
@@ -57,10 +59,10 @@ final class WebSocketClient$JS extends WebSocketClientBase {
5759
StreamSubscription<Object?>? _dataBindSubscription;
5860

5961
/// Binding to error from native WebSocket client.
60-
StreamSubscription<html.Event>? _errorBindSubscription;
62+
StreamSubscription<web.Event>? _errorBindSubscription;
6163

6264
/// Binding to close event from native WebSocket client.
63-
StreamSubscription<html.CloseEvent>? _closeBindSubscription;
65+
StreamSubscription<web.CloseEvent>? _closeBindSubscription;
6466

6567
/// Ready state of the WebSocket client.
6668
@override
@@ -75,31 +77,33 @@ final class WebSocketClient$JS extends WebSocketClientBase {
7577
@override
7678
void push(Object data) {
7779
final client = _client;
78-
if (client == null || client.readyState != html.WebSocket.OPEN) {
80+
if (client == null || client.readyState != web.WebSocket.OPEN) {
7981
throw const WSClientClosedException(
8082
message: 'WebSocket client is not connected.');
8183
}
8284
try {
83-
switch (data) {
84-
case String text:
85-
client.sendString(text);
86-
case html.Blob blob:
87-
client.sendBlob(blob);
88-
default:
89-
if (_options?.useBlobForBinary == true) {
90-
client.sendBlob(_blobCodec.write(data));
91-
} else {
92-
switch (data) {
93-
case TypedData td:
94-
client.sendTypedData(td);
95-
case ByteBuffer bb:
96-
client.sendByteBuffer(bb);
97-
case List<int> bytes:
98-
client.sendTypedData(Uint8List.fromList(bytes));
99-
default:
100-
throw ArgumentError.value(data, 'data', 'Invalid data type.');
101-
}
102-
}
85+
if (data is String) {
86+
client.send(data.toJS);
87+
return;
88+
} else if (_options?.useBlobForBinary == true) {
89+
client.send(_blobCodec.write(data));
90+
} else {
91+
switch (data) {
92+
case TypedData td:
93+
client.send(Uint8List.view(
94+
td.buffer,
95+
td.offsetInBytes,
96+
td.lengthInBytes,
97+
).toJS);
98+
case ByteBuffer bb:
99+
client.send(bb.toJS);
100+
case List<int> bytes:
101+
client.send(Uint8List.fromList(bytes).toJS);
102+
case web.Blob blob:
103+
client.send(web.Blob([blob].toJS));
104+
default:
105+
throw ArgumentError.value(data, 'data', 'Invalid data type.');
106+
}
103107
}
104108
} on Object catch (error, stackTrace) {
105109
warning(error, stackTrace, 'WebSocketClient\$JS.add: $error');
@@ -113,7 +117,10 @@ final class WebSocketClient$JS extends WebSocketClientBase {
113117
try {
114118
if (_client != null) await disconnect(1001, 'RECONNECTING');
115119
super.connect(url);
116-
final client = _client = html.WebSocket(url, protocols);
120+
final client = _client = web.WebSocket(
121+
url,
122+
protocols?.map((e) => e.toJS).toList().toJS ?? <js.JSString>[].toJS,
123+
);
117124
final completer = Completer<void>();
118125
client.onOpen.first.whenComplete(() {
119126
if (completer.isCompleted) return;
@@ -135,7 +142,7 @@ final class WebSocketClient$JS extends WebSocketClientBase {
135142
.map<Object?>((event) => event.data)
136143
.asyncMap<Object?>((data) => switch (data) {
137144
String text => text,
138-
html.Blob blob => _blobCodec.read(blob),
145+
web.Blob blob => _blobCodec.read(blob),
139146
TypedData td => Uint8List.view(
140147
td.buffer,
141148
td.offsetInBytes,
@@ -187,7 +194,11 @@ final class WebSocketClient$JS extends WebSocketClientBase {
187194
_dataBindSubscription = null;
188195
if (client != null) {
189196
try {
190-
client.close(code, reason);
197+
if (code != null && reason != null) {
198+
client.close(code, reason);
199+
} else {
200+
client.close();
201+
}
191202
} on Object {/* ignore */} // coverage:ignore-line
192203
_client = null;
193204
}
@@ -206,61 +217,33 @@ final class _BlobCodec {
206217
_BlobCodec();
207218

208219
@internal
209-
html.Blob write(Object data) {
220+
web.Blob write(Object data) {
210221
switch (data) {
211222
case String text:
212-
return html.Blob([Uint8List.fromList(utf8.encode(text))]);
223+
return web.Blob([Uint8List.fromList(utf8.encode(text)).toJS].toJS);
213224
case TypedData td:
214-
return html.Blob([
225+
return web.Blob([
215226
Uint8List.view(
216227
td.buffer,
217228
td.offsetInBytes,
218229
td.lengthInBytes,
219-
)
220-
]);
230+
).toJS
231+
].toJS);
221232
case ByteBuffer bb:
222-
return html.Blob([bb.asUint8List()]);
233+
return web.Blob([bb.asUint8List().toJS].toJS);
223234
case List<int> bytes:
224-
return html.Blob([Uint8List.fromList(bytes)]);
235+
return web.Blob([Uint8List.fromList(bytes).toJS].toJS);
236+
case web.Blob blob:
237+
return web.Blob([blob].toJS);
225238
default:
226239
throw ArgumentError.value(data, 'data', 'Invalid data type.');
227240
}
228241
}
229242

230243
@internal
231-
FutureOr<Object> read(html.Blob blob) async {
232-
final completer = Completer<Object>();
233-
234-
void complete(Object data) {
235-
if (completer.isCompleted) return;
236-
completer.complete(data);
237-
}
238-
239-
void completeError(Object error, [StackTrace? stackTrace]) {
240-
if (completer.isCompleted) return;
241-
completer.completeError(error, stackTrace);
242-
}
243-
244-
late final html.FileReader reader;
245-
reader = html.FileReader()
246-
..onLoadEnd.listen((_) {
247-
final result = reader.result;
248-
switch (result) {
249-
case String text:
250-
complete(text);
251-
break;
252-
case Uint8List bytes:
253-
complete(bytes);
254-
break;
255-
case ByteBuffer bb:
256-
complete(bb.asUint8List());
257-
break;
258-
default:
259-
completeError('Unexpected result type: ${result.runtimeType}');
260-
}
261-
})
262-
..onError.listen(completeError)
263-
..readAsArrayBuffer(blob);
264-
return completer.future;
244+
Future<Object> read(web.Blob blob) async {
245+
final arrayBuffer = await blob.arrayBuffer().toDart;
246+
final bytes = arrayBuffer.toDart.asUint8List();
247+
return bytes;
265248
}
266249
}

pubspec.yaml

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: ws
33
description: >
44
WS: A compact, highly efficient WebSocket library. Easily establish, manage, and reconnect WebSocket connections in real-time apps.
55
6-
version: 1.0.0
6+
version: 1.1.0-dev.1
77

88
homepage: https://github.com/plugfox/ws
99

@@ -39,8 +39,9 @@ environment:
3939
sdk: '>=3.1.0 <4.0.0'
4040

4141
dependencies:
42+
web: ^0.5.1
4243
meta: ^1.9.1
4344

4445
dev_dependencies:
45-
lints: ^3.0.0
46-
test: ^1.24.2
46+
lints: ^4.0.0
47+
test: ^1.25.7

server/lib/src/util/run_server.dart

-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ Future<void> runServer<Config>({
8686
(message) => ports.forEach((port) => port.send(message)),
8787
cancelOnError: false,
8888
); */
89-
// TODO(plugfox): Health checks
9089
l.s(
9190
'Started ${parsedArguments.isolates} server(s) '
9291
'at http://${parsedArguments.address.address}:${parsedArguments.port} '

test/client/client_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ void main() {
336336
client.add(binaryData);
337337
final received =
338338
await client.stream.first.timeout(const Duration(seconds: 5));
339+
if (received is String) throw Exception('Received is String');
339340
expect(
340341
received,
341342
isA<List<int>>()
@@ -443,6 +444,7 @@ void main() {
443444
client.add(binaryData);
444445
final received =
445446
await client.stream.first.timeout(const Duration(seconds: 5));
447+
if (received is String) throw Exception('Received is String');
446448
expect(
447449
received,
448450
isA<List<int>>()

0 commit comments

Comments
 (0)