diff --git a/scripts/build/deps/webkit.ts b/scripts/build/deps/webkit.ts index 69d2d341084..6a0fe963f2d 100644 --- a/scripts/build/deps/webkit.ts +++ b/scripts/build/deps/webkit.ts @@ -7,7 +7,13 @@ // -lto variants built with ThinLTO (per-module summaries for cross-language // importing), and the Windows ICU data table filtered + per-item zstd // compressed (lazily decompressed via bun_icu_decompress.cpp). -export const WEBKIT_VERSION = "cd821fecca0d39c8bac874c283d956868c7f0de0"; +// TEMPORARY preview pin: main's WebKit cd821fec + the asyncModuleExecutionResume +// fix from oven-sh/WebKit#252 (fixes oven-sh/bun#32178), rebased onto cd821fec as +// commit 83144fc3 so it is ABI-compatible with main's bindings. +// Swap to the oven-sh/WebKit main autobuild SHA that includes #252 (the new commit +// created when #252 lands, NOT cd821fec which is its unfixed base), before merging. +// (main pin superseded by this preview: "cd821fecca0d39c8bac874c283d956868c7f0de0") +export const WEBKIT_VERSION = "autobuild-preview-pr-252-83144fc3"; /** * WebKit (JavaScriptCore) — the JS engine. diff --git a/test/regression/issue/32178.test.ts b/test/regression/issue/32178.test.ts new file mode 100644 index 00000000000..81a7321b402 --- /dev/null +++ b/test/regression/issue/32178.test.ts @@ -0,0 +1,67 @@ +// https://github.com/oven-sh/bun/issues/32178 +import { expect, test } from "bun:test"; +import { bunEnv, bunExe, tempDir } from "harness"; + +test.concurrent("top-level await resumes while an AsyncLocalStorage context is active", async () => { + using dir = tempDir("issue-32178", { + "entry.ts": ` + import { AsyncLocalStorage } from "node:async_hooks"; + const als = new AsyncLocalStorage(); + als.enterWith({ v: 42 }); + await Promise.resolve(1); + console.log("after microtask await:", JSON.stringify(als.getStore())); + await new Promise(r => setImmediate(r)); + console.log("after macrotask await:", JSON.stringify(als.getStore())); + `, + }); + + await using proc = Bun.spawn({ + cmd: [bunExe(), "entry.ts"], + env: bunEnv, + cwd: String(dir), + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + // The async context must also survive across the top-level awaits, like Node. + expect({ stdout, stderr, exitCode }).toEqual({ + stdout: 'after microtask await: {"v":42}\nafter macrotask await: {"v":42}\n', + stderr: "", + exitCode: 0, + }); +}); + +test.concurrent("imported top-level-await module entering an AsyncLocalStorage context", async () => { + using dir = tempDir("issue-32178-import", { + "main.ts": ` + import { store } from "./tla.ts"; + console.log("imported:", JSON.stringify(store)); + `, + "tla.ts": ` + import { AsyncLocalStorage } from "node:async_hooks"; + const als = new AsyncLocalStorage(); + als.enterWith({ id: 7 }); + await Promise.resolve(); + await Promise.resolve(); + export const store = als.getStore(); + `, + }); + + await using proc = Bun.spawn({ + cmd: [bunExe(), "main.ts"], + env: bunEnv, + cwd: String(dir), + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + expect({ stdout, stderr, exitCode }).toEqual({ + stdout: 'imported: {"id":7}\n', + stderr: "", + exitCode: 0, + }); +});