@pravosleva/reactive-engine 2.5.0-alpha.8 → 2.6.0-beta.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/dist/angular/index.cjs +1 -1
- package/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.mjs +1 -1
- package/dist/core/core.advanced.optimization.test.d.ts +2 -0
- package/dist/core/core.advanced.optimization.test.d.ts.map +1 -0
- package/dist/core/core.d.ts +20 -8
- package/dist/core/core.d.ts.map +1 -1
- package/dist/core/core.logger.d.ts.map +1 -1
- package/dist/core/core.method.computed.d.ts.map +1 -1
- package/dist/core/core.method.reactive.d.ts +3 -0
- package/dist/core/core.method.reactive.d.ts.map +1 -1
- package/dist/core/core.method.resource.d.ts +13 -0
- package/dist/core/core.method.resource.d.ts.map +1 -0
- package/dist/core/core.method.signal.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core.automatic.cjs +1 -1
- package/dist/core.automatic.cjs.map +1 -1
- package/dist/core.automatic.mjs +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.global.cjs +1 -1
- package/dist/core.global.cjs.map +1 -1
- package/dist/core.global.mjs +1 -1
- package/dist/core.logger.cjs +2 -0
- package/dist/core.logger.cjs.map +1 -0
- package/dist/core.logger.mjs +51 -0
- package/dist/core.logger.mjs.map +1 -0
- package/dist/core.method.computed.cjs +1 -1
- package/dist/core.method.computed.cjs.map +1 -1
- package/dist/core.method.computed.mjs +71 -86
- package/dist/core.method.computed.mjs.map +1 -1
- package/dist/core.method.reactive.cjs +1 -1
- package/dist/core.method.reactive.cjs.map +1 -1
- package/dist/core.method.reactive.mjs +45 -104
- package/dist/core.method.reactive.mjs.map +1 -1
- package/dist/core.method.resource.cjs +2 -0
- package/dist/core.method.resource.cjs.map +1 -0
- package/dist/core.method.resource.mjs +143 -0
- package/dist/core.method.resource.mjs.map +1 -0
- package/dist/core.method.signal.cjs +1 -1
- package/dist/core.method.signal.cjs.map +1 -1
- package/dist/core.method.signal.mjs +67 -38
- package/dist/core.method.signal.mjs.map +1 -1
- package/dist/core.mjs +80 -107
- package/dist/core.mjs.map +1 -1
- package/dist/decorators/withThrottleComputed/withThrottleComputed.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index2.cjs +1 -1
- package/dist/index2.mjs +5 -5
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.mjs +1 -1
- package/dist/reactive-engine.umd.js +13 -0
- package/dist/reactive-engine.umd.js.map +1 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/core/core.advanced.reactive-framework-test-suite.p3.test.d.ts +0 -2
- package/dist/core/core.advanced.reactive-framework-test-suite.p3.test.d.ts.map +0 -1
- package/dist/reactive-engine@2.5.0-alpha.8.umd.js +0 -13
- package/dist/reactive-engine@2.5.0-alpha.8.umd.js.map +0 -1
|
@@ -1,93 +1,78 @@
|
|
|
1
1
|
//#region src/core/core.method.computed.ts
|
|
2
2
|
function e(e, t, n) {
|
|
3
|
-
let r =
|
|
4
|
-
if (
|
|
5
|
-
|
|
6
|
-
if (t) return t;
|
|
7
|
-
}
|
|
8
|
-
let a = e.computedCache.get(t);
|
|
9
|
-
if (a) {
|
|
10
|
-
let t = a._node || a;
|
|
11
|
-
if (e.batchDepth === 0) t.state = 2;
|
|
12
|
-
else return a;
|
|
13
|
-
}
|
|
14
|
-
let o, s = !0, c = 0, l = !1, u = -1, d = 2, f = -1, p = /* @__PURE__ */ new Set(), m = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Set(), g = /* @__PURE__ */ new Set(), _ = (e) => {
|
|
3
|
+
let r = e.computedCache.get(t);
|
|
4
|
+
if (r) return r;
|
|
5
|
+
let i, a = !0, o = 0, s = !1, c = -1, l = 2, u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), m = (e) => {
|
|
15
6
|
if (!e) return;
|
|
16
7
|
let t = e._node || e;
|
|
17
8
|
if (t.dependencies && t.dependencies.size > 0) {
|
|
18
9
|
for (let n of t.dependencies) {
|
|
19
10
|
let r = n, i = r._node || r;
|
|
20
|
-
i.subscribers && (i.subscribers.delete(t), i.subscribers.delete(e), i.subscribers.delete(
|
|
11
|
+
i.subscribers && (i.subscribers.delete(t), i.subscribers.delete(e), i.subscribers.delete(v), i.type === "computed" && i.subscribers.size === 0 && m(i));
|
|
21
12
|
}
|
|
22
13
|
t.dependencies.clear(), t.depVersions && t.depVersions.clear();
|
|
23
14
|
}
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
let
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
n = !0;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
15
|
+
}, h = -1, g = (t) => {
|
|
16
|
+
if (!s || l === 2) return t.run();
|
|
17
|
+
if (h === e.epoch && e.batchDepth === 0) return !1;
|
|
18
|
+
let n = !1;
|
|
19
|
+
if (u && u.size > 0) for (let e of u) {
|
|
20
|
+
let t = e._node || e;
|
|
21
|
+
if (t.type === "computed" && t.update && t.update(), e.hasBatchValue || d.get(e) !== t.version) {
|
|
22
|
+
n = !0;
|
|
23
|
+
break;
|
|
36
24
|
}
|
|
37
|
-
return e.epoch, n || s ? t.run() : (d = 0, !1);
|
|
38
25
|
}
|
|
39
|
-
return
|
|
40
|
-
},
|
|
26
|
+
return h = e.epoch, n || a ? t.run() : (l = 0, !1);
|
|
27
|
+
}, _ = 0, v = {
|
|
41
28
|
id: e.subscriberId++,
|
|
42
|
-
dependencies:
|
|
43
|
-
subscribers:
|
|
44
|
-
ownedEffects:
|
|
29
|
+
dependencies: u,
|
|
30
|
+
subscribers: p,
|
|
31
|
+
ownedEffects: f,
|
|
45
32
|
depth: 1,
|
|
46
33
|
type: "computed",
|
|
47
34
|
fn: t,
|
|
48
35
|
get version() {
|
|
49
|
-
return
|
|
36
|
+
return o;
|
|
50
37
|
},
|
|
51
38
|
get state() {
|
|
52
|
-
return
|
|
39
|
+
return l;
|
|
53
40
|
},
|
|
54
41
|
set state(e) {
|
|
55
|
-
|
|
42
|
+
l = e;
|
|
56
43
|
},
|
|
57
44
|
get depVersions() {
|
|
58
|
-
return
|
|
45
|
+
return d;
|
|
59
46
|
},
|
|
60
|
-
update: () => v
|
|
47
|
+
update: () => g(v),
|
|
61
48
|
run: () => {
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
e.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (g.length = 0, p.size > 0) for (let e of p) g.push(e);
|
|
70
|
-
p.clear();
|
|
49
|
+
if (c === e.epoch && s && l === 0 && e.batchDepth === 0) return !1;
|
|
50
|
+
if (c = e.epoch, h = e.epoch, e.cycleDetectionStack.has(v)) throw Error("[Graph Error] Cyclic dependency detected");
|
|
51
|
+
e.cycleDetectionStack.add(v);
|
|
52
|
+
let r = e.activeConsumer, p = e.activeOwner;
|
|
53
|
+
e.activeConsumer = v, e.activeOwner = v, _++, v.activeRunId = _;
|
|
54
|
+
let m = u.size > 0 ? Array.from(u) : null;
|
|
55
|
+
u.clear();
|
|
71
56
|
try {
|
|
72
|
-
if (
|
|
73
|
-
for (let e of
|
|
74
|
-
|
|
57
|
+
if (f.size > 0) {
|
|
58
|
+
for (let e of f) e && typeof e.dispose == "function" && e.dispose();
|
|
59
|
+
f.clear();
|
|
75
60
|
}
|
|
76
61
|
let r = t();
|
|
77
|
-
if (
|
|
78
|
-
let e =
|
|
79
|
-
for (let t
|
|
80
|
-
let n =
|
|
81
|
-
if (!e || !
|
|
62
|
+
if (m !== null) {
|
|
63
|
+
let e = m.length === u.size;
|
|
64
|
+
for (let t of m) {
|
|
65
|
+
let n = t;
|
|
66
|
+
if (!e || !u.has(n)) {
|
|
82
67
|
let e = n._node || n;
|
|
83
|
-
e.subscribers && e.subscribers.delete(
|
|
68
|
+
e.subscribers && e.subscribers.delete(v), d.delete(n);
|
|
84
69
|
}
|
|
85
70
|
}
|
|
86
71
|
}
|
|
87
|
-
let
|
|
88
|
-
if (
|
|
89
|
-
let t;
|
|
90
|
-
|
|
72
|
+
let c = a || !Object.is(i, r);
|
|
73
|
+
if (c) {
|
|
74
|
+
let t = a ? void 0 : typeof i == "object" && i ? JSON.parse(JSON.stringify(i)) : i;
|
|
75
|
+
i = r, o++, e.log && n && e.log({
|
|
91
76
|
type: "computed",
|
|
92
77
|
label: n,
|
|
93
78
|
details: {
|
|
@@ -96,69 +81,69 @@ function e(e, t, n) {
|
|
|
96
81
|
}
|
|
97
82
|
});
|
|
98
83
|
}
|
|
99
|
-
|
|
100
|
-
let
|
|
101
|
-
for (let e of
|
|
84
|
+
a = !1, l = 0, s = !0;
|
|
85
|
+
let p = 0;
|
|
86
|
+
for (let e of u) {
|
|
102
87
|
let t = e, n = t._node || t;
|
|
103
|
-
|
|
88
|
+
d.set(t, n.version), n.subscribers && n.subscribers.add(v), n.depth !== void 0 && n.depth > p && (p = n.depth);
|
|
104
89
|
}
|
|
105
|
-
return
|
|
90
|
+
return v.depth = p + 1, c;
|
|
106
91
|
} finally {
|
|
107
|
-
e.activeConsumer =
|
|
92
|
+
e.activeConsumer = r, e.activeOwner = p, e.cycleDetectionStack.delete(v);
|
|
108
93
|
}
|
|
109
94
|
},
|
|
110
95
|
markDirty: (t) => {
|
|
111
|
-
if (!(
|
|
112
|
-
|
|
113
|
-
for (let t of
|
|
96
|
+
if (!(l >= t)) {
|
|
97
|
+
l = t;
|
|
98
|
+
for (let t of p) {
|
|
114
99
|
let n = t._node || t;
|
|
115
100
|
n.type === "effect" ? (n.isDirty = !0, e.scheduleEffect(t)) : n.markDirty && n.markDirty(1);
|
|
116
101
|
}
|
|
117
102
|
}
|
|
118
103
|
}
|
|
119
|
-
},
|
|
104
|
+
}, y = {
|
|
120
105
|
get value() {
|
|
121
106
|
let t = e.activeConsumer;
|
|
122
|
-
if (t && t !==
|
|
123
|
-
|
|
124
|
-
let e =
|
|
125
|
-
n.depth !== void 0 && e >= n.depth && (n.depth = e + 1), t.activeRunId !== void 0 && (
|
|
107
|
+
if (t && t !== v) {
|
|
108
|
+
p.add(t), t.dependencies.add(v);
|
|
109
|
+
let e = v.depth || 1, n = t._node || t;
|
|
110
|
+
n.depth !== void 0 && e >= n.depth && (n.depth = e + 1), t.activeRunId !== void 0 && (v._lastSeenInRunId = t.activeRunId);
|
|
126
111
|
}
|
|
127
|
-
return v
|
|
112
|
+
return g(v), t && t.depVersions && t.depVersions.set(y, o), i;
|
|
128
113
|
},
|
|
129
114
|
get valueWithoutTracking() {
|
|
130
|
-
return
|
|
115
|
+
return i;
|
|
131
116
|
},
|
|
132
117
|
get version() {
|
|
133
|
-
return
|
|
118
|
+
return o;
|
|
134
119
|
},
|
|
135
120
|
get dependencies() {
|
|
136
|
-
return
|
|
121
|
+
return u;
|
|
137
122
|
},
|
|
138
123
|
subscribe(t) {
|
|
139
|
-
let n = {
|
|
124
|
+
let n = this, r = {
|
|
140
125
|
id: e.subscriberId++,
|
|
141
126
|
isDirty: !0,
|
|
142
127
|
depth: 9999,
|
|
143
128
|
dependencies: /* @__PURE__ */ new Set(),
|
|
144
129
|
type: "effect",
|
|
145
130
|
run: () => {
|
|
146
|
-
if (!
|
|
147
|
-
t(
|
|
131
|
+
if (!r.isDisposed) try {
|
|
132
|
+
t(n.value);
|
|
148
133
|
} catch (e) {
|
|
149
134
|
console.error(e);
|
|
150
135
|
}
|
|
151
136
|
}
|
|
152
137
|
};
|
|
153
|
-
return
|
|
154
|
-
|
|
138
|
+
return p.add(r), t(this.value), () => {
|
|
139
|
+
r.isDisposed = !0, p.delete(r), r.dependencies.clear();
|
|
155
140
|
};
|
|
156
141
|
},
|
|
157
142
|
subscribeState(e) {
|
|
158
|
-
return
|
|
143
|
+
return y.subscribe(e);
|
|
159
144
|
},
|
|
160
145
|
destroy: () => {
|
|
161
|
-
|
|
146
|
+
m(v), p && p.clear(), e.computedCache.delete(t), u.clear(), d.clear(), f.clear(), a = !0, l = 2, s = !1;
|
|
162
147
|
},
|
|
163
148
|
__subscribe(t) {
|
|
164
149
|
let n = {
|
|
@@ -167,12 +152,12 @@ function e(e, t, n) {
|
|
|
167
152
|
run: t,
|
|
168
153
|
isDirty: !1
|
|
169
154
|
};
|
|
170
|
-
return
|
|
171
|
-
|
|
155
|
+
return p.add(n), () => {
|
|
156
|
+
p.delete(n);
|
|
172
157
|
};
|
|
173
158
|
}
|
|
174
159
|
};
|
|
175
|
-
return
|
|
160
|
+
return y.run = () => v.run(), e.computedCache.set(t, y), y._node = v, y.subscribers = p, y;
|
|
176
161
|
}
|
|
177
162
|
//#endregion
|
|
178
163
|
export { e as createComputed };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.method.computed.mjs","names":[],"sources":["../src/core/core.method.computed.ts"],"sourcesContent":["import { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const fnSourceKey = fn.toString()\n const cacheKey = signalName ? `${signalName}:${fnSourceKey}` : fnSourceKey\n\n if (!engine.computedStringCache) {\n engine.computedStringCache = new Map<string, any>()\n }\n\n if (engine.batchDepth > 0) {\n const existingString = engine.computedStringCache.get(cacheKey)\n if (existingString) {\n return existingString as Computed<T>\n }\n }\n\n const existingWeak = engine.computedCache.get(fn)\n if (existingWeak) {\n const actNode = existingWeak._node || existingWeak\n if (engine.batchDepth === 0) {\n actNode.state = 2\n } else {\n return existingWeak as Computed<T>\n }\n }\n\n let value: T\n let isDirty = true\n let version = 0\n let isInitialized = false\n let evaluatedInEpoch = -1\n let state = 2 // 2 = DIRTY, 1 = CHECK, 0 = STABLE\n\n let lastEvaluatedIteration = -1\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n const ownedEffects = new Set<any>()\n const subscribers = new Set<any>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n for (const unknownDep of actNode.dependencies) {\n const dep = unknownDep as any\n const rawDepNode = dep._node || dep\n\n if (rawDepNode.subscribers) {\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n }\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n }\n }\n\n let verifiedInEpoch = -1\n\n const updateIfNecessary = (node: any): boolean => {\n const currentBatchIteration = engine['batchIterationId']\n if (currentBatchIteration !== undefined && lastEvaluatedIteration === currentBatchIteration) {\n return false\n }\n\n // Если узел уже был вычислен в текущей эпохе ядра и стабилен — мгновенный выход\n if (evaluatedInEpoch === engine.epoch && isInitialized && state === 0) {\n return false\n }\n\n // Если узел гарантированно грязный или еще не инициализирован — вычисляем\n if (!isInitialized || state === 2) {\n return node.run()\n }\n\n // Если узел в состоянии CHECK (1), опрашиваем родителей\n if (state === 1) {\n let hasChangedParent = false\n\n if (dependencies && dependencies.size > 0) {\n for (const dep of dependencies) {\n const rawDep = dep._node || dep\n\n // Если родитель — это другой computed, просим его актуализироваться сначала (Topological Order)\n if (rawDep.type === 'computed') {\n if (rawDep.update) {\n rawDep.update()\n }\n }\n\n // Проверяем, изменилась ли версия родителя относительно той, что мы запомнили\n if ((dep as any).hasBatchValue || depVersions.get(dep) !== rawDep.version) {\n hasChangedParent = true\n break // Хватит одного изменения, чтобы узел стал грязным\n }\n }\n }\n\n verifiedInEpoch = engine.epoch\n\n if (hasChangedParent || isDirty) {\n return node.run()\n }\n\n // ⚛️ ГАШЕНИЕ ВОЛНЫ (Value-Equality & Unreachable Cut):\n // Если состояние было CHECK (1), но после опроса родителей ни одна версия\n // не изменилась, мы просто стабилизируем узел БЕЗ его перевычисления.\n state = 0\n return false\n }\n\n state = 0\n return false\n }\n\n let currentRunId = 0\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n ownedEffects,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get state() { return state },\n set state(val: number) { state = val },\n get depVersions() { return depVersions },\n update: () => updateIfNecessary(computedNode),\n run: () => {\n const currentBatchIteration = engine['batchIterationId']\n if (currentBatchIteration !== undefined && lastEvaluatedIteration === currentBatchIteration) {\n return false\n }\n\n if (evaluatedInEpoch === engine.epoch && isInitialized && state === 0 && engine.batchDepth === 0) {\n return false\n }\n evaluatedInEpoch = engine.epoch\n verifiedInEpoch = engine.epoch\n\n if (currentBatchIteration !== undefined) {\n lastEvaluatedIteration = currentBatchIteration\n }\n\n if (engine.cycleDetectionStack.has(computedNode)) {\n throw new Error('[Graph Error] Cyclic dependency detected')\n }\n engine.cycleDetectionStack.add(computedNode)\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n engine.activeConsumer = computedNode\n engine.activeOwner = computedNode\n\n currentRunId++\n computedNode.activeRunId = currentRunId\n\n if (!engine._poolArr) engine._poolArr = []\n const oldDeps = engine._poolArr\n oldDeps.length = 0\n\n if (dependencies.size > 0) {\n for (const dep of dependencies) {\n oldDeps.push(dep)\n }\n }\n dependencies.clear()\n\n try {\n if (ownedEffects.size > 0) {\n for (const child of ownedEffects) {\n if (child && typeof child.dispose === 'function') {\n child.dispose()\n }\n }\n ownedEffects.clear()\n }\n\n const newValue = fn()\n\n if (oldDeps.length > 0) {\n const isSizeIdentical = oldDeps.length === dependencies.size\n for (let i = 0; i < oldDeps.length; i++) {\n const dep = oldDeps[i]\n if (!isSizeIdentical || !dependencies.has(dep)) {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n depVersions.delete(dep)\n }\n }\n }\n\n const changed = isDirty || !Object.is(value, newValue)\n\n if (changed) {\n let previousValueSnapshot = undefined\n if (engine.log && signalName && engine.logger && engine.logger.isEnabled) {\n previousValueSnapshot = isDirty ? undefined : (typeof value === 'object' && value !== null ? JSON.parse(JSON.stringify(value)) : value)\n }\n\n value = newValue\n version++\n\n if (engine.log && signalName) {\n engine.log({\n type: 'computed',\n label: signalName,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n }\n\n isDirty = false\n state = 0\n isInitialized = true\n\n let maxDepDepth = 0\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n const rawNode = dep._node || dep\n\n // Синхронизируем эталонные версии сигналов и компьютедов батча\n depVersions.set(dep, rawNode.version)\n\n if (rawNode.subscribers) rawNode.subscribers.add(computedNode)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) {\n maxDepDepth = rawNode.depth\n }\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n engine.cycleDetectionStack.delete(computedNode)\n }\n },\n markDirty: (parentState: number) => {\n if (state >= parentState) return\n state = parentState\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n // Каскадно передаем статус проверки вниз по графу зависимостей\n rawSub.markDirty(1)\n }\n }\n }\n\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n const consumer = engine.activeConsumer\n if (consumer && consumer !== computedNode) {\n subscribers.add(consumer)\n consumer.dependencies.add(computedNode)\n\n const currentDepth = computedNode.depth || 1\n const consumerRaw = consumer._node || consumer\n if (consumerRaw.depth !== undefined && currentDepth >= consumerRaw.depth) {\n consumerRaw.depth = currentDepth + 1\n }\n\n if (consumer.activeRunId !== undefined) {\n computedNode._lastSeenInRunId = consumer.activeRunId\n }\n }\n\n updateIfNecessary(computedNode)\n\n if (consumer && consumer.depVersions) {\n consumer.depVersions.set(computedInstance, version)\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\n get dependencies() { return dependencies },\n\n subscribe(cb: (val: T) => void): CleanupFn {\n const fakeEffect: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 9999,\n dependencies: new Set(),\n type: 'effect',\n run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(computedInstance.value) } catch (err) { console.error(err) }\n }\n }\n subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n releaseNode(computedNode)\n if (subscribers) subscribers.clear()\n\n engine.computedCache.delete(fn)\n if (engine.computedStringCache) {\n engine.computedStringCache.delete(cacheKey)\n }\n\n isDirty = true\n state = 2\n isInitialized = false\n },\n __subscribe(cb: () => void): CleanupFn {\n const hookEffect: any = {\n id: engine.subscriberId++,\n type: 'effect',\n run: cb,\n isDirty: false\n }\n subscribers.add(hookEffect)\n return () => {\n hookEffect.isDisposed = true\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n computedInstance.run = () => computedNode.run()\n\n engine.computedCache.set(fn, computedInstance)\n if (engine.batchDepth > 0) {\n engine.computedStringCache.set(cacheKey, computedInstance)\n }\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n\n return computedInstance\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.method.computed.mjs","names":[],"sources":["../src/core/core.method.computed.ts"],"sourcesContent":["// core.method.computed.ts\nimport { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n // 1. Быстрый канонический WeakMap путь — единственный безопасный для долгоживущих объектов\n const existing = engine.computedCache.get(fn)\n if (existing) return existing as Computed<T>\n\n let value: T\n let isDirty = true\n let version = 0\n let isInitialized = false\n let evaluatedInEpoch = -1\n let state = 2 // 2 = DIRTY, 1 = CHECK, 0 = STABLE\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n const ownedEffects = new Set<any>()\n const subscribers = new Set<any>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n for (const unknownDep of actNode.dependencies) {\n const dep = unknownDep as any\n const rawDepNode = dep._node || dep\n\n if (rawDepNode.subscribers) {\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n }\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n }\n }\n\n let verifiedInEpoch = -1\n\n const updateIfNecessary = (node: any): boolean => {\n if (!isInitialized || state === 2) {\n return node.run()\n }\n\n if (verifiedInEpoch === engine.epoch && engine.batchDepth === 0) {\n return false\n }\n\n let hasChangedParent = false\n\n if (dependencies && dependencies.size > 0) {\n for (const dep of dependencies) {\n const rawDep = dep._node || dep\n\n if (rawDep.type === 'computed') {\n if (rawDep.update) rawDep.update()\n }\n\n if (dep.hasBatchValue || depVersions.get(dep) !== rawDep.version) {\n hasChangedParent = true\n break\n }\n }\n }\n\n verifiedInEpoch = engine.epoch\n\n if (hasChangedParent || isDirty) {\n return node.run()\n }\n\n state = 0\n return false\n }\n\n let currentRunId = 0\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n ownedEffects,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get state() { return state },\n set state(val: number) { state = val },\n get depVersions() { return depVersions },\n update: () => updateIfNecessary(computedNode),\n run: () => {\n if (evaluatedInEpoch === engine.epoch && isInitialized && state === 0 && engine.batchDepth === 0) {\n return false\n }\n evaluatedInEpoch = engine.epoch\n verifiedInEpoch = engine.epoch\n\n if (engine.cycleDetectionStack.has(computedNode)) {\n throw new Error('[Graph Error] Cyclic dependency detected')\n }\n engine.cycleDetectionStack.add(computedNode)\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n engine.activeConsumer = computedNode\n engine.activeOwner = computedNode\n\n currentRunId++\n computedNode.activeRunId = currentRunId\n\n const oldDeps = dependencies.size > 0 ? Array.from(dependencies) : null\n dependencies.clear()\n\n try {\n if (ownedEffects.size > 0) {\n for (const child of ownedEffects) {\n if (child && typeof child.dispose === 'function') {\n child.dispose()\n }\n }\n ownedEffects.clear()\n }\n\n const newValue = fn()\n\n if (oldDeps !== null) {\n const isSizeIdentical = oldDeps.length === dependencies.size\n for (const unknownDep of oldDeps) {\n const dep = unknownDep as any\n if (!isSizeIdentical || !dependencies.has(dep)) {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n depVersions.delete(dep)\n }\n }\n }\n\n const changed = isDirty || !Object.is(value, newValue)\n\n if (changed) {\n const previousValueSnapshot = isDirty ? undefined : (typeof value === 'object' && value !== null ? JSON.parse(JSON.stringify(value)) : value)\n value = newValue\n version++\n\n if (engine.log && signalName) {\n engine.log({\n type: 'computed',\n label: signalName,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n }\n\n isDirty = false\n state = 0\n isInitialized = true\n\n let maxDepDepth = 0\n for (const unknownDep of dependencies) {\n const dep = unknownDep as any\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n if (rawNode.subscribers) rawNode.subscribers.add(computedNode)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) {\n maxDepDepth = rawNode.depth\n }\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n engine.cycleDetectionStack.delete(computedNode)\n }\n },\n markDirty: (parentState: number) => {\n if (state >= parentState) return\n state = parentState\n\n for (const sub of subscribers) {\n const rawSub = sub._node || sub\n if (rawSub.type === 'effect') {\n rawSub.isDirty = true\n engine.scheduleEffect(sub)\n } else if (rawSub.markDirty) {\n rawSub.markDirty(1)\n }\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n const consumer = engine.activeConsumer\n if (consumer && consumer !== computedNode) {\n subscribers.add(consumer)\n consumer.dependencies.add(computedNode)\n\n const currentDepth = computedNode.depth || 1\n const consumerRaw = consumer._node || consumer\n if (consumerRaw.depth !== undefined && currentDepth >= consumerRaw.depth) {\n consumerRaw.depth = currentDepth + 1\n }\n\n if (consumer.activeRunId !== undefined) {\n computedNode._lastSeenInRunId = consumer.activeRunId\n }\n }\n\n updateIfNecessary(computedNode)\n\n if (consumer && consumer.depVersions) {\n consumer.depVersions.set(computedInstance, version)\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\n get dependencies() { return dependencies },\n\n subscribe(cb: (val: T) => void): CleanupFn {\n // ⚛️ ФИКС УТЕЧКИ ПАМЯТИ: Выносим ссылку наружу, убираем сильное замыкание на инстанс\n const self = this\n const fakeEffect: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 9999,\n dependencies: new Set(),\n type: 'effect',\n run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(self.value) } catch (err) { console.error(err) }\n }\n }\n subscribers.add(fakeEffect)\n cb(this.value)\n return () => {\n fakeEffect.isDisposed = true\n subscribers.delete(fakeEffect)\n fakeEffect.dependencies.clear() // Разрываем связи с графом\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n releaseNode(computedNode)\n if (subscribers) subscribers.clear()\n engine.computedCache.delete(fn)\n\n // Безопасное зануление ссылок для помощи GC\n dependencies.clear()\n depVersions.clear()\n ownedEffects.clear()\n\n isDirty = true\n state = 2\n isInitialized = false\n },\n __subscribe(cb: () => void): CleanupFn {\n const hookEffect: any = {\n id: engine.subscriberId++,\n type: 'effect',\n run: cb,\n isDirty: false\n }\n subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n computedInstance.run = () => computedNode.run()\n engine.computedCache.set(fn, computedInstance)\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n\n return computedInstance\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(t,n
|
|
1
|
+
function e(e,t,n){if(e.proxyTargets.has(t))return t;if(e.proxyCache.has(t))return e.proxyCache.get(t);e.reactiveSignals.has(t)||e.reactiveSignals.set(t,new Map);let r=e.reactiveSignals.get(t),i=new Proxy(t,{get(t,i,a){if(i===`__subscribe`&&Array.isArray(t))return n=>{let i=r.get(`length`);return i||(i=e.signal(t.length),r.set(`length`,i)),i.subscribe(n)};if(Array.isArray(t)&&typeof i==`string`&&[`push`,`pop`,`shift`,`unshift`,`splice`,`sort`,`reverse`].includes(i))return(...n)=>{let o;return e.batch(()=>{o=Reflect.get(t,i).apply(a,n);let e=r.get(`length`);e&&(e.value=t.length),r.forEach((e,n)=>{n!==`length`&&(e.value=Reflect.get(t,n))})}),o};if(typeof i==`symbol`||i===`constructor`||i===`toJSON`)return Reflect.get(t,i,a);let o=r.get(i);if(!o){let a=Reflect.get(t,i);o=e.signal(a),r.set(i,o),typeof a==`object`&&a&&(o._proxyCache=e.reactive(a,n?`${n}.${String(i)}`:String(i)))}return o._proxyCache===void 0?o.value:(o.value,o._proxyCache)},set(t,n,i,a){let o=(e.proxyTargets.has(i),i),s=Reflect.get(t,n);if(s===o&&n!==`length`)return!0;Reflect.set(t,n,o);let c=r.get(n);if(c||(c=e.signal(s),r.set(n,c)),c._proxyCache=void 0,c.value=o,Array.isArray(t)&&n!==`length`){let e=r.get(`length`);e&&(e.value=t.length)}return!0}});return e.proxyCache.set(t,i),e.proxyTargets.add(i),i}exports.createReactive=e;
|
|
2
2
|
//# sourceMappingURL=core.method.reactive.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.method.reactive.cjs","names":[],"sources":["../src/core/core.method.reactive.ts"],"sourcesContent":["import { SignalOptions } from './types'\n\nexport function createReactive<T extends object>(\n engine: any,\n target: T,\n name?: string\n): T {\n if (target === null || typeof target !== 'object') {\n return target\n }\n\n // 1. Возвращаем уже существующий Proxy из кэша ядра\n if (engine.proxyCache.has(target)) {\n return engine.proxyCache.get(target) as T\n }\n if (engine.proxyTargets.has(target)) {\n return target\n }\n\n const signalMap = new Map<string | symbol, any>()\n engine.reactiveSignals.set(target, signalMap)\n\n // Внутренний скрытый сигнал длины для массивов\n let lenSignal: any = null\n if (Array.isArray(target)) {\n lenSignal = engine.signal(target.length, `[RE-INTERNAL]:len:${name || 'array'}`)\n }\n\n // ⚡ ВЫСОКОСКОРОСТНАЯ ИНСТРУМЕНТАЦИЯ НАТИВНЫХ МЕТОДОВ МАССИВОВ\n const arrayInstrumentations: Record<string | symbol, Function> = {\n push(...args: any[]) {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.push.apply(rawTarget, args)\n if (lenSignal) lenSignal.value = rawTarget.length\n // Пинаем подписчиков на свойства\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n pop() {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.pop.apply(rawTarget)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n shift() {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.shift.apply(rawTarget)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n unshift(...args: any[]) {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.unshift.apply(rawTarget, args)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n splice(...args: any[]) {\n const rawTarget = target as any\n return engine.batch(() => {\n // Приведение к any снимает строгую проверку кортежа аргументов [start, deleteCount]\n const res = (Array.prototype.splice as any).apply(rawTarget, args)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n reverse() {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.reverse.apply(rawTarget)\n if (lenSignal) {\n lenSignal.value = rawTarget.length\n }\n\n // ⚛️ ЧЕСТНЫЙ ПЕРЕБОР ИНДЕКСОВ: Оповещаем подписчиков, которые следят за\n // конкретными элементами массива по числовым ключам (state.numbers[0])\n for (let i = 0; i < rawTarget.length; i++) {\n notifyKeyChange(rawTarget, String(i))\n notifyKeyChange(rawTarget, String(i))\n }\n\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n sort(compareFn?: (a: any, b: any) => number) {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = (Array.prototype.sort as any).apply(rawTarget, [compareFn])\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n }\n }\n\n function notifyKeyChange(rawTarget: any, key: string | symbol) {\n const map = engine.reactiveSignals.get(rawTarget)\n if (map) {\n const sig = map.get(key)\n if (sig) {\n // Симулируем пинок изменения объекта самому себе через инкремент версии\n sig.value = (sig.value || 0) + 1\n }\n }\n }\n\n const handler: ProxyHandler<any> = {\n get(rawTarget, key, receiver) {\n if (key === '__isProxy') return true\n if (key === '_target') return rawTarget\n if (key === '_lenSignal') return lenSignal\n\n // Если это массив и вызывается деструктивный метод — отдаем атомарный мутатор\n if (Array.isArray(rawTarget) && Object.prototype.hasOwnProperty.call(arrayInstrumentations, key)) {\n return arrayInstrumentations[key].bind(receiver)\n }\n\n // Если мы находимся в реактивном контексте — подписываем текущий ключ\n if (engine.activeConsumer) {\n let sig = signalMap.get(key)\n if (!sig) {\n sig = engine.signal(0, `reactive:${name || 'object'}:${String(key)}`)\n signalMap.set(key, sig)\n }\n // Считываем значение сигнала для автоматической регистрации ребра графа\n sig.value\n if (key === 'length' && lenSignal) {\n lenSignal.value\n }\n }\n\n const res = Reflect.get(rawTarget, key, receiver)\n\n // Ленивое глубокое Proxy-проксирование на лету\n if (res !== null && typeof res === 'object') {\n return createReactive(engine, res, `${name || 'object'}.${String(key)}`)\n }\n return res\n },\n\n set(rawTarget, key, newValue, receiver) {\n const oldValue = Reflect.get(rawTarget, key, receiver)\n\n // Прерываем холостые мутации примитивов по Object.is\n if (Object.is(oldValue, newValue) && key !== 'length') {\n return true\n }\n\n const res = Reflect.set(rawTarget, key, newValue, receiver)\n if (res) {\n // Каскадно уведомляем граф через скрытый сигнальный маркер ключа\n let sig = signalMap.get(key)\n if (sig) {\n sig.value = (sig.value || 0) + 1\n }\n if (Array.isArray(rawTarget) && key !== 'length' && lenSignal) {\n // Принудительно триггерим длину, если изменился индекс массива\n lenSignal.value = rawTarget.length\n }\n }\n return res\n },\n\n deleteProperty(rawTarget, key) {\n const hasKey = Reflect.has(rawTarget, key)\n const res = Reflect.deleteProperty(rawTarget, key)\n if (res && hasKey) {\n let sig = signalMap.get(key)\n if (sig) {\n sig.value = (sig.value || 0) + 1\n }\n if (Array.isArray(rawTarget) && lenSignal) {\n lenSignal.value = rawTarget.length\n }\n }\n return res\n },\n\n ownKeys(rawTarget) {\n if (engine.activeConsumer) {\n let sig = signalMap.get('__ownKeys__')\n if (!sig) {\n sig = engine.signal(0, `reactive:${name || 'object'}:__ownKeys__`)\n signalMap.set('__ownKeys__', sig)\n }\n sig.value\n }\n return Reflect.ownKeys(rawTarget)\n }\n }\n\n const proxy = new Proxy(target, handler)\n engine.proxyCache.set(target, proxy)\n engine.proxyTargets.add(proxy)\n\n return proxy as T\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.method.reactive.cjs","names":[],"sources":["../src/core/core.method.reactive.ts"],"sourcesContent":["/**\n * * Изолированная фабрика глубоких реактивных Proxy-объектов графа.\n */\nexport function createReactive<T extends object>(\n engine: any,\n target: T,\n name?: string\n): T {\n if (engine.proxyTargets.has(target)) return target as any\n if (engine.proxyCache.has(target)) return engine.proxyCache.get(target) as any\n if (!engine.reactiveSignals.has(target)) engine.reactiveSignals.set(target, new Map())\n const signalsMap = engine.reactiveSignals.get(target)!\n\n const handler: ProxyHandler<T> = {\n get(t: T, prop: string | symbol, receiver: any) {\n if (prop === '__subscribe' && Array.isArray(t)) {\n return (cb: () => void) => {\n let lengthSig = signalsMap.get('length')\n if (!lengthSig) {\n lengthSig = engine.signal(t.length)\n signalsMap.set('length', lengthSig)\n }\n return lengthSig.subscribe(cb)\n }\n }\n\n if (Array.isArray(t) && typeof prop === 'string' && ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].includes(prop)) {\n return (...args: any[]) => {\n let result: any\n engine.batch(() => {\n result = (Reflect.get(t, prop) as Function).apply(receiver, args)\n\n let lengthSig = signalsMap.get('length')\n if (lengthSig) lengthSig.value = t.length\n\n signalsMap.forEach((sig: any, key: string) => {\n if (key !== 'length') sig.value = Reflect.get(t, key)\n })\n })\n return result\n }\n }\n\n if (typeof prop === 'symbol' || prop === 'constructor' || prop === 'toJSON') return Reflect.get(t, prop, receiver)\n\n let sig = signalsMap.get(prop)\n if (!sig) {\n const rawValue = Reflect.get(t, prop)\n sig = engine.signal(rawValue)\n signalsMap.set(prop, sig)\n\n // ⚡ ЛЕНИВОЕ КЭШИРОВАНИЕ НА ЧТЕНИИ (O(1) Hot Path):\n // Создаем прокси-обертку строго один раз при первом РЕАЛЬНОМ обращении к свойству,\n // а не принудительно при записи.\n if (rawValue !== null && typeof rawValue === 'object') {\n (sig as any)._proxyCache = engine.reactive(rawValue, name ? `${name}.${String(prop)}` : String(prop))\n }\n }\n\n if ((sig as any)._proxyCache !== undefined) {\n sig.value // Честная регистрация ребра для сохранения топологии глубины веток\n return (sig as any)._proxyCache\n }\n\n return sig.value\n },\n\n set(t: T, prop: string | symbol, value: any, receiver: any) {\n const rawValue = engine.proxyTargets.has(value) ? value : value\n const oldValue = Reflect.get(t, prop)\n\n if (oldValue === rawValue && prop !== 'length') return true\n Reflect.set(t, prop, rawValue)\n\n let sig = signalsMap.get(prop)\n if (!sig) {\n sig = engine.signal(oldValue)\n signalsMap.set(prop, sig)\n }\n\n // ⚡ МЕГА-УСКOРЕНИЕ ДЛЯ СЕТТЕРOВ:\n // При записи мы просто СБРАСЫВАЕМ кэш прокси на узле в undefined.\n // Если бенчмарк захочет прочитать это свойство на следующей итерации,\n // ловушка геттера лениво создаст прокси. Если нет — мы сэкономили 100% ресурсов!\n (sig as any)._proxyCache = undefined\n sig.value = rawValue\n\n if (Array.isArray(t) && prop !== 'length') {\n let lengthSig = signalsMap.get('length')\n if (lengthSig) lengthSig.value = t.length\n }\n return true\n }\n }\n\n const proxy = new Proxy(target, handler)\n engine.proxyCache.set(target, proxy)\n engine.proxyTargets.add(proxy)\n return proxy\n}\n"],"mappings":"AAGA,SAAgB,EACd,EACA,EACA,EACG,CACH,GAAI,EAAO,aAAa,IAAI,CAAM,EAAG,OAAO,EAC5C,GAAI,EAAO,WAAW,IAAI,CAAM,EAAG,OAAO,EAAO,WAAW,IAAI,CAAM,EACjE,EAAO,gBAAgB,IAAI,CAAM,GAAG,EAAO,gBAAgB,IAAI,EAAQ,IAAI,GAAK,EACrF,IAAM,EAAa,EAAO,gBAAgB,IAAI,CAAM,EAoF9C,EAAQ,IAAI,MAAM,EAAQ,CAjF9B,IAAI,EAAM,EAAuB,EAAe,CAC9C,GAAI,IAAS,eAAiB,MAAM,QAAQ,CAAC,EAC3C,MAAQ,IAAmB,CACzB,IAAI,EAAY,EAAW,IAAI,QAAQ,EAKvC,OAJK,IACH,EAAY,EAAO,OAAO,EAAE,MAAM,EAClC,EAAW,IAAI,SAAU,CAAS,GAE7B,EAAU,UAAU,CAAE,CAC/B,EAGF,GAAI,MAAM,QAAQ,CAAC,GAAK,OAAO,GAAS,UAAY,CAAC,OAAQ,MAAO,QAAS,UAAW,SAAU,OAAQ,SAAS,CAAC,CAAC,SAAS,CAAI,EAChI,OAAQ,GAAG,IAAgB,CACzB,IAAI,EAWJ,OAVA,EAAO,UAAY,CACjB,EAAU,QAAQ,IAAI,EAAG,CAAI,CAAC,CAAc,MAAM,EAAU,CAAI,EAEhE,IAAI,EAAY,EAAW,IAAI,QAAQ,EACnC,IAAW,EAAU,MAAQ,EAAE,QAEnC,EAAW,SAAS,EAAU,IAAgB,CACxC,IAAQ,WAAU,EAAI,MAAQ,QAAQ,IAAI,EAAG,CAAG,EACtD,CAAC,CACH,CAAC,EACM,CACT,EAGF,GAAI,OAAO,GAAS,UAAY,IAAS,eAAiB,IAAS,SAAU,OAAO,QAAQ,IAAI,EAAG,EAAM,CAAQ,EAEjH,IAAI,EAAM,EAAW,IAAI,CAAI,EAC7B,GAAI,CAAC,EAAK,CACR,IAAM,EAAW,QAAQ,IAAI,EAAG,CAAI,EACpC,EAAM,EAAO,OAAO,CAAQ,EAC5B,EAAW,IAAI,EAAM,CAAG,EAKC,OAAO,GAAa,UAAzC,IACF,EAAa,YAAc,EAAO,SAAS,EAAU,EAAO,GAAG,EAAK,GAAG,OAAO,CAAI,IAAM,OAAO,CAAI,CAAC,EAExG,CAOA,OALK,EAAY,cAAgB,IAAA,GAK1B,EAAI,OAJT,EAAI,MACI,EAAY,YAIxB,EAEA,IAAI,EAAM,EAAuB,EAAY,EAAe,CAC1D,IAAM,GAAW,EAAO,aAAa,IAAI,CAAK,EAAI,GAC5C,EAAW,QAAQ,IAAI,EAAG,CAAI,EAEpC,GAAI,IAAa,GAAY,IAAS,SAAU,MAAO,GACvD,QAAQ,IAAI,EAAG,EAAM,CAAQ,EAE7B,IAAI,EAAM,EAAW,IAAI,CAAI,EAa7B,GAZK,IACH,EAAM,EAAO,OAAO,CAAQ,EAC5B,EAAW,IAAI,EAAM,CAAG,GAO1B,EAAa,YAAc,IAAA,GAC3B,EAAI,MAAQ,EAER,MAAM,QAAQ,CAAC,GAAK,IAAS,SAAU,CACzC,IAAI,EAAY,EAAW,IAAI,QAAQ,EACnC,IAAW,EAAU,MAAQ,EAAE,OACrC,CACA,MAAO,EACT,CAG8B,CAAO,EAGvC,OAFA,EAAO,WAAW,IAAI,EAAQ,CAAK,EACnC,EAAO,aAAa,IAAI,CAAK,EACtB,CACT"}
|
|
@@ -1,112 +1,53 @@
|
|
|
1
1
|
//#region src/core/core.method.reactive.ts
|
|
2
|
-
function e(t, n
|
|
3
|
-
if (
|
|
4
|
-
if (
|
|
5
|
-
|
|
6
|
-
let
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return
|
|
21
|
-
let
|
|
22
|
-
return
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let t = Array.prototype.unshift.apply(r, e);
|
|
36
|
-
return a && (a.value = r.length), s(r, "length"), t;
|
|
37
|
-
});
|
|
38
|
-
},
|
|
39
|
-
splice(...e) {
|
|
40
|
-
let r = n;
|
|
41
|
-
return t.batch(() => {
|
|
42
|
-
let t = Array.prototype.splice.apply(r, e);
|
|
43
|
-
return a && (a.value = r.length), s(r, "length"), t;
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
reverse() {
|
|
47
|
-
let e = n;
|
|
48
|
-
return t.batch(() => {
|
|
49
|
-
let t = Array.prototype.reverse.apply(e);
|
|
50
|
-
a && (a.value = e.length);
|
|
51
|
-
for (let t = 0; t < e.length; t++) s(e, String(t)), s(e, String(t));
|
|
52
|
-
return s(e, "length"), t;
|
|
53
|
-
});
|
|
54
|
-
},
|
|
55
|
-
sort(e) {
|
|
56
|
-
let r = n;
|
|
57
|
-
return t.batch(() => {
|
|
58
|
-
let t = Array.prototype.sort.apply(r, [e]);
|
|
59
|
-
return a && (a.value = r.length), s(r, "length"), t;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
function s(e, n) {
|
|
64
|
-
let r = t.reactiveSignals.get(e);
|
|
65
|
-
if (r) {
|
|
66
|
-
let e = r.get(n);
|
|
67
|
-
e && (e.value = (e.value || 0) + 1);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
let c = new Proxy(n, {
|
|
71
|
-
get(n, s, c) {
|
|
72
|
-
if (s === "__isProxy") return !0;
|
|
73
|
-
if (s === "_target") return n;
|
|
74
|
-
if (s === "_lenSignal") return a;
|
|
75
|
-
if (Array.isArray(n) && Object.prototype.hasOwnProperty.call(o, s)) return o[s].bind(c);
|
|
76
|
-
if (t.activeConsumer) {
|
|
77
|
-
let e = i.get(s);
|
|
78
|
-
e || (e = t.signal(0, `reactive:${r || "object"}:${String(s)}`), i.set(s, e)), e.value, s === "length" && a && a.value;
|
|
79
|
-
}
|
|
80
|
-
let l = Reflect.get(n, s, c);
|
|
81
|
-
return typeof l == "object" && l ? e(t, l, `${r || "object"}.${String(s)}`) : l;
|
|
82
|
-
},
|
|
83
|
-
set(e, t, n, r) {
|
|
84
|
-
let o = Reflect.get(e, t, r);
|
|
85
|
-
if (Object.is(o, n) && t !== "length") return !0;
|
|
86
|
-
let s = Reflect.set(e, t, n, r);
|
|
87
|
-
if (s) {
|
|
88
|
-
let n = i.get(t);
|
|
89
|
-
n && (n.value = (n.value || 0) + 1), Array.isArray(e) && t !== "length" && a && (a.value = e.length);
|
|
2
|
+
function e(e, t, n) {
|
|
3
|
+
if (e.proxyTargets.has(t)) return t;
|
|
4
|
+
if (e.proxyCache.has(t)) return e.proxyCache.get(t);
|
|
5
|
+
e.reactiveSignals.has(t) || e.reactiveSignals.set(t, /* @__PURE__ */ new Map());
|
|
6
|
+
let r = e.reactiveSignals.get(t), i = new Proxy(t, {
|
|
7
|
+
get(t, i, a) {
|
|
8
|
+
if (i === "__subscribe" && Array.isArray(t)) return (n) => {
|
|
9
|
+
let i = r.get("length");
|
|
10
|
+
return i || (i = e.signal(t.length), r.set("length", i)), i.subscribe(n);
|
|
11
|
+
};
|
|
12
|
+
if (Array.isArray(t) && typeof i == "string" && [
|
|
13
|
+
"push",
|
|
14
|
+
"pop",
|
|
15
|
+
"shift",
|
|
16
|
+
"unshift",
|
|
17
|
+
"splice",
|
|
18
|
+
"sort",
|
|
19
|
+
"reverse"
|
|
20
|
+
].includes(i)) return (...n) => {
|
|
21
|
+
let o;
|
|
22
|
+
return e.batch(() => {
|
|
23
|
+
o = Reflect.get(t, i).apply(a, n);
|
|
24
|
+
let e = r.get("length");
|
|
25
|
+
e && (e.value = t.length), r.forEach((e, n) => {
|
|
26
|
+
n !== "length" && (e.value = Reflect.get(t, n));
|
|
27
|
+
});
|
|
28
|
+
}), o;
|
|
29
|
+
};
|
|
30
|
+
if (typeof i == "symbol" || i === "constructor" || i === "toJSON") return Reflect.get(t, i, a);
|
|
31
|
+
let o = r.get(i);
|
|
32
|
+
if (!o) {
|
|
33
|
+
let a = Reflect.get(t, i);
|
|
34
|
+
o = e.signal(a), r.set(i, o), typeof a == "object" && a && (o._proxyCache = e.reactive(a, n ? `${n}.${String(i)}` : String(i)));
|
|
90
35
|
}
|
|
91
|
-
return
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
let
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
ownKeys(e) {
|
|
102
|
-
if (t.activeConsumer) {
|
|
103
|
-
let e = i.get("__ownKeys__");
|
|
104
|
-
e || (e = t.signal(0, `reactive:${r || "object"}:__ownKeys__`), i.set("__ownKeys__", e)), e.value;
|
|
36
|
+
return o._proxyCache === void 0 ? o.value : (o.value, o._proxyCache);
|
|
37
|
+
},
|
|
38
|
+
set(t, n, i, a) {
|
|
39
|
+
let o = (e.proxyTargets.has(i), i), s = Reflect.get(t, n);
|
|
40
|
+
if (s === o && n !== "length") return !0;
|
|
41
|
+
Reflect.set(t, n, o);
|
|
42
|
+
let c = r.get(n);
|
|
43
|
+
if (c || (c = e.signal(s), r.set(n, c)), c._proxyCache = void 0, c.value = o, Array.isArray(t) && n !== "length") {
|
|
44
|
+
let e = r.get("length");
|
|
45
|
+
e && (e.value = t.length);
|
|
105
46
|
}
|
|
106
|
-
return
|
|
47
|
+
return !0;
|
|
107
48
|
}
|
|
108
49
|
});
|
|
109
|
-
return
|
|
50
|
+
return e.proxyCache.set(t, i), e.proxyTargets.add(i), i;
|
|
110
51
|
}
|
|
111
52
|
//#endregion
|
|
112
53
|
export { e as createReactive };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.method.reactive.mjs","names":[],"sources":["../src/core/core.method.reactive.ts"],"sourcesContent":["import { SignalOptions } from './types'\n\nexport function createReactive<T extends object>(\n engine: any,\n target: T,\n name?: string\n): T {\n if (target === null || typeof target !== 'object') {\n return target\n }\n\n // 1. Возвращаем уже существующий Proxy из кэша ядра\n if (engine.proxyCache.has(target)) {\n return engine.proxyCache.get(target) as T\n }\n if (engine.proxyTargets.has(target)) {\n return target\n }\n\n const signalMap = new Map<string | symbol, any>()\n engine.reactiveSignals.set(target, signalMap)\n\n // Внутренний скрытый сигнал длины для массивов\n let lenSignal: any = null\n if (Array.isArray(target)) {\n lenSignal = engine.signal(target.length, `[RE-INTERNAL]:len:${name || 'array'}`)\n }\n\n // ⚡ ВЫСОКОСКОРОСТНАЯ ИНСТРУМЕНТАЦИЯ НАТИВНЫХ МЕТОДОВ МАССИВОВ\n const arrayInstrumentations: Record<string | symbol, Function> = {\n push(...args: any[]) {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.push.apply(rawTarget, args)\n if (lenSignal) lenSignal.value = rawTarget.length\n // Пинаем подписчиков на свойства\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n pop() {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.pop.apply(rawTarget)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n shift() {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.shift.apply(rawTarget)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n unshift(...args: any[]) {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.unshift.apply(rawTarget, args)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n splice(...args: any[]) {\n const rawTarget = target as any\n return engine.batch(() => {\n // Приведение к any снимает строгую проверку кортежа аргументов [start, deleteCount]\n const res = (Array.prototype.splice as any).apply(rawTarget, args)\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n reverse() {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = Array.prototype.reverse.apply(rawTarget)\n if (lenSignal) {\n lenSignal.value = rawTarget.length\n }\n\n // ⚛️ ЧЕСТНЫЙ ПЕРЕБОР ИНДЕКСОВ: Оповещаем подписчиков, которые следят за\n // конкретными элементами массива по числовым ключам (state.numbers[0])\n for (let i = 0; i < rawTarget.length; i++) {\n notifyKeyChange(rawTarget, String(i))\n notifyKeyChange(rawTarget, String(i))\n }\n\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n },\n sort(compareFn?: (a: any, b: any) => number) {\n const rawTarget = target as any\n return engine.batch(() => {\n const res = (Array.prototype.sort as any).apply(rawTarget, [compareFn])\n if (lenSignal) lenSignal.value = rawTarget.length\n notifyKeyChange(rawTarget, 'length')\n return res\n })\n }\n }\n\n function notifyKeyChange(rawTarget: any, key: string | symbol) {\n const map = engine.reactiveSignals.get(rawTarget)\n if (map) {\n const sig = map.get(key)\n if (sig) {\n // Симулируем пинок изменения объекта самому себе через инкремент версии\n sig.value = (sig.value || 0) + 1\n }\n }\n }\n\n const handler: ProxyHandler<any> = {\n get(rawTarget, key, receiver) {\n if (key === '__isProxy') return true\n if (key === '_target') return rawTarget\n if (key === '_lenSignal') return lenSignal\n\n // Если это массив и вызывается деструктивный метод — отдаем атомарный мутатор\n if (Array.isArray(rawTarget) && Object.prototype.hasOwnProperty.call(arrayInstrumentations, key)) {\n return arrayInstrumentations[key].bind(receiver)\n }\n\n // Если мы находимся в реактивном контексте — подписываем текущий ключ\n if (engine.activeConsumer) {\n let sig = signalMap.get(key)\n if (!sig) {\n sig = engine.signal(0, `reactive:${name || 'object'}:${String(key)}`)\n signalMap.set(key, sig)\n }\n // Считываем значение сигнала для автоматической регистрации ребра графа\n sig.value\n if (key === 'length' && lenSignal) {\n lenSignal.value\n }\n }\n\n const res = Reflect.get(rawTarget, key, receiver)\n\n // Ленивое глубокое Proxy-проксирование на лету\n if (res !== null && typeof res === 'object') {\n return createReactive(engine, res, `${name || 'object'}.${String(key)}`)\n }\n return res\n },\n\n set(rawTarget, key, newValue, receiver) {\n const oldValue = Reflect.get(rawTarget, key, receiver)\n\n // Прерываем холостые мутации примитивов по Object.is\n if (Object.is(oldValue, newValue) && key !== 'length') {\n return true\n }\n\n const res = Reflect.set(rawTarget, key, newValue, receiver)\n if (res) {\n // Каскадно уведомляем граф через скрытый сигнальный маркер ключа\n let sig = signalMap.get(key)\n if (sig) {\n sig.value = (sig.value || 0) + 1\n }\n if (Array.isArray(rawTarget) && key !== 'length' && lenSignal) {\n // Принудительно триггерим длину, если изменился индекс массива\n lenSignal.value = rawTarget.length\n }\n }\n return res\n },\n\n deleteProperty(rawTarget, key) {\n const hasKey = Reflect.has(rawTarget, key)\n const res = Reflect.deleteProperty(rawTarget, key)\n if (res && hasKey) {\n let sig = signalMap.get(key)\n if (sig) {\n sig.value = (sig.value || 0) + 1\n }\n if (Array.isArray(rawTarget) && lenSignal) {\n lenSignal.value = rawTarget.length\n }\n }\n return res\n },\n\n ownKeys(rawTarget) {\n if (engine.activeConsumer) {\n let sig = signalMap.get('__ownKeys__')\n if (!sig) {\n sig = engine.signal(0, `reactive:${name || 'object'}:__ownKeys__`)\n signalMap.set('__ownKeys__', sig)\n }\n sig.value\n }\n return Reflect.ownKeys(rawTarget)\n }\n }\n\n const proxy = new Proxy(target, handler)\n engine.proxyCache.set(target, proxy)\n engine.proxyTargets.add(proxy)\n\n return proxy as T\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.method.reactive.mjs","names":[],"sources":["../src/core/core.method.reactive.ts"],"sourcesContent":["/**\n * * Изолированная фабрика глубоких реактивных Proxy-объектов графа.\n */\nexport function createReactive<T extends object>(\n engine: any,\n target: T,\n name?: string\n): T {\n if (engine.proxyTargets.has(target)) return target as any\n if (engine.proxyCache.has(target)) return engine.proxyCache.get(target) as any\n if (!engine.reactiveSignals.has(target)) engine.reactiveSignals.set(target, new Map())\n const signalsMap = engine.reactiveSignals.get(target)!\n\n const handler: ProxyHandler<T> = {\n get(t: T, prop: string | symbol, receiver: any) {\n if (prop === '__subscribe' && Array.isArray(t)) {\n return (cb: () => void) => {\n let lengthSig = signalsMap.get('length')\n if (!lengthSig) {\n lengthSig = engine.signal(t.length)\n signalsMap.set('length', lengthSig)\n }\n return lengthSig.subscribe(cb)\n }\n }\n\n if (Array.isArray(t) && typeof prop === 'string' && ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].includes(prop)) {\n return (...args: any[]) => {\n let result: any\n engine.batch(() => {\n result = (Reflect.get(t, prop) as Function).apply(receiver, args)\n\n let lengthSig = signalsMap.get('length')\n if (lengthSig) lengthSig.value = t.length\n\n signalsMap.forEach((sig: any, key: string) => {\n if (key !== 'length') sig.value = Reflect.get(t, key)\n })\n })\n return result\n }\n }\n\n if (typeof prop === 'symbol' || prop === 'constructor' || prop === 'toJSON') return Reflect.get(t, prop, receiver)\n\n let sig = signalsMap.get(prop)\n if (!sig) {\n const rawValue = Reflect.get(t, prop)\n sig = engine.signal(rawValue)\n signalsMap.set(prop, sig)\n\n // ⚡ ЛЕНИВОЕ КЭШИРОВАНИЕ НА ЧТЕНИИ (O(1) Hot Path):\n // Создаем прокси-обертку строго один раз при первом РЕАЛЬНОМ обращении к свойству,\n // а не принудительно при записи.\n if (rawValue !== null && typeof rawValue === 'object') {\n (sig as any)._proxyCache = engine.reactive(rawValue, name ? `${name}.${String(prop)}` : String(prop))\n }\n }\n\n if ((sig as any)._proxyCache !== undefined) {\n sig.value // Честная регистрация ребра для сохранения топологии глубины веток\n return (sig as any)._proxyCache\n }\n\n return sig.value\n },\n\n set(t: T, prop: string | symbol, value: any, receiver: any) {\n const rawValue = engine.proxyTargets.has(value) ? value : value\n const oldValue = Reflect.get(t, prop)\n\n if (oldValue === rawValue && prop !== 'length') return true\n Reflect.set(t, prop, rawValue)\n\n let sig = signalsMap.get(prop)\n if (!sig) {\n sig = engine.signal(oldValue)\n signalsMap.set(prop, sig)\n }\n\n // ⚡ МЕГА-УСКOРЕНИЕ ДЛЯ СЕТТЕРOВ:\n // При записи мы просто СБРАСЫВАЕМ кэш прокси на узле в undefined.\n // Если бенчмарк захочет прочитать это свойство на следующей итерации,\n // ловушка геттера лениво создаст прокси. Если нет — мы сэкономили 100% ресурсов!\n (sig as any)._proxyCache = undefined\n sig.value = rawValue\n\n if (Array.isArray(t) && prop !== 'length') {\n let lengthSig = signalsMap.get('length')\n if (lengthSig) lengthSig.value = t.length\n }\n return true\n }\n }\n\n const proxy = new Proxy(target, handler)\n engine.proxyCache.set(target, proxy)\n engine.proxyTargets.add(proxy)\n return proxy\n}\n"],"mappings":";AAGA,SAAgB,EACd,GACA,GACA,GACG;CACH,IAAI,EAAO,aAAa,IAAI,CAAM,GAAG,OAAO;CAC5C,IAAI,EAAO,WAAW,IAAI,CAAM,GAAG,OAAO,EAAO,WAAW,IAAI,CAAM;CACtE,AAAK,EAAO,gBAAgB,IAAI,CAAM,KAAG,EAAO,gBAAgB,IAAI,mBAAQ,IAAI,IAAI,CAAC;CACrF,IAAM,IAAa,EAAO,gBAAgB,IAAI,CAAM,GAoF9C,IAAQ,IAAI,MAAM,GAAQ;EAjF9B,IAAI,GAAM,GAAuB,GAAe;GAC9C,IAAI,MAAS,iBAAiB,MAAM,QAAQ,CAAC,GAC3C,QAAQ,MAAmB;IACzB,IAAI,IAAY,EAAW,IAAI,QAAQ;IAKvC,OAJK,MACH,IAAY,EAAO,OAAO,EAAE,MAAM,GAClC,EAAW,IAAI,UAAU,CAAS,IAE7B,EAAU,UAAU,CAAE;GAC/B;GAGF,IAAI,MAAM,QAAQ,CAAC,KAAK,OAAO,KAAS,YAAY;IAAC;IAAQ;IAAO;IAAS;IAAW;IAAU;IAAQ;GAAS,CAAC,CAAC,SAAS,CAAI,GAChI,QAAQ,GAAG,MAAgB;IACzB,IAAI;IAWJ,OAVA,EAAO,YAAY;KACjB,IAAU,QAAQ,IAAI,GAAG,CAAI,CAAC,CAAc,MAAM,GAAU,CAAI;KAEhE,IAAI,IAAY,EAAW,IAAI,QAAQ;KAGvC,AAFI,MAAW,EAAU,QAAQ,EAAE,SAEnC,EAAW,SAAS,GAAU,MAAgB;MAC5C,AAAI,MAAQ,aAAU,EAAI,QAAQ,QAAQ,IAAI,GAAG,CAAG;KACtD,CAAC;IACH,CAAC,GACM;GACT;GAGF,IAAI,OAAO,KAAS,YAAY,MAAS,iBAAiB,MAAS,UAAU,OAAO,QAAQ,IAAI,GAAG,GAAM,CAAQ;GAEjH,IAAI,IAAM,EAAW,IAAI,CAAI;GAC7B,IAAI,CAAC,GAAK;IACR,IAAM,IAAW,QAAQ,IAAI,GAAG,CAAI;IAOpC,AANA,IAAM,EAAO,OAAO,CAAQ,GAC5B,EAAW,IAAI,GAAM,CAAG,GAKC,OAAO,KAAa,YAAzC,MACF,EAAa,cAAc,EAAO,SAAS,GAAU,IAAO,GAAG,EAAK,GAAG,OAAO,CAAI,MAAM,OAAO,CAAI,CAAC;GAExG;GAOA,OALK,EAAY,gBAAgB,KAAA,IAK1B,EAAI,SAJT,EAAI,OACI,EAAY;EAIxB;EAEA,IAAI,GAAM,GAAuB,GAAY,GAAe;GAC1D,IAAM,KAAW,EAAO,aAAa,IAAI,CAAK,GAAI,IAC5C,IAAW,QAAQ,IAAI,GAAG,CAAI;GAEpC,IAAI,MAAa,KAAY,MAAS,UAAU,OAAO;GACvD,QAAQ,IAAI,GAAG,GAAM,CAAQ;GAE7B,IAAI,IAAM,EAAW,IAAI,CAAI;GAa7B,IAZK,MACH,IAAM,EAAO,OAAO,CAAQ,GAC5B,EAAW,IAAI,GAAM,CAAG,IAO1B,EAAa,cAAc,KAAA,GAC3B,EAAI,QAAQ,GAER,MAAM,QAAQ,CAAC,KAAK,MAAS,UAAU;IACzC,IAAI,IAAY,EAAW,IAAI,QAAQ;IACvC,AAAI,MAAW,EAAU,QAAQ,EAAE;GACrC;GACA,OAAO;EACT;CAG8B,CAAO;CAGvC,OAFA,EAAO,WAAW,IAAI,GAAQ,CAAK,GACnC,EAAO,aAAa,IAAI,CAAK,GACtB;AACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./utils/getExtractedValues.cjs");function t(t,n,r,i){let a=i&&typeof i==`object`,o=a?i.name||`unnamed_resource`:i||`unnamed_resource`,s=a?i:{},c=s.resetDataOnSourceChange??!0,l=s.responseValidate,u=s.validateBeforeFetch,d=t.signal({data:null,loading:!0,error:null,isRetrying:!1},`[CORE_INTERNAL_SIGNAL=1]:resource:state:${o}`),f=e=>{t.log({type:`resource`,label:o,details:{to:e,from:d.value}}),d.value=e},p=async(r,i,a=!1)=>{if(i.aborted)return;if(s.validateBeforeFetch&&s.validateBeforeFetch(r),u){let e=u(r);if(e===!1||typeof e==`string`){if(i.aborted)return;let n=typeof e==`string`?e:`Pre-fetch validation failed for resource`,r=a?null:t.untrack(()=>d.value.data);f({data:r,loading:!1,error:n,isRetrying:!1});return}}let p=a&&c?null:t.untrack(()=>d.value.data);f({data:p,loading:!0,error:null,isRetrying:!1});for(let a=0;a<=0;a++){if(i.aborted)return;let s=i;try{let e=await n(r,s);if(i.aborted)return;if(s.aborted)throw new DOMException(`The operation timed out.`,`TimeoutError`);if(l){let t=l(e);if(t===!1||typeof t==`string`){if(i.aborted)return;f({data:null,loading:!1,error:typeof t==`string`?t:`Validation failed`,isRetrying:!1});return}}if(i.aborted)return;f({data:e,loading:!1,error:null,isRetrying:!1});return}catch(n){if(i.aborted||n.name===`AbortError`&&i.aborted)return;let r=n.name===`TimeoutError`||n.name===`AbortError`||n.message?.includes(`timeout`),s=e.getExtractedValues({tested:[n.message],expectedKey:`THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY`,valueType:`number`})?.[0]===`1`||!1,c=s&&e.getExtractedValues({tested:[n.message],expectedKey:`MESSAGE`,valueType:`string`})?.[0]||`Custom validation error`,l=s||n.name===`ValidationError`;if(a===0||l){if(i.aborted)return;let e=r?Error(`Request timed out after 1000ms`,{cause:n}):s?Error(c,{cause:n}):n;f({data:null,loading:!1,error:e instanceof Error?e.message:typeof e==`string`?e:`typeof finalError is ${typeof e}`,isRetrying:!1});return}else{if(i.aborted)return;let e=1e3*2**a;e=Math.min(e,3e5);let n=Math.random()*200;e+=n,f({data:d.value.data,loading:!0,error:null,isRetrying:!0}),console.warn(`[Resource Retry] "${o}" сбой по ${r?`таймауту`:`ошибке сети`}. Попытка ${a+1}/${a+1}...`);try{if(await t.delay(e,i),i.aborted)return}catch{return}}}}},m=null,h=t.effect(()=>{let e=r?r.value:void 0,n=new AbortController;return m=n,t.untrack(()=>{p(e,n.signal,!0)}),()=>n.abort()},`[CORE_INTERNAL_SIGNAL=1]:effect`);return{get data(){return d.value.data},get loading(){return d.value.loading},get error(){return d.value.error},get isRetrying(){return d.value.isRetrying},get value(){return d.value},refetch:()=>{m?.abort(),m=new AbortController,p(r?r.value:void 0,m.signal,!1)},subscribe:e=>d.subscribe(e),destroy:()=>{m?.abort(),m=null,typeof h==`function`&&h(),d.destroy&&d.destroy()}}}exports.createResource=t;
|
|
2
|
+
//# sourceMappingURL=core.method.resource.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.method.resource.cjs","names":[],"sources":["../src/core/core.method.resource.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Resource, ResourceOptions, ResourceState, Signal } from './types'\n\n// Контракт ядра движка для безопасных вызовов методов с дженериками\ninterface IReactiveEngine {\n signal<V>(initialValue: V, optionsOrName?: any): Signal<V>;\n effect(fn: () => any, name?: string): () => void;\n untrack<V>(fn: () => V): V;\n log(params: any): void;\n delay(ms: number, signal: AbortSignal): Promise<void>;\n}\n\nexport function createResource<T, S = void>(\n engine: IReactiveEngine,\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n source?: { value: S },\n optionsOrName?: string | ResourceOptions<T, S>\n): Resource<T> {\n const isOptionsObject = optionsOrName && typeof optionsOrName === 'object'\n const resourceSignalName = isOptionsObject\n ? ((optionsOrName as ResourceOptions<T, S>).name || 'unnamed_resource')\n : (optionsOrName as string) || 'unnamed_resource'\n\n const options: Partial<ResourceOptions<T, S>> = isOptionsObject\n ? (optionsOrName as ResourceOptions<T, S>)\n : {}\n\n const resetDataOnSourceChange = options.resetDataOnSourceChange ?? true\n const responseValidate = options.responseValidate\n const validateBeforeFetch = options.validateBeforeFetch\n const retryCount = 0\n const baseDelay = 1000\n const useExponential = true\n const maxRetryDelay = 1000 * 60 * 5\n const timeoutMs = 1000\n\n // Вызов скомпилируется успешно, так как метод signal теперь строго описан в интерфейсе\n const state = engine.signal<ResourceState<T>>(\n { data: null, loading: true, error: null, isRetrying: false },\n `[CORE_INTERNAL_SIGNAL=1]:resource:state:${resourceSignalName}`\n )\n\n const updateResourceState = (nextState: ResourceState<T>) => {\n engine.log({ type: 'resource', label: resourceSignalName, details: { to: nextState, from: state.value } })\n state.value = nextState\n }\n\n const load = async (sValue: S, effectSignal: AbortSignal, isSourceChange = false) => {\n if (effectSignal.aborted) return\n const isValid = options.validateBeforeFetch ? options.validateBeforeFetch(sValue) : true\n\n if (validateBeforeFetch) {\n const preValidationResult = validateBeforeFetch(sValue)\n if (preValidationResult === false || typeof preValidationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof preValidationResult === 'string'\n ? preValidationResult\n : 'Pre-fetch validation failed for resource'\n\n const currentData = isSourceChange ? null : engine.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n const shouldClear = isSourceChange && resetDataOnSourceChange\n const currentData = shouldClear ? null : engine.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: true, error: null, isRetrying: false })\n for (let attempt = 0; attempt <= retryCount; attempt++) {\n if (effectSignal.aborted) return\n let combinedSignal = effectSignal\n try {\n const data = await fetcher(sValue, combinedSignal)\n if (effectSignal.aborted) return\n if (combinedSignal.aborted) {\n throw new DOMException('The operation timed out.', 'TimeoutError')\n }\n if (responseValidate) {\n const validationResult = responseValidate(data)\n if (validationResult === false || typeof validationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof validationResult === 'string' ? validationResult : 'Validation failed'\n updateResourceState({ data: null, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n if (effectSignal.aborted) return\n updateResourceState({ data, loading: false, error: null, isRetrying: false })\n return\n } catch (e: unknown) {\n if (effectSignal.aborted || ((e as Error).name === 'AbortError' && effectSignal.aborted)) return\n const isTimeout = (e as Error).name === 'TimeoutError' || (e as Error).name === 'AbortError' || (e as Error).message?.includes('timeout')\n const isCustomValidationError = getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY', valueType: 'number',\n })?.[0] === '1' || false\n const __defaultCustomValidationErrorMessage = 'Custom validation error'\n let customValidationErrorMessage: string = isCustomValidationError\n ? (getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'MESSAGE', valueType: 'string',\n })?.[0] || __defaultCustomValidationErrorMessage)\n : __defaultCustomValidationErrorMessage\n const isFetchBodyValidationError = isCustomValidationError || (e as Error).name === 'ValidationError'\n if (attempt === retryCount || isFetchBodyValidationError) {\n if (effectSignal.aborted) return\n const finalError = isTimeout\n ? new Error(`Request timed out after ${timeoutMs}ms`, { cause: e })\n : isCustomValidationError\n ? new Error(customValidationErrorMessage, { cause: e })\n : e\n\n updateResourceState({\n data: null, loading: false,\n error: finalError instanceof Error ? finalError.message : typeof finalError === 'string' ? finalError : `typeof finalError is ${typeof finalError}`,\n isRetrying: false,\n })\n return\n } else {\n if (effectSignal.aborted) return\n let currentDelay = useExponential ? baseDelay * Math.pow(2, attempt) : baseDelay\n currentDelay = Math.min(currentDelay, maxRetryDelay)\n const jitter = Math.random() * 200\n currentDelay = currentDelay + jitter\n updateResourceState({ data: state.value.data, loading: true, error: null, isRetrying: true })\n const logReason = isTimeout ? 'таймауту' : 'ошибке сети'\n console.warn(`[Resource Retry] \"${resourceSignalName}\" сбой по ${logReason}. Попытка ${attempt + 1}/${retryCount > 0 ? retryCount + 1 : attempt + 1}...`)\n\n try {\n await engine.delay(currentDelay, effectSignal)\n if (effectSignal.aborted) return\n } catch (delayError) {\n return\n }\n }\n }\n }\n }\n\n let activeEffectController: AbortController | null = null\n\n const disposeInternalEffect = engine.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n engine.untrack(() => {\n load(sValue as S, effectController.signal, true)\n })\n\n return () => effectController.abort()\n }, '[CORE_INTERNAL_SIGNAL=1]:effect')\n\n return {\n get data() { return state.value.data },\n get loading() { return state.value.loading },\n get error() { return state.value.error },\n get isRetrying() { return state.value.isRetrying },\n get value() { return state.value },\n refetch: () => {\n activeEffectController?.abort()\n activeEffectController = new AbortController()\n load(source ? source.value : undefined as S, activeEffectController.signal, false)\n },\n subscribe: (cb: (val: ResourceState<T>) => void) => state.subscribe(cb),\n destroy: () => {\n activeEffectController?.abort()\n activeEffectController = null\n if (typeof disposeInternalEffect === 'function') {\n disposeInternalEffect()\n }\n if ((state as any).destroy) {\n (state as any).destroy()\n }\n }\n } as any\n}\n"],"mappings":"kDAYA,SAAgB,EACd,EACA,EACA,EACA,EACa,CACb,IAAM,EAAkB,GAAiB,OAAO,GAAkB,SAC5D,EAAqB,EACrB,EAAwC,MAAQ,mBACjD,GAA4B,mBAE3B,EAA0C,EAC3C,EACD,CAAC,EAEC,EAA0B,EAAQ,yBAA2B,GAC7D,EAAmB,EAAQ,iBAC3B,EAAsB,EAAQ,oBAQ9B,EAAQ,EAAO,OACnB,CAAE,KAAM,KAAM,QAAS,GAAM,MAAO,KAAM,WAAY,EAAM,EAC5D,2CAA2C,GAC7C,EAEM,EAAuB,GAAgC,CAC3D,EAAO,IAAI,CAAE,KAAM,WAAY,MAAO,EAAoB,QAAS,CAAE,GAAI,EAAW,KAAM,EAAM,KAAM,CAAE,CAAC,EACzG,EAAM,MAAQ,CAChB,EAEM,EAAO,MAAO,EAAW,EAA2B,EAAiB,KAAU,CACnF,GAAI,EAAa,QAAS,OAG1B,GAFgB,EAAQ,qBAAsB,EAAQ,oBAAoB,CAAM,EAE5E,EAAqB,CACvB,IAAM,EAAsB,EAAoB,CAAM,EACtD,GAAI,IAAwB,IAAS,OAAO,GAAwB,SAAU,CAC5E,GAAI,EAAa,QAAS,OAC1B,IAAM,EAAW,OAAO,GAAwB,SAC5C,EACA,2CAEE,EAAc,EAAiB,KAAO,EAAO,YAAc,EAAM,MAAM,IAAI,EACjF,EAAoB,CAAE,KAAM,EAAa,QAAS,GAAO,MAAO,EAAU,WAAY,EAAM,CAAC,EAC7F,MACF,CACF,CAEA,IAAM,EADc,GAAkB,EACJ,KAAO,EAAO,YAAc,EAAM,MAAM,IAAI,EAC9E,EAAoB,CAAE,KAAM,EAAa,QAAS,GAAM,MAAO,KAAM,WAAY,EAAM,CAAC,EACxF,IAAK,IAAI,EAAU,EAAG,GAAW,EAAY,IAAW,CACtD,GAAI,EAAa,QAAS,OAC1B,IAAI,EAAiB,EACrB,GAAI,CACF,IAAM,EAAO,MAAM,EAAQ,EAAQ,CAAc,EACjD,GAAI,EAAa,QAAS,OAC1B,GAAI,EAAe,QACjB,MAAM,IAAI,aAAa,2BAA4B,cAAc,EAEnE,GAAI,EAAkB,CACpB,IAAM,EAAmB,EAAiB,CAAI,EAC9C,GAAI,IAAqB,IAAS,OAAO,GAAqB,SAAU,CACtE,GAAI,EAAa,QAAS,OAE1B,EAAoB,CAAE,KAAM,KAAM,QAAS,GAAO,MADjC,OAAO,GAAqB,SAAW,EAAmB,oBACR,WAAY,EAAM,CAAC,EACtF,MACF,CACF,CACA,GAAI,EAAa,QAAS,OAC1B,EAAoB,CAAE,OAAM,QAAS,GAAO,MAAO,KAAM,WAAY,EAAM,CAAC,EAC5E,MACF,OAAS,EAAY,CACnB,GAAI,EAAa,SAAa,EAAY,OAAS,cAAgB,EAAa,QAAU,OAC1F,IAAM,EAAa,EAAY,OAAS,gBAAmB,EAAY,OAAS,cAAiB,EAAY,SAAS,SAAS,SAAS,EAClI,EAA0B,EAAA,mBAAmB,CACjD,OAAQ,CAAE,EAAY,OAAO,EAAG,YAAa,yCAA0C,UAAW,QACpG,CAAC,CAAC,GAAG,KAAO,KAAO,GAEf,EAAuC,GACtC,EAAA,mBAAmB,CACpB,OAAQ,CAAE,EAAY,OAAO,EAAG,YAAa,UAAW,UAAW,QACrE,CAAC,CAAC,GAAG,IACH,0BACE,EAA6B,GAA4B,EAAY,OAAS,kBACpF,GAAI,IAAY,GAAc,EAA4B,CACxD,GAAI,EAAa,QAAS,OAC1B,IAAM,EAAa,EACX,MAAM,iCAA0C,CAAE,MAAO,CAAE,CAAC,EAChE,EACM,MAAM,EAA8B,CAAE,MAAO,CAAE,CAAC,EACpD,EAEN,EAAoB,CAClB,KAAM,KAAM,QAAS,GACrB,MAAO,aAAsB,MAAQ,EAAW,QAAU,OAAO,GAAe,SAAW,EAAa,wBAAwB,OAAO,IACvI,WAAY,EACd,CAAC,EACD,MACF,KAAO,CACL,GAAI,EAAa,QAAS,OAC1B,IAAI,EAAgC,IAAqB,GAAG,EAC5D,EAAe,KAAK,IAAI,EAAc,GAAa,EACnD,IAAM,EAAS,KAAK,OAAO,EAAI,IAC/B,GAA8B,EAC9B,EAAoB,CAAE,KAAM,EAAM,MAAM,KAAM,QAAS,GAAM,MAAO,KAAM,WAAY,EAAK,CAAC,EAE5F,QAAQ,KAAK,qBAAqB,EAAmB,YADnC,EAAY,WAAa,cACgC,YAAY,EAAU,EAAE,GAAqC,EAAU,EAAE,IAAI,EAExJ,GAAI,CAEF,GADA,MAAM,EAAO,MAAM,EAAc,CAAY,EACzC,EAAa,QAAS,MAC5B,MAAqB,CACnB,MACF,CACF,CACF,CACF,CACF,EAEI,EAAiD,KAE/C,EAAwB,EAAO,WAAa,CAChD,IAAM,EAAS,EAAS,EAAO,MAAQ,IAAA,GACjC,EAAmB,IAAI,gBAO7B,MANA,GAAyB,EAEzB,EAAO,YAAc,CACnB,EAAK,EAAa,EAAiB,OAAQ,EAAI,CACjD,CAAC,MAEY,EAAiB,MAAM,CACtC,EAAG,iCAAiC,EAEpC,MAAO,CACL,IAAI,MAAO,CAAE,OAAO,EAAM,MAAM,IAAK,EACrC,IAAI,SAAU,CAAE,OAAO,EAAM,MAAM,OAAQ,EAC3C,IAAI,OAAQ,CAAE,OAAO,EAAM,MAAM,KAAM,EACvC,IAAI,YAAa,CAAE,OAAO,EAAM,MAAM,UAAW,EACjD,IAAI,OAAQ,CAAE,OAAO,EAAM,KAAM,EACjC,YAAe,CACb,GAAwB,MAAM,EAC9B,EAAyB,IAAI,gBAC7B,EAAK,EAAS,EAAO,MAAQ,IAAA,GAAgB,EAAuB,OAAQ,EAAK,CACnF,EACA,UAAY,GAAwC,EAAM,UAAU,CAAE,EACtE,YAAe,CACb,GAAwB,MAAM,EAC9B,EAAyB,KACrB,OAAO,GAA0B,YACnC,EAAsB,EAEnB,EAAc,SACjB,EAAe,QAAQ,CAE3B,CACF,CACF"}
|