Skip to content

Commit

Permalink
wasm: catch and rethrow stack overflows (#3915)
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Sep 21, 2024
1 parent 11d3196 commit ed5a555
Showing 1 changed file with 30 additions and 11 deletions.
41 changes: 30 additions & 11 deletions lib/npm/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ const startRunningService = async (wasmURL: string | URL, wasmModule: WebAssembl
terminate: () => void
}

let rejectAllWith: (error: unknown) => void
const rejectAllPromise = new Promise(resolve => rejectAllWith = resolve)

if (useWorker) {
// Run esbuild off the main thread
let blob = new Blob([`onmessage=${WEB_WORKER_SOURCE_CODE}(postMessage)`], { type: 'text/javascript' })
Expand All @@ -98,7 +101,13 @@ const startRunningService = async (wasmURL: string | URL, wasmModule: WebAssembl
let go: Go | undefined
worker = {
onmessage: null,
postMessage: data => setTimeout(() => go = onmessage({ data })),
postMessage: data => setTimeout(() => {
try {
go = onmessage({ data })
} catch (error) {
rejectAllWith(error) // Catch strange crashes (e.g. stack overflow)
}
}),
terminate() {
if (go)
for (let timeout of go._scheduledTimeouts.values())
Expand Down Expand Up @@ -144,29 +153,34 @@ const startRunningService = async (wasmURL: string | URL, wasmModule: WebAssembl

longLivedService = {
build: (options: types.BuildOptions) =>
new Promise<types.BuildResult>((resolve, reject) =>
new Promise<types.BuildResult>((resolve, reject) => {
rejectAllPromise.then(reject)
service.buildOrContext({
callName: 'build',
refs: null,
options,
isTTY: false,
defaultWD: '/',
callback: (err, res) => err ? reject(err) : resolve(res as types.BuildResult),
})),
})
}),

context: (options: types.BuildOptions) =>
new Promise<types.BuildContext>((resolve, reject) =>
new Promise<types.BuildContext>((resolve, reject) => {
rejectAllPromise.then(reject)
service.buildOrContext({
callName: 'context',
refs: null,
options,
isTTY: false,
defaultWD: '/',
callback: (err, res) => err ? reject(err) : resolve(res as types.BuildContext),
})),
})
}),

transform: (input: string | Uint8Array, options?: types.TransformOptions) =>
new Promise<types.TransformResult>((resolve, reject) =>
new Promise<types.TransformResult>((resolve, reject) => {
rejectAllPromise.then(reject)
service.transform({
callName: 'transform',
refs: null,
Expand All @@ -178,27 +192,32 @@ const startRunningService = async (wasmURL: string | URL, wasmModule: WebAssembl
writeFile(_, callback) { callback(null); },
},
callback: (err, res) => err ? reject(err) : resolve(res!),
})),
})
}),

formatMessages: (messages, options) =>
new Promise((resolve, reject) =>
new Promise((resolve, reject) => {
rejectAllPromise.then(reject)
service.formatMessages({
callName: 'formatMessages',
refs: null,
messages,
options,
callback: (err, res) => err ? reject(err) : resolve(res!),
})),
})
}),

analyzeMetafile: (metafile, options) =>
new Promise((resolve, reject) =>
new Promise((resolve, reject) => {
rejectAllPromise.then(reject)
service.analyzeMetafile({
callName: 'analyzeMetafile',
refs: null,
metafile: typeof metafile === 'string' ? metafile : JSON.stringify(metafile),
options,
callback: (err, res) => err ? reject(err) : resolve(res!),
})),
})
}),
}
}

Expand Down

0 comments on commit ed5a555

Please sign in to comment.