Skip to content

fix(scripts): register nameless scripts under their verbatim class name#8844

Merged
mvaligursky merged 1 commit into
mainfrom
mv-registerscript-verbatim-name
Jun 4, 2026
Merged

fix(scripts): register nameless scripts under their verbatim class name#8844
mvaligursky merged 1 commit into
mainfrom
mv-registerscript-verbatim-name

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

Summary

Since 2.19.3, registering an ES6 script class without an explicit name and referencing it by the class name stopped working — the script silently fails to attach. Reported by a user with "hundreds of scripts" extending pc.ScriptType and registered via pc.registerScript(Class).

Root cause

#8831 changed the name registerScript/createScript derive when no explicit name is given:

// before (≤ 2.19.2): verbatim class name → "PlayerController"
name = name || script.__name || ScriptType.__getScriptName(script);
// after (2.19.3, #8831): lowerCamelCase → "playerController"
name = name || getScriptRegistryName(script);

The registry is keyed by that name, so an entity referencing the script as PlayerController no longer resolves it. Passing an explicit name works, but that's painful across hundreds of scripts.

Fix

Restore the verbatim class-name fallback in registerScript only:

name = name ||
    (Object.prototype.hasOwnProperty.call(script, '__name') && script.__name) ||
    getScriptName(script); // own scriptName, else verbatim class name
  • Own-property only, so Fix ESM script registration by name and subclass name collision #8831's two real fixes are preserved: the ESM static scriptName class-field case and the subclass-name-collision case.
  • Scoped to registerScript. ScriptComponent.create, ScriptRegistry.add and the asset loader still use the lowerCamelCase getScriptRegistryName. The editor and asset pipeline always pass an explicit name, so they're unaffected — only code-driven nameless registerScript(Class) changes (the regressed path).

This was chosen over a dual-name alias (previous draft, #8840) to avoid the long-term maintenance cost and edge cases of registering each script under two names.

Note on create(Class)

create() is unchanged. For the register-then-reference flow it stays consistent: registerScript(Class) sets __name to the verbatim name, and create() reuses an existing own __name rather than recomputing. lowerCamelCase derivation in create(Class) only applies to a class that was never registered — long-standing behavior.

Tests

  • Updated the two tests that asserted the lowerCamelCase fallback to assert verbatim.
  • Added a regression test: registerScript(class PlayerController)entity.script.create('PlayerController') attaches the instance.
  • Full suite: 1749 passing.

🤖 Generated with Claude Code

#8831 (2.19.3) changed the name a script is registered under when no
explicit name is passed to `registerScript(Class)` - from the verbatim
class name (e.g. `PlayerController`) to the lowerCamelCase form
(`playerController`). Projects that register ES6 classes this way and
reference them by their class name then failed to resolve the script, so
it never attached.

Restore the pre-2.19.3 behaviour: `registerScript` falls back to the
verbatim class name (still honouring an explicit name, an own `__name`, or
an own `scriptName`). Resolution stays own-property only, so #8831's
subclass-collision and ESM `scriptName`-field fixes are preserved.

`ScriptComponent.create`, `ScriptRegistry.add` and the asset loader keep
using the lowerCamelCase `getScriptRegistryName`, so the editor and asset
pipeline (which always pass an explicit name) are unaffected - the change
is scoped to code-driven nameless `registerScript(Class)` calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression introduced in 2.19.3 where pc.registerScript(SomeClass) (with no explicit name) no longer allowed scripts to be referenced/attached by their verbatim ES6 class name, causing script attachment to silently fail in class-name–based projects.

Changes:

  • Updates registerScript to fall back to the verbatim class name (own __name → own scriptName → verbatim class name) instead of the lowerCamelCase registry fallback.
  • Adjusts existing tests to assert verbatim-name registration for nameless registerScript usage.
  • Adds a regression test ensuring entity.script.create('ClassName') attaches correctly after nameless registerScript(ClassName).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/framework/script/script-create.js Restores verbatim class-name fallback for nameless registerScript while preserving own-property name resolution.
test/framework/script/script-registry.test.mjs Updates expectations and adds coverage for class-name attachment after nameless registration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mvaligursky mvaligursky merged commit d470dd1 into main Jun 4, 2026
9 checks passed
@mvaligursky mvaligursky deleted the mv-registerscript-verbatim-name branch June 4, 2026 15:01
mvaligursky added a commit that referenced this pull request Jun 4, 2026
…me (#8844)

#8831 (2.19.3) changed the name a script is registered under when no
explicit name is passed to `registerScript(Class)` - from the verbatim
class name (e.g. `PlayerController`) to the lowerCamelCase form
(`playerController`). Projects that register ES6 classes this way and
reference them by their class name then failed to resolve the script, so
it never attached.

Restore the pre-2.19.3 behaviour: `registerScript` falls back to the
verbatim class name (still honouring an explicit name, an own `__name`, or
an own `scriptName`). Resolution stays own-property only, so #8831's
subclass-collision and ESM `scriptName`-field fixes are preserved.

`ScriptComponent.create`, `ScriptRegistry.add` and the asset loader keep
using the lowerCamelCase `getScriptRegistryName`, so the editor and asset
pipeline (which always pass an explicit name) are unaffected - the change
is scoped to code-driven nameless `registerScript(Class)` calls.

Co-authored-by: Martin Valigursky <mvaligursky@snapchat.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants