You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[P2] Interpreter: static blocks skip lexical reservation without var loop heads #2870
Class static blocks without a var loop head do not reserve their lexical bindings before creating closures. A closure can consequently read an outer binding during the inner binding's temporal dead zone.
Full strict TypeScript checking and both SharpTS no-emit profiles accept this exact source. The checked interpreter exits zero with empty stderr but omits the expected ReferenceError catch. The outer binding is deliberately var; its value must remain 99, while the inner lexical binding must be inaccessible until initialized.
Interpreter.ExecuteClassStaticBlock currently creates a block environment and calls ReserveLexicalDeclarations only when InterpreterVarDeclarations.CollectLoopHeads finds a var loop head. VariableResolver.VisitStaticBlock makes its scope and lexical preregistration conditional on the same test. This source has no loop. Ordinary blocks already reserve their lexical bindings at entry. A static block needs that protocol independently of whether it contains a loop.
Acceptance: reserve static-block lexical bindings in their own scope before any statement executes, with matching resolver scope depth. Preserve class/static this, source order, independent sibling scopes, nested lexical shadows, and existing block-owned loop-var behavior. This report does not require a new compiler storage policy.
This was reproduced using immutable runtime SHA-256 D4B4C417F6C992CEF3FD2FCF9B2A797DA7B1BE5DE59F71BFEE5D6B4DC8C40ED6, pin DCD4A3107ED2D1DAAD8D4350F503A7DEAF3C3AFA199EE3AF3B1E2A32DE01C340, on clean committed HEAD 19d4bf721f17fee071da207a407cc1e78c66ee61. The pin's historical build base is 2e44c4aca13bb71fd655910da4bb40290a9fe6da. The source and complete 20-file package remained unchanged; all child processes closed and drained. No introducing commit is claimed.
The compiler also omits the catch on this source, independently tracked as #2869: its lexical-name collector skips static initializers. That compiler metadata omission is separate from this interpreter/resolver scope-entry omission. #2806 changes checker environments and cannot repair this runtime entry path. Its retained whole static-block TDZ control contains for (var step of [1]) {}, which activates the existing reservation branch and explains why that interpreter control passes. Existing #2454 concerns class-expression compiler snapshots after initialization.
Ten fresh all-state searches returned 56 unique candidates without a capped result set. Reading the 12 closest full reports and all comments found no focused static-block reservation owner. Closed #2345 covers ordinary-block lexical reservation; #2706 covers classic-global loop-var publication, #2583 named-function self/body scope, and #2659 ordinary function-body var hoisting. This is a separate uncovered static-block entry path.
Exact source SHA-256: 2E7849D963AE498DDC1E62EF34F4624E8A283408A30B0ECAB908DEB312B6C419. Evidence: 2806-nominal-static-tdz-current-proof/baseline-summary.json (B028AAAF9F6F848765EF94140ECC530B84E61A15DC78F60606D3BD75DF96538A), raw results 329B2E221DE36732D930138D3D731A71F9E17D6FA056492098C95986CCC455F5, and static classification B678D4BE21AF5162DDB04C1AAD5141F9250CFDC6A162236C924B203498BC0A14.
Activity