Skip to content

Commit

Permalink
fix: transfer response buffer on safari (#1771)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito authored Oct 15, 2023
1 parent b028c66 commit 6405bea
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 16 deletions.
7 changes: 5 additions & 2 deletions src/browser/setupWorker/glossary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export type ServiceWorkerOutgoingEventTypes =
| 'CLIENT_CLOSED'

export interface StringifiedResponse extends ResponseInit {
body: string | ReadableStream<Uint8Array> | null
body: string | ArrayBuffer | ReadableStream<Uint8Array> | null
}

/**
Expand Down Expand Up @@ -146,7 +146,10 @@ export interface SetupWorkerInternalContext {
ServiceWorkerMessage<EventType, ServiceWorkerIncomingEventsMap[EventType]>
>
}
useFallbackMode: boolean
supports: {
serviceWorkerApi: boolean
readableStreamTransfer: boolean
}
fallbackInterceptor?: Interceptor<HttpRequestEventMap>
}

Expand Down
12 changes: 8 additions & 4 deletions src/browser/setupWorker/setupWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { SetupApi } from '~/core/SetupApi'
import { mergeRight } from '~/core/utils/internal/mergeRight'
import { LifeCycleEventsMap } from '~/core/sharedOptions'
import { SetupWorker } from './glossary'
import { supportsReadableStreamTransfer } from '../utils/supportsReadableStreamTransfer'

interface Listener {
target: EventTarget
Expand Down Expand Up @@ -142,8 +143,11 @@ export class SetupWorkerApi
})
},
},
useFallbackMode:
!('serviceWorker' in navigator) || location.protocol === 'file:',
supports: {
serviceWorkerApi:
!('serviceWorker' in navigator) || location.protocol === 'file:',
readableStreamTransfer: supportsReadableStreamTransfer(),
},
}

/**
Expand All @@ -156,11 +160,11 @@ export class SetupWorkerApi
},
})

this.startHandler = context.useFallbackMode
this.startHandler = context.supports.serviceWorkerApi
? createFallbackStart(context)
: createStartHandler(context)

this.stopHandler = context.useFallbackMode
this.stopHandler = context.supports.serviceWorkerApi
? createFallbackStop(context)
: createStop(context)

Expand Down
31 changes: 21 additions & 10 deletions src/browser/setupWorker/start/createRequestListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,29 @@ export const createRequestListener = (
// ".log()" method of the request handler.
const responseClone = response.clone()
const responseInit = toResponseInit(response)
const responseStream = responseClone.body

messageChannel.postMessage(
'MOCK_RESPONSE',
{
/**
* @note Safari doesn't support transferring a "ReadableStream".
* Check that the browser supports that before sending it to the worker.
*/
if (context.supports.readableStreamTransfer) {
const responseStream = response.body
messageChannel.postMessage(
'MOCK_RESPONSE',
{
...responseInit,
body: responseStream,
},
responseStream ? [responseStream] : undefined,
)
} else {
// As a fallback, send the response body buffer to the worker.
const responseBuffer = await responseClone.arrayBuffer()
messageChannel.postMessage('MOCK_RESPONSE', {
...responseInit,
body: responseStream,
},
// Transfer response's buffer so it could
// be sent over to the worker.
responseStream ? [responseStream] : undefined,
)
body: responseBuffer,
})
}

if (!options.quiet) {
context.emitter.once('response:mocked', ({ response }) => {
Expand Down
17 changes: 17 additions & 0 deletions src/browser/utils/supportsReadableStreamTransfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Returns a boolean indicating whether the current browser
* supports `ReadableStream` as a `Transferable` when posting
* messages.
*/
export function supportsReadableStreamTransfer() {
try {
const stream = new ReadableStream({
start: (controller) => controller.close(),
})
const message = new MessageChannel()
message.port1.postMessage(stream, [stream])
return true
} catch (error) {
return false
}
}

0 comments on commit 6405bea

Please sign in to comment.