From 0112d0862bcdb4eca7ece76be42159e53ec31473 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:49:10 +0000 Subject: [PATCH 1/3] jsc: don't leak builtin @-identifiers in TypeError messages (debug/ASAN) In ASSERT_ENABLED builds (debug and ASAN), JSC builtins emit expression info, and when a .@call() inside a builtin (e.g. the WrapForValidIterator next/return prototype functions used by Iterator.from) hits a non-callable value, the Call IC slow path feeds the builtin code block and bytecode index straight into appendSourceToErrorMessage, which splices the private @-identifier source text into the user-visible TypeError: Iterator.from({}).next() // TypeError: @getWrapForValidIteratorInternalField(this, // @wrapForValidIteratorFieldIteratedNextMethod).@call is not a // function. (In '...') Release builds are unaffected: BytecodeGenerator::emitExpressionInfo skips builtins under '#if !ASSERT_ENABLED', so hasExpressionInfo() returns false and appendSourceToErrorMessage bails early. WebKit fix (oven-sh/WebKit#369) adds an isBuiltinFunction() check in appendSourceToErrorMessage so ASSERT_ENABLED output matches release. The preview build here is the current WEBKIT_VERSION (549170099) plus that one commit. --- scripts/build/deps/webkit.ts | 2 +- test/js/bun/jsc/builtin-error-message.test.ts | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/js/bun/jsc/builtin-error-message.test.ts diff --git a/scripts/build/deps/webkit.ts b/scripts/build/deps/webkit.ts index f84dd77e0e19..8ca6857967c7 100644 --- a/scripts/build/deps/webkit.ts +++ b/scripts/build/deps/webkit.ts @@ -3,7 +3,7 @@ * for local mode. Override via `--webkit-version=` to test a branch. * From https://github.com/oven-sh/WebKit releases. */ -export const WEBKIT_VERSION = "549170099226f816a4b204ea1d8fa102fb79eefa"; +export const WEBKIT_VERSION = "autobuild-preview-pr-369-bce3c3e1"; /** * WebKit (JavaScriptCore) — the JS engine. diff --git a/test/js/bun/jsc/builtin-error-message.test.ts b/test/js/bun/jsc/builtin-error-message.test.ts new file mode 100644 index 000000000000..275b2e234846 --- /dev/null +++ b/test/js/bun/jsc/builtin-error-message.test.ts @@ -0,0 +1,39 @@ +import { test, expect } from "bun:test"; + +// TypeError messages thrown from JSC builtin JavaScript must not leak the +// builtin's private @-prefixed identifiers (e.g. `@call`, `@getWrapForValidIteratorInternalField`) +// into user-visible `error.message`. Release builds already suppress this by +// omitting expression info for builtins; this test guards the ASSERT_ENABLED +// path (debug / ASAN) where builtins do carry expression info. + +function messageOf(fn: () => unknown): string { + try { + fn(); + } catch (e) { + return (e as Error).message; + } + throw new Error("expected fn to throw"); +} + +test("%WrapForValidIteratorPrototype%.next on a wrapped iterator with no next method", () => { + const msg = messageOf(() => Iterator.from({} as any).next()); + expect(msg).not.toContain("@"); + expect(msg).not.toContain("WrapForValidIterator"); + expect(msg).toBe("undefined is not a function"); +}); + +test("%WrapForValidIteratorPrototype%.return with a non-callable return", () => { + const msg = messageOf(() => + Iterator.from({ next: () => ({ done: false, value: 1 }), return: 5 } as any).return(), + ); + expect(msg).not.toContain("@"); + expect(msg).not.toContain("returnMethod"); + expect(msg).toBe("5 is not a function"); +}); + +test("Iterator.from with a non-callable Symbol.iterator", () => { + const msg = messageOf(() => Iterator.from({ [Symbol.iterator]: 5 } as any)); + expect(msg).not.toContain("@"); + expect(msg).not.toContain("method"); + expect(msg).toBe("5 is not a function"); +}); From dc4a69e05b0f99a78b0b87857dc66422460339c9 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:51:59 +0000 Subject: [PATCH 2/3] [autofix.ci] apply automated fixes --- test/js/bun/jsc/builtin-error-message.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/js/bun/jsc/builtin-error-message.test.ts b/test/js/bun/jsc/builtin-error-message.test.ts index 275b2e234846..8494ea2ac377 100644 --- a/test/js/bun/jsc/builtin-error-message.test.ts +++ b/test/js/bun/jsc/builtin-error-message.test.ts @@ -1,4 +1,4 @@ -import { test, expect } from "bun:test"; +import { expect, test } from "bun:test"; // TypeError messages thrown from JSC builtin JavaScript must not leak the // builtin's private @-prefixed identifiers (e.g. `@call`, `@getWrapForValidIteratorInternalField`) @@ -23,9 +23,7 @@ test("%WrapForValidIteratorPrototype%.next on a wrapped iterator with no next me }); test("%WrapForValidIteratorPrototype%.return with a non-callable return", () => { - const msg = messageOf(() => - Iterator.from({ next: () => ({ done: false, value: 1 }), return: 5 } as any).return(), - ); + const msg = messageOf(() => Iterator.from({ next: () => ({ done: false, value: 1 }), return: 5 } as any).return()); expect(msg).not.toContain("@"); expect(msg).not.toContain("returnMethod"); expect(msg).toBe("5 is not a function"); From 6e52dfd22b911b29ec8eb46859daa46f5c29c94b Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Tue, 28 Jul 2026 22:43:36 +0000 Subject: [PATCH 3/3] ci: retrigger (WebKit preview build is now published)