Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/nuxt-cli/src/dev/broadcast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BroadcastChannel } from 'node:worker_threads'

import { debug } from '../utils/logger'

/** Listen on the channel called `name`, or return nothing where the runtime cannot open one. */
export function openBroadcast<T>(name: string, onMessage: (data: T) => void): BroadcastChannel | undefined {
try {
const channel = new BroadcastChannel(name)
channel.unref()
channel.onmessage = (event: { data: T }) => onMessage(event.data)
return channel
}
catch (error) {
debug(`Could not open the \`${name}\` channel:`, error)
}
}
14 changes: 5 additions & 9 deletions packages/nuxt-cli/src/dev/error-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import type { ProgressSnapshot } from '../utils/progress-snapshot'

import process from 'node:process'

import { BroadcastChannel } from 'node:worker_threads'

import { isAbsolute, join, relative } from 'pathe'

import { debug } from '../utils/logger'
import { openBroadcast } from './broadcast'
import { isLoopbackAddress } from './host-check'
import { DEV_INTERNAL_PREFIX } from './progress'

Expand Down Expand Up @@ -332,11 +331,7 @@ export interface ErrorBridgeHandlers {
* until the returned function is called.
*/
export function openErrorBridge(handlers: ErrorBridgeHandlers = {}, options: ErrorChannelOptions = {}): () => void {
const broadcast = new BroadcastChannel(ERROR_BROADCAST_CHANNEL)
broadcast.unref()
broadcast.postMessage(SYNC_MESSAGE)
broadcast.onmessage = (event: { data: unknown }) => {
const message = event.data
const broadcast = openBroadcast(ERROR_BROADCAST_CHANNEL, (message: unknown) => {
if (!isDevErrorMessage(message)) {
return
}
Expand Down Expand Up @@ -368,8 +363,9 @@ export function openErrorBridge(handlers: ErrorBridgeHandlers = {}, options: Err
}
}
}).catch(error => debug('Could not handle a forwarded error report:', error))
}
return () => broadcast.close()
})
broadcast?.postMessage(SYNC_MESSAGE)
return () => broadcast?.close()
}

export async function closeErrorChannel(): Promise<void> {
Expand Down
10 changes: 3 additions & 7 deletions packages/nuxt-cli/src/dev/log-channel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BroadcastChannel } from 'node:worker_threads'
import { openBroadcast } from './broadcast'

export interface ServerLogEvent {
level: number
Expand Down Expand Up @@ -26,10 +26,6 @@ export const DEV_LOG_CHANNEL = 'nuxt:dev:log'

/** Receive the app's logs until the returned function is called. */
export function openDevLogChannel(sink: (log: ServerLogEvent) => void): () => void {
const channel = new BroadcastChannel(DEV_LOG_CHANNEL)
channel.unref()
channel.onmessage = (event: { data: ServerLogEvent }) => {
sink(event.data)
}
return () => channel.close()
const channel = openBroadcast(DEV_LOG_CHANNEL, sink)
return () => channel?.close()
}
10 changes: 3 additions & 7 deletions packages/nuxt-cli/src/dev/span-channel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BroadcastChannel } from 'node:worker_threads'
import { openBroadcast } from './broadcast'

/** A timed piece of work the app did while serving a request. */
export interface DevRequestSpan {
Expand Down Expand Up @@ -29,10 +29,6 @@ const DEV_SPAN_CHANNEL = 'nuxt:dev:span'

/** Receive the app's spans until the returned function is called. */
export function openDevSpanChannel(sink: (span: DevRequestSpan) => void): () => void {
const channel = new BroadcastChannel(DEV_SPAN_CHANNEL)
channel.unref()
channel.onmessage = (event: { data: DevRequestSpan }) => {
sink(event.data)
}
return () => channel.close()
const channel = openBroadcast(DEV_SPAN_CHANNEL, sink)
return () => channel?.close()
}
24 changes: 24 additions & 0 deletions packages/nuxt-cli/test/unit/broadcast.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, expect, it, vi } from 'vitest'

import { openErrorBridge } from '../../src/dev/error-channel'
import { openDevLogChannel } from '../../src/dev/log-channel'
import { openDevSpanChannel } from '../../src/dev/span-channel'

vi.mock('node:worker_threads', async importOriginal => ({
...await importOriginal<typeof import('node:worker_threads')>(),
BroadcastChannel: class {
constructor() {
throw new TypeError('Cannot read properties of undefined (reading \'on\')')
}
},
}))

describe('dev channels', () => {
it.each([
['log', () => openDevLogChannel(() => {})],
['span', () => openDevSpanChannel(() => {})],
['error', () => openErrorBridge()],
])('should open and close the %s channel when `BroadcastChannel` cannot be constructed', (_, open) => {
expect(() => open()()).not.toThrow()
})
})
Loading