Skip to content
Draft
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
2 changes: 1 addition & 1 deletion scripts/build/deps/webkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* for local mode. Override via `--webkit-version=<hash>` to test a branch.
* From https://github.com/oven-sh/WebKit releases.
*/
export const WEBKIT_VERSION = "cf1b36ec8703d8e87436094d21d478d358c7d886";
export const WEBKIT_VERSION = "autobuild-preview-pr-641-05a48085";
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 WEBKIT_VERSION is pinned to autobuild-preview-pr-641-05a48085, an ephemeral preview-PR release; merging this makes every fresh checkout's build depend on an artifact that is deleted once oven-sh/WebKit#641 closes, whereas the base pin is a permanent merged-commit SHA. Fix: before merge, repin to the merged commit's 40-hex SHA on oven-sh/WebKit main and confirm prebuilt tarballs exist for every platform×{debug,lto,asan,musl} flavor prebuiltSuffix() produces (per .claude/docs/landing-prs.md "Dependencies & vendoring": never merge a pin to preview tags or unmerged-PR builds).

Extended reasoning...

prebuiltUrl() in scripts/build/deps/webkit.ts:68-75 turns this value into https://github.com/oven-sh/WebKit/releases/download/autobuild-preview-pr-641-05a48085/bun-webkit-<os>-<arch><suffix>.tar.gz. Preview autobuild-preview-pr-* releases are transient CI artifacts for unmerged PRs; once WebKit#641 is merged or closed the release is removed and dep_fetch 404s, so bun bd fails from a clean cache on this commit (base branch pins a permanent autobuild-<sha> release that never disappears). The PR author states this is not mergeable as-is; landing-prs.md line 47 makes it a hard block. No other files reference the old SHA (grep clean), so only this line needs the repin.

Verification: normal — acknowledged in diff: the PR description states "This is a preview pin and must be repinned to a commit on the fork's main once #641 merges; it is not mergeable as is," and that claim holds against the code. The diff at /home/claude/bun/scripts/build/deps/webkit.ts:6 changes WEBKIT_VERSION from the permanent 40-hex merged-commit SHA "cf1b36ec8703d8e87436094d21d478d358c7d886"…

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. The preview pin is there so that CI runs the new tests against oven-sh/WebKit#641, and this PR must not merge with it. I leave this thread open as the merge gate. When #641 lands I repin to the merge commit on the fork's main, check that its autobuild-<sha> release has a tarball for every platform and flavor, and resolve the thread.


/**
* WebKit (JavaScriptCore) — the JS engine.
Expand Down
64 changes: 63 additions & 1 deletion test/js/node/v8/capture-stack-trace.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { nativeFrameForTesting } from "bun:internal-for-testing";
import { noInline } from "bun:jsc";
import { afterEach, expect, mock, test } from "bun:test";
import { afterEach, describe, expect, mock, test } from "bun:test";
import { bunEnv, bunExe, tempDir } from "harness";
import { sep } from "node:path";
const origPrepareStackTrace = Error.prepareStackTrace;
afterEach(() => {
Error.prepareStackTrace = origPrepareStackTrace;
Expand Down Expand Up @@ -1223,3 +1224,64 @@ test.concurrent.each([[{}], [{ BUN_JSC_useSourceProviderCache: "0" }]])(
expect(exitCode).toBe(0);
},
);

// The `stack` of `new WebAssembly.Exception(tag, payload, { traceStack: true })` is the stack of an Error created at
// that point: V8-style, source-mapped, and passed through Error.prepareStackTrace.
describe("WebAssembly.Exception with traceStack", () => {
const tag = new WebAssembly.Tag({ parameters: [] });
// Both on one line, so only the column of the first frame differs.
// prettier-ignore
function createBoth() { return [new WebAssembly.Exception(tag, [], { traceStack: true }), new Error()]; }

test("stack is formatted and source-mapped like the stack of an Error", () => {
const [exception, error] = createBoth();
const withoutFirstColumn = stack => stack.replace(/:\d+\)$/m, ")");
expect(exception.stack).toStartWith(`Error\n at createBoth (${import.meta.path}:`);
expect(withoutFirstColumn(exception.stack)).toBe(withoutFirstColumn(error.stack));
});

test("stack goes through Error.prepareStackTrace", () => {
Error.prepareStackTrace = (_, callSites) => callSites;
const [exception, error] = createBoth();
const summarize = callSites =>
callSites.map(site => [site.getFunctionName(), site.getFileName(), site.getLineNumber()]);
expect(summarize(exception.stack)).toEqual(summarize(error.stack));
expect(summarize(exception.stack)[0]).toEqual(["createBoth", import.meta.path, expect.any(Number)]);
});

test("stack stays a getter on the prototype", () => {
const [exception] = createBoth();
expect(Reflect.ownKeys(exception)).toEqual([]);
expect(Object.getOwnPropertyDescriptor(WebAssembly.Exception.prototype, "stack").get).toBeFunction();
expect(new WebAssembly.Exception(tag, []).stack).toBeUndefined();
});

test("positions are those of the source file, not of the transpiled file", async () => {
using dir = tempDir("wasm-exception-stack", {
"thrower.ts": `// line 1
// line 2
type Erased = { erased: true };
function thrower(): WebAssembly.Exception {
const tag = new WebAssembly.Tag({ parameters: [] });
return new WebAssembly.Exception(tag, [], { traceStack: true });
}
console.log(thrower().stack);
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "thrower.ts"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(stdout.replaceAll(String(dir) + sep, "").replace(/:(\d+):\d+/g, ":$1")).toMatchInlineSnapshot(`
"Error
at thrower (thrower.ts:6)
at thrower.ts:8
"
`);
expect(exitCode).toBe(0);
});
});
Loading