Skip to content

move static define() block to end of class body#39

Merged
bemky merged 2 commits into
mainfrom
move-define-to-end
May 26, 2026
Merged

move static define() block to end of class body#39
bemky merged 2 commits into
mainfrom
move-define-to-end

Conversation

@bemky
Copy link
Copy Markdown
Owner

@bemky bemky commented May 7, 2026

Summary

Follow-up to #37. Even with the cache-invalidation fix in scanPrototypesFor, the first instance constructed by an upgrade-during-class-init still ends up with empty static metadata — the cache no longer poisons subsequent instances, but that one early instance is broken. This change eliminates the timing window entirely.

customElements.define synchronously upgrades any pre-existing matching elements in the DOM, which runs the constructor. The constructor reads assignableAttributes, events, bindMethods, etc., and several components also touch class-level singletons like static observer = new ResizeObserver(...). Calling define() mid-class-body — as we did everywhere, right after static tagName = ... — let that upgrade fire before the rest of the static field initializers had run.

Move every static { this.define() } block to be the last static in its class so registration always happens after the class is fully initialized. Document the requirement on KompElement.define's JSDoc and update the FormField example.

Verified with a smoke test: parsing <komp-dropzone enabled> into the DOM and then importing the module now correctly resolves all three keys of assignableAttributes (enabled, dragHereOverlay, dragOverOverlay) on the upgraded instance.

Drops a leftover empty if (!window.customElements.get('komp-floater')) {} block at the bottom of floater.js (looks like a leftover from a previous registration refactor).

Test plan

  • npm test — 33 passing
  • npm run docs builds without warnings
  • Smoke test: HTML-first <komp-dropzone> resolves full assignableAttributes after import
  • Existing demos render unchanged

🤖 Generated with Claude Code

bemky and others added 2 commits May 7, 2026 11:41
`customElements.define` synchronously upgrades any pre-existing matching
elements in the DOM, which runs the constructor. The constructor reads
static metadata (`assignableAttributes`, `events`, `bindMethods`) and
may also touch class-level singletons like `static observer = new
ResizeObserver(...)`. Calling `define()` mid-class-body — e.g. right
after `static tagName = ...` as we did everywhere — let that upgrade
fire before the rest of the static field initializers had run, leaving
the upgraded instance with empty `assignableAttributes` and risking
errors on missing singletons.

Move every `static { this.define() }` block to be the last static in
its class. Also document the requirement on `KompElement.define`'s
JSDoc and update `FormField`'s example. Drops a leftover empty
`if (!window.customElements.get('komp-floater'))` block in floater.js.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bemky bemky merged commit f7f7444 into main May 26, 2026
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