1
1
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2
2
import { primordials } from "ext:core/mod.js" ;
3
- import { getLocationHref } from "ext:deno_web/12_location.js" ;
4
3
import * as webidl from "ext:deno_webidl/00_webidl.js" ;
5
4
import {
6
5
connectQuic ,
7
6
webtransportAccept ,
8
7
webtransportConnect ,
9
8
} from "ext:deno_net/03_quic.js" ;
9
+ import { assert } from "./00_infra.js" ;
10
+ import { DOMException } from "./01_dom_exception.js" ;
10
11
import {
11
12
getReadableStreamResourceBacking ,
12
13
getWritableStreamResourceBacking ,
@@ -16,7 +17,7 @@ import {
16
17
WritableStreamDefaultWriter ,
17
18
writableStreamForRid ,
18
19
} from "./06_streams.js" ;
19
- import { assert } from "./00_infra .js" ;
20
+ import { getLocationHref } from "./12_location .js" ;
20
21
21
22
const {
22
23
ArrayBufferPrototype,
@@ -97,6 +98,7 @@ const illegalConstructorKey = Symbol("illegalConstructorKey");
97
98
class WebTransport {
98
99
[ webidl . brand ] = webidl . brand ;
99
100
#conn;
101
+ #promise;
100
102
#ready;
101
103
// deno-lint-ignore prefer-primordials
102
104
#closed = Promise . withResolvers ( ) ;
@@ -199,12 +201,14 @@ class WebTransport {
199
201
} ,
200
202
) ;
201
203
204
+ this . #promise = promise ;
202
205
this . #datagrams = new WebTransportDatagramDuplexStream (
203
206
illegalConstructorKey ,
204
207
promise ,
205
208
) ;
206
-
207
- this . #ready = PromisePrototypeThen ( promise , ( ) => undefined ) ;
209
+ this . #ready = PromisePrototypeThen ( promise , ( ) => undefined , ( e ) => {
210
+ throw new WebTransportError ( e . message ) ;
211
+ } ) ;
208
212
}
209
213
210
214
getStats ( ) {
@@ -261,6 +265,11 @@ class WebTransport {
261
265
"Failed to execute 'close' on 'WebTransport'" ,
262
266
"Argument 1" ,
263
267
) ;
268
+ if ( ! this . #conn) {
269
+ throw new WebTransportError ( "WebTransport is not connected" , {
270
+ source : "session" ,
271
+ } ) ;
272
+ }
264
273
this . #conn. close ( {
265
274
closeCode : closeInfo . closeCode ,
266
275
reason : closeInfo . reason ,
@@ -280,7 +289,8 @@ class WebTransport {
280
289
"Argument 1" ,
281
290
) ;
282
291
283
- const bidi = await this . #conn. createBidirectionalStream ( {
292
+ const { conn } = await this . #promise;
293
+ const bidi = await conn . createBidirectionalStream ( {
284
294
waitUntilAvailable : options . waitUntilAvailable ,
285
295
} ) ;
286
296
@@ -303,28 +313,34 @@ class WebTransport {
303
313
304
314
get incomingBidirectionalStreams ( ) {
305
315
webidl . assertBranded ( this , WebTransportPrototype ) ;
306
-
307
316
if ( ! this . #incomingBidirectionalStreams) {
308
- this . #incomingBidirectionalStreams = this . #conn
309
- . incomingBidirectionalStreams . pipeThrough (
310
- new TransformStream ( {
311
- transform : async ( bidi , controller ) => {
312
- const reader = bidi . readable . getReader ( { mode : "byob" } ) ;
313
- const { value } = await reader . read (
314
- new Uint8Array ( this . #headerBi. length ) ,
317
+ const readerPromise = PromisePrototypeThen (
318
+ this . #promise,
319
+ ( { conn } ) => conn . incomingBidirectionalStreams . getReader ( ) ,
320
+ ) ;
321
+ this . #incomingBidirectionalStreams = new ReadableStream ( {
322
+ pull : async ( controller ) => {
323
+ const reader = await readerPromise ;
324
+ const { value : bidi , done } = await reader . read ( ) ;
325
+ if ( done ) {
326
+ controller . close ( ) ;
327
+ } else {
328
+ const reader = bidi . readable . getReader ( { mode : "byob" } ) ;
329
+ const { value } = await reader . read (
330
+ new Uint8Array ( this . #headerBi. length ) ,
331
+ ) ;
332
+ reader . releaseLock ( ) ;
333
+ if ( value && equal ( value , this . #headerBi) ) {
334
+ controller . enqueue (
335
+ new WebTransportBidirectionalStream (
336
+ illegalConstructorKey ,
337
+ bidi ,
338
+ ) ,
315
339
) ;
316
- reader . releaseLock ( ) ;
317
- if ( value && equal ( value , this . #headerBi) ) {
318
- controller . enqueue (
319
- new WebTransportBidirectionalStream (
320
- illegalConstructorKey ,
321
- bidi ,
322
- ) ,
323
- ) ;
324
- }
325
- } ,
326
- } ) ,
327
- ) ;
340
+ }
341
+ }
342
+ } ,
343
+ } ) ;
328
344
}
329
345
return this . #incomingBidirectionalStreams;
330
346
}
@@ -337,7 +353,8 @@ class WebTransport {
337
353
"Argument 1" ,
338
354
) ;
339
355
340
- const stream = await this . #conn. createUnidirectionalStream ( {
356
+ const { conn } = await this . #promise;
357
+ const stream = await conn . createUnidirectionalStream ( {
341
358
waitUntilAvailable : options . waitUntilAvailable ,
342
359
} ) ;
343
360
@@ -359,24 +376,32 @@ class WebTransport {
359
376
webidl . assertBranded ( this , WebTransportPrototype ) ;
360
377
361
378
if ( ! this . #incomingUnidirectionalStreams) {
362
- this . #incomingUnidirectionalStreams = this . #conn
363
- . incomingUnidirectionalStreams . pipeThrough (
364
- new TransformStream ( {
365
- transform : async ( stream , controller ) => {
366
- const reader = stream . getReader ( { mode : "byob" } ) ;
367
- const { value } = await reader . read (
368
- new Uint8Array ( this . #headerUni. length ) ,
379
+ const readerPromise = PromisePrototypeThen (
380
+ this . #promise,
381
+ ( { conn } ) => conn . incomingUnidirectionalStreams . getReader ( ) ,
382
+ ) ;
383
+ this . #incomingUnidirectionalStreams = new ReadableStream ( {
384
+ pull : async ( controller ) => {
385
+ const reader = await readerPromise ;
386
+ const { value : stream , done } = await reader . read ( ) ;
387
+ if ( done ) {
388
+ controller . close ( ) ;
389
+ } else {
390
+ const reader = stream . getReader ( { mode : "byob" } ) ;
391
+ const { value } = await reader . read (
392
+ new Uint8Array ( this . #headerUni. length ) ,
393
+ ) ;
394
+ reader . releaseLock ( ) ;
395
+ if ( value && equal ( value , this . #headerUni) ) {
396
+ controller . enqueue (
397
+ readableStream ( stream ) ,
369
398
) ;
370
- reader . releaseLock ( ) ;
371
- if ( value && equal ( value , this . #headerUni) ) {
372
- controller . enqueue (
373
- readableStream ( stream ) ,
374
- ) ;
375
- }
376
- } ,
377
- } ) ,
378
- ) ;
399
+ }
400
+ }
401
+ } ,
402
+ } ) ;
379
403
}
404
+
380
405
return this . #incomingUnidirectionalStreams;
381
406
}
382
407
@@ -390,7 +415,7 @@ class WebTransport {
390
415
return false ;
391
416
}
392
417
}
393
-
418
+ webidl . configureInterface ( WebTransport ) ;
394
419
const WebTransportPrototype = WebTransport . prototype ;
395
420
396
421
async function upgradeWebTransport ( conn ) {
@@ -456,7 +481,7 @@ class WebTransportBidirectionalStream {
456
481
return this . #writable;
457
482
}
458
483
}
459
-
484
+ webidl . configureInterface ( WebTransportBidirectionalStream ) ;
460
485
const WebTransportBidirectionalStreamPrototype =
461
486
WebTransportBidirectionalStream . prototype ;
462
487
@@ -515,7 +540,7 @@ class WebTransportSendStream extends WritableStream {
515
540
return new WebTransportWriter ( this ) ;
516
541
}
517
542
}
518
-
543
+ webidl . configureInterface ( WebTransportSendStream ) ;
519
544
const WebTransportSendStreamPrototype = WebTransportSendStream . prototype ;
520
545
521
546
class WebTransportReceiveStream extends ReadableStream {
@@ -538,14 +563,15 @@ class WebTransportReceiveStream extends ReadableStream {
538
563
} ) ;
539
564
}
540
565
}
541
-
566
+ webidl . configureInterface ( WebTransportReceiveStream ) ;
542
567
const WebTransportReceiveStreamPrototype = WebTransportReceiveStream . prototype ;
543
568
544
569
class WebTransportWriter extends WritableStreamDefaultWriter {
545
570
[ webidl . brand ] = webidl . brand ;
546
571
547
572
// atomicWrite() {}
548
573
}
574
+ webidl . configureInterface ( WebTransportWriter ) ;
549
575
550
576
class WebTransportDatagramDuplexStream {
551
577
[ webidl . brand ] = webidl . brand ;
@@ -807,7 +833,7 @@ class WebTransportDatagramDuplexStream {
807
833
return this . #writable;
808
834
}
809
835
}
810
-
836
+ webidl . configureInterface ( WebTransportDatagramDuplexStream ) ;
811
837
const WebTransportDatagramDuplexStreamPrototype =
812
838
WebTransportDatagramDuplexStream . prototype ;
813
839
@@ -827,9 +853,40 @@ class WebTransportSendGroup {
827
853
} ) ;
828
854
}
829
855
}
830
-
856
+ webidl . configureInterface ( WebTransportSendGroup ) ;
831
857
const WebTransportSendGroupPrototype = WebTransportSendGroup . prototype ;
832
858
859
+ class WebTransportError extends DOMException {
860
+ #source;
861
+ #streamErrorCode;
862
+
863
+ constructor ( message = "" , init = { __proto__ : null } ) {
864
+ super ( message , "WebTransportError" ) ;
865
+ this [ webidl . brand ] = webidl . brand ;
866
+
867
+ init = webidl . converters [ "WebTransportErrorOptions" ] (
868
+ init ,
869
+ "Failed to construct 'WebTransportError'" ,
870
+ "Argument 2" ,
871
+ ) ;
872
+
873
+ this . #source = init . source ;
874
+ this . #streamErrorCode = init . streamErrorCode ;
875
+ }
876
+
877
+ get source ( ) {
878
+ webidl . assertBranded ( this , WebTransportErrorPrototype ) ;
879
+ return this . #source;
880
+ }
881
+
882
+ get streamErrorCode ( ) {
883
+ webidl . assertBranded ( this , WebTransportErrorPrototype ) ;
884
+ return this . #streamErrorCode;
885
+ }
886
+ }
887
+ webidl . configureInterface ( WebTransportError ) ;
888
+ const WebTransportErrorPrototype = WebTransportError . prototype ;
889
+
833
890
webidl . converters . WebTransportSendGroup = webidl . createInterfaceConverter (
834
891
"WebTransportSendGroup" ,
835
892
WebTransportSendGroupPrototype ,
@@ -933,11 +990,33 @@ webidl.converters.WebTransportOptions = webidl
933
990
} ,
934
991
] ) ;
935
992
993
+ webidl . converters . WebTransportErrorSource = webidl . createEnumConverter (
994
+ "WebTransportErrorSource" ,
995
+ [ "stream" , "session" ] ,
996
+ ) ;
997
+
998
+ webidl . converters . WebTransportErrorOptions = webidl . createDictionaryConverter (
999
+ "WebTransportErrorOptions" ,
1000
+ [
1001
+ {
1002
+ key : "source" ,
1003
+ converter : webidl . converters . WebTransportErrorSource ,
1004
+ defaultValue : "stream" ,
1005
+ } ,
1006
+ {
1007
+ key : "streamErrorCode" ,
1008
+ converter : webidl . converters [ "unsigned long?" ] ,
1009
+ defaultValue : null ,
1010
+ } ,
1011
+ ] ,
1012
+ ) ;
1013
+
936
1014
export {
937
1015
upgradeWebTransport ,
938
1016
WebTransport ,
939
1017
WebTransportBidirectionalStream ,
940
1018
WebTransportDatagramDuplexStream ,
1019
+ WebTransportError ,
941
1020
WebTransportReceiveStream ,
942
1021
WebTransportSendGroup ,
943
1022
WebTransportSendStream ,
0 commit comments