@takazudo/zfb 2.22.1 → 3.1.0
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/README.md +13 -16
- package/dist/config.d.ts +77 -25
- package/dist/config.js +27 -6
- package/dist/config.js.map +1 -1
- package/dist/content.d.ts +8 -22
- package/dist/content.js +6 -28
- package/dist/content.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/island-boundary.d.ts +4 -0
- package/dist/island-boundary.js +42 -0
- package/dist/island-boundary.js.map +1 -0
- package/dist/island.d.ts +2 -118
- package/dist/island.js +4 -284
- package/dist/island.js.map +1 -1
- package/dist/jsx-types.d.ts +2 -38
- package/dist/jsx-types.js +3 -10
- package/dist/jsx-types.js.map +1 -1
- package/dist/plugins.d.ts +40 -0
- package/dist/plugins.js.map +1 -1
- package/dist/runtime.d.ts +26 -77
- package/dist/runtime.js +307 -340
- package/dist/runtime.js.map +1 -1
- package/dist/zudo-react/client.d.ts +3 -0
- package/dist/zudo-react/client.js +3 -0
- package/dist/zudo-react/client.js.map +1 -0
- package/dist/zudo-react/description.d.ts +16 -0
- package/dist/zudo-react/description.js +64 -0
- package/dist/zudo-react/description.js.map +1 -0
- package/dist/zudo-react/dom-bindings.d.ts +13 -0
- package/dist/zudo-react/dom-bindings.js +58 -0
- package/dist/zudo-react/dom-bindings.js.map +1 -0
- package/dist/zudo-react/escape.d.ts +2 -0
- package/dist/zudo-react/escape.js +7 -0
- package/dist/zudo-react/escape.js.map +1 -0
- package/dist/zudo-react/forms.d.ts +29 -0
- package/dist/zudo-react/forms.js +371 -0
- package/dist/zudo-react/forms.js.map +1 -0
- package/dist/zudo-react/hydrate.d.ts +4 -0
- package/dist/zudo-react/hydrate.js +912 -0
- package/dist/zudo-react/hydrate.js.map +1 -0
- package/dist/zudo-react/index.d.ts +47 -0
- package/dist/zudo-react/index.js +13 -0
- package/dist/zudo-react/index.js.map +1 -0
- package/dist/zudo-react/island-root-type.d.ts +1 -0
- package/dist/zudo-react/island-root-type.js +2 -0
- package/dist/zudo-react/island-root-type.js.map +1 -0
- package/dist/zudo-react/jsx-dev-runtime.d.ts +8 -0
- package/dist/zudo-react/jsx-dev-runtime.js +6 -0
- package/dist/zudo-react/jsx-dev-runtime.js.map +1 -0
- package/dist/zudo-react/jsx-runtime.d.ts +5 -0
- package/dist/zudo-react/jsx-runtime.js +7 -0
- package/dist/zudo-react/jsx-runtime.js.map +1 -0
- package/dist/zudo-react/jsx-types.d.ts +216 -0
- package/dist/zudo-react/jsx-types.js +2 -0
- package/dist/zudo-react/jsx-types.js.map +1 -0
- package/dist/zudo-react/props-transport.d.ts +2 -0
- package/dist/zudo-react/props-transport.js +95 -0
- package/dist/zudo-react/props-transport.js.map +1 -0
- package/dist/zudo-react/reactive-types.d.ts +8 -0
- package/dist/zudo-react/reactive-types.js +2 -0
- package/dist/zudo-react/reactive-types.js.map +1 -0
- package/dist/zudo-react/reactive.d.ts +20 -0
- package/dist/zudo-react/reactive.js +176 -0
- package/dist/zudo-react/reactive.js.map +1 -0
- package/dist/zudo-react/render-html.d.ts +3 -0
- package/dist/zudo-react/render-html.js +535 -0
- package/dist/zudo-react/render-html.js.map +1 -0
- package/dist/zudo-react/root.d.ts +20 -0
- package/dist/zudo-react/root.js +74 -0
- package/dist/zudo-react/root.js.map +1 -0
- package/dist/zudo-react/scheduler.d.ts +12 -0
- package/dist/zudo-react/scheduler.js +113 -0
- package/dist/zudo-react/scheduler.js.map +1 -0
- package/dist/zudo-react/scope.d.ts +42 -0
- package/dist/zudo-react/scope.js +220 -0
- package/dist/zudo-react/scope.js.map +1 -0
- package/dist/zudo-react/server.d.ts +15 -0
- package/dist/zudo-react/server.js +11 -0
- package/dist/zudo-react/server.js.map +1 -0
- package/dist/zudo-react/structure.d.ts +16 -0
- package/dist/zudo-react/structure.js +49 -0
- package/dist/zudo-react/structure.js.map +1 -0
- package/dist/zudo-react/vocabulary.d.ts +12 -0
- package/dist/zudo-react/vocabulary.js +96 -0
- package/dist/zudo-react/vocabulary.js.map +1 -0
- package/package.json +28 -24
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const forbidden = new Set(["__proto__", "prototype", "constructor"]);
|
|
2
|
+
function fail(code, path, detail = "") {
|
|
3
|
+
throw new TypeError(`${code} at ${path}${detail ? ` (${detail})` : ""}`);
|
|
4
|
+
}
|
|
5
|
+
function validate(value, path, ancestors) {
|
|
6
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
7
|
+
return;
|
|
8
|
+
if (typeof value === "number") {
|
|
9
|
+
if (!Number.isFinite(value))
|
|
10
|
+
fail("ZR_PROPS_NUMBER", path);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (value === undefined)
|
|
14
|
+
fail("ZR_PROPS_UNDEFINED", path);
|
|
15
|
+
if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint")
|
|
16
|
+
fail(`ZR_PROPS_${typeof value}`.toUpperCase(), path);
|
|
17
|
+
if (typeof value !== "object")
|
|
18
|
+
fail("ZR_PROPS_VALUE", path);
|
|
19
|
+
const record = value;
|
|
20
|
+
if ("$$zudo" in record || "$$zudoReactive" in record)
|
|
21
|
+
fail("ZR_PROPS_RUNTIME_VALUE", path);
|
|
22
|
+
const ancestor = ancestors.get(record);
|
|
23
|
+
if (ancestor !== undefined)
|
|
24
|
+
fail("ZR_PROPS_CYCLE", path, `ancestor ${ancestor}`);
|
|
25
|
+
const array = Array.isArray(record);
|
|
26
|
+
if (!array &&
|
|
27
|
+
Object.getPrototypeOf(record) !== Object.prototype &&
|
|
28
|
+
Object.getPrototypeOf(record) !== null)
|
|
29
|
+
fail("ZR_PROPS_OBJECT_KIND", path);
|
|
30
|
+
ancestors.set(record, path);
|
|
31
|
+
try {
|
|
32
|
+
const descriptors = Object.getOwnPropertyDescriptors(record);
|
|
33
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
34
|
+
if (typeof key === "symbol")
|
|
35
|
+
fail("ZR_PROPS_PROPERTY", path, "symbol key");
|
|
36
|
+
if (array && key === "length")
|
|
37
|
+
continue;
|
|
38
|
+
const next = array ? `${path}[${key}]` : `${path}.${key}`;
|
|
39
|
+
if (forbidden.has(key))
|
|
40
|
+
fail("ZR_PROPS_KEY", next);
|
|
41
|
+
const descriptor = descriptors[key];
|
|
42
|
+
if (!descriptor || !descriptor.enumerable || !("value" in descriptor))
|
|
43
|
+
fail("ZR_PROPS_PROPERTY", next);
|
|
44
|
+
if (array && (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= record.length))
|
|
45
|
+
fail("ZR_PROPS_PROPERTY", next);
|
|
46
|
+
validate(descriptor.value, next, ancestors);
|
|
47
|
+
}
|
|
48
|
+
if (array) {
|
|
49
|
+
for (let index = 0; index < record.length; index++) {
|
|
50
|
+
if (!Object.hasOwn(record, index))
|
|
51
|
+
fail("ZR_PROPS_UNDEFINED", `${path}[${index}]`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
ancestors.delete(record);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function serializeProps(props) {
|
|
60
|
+
if (props === null || Array.isArray(props) || typeof props !== "object")
|
|
61
|
+
fail("ZR_PROPS_OBJECT_KIND", "props");
|
|
62
|
+
const descriptors = Object.getOwnPropertyDescriptors(props);
|
|
63
|
+
const child = descriptors.children;
|
|
64
|
+
if (child) {
|
|
65
|
+
if (!child.enumerable || !("value" in child))
|
|
66
|
+
fail("ZR_PROPS_PROPERTY", "props.children");
|
|
67
|
+
if (!emptyChildren(child.value))
|
|
68
|
+
fail("ZR_PROPS_CHILDREN", "props.children");
|
|
69
|
+
delete descriptors.children;
|
|
70
|
+
}
|
|
71
|
+
const payload = Object.defineProperties(Object.create(Object.getPrototypeOf(props)), descriptors);
|
|
72
|
+
validate(payload, "props", new Map());
|
|
73
|
+
return JSON.stringify(payload);
|
|
74
|
+
}
|
|
75
|
+
function emptyChildren(value) {
|
|
76
|
+
return (value == null ||
|
|
77
|
+
typeof value === "boolean" ||
|
|
78
|
+
(Array.isArray(value) && value.every(emptyChildren)));
|
|
79
|
+
}
|
|
80
|
+
export function parseProps(json) {
|
|
81
|
+
let parsed;
|
|
82
|
+
try {
|
|
83
|
+
parsed = JSON.parse(json);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
fail("ZR_PROPS_JSON", "props");
|
|
87
|
+
}
|
|
88
|
+
if (parsed === null || Array.isArray(parsed) || typeof parsed !== "object")
|
|
89
|
+
fail("ZR_PROPS_OBJECT_KIND", "props");
|
|
90
|
+
if (Object.hasOwn(parsed, "children"))
|
|
91
|
+
fail("ZR_PROPS_CHILDREN", "props.children");
|
|
92
|
+
validate(parsed, "props", new Map());
|
|
93
|
+
return parsed;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=props-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"props-transport.js","sourceRoot":"","sources":["../../src/zudo-react/props-transport.ts"],"names":[],"mappings":"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","sourcesContent":["const forbidden = new Set([\"__proto__\", \"prototype\", \"constructor\"]);\n\nfunction fail(code: string, path: string, detail = \"\"): never {\n throw new TypeError(`${code} at ${path}${detail ? ` (${detail})` : \"\"}`);\n}\n\nfunction validate(value: unknown, path: string, ancestors: Map<object, string>): void {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) fail(\"ZR_PROPS_NUMBER\", path);\n return;\n }\n if (value === undefined) fail(\"ZR_PROPS_UNDEFINED\", path);\n if (typeof value === \"function\" || typeof value === \"symbol\" || typeof value === \"bigint\")\n fail(`ZR_PROPS_${typeof value}`.toUpperCase(), path);\n if (typeof value !== \"object\") fail(\"ZR_PROPS_VALUE\", path);\n const record = value as object;\n if (\"$$zudo\" in record || \"$$zudoReactive\" in record) fail(\"ZR_PROPS_RUNTIME_VALUE\", path);\n const ancestor = ancestors.get(record);\n if (ancestor !== undefined) fail(\"ZR_PROPS_CYCLE\", path, `ancestor ${ancestor}`);\n const array = Array.isArray(record);\n if (\n !array &&\n Object.getPrototypeOf(record) !== Object.prototype &&\n Object.getPrototypeOf(record) !== null\n )\n fail(\"ZR_PROPS_OBJECT_KIND\", path);\n ancestors.set(record, path);\n try {\n const descriptors = Object.getOwnPropertyDescriptors(record);\n for (const key of Reflect.ownKeys(descriptors)) {\n if (typeof key === \"symbol\") fail(\"ZR_PROPS_PROPERTY\", path, \"symbol key\");\n if (array && key === \"length\") continue;\n const next = array ? `${path}[${key}]` : `${path}.${key}`;\n if (forbidden.has(key)) fail(\"ZR_PROPS_KEY\", next);\n const descriptor = descriptors[key];\n if (!descriptor || !descriptor.enumerable || !(\"value\" in descriptor))\n fail(\"ZR_PROPS_PROPERTY\", next);\n if (array && (!/^(0|[1-9]\\d*)$/.test(key) || Number(key) >= record.length))\n fail(\"ZR_PROPS_PROPERTY\", next);\n validate(descriptor.value, next, ancestors);\n }\n if (array) {\n for (let index = 0; index < record.length; index++) {\n if (!Object.hasOwn(record, index)) fail(\"ZR_PROPS_UNDEFINED\", `${path}[${index}]`);\n }\n }\n } finally {\n ancestors.delete(record);\n }\n}\n\nexport function serializeProps(props: Record<string, unknown>): string {\n if (props === null || Array.isArray(props) || typeof props !== \"object\")\n fail(\"ZR_PROPS_OBJECT_KIND\", \"props\");\n const descriptors = Object.getOwnPropertyDescriptors(props);\n const child = descriptors.children;\n if (child) {\n if (!child.enumerable || !(\"value\" in child)) fail(\"ZR_PROPS_PROPERTY\", \"props.children\");\n if (!emptyChildren(child.value)) fail(\"ZR_PROPS_CHILDREN\", \"props.children\");\n delete descriptors.children;\n }\n const payload = Object.defineProperties(Object.create(Object.getPrototypeOf(props)), descriptors);\n validate(payload, \"props\", new Map());\n return JSON.stringify(payload);\n}\n\nfunction emptyChildren(value: unknown): boolean {\n return (\n value == null ||\n typeof value === \"boolean\" ||\n (Array.isArray(value) && value.every(emptyChildren))\n );\n}\n\nexport function parseProps(json: string): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n fail(\"ZR_PROPS_JSON\", \"props\");\n }\n if (parsed === null || Array.isArray(parsed) || typeof parsed !== \"object\")\n fail(\"ZR_PROPS_OBJECT_KIND\", \"props\");\n if (Object.hasOwn(parsed, \"children\")) fail(\"ZR_PROPS_CHILDREN\", \"props.children\");\n validate(parsed, \"props\", new Map());\n return parsed as Record<string, unknown>;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive-types.js","sourceRoot":"","sources":["../../src/zudo-react/reactive-types.ts"],"names":[],"mappings":"","sourcesContent":["export interface ReadonlySignal<T> {\n readonly value: T;\n readonly $$zudoReactive: \"zudo-react.reactive.v1\";\n}\n\nexport interface Signal<T> extends ReadonlySignal<T> {\n value: T;\n readonly $$zudoWritable: \"zudo-react.writable.v1\";\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Job, type Phase } from "./scheduler.js";
|
|
2
|
+
import type { ReadonlySignal, Signal } from "./reactive-types.js";
|
|
3
|
+
declare function untracked<T>(fn: () => T): T;
|
|
4
|
+
export { untracked };
|
|
5
|
+
export declare function signal<T>(initial: T): Signal<T>;
|
|
6
|
+
export declare function computed<T>(read: () => T): ReadonlySignal<T>;
|
|
7
|
+
export declare function readSnapshot<T>(value: ReadonlySignal<T>): T;
|
|
8
|
+
export interface Subscription {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
run(): void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function subscribe(callback: () => void, options?: {
|
|
14
|
+
phase?: Phase;
|
|
15
|
+
id?: string;
|
|
16
|
+
active?: () => boolean;
|
|
17
|
+
report?: Job["report"];
|
|
18
|
+
}): Subscription;
|
|
19
|
+
/** Internal test introspection; absent from every public entry. */
|
|
20
|
+
export declare function subscriberCount(value: ReadonlySignal<unknown>): number;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { enqueue } from "./scheduler.js";
|
|
2
|
+
let currentObserver = null;
|
|
3
|
+
let evaluating = 0;
|
|
4
|
+
const evaluationStack = [];
|
|
5
|
+
let nextId = 0;
|
|
6
|
+
// The quoted own key is the retained runtime definition witness.
|
|
7
|
+
const core = { "@takazudo/zfb/zudo-react/runtime-definition-v1": true, nextId: () => ++nextId };
|
|
8
|
+
function track(source) {
|
|
9
|
+
if (!currentObserver)
|
|
10
|
+
return;
|
|
11
|
+
source.subscribers.add(currentObserver);
|
|
12
|
+
currentObserver.dependencies.add(source);
|
|
13
|
+
}
|
|
14
|
+
function detach(observer) {
|
|
15
|
+
for (const source of observer.dependencies)
|
|
16
|
+
source.subscribers.delete(observer);
|
|
17
|
+
observer.dependencies.clear();
|
|
18
|
+
}
|
|
19
|
+
function untracked(fn) {
|
|
20
|
+
const previous = currentObserver;
|
|
21
|
+
currentObserver = null;
|
|
22
|
+
try {
|
|
23
|
+
return fn();
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
currentObserver = previous;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export { untracked };
|
|
30
|
+
class Writable {
|
|
31
|
+
current;
|
|
32
|
+
$$zudoReactive = "zudo-react.reactive.v1";
|
|
33
|
+
$$zudoWritable = "zudo-react.writable.v1";
|
|
34
|
+
subscribers = new Set();
|
|
35
|
+
constructor(current) {
|
|
36
|
+
this.current = current;
|
|
37
|
+
if (!core["@takazudo/zfb/zudo-react/runtime-definition-v1"])
|
|
38
|
+
throw new Error("ZR_RUNTIME_DEFINITION");
|
|
39
|
+
}
|
|
40
|
+
get value() {
|
|
41
|
+
track(this);
|
|
42
|
+
return this.current;
|
|
43
|
+
}
|
|
44
|
+
set value(value) {
|
|
45
|
+
if (evaluating > 0)
|
|
46
|
+
throw new Error("ZR_COMPUTED_WRITE: write during computed evaluation");
|
|
47
|
+
if (Object.is(value, this.current))
|
|
48
|
+
return;
|
|
49
|
+
this.current = value;
|
|
50
|
+
for (const observer of [...this.subscribers])
|
|
51
|
+
observer.invalidate();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
class Computed {
|
|
55
|
+
read;
|
|
56
|
+
$$zudoReactive = "zudo-react.reactive.v1";
|
|
57
|
+
id = `computed:${core.nextId()}`;
|
|
58
|
+
subscribers = new Set();
|
|
59
|
+
dependencies = new Set();
|
|
60
|
+
cached;
|
|
61
|
+
dirty = true;
|
|
62
|
+
evaluatingNow = false;
|
|
63
|
+
constructor(read) {
|
|
64
|
+
this.read = read;
|
|
65
|
+
}
|
|
66
|
+
get value() {
|
|
67
|
+
if (this.evaluatingNow) {
|
|
68
|
+
throw new Error(`ZR_COMPUTED_CYCLE: ${[...evaluationStack.map((entry) => entry.id), this.id].join(" -> ")}`);
|
|
69
|
+
}
|
|
70
|
+
if (this.dirty)
|
|
71
|
+
this.evaluate();
|
|
72
|
+
track(this);
|
|
73
|
+
if (this.subscribers.size === 0) {
|
|
74
|
+
detachAndRelease(this);
|
|
75
|
+
this.dirty = true;
|
|
76
|
+
}
|
|
77
|
+
return this.cached;
|
|
78
|
+
}
|
|
79
|
+
evaluate() {
|
|
80
|
+
detachAndRelease(this);
|
|
81
|
+
const previous = currentObserver;
|
|
82
|
+
currentObserver = this;
|
|
83
|
+
this.evaluatingNow = true;
|
|
84
|
+
evaluationStack.push(this);
|
|
85
|
+
evaluating++;
|
|
86
|
+
try {
|
|
87
|
+
this.cached = this.read();
|
|
88
|
+
this.dirty = false;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
detachAndRelease(this);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
evaluating--;
|
|
96
|
+
evaluationStack.pop();
|
|
97
|
+
this.evaluatingNow = false;
|
|
98
|
+
currentObserver = previous;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
invalidate() {
|
|
102
|
+
if (this.dirty)
|
|
103
|
+
return;
|
|
104
|
+
this.dirty = true;
|
|
105
|
+
for (const observer of [...this.subscribers])
|
|
106
|
+
observer.invalidate();
|
|
107
|
+
}
|
|
108
|
+
release() {
|
|
109
|
+
if (this.subscribers.size === 0) {
|
|
110
|
+
detachAndRelease(this);
|
|
111
|
+
this.dirty = true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function release(source) {
|
|
116
|
+
if (source instanceof Computed)
|
|
117
|
+
source.release();
|
|
118
|
+
}
|
|
119
|
+
function detachAndRelease(observer) {
|
|
120
|
+
const sources = [...observer.dependencies];
|
|
121
|
+
detach(observer);
|
|
122
|
+
for (const source of sources)
|
|
123
|
+
release(source);
|
|
124
|
+
}
|
|
125
|
+
export function signal(initial) {
|
|
126
|
+
return new Writable(initial);
|
|
127
|
+
}
|
|
128
|
+
export function computed(read) {
|
|
129
|
+
return new Computed(read);
|
|
130
|
+
}
|
|
131
|
+
export function readSnapshot(value) {
|
|
132
|
+
return untracked(() => value.value);
|
|
133
|
+
}
|
|
134
|
+
export function subscribe(callback, options = {}) {
|
|
135
|
+
let disposed = false;
|
|
136
|
+
const observer = {
|
|
137
|
+
id: options.id ?? `subscriber:${core.nextId()}`,
|
|
138
|
+
dependencies: new Set(),
|
|
139
|
+
invalidate() {
|
|
140
|
+
enqueue(job);
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
const job = {
|
|
144
|
+
id: observer.id,
|
|
145
|
+
phase: options.phase ?? "commit",
|
|
146
|
+
active: () => !disposed && (options.active?.() ?? true),
|
|
147
|
+
run: () => subscription.run(),
|
|
148
|
+
...(options.report ? { report: options.report } : {}),
|
|
149
|
+
};
|
|
150
|
+
const subscription = {
|
|
151
|
+
id: observer.id,
|
|
152
|
+
run() {
|
|
153
|
+
if (!job.active())
|
|
154
|
+
return;
|
|
155
|
+
detachAndRelease(observer);
|
|
156
|
+
const previous = currentObserver;
|
|
157
|
+
currentObserver = observer;
|
|
158
|
+
try {
|
|
159
|
+
callback();
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
currentObserver = previous;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
dispose() {
|
|
166
|
+
disposed = true;
|
|
167
|
+
detachAndRelease(observer);
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
return subscription;
|
|
171
|
+
}
|
|
172
|
+
/** Internal test introspection; absent from every public entry. */
|
|
173
|
+
export function subscriberCount(value) {
|
|
174
|
+
return value instanceof Writable || value instanceof Computed ? value.subscribers.size : 0;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=reactive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../src/zudo-react/reactive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwB,MAAM,gBAAgB,CAAC;AAW/D,IAAI,eAAe,GAAoB,IAAI,CAAC;AAC5C,IAAI,UAAU,GAAG,CAAC,CAAC;AACnB,MAAM,eAAe,GAAwB,EAAE,CAAC;AAChD,IAAI,MAAM,GAAG,CAAC,CAAC;AAEf,iEAAiE;AACjE,MAAM,IAAI,GAAG,EAAE,gDAAgD,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAEhG,SAAS,KAAK,CAAC,MAAc;IAC3B,IAAI,CAAC,eAAe;QAAE,OAAO;IAC7B,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACxC,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AACD,SAAS,MAAM,CAAC,QAAkB;IAChC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,YAAY;QAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChF,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AACD,SAAS,SAAS,CAAI,EAAW;IAC/B,MAAM,QAAQ,GAAG,eAAe,CAAC;IACjC,eAAe,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,eAAe,GAAG,QAAQ,CAAC;IAC7B,CAAC;AACH,CAAC;AACD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,MAAM,QAAQ;IAIQ;IAHX,cAAc,GAAG,wBAAiC,CAAC;IACnD,cAAc,GAAG,wBAAiC,CAAC;IACnD,WAAW,GAAG,IAAI,GAAG,EAAY,CAAC;IAC3C,YAAoB,OAAU;QAAV,YAAO,GAAP,OAAO,CAAG;QAC5B,IAAI,CAAC,IAAI,CAAC,gDAAgD,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,KAAK;QACP,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,CAAC,KAAQ;QAChB,IAAI,UAAU,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAC3F,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO;QAC3C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;YAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;IACtE,CAAC;CACF;AAED,MAAM,QAAQ;IAQiB;IAPpB,cAAc,GAAG,wBAAiC,CAAC;IACnD,EAAE,GAAG,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;IACjC,WAAW,GAAG,IAAI,GAAG,EAAY,CAAC;IAClC,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,CAAK;IACX,KAAK,GAAG,IAAI,CAAC;IACb,aAAa,GAAG,KAAK,CAAC;IAC9B,YAA6B,IAAa;QAAb,SAAI,GAAJ,IAAI,CAAS;IAAG,CAAC;IAC9C,IAAI,KAAK;QACP,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,sBAAsB,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAC5F,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAChC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IACO,QAAQ;QACd,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,QAAQ,GAAG,eAAe,CAAC;QACjC,eAAe,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,eAAe,CAAC,IAAI,CAAC,IAAyB,CAAC,CAAC;QAChD,UAAU,EAAE,CAAC;QACb,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,UAAU,EAAE,CAAC;YACb,eAAe,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,eAAe,GAAG,QAAQ,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,UAAU;QACR,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;YAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;IACtE,CAAC;IACD,OAAO;QACL,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAChC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AAED,SAAS,OAAO,CAAC,MAAc;IAC7B,IAAI,MAAM,YAAY,QAAQ;QAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AACnD,CAAC;AACD,SAAS,gBAAgB,CAAC,QAAkB;IAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjB,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,MAAM,CAAI,OAAU;IAClC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC;AACD,MAAM,UAAU,QAAQ,CAAI,IAAa;IACvC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AACD,MAAM,UAAU,YAAY,CAAI,KAAwB;IACtD,OAAO,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAOD,MAAM,UAAU,SAAS,CACvB,QAAoB,EACpB,UAA0F,EAAE;IAE5F,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,QAAQ,GAAa;QACzB,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,EAAE;QAC/C,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,UAAU;YACR,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;KACF,CAAC;IACF,MAAM,GAAG,GAAQ;QACf,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ;QAChC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC;QACvD,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE;QAC7B,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;IACF,MAAM,YAAY,GAAiB;QACjC,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,GAAG;YACD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE;gBAAE,OAAO;YAC1B,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM,QAAQ,GAAG,eAAe,CAAC;YACjC,eAAe,GAAG,QAAQ,CAAC;YAC3B,IAAI,CAAC;gBACH,QAAQ,EAAE,CAAC;YACb,CAAC;oBAAS,CAAC;gBACT,eAAe,GAAG,QAAQ,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,OAAO;YACL,QAAQ,GAAG,IAAI,CAAC;YAChB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;IACF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,KAA8B;IAC5D,OAAO,KAAK,YAAY,QAAQ,IAAI,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["import { enqueue, type Job, type Phase } from \"./scheduler.js\";\nimport type { ReadonlySignal, Signal } from \"./reactive-types.js\";\n\ninterface Source {\n readonly subscribers: Set<Observer>;\n}\ninterface Observer {\n readonly id: string;\n readonly dependencies: Set<Source>;\n invalidate(): void;\n}\nlet currentObserver: Observer | null = null;\nlet evaluating = 0;\nconst evaluationStack: Computed<unknown>[] = [];\nlet nextId = 0;\n\n// The quoted own key is the retained runtime definition witness.\nconst core = { \"@takazudo/zfb/zudo-react/runtime-definition-v1\": true, nextId: () => ++nextId };\n\nfunction track(source: Source): void {\n if (!currentObserver) return;\n source.subscribers.add(currentObserver);\n currentObserver.dependencies.add(source);\n}\nfunction detach(observer: Observer): void {\n for (const source of observer.dependencies) source.subscribers.delete(observer);\n observer.dependencies.clear();\n}\nfunction untracked<T>(fn: () => T): T {\n const previous = currentObserver;\n currentObserver = null;\n try {\n return fn();\n } finally {\n currentObserver = previous;\n }\n}\nexport { untracked };\n\nclass Writable<T> implements Signal<T>, Source {\n readonly $$zudoReactive = \"zudo-react.reactive.v1\" as const;\n readonly $$zudoWritable = \"zudo-react.writable.v1\" as const;\n readonly subscribers = new Set<Observer>();\n constructor(private current: T) {\n if (!core[\"@takazudo/zfb/zudo-react/runtime-definition-v1\"])\n throw new Error(\"ZR_RUNTIME_DEFINITION\");\n }\n get value(): T {\n track(this);\n return this.current;\n }\n set value(value: T) {\n if (evaluating > 0) throw new Error(\"ZR_COMPUTED_WRITE: write during computed evaluation\");\n if (Object.is(value, this.current)) return;\n this.current = value;\n for (const observer of [...this.subscribers]) observer.invalidate();\n }\n}\n\nclass Computed<T> implements ReadonlySignal<T>, Source, Observer {\n readonly $$zudoReactive = \"zudo-react.reactive.v1\" as const;\n readonly id = `computed:${core.nextId()}`;\n readonly subscribers = new Set<Observer>();\n readonly dependencies = new Set<Source>();\n private cached!: T;\n private dirty = true;\n private evaluatingNow = false;\n constructor(private readonly read: () => T) {}\n get value(): T {\n if (this.evaluatingNow) {\n throw new Error(\n `ZR_COMPUTED_CYCLE: ${[...evaluationStack.map((entry) => entry.id), this.id].join(\" -> \")}`,\n );\n }\n if (this.dirty) this.evaluate();\n track(this);\n if (this.subscribers.size === 0) {\n detachAndRelease(this);\n this.dirty = true;\n }\n return this.cached;\n }\n private evaluate(): void {\n detachAndRelease(this);\n const previous = currentObserver;\n currentObserver = this;\n this.evaluatingNow = true;\n evaluationStack.push(this as Computed<unknown>);\n evaluating++;\n try {\n this.cached = this.read();\n this.dirty = false;\n } catch (error) {\n detachAndRelease(this);\n throw error;\n } finally {\n evaluating--;\n evaluationStack.pop();\n this.evaluatingNow = false;\n currentObserver = previous;\n }\n }\n invalidate(): void {\n if (this.dirty) return;\n this.dirty = true;\n for (const observer of [...this.subscribers]) observer.invalidate();\n }\n release(): void {\n if (this.subscribers.size === 0) {\n detachAndRelease(this);\n this.dirty = true;\n }\n }\n}\n\nfunction release(source: Source): void {\n if (source instanceof Computed) source.release();\n}\nfunction detachAndRelease(observer: Observer): void {\n const sources = [...observer.dependencies];\n detach(observer);\n for (const source of sources) release(source);\n}\n\nexport function signal<T>(initial: T): Signal<T> {\n return new Writable(initial);\n}\nexport function computed<T>(read: () => T): ReadonlySignal<T> {\n return new Computed(read);\n}\nexport function readSnapshot<T>(value: ReadonlySignal<T>): T {\n return untracked(() => value.value);\n}\n\nexport interface Subscription {\n readonly id: string;\n run(): void;\n dispose(): void;\n}\nexport function subscribe(\n callback: () => void,\n options: { phase?: Phase; id?: string; active?: () => boolean; report?: Job[\"report\"] } = {},\n): Subscription {\n let disposed = false;\n const observer: Observer = {\n id: options.id ?? `subscriber:${core.nextId()}`,\n dependencies: new Set(),\n invalidate() {\n enqueue(job);\n },\n };\n const job: Job = {\n id: observer.id,\n phase: options.phase ?? \"commit\",\n active: () => !disposed && (options.active?.() ?? true),\n run: () => subscription.run(),\n ...(options.report ? { report: options.report } : {}),\n };\n const subscription: Subscription = {\n id: observer.id,\n run() {\n if (!job.active()) return;\n detachAndRelease(observer);\n const previous = currentObserver;\n currentObserver = observer;\n try {\n callback();\n } finally {\n currentObserver = previous;\n }\n },\n dispose() {\n disposed = true;\n detachAndRelease(observer);\n },\n };\n return subscription;\n}\n\n/** Internal test introspection; absent from every public entry. */\nexport function subscriberCount(value: ReadonlySignal<unknown>): number {\n return value instanceof Writable || value instanceof Computed ? value.subscribers.size : 0;\n}\n"]}
|