Skip to content

Fix #746: nested namespace shadowing same-named top-level namespace throws in interpreter#803

Open
nickna wants to merge 1 commit into
mainfrom
wrk/nervous-cannon-7bad89
Open

Fix #746: nested namespace shadowing same-named top-level namespace throws in interpreter#803
nickna wants to merge 1 commit into
mainfrom
wrk/nervous-cannon-7bad89

Conversation

@nickna

@nickna nickna commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • GetLocalNamespace added to RuntimeEnvironment — checks only the current scope's _namespaces dict (no chain traversal)
  • ExecuteNamespace changed to use GetLocalNamespace instead of GetNamespace when deciding whether to merge a namespace declaration
  • Test added: NestedNamespace_ShadowsSameNamedTopLevelNamespace (both modes)

Root cause

ExecuteNamespace called _environment.GetNamespace(name), which walks up the full scope chain. When a nested O.A was declared and the global scope already held a top-level namespace A, the chain-walk found the global A and entered the merge path — skipping the else branch that calls _environment.DefineNamespace(name, nsObj).

As a result, namespaceEnvO._values never got an "A" entry. The VariableResolver had correctly pre-computed distance = 2 for the bare A reference inside O.B.f (pointing to O's scope), but GetAt(2, "A") returned RuntimeValue.Undefined because that slot was never written. The subsequent property access on Undefined threw:

Runtime Error: Only instances and objects have properties

The compiled path was already correct — ResolveNamespaceField keys namespace fields by their full dotted path ("O.A" vs "A"), so the collision never occurs there.

Fix

GetLocalNamespace checks _namespaces on the current scope only. Using it in ExecuteNamespace ensures a nested O.A is always treated as a new binding in O's scope rather than a merge into the outer A. Declaration-merging at the same level is unaffected — GetLocalNamespace still finds a previously-defined namespace in the same scope.

Test plan

  • NestedNamespace_ShadowsSameNamedTopLevelNamespace passes in both interpreted and compiled mode (was failing with the runtime error above)
  • All 101 NamespaceTests pass
  • Full suite: 13421 passed, 0 failed

…hrows in interpreter

ExecuteNamespace called _environment.GetNamespace(name), which walks up the
full scope chain. When a nested `O.A` was declared and the global scope
already held a top-level `namespace A`, GetNamespace found the global one and
entered the merge path — skipping the DefineNamespace call that would have
planted "A" in namespaceEnvO._values.

The VariableResolver had correctly pre-computed distance=2 for the bare `A`
reference inside O.B.f (pointing to O's scope), but GetAt(2, "A") returned
Undefined because that slot was never written. The subsequent property access
on Undefined threw "Only instances and objects have properties".

Fix: add GetLocalNamespace (checks _namespaces on the current scope only, no
chain walk) and use it in ExecuteNamespace. Same-level declaration merging is
unaffected — GetLocalNamespace still finds a previously-defined namespace in
the same scope. Compiled mode was already correct via ResolveNamespaceField.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant