Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
95db6ce
Updated CHANGELOG and package.json
hexplus Mar 28, 2026
56080d8
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 28, 2026
7eeec49
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 28, 2026
14a9cd4
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
9487727
ci: use npm install instead of npm ci
hexplus Mar 29, 2026
6b4bd83
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
0b9a0cc
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
0777184
trusted-publisher
hexplus Mar 29, 2026
4d46e82
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
bea9788
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
825a8dc
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
55c4436
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
0d2c7e0
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
8da81e8
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
325ce5d
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Mar 29, 2026
0cad329
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 1, 2026
aea6787
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 4, 2026
00e5e88
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 7, 2026
b10a2c5
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 7, 2026
639eae0
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 9, 2026
405e4fe
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 11, 2026
ee7cf48
Updated main
hexplus Apr 11, 2026
8c77fca
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 11, 2026
da6d752
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 11, 2026
c047837
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 12, 2026
a52fffc
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 12, 2026
43b5675
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 14, 2026
44df880
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 18, 2026
aba311a
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 19, 2026
4bf3286
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Apr 19, 2026
a086428
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus May 29, 2026
e316ae0
Missing update package.json
hexplus May 29, 2026
278bfc6
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus May 29, 2026
08bc9b8
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 1, 2026
7b5557d
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 5, 2026
226ae51
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 5, 2026
0d5c8de
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 12, 2026
b0053ef
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 12, 2026
1b60022
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 26, 2026
24659ad
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 26, 2026
539f29a
Merge branch 'main' of https://github.com/hexplus/SibuJS
hexplus Jun 26, 2026
5e389ee
test: cover duplicate-instance detection in track.ts/batch.ts shims
hexplus Jun 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/reactivity/track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ const _isDev = isDev();
// raw ESM it is undefined, so we fall back to "dev". Only used to enrich the
// multi-instance dev warning.
declare const __SIBU_VERSION__: string | undefined;
// The `__SIBU_VERSION__` branch only runs when a bundler inlined the define; the
// source test runner always takes the "dev" fallback, so that side is excluded.
/* v8 ignore next */
const _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";

interface ReactiveApi {
Expand Down
68 changes: 68 additions & 0 deletions tests/duplicate-instance-source.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";

// ---------------------------------------------------------------------------
// Covers the duplicate-instance DETECTION path on the real source modules.
//
// `tests/duplicate-instance.test.ts` proves cross-instance behavior by bundling
// the core and evaluating it twice — but that runs a bundled copy, so coverage
// instrumentation never credits the source module's "a duplicate loaded" branch
// (the in-process module evaluates exactly once, always taking the first-copy
// path). Here we exercise that branch directly: pre-seed the `globalThis`
// registry as if a first copy had already published its API, then freshly
// import the source module so its resolver takes the duplicate path.
// ---------------------------------------------------------------------------

const REACTIVE_KEY = Symbol.for("sibujs.reactive.v1");
const BATCH_KEY = Symbol.for("sibujs.reactive.batch.v1");

type Registry = Record<symbol, unknown>;

describe("duplicate-instance detection on the source modules", () => {
beforeEach(() => {
vi.resetModules();
});

afterEach(() => {
delete (globalThis as Registry)[REACTIVE_KEY];
delete (globalThis as Registry)[BATCH_KEY];
vi.restoreAllMocks();
});

test("track.ts delegates to the first copy and dev-warns once on a duplicate load", async () => {
// Simulate a first copy of the reactive runtime having published its API.
(globalThis as Registry)[REACTIVE_KEY] = { version: "0.0.0-first", __dupWarned: false };
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});

await import("../src/reactivity/track");

expect(warn).toHaveBeenCalledTimes(1);
expect(String(warn.mock.calls[0][0])).toContain("Multiple instances of the reactive runtime");
// The registry object is stamped so a third copy stays quiet.
expect((globalThis as Record<symbol, { __dupWarned?: boolean }>)[REACTIVE_KEY].__dupWarned).toBe(true);
});

test("track.ts does not warn again when the first copy already warned", async () => {
(globalThis as Registry)[REACTIVE_KEY] = { version: "0.0.0-first", __dupWarned: true };
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});

await import("../src/reactivity/track");

expect(warn).not.toHaveBeenCalled();
});

test("batch.ts re-exports the first copy's functions on a duplicate load", async () => {
const firstBatch = {
batch: <T>(fn: () => T): T => fn(),
enqueueBatchedSignal: () => false,
isBatching: () => false,
};
(globalThis as Registry)[BATCH_KEY] = firstBatch;

const mod = await import("../src/reactivity/batch");

// The duplicate copy delegates to the first copy's functions verbatim.
expect(mod.batch).toBe(firstBatch.batch);
expect(mod.isBatching).toBe(firstBatch.isBatching);
expect(mod.enqueueBatchedSignal).toBe(firstBatch.enqueueBatchedSignal);
});
});
Loading