@fails-components/webtransport 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/old_test/echoserver.js +1 -1
- package/old_test/test.js +1 -1
- package/package.json +10 -25
- package/readme.md +2 -2
- package/test/bidirectional-streams.spec.js +0 -150
- package/test/datagrams.spec.js +0 -104
- package/test/fixtures/certificate.js +0 -456
- package/test/fixtures/chai.js +0 -8
- package/test/fixtures/known-bytes.js +0 -44
- package/test/fixtures/p-timeout.js +0 -33
- package/test/fixtures/quiche.browser.js +0 -2
- package/test/fixtures/quiche.js +0 -1
- package/test/fixtures/read-cert-hash.js +0 -7
- package/test/fixtures/read-stream.js +0 -57
- package/test/fixtures/reader-value.js +0 -51
- package/test/fixtures/server.js +0 -467
- package/test/fixtures/webtransport.browser.js +0 -19
- package/test/fixtures/webtransport.js +0 -3
- package/test/fixtures/write-stream.js +0 -24
- package/test/index.js +0 -124
- package/test/pw-no-https-errors.json +0 -5
- package/test/session.spec.js +0 -199
- package/test/stream-limits.spec.js +0 -259
- package/test/unidirectional-streams.spec.js +0 -133
package/test/fixtures/server.js
DELETED
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
import { generateWebTransportCertificate } from './certificate.js'
|
|
2
|
-
import { Http2Server, Http3Server } from '../../lib/index.node.js'
|
|
3
|
-
import { pTimeout } from './p-timeout.js'
|
|
4
|
-
import { getReaderStream, getReaderValue } from './reader-value.js'
|
|
5
|
-
import { writeStream } from './write-stream.js'
|
|
6
|
-
import { readStream } from './read-stream.js'
|
|
7
|
-
import * as ui8 from 'uint8arrays'
|
|
8
|
-
import { KNOWN_BYTES, KNOWN_BYTES_LENGTH } from './known-bytes.js'
|
|
9
|
-
|
|
10
|
-
export async function createServer() {
|
|
11
|
-
const attrs = [
|
|
12
|
-
{ shortName: 'C', value: 'DE' },
|
|
13
|
-
{ shortName: 'ST', value: 'Berlin' },
|
|
14
|
-
{ shortName: 'L', value: 'Berlin' },
|
|
15
|
-
{ shortName: 'O', value: 'WebTransport Test Server' },
|
|
16
|
-
{ shortName: 'CN', value: '127.0.0.1' }
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
const certificate = await generateWebTransportCertificate(attrs, {
|
|
20
|
-
days: 13
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
if (certificate == null) {
|
|
24
|
-
throw new Error('Certificate generation failed')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** @type {Http2Server|Http3Server} */
|
|
28
|
-
let server
|
|
29
|
-
if (process.env.USE_HTTP2 === 'true') {
|
|
30
|
-
server = new Http2Server({
|
|
31
|
-
/* port: 8080,
|
|
32
|
-
host: '0.0.0.0', */
|
|
33
|
-
port: 0,
|
|
34
|
-
host: '127.0.0.1',
|
|
35
|
-
secret: 'mysecret',
|
|
36
|
-
cert: certificate.cert, // unclear if it is the correct format
|
|
37
|
-
privKey: certificate.private
|
|
38
|
-
})
|
|
39
|
-
} else {
|
|
40
|
-
server = new Http3Server({
|
|
41
|
-
/* port: 8080,
|
|
42
|
-
host: '0.0.0.0', */
|
|
43
|
-
port: 0,
|
|
44
|
-
host: '127.0.0.1',
|
|
45
|
-
secret: 'mysecret',
|
|
46
|
-
cert: certificate.cert, // unclear if it is the correct format
|
|
47
|
-
privKey: certificate.private
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let adjustlimit = 1
|
|
52
|
-
if (process.env.USE_HTTP2 === 'true') {
|
|
53
|
-
adjustlimit = 0
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
server.ready
|
|
57
|
-
.then(async () => {
|
|
58
|
-
server.setRequestCallback(async (args) => {
|
|
59
|
-
const url = args.header[':path']
|
|
60
|
-
const [path] = url.split('?')
|
|
61
|
-
|
|
62
|
-
if (server.sessionController[path] == null) {
|
|
63
|
-
return {
|
|
64
|
-
...args,
|
|
65
|
-
path,
|
|
66
|
-
status: 404
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
...args,
|
|
72
|
-
path,
|
|
73
|
-
userData: {
|
|
74
|
-
search: url.substring(path.length)
|
|
75
|
-
},
|
|
76
|
-
header: {
|
|
77
|
-
...args.header,
|
|
78
|
-
':path': path
|
|
79
|
-
},
|
|
80
|
-
status: 200
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
// set up listeners for the different server paths used by the tests
|
|
85
|
-
console.log('server ready')
|
|
86
|
-
await Promise.all(
|
|
87
|
-
[
|
|
88
|
-
// echo server, initiated by remote
|
|
89
|
-
async () => {
|
|
90
|
-
for await (const session of getReaderStream(
|
|
91
|
-
server.sessionStream('/bidirectional_client_initiated_echo')
|
|
92
|
-
)) {
|
|
93
|
-
try {
|
|
94
|
-
const bidiStream = await getReaderValue(
|
|
95
|
-
session.incomingBidirectionalStreams
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
// redirect input to output
|
|
99
|
-
await bidiStream.readable.pipeTo(bidiStream.writable)
|
|
100
|
-
} catch {
|
|
101
|
-
// in some tests the client closes the stream
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
// echo server, initiated by local
|
|
107
|
-
async () => {
|
|
108
|
-
for await (const session of getReaderStream(
|
|
109
|
-
server.sessionStream('/bidirectional_server_initiated_echo')
|
|
110
|
-
)) {
|
|
111
|
-
try {
|
|
112
|
-
const stream = await session.createBidirectionalStream()
|
|
113
|
-
|
|
114
|
-
await writeStream(stream.writable, KNOWN_BYTES)
|
|
115
|
-
|
|
116
|
-
const received = await readStream(
|
|
117
|
-
stream.readable,
|
|
118
|
-
KNOWN_BYTES_LENGTH
|
|
119
|
-
)
|
|
120
|
-
// await stream.readable.cancel() // cancel so that the client can progress
|
|
121
|
-
|
|
122
|
-
// if we did not get the data we sent, close the session with a reason
|
|
123
|
-
if (
|
|
124
|
-
!ui8.equals(ui8.concat(KNOWN_BYTES), ui8.concat(received))
|
|
125
|
-
) {
|
|
126
|
-
session.close({
|
|
127
|
-
closeCode: 500,
|
|
128
|
-
reason: 'data did not match'
|
|
129
|
-
})
|
|
130
|
-
} else {
|
|
131
|
-
session.close()
|
|
132
|
-
}
|
|
133
|
-
} catch {
|
|
134
|
-
// in some tests the client closes the stream
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
// echo server, initiated by local
|
|
140
|
-
async () => {
|
|
141
|
-
for await (const session of getReaderStream(
|
|
142
|
-
server.sessionStream('/bidirectional_server_fin_send')
|
|
143
|
-
)) {
|
|
144
|
-
try {
|
|
145
|
-
// adapted from issue of achingbrain
|
|
146
|
-
const stream = await session.createBidirectionalStream()
|
|
147
|
-
|
|
148
|
-
const writer = stream.writable.getWriter()
|
|
149
|
-
|
|
150
|
-
await writer.ready
|
|
151
|
-
|
|
152
|
-
writer.write(Uint8Array.from([0, 1, 2, 3])).catch((err) => {
|
|
153
|
-
console.info('error writing to stream', err)
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
await writer.close()
|
|
157
|
-
} catch {
|
|
158
|
-
// in some tests the client closes the stream
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
// echo datagrams, initiated by remote
|
|
164
|
-
async () => {
|
|
165
|
-
for await (const session of getReaderStream(
|
|
166
|
-
server.sessionStream('/datagrams_client_send')
|
|
167
|
-
)) {
|
|
168
|
-
// datagram transport is unreliable, at least one message should make it through
|
|
169
|
-
const expected = 1
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
const received = await pTimeout(
|
|
173
|
-
readStream(session.datagrams.readable, expected),
|
|
174
|
-
1000
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
// if we did not get the data we sent, close the session with a reason
|
|
178
|
-
if (received.length !== expected) {
|
|
179
|
-
throw new Error('Did not receive enough bytes')
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
session.close()
|
|
183
|
-
} catch (/** @type {any} */ err) {
|
|
184
|
-
session.close({
|
|
185
|
-
closeCode: 500,
|
|
186
|
-
reason: err.message
|
|
187
|
-
})
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
// echo datagrams, initiated by local
|
|
193
|
-
async () => {
|
|
194
|
-
for await (const session of getReaderStream(
|
|
195
|
-
server.sessionStream('/datagrams_server_send')
|
|
196
|
-
)) {
|
|
197
|
-
const writer = session.datagrams.writable.getWriter()
|
|
198
|
-
let closed = false
|
|
199
|
-
|
|
200
|
-
// write datagrams until the client receives one and closes the connection
|
|
201
|
-
// eslint-disable-next-line promise/catch-or-return
|
|
202
|
-
Promise.resolve().then(async () => {
|
|
203
|
-
while (!closed) {
|
|
204
|
-
try {
|
|
205
|
-
await writer.ready
|
|
206
|
-
await writer.write(Uint8Array.from([0, 1, 2, 3, 4]))
|
|
207
|
-
await new Promise((resolve) => setTimeout(resolve, 1)) // do not flood everything
|
|
208
|
-
} catch {
|
|
209
|
-
// the session can be closed while we are writing
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
await session.closed
|
|
215
|
-
closed = true
|
|
216
|
-
}
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
// receive 100+ bidi streams and block
|
|
220
|
-
async () => {
|
|
221
|
-
for await (const session of getReaderStream(
|
|
222
|
-
server.sessionStream('/streamlimits_getbidis_wua')
|
|
223
|
-
)) {
|
|
224
|
-
try {
|
|
225
|
-
await session.ready
|
|
226
|
-
const bidistreams = []
|
|
227
|
-
while (bidistreams.length < 100 - adjustlimit) {
|
|
228
|
-
bidistreams.push(
|
|
229
|
-
await getReaderValue(session.incomingBidirectionalStreams)
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
await getReaderValue(session.incomingUnidirectionalStreams)
|
|
233
|
-
await getReaderValue(session.incomingUnidirectionalStreams)
|
|
234
|
-
for (let i = 0; i < 50 + adjustlimit; i++) {
|
|
235
|
-
/* const curstream = */ bidistreams.shift()
|
|
236
|
-
// await curstream.writable.close() // canceled by client
|
|
237
|
-
}
|
|
238
|
-
while (bidistreams.length < 100 - adjustlimit) {
|
|
239
|
-
bidistreams.push(
|
|
240
|
-
await getReaderValue(session.incomingBidirectionalStreams)
|
|
241
|
-
)
|
|
242
|
-
}
|
|
243
|
-
await getReaderValue(session.incomingUnidirectionalStreams)
|
|
244
|
-
await session.close()
|
|
245
|
-
// eslint-disable-next-line no-unused-vars
|
|
246
|
-
} catch (error) {
|
|
247
|
-
// do not crash server, if a problem occurs...
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
// receive 100+ bidi streams and do not block
|
|
252
|
-
async () => {
|
|
253
|
-
for await (const session of getReaderStream(
|
|
254
|
-
server.sessionStream('/streamlimits_getbidis')
|
|
255
|
-
)) {
|
|
256
|
-
try {
|
|
257
|
-
await session.ready
|
|
258
|
-
const bidistreams = []
|
|
259
|
-
while (bidistreams.length < 150) {
|
|
260
|
-
bidistreams.push(
|
|
261
|
-
await getReaderValue(session.incomingBidirectionalStreams)
|
|
262
|
-
)
|
|
263
|
-
}
|
|
264
|
-
await session.close()
|
|
265
|
-
// eslint-disable-next-line no-unused-vars
|
|
266
|
-
} catch (error) {
|
|
267
|
-
// do not crash server, if a problem occurs...
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
async () => {
|
|
272
|
-
for await (const session of getReaderStream(
|
|
273
|
-
server.sessionStream('/streamlimits_getunidis_wua')
|
|
274
|
-
)) {
|
|
275
|
-
try {
|
|
276
|
-
await session.ready
|
|
277
|
-
const unidistreams = []
|
|
278
|
-
while (unidistreams.length < 100 - adjustlimit) {
|
|
279
|
-
unidistreams.push(
|
|
280
|
-
await getReaderValue(session.incomingUnidirectionalStreams)
|
|
281
|
-
)
|
|
282
|
-
}
|
|
283
|
-
await getReaderValue(session.incomingBidirectionalStreams)
|
|
284
|
-
await getReaderValue(session.incomingBidirectionalStreams)
|
|
285
|
-
for (let i = 0; i < 50 + adjustlimit; i++) {
|
|
286
|
-
unidistreams.shift()
|
|
287
|
-
}
|
|
288
|
-
while (unidistreams.length < 100 - adjustlimit) {
|
|
289
|
-
unidistreams.push(
|
|
290
|
-
await getReaderValue(session.incomingUnidirectionalStreams)
|
|
291
|
-
)
|
|
292
|
-
}
|
|
293
|
-
await getReaderValue(session.incomingBidirectionalStreams)
|
|
294
|
-
await session.close()
|
|
295
|
-
// eslint-disable-next-line no-unused-vars
|
|
296
|
-
} catch (error) {
|
|
297
|
-
// do not crash server, if a problem occurs...
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
// receive 100+ unidi streams and do not block
|
|
302
|
-
async () => {
|
|
303
|
-
for await (const session of getReaderStream(
|
|
304
|
-
server.sessionStream('/streamlimits_getunidis')
|
|
305
|
-
)) {
|
|
306
|
-
try {
|
|
307
|
-
await session.ready
|
|
308
|
-
const unidistreams = []
|
|
309
|
-
while (unidistreams.length < 150) {
|
|
310
|
-
unidistreams.push(
|
|
311
|
-
await getReaderValue(session.incomingUnidirectionalStreams)
|
|
312
|
-
)
|
|
313
|
-
}
|
|
314
|
-
await session.close()
|
|
315
|
-
// eslint-disable-next-line no-unused-vars
|
|
316
|
-
} catch (error) {
|
|
317
|
-
// do not crash server, if a problem occurs...
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
},
|
|
321
|
-
// cleanly close remote sessions
|
|
322
|
-
async () => {
|
|
323
|
-
for await (const session of getReaderStream(
|
|
324
|
-
server.sessionStream('/session_close')
|
|
325
|
-
)) {
|
|
326
|
-
await session.close()
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
|
|
330
|
-
// cleanly close remote sessions
|
|
331
|
-
async () => {
|
|
332
|
-
for await (const session of getReaderStream(
|
|
333
|
-
server.sessionStream('/session_close_with_reason')
|
|
334
|
-
)) {
|
|
335
|
-
session.close({
|
|
336
|
-
closeCode: 7,
|
|
337
|
-
reason: 'this is the reason'
|
|
338
|
-
})
|
|
339
|
-
}
|
|
340
|
-
},
|
|
341
|
-
|
|
342
|
-
// support user data
|
|
343
|
-
async () => {
|
|
344
|
-
for await (const session of getReaderStream(
|
|
345
|
-
server.sessionStream('/session_with_userdata')
|
|
346
|
-
)) {
|
|
347
|
-
try {
|
|
348
|
-
const stream = await session.createUnidirectionalStream()
|
|
349
|
-
await writeStream(stream, [
|
|
350
|
-
new TextEncoder().encode(JSON.stringify(session.userData))
|
|
351
|
-
])
|
|
352
|
-
// session.close() // do not close it here, the stream is closed before a reader is attached on client side
|
|
353
|
-
} catch (err) {
|
|
354
|
-
session.close({
|
|
355
|
-
closeCode: 1,
|
|
356
|
-
reason: err.stack
|
|
357
|
-
})
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
// send data over unidirectional stream, initiated by remote
|
|
363
|
-
async () => {
|
|
364
|
-
for await (const session of getReaderStream(
|
|
365
|
-
server.sessionStream('/unidirectional_client_send')
|
|
366
|
-
)) {
|
|
367
|
-
try {
|
|
368
|
-
const stream = await getReaderValue(
|
|
369
|
-
session.incomingUnidirectionalStreams
|
|
370
|
-
)
|
|
371
|
-
const received = await readStream(stream, KNOWN_BYTES_LENGTH)
|
|
372
|
-
// await stream.cancel() // cancel so that the client can progress
|
|
373
|
-
// if we did not get the data we sent, close the session with a reason
|
|
374
|
-
if (
|
|
375
|
-
!ui8.equals(ui8.concat(KNOWN_BYTES), ui8.concat(received))
|
|
376
|
-
) {
|
|
377
|
-
session.close({
|
|
378
|
-
closeCode: 500,
|
|
379
|
-
reason: 'data did not match'
|
|
380
|
-
})
|
|
381
|
-
} else {
|
|
382
|
-
session.close()
|
|
383
|
-
}
|
|
384
|
-
// eslint-disable-next-line no-unused-vars
|
|
385
|
-
} catch (error) {
|
|
386
|
-
// in some tests the client closes the stream
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
|
|
391
|
-
// send data over unidirectional stream, initiated by local
|
|
392
|
-
async () => {
|
|
393
|
-
for await (const session of getReaderStream(
|
|
394
|
-
server.sessionStream('/unidirectional_server_send')
|
|
395
|
-
)) {
|
|
396
|
-
const stream = await session.createUnidirectionalStream()
|
|
397
|
-
|
|
398
|
-
await writeStream(stream, KNOWN_BYTES)
|
|
399
|
-
}
|
|
400
|
-
},
|
|
401
|
-
|
|
402
|
-
// delays reading from stream after client writes
|
|
403
|
-
async () => {
|
|
404
|
-
for await (const session of getReaderStream(
|
|
405
|
-
server.sessionStream('/unidirectional_server_delay_before_read')
|
|
406
|
-
)) {
|
|
407
|
-
const stream = await getReaderValue(
|
|
408
|
-
session.incomingUnidirectionalStreams
|
|
409
|
-
)
|
|
410
|
-
|
|
411
|
-
// wait before we read from the stream, should trigger backpressure
|
|
412
|
-
// on the client
|
|
413
|
-
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
414
|
-
|
|
415
|
-
const received = await readStream(stream, KNOWN_BYTES_LENGTH)
|
|
416
|
-
// await stream.cancel() // cancel so that the client can progress
|
|
417
|
-
|
|
418
|
-
// if we did not get expected data, close the session with a reason
|
|
419
|
-
if (!ui8.equals(ui8.concat(KNOWN_BYTES), ui8.concat(received))) {
|
|
420
|
-
console.log('ERROR', KNOWN_BYTES, received)
|
|
421
|
-
session.close({
|
|
422
|
-
closeCode: 500,
|
|
423
|
-
reason: 'data did not match'
|
|
424
|
-
})
|
|
425
|
-
} else {
|
|
426
|
-
await new Promise((resolve) => setTimeout(resolve, 2000)) // time out is needed, since it can be received before the read is complete
|
|
427
|
-
// and we want the client to close the session after it has processeed the read
|
|
428
|
-
session.close()
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
].map((fn) => fn())
|
|
433
|
-
)
|
|
434
|
-
})
|
|
435
|
-
.catch((/** @type {any} */ err) => {
|
|
436
|
-
console.error('server crashed', err)
|
|
437
|
-
})
|
|
438
|
-
|
|
439
|
-
return {
|
|
440
|
-
server,
|
|
441
|
-
certificate
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
const { server, certificate } = await createServer()
|
|
446
|
-
server.startServer()
|
|
447
|
-
await server.ready
|
|
448
|
-
|
|
449
|
-
const address = server.address()
|
|
450
|
-
|
|
451
|
-
if (address == null) {
|
|
452
|
-
throw new Error('Could not determine server address')
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// tell the calling process how to contact us
|
|
456
|
-
if (process.send)
|
|
457
|
-
process.send({
|
|
458
|
-
address: `https://${address.host}:${address.port}`,
|
|
459
|
-
certificate: certificate.fingerprint
|
|
460
|
-
})
|
|
461
|
-
else {
|
|
462
|
-
console.error('No IPC channel')
|
|
463
|
-
console.log({
|
|
464
|
-
address: `https://${address.host}:${address.port}`,
|
|
465
|
-
certificate: certificate.fingerprint
|
|
466
|
-
})
|
|
467
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
WebTransportPolyfill,
|
|
3
|
-
WebTransportPonyfill
|
|
4
|
-
} from '../../lib/webtransport.browser'
|
|
5
|
-
|
|
6
|
-
/** @type {import('../../lib/dom').WebTransport} */
|
|
7
|
-
// @ts-ignore
|
|
8
|
-
let webtransport = globalThis.WebTransport
|
|
9
|
-
if (process.env.USE_POLYFILL === 'true') {
|
|
10
|
-
// @ts-ignore
|
|
11
|
-
webtransport = WebTransportPolyfill
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (process.env.USE_PONYFILL === 'true') {
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
webtransport = WebTransportPonyfill
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default webtransport
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Write contents to a stream and close it
|
|
3
|
-
*
|
|
4
|
-
* @template T
|
|
5
|
-
* @param {WritableStream<T>} writable
|
|
6
|
-
* @param {T[]} input
|
|
7
|
-
* @returns
|
|
8
|
-
*/
|
|
9
|
-
export async function writeStream(writable, input) {
|
|
10
|
-
const writer = writable.getWriter()
|
|
11
|
-
|
|
12
|
-
for (const buf of input) {
|
|
13
|
-
await writer.ready
|
|
14
|
-
await writer.write(buf)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
await writer.ready
|
|
18
|
-
await writer.releaseLock()
|
|
19
|
-
try {
|
|
20
|
-
await writable.close()
|
|
21
|
-
} catch (error) {
|
|
22
|
-
console.log('Did we get a STOP_SENDING? ignore', error)
|
|
23
|
-
}
|
|
24
|
-
}
|
package/test/index.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { execa } from 'execa'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Run server as separate process so we can kill it without
|
|
5
|
-
* getting stuck waiting for the custom event loop to end.
|
|
6
|
-
*/
|
|
7
|
-
async function startServer() {
|
|
8
|
-
let http2 = false
|
|
9
|
-
if (process.argv[3] === 'http2') http2 = true
|
|
10
|
-
// eslint-disable-next-line no-unused-vars
|
|
11
|
-
return new Promise((resolve, reject) => {
|
|
12
|
-
let foundAddress = false
|
|
13
|
-
|
|
14
|
-
const server = execa('node', ['./test/fixtures/server.js'], {
|
|
15
|
-
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
16
|
-
env: {
|
|
17
|
-
USE_HTTP2: http2 ? 'true' : 'false'
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
server.on('message', (data) => {
|
|
21
|
-
if (!foundAddress) {
|
|
22
|
-
foundAddress = true
|
|
23
|
-
|
|
24
|
-
resolve(data)
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param {string} certificate
|
|
32
|
-
* @param {string} serverAddress
|
|
33
|
-
*/
|
|
34
|
-
async function runTests(certificate, serverAddress) {
|
|
35
|
-
const env = process.argv[2]
|
|
36
|
-
let http2 = false
|
|
37
|
-
if (process.argv[3] === 'http2') http2 = true
|
|
38
|
-
let polyfill = false
|
|
39
|
-
let ponyfill = false
|
|
40
|
-
let slice = 4
|
|
41
|
-
if (process.argv.length > 3 && process.argv[4] === 'polyfill') {
|
|
42
|
-
polyfill = true
|
|
43
|
-
slice++
|
|
44
|
-
if (env === 'node') throw new Error('Polyfill not supported on node')
|
|
45
|
-
}
|
|
46
|
-
if (process.argv.length > 3 && process.argv[4] === 'ponyfill') {
|
|
47
|
-
ponyfill = true
|
|
48
|
-
slice++
|
|
49
|
-
if (env === 'node') throw new Error('Ponyfill not supported on node')
|
|
50
|
-
}
|
|
51
|
-
/** @type {string} */
|
|
52
|
-
let command = ''
|
|
53
|
-
/** @type {string[]} */
|
|
54
|
-
let args = []
|
|
55
|
-
|
|
56
|
-
if (env === 'node') {
|
|
57
|
-
command = 'mocha'
|
|
58
|
-
args = [
|
|
59
|
-
process.env.CI ? '--no-colors' : '--colors',
|
|
60
|
-
'./test/*.spec.js',
|
|
61
|
-
...process.argv.slice(4)
|
|
62
|
-
]
|
|
63
|
-
const tests = execa(command, args, {
|
|
64
|
-
env: {
|
|
65
|
-
DEBUG_COLORS: process.env.CI ? '' : 'true',
|
|
66
|
-
CERT_HASH: certificate,
|
|
67
|
-
SERVER_URL: serverAddress,
|
|
68
|
-
USE_HTTP2: http2 ? 'true' : 'false'
|
|
69
|
-
},
|
|
70
|
-
stdio: ['inherit', 'inherit', 'inherit']
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
await tests
|
|
74
|
-
} else if (env === 'chromium' || env === 'firefox' || env === 'webkit') {
|
|
75
|
-
command = 'playwright-test'
|
|
76
|
-
const otheropts = []
|
|
77
|
-
if (polyfill || ponyfill || env === 'firefox')
|
|
78
|
-
otheropts.push('--config', './test/pw-no-https-errors.json')
|
|
79
|
-
args = [
|
|
80
|
-
'./test/*.spec.js',
|
|
81
|
-
'-b',
|
|
82
|
-
env /* the browser */,
|
|
83
|
-
...otheropts,
|
|
84
|
-
...process.argv.slice(slice)
|
|
85
|
-
]
|
|
86
|
-
const tests = execa(command, args, {
|
|
87
|
-
env: {
|
|
88
|
-
DEBUG_COLORS: process.env.CI ? '' : 'true',
|
|
89
|
-
CERT_HASH: certificate,
|
|
90
|
-
SERVER_URL: serverAddress,
|
|
91
|
-
USE_HTTP2: http2 ? 'true' : 'false',
|
|
92
|
-
USE_POLYFILL: polyfill ? 'true' : 'false',
|
|
93
|
-
USE_PONYFILL: ponyfill ? 'true' : 'false',
|
|
94
|
-
NO_CERT_HASHES:
|
|
95
|
-
env === 'firefox' && !ponyfill && !polyfill ? 'true' : 'false',
|
|
96
|
-
BROWSER: env
|
|
97
|
-
},
|
|
98
|
-
stdio: ['inherit', 'inherit', 'inherit']
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
await tests
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let success = true
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
const { address, certificate } = await startServer()
|
|
109
|
-
|
|
110
|
-
await runTests(certificate, address)
|
|
111
|
-
} catch (/** @type {any} */ err) {
|
|
112
|
-
if (err.command == null) {
|
|
113
|
-
// was not an execa error
|
|
114
|
-
throw err
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (err.failed || err.timedOut || err.isCancelled || err.isKilled) {
|
|
118
|
-
console.log('Error cause mocha process', err)
|
|
119
|
-
success = false
|
|
120
|
-
}
|
|
121
|
-
} finally {
|
|
122
|
-
// this will cause the server process to exit too as it is a child of this process
|
|
123
|
-
process.exit(success ? 0 : 1)
|
|
124
|
-
}
|