fix(webworker): scope Linux-only CI checks

This commit is contained in:
imccyu 2026-08-24 01:01:19 +08:00
parent 5ad9b128f9
commit be852d4e9b
3 changed files with 53 additions and 23 deletions

View file

@ -481,6 +481,40 @@ export interface WriteStreamOptions {
/** Node implements file-stream `autoClose` through the stream's `autoDestroy` state. */
const streamAutoDestroy = (autoClose: boolean | undefined): boolean => autoClose ?? true
interface FileStreamState {
fd: number | null
pending: boolean
}
/** Release the descriptor and abort listener shared by both file-stream directions. */
function destroyFileStream(
stream: FileStreamState,
signal: AbortSignal | undefined,
onAbort: (() => void) | undefined,
error: Error | null,
callback: (error: Error | null) => void,
): void {
signal?.removeEventListener('abort', onAbort as () => void)
if (stream.fd !== null) closeSync(stream.fd)
stream.fd = null
stream.pending = false
callback(error)
}
interface ClosableFileStream {
once(event: string, listener: () => void): unknown
destroy(): unknown
}
/** Register an optional completion callback and explicitly destroy a file stream. */
function closeFileStream(
stream: ClosableFileStream,
callback?: (error?: NodeJS.ErrnoException | null) => void,
): void {
if (callback !== undefined) stream.once('close', () => { callback(null) })
stream.destroy()
}
/** Read stream over one VFS file. */
export class ReadStream extends Readable {
/** Resolved path opened by this stream. */
@ -560,11 +594,7 @@ export class ReadStream extends Readable {
}
override _destroy(error: Error | null, callback: (error?: Error | null) => void): void {
this.signal?.removeEventListener('abort', this.onAbort as () => void)
if (this.fd !== null) closeSync(this.fd)
this.fd = null
this.pending = false
callback(error)
destroyFileStream(this, this.signal, this.onAbort, error, callback)
}
/**
@ -572,8 +602,7 @@ export class ReadStream extends Readable {
* @param callback - Optional completion callback after `close`.
*/
close(callback?: (error?: NodeJS.ErrnoException | null) => void): void {
if (callback !== undefined) this.once('close', () => { callback(null) })
this.destroy()
closeFileStream(this, callback)
}
}
@ -647,11 +676,7 @@ export class WriteStream extends Writable {
}
override _destroy(error: Error | null, callback: (error: Error | null) => void): void {
this.signal?.removeEventListener('abort', this.onAbort as () => void)
closeDescriptor(this.fd)
this.fd = null
this.pending = false
callback(error)
destroyFileStream(this, this.signal, this.onAbort, error, callback)
}
/**
@ -659,16 +684,10 @@ export class WriteStream extends Writable {
* @param callback - Optional completion callback after `close`.
*/
close(callback?: (error?: NodeJS.ErrnoException | null) => void): void {
if (callback !== undefined) this.once('close', () => { callback(null) })
this.destroy()
closeFileStream(this, callback)
}
}
/** Close a stream-owned descriptor when it has opened successfully. */
function closeDescriptor(fd: number | null): void {
if (fd !== null) closeSync(fd)
}
/**
* Create a Node-compatible readable file stream over the VFS.
* @param path - File path.

View file

@ -279,7 +279,7 @@ describe('file streams', () => {
expect(workerStream.default._isArrayBufferView(new Uint8Array())).toBe(true)
})
it('matches Node file-stream defaults and abort error identity', async () => {
it('uses Node 22 Linux file-stream defaults and abort error identity', async () => {
const nativeRoot = mkdtempSync(join(tmpdir(), 'dsh-stream-diff-'))
nativeRoots.push(nativeRoot)
const nativePath = join(nativeRoot, 'input.txt')

View file

@ -57,6 +57,17 @@ const windowsUnsupportedTests = process.platform === 'win32'
]
: []
// These suites compare against or assemble the Worker's fixed Linux platform.
// Host-native Windows and macOS behavior is not their oracle.
const nonLinuxWebWorkerTests = process.platform === 'linux'
? []
: [
'packages/experimental/webworker-runtime/tests/node/fs-watch-stream.spec.ts',
'packages/experimental/webworker-runtime/tests/node/sandbox-stack.spec.ts',
]
const platformUnsupportedTests = [...windowsUnsupportedTests, ...nonLinuxWebWorkerTests]
const windowsUnsupportedCoveragePackages = process.platform === 'win32'
? [...windowsUnsupportedPackages, 'packages/subprocess/*']
: []
@ -142,7 +153,7 @@ export default defineConfig({
setupFiles: ['./scripts/test-invariants.ts'],
// .tsx: client component specs (jsdom via per-file @vitest-environment pragma).
include: testIncludes,
exclude: windowsUnsupportedTests,
exclude: platformUnsupportedTests,
// One coverage invocation aggregates both projects. Every suite forks for
// Node stability; process-bound suites stay separate for inventory control.
projects: [
@ -158,7 +169,7 @@ export default defineConfig({
setupFiles: ['./scripts/test-invariants.ts'],
include: testIncludes,
exclude: [
...windowsUnsupportedTests,
...platformUnsupportedTests,
...processBoundTests,
...coverageExemptExcludes,
],
@ -173,7 +184,7 @@ export default defineConfig({
setupFiles: ['./scripts/test-invariants.ts'],
include: processBoundTests,
exclude: [
...windowsUnsupportedTests,
...platformUnsupportedTests,
...coverageExemptExcludes,
],
},