Skip to content

Fix transpile crash synthesizing implicit constructor with a class-typed param - #1769

Draft
markwpearce wants to merge 1 commit into
v1from
fix-implicit-ctor-namespace-crash
Draft

Fix transpile crash synthesizing implicit constructor with a class-typed param#1769
markwpearce wants to merge 1 commit into
v1from
fix-implicit-ctor-namespace-crash

Conversation

@markwpearce

Copy link
Copy Markdown
Collaborator

Summary

  • A subclass with no explicit constructor gets one synthesized from its parent's constructor signature (ClassStatement.getTranspiledClassBody). The synthesized parameter list was built by deep-cloning the parent's FunctionParameterExpression nodes via .clone() - but the clone is detached from the AST (no .parent), so a class/enum-typed parameter's TypeExpression can no longer resolve its type by symbol lookup at transpile time. This crashes in TypeExpression.transpile() on exprType.toTypeString() when exprType comes back undefined.
  • Confirmed via the full CLI build pipeline that this happens even for a same-namespace parent/subclass, not only across a namespace boundary as originally suspected in the issue - any custom (non-built-in) type on an inherited, implicitly-constructed parameter crashes. Primitive types are unaffected only because TypeExpression.transpile() short-circuits on the raw type name before ever calling getType().
  • Fix: resolve each such parameter's type once, while the original (still AST-attached) parameter can still resolve it via its real symbol table, and bake the fully-qualified name + resolved type directly into the clone via a small ResolvedTypeExpression that bypasses symbol-table resolution entirely (so it works regardless of parenting or namespace).

Fixes #1767

Test plan

  • Verified against the exact repro from the issue via the full bsc CLI pipeline (both cross-namespace and same-namespace variants) - no crash, correct output
  • Added regression tests in src/files/BrsFile.Class.spec.ts covering both cross-namespace and same-namespace implicit-constructor inheritance of a class-typed param
  • Full test suite passes (npm run test:nocover) - 4277 passing, 0 failing
  • npm run lint passes

🤖 Generated with Claude Code

…ped param

A subclass with no explicit constructor gets one synthesized from its
parent's constructor signature. The synthesized parameter list was built
by deep-cloning the parent's FunctionParameterExpression nodes, but the
clone is detached from the AST (no parent), so a class/enum-typed
parameter's TypeExpression can no longer resolve its type by symbol
lookup at transpile time - crashing in TypeExpression.transpile() on
`exprType.toTypeString()` when exprType comes back undefined. This
happens even for a same-namespace parent/subclass, not just across a
namespace boundary as originally suspected - any custom type on an
inherited, implicitly-constructed parameter crashes, since primitive
types are unaffected only because they short-circuit before ever calling
getType().

Resolve each such parameter's type once, while the original (still
attached) parameter can still resolve it, and bake the fully-qualified
name and resolved type directly into the clone via a small
ResolvedTypeExpression that bypasses symbol-table resolution entirely.

Fixes #1767

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@markwpearce markwpearce added this to the v1.0.0 milestone Jul 30, 2026
@markwpearce
markwpearce marked this pull request as draft July 30, 2026 16:55
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