Repro (5 lines, SIGSEGV)
function mk(P) { class D extends (P ?? Object) {} return D; }
const A = mk(null);
const B = mk(A);
console.log("ok " + typeof new B());
node : ok object
perry: Segmentation fault (core dumped) rc=139
The ?? is not the trigger — the explicit form crashes identically:
function mk(P) { const Base = P === null ? Object : P; class D extends Base {} return D; }
const A = mk(null);
const B = mk(A);
console.log("ok " + typeof new B()); // perry: SIGSEGV
What narrows it
| variant |
perry |
one level — mk(null), then new A() |
ok, node-identical |
two levels — mk(null), mk(A), then new B() |
SIGSEGV |
So the trigger is a factory function that returns class D extends <parameter>, invoked twice, where the second call's superclass is the class produced by the first — then instantiating the second. One level is fine; the second level is what dies. new B() is required (constructing the derived class); building the classes alone does not crash.
Not a regression: identical SIGSEGV on 83754818e (#9242) and on a03be729c (#9336), so it predates the whole #9341 window.
Why this shape matters
This is the exact idiom zod v4's $constructor uses, and zod is the largest single consumer of it in the claude-code bundle:
function $constructor(name, initializer, params) {
class Definition extends (params?.Parent ?? Object) {} // <- the factory
…
return _;
}
const $ZodType = $constructor("$ZodType", init);
const $ZodString = $constructor("$ZodString", init, { Parent: $ZodType }); // <- second level
Instrumenting Object.defineProperty on the real node cli_2.1.112.js --help run shows this constructor factory executing 161 times, so the bundle drives this path hard. It does not crash there today (cc --help is byte-identical to node on 83754818e), which means perry is getting through the bundle's instance of the shape by some route the reduced form does not take — worth understanding, because it is a hard crash sitting directly under the most heavily used schema library in the corpus.
Found while bisecting #9341; filed separately because it is not that regression — both the green and the broken build crash on it.
Repro (5 lines, SIGSEGV)
The
??is not the trigger — the explicit form crashes identically:What narrows it
mk(null), thennew A()mk(null),mk(A), thennew B()So the trigger is a factory function that returns
class D extends <parameter>, invoked twice, where the second call's superclass is the class produced by the first — then instantiating the second. One level is fine; the second level is what dies.new B()is required (constructing the derived class); building the classes alone does not crash.Not a regression: identical SIGSEGV on
83754818e(#9242) and ona03be729c(#9336), so it predates the whole #9341 window.Why this shape matters
This is the exact idiom zod v4's
$constructoruses, and zod is the largest single consumer of it in theclaude-codebundle:Instrumenting
Object.definePropertyon the realnode cli_2.1.112.js --helprun shows this constructor factory executing 161 times, so the bundle drives this path hard. It does not crash there today (cc --helpis byte-identical to node on83754818e), which means perry is getting through the bundle's instance of the shape by some route the reduced form does not take — worth understanding, because it is a hard crash sitting directly under the most heavily used schema library in the corpus.Found while bisecting #9341; filed separately because it is not that regression — both the green and the broken build crash on it.