Skip to content

Feature/reactive runtime resilient to duplicate module instances#36

Merged
hexplus merged 39 commits into
mainfrom
feature/reactive-runtime-resilient-to-duplicate-module-instances
Jun 26, 2026
Merged

Feature/reactive runtime resilient to duplicate module instances#36
hexplus merged 39 commits into
mainfrom
feature/reactive-runtime-resilient-to-duplicate-module-instances

Conversation

@hexplus

@hexplus hexplus commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Description

Makes the reactive runtime resilient to duplicate module instances.

When a bundler loads the reactive-core module more than once on a page — which
routinely happens under dependency pre-bundling (Vite optimizeDeps / esbuild,
where the same internal chunk is served twice: once with an ?v=<hash> query
and once raw) — reactivity silently died. The two copies formed independent
reactive "worlds": a signal() write notified one copy's queue while a reactive
binding had tracked itself through the other's, so the binding stopped updating
with no error thrown. Raw ESM usage was never affected.

This PR fixes it with a first-copy-wins, share-the-functions registry: the
first-loaded copy publishes its implementations on a globalThis registry
(keyed by a versioned Symbol.for), and every later copy re-exports the first
copy's functions. Exactly one copy's code runs, so all copies funnel through a
single source of truth — and because the running code is byte-identical to the
single-instance build, there's no hot-path indirection and no perf change.
(An earlier attempt that shared the state regressed binding/effect creation by
~70%; sharing the functions avoids that entirely — confirmed by interleaved
cold + warm benchmarks.)

Also adds a one-time, dev-only warning when a duplicate runtime is detected,
explaining how to de-duplicate (optimizeDeps.exclude / resolve.dedupe);
stripped from production builds.

Changes: src/reactivity/track-core.ts (new — implementations + state),
src/reactivity/track.ts (rewritten — registry shim), src/reactivity/batch.ts
(same pattern), src/core/signals/derived.ts (uses isTrackingSuspended()),
new tests/duplicate-instance.test.ts. Version 3.3.03.3.1, CHANGELOG
entry, and docs-site version badges bumped (en/es/zh).

Related Issue

Closes #

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • I have read CONTRIBUTING.md
  • My code builds without errors
  • I have tested my changes
  • I have updated documentation if needed

hexplus added 30 commits March 28, 2026 15:11
@hexplus hexplus merged commit f917a8e into main Jun 26, 2026
1 check passed
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