@reckona/mreact-reactive-core 0.0.153 → 0.0.154
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/batch.d.ts.map +1 -1
- package/dist/batch.js +3 -0
- package/dist/batch.js.map +1 -1
- package/dist/cell.d.ts +1 -0
- package/dist/cell.d.ts.map +1 -1
- package/dist/cell.js +72 -33
- package/dist/cell.js.map +1 -1
- package/dist/computed.d.ts.map +1 -1
- package/dist/computed.js +4 -5
- package/dist/computed.js.map +1 -1
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +2 -0
- package/dist/scheduler.js.map +1 -1
- package/dist/state.d.ts +1 -2
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js.map +1 -1
- package/dist/tracking.d.ts +1 -0
- package/dist/tracking.d.ts.map +1 -1
- package/dist/tracking.js +40 -49
- package/dist/tracking.js.map +1 -1
- package/package.json +1 -1
- package/src/batch.ts +3 -0
- package/src/cell.ts +100 -40
- package/src/computed.ts +4 -5
- package/src/scheduler.ts +2 -0
- package/src/state.ts +5 -2
- package/src/tracking.ts +46 -50
package/dist/batch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAKA,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAcvC;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAcxE"}
|
package/dist/batch.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { runtimeState } from "./state.js";
|
|
2
|
+
import { invalidateDevtoolsWriteCache } from "./cell.js";
|
|
2
3
|
import { schedulePendingFlush } from "./scheduler.js";
|
|
3
4
|
import { flushPendingComputed } from "./tracking.js";
|
|
4
5
|
export function batch(fn) {
|
|
6
|
+
invalidateDevtoolsWriteCache();
|
|
5
7
|
runtimeState.batchDepth += 1;
|
|
6
8
|
try {
|
|
7
9
|
return fn();
|
|
@@ -15,6 +17,7 @@ export function batch(fn) {
|
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
export async function batchAsync(fn) {
|
|
20
|
+
invalidateDevtoolsWriteCache();
|
|
18
21
|
runtimeState.batchDepth += 1;
|
|
19
22
|
try {
|
|
20
23
|
return await fn();
|
package/dist/batch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,UAAU,KAAK,CAAI,EAAW;IAClC,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;QAE7B,IAAI,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAClC,oBAAoB,EAAE,CAAC;YACvB,oBAAoB,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,EAAwB;IAC1D,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;QAE7B,IAAI,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAClC,oBAAoB,EAAE,CAAC;YACvB,oBAAoB,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { runtimeState } from \"./state.js\";\nimport { schedulePendingFlush } from \"./scheduler.js\";\nimport { flushPendingComputed } from \"./tracking.js\";\n\nexport function batch<T>(fn: () => T): T {\n runtimeState.batchDepth += 1;\n\n try {\n return fn();\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n flushPendingComputed();\n schedulePendingFlush();\n }\n }\n}\n\nexport async function batchAsync<T>(fn: () => Promise<T> | T): Promise<T> {\n runtimeState.batchDepth += 1;\n\n try {\n return await fn();\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n flushPendingComputed();\n schedulePendingFlush();\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,UAAU,KAAK,CAAI,EAAW;IAClC,4BAA4B,EAAE,CAAC;IAC/B,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;QAE7B,IAAI,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAClC,oBAAoB,EAAE,CAAC;YACvB,oBAAoB,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,EAAwB;IAC1D,4BAA4B,EAAE,CAAC;IAC/B,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;QAE7B,IAAI,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAClC,oBAAoB,EAAE,CAAC;YACvB,oBAAoB,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { runtimeState } from \"./state.js\";\nimport { invalidateDevtoolsWriteCache } from \"./cell.js\";\nimport { schedulePendingFlush } from \"./scheduler.js\";\nimport { flushPendingComputed } from \"./tracking.js\";\n\nexport function batch<T>(fn: () => T): T {\n invalidateDevtoolsWriteCache();\n runtimeState.batchDepth += 1;\n\n try {\n return fn();\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n flushPendingComputed();\n schedulePendingFlush();\n }\n }\n}\n\nexport async function batchAsync<T>(fn: () => Promise<T> | T): Promise<T> {\n invalidateDevtoolsWriteCache();\n runtimeState.batchDepth += 1;\n\n try {\n return await fn();\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n flushPendingComputed();\n schedulePendingFlush();\n }\n }\n}\n"]}
|
package/dist/cell.d.ts
CHANGED
package/dist/cell.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell.d.ts","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cell.d.ts","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AA4BvC,wBAAgB,4BAA4B,IAAI,IAAI,CAInD;AAqED,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAiB3C"}
|
package/dist/cell.js
CHANGED
|
@@ -1,44 +1,83 @@
|
|
|
1
|
-
import { notifySubscribers, trackSource } from "./tracking.js";
|
|
1
|
+
import { notifySubscribers, sourceSubscriberCount, trackSource } from "./tracking.js";
|
|
2
2
|
const clientDevtoolsDisabled = typeof __MREACT_CLIENT_DEVTOOLS__ !== "undefined" &&
|
|
3
3
|
__MREACT_CLIENT_DEVTOOLS__ === false;
|
|
4
|
+
// Write-path devtools cache: `undefined` = not sampled yet, `null` = sampled
|
|
5
|
+
// and absent, object = sampled and attached. The no-devtools write fast path
|
|
6
|
+
// is a single module-local null comparison instead of a globalThis property
|
|
7
|
+
// walk per write. A late attach is observed at the next batch or flush
|
|
8
|
+
// boundary (see invalidateDevtoolsWriteCache callers); a detach or hook swap
|
|
9
|
+
// is observed on the next write because the emit path revalidates identity.
|
|
10
|
+
let cachedDevtoolsHook = clientDevtoolsDisabled
|
|
11
|
+
? null
|
|
12
|
+
: undefined;
|
|
13
|
+
export function invalidateDevtoolsWriteCache() {
|
|
14
|
+
if (!clientDevtoolsDisabled) {
|
|
15
|
+
cachedDevtoolsHook = undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function resolveDevtoolsHook() {
|
|
19
|
+
const hook = globalThis.__mreactDevtools;
|
|
20
|
+
const resolved = hook !== undefined && typeof hook.emit === "function" ? hook : null;
|
|
21
|
+
cachedDevtoolsHook = resolved;
|
|
22
|
+
return resolved;
|
|
23
|
+
}
|
|
24
|
+
function emitCellSetEvent(source, previous, value) {
|
|
25
|
+
// Cold path: only reached while a devtools hook is (or was) attached, or on
|
|
26
|
+
// the first write after a cache invalidation. Revalidate against the live
|
|
27
|
+
// global so a disposed or swapped hook never receives stale events.
|
|
28
|
+
const live = globalThis.__mreactDevtools;
|
|
29
|
+
const hook = cachedDevtoolsHook !== undefined && cachedDevtoolsHook === live
|
|
30
|
+
? cachedDevtoolsHook
|
|
31
|
+
: resolveDevtoolsHook();
|
|
32
|
+
if (hook === null) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const emit = hook.emit;
|
|
36
|
+
if (typeof emit !== "function") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
emit.call(hook, {
|
|
40
|
+
package: "@reckona/mreact-reactive-core",
|
|
41
|
+
previous,
|
|
42
|
+
subscribers: sourceSubscriberCount(source),
|
|
43
|
+
timestamp: Date.now(),
|
|
44
|
+
type: "reactive:cell:set",
|
|
45
|
+
value,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// One shared write function keeps the hot store/notify sequence in a single
|
|
49
|
+
// optimizable function instead of a fresh fat closure per cell.
|
|
50
|
+
function writeCellValue(state, next) {
|
|
51
|
+
const previous = state.value;
|
|
52
|
+
const resolved = typeof next === "function" ? next(previous) : next;
|
|
53
|
+
if (Object.is(previous, resolved)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
state.value = resolved;
|
|
57
|
+
// clientDevtoolsDisabled folds to true under the client build define, which
|
|
58
|
+
// makes this branch statically dead so bundlers drop the emit path (and its
|
|
59
|
+
// globalThis.__mreactDevtools references) from production client bundles.
|
|
60
|
+
if (!clientDevtoolsDisabled && cachedDevtoolsHook !== null) {
|
|
61
|
+
emitCellSetEvent(state.source, previous, resolved);
|
|
62
|
+
}
|
|
63
|
+
if (state.source.subscribers !== null) {
|
|
64
|
+
notifySubscribers(state.source);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
4
67
|
export function cell(initial) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
68
|
+
const state = {
|
|
69
|
+
source: {
|
|
70
|
+
subscribers: null,
|
|
71
|
+
},
|
|
72
|
+
value: initial,
|
|
8
73
|
};
|
|
9
74
|
return {
|
|
10
75
|
get() {
|
|
11
|
-
trackSource(source);
|
|
12
|
-
return
|
|
76
|
+
trackSource(state.source);
|
|
77
|
+
return state.value;
|
|
13
78
|
},
|
|
14
79
|
set(next) {
|
|
15
|
-
|
|
16
|
-
if (Object.is(current, resolved)) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (clientDevtoolsDisabled) {
|
|
20
|
-
current = resolved;
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
const devtools = globalThis.__mreactDevtools;
|
|
24
|
-
const emit = devtools?.emit;
|
|
25
|
-
if (typeof emit !== "function") {
|
|
26
|
-
current = resolved;
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
const previous = current;
|
|
30
|
-
current = resolved;
|
|
31
|
-
emit.call(devtools, {
|
|
32
|
-
package: "@reckona/mreact-reactive-core",
|
|
33
|
-
previous,
|
|
34
|
-
subscribers: source.subscribers.size,
|
|
35
|
-
timestamp: Date.now(),
|
|
36
|
-
type: "reactive:cell:set",
|
|
37
|
-
value: resolved,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
notifySubscribers(source);
|
|
80
|
+
writeCellValue(state, next);
|
|
42
81
|
},
|
|
43
82
|
};
|
|
44
83
|
}
|
package/dist/cell.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell.js","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"cell.js","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Cell } from \"./types.js\";\nimport type { Source } from \"./state.js\";\nimport { notifySubscribers, sourceSubscriberCount, trackSource } from \"./tracking.js\";\n\ndeclare const __MREACT_CLIENT_DEVTOOLS__: boolean | undefined;\n\nconst clientDevtoolsDisabled =\n typeof __MREACT_CLIENT_DEVTOOLS__ !== \"undefined\" &&\n __MREACT_CLIENT_DEVTOOLS__ === false;\n\ninterface DevtoolsHook {\n emit?: ((event: Record<string, unknown>) => void) | undefined;\n}\n\ntype GlobalWithDevtools = typeof globalThis & {\n __mreactDevtools?: DevtoolsHook | undefined;\n};\n\n// Write-path devtools cache: `undefined` = not sampled yet, `null` = sampled\n// and absent, object = sampled and attached. The no-devtools write fast path\n// is a single module-local null comparison instead of a globalThis property\n// walk per write. A late attach is observed at the next batch or flush\n// boundary (see invalidateDevtoolsWriteCache callers); a detach or hook swap\n// is observed on the next write because the emit path revalidates identity.\nlet cachedDevtoolsHook: DevtoolsHook | null | undefined = clientDevtoolsDisabled\n ? null\n : undefined;\n\nexport function invalidateDevtoolsWriteCache(): void {\n if (!clientDevtoolsDisabled) {\n cachedDevtoolsHook = undefined;\n }\n}\n\nfunction resolveDevtoolsHook(): DevtoolsHook | null {\n const hook = (globalThis as GlobalWithDevtools).__mreactDevtools;\n const resolved = hook !== undefined && typeof hook.emit === \"function\" ? hook : null;\n cachedDevtoolsHook = resolved;\n return resolved;\n}\n\nfunction emitCellSetEvent<T>(source: Source, previous: T, value: T): void {\n // Cold path: only reached while a devtools hook is (or was) attached, or on\n // the first write after a cache invalidation. Revalidate against the live\n // global so a disposed or swapped hook never receives stale events.\n const live = (globalThis as GlobalWithDevtools).__mreactDevtools;\n const hook =\n cachedDevtoolsHook !== undefined && cachedDevtoolsHook === live\n ? cachedDevtoolsHook\n : resolveDevtoolsHook();\n\n if (hook === null) {\n return;\n }\n\n const emit = hook.emit;\n\n if (typeof emit !== \"function\") {\n return;\n }\n\n emit.call(hook, {\n package: \"@reckona/mreact-reactive-core\",\n previous,\n subscribers: sourceSubscriberCount(source),\n timestamp: Date.now(),\n type: \"reactive:cell:set\",\n value,\n });\n}\n\ninterface CellState<T> {\n value: T;\n readonly source: Source;\n}\n\n// One shared write function keeps the hot store/notify sequence in a single\n// optimizable function instead of a fresh fat closure per cell.\nfunction writeCellValue<T>(state: CellState<T>, next: T | ((prev: T) => T)): void {\n const previous = state.value;\n const resolved =\n typeof next === \"function\" ? (next as (prev: T) => T)(previous) : next;\n\n if (Object.is(previous, resolved)) {\n return;\n }\n\n state.value = resolved;\n\n // clientDevtoolsDisabled folds to true under the client build define, which\n // makes this branch statically dead so bundlers drop the emit path (and its\n // globalThis.__mreactDevtools references) from production client bundles.\n if (!clientDevtoolsDisabled && cachedDevtoolsHook !== null) {\n emitCellSetEvent(state.source, previous, resolved);\n }\n\n if (state.source.subscribers !== null) {\n notifySubscribers(state.source);\n }\n}\n\nexport function cell<T>(initial: T): Cell<T> {\n const state: CellState<T> = {\n source: {\n subscribers: null,\n },\n value: initial,\n };\n\n return {\n get(): T {\n trackSource(state.source);\n return state.value;\n },\n set(next: T | ((prev: T) => T)): void {\n writeCellValue(state, next);\n },\n };\n}\n"]}
|
package/dist/computed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC1C;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,EAAE,EAAE,MAAM,CAAC,EACX,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GACjD,YAAY,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC1C;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,EAAE,EAAE,MAAM,CAAC,EACX,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GACjD,YAAY,CAAC,CAAC,CAAC,CAyIjB"}
|
package/dist/computed.js
CHANGED
|
@@ -7,7 +7,7 @@ export function computed(fn, options) {
|
|
|
7
7
|
let dirty = true;
|
|
8
8
|
const equals = typeof options === "function" ? options : (options?.equals ?? Object.is);
|
|
9
9
|
const source = {
|
|
10
|
-
subscribers:
|
|
10
|
+
subscribers: null,
|
|
11
11
|
};
|
|
12
12
|
const computation = {
|
|
13
13
|
id: runtimeState.nextComputationId,
|
|
@@ -16,12 +16,12 @@ export function computed(fn, options) {
|
|
|
16
16
|
queued: false,
|
|
17
17
|
markDirty() {
|
|
18
18
|
if (dirty) {
|
|
19
|
-
if (source.subscribers
|
|
19
|
+
if (source.subscribers === null || computation.queued) {
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
dirty = true;
|
|
24
|
-
if (source.subscribers
|
|
24
|
+
if (source.subscribers !== null) {
|
|
25
25
|
if (runtimeState.notificationDepth > 0) {
|
|
26
26
|
computation.queued = true;
|
|
27
27
|
runtimeState.pendingComputed.add(computation);
|
|
@@ -44,8 +44,7 @@ export function computed(fn, options) {
|
|
|
44
44
|
computation.queued = false;
|
|
45
45
|
runtimeState.pendingComputed.delete(computation);
|
|
46
46
|
cleanupDeps(computation);
|
|
47
|
-
source.subscribers
|
|
48
|
-
source.singleSubscriber = undefined;
|
|
47
|
+
source.subscribers = null;
|
|
49
48
|
},
|
|
50
49
|
};
|
|
51
50
|
runtimeState.nextComputationId += 1;
|
package/dist/computed.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed.js","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,WAAW,GACZ,MAAM,eAAe,CAAC;AASvB,MAAM,UAAU,QAAQ,CACtB,EAAW,EACX,OAAkD;IAElD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,KAAQ,CAAC;IACb,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,MAAM,MAAM,GAAG,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;IAExF,MAAM,MAAM,GAAW;QACrB,WAAW,EAAE,IAAI
|
|
1
|
+
{"version":3,"file":"computed.js","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveComputation, Source } from \"./state.js\";\nimport { schedulePendingFlush } from \"./scheduler.js\";\nimport { runtimeState } from \"./state.js\";\nimport {\n cleanupAddedDeps,\n cleanupDeps,\n cleanupUntrackedDeps,\n nextTrackingVersionFor,\n notifySubscribers,\n preserveIncrementalTracking,\n trackIncrementalSource,\n trackSource,\n} from \"./tracking.js\";\nimport type { ReadonlyCell } from \"./types.js\";\n\nexport type ComputedEquality<T> = (previous: T, next: T) => boolean;\n\nexport interface ComputedOptions<T> {\n equals?: ComputedEquality<T> | undefined;\n}\n\nexport function computed<T>(\n fn: () => T,\n options?: ComputedOptions<T> | ComputedEquality<T>,\n): ReadonlyCell<T> {\n let hasValue = false;\n let value: T;\n let dirty = true;\n const equals = typeof options === \"function\" ? options : (options?.equals ?? Object.is);\n\n const source: Source = {\n subscribers: null,\n };\n\n const computation: ReactiveComputation = {\n id: runtimeState.nextComputationId,\n deps: new Set(),\n disposed: false,\n queued: false,\n markDirty() {\n if (dirty) {\n if (source.subscribers === null || computation.queued) {\n return;\n }\n }\n\n dirty = true;\n\n if (source.subscribers !== null) {\n if (runtimeState.notificationDepth > 0) {\n computation.queued = true;\n runtimeState.pendingComputed.add(computation);\n return;\n }\n\n publishIfChanged();\n }\n },\n run() {\n publishIfChanged();\n },\n trackSource(source) {\n trackIncrementalSource(source, computation);\n },\n dispose() {\n if (computation.disposed) {\n return;\n }\n\n computation.disposed = true;\n computation.queued = false;\n runtimeState.pendingComputed.delete(computation);\n cleanupDeps(computation);\n source.subscribers = null;\n },\n };\n\n runtimeState.nextComputationId += 1;\n\n function publishIfChanged(): void {\n const previousHasValue = hasValue;\n const previousValue = value;\n\n try {\n const nextValue = recompute();\n\n if (!previousHasValue || !equals(previousValue, nextValue)) {\n notifySubscribers(source);\n }\n } catch {\n runtimeState.batchDepth += 1;\n\n try {\n notifySubscribers(source);\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n schedulePendingFlush();\n }\n }\n }\n }\n\n function recompute(): T {\n if (!dirty && hasValue) {\n return value;\n }\n\n const previousTracker = runtimeState.activeTracker;\n const previousDepsSize = computation.deps.size;\n const nextTrackingVersion = nextTrackingVersionFor(computation);\n\n computation.trackingAddedDeps = [];\n computation.trackingCount = 0;\n computation.trackingVersion = nextTrackingVersion;\n runtimeState.activeTracker = computation;\n\n try {\n const nextValue = fn();\n\n const addedDeps = computation.trackingAddedDeps;\n const trackedCount = computation.trackingCount ?? 0;\n\n if (trackedCount !== previousDepsSize || (addedDeps?.length ?? 0) > 0) {\n cleanupUntrackedDeps(computation, nextTrackingVersion);\n }\n\n value = nextValue;\n hasValue = true;\n dirty = false;\n\n return value;\n } catch (error) {\n cleanupAddedDeps(computation);\n dirty = true;\n\n throw error;\n } finally {\n computation.trackingAddedDeps = undefined;\n computation.trackingCount = undefined;\n computation.trackingTouchedDeps = undefined;\n runtimeState.activeTracker = previousTracker;\n }\n }\n\n return {\n get(): T {\n trackSource(source);\n\n if (dirty) {\n const activeTracker = runtimeState.activeTracker;\n\n if (activeTracker !== null && activeTracker !== computation) {\n preserveIncrementalTracking(activeTracker);\n }\n }\n\n return recompute();\n },\n };\n}\n"]}
|
package/dist/scheduler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACnC;AAqBD,wBAAgB,YAAY,CAAC,aAAa,EAAE,SAAS,GAAG,MAAM,IAAI,CAOjE;AAED,wBAAgB,6BAA6B,IAAI,IAAI,CAQpD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAkBvE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAiB3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAqC9C"}
|
package/dist/scheduler.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { invalidateDevtoolsWriteCache } from "./cell.js";
|
|
1
2
|
import { runtimeState } from "./state.js";
|
|
2
3
|
const defaultScheduler = {
|
|
3
4
|
schedule(flush) {
|
|
@@ -66,6 +67,7 @@ export function flushQueuedComputations() {
|
|
|
66
67
|
if (flushing) {
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
70
|
+
invalidateDevtoolsWriteCache();
|
|
69
71
|
scheduled = false;
|
|
70
72
|
flushing = true;
|
|
71
73
|
let firstError;
|
package/dist/scheduler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { runtimeState, type ReactiveComputation } from \"./state.js\";\n\nexport interface Scheduler {\n schedule(flush: () => void): void;\n}\n\nconst defaultScheduler: Scheduler = {\n schedule(flush) {\n if (typeof queueMicrotask === \"function\") {\n queueMicrotask(flush);\n return;\n }\n\n void Promise.resolve().then(flush);\n },\n};\n\nlet scheduler = defaultScheduler;\nlet queue: ReactiveComputation[] = [];\nlet lastQueuedComputationId = -1;\nlet queueRequiresSort = false;\nlet scheduled = false;\nlet flushing = false;\nconst maxFlushIterations = 100;\n\nexport function setScheduler(nextScheduler: Scheduler): () => void {\n const previous = scheduler;\n scheduler = nextScheduler;\n\n return () => {\n scheduler = previous;\n };\n}\n\nexport function resetSchedulerStateForTesting(): void {\n for (const computation of queue) {\n computation.queued = false;\n }\n\n clearQueue();\n scheduled = false;\n flushing = false;\n}\n\nexport function queueComputation(computation: ReactiveComputation): void {\n if (computation.disposed || computation.queued) {\n return;\n }\n\n if (computation.id < lastQueuedComputationId) {\n queueRequiresSort = true;\n }\n\n lastQueuedComputationId = computation.id;\n queue.push(computation);\n computation.queued = true;\n\n if (runtimeState.batchDepth > 0) {\n return;\n }\n\n schedulePendingFlush();\n}\n\nexport function schedulePendingFlush(): void {\n if (queue.length === 0 || scheduled || flushing) {\n return;\n }\n\n scheduled = true;\n\n try {\n scheduler.schedule(flushQueuedComputations);\n } catch (error) {\n scheduled = false;\n for (const computation of queue) {\n computation.queued = false;\n }\n clearQueue();\n throw error;\n }\n}\n\nexport function flushQueuedComputations(): void {\n if (flushing) {\n return;\n }\n\n scheduled = false;\n flushing = true;\n let firstError: unknown;\n\n try {\n for (let iteration = 0; queue.length > 0; iteration += 1) {\n if (iteration >= maxFlushIterations) {\n throw new Error(\"Reactive flush limit exceeded\");\n }\n\n const current = takeQueuedComputations();\n\n for (const computation of current) {\n computation.queued = false;\n\n if (!computation.disposed) {\n try {\n computation.run();\n } catch (error) {\n firstError ??= error;\n }\n }\n }\n }\n\n if (firstError !== undefined) {\n throw firstError;\n }\n } finally {\n flushing = false;\n }\n}\n\nfunction clearQueue(): void {\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n}\n\nfunction takeQueuedComputations(): ReactiveComputation[] {\n if (queueRequiresSort) {\n const current = queue.sort((a, b) => a.id - b.id);\n clearQueue();\n return current;\n }\n\n const current = queue;\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n return current;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { invalidateDevtoolsWriteCache } from \"./cell.js\";\nimport { runtimeState, type ReactiveComputation } from \"./state.js\";\n\nexport interface Scheduler {\n schedule(flush: () => void): void;\n}\n\nconst defaultScheduler: Scheduler = {\n schedule(flush) {\n if (typeof queueMicrotask === \"function\") {\n queueMicrotask(flush);\n return;\n }\n\n void Promise.resolve().then(flush);\n },\n};\n\nlet scheduler = defaultScheduler;\nlet queue: ReactiveComputation[] = [];\nlet lastQueuedComputationId = -1;\nlet queueRequiresSort = false;\nlet scheduled = false;\nlet flushing = false;\nconst maxFlushIterations = 100;\n\nexport function setScheduler(nextScheduler: Scheduler): () => void {\n const previous = scheduler;\n scheduler = nextScheduler;\n\n return () => {\n scheduler = previous;\n };\n}\n\nexport function resetSchedulerStateForTesting(): void {\n for (const computation of queue) {\n computation.queued = false;\n }\n\n clearQueue();\n scheduled = false;\n flushing = false;\n}\n\nexport function queueComputation(computation: ReactiveComputation): void {\n if (computation.disposed || computation.queued) {\n return;\n }\n\n if (computation.id < lastQueuedComputationId) {\n queueRequiresSort = true;\n }\n\n lastQueuedComputationId = computation.id;\n queue.push(computation);\n computation.queued = true;\n\n if (runtimeState.batchDepth > 0) {\n return;\n }\n\n schedulePendingFlush();\n}\n\nexport function schedulePendingFlush(): void {\n if (queue.length === 0 || scheduled || flushing) {\n return;\n }\n\n scheduled = true;\n\n try {\n scheduler.schedule(flushQueuedComputations);\n } catch (error) {\n scheduled = false;\n for (const computation of queue) {\n computation.queued = false;\n }\n clearQueue();\n throw error;\n }\n}\n\nexport function flushQueuedComputations(): void {\n if (flushing) {\n return;\n }\n\n invalidateDevtoolsWriteCache();\n scheduled = false;\n flushing = true;\n let firstError: unknown;\n\n try {\n for (let iteration = 0; queue.length > 0; iteration += 1) {\n if (iteration >= maxFlushIterations) {\n throw new Error(\"Reactive flush limit exceeded\");\n }\n\n const current = takeQueuedComputations();\n\n for (const computation of current) {\n computation.queued = false;\n\n if (!computation.disposed) {\n try {\n computation.run();\n } catch (error) {\n firstError ??= error;\n }\n }\n }\n }\n\n if (firstError !== undefined) {\n throw firstError;\n }\n } finally {\n flushing = false;\n }\n}\n\nfunction clearQueue(): void {\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n}\n\nfunction takeQueuedComputations(): ReactiveComputation[] {\n if (queueRequiresSort) {\n const current = queue.sort((a, b) => a.id - b.id);\n clearQueue();\n return current;\n }\n\n const current = queue;\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n return current;\n}\n"]}
|
package/dist/state.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export interface Source {
|
|
2
|
-
|
|
3
|
-
subscribers: Set<ReactiveComputation>;
|
|
2
|
+
subscribers: ReactiveComputation | Set<ReactiveComputation> | null;
|
|
4
3
|
trackedBy?: ReactiveComputation | undefined;
|
|
5
4
|
trackedVersion?: number | undefined;
|
|
6
5
|
}
|
package/dist/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,MAAM;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,MAAM;IAKrB,WAAW,EAAE,mBAAmB,GAAG,GAAG,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC;IACnE,SAAS,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACzC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC3C,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,IAAI,IAAI,CAAC;IAClB,GAAG,IAAI,IAAI,CAAC;IACZ,OAAO,IAAI,IAAI,CAAC;IAChB,WAAW,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,MAAM,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAAC;AAEjD,eAAO,MAAM,YAAY,EAAE;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;CAS3C,CAAC"}
|
package/dist/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,wEAAwE;AACxE,6EAA6E;AAC7E,+BAA+B;AAC/B,+BAA+B,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,wEAAwE;AACxE,6EAA6E;AAC7E,+BAA+B;AAC/B,+BAA+B,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AA6BjD,MAAM,CAAC,MAAM,YAAY,GAQrB;IACF,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,SAAS;IACvB,gBAAgB,EAAE,KAAK;IACvB,iBAAiB,EAAE,CAAC;IACpB,iBAAiB,EAAE,CAAC;IACpB,eAAe,EAAE,IAAI,GAAG,EAAE;CAC3B,CAAC","sourcesContent":["import { warnOnDuplicateReactiveCoreCopy } from \"./duplicate-guard.js\";\n\n// This module holds the per-copy reactive runtime identity, so a second\n// evaluation in the same browser page is exactly the duplication that breaks\n// cross-package cell tracking.\nwarnOnDuplicateReactiveCoreCopy(import.meta.url);\n\nexport interface Source {\n // null while nothing subscribes, the computation itself while exactly one\n // does, and a Set from the second subscriber on (kept as a Set until it\n // empties back to null). Most sources never allocate a Set at all, and hot\n // write sites can gate on a null check instead of a Set.size accessor.\n subscribers: ReactiveComputation | Set<ReactiveComputation> | null;\n trackedBy?: ReactiveComputation | undefined;\n trackedVersion?: number | undefined;\n}\n\nexport interface ReactiveComputation {\n readonly id: number;\n deps: Set<Source>;\n trackingAddedDeps?: Source[] | undefined;\n trackingCount?: number | undefined;\n trackingTouchedDeps?: Source[] | undefined;\n trackingVersion?: number | undefined;\n disposed: boolean;\n queued: boolean;\n markDirty(): void;\n run(): void;\n dispose(): void;\n trackSource?(source: Source): void;\n}\n\nexport type Tracker = ReactiveComputation | null;\n\nexport const runtimeState: {\n activeTracker: Tracker;\n batchDepth: number;\n cleanupOwner: ((dispose: () => void) => void) | undefined;\n flushingComputed: boolean;\n nextComputationId: number;\n notificationDepth: number;\n pendingComputed: Set<ReactiveComputation>;\n} = {\n activeTracker: null,\n batchDepth: 0,\n cleanupOwner: undefined,\n flushingComputed: false,\n nextComputationId: 0,\n notificationDepth: 0,\n pendingComputed: new Set(),\n};\n"]}
|
package/dist/tracking.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactiveComputation, type Source } from "./state.js";
|
|
2
2
|
export declare function trackSource(source: Source): void;
|
|
3
|
+
export declare function sourceSubscriberCount(source: Source): number;
|
|
3
4
|
export declare function cleanupDeps(computation: ReactiveComputation): void;
|
|
4
5
|
export declare function nextTrackingVersionFor(computation: ReactiveComputation): number;
|
|
5
6
|
export declare function trackIncrementalSource(source: Source, computation: ReactiveComputation): void;
|
package/dist/tracking.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAIjF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAIjF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAchD;AAgCD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAalE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,CAc/E;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,IAAI,CAwBN;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAgBlF;AAED,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,mBAAmB,EAChC,eAAe,EAAE,MAAM,GACtB,IAAI,CAyBN;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAmBvE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAgDtD;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAmC3C"}
|
package/dist/tracking.js
CHANGED
|
@@ -9,35 +9,48 @@ export function trackSource(source) {
|
|
|
9
9
|
tracker.trackSource(source);
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
tracker.deps.add(source);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const previousSize = source.subscribers.size;
|
|
17
|
-
source.subscribers.add(tracker);
|
|
12
|
+
addSourceSubscriber(source, tracker);
|
|
18
13
|
tracker.deps.add(source);
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
}
|
|
15
|
+
function addSourceSubscriber(source, computation) {
|
|
16
|
+
const subscribers = source.subscribers;
|
|
17
|
+
if (subscribers === null) {
|
|
18
|
+
source.subscribers = computation;
|
|
21
19
|
}
|
|
22
|
-
else if (
|
|
23
|
-
|
|
20
|
+
else if (subscribers instanceof Set) {
|
|
21
|
+
subscribers.add(computation);
|
|
24
22
|
}
|
|
23
|
+
else if (subscribers !== computation) {
|
|
24
|
+
source.subscribers = new Set([subscribers, computation]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function removeSourceSubscriber(source, computation) {
|
|
28
|
+
const subscribers = source.subscribers;
|
|
29
|
+
if (subscribers === computation) {
|
|
30
|
+
source.subscribers = null;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (subscribers instanceof Set && subscribers.delete(computation)) {
|
|
34
|
+
if (subscribers.size === 0) {
|
|
35
|
+
source.subscribers = null;
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
export function sourceSubscriberCount(source) {
|
|
42
|
+
const subscribers = source.subscribers;
|
|
43
|
+
return subscribers === null ? 0 : subscribers instanceof Set ? subscribers.size : 1;
|
|
25
44
|
}
|
|
26
45
|
export function cleanupDeps(computation) {
|
|
27
46
|
for (const dep of computation.deps) {
|
|
28
|
-
if (!dep
|
|
47
|
+
if (!removeSourceSubscriber(dep, computation)) {
|
|
29
48
|
continue;
|
|
30
49
|
}
|
|
31
50
|
if (dep.trackedBy === computation) {
|
|
32
51
|
dep.trackedBy = undefined;
|
|
33
52
|
dep.trackedVersion = undefined;
|
|
34
53
|
}
|
|
35
|
-
if (dep.subscribers.size === 0) {
|
|
36
|
-
dep.singleSubscriber = undefined;
|
|
37
|
-
}
|
|
38
|
-
else if (dep.subscribers.size === 1) {
|
|
39
|
-
dep.singleSubscriber = dep.subscribers.values().next().value;
|
|
40
|
-
}
|
|
41
54
|
}
|
|
42
55
|
computation.deps.clear();
|
|
43
56
|
}
|
|
@@ -69,16 +82,9 @@ export function trackIncrementalSource(source, computation) {
|
|
|
69
82
|
if (computation.deps.has(source)) {
|
|
70
83
|
return;
|
|
71
84
|
}
|
|
72
|
-
|
|
73
|
-
source.subscribers.add(computation);
|
|
85
|
+
addSourceSubscriber(source, computation);
|
|
74
86
|
computation.deps.add(source);
|
|
75
87
|
computation.trackingAddedDeps?.push(source);
|
|
76
|
-
if (previousSize === 0) {
|
|
77
|
-
source.singleSubscriber = computation;
|
|
78
|
-
}
|
|
79
|
-
else if (source.subscribers.size > 1) {
|
|
80
|
-
source.singleSubscriber = undefined;
|
|
81
|
-
}
|
|
82
88
|
}
|
|
83
89
|
export function preserveIncrementalTracking(computation) {
|
|
84
90
|
const trackingVersion = computation.trackingVersion;
|
|
@@ -102,7 +108,7 @@ export function cleanupUntrackedDeps(computation, trackingVersion) {
|
|
|
102
108
|
(dep.trackedBy === computation && dep.trackedVersion === trackingVersion)) {
|
|
103
109
|
continue;
|
|
104
110
|
}
|
|
105
|
-
if (!dep
|
|
111
|
+
if (!removeSourceSubscriber(dep, computation)) {
|
|
106
112
|
continue;
|
|
107
113
|
}
|
|
108
114
|
if (dep.trackedBy === computation) {
|
|
@@ -110,12 +116,6 @@ export function cleanupUntrackedDeps(computation, trackingVersion) {
|
|
|
110
116
|
dep.trackedVersion = undefined;
|
|
111
117
|
}
|
|
112
118
|
computation.deps.delete(dep);
|
|
113
|
-
if (dep.subscribers.size === 0) {
|
|
114
|
-
dep.singleSubscriber = undefined;
|
|
115
|
-
}
|
|
116
|
-
else if (dep.subscribers.size === 1) {
|
|
117
|
-
dep.singleSubscriber = dep.subscribers.values().next().value;
|
|
118
|
-
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
export function cleanupAddedDeps(computation) {
|
|
@@ -124,7 +124,7 @@ export function cleanupAddedDeps(computation) {
|
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
126
|
for (const dep of addedDeps) {
|
|
127
|
-
if (!dep
|
|
127
|
+
if (!removeSourceSubscriber(dep, computation)) {
|
|
128
128
|
continue;
|
|
129
129
|
}
|
|
130
130
|
if (dep.trackedBy === computation) {
|
|
@@ -132,24 +132,18 @@ export function cleanupAddedDeps(computation) {
|
|
|
132
132
|
dep.trackedVersion = undefined;
|
|
133
133
|
}
|
|
134
134
|
computation.deps.delete(dep);
|
|
135
|
-
if (dep.subscribers.size === 0) {
|
|
136
|
-
dep.singleSubscriber = undefined;
|
|
137
|
-
}
|
|
138
|
-
else if (dep.subscribers.size === 1) {
|
|
139
|
-
dep.singleSubscriber = dep.subscribers.values().next().value;
|
|
140
|
-
}
|
|
141
135
|
}
|
|
142
136
|
}
|
|
143
137
|
export function notifySubscribers(source) {
|
|
144
|
-
|
|
138
|
+
const subscribers = source.subscribers;
|
|
139
|
+
if (subscribers === null) {
|
|
145
140
|
return;
|
|
146
141
|
}
|
|
147
|
-
|
|
148
|
-
if (cachedSingleSubscriber !== undefined) {
|
|
142
|
+
if (!(subscribers instanceof Set)) {
|
|
149
143
|
runtimeState.notificationDepth += 1;
|
|
150
144
|
try {
|
|
151
|
-
if (!
|
|
152
|
-
|
|
145
|
+
if (!subscribers.disposed && !subscribers.queued) {
|
|
146
|
+
subscribers.markDirty();
|
|
153
147
|
}
|
|
154
148
|
}
|
|
155
149
|
finally {
|
|
@@ -162,17 +156,14 @@ export function notifySubscribers(source) {
|
|
|
162
156
|
}
|
|
163
157
|
runtimeState.notificationDepth += 1;
|
|
164
158
|
try {
|
|
165
|
-
const singleSubscriber =
|
|
166
|
-
? source.subscribers.values().next().value
|
|
167
|
-
: undefined;
|
|
159
|
+
const singleSubscriber = subscribers.size === 1 ? subscribers.values().next().value : undefined;
|
|
168
160
|
if (singleSubscriber !== undefined) {
|
|
169
161
|
if (!singleSubscriber.disposed && !singleSubscriber.queued) {
|
|
170
162
|
singleSubscriber.markDirty();
|
|
171
163
|
}
|
|
172
164
|
}
|
|
173
165
|
else {
|
|
174
|
-
const
|
|
175
|
-
for (const subscriber of subscribers) {
|
|
166
|
+
for (const subscriber of orderedComputations(subscribers)) {
|
|
176
167
|
if (!subscriber.disposed && !subscriber.queued) {
|
|
177
168
|
subscriber.markDirty();
|
|
178
169
|
}
|
package/dist/tracking.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracking.js","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"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","sourcesContent":["import { runtimeState, type ReactiveComputation, type Source } from \"./state.js\";\n\nconst maxPendingComputedFlushIterations = 100;\n\nexport function trackSource(source: Source): void {\n const tracker = runtimeState.activeTracker;\n\n if (tracker === null || tracker.disposed) {\n return;\n }\n\n if (tracker.trackSource !== undefined) {\n tracker.trackSource(source);\n return;\n }\n\n if (source.singleSubscriber === tracker) {\n tracker.deps.add(source);\n return;\n }\n\n const previousSize = source.subscribers.size;\n source.subscribers.add(tracker);\n tracker.deps.add(source);\n\n if (previousSize === 0) {\n source.singleSubscriber = tracker;\n } else if (source.subscribers.size > 1) {\n source.singleSubscriber = undefined;\n }\n}\n\nexport function cleanupDeps(computation: ReactiveComputation): void {\n for (const dep of computation.deps) {\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n\n computation.deps.clear();\n}\n\nexport function nextTrackingVersionFor(computation: ReactiveComputation): number {\n const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;\n\n if (Number.isSafeInteger(nextTrackingVersion)) {\n return nextTrackingVersion;\n }\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation) {\n dep.trackedVersion = undefined;\n }\n }\n\n return 1;\n}\n\nexport function trackIncrementalSource(\n source: Source,\n computation: ReactiveComputation,\n): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined) {\n trackSource(source);\n return;\n }\n\n if (source.trackedBy === computation && source.trackedVersion === trackingVersion) {\n return;\n }\n\n source.trackedBy = computation;\n source.trackedVersion = trackingVersion;\n computation.trackingCount = (computation.trackingCount ?? 0) + 1;\n computation.trackingTouchedDeps?.push(source);\n\n if (computation.deps.has(source)) {\n return;\n }\n\n const previousSize = source.subscribers.size;\n source.subscribers.add(computation);\n computation.deps.add(source);\n computation.trackingAddedDeps?.push(source);\n\n if (previousSize === 0) {\n source.singleSubscriber = computation;\n } else if (source.subscribers.size > 1) {\n source.singleSubscriber = undefined;\n }\n}\n\nexport function preserveIncrementalTracking(computation: ReactiveComputation): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined || computation.trackingTouchedDeps !== undefined) {\n return;\n }\n\n const touchedDeps: Source[] = [];\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation && dep.trackedVersion === trackingVersion) {\n touchedDeps.push(dep);\n }\n }\n\n computation.trackingTouchedDeps = touchedDeps;\n}\n\nexport function cleanupUntrackedDeps(\n computation: ReactiveComputation,\n trackingVersion: number,\n): void {\n const touchedDeps =\n computation.trackingTouchedDeps === undefined\n ? undefined\n : new Set(computation.trackingTouchedDeps);\n\n for (const dep of computation.deps) {\n if (\n touchedDeps?.has(dep) === true ||\n (dep.trackedBy === computation && dep.trackedVersion === trackingVersion)\n ) {\n continue;\n }\n\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n}\n\nexport function cleanupAddedDeps(computation: ReactiveComputation): void {\n const addedDeps = computation.trackingAddedDeps;\n\n if (addedDeps === undefined) {\n return;\n }\n\n for (const dep of addedDeps) {\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n}\n\nexport function notifySubscribers(source: Source): void {\n if (source.subscribers.size === 0) {\n return;\n }\n\n const cachedSingleSubscriber = source.singleSubscriber;\n if (cachedSingleSubscriber !== undefined) {\n runtimeState.notificationDepth += 1;\n\n try {\n if (!cachedSingleSubscriber.disposed && !cachedSingleSubscriber.queued) {\n cachedSingleSubscriber.markDirty();\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n return;\n }\n\n runtimeState.notificationDepth += 1;\n\n try {\n const singleSubscriber =\n source.subscribers.size === 1\n ? source.subscribers.values().next().value\n : undefined;\n\n if (singleSubscriber !== undefined) {\n if (!singleSubscriber.disposed && !singleSubscriber.queued) {\n singleSubscriber.markDirty();\n }\n } else {\n const subscribers = orderedComputations(source.subscribers);\n\n for (const subscriber of subscribers) {\n if (!subscriber.disposed && !subscriber.queued) {\n subscriber.markDirty();\n }\n }\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n}\n\nexport function flushPendingComputed(): void {\n if (runtimeState.flushingComputed) {\n return;\n }\n\n runtimeState.flushingComputed = true;\n\n try {\n for (\n let iteration = 0;\n runtimeState.pendingComputed.size > 0;\n iteration += 1\n ) {\n if (iteration >= maxPendingComputedFlushIterations) {\n runtimeState.pendingComputed.clear();\n throw new Error(\"Reactive computed flush limit exceeded\");\n }\n\n const computations =\n runtimeState.pendingComputed.size === 1\n ? [runtimeState.pendingComputed.values().next().value as ReactiveComputation]\n : orderedComputations(runtimeState.pendingComputed);\n runtimeState.pendingComputed.clear();\n\n for (const computation of computations) {\n computation.queued = false;\n\n if (!computation.disposed) {\n computation.run();\n }\n }\n }\n } finally {\n runtimeState.flushingComputed = false;\n }\n}\n\nfunction orderedComputations(\n computations: ReadonlySet<ReactiveComputation>,\n): ReactiveComputation[] {\n const ordered: ReactiveComputation[] = [];\n let previousId = -1;\n let monotonic = true;\n\n for (const computation of computations) {\n ordered.push(computation);\n\n if (computation.id < previousId) {\n monotonic = false;\n }\n\n previousId = computation.id;\n }\n\n return monotonic || ordered.length < 2\n ? ordered\n : ordered.sort((a, b) => a.id - b.id);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tracking.js","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"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","sourcesContent":["import { runtimeState, type ReactiveComputation, type Source } from \"./state.js\";\n\nconst maxPendingComputedFlushIterations = 100;\n\nexport function trackSource(source: Source): void {\n const tracker = runtimeState.activeTracker;\n\n if (tracker === null || tracker.disposed) {\n return;\n }\n\n if (tracker.trackSource !== undefined) {\n tracker.trackSource(source);\n return;\n }\n\n addSourceSubscriber(source, tracker);\n tracker.deps.add(source);\n}\n\nfunction addSourceSubscriber(source: Source, computation: ReactiveComputation): void {\n const subscribers = source.subscribers;\n\n if (subscribers === null) {\n source.subscribers = computation;\n } else if (subscribers instanceof Set) {\n subscribers.add(computation);\n } else if (subscribers !== computation) {\n source.subscribers = new Set([subscribers, computation]);\n }\n}\n\nfunction removeSourceSubscriber(source: Source, computation: ReactiveComputation): boolean {\n const subscribers = source.subscribers;\n\n if (subscribers === computation) {\n source.subscribers = null;\n return true;\n }\n\n if (subscribers instanceof Set && subscribers.delete(computation)) {\n if (subscribers.size === 0) {\n source.subscribers = null;\n }\n return true;\n }\n\n return false;\n}\n\nexport function sourceSubscriberCount(source: Source): number {\n const subscribers = source.subscribers;\n\n return subscribers === null ? 0 : subscribers instanceof Set ? subscribers.size : 1;\n}\n\nexport function cleanupDeps(computation: ReactiveComputation): void {\n for (const dep of computation.deps) {\n if (!removeSourceSubscriber(dep, computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n }\n\n computation.deps.clear();\n}\n\nexport function nextTrackingVersionFor(computation: ReactiveComputation): number {\n const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;\n\n if (Number.isSafeInteger(nextTrackingVersion)) {\n return nextTrackingVersion;\n }\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation) {\n dep.trackedVersion = undefined;\n }\n }\n\n return 1;\n}\n\nexport function trackIncrementalSource(\n source: Source,\n computation: ReactiveComputation,\n): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined) {\n trackSource(source);\n return;\n }\n\n if (source.trackedBy === computation && source.trackedVersion === trackingVersion) {\n return;\n }\n\n source.trackedBy = computation;\n source.trackedVersion = trackingVersion;\n computation.trackingCount = (computation.trackingCount ?? 0) + 1;\n computation.trackingTouchedDeps?.push(source);\n\n if (computation.deps.has(source)) {\n return;\n }\n\n addSourceSubscriber(source, computation);\n computation.deps.add(source);\n computation.trackingAddedDeps?.push(source);\n}\n\nexport function preserveIncrementalTracking(computation: ReactiveComputation): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined || computation.trackingTouchedDeps !== undefined) {\n return;\n }\n\n const touchedDeps: Source[] = [];\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation && dep.trackedVersion === trackingVersion) {\n touchedDeps.push(dep);\n }\n }\n\n computation.trackingTouchedDeps = touchedDeps;\n}\n\nexport function cleanupUntrackedDeps(\n computation: ReactiveComputation,\n trackingVersion: number,\n): void {\n const touchedDeps =\n computation.trackingTouchedDeps === undefined\n ? undefined\n : new Set(computation.trackingTouchedDeps);\n\n for (const dep of computation.deps) {\n if (\n touchedDeps?.has(dep) === true ||\n (dep.trackedBy === computation && dep.trackedVersion === trackingVersion)\n ) {\n continue;\n }\n\n if (!removeSourceSubscriber(dep, computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n }\n}\n\nexport function cleanupAddedDeps(computation: ReactiveComputation): void {\n const addedDeps = computation.trackingAddedDeps;\n\n if (addedDeps === undefined) {\n return;\n }\n\n for (const dep of addedDeps) {\n if (!removeSourceSubscriber(dep, computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n }\n}\n\nexport function notifySubscribers(source: Source): void {\n const subscribers = source.subscribers;\n\n if (subscribers === null) {\n return;\n }\n\n if (!(subscribers instanceof Set)) {\n runtimeState.notificationDepth += 1;\n\n try {\n if (!subscribers.disposed && !subscribers.queued) {\n subscribers.markDirty();\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n return;\n }\n\n runtimeState.notificationDepth += 1;\n\n try {\n const singleSubscriber =\n subscribers.size === 1 ? subscribers.values().next().value : undefined;\n\n if (singleSubscriber !== undefined) {\n if (!singleSubscriber.disposed && !singleSubscriber.queued) {\n singleSubscriber.markDirty();\n }\n } else {\n for (const subscriber of orderedComputations(subscribers)) {\n if (!subscriber.disposed && !subscriber.queued) {\n subscriber.markDirty();\n }\n }\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n}\n\nexport function flushPendingComputed(): void {\n if (runtimeState.flushingComputed) {\n return;\n }\n\n runtimeState.flushingComputed = true;\n\n try {\n for (\n let iteration = 0;\n runtimeState.pendingComputed.size > 0;\n iteration += 1\n ) {\n if (iteration >= maxPendingComputedFlushIterations) {\n runtimeState.pendingComputed.clear();\n throw new Error(\"Reactive computed flush limit exceeded\");\n }\n\n const computations =\n runtimeState.pendingComputed.size === 1\n ? [runtimeState.pendingComputed.values().next().value as ReactiveComputation]\n : orderedComputations(runtimeState.pendingComputed);\n runtimeState.pendingComputed.clear();\n\n for (const computation of computations) {\n computation.queued = false;\n\n if (!computation.disposed) {\n computation.run();\n }\n }\n }\n } finally {\n runtimeState.flushingComputed = false;\n }\n}\n\nfunction orderedComputations(\n computations: ReadonlySet<ReactiveComputation>,\n): ReactiveComputation[] {\n const ordered: ReactiveComputation[] = [];\n let previousId = -1;\n let monotonic = true;\n\n for (const computation of computations) {\n ordered.push(computation);\n\n if (computation.id < previousId) {\n monotonic = false;\n }\n\n previousId = computation.id;\n }\n\n return monotonic || ordered.length < 2\n ? ordered\n : ordered.sort((a, b) => a.id - b.id);\n}\n"]}
|
package/package.json
CHANGED
package/src/batch.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { runtimeState } from "./state.js";
|
|
2
|
+
import { invalidateDevtoolsWriteCache } from "./cell.js";
|
|
2
3
|
import { schedulePendingFlush } from "./scheduler.js";
|
|
3
4
|
import { flushPendingComputed } from "./tracking.js";
|
|
4
5
|
|
|
5
6
|
export function batch<T>(fn: () => T): T {
|
|
7
|
+
invalidateDevtoolsWriteCache();
|
|
6
8
|
runtimeState.batchDepth += 1;
|
|
7
9
|
|
|
8
10
|
try {
|
|
@@ -18,6 +20,7 @@ export function batch<T>(fn: () => T): T {
|
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export async function batchAsync<T>(fn: () => Promise<T> | T): Promise<T> {
|
|
23
|
+
invalidateDevtoolsWriteCache();
|
|
21
24
|
runtimeState.batchDepth += 1;
|
|
22
25
|
|
|
23
26
|
try {
|
package/src/cell.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Cell } from "./types.js";
|
|
2
2
|
import type { Source } from "./state.js";
|
|
3
|
-
import { notifySubscribers, trackSource } from "./tracking.js";
|
|
3
|
+
import { notifySubscribers, sourceSubscriberCount, trackSource } from "./tracking.js";
|
|
4
4
|
|
|
5
5
|
declare const __MREACT_CLIENT_DEVTOOLS__: boolean | undefined;
|
|
6
6
|
|
|
@@ -8,52 +8,112 @@ const clientDevtoolsDisabled =
|
|
|
8
8
|
typeof __MREACT_CLIENT_DEVTOOLS__ !== "undefined" &&
|
|
9
9
|
__MREACT_CLIENT_DEVTOOLS__ === false;
|
|
10
10
|
|
|
11
|
+
interface DevtoolsHook {
|
|
12
|
+
emit?: ((event: Record<string, unknown>) => void) | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type GlobalWithDevtools = typeof globalThis & {
|
|
16
|
+
__mreactDevtools?: DevtoolsHook | undefined;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Write-path devtools cache: `undefined` = not sampled yet, `null` = sampled
|
|
20
|
+
// and absent, object = sampled and attached. The no-devtools write fast path
|
|
21
|
+
// is a single module-local null comparison instead of a globalThis property
|
|
22
|
+
// walk per write. A late attach is observed at the next batch or flush
|
|
23
|
+
// boundary (see invalidateDevtoolsWriteCache callers); a detach or hook swap
|
|
24
|
+
// is observed on the next write because the emit path revalidates identity.
|
|
25
|
+
let cachedDevtoolsHook: DevtoolsHook | null | undefined = clientDevtoolsDisabled
|
|
26
|
+
? null
|
|
27
|
+
: undefined;
|
|
28
|
+
|
|
29
|
+
export function invalidateDevtoolsWriteCache(): void {
|
|
30
|
+
if (!clientDevtoolsDisabled) {
|
|
31
|
+
cachedDevtoolsHook = undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function resolveDevtoolsHook(): DevtoolsHook | null {
|
|
36
|
+
const hook = (globalThis as GlobalWithDevtools).__mreactDevtools;
|
|
37
|
+
const resolved = hook !== undefined && typeof hook.emit === "function" ? hook : null;
|
|
38
|
+
cachedDevtoolsHook = resolved;
|
|
39
|
+
return resolved;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function emitCellSetEvent<T>(source: Source, previous: T, value: T): void {
|
|
43
|
+
// Cold path: only reached while a devtools hook is (or was) attached, or on
|
|
44
|
+
// the first write after a cache invalidation. Revalidate against the live
|
|
45
|
+
// global so a disposed or swapped hook never receives stale events.
|
|
46
|
+
const live = (globalThis as GlobalWithDevtools).__mreactDevtools;
|
|
47
|
+
const hook =
|
|
48
|
+
cachedDevtoolsHook !== undefined && cachedDevtoolsHook === live
|
|
49
|
+
? cachedDevtoolsHook
|
|
50
|
+
: resolveDevtoolsHook();
|
|
51
|
+
|
|
52
|
+
if (hook === null) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const emit = hook.emit;
|
|
57
|
+
|
|
58
|
+
if (typeof emit !== "function") {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
emit.call(hook, {
|
|
63
|
+
package: "@reckona/mreact-reactive-core",
|
|
64
|
+
previous,
|
|
65
|
+
subscribers: sourceSubscriberCount(source),
|
|
66
|
+
timestamp: Date.now(),
|
|
67
|
+
type: "reactive:cell:set",
|
|
68
|
+
value,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface CellState<T> {
|
|
73
|
+
value: T;
|
|
74
|
+
readonly source: Source;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// One shared write function keeps the hot store/notify sequence in a single
|
|
78
|
+
// optimizable function instead of a fresh fat closure per cell.
|
|
79
|
+
function writeCellValue<T>(state: CellState<T>, next: T | ((prev: T) => T)): void {
|
|
80
|
+
const previous = state.value;
|
|
81
|
+
const resolved =
|
|
82
|
+
typeof next === "function" ? (next as (prev: T) => T)(previous) : next;
|
|
83
|
+
|
|
84
|
+
if (Object.is(previous, resolved)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
state.value = resolved;
|
|
89
|
+
|
|
90
|
+
// clientDevtoolsDisabled folds to true under the client build define, which
|
|
91
|
+
// makes this branch statically dead so bundlers drop the emit path (and its
|
|
92
|
+
// globalThis.__mreactDevtools references) from production client bundles.
|
|
93
|
+
if (!clientDevtoolsDisabled && cachedDevtoolsHook !== null) {
|
|
94
|
+
emitCellSetEvent(state.source, previous, resolved);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (state.source.subscribers !== null) {
|
|
98
|
+
notifySubscribers(state.source);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
11
102
|
export function cell<T>(initial: T): Cell<T> {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
103
|
+
const state: CellState<T> = {
|
|
104
|
+
source: {
|
|
105
|
+
subscribers: null,
|
|
106
|
+
},
|
|
107
|
+
value: initial,
|
|
15
108
|
};
|
|
16
109
|
|
|
17
110
|
return {
|
|
18
111
|
get(): T {
|
|
19
|
-
trackSource(source);
|
|
20
|
-
return
|
|
112
|
+
trackSource(state.source);
|
|
113
|
+
return state.value;
|
|
21
114
|
},
|
|
22
115
|
set(next: T | ((prev: T) => T)): void {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (Object.is(current, resolved)) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (clientDevtoolsDisabled) {
|
|
30
|
-
current = resolved;
|
|
31
|
-
} else {
|
|
32
|
-
const devtools = (
|
|
33
|
-
globalThis as typeof globalThis & {
|
|
34
|
-
__mreactDevtools?:
|
|
35
|
-
| { emit?: (event: Record<string, unknown>) => void }
|
|
36
|
-
| undefined;
|
|
37
|
-
}
|
|
38
|
-
).__mreactDevtools;
|
|
39
|
-
const emit = devtools?.emit;
|
|
40
|
-
|
|
41
|
-
if (typeof emit !== "function") {
|
|
42
|
-
current = resolved;
|
|
43
|
-
} else {
|
|
44
|
-
const previous = current;
|
|
45
|
-
current = resolved;
|
|
46
|
-
emit.call(devtools, {
|
|
47
|
-
package: "@reckona/mreact-reactive-core",
|
|
48
|
-
previous,
|
|
49
|
-
subscribers: source.subscribers.size,
|
|
50
|
-
timestamp: Date.now(),
|
|
51
|
-
type: "reactive:cell:set",
|
|
52
|
-
value: resolved,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
notifySubscribers(source);
|
|
116
|
+
writeCellValue(state, next);
|
|
57
117
|
},
|
|
58
118
|
};
|
|
59
119
|
}
|
package/src/computed.ts
CHANGED
|
@@ -29,7 +29,7 @@ export function computed<T>(
|
|
|
29
29
|
const equals = typeof options === "function" ? options : (options?.equals ?? Object.is);
|
|
30
30
|
|
|
31
31
|
const source: Source = {
|
|
32
|
-
subscribers:
|
|
32
|
+
subscribers: null,
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
const computation: ReactiveComputation = {
|
|
@@ -39,14 +39,14 @@ export function computed<T>(
|
|
|
39
39
|
queued: false,
|
|
40
40
|
markDirty() {
|
|
41
41
|
if (dirty) {
|
|
42
|
-
if (source.subscribers
|
|
42
|
+
if (source.subscribers === null || computation.queued) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
dirty = true;
|
|
48
48
|
|
|
49
|
-
if (source.subscribers
|
|
49
|
+
if (source.subscribers !== null) {
|
|
50
50
|
if (runtimeState.notificationDepth > 0) {
|
|
51
51
|
computation.queued = true;
|
|
52
52
|
runtimeState.pendingComputed.add(computation);
|
|
@@ -71,8 +71,7 @@ export function computed<T>(
|
|
|
71
71
|
computation.queued = false;
|
|
72
72
|
runtimeState.pendingComputed.delete(computation);
|
|
73
73
|
cleanupDeps(computation);
|
|
74
|
-
source.subscribers
|
|
75
|
-
source.singleSubscriber = undefined;
|
|
74
|
+
source.subscribers = null;
|
|
76
75
|
},
|
|
77
76
|
};
|
|
78
77
|
|
package/src/scheduler.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { invalidateDevtoolsWriteCache } from "./cell.js";
|
|
1
2
|
import { runtimeState, type ReactiveComputation } from "./state.js";
|
|
2
3
|
|
|
3
4
|
export interface Scheduler {
|
|
@@ -86,6 +87,7 @@ export function flushQueuedComputations(): void {
|
|
|
86
87
|
return;
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
invalidateDevtoolsWriteCache();
|
|
89
91
|
scheduled = false;
|
|
90
92
|
flushing = true;
|
|
91
93
|
let firstError: unknown;
|
package/src/state.ts
CHANGED
|
@@ -6,8 +6,11 @@ import { warnOnDuplicateReactiveCoreCopy } from "./duplicate-guard.js";
|
|
|
6
6
|
warnOnDuplicateReactiveCoreCopy(import.meta.url);
|
|
7
7
|
|
|
8
8
|
export interface Source {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// null while nothing subscribes, the computation itself while exactly one
|
|
10
|
+
// does, and a Set from the second subscriber on (kept as a Set until it
|
|
11
|
+
// empties back to null). Most sources never allocate a Set at all, and hot
|
|
12
|
+
// write sites can gate on a null check instead of a Set.size accessor.
|
|
13
|
+
subscribers: ReactiveComputation | Set<ReactiveComputation> | null;
|
|
11
14
|
trackedBy?: ReactiveComputation | undefined;
|
|
12
15
|
trackedVersion?: number | undefined;
|
|
13
16
|
}
|
package/src/tracking.ts
CHANGED
|
@@ -14,25 +14,49 @@ export function trackSource(source: Source): void {
|
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
addSourceSubscriber(source, tracker);
|
|
18
|
+
tracker.deps.add(source);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function addSourceSubscriber(source: Source, computation: ReactiveComputation): void {
|
|
22
|
+
const subscribers = source.subscribers;
|
|
23
|
+
|
|
24
|
+
if (subscribers === null) {
|
|
25
|
+
source.subscribers = computation;
|
|
26
|
+
} else if (subscribers instanceof Set) {
|
|
27
|
+
subscribers.add(computation);
|
|
28
|
+
} else if (subscribers !== computation) {
|
|
29
|
+
source.subscribers = new Set([subscribers, computation]);
|
|
20
30
|
}
|
|
31
|
+
}
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
source.subscribers
|
|
24
|
-
|
|
33
|
+
function removeSourceSubscriber(source: Source, computation: ReactiveComputation): boolean {
|
|
34
|
+
const subscribers = source.subscribers;
|
|
35
|
+
|
|
36
|
+
if (subscribers === computation) {
|
|
37
|
+
source.subscribers = null;
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
25
40
|
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
if (subscribers instanceof Set && subscribers.delete(computation)) {
|
|
42
|
+
if (subscribers.size === 0) {
|
|
43
|
+
source.subscribers = null;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
30
46
|
}
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function sourceSubscriberCount(source: Source): number {
|
|
52
|
+
const subscribers = source.subscribers;
|
|
53
|
+
|
|
54
|
+
return subscribers === null ? 0 : subscribers instanceof Set ? subscribers.size : 1;
|
|
31
55
|
}
|
|
32
56
|
|
|
33
57
|
export function cleanupDeps(computation: ReactiveComputation): void {
|
|
34
58
|
for (const dep of computation.deps) {
|
|
35
|
-
if (!dep
|
|
59
|
+
if (!removeSourceSubscriber(dep, computation)) {
|
|
36
60
|
continue;
|
|
37
61
|
}
|
|
38
62
|
|
|
@@ -40,12 +64,6 @@ export function cleanupDeps(computation: ReactiveComputation): void {
|
|
|
40
64
|
dep.trackedBy = undefined;
|
|
41
65
|
dep.trackedVersion = undefined;
|
|
42
66
|
}
|
|
43
|
-
|
|
44
|
-
if (dep.subscribers.size === 0) {
|
|
45
|
-
dep.singleSubscriber = undefined;
|
|
46
|
-
} else if (dep.subscribers.size === 1) {
|
|
47
|
-
dep.singleSubscriber = dep.subscribers.values().next().value;
|
|
48
|
-
}
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
computation.deps.clear();
|
|
@@ -91,16 +109,9 @@ export function trackIncrementalSource(
|
|
|
91
109
|
return;
|
|
92
110
|
}
|
|
93
111
|
|
|
94
|
-
|
|
95
|
-
source.subscribers.add(computation);
|
|
112
|
+
addSourceSubscriber(source, computation);
|
|
96
113
|
computation.deps.add(source);
|
|
97
114
|
computation.trackingAddedDeps?.push(source);
|
|
98
|
-
|
|
99
|
-
if (previousSize === 0) {
|
|
100
|
-
source.singleSubscriber = computation;
|
|
101
|
-
} else if (source.subscribers.size > 1) {
|
|
102
|
-
source.singleSubscriber = undefined;
|
|
103
|
-
}
|
|
104
115
|
}
|
|
105
116
|
|
|
106
117
|
export function preserveIncrementalTracking(computation: ReactiveComputation): void {
|
|
@@ -138,7 +149,7 @@ export function cleanupUntrackedDeps(
|
|
|
138
149
|
continue;
|
|
139
150
|
}
|
|
140
151
|
|
|
141
|
-
if (!dep
|
|
152
|
+
if (!removeSourceSubscriber(dep, computation)) {
|
|
142
153
|
continue;
|
|
143
154
|
}
|
|
144
155
|
|
|
@@ -148,12 +159,6 @@ export function cleanupUntrackedDeps(
|
|
|
148
159
|
}
|
|
149
160
|
|
|
150
161
|
computation.deps.delete(dep);
|
|
151
|
-
|
|
152
|
-
if (dep.subscribers.size === 0) {
|
|
153
|
-
dep.singleSubscriber = undefined;
|
|
154
|
-
} else if (dep.subscribers.size === 1) {
|
|
155
|
-
dep.singleSubscriber = dep.subscribers.values().next().value;
|
|
156
|
-
}
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
|
|
@@ -165,7 +170,7 @@ export function cleanupAddedDeps(computation: ReactiveComputation): void {
|
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
for (const dep of addedDeps) {
|
|
168
|
-
if (!dep
|
|
173
|
+
if (!removeSourceSubscriber(dep, computation)) {
|
|
169
174
|
continue;
|
|
170
175
|
}
|
|
171
176
|
|
|
@@ -175,27 +180,22 @@ export function cleanupAddedDeps(computation: ReactiveComputation): void {
|
|
|
175
180
|
}
|
|
176
181
|
|
|
177
182
|
computation.deps.delete(dep);
|
|
178
|
-
|
|
179
|
-
if (dep.subscribers.size === 0) {
|
|
180
|
-
dep.singleSubscriber = undefined;
|
|
181
|
-
} else if (dep.subscribers.size === 1) {
|
|
182
|
-
dep.singleSubscriber = dep.subscribers.values().next().value;
|
|
183
|
-
}
|
|
184
183
|
}
|
|
185
184
|
}
|
|
186
185
|
|
|
187
186
|
export function notifySubscribers(source: Source): void {
|
|
188
|
-
|
|
187
|
+
const subscribers = source.subscribers;
|
|
188
|
+
|
|
189
|
+
if (subscribers === null) {
|
|
189
190
|
return;
|
|
190
191
|
}
|
|
191
192
|
|
|
192
|
-
|
|
193
|
-
if (cachedSingleSubscriber !== undefined) {
|
|
193
|
+
if (!(subscribers instanceof Set)) {
|
|
194
194
|
runtimeState.notificationDepth += 1;
|
|
195
195
|
|
|
196
196
|
try {
|
|
197
|
-
if (!
|
|
198
|
-
|
|
197
|
+
if (!subscribers.disposed && !subscribers.queued) {
|
|
198
|
+
subscribers.markDirty();
|
|
199
199
|
}
|
|
200
200
|
} finally {
|
|
201
201
|
runtimeState.notificationDepth -= 1;
|
|
@@ -211,18 +211,14 @@ export function notifySubscribers(source: Source): void {
|
|
|
211
211
|
|
|
212
212
|
try {
|
|
213
213
|
const singleSubscriber =
|
|
214
|
-
|
|
215
|
-
? source.subscribers.values().next().value
|
|
216
|
-
: undefined;
|
|
214
|
+
subscribers.size === 1 ? subscribers.values().next().value : undefined;
|
|
217
215
|
|
|
218
216
|
if (singleSubscriber !== undefined) {
|
|
219
217
|
if (!singleSubscriber.disposed && !singleSubscriber.queued) {
|
|
220
218
|
singleSubscriber.markDirty();
|
|
221
219
|
}
|
|
222
220
|
} else {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
for (const subscriber of subscribers) {
|
|
221
|
+
for (const subscriber of orderedComputations(subscribers)) {
|
|
226
222
|
if (!subscriber.disposed && !subscriber.queued) {
|
|
227
223
|
subscriber.markDirty();
|
|
228
224
|
}
|