Summary
Array.from(p) where p is a Proxy wrapping an array segfaults (SIGSEGV, exit 139). Spreading and for…of over the same proxy work, so the value is iterable; only Array.from crashes. Found while chasing OpenCode's request path (tracker #10107).
Repro
const t = (name: string, f: () => any) => { try { console.log(name, JSON.stringify(f())) } catch (e: any) { console.log(name, "THROW", e.message) } }
const pa = () => new Proxy([["x-a", "1"]], {})
t("Q1 [...proxyOverArray]", () => [...(pa() as any)].length)
t("Q2 for..of proxyOverArray", () => { let n = 0; for (const _ of pa() as any) n++; return n })
t("Q3 Array.isArray(proxyOverArray)", () => Array.isArray(pa()))
t("Q4 proxy[Symbol.iterator] typeof", () => typeof (pa() as any)[Symbol.iterator])
t("Q5 Array.from(proxyOverArray)", () => Array.from(pa() as any).length)
perry 0.5.1569 (Linux x86_64), perry compile proxy-iter.ts:
Q1 [...proxyOverArray] 1
Q2 for..of proxyOverArray 1
Q3 Array.isArray(proxyOverArray) true
Q4 proxy[Symbol.iterator] typeof "function"
Segmentation fault (core dumped) ← Q5
bun 1.3.14 prints Q5 Array.from(proxyOverArray) 1 and continues.
Notes
Array.isArray returns true for the proxy, so any code path that branches on it and then takes an array-specific fast path will dereference the proxy id as if it were an ArrayHeader. That is the likely shape of the crash; js_for_of_to_array on such a value is reachable from the Headers constructor too (new Headers(new Proxy([["a","1"]], {}))), which is how I found it.
- A crash rather than a
TypeError makes this worse than a plain correctness gap: it takes the whole process down with no JS-level stack.
Related: the Headers record-init proxy gap I am fixing separately, and tracker #10107.
Summary
Array.from(p)wherepis aProxywrapping an array segfaults (SIGSEGV, exit 139). Spreading andfor…ofover the same proxy work, so the value is iterable; onlyArray.fromcrashes. Found while chasing OpenCode's request path (tracker #10107).Repro
perry 0.5.1569 (Linux x86_64),
perry compile proxy-iter.ts:bun 1.3.14 prints
Q5 Array.from(proxyOverArray) 1and continues.Notes
Array.isArrayreturnstruefor the proxy, so any code path that branches on it and then takes an array-specific fast path will dereference the proxy id as if it were anArrayHeader. That is the likely shape of the crash;js_for_of_to_arrayon such a value is reachable from theHeadersconstructor too (new Headers(new Proxy([["a","1"]], {}))), which is how I found it.TypeErrormakes this worse than a plain correctness gap: it takes the whole process down with no JS-level stack.Related: the
Headersrecord-init proxy gap I am fixing separately, and tracker #10107.