Skip to content

module-level const/let reads before the declaration don't throw (no TDZ at module level) #11826

Description

@proggeramlug

In a compound member assignment whose base is a const binding still in its temporal dead zone, perry evaluates the computed key first and then throws a TypeError. Per spec, the base is evaluated first, so reading the binding throws a ReferenceError before the key expression runs.

Repro (main 34acf64e, v0.5.1656, Linux x86_64):

let calls = 0;
function f(): string { calls++; return "a"; }
try {
  tdz[f()] += 1;
  console.log("no throw");
} catch (e: any) {
  console.log(e.constructor.name, "f calls:", calls);
}
const tdz: any = { a: 1 };
runtime output
node ReferenceError f calls: 0
bun ReferenceError f calls: 0
perry TypeError f calls: 1

Two differences: the key's side effect (f()) runs when it shouldn't, and the error type is wrong. The TDZ check on the base is either skipped or ordered after the key spill in the compound-assignment lowering (hoist_compound_member_assign, crates/perry-hir/src/lower/expr_assign.rs).

Found while building #11825, which doesn't change this behaviour: that PR keeps the base temp, ahead of the key, whenever the key is spilled.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions