Skip to content

[patch] Honour IsStatic and IsConstant on JavaScript fields - #157

Merged
matt-edmondson merged 2 commits into
mainfrom
fix/104-javascript-static-fields
Oct 5, 2026
Merged

matt-edmondson merged 2 commits into
mainfrom
fix/104-javascript-static-fields

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #104

Problem

JavaScriptGenerator.GenerateFieldDeclaration wrote every FieldDeclaration as name = value; and never read IsStatic or IsConstant. This broke in two places:

  • Inside a class, a static or constant field became an instance field, so Counter.MAX was undefined.
  • At file or namespace scope, the field was a bare assignment to an undeclared name. That throws ReferenceError when an ES module loads, and creates a global in a classic script.

Change

  • A class body now sends a FieldDeclaration to a new GenerateClassField. It writes static when the field is IsStatic || IsConstant, matching the existing VariableDeclaration-as-field path.
  • Outside a class, GenerateFieldDeclaration writes const for a constant with an initializer and let otherwise. This is the rule GenerateVariableDeclaration already uses for locals, since const needs an initializer.
  • Both paths share a single WriteField helper.

Tests

New tests in JavaScriptGeneratorTests:

  • A text test checks that a static field and a constant field in a class are written static, and that an instance field is not.
  • A text test checks file-scope fields: const Limit = 10;, let total = 0;, and let Pending; for an uninitialized constant.
  • A Node.js toolchain test loads the issue's repro as an ES module. It checks Counter.MAX === 99, that MAX is not on instances, and that Limit does not leak onto globalThis. It is inconclusive when node is not on the path.

With the generator change reverted, all three tests fail. The full suite passes: 1057/1057.

This branch is independent of #156 (the super() fix for #103). Both touch the class-body switch in GenerateClassDeclaration, on adjacent lines. Whichever merges second may need a trivial rebase.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N47Hdpq8iSMutiKdDS81pa


Generated by Claude Code

The JavaScript generator wrote every FieldDeclaration as `name = value;`.
Inside a class, a static or constant field became an ordinary instance field,
so `Counter.MAX` was undefined. At file or namespace scope, the declaration
was a bare assignment to an undeclared name, which throws ReferenceError when
an ES module loads and leaks a global in a script.

A class field is now written `static` when it is static or constant, matching
the VariableDeclaration path. A field outside a class is declared `const`
when it is a constant with an initializer, and `let` otherwise, the same way
locals are.

Fixes #104

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N47Hdpq8iSMutiKdDS81pa
…atic-fields

# Conflicts:
#	Coder.Test/Languages/JavaScriptGeneratorTests.cs
@sonarqubecloud

sonarqubecloud Bot commented Oct 5, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 04ea4f8 into main Oct 5, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/104-javascript-static-fields branch October 5, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant