Skip to content

Compiled generator: nested-block shadow of a closure-captured name still leaks (out of #711 scope) #767

@nickna

Description

@nickna

Summary

The #711 fix disambiguates a nested-block let/const that shadows an enclosing binding by giving it its own storage — except when the shadowed name is also referenced by a nested closure (arrow/function/class) in the same generator. Those names are deliberately left untouched because the closure-capture machinery keys captured variables by source name and the #711 rename does not rewrite closure interiors; renaming a captured name would desync the capture. So this residual case still leaks.

Repro

function* g(): Generator<number> {
  const r = 100;
  {
    const r = 5;
    const f = () => r;   // arrow captures the inner r → name "r" is off-limits to the #711 rename
    yield f();
  }
  yield r;
}
console.log([...g()]);
  • Interpreted: [5, 100] (correct)
  • Compiled: [5, 5] (wrong — outer r leaked to 5 via the shared field/DC)

Notes

A proper fix needs precise per-binding capture analysis (which arrow captures which lexical binding) so a shadowing binding can be renamed and its capturing closures updated consistently — rather than the current conservative "skip if the name appears in any closure" guard in GeneratorBlockScopeRenamer. Astronomically rare; low priority. Found while implementing #711.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions