2
2
// coverage:ignore-file
3
3
import 'dart:async' ;
4
4
import 'dart:convert' ;
5
- import 'dart:html ' as html show WebSocket, Blob, Event, CloseEvent, FileReader ;
5
+ import 'dart:js_interop ' as js ;
6
6
import 'dart:typed_data' ;
7
7
8
8
import 'package:meta/meta.dart' ;
9
+ import 'package:web/web.dart' as web
10
+ show Blob, CloseEvent, Event, WebSocket, WebSocketEvents;
9
11
import 'package:ws/src/client/web_socket_ready_state.dart' ;
10
12
import 'package:ws/src/client/websocket_exception.dart' ;
11
13
import 'package:ws/src/client/ws_client_base.dart' ;
@@ -47,7 +49,7 @@ final class WebSocketClient$JS extends WebSocketClientBase {
47
49
final $WebSocketOptions$JS ? _options;
48
50
49
51
/// Native WebSocket client.
50
- html .WebSocket ? _client;
52
+ web .WebSocket ? _client;
51
53
52
54
/// Blob codec for `Blob <-> List<int>` conversion.
53
55
late final _BlobCodec _blobCodec = _BlobCodec ();
@@ -57,10 +59,10 @@ final class WebSocketClient$JS extends WebSocketClientBase {
57
59
StreamSubscription <Object ?>? _dataBindSubscription;
58
60
59
61
/// Binding to error from native WebSocket client.
60
- StreamSubscription <html .Event >? _errorBindSubscription;
62
+ StreamSubscription <web .Event >? _errorBindSubscription;
61
63
62
64
/// Binding to close event from native WebSocket client.
63
- StreamSubscription <html .CloseEvent >? _closeBindSubscription;
65
+ StreamSubscription <web .CloseEvent >? _closeBindSubscription;
64
66
65
67
/// Ready state of the WebSocket client.
66
68
@override
@@ -75,31 +77,33 @@ final class WebSocketClient$JS extends WebSocketClientBase {
75
77
@override
76
78
void push (Object data) {
77
79
final client = _client;
78
- if (client == null || client.readyState != html .WebSocket .OPEN ) {
80
+ if (client == null || client.readyState != web .WebSocket .OPEN ) {
79
81
throw const WSClientClosedException (
80
82
message: 'WebSocket client is not connected.' );
81
83
}
82
84
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
+ }
103
107
}
104
108
} on Object catch (error, stackTrace) {
105
109
warning (error, stackTrace, 'WebSocketClient\$ JS.add: $error ' );
@@ -113,7 +117,10 @@ final class WebSocketClient$JS extends WebSocketClientBase {
113
117
try {
114
118
if (_client != null ) await disconnect (1001 , 'RECONNECTING' );
115
119
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
+ );
117
124
final completer = Completer <void >();
118
125
client.onOpen.first.whenComplete (() {
119
126
if (completer.isCompleted) return ;
@@ -135,7 +142,7 @@ final class WebSocketClient$JS extends WebSocketClientBase {
135
142
.map <Object ?>((event) => event.data)
136
143
.asyncMap <Object ?>((data) => switch (data) {
137
144
String text => text,
138
- html .Blob blob => _blobCodec.read (blob),
145
+ web .Blob blob => _blobCodec.read (blob),
139
146
TypedData td => Uint8List .view (
140
147
td.buffer,
141
148
td.offsetInBytes,
@@ -187,7 +194,11 @@ final class WebSocketClient$JS extends WebSocketClientBase {
187
194
_dataBindSubscription = null ;
188
195
if (client != null ) {
189
196
try {
190
- client.close (code, reason);
197
+ if (code != null && reason != null ) {
198
+ client.close (code, reason);
199
+ } else {
200
+ client.close ();
201
+ }
191
202
} on Object {/* ignore */ } // coverage:ignore-line
192
203
_client = null ;
193
204
}
@@ -206,61 +217,33 @@ final class _BlobCodec {
206
217
_BlobCodec ();
207
218
208
219
@internal
209
- html .Blob write (Object data) {
220
+ web .Blob write (Object data) {
210
221
switch (data) {
211
222
case String text:
212
- return html .Blob ([Uint8List .fromList (utf8.encode (text))] );
223
+ return web .Blob ([Uint8List .fromList (utf8.encode (text)).toJS].toJS );
213
224
case TypedData td:
214
- return html .Blob ([
225
+ return web .Blob ([
215
226
Uint8List .view (
216
227
td.buffer,
217
228
td.offsetInBytes,
218
229
td.lengthInBytes,
219
- )
220
- ]);
230
+ ).toJS
231
+ ].toJS );
221
232
case ByteBuffer bb:
222
- return html .Blob ([bb.asUint8List ()] );
233
+ return web .Blob ([bb.asUint8List ().toJS].toJS );
223
234
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);
225
238
default :
226
239
throw ArgumentError .value (data, 'data' , 'Invalid data type.' );
227
240
}
228
241
}
229
242
230
243
@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;
265
248
}
266
249
}
0 commit comments