From 4d27f1497a1f179cef12ce69578d3ee12c70d257 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 22 Mar 2023 20:24:30 -0700 Subject: [PATCH 01/10] feat: resolve serviceWorker error window.WebTransport doesn't exist in service worker. --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 60342a5..c6fbf62 100644 --- a/src/index.ts +++ b/src/index.ts @@ -299,7 +299,7 @@ class WebTransport implements Transport { throw new Error('Expected multiaddr to contain certhashes') } - const wt = new window.WebTransport(`${url}/.well-known/libp2p-webtransport?type=noise`, { + const wt = new globalThis.WebTransport(`${url}/.well-known/libp2p-webtransport?type=noise`, { serverCertificateHashes: certhashes.map(certhash => ({ algorithm: 'sha-256', value: certhash.digest From 27596922cb0258870cd65dd20290e17fefac98f0 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 22 Mar 2023 20:54:29 -0700 Subject: [PATCH 02/10] fix: type errors after using globalThis.WebTransport --- src/index.ts | 23 +++++++++++++++++++---- tsconfig.json | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index c6fbf62..2af81a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,10 +12,25 @@ import type { StreamMuxerFactory, StreamMuxerInit, StreamMuxer } from '@libp2p/i import { Uint8ArrayList } from 'uint8arraylist' const log = logger('libp2p:webtransport') + declare global { - interface Window { - WebTransport: any + interface WebTransportConfig { + serverCertificateHashes?: Array<{algorithm: string, value: Uint8Array}> + } + /** + * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport + */ + class GlobalThisWebTransport { + closed: Promise + datagrams: Stream + incomingBidirectionalStreams: ReadableStream + incomingUnidirectionalStreams: ReadableStream + createBidirectionalStream (): Promise + ready: Promise + close (): any } + // eslint-disable-next-line no-var + var WebTransport: new (url: string, config: WebTransportConfig) => GlobalThisWebTransport } // @ts-expect-error - Not easy to combine these types. @@ -349,7 +364,7 @@ class WebTransport implements Transport { return await options.upgrader.upgradeOutbound(maConn, { skipEncryption: true, muxerFactory: this.webtransportMuxer(wt), skipProtection: true }) } - async authenticateWebTransport (wt: typeof window.WebTransport, localPeer: PeerId, remotePeer: PeerId, certhashes: Array>): Promise { + async authenticateWebTransport (wt: InstanceType, localPeer: PeerId, remotePeer: PeerId, certhashes: Array>): Promise { const stream = await wt.createBidirectionalStream() const writer = stream.writable.getWriter() const reader = stream.readable.getReader() @@ -390,7 +405,7 @@ class WebTransport implements Transport { return true } - webtransportMuxer (wt: typeof window.WebTransport): StreamMuxerFactory { + webtransportMuxer (wt: InstanceType): StreamMuxerFactory { let streamIDCounter = 0 const config = this.config return { diff --git a/tsconfig.json b/tsconfig.json index 13a3599..1a10e2b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + "lib": ["ES2021", "ES2021.Promise", "ES2021.String", "ES2020.BigInt", "DOM", "DOM.Iterable", "WebWorker"], }, "include": [ "src", From c1acecf9d2159eb2278a129adf6f6b7a8a7e8aef Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 22 Mar 2023 20:55:04 -0700 Subject: [PATCH 03/10] fix(lint): use boolean directly --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 2af81a8..15dd43a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -426,7 +426,7 @@ class WebTransport implements Transport { const reader = wt.incomingBidirectionalStreams.getReader() while (true) { const { done, value: wtStream } = await reader.read() - if (done === true) { + if (done) { break } if (activeStreams.length >= config.maxInboundStreams) { From 02d35aaa2c4d36549bde9e8e599acaa98097b146 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 22 Mar 2023 21:05:09 -0700 Subject: [PATCH 04/10] feat: move types to global.d.ts and update --- src/global.d.ts | 26 ++++++++++++++++++++++++++ src/index.ts | 7 ++++--- 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 src/global.d.ts diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..8843fa2 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,26 @@ + +interface WebTransportConfig { + serverCertificateHashes?: Array<{algorithm: string, value: Uint8Array}> +} +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransportBidirectionalStream + */ +interface WebTransportBidirectionalStream { + readable: ReadableStream + writable: WritableStream +} +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport + */ +interface GlobalThisWebTransport extends EventTarget { + closed: Promise + datagrams: Duplex + incomingBidirectionalStreams: ReadableStream + incomingUnidirectionalStreams: ReadableStream + ready: Promise + close: (options?: {closeCode: number, reason: string}) => void + createBidirectionalStream: () => Promise> + createUnidirectionalStream: () => Promise +} +// eslint-disable-next-line no-var, @typescript-eslint/no-unused-vars +var WebTransport: new (url: string, config: WebTransportConfig) => GlobalThisWebTransport diff --git a/src/index.ts b/src/index.ts index 15dd43a..51dddfb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,14 +20,15 @@ declare global { /** * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport */ - class GlobalThisWebTransport { + interface GlobalThisWebTransport extends EventTarget { closed: Promise datagrams: Stream incomingBidirectionalStreams: ReadableStream incomingUnidirectionalStreams: ReadableStream - createBidirectionalStream (): Promise ready: Promise - close (): any + close: (options: {closeCode: number, reason: string}) => void + createBidirectionalStream: () => Promise + createUnidirectionalStream: () => Promise } // eslint-disable-next-line no-var var WebTransport: new (url: string, config: WebTransportConfig) => GlobalThisWebTransport From 417932a0ff4f6e038566fda62be5ea295facc881 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 22 Mar 2023 21:05:39 -0700 Subject: [PATCH 05/10] chore: remove types from index.ts --- src/index.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/index.ts b/src/index.ts index 51dddfb..6aeba1a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,27 +13,6 @@ import { Uint8ArrayList } from 'uint8arraylist' const log = logger('libp2p:webtransport') -declare global { - interface WebTransportConfig { - serverCertificateHashes?: Array<{algorithm: string, value: Uint8Array}> - } - /** - * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport - */ - interface GlobalThisWebTransport extends EventTarget { - closed: Promise - datagrams: Stream - incomingBidirectionalStreams: ReadableStream - incomingUnidirectionalStreams: ReadableStream - ready: Promise - close: (options: {closeCode: number, reason: string}) => void - createBidirectionalStream: () => Promise - createUnidirectionalStream: () => Promise - } - // eslint-disable-next-line no-var - var WebTransport: new (url: string, config: WebTransportConfig) => GlobalThisWebTransport -} - // @ts-expect-error - Not easy to combine these types. const multibaseDecoder = Object.values(bases).map(b => b.decoder).reduce((d, b) => d.or(b)) From 3275d498d4b404267868ec1d2140371ed7bb799b Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 22 Mar 2023 21:08:46 -0700 Subject: [PATCH 06/10] fix: lint --- src/global.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global.d.ts b/src/global.d.ts index 8843fa2..4f46245 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,6 +1,6 @@ interface WebTransportConfig { - serverCertificateHashes?: Array<{algorithm: string, value: Uint8Array}> + serverCertificateHashes?: Array<{ algorithm: string, value: Uint8Array }> } /** * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransportBidirectionalStream @@ -18,7 +18,7 @@ interface GlobalThisWebTransport extends EventTarget { incomingBidirectionalStreams: ReadableStream incomingUnidirectionalStreams: ReadableStream ready: Promise - close: (options?: {closeCode: number, reason: string}) => void + close: (options?: { closeCode: number, reason: string }) => void createBidirectionalStream: () => Promise> createUnidirectionalStream: () => Promise } From c99eeeed104f8075c7a8de7286d212227a660f8e Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 23 Mar 2023 10:36:58 -0700 Subject: [PATCH 07/10] fix: use types from @fails-component/webtransport --- package.json | 1 + src/global.d.ts | 26 -------------------------- src/index.ts | 4 ++-- src/types.ts | 7 +++++++ 4 files changed, 10 insertions(+), 28 deletions(-) delete mode 100644 src/global.d.ts create mode 100644 src/types.ts diff --git a/package.json b/package.json index b4052b7..e585757 100644 --- a/package.json +++ b/package.json @@ -167,6 +167,7 @@ "uint8arraylist": "^2.3.3" }, "devDependencies": { + "@fails-components/webtransport": "^0.1.5", "aegir": "^38.1.7", "libp2p": "^0.43.2" }, diff --git a/src/global.d.ts b/src/global.d.ts deleted file mode 100644 index 4f46245..0000000 --- a/src/global.d.ts +++ /dev/null @@ -1,26 +0,0 @@ - -interface WebTransportConfig { - serverCertificateHashes?: Array<{ algorithm: string, value: Uint8Array }> -} -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransportBidirectionalStream - */ -interface WebTransportBidirectionalStream { - readable: ReadableStream - writable: WritableStream -} -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport - */ -interface GlobalThisWebTransport extends EventTarget { - closed: Promise - datagrams: Duplex - incomingBidirectionalStreams: ReadableStream - incomingUnidirectionalStreams: ReadableStream - ready: Promise - close: (options?: { closeCode: number, reason: string }) => void - createBidirectionalStream: () => Promise> - createUnidirectionalStream: () => Promise -} -// eslint-disable-next-line no-var, @typescript-eslint/no-unused-vars -var WebTransport: new (url: string, config: WebTransportConfig) => GlobalThisWebTransport diff --git a/src/index.ts b/src/index.ts index 6aeba1a..dbcc1d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -350,11 +350,11 @@ class WebTransport implements Transport { const reader = stream.readable.getReader() await writer.ready - const duplex = { + const duplex: Duplex> = { source: (async function * () { while (true) { const val = await reader.read() - yield val.value + yield val.value as Uint8Array } })(), sink: async function (source: Source) { diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..e94db62 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,7 @@ +import type { WebTransport as WebTransportType } from '@fails-components/webtransport' +import type { WebTransportOptions } from '@fails-components/webtransport/dist/lib/dom' + +declare global { + // eslint-disable-next-line no-var, @typescript-eslint/no-unused-vars + var WebTransport: new (url: string, config: WebTransportOptions) => WebTransportType +} From 5306c0c6a66e277478f623ae584dcf3f1aba7db8 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 23 Mar 2023 10:44:49 -0700 Subject: [PATCH 08/10] chore: revert tsconfig updates we should get changes from aegir when https://github.com/ipfs/aegir/pull/1219 lands --- tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 1a10e2b..13a3599 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { - "outDir": "dist", - "lib": ["ES2021", "ES2021.Promise", "ES2021.String", "ES2020.BigInt", "DOM", "DOM.Iterable", "WebWorker"], + "outDir": "dist" }, "include": [ "src", From 48179199efd5ba7fb622df9446b6065b294cf36d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 24 Mar 2023 16:33:01 +0000 Subject: [PATCH 09/10] chore: add npm script to test on webworkers --- package.json | 1 + src/index.ts | 21 ++++++++++++++------- src/types.ts | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index e585757..7079bcb 100644 --- a/package.json +++ b/package.json @@ -150,6 +150,7 @@ "build": "aegir build", "test": "aegir test -t browser", "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", "release": "aegir release", "docs": "aegir docs" }, diff --git a/src/index.ts b/src/index.ts index dbcc1d4..5cbab7d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -260,7 +260,7 @@ export interface WebTransportComponents { peerId: PeerId } -class WebTransport implements Transport { +class WebTransportTransport implements Transport { private readonly components: WebTransportComponents private readonly config: Required @@ -294,7 +294,7 @@ class WebTransport implements Transport { throw new Error('Expected multiaddr to contain certhashes') } - const wt = new globalThis.WebTransport(`${url}/.well-known/libp2p-webtransport?type=noise`, { + const wt = new WebTransport(`${url}/.well-known/libp2p-webtransport?type=noise`, { serverCertificateHashes: certhashes.map(certhash => ({ algorithm: 'sha-256', value: certhash.digest @@ -344,17 +344,24 @@ class WebTransport implements Transport { return await options.upgrader.upgradeOutbound(maConn, { skipEncryption: true, muxerFactory: this.webtransportMuxer(wt), skipProtection: true }) } - async authenticateWebTransport (wt: InstanceType, localPeer: PeerId, remotePeer: PeerId, certhashes: Array>): Promise { + async authenticateWebTransport (wt: InstanceType, localPeer: PeerId, remotePeer: PeerId, certhashes: Array>): Promise { const stream = await wt.createBidirectionalStream() const writer = stream.writable.getWriter() const reader = stream.readable.getReader() await writer.ready - const duplex: Duplex> = { + const duplex = { source: (async function * () { while (true) { const val = await reader.read() - yield val.value as Uint8Array + + if (val.value != null) { + yield val.value + } + + if (val.done) { + break + } } })(), sink: async function (source: Source) { @@ -385,7 +392,7 @@ class WebTransport implements Transport { return true } - webtransportMuxer (wt: InstanceType): StreamMuxerFactory { + webtransportMuxer (wt: InstanceType): StreamMuxerFactory { let streamIDCounter = 0 const config = this.config return { @@ -477,5 +484,5 @@ class WebTransport implements Transport { } export function webTransport (init: WebTransportInit = {}): (components: WebTransportComponents) => Transport { - return (components: WebTransportComponents) => new WebTransport(components, init) + return (components: WebTransportComponents) => new WebTransportTransport(components, init) } diff --git a/src/types.ts b/src/types.ts index e94db62..81854e0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,6 +2,8 @@ import type { WebTransport as WebTransportType } from '@fails-components/webtran import type { WebTransportOptions } from '@fails-components/webtransport/dist/lib/dom' declare global { + // will be added to the global TypeScript types once the WebTransport spec is no + // longer experimental - https://github.com/microsoft/TypeScript/issues/51912 // eslint-disable-next-line no-var, @typescript-eslint/no-unused-vars var WebTransport: new (url: string, config: WebTransportOptions) => WebTransportType } From 72d200ee7c1b9a7c124ba54c31dce00989a84ea7 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 24 Mar 2023 16:39:07 +0000 Subject: [PATCH 10/10] chore: simplify --- package.json | 3 +-- src/index.ts | 10 ++++++++-- src/types.ts | 9 --------- 3 files changed, 9 insertions(+), 13 deletions(-) delete mode 100644 src/types.ts diff --git a/package.json b/package.json index 7079bcb..709e9a4 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "lint": "aegir lint", "dep-check": "aegir dep-check", "build": "aegir build", - "test": "aegir test -t browser", + "test": "aegir test -t browser -t webworker", "test:chrome": "aegir test -t browser --cov", "test:chrome-webworker": "aegir test -t webworker", "release": "aegir release", @@ -168,7 +168,6 @@ "uint8arraylist": "^2.3.3" }, "devDependencies": { - "@fails-components/webtransport": "^0.1.5", "aegir": "^38.1.7", "libp2p": "^0.43.2" }, diff --git a/src/index.ts b/src/index.ts index 5cbab7d..e54c01a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,10 @@ import type { Duplex, Source } from 'it-stream-types' import type { StreamMuxerFactory, StreamMuxerInit, StreamMuxer } from '@libp2p/interface-stream-muxer' import { Uint8ArrayList } from 'uint8arraylist' +declare global { + var WebTransport: any +} + const log = logger('libp2p:webtransport') // @ts-expect-error - Not easy to combine these types. @@ -359,7 +363,7 @@ class WebTransportTransport implements Transport { yield val.value } - if (val.done) { + if (val.done === true) { break } } @@ -413,9 +417,11 @@ class WebTransportTransport implements Transport { const reader = wt.incomingBidirectionalStreams.getReader() while (true) { const { done, value: wtStream } = await reader.read() - if (done) { + + if (done === true) { break } + if (activeStreams.length >= config.maxInboundStreams) { // We've reached our limit, close this stream. wtStream.writable.close().catch((err: Error) => { diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 81854e0..0000000 --- a/src/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { WebTransport as WebTransportType } from '@fails-components/webtransport' -import type { WebTransportOptions } from '@fails-components/webtransport/dist/lib/dom' - -declare global { - // will be added to the global TypeScript types once the WebTransport spec is no - // longer experimental - https://github.com/microsoft/TypeScript/issues/51912 - // eslint-disable-next-line no-var, @typescript-eslint/no-unused-vars - var WebTransport: new (url: string, config: WebTransportOptions) => WebTransportType -}