@pravosleva/reactive-engine 2.0.0 → 2.1.0-beta

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.
Files changed (48) hide show
  1. package/dist/BaseREServiceEnhanced.cjs.map +1 -1
  2. package/dist/BaseREServiceEnhanced.mjs.map +1 -1
  3. package/dist/core/BaseREServiceEnhanced.d.ts +3 -3
  4. package/dist/core/BaseREServiceEnhanced.d.ts.map +1 -1
  5. package/dist/core/core.automatic.d.ts +0 -19
  6. package/dist/core/core.automatic.d.ts.map +1 -1
  7. package/dist/core/core.d.ts.map +1 -1
  8. package/dist/core/core.logger.d.ts +22 -0
  9. package/dist/core/core.logger.d.ts.map +1 -0
  10. package/dist/core/core.method.computed.d.ts +0 -4
  11. package/dist/core/core.method.computed.d.ts.map +1 -1
  12. package/dist/core/core.method.signal.d.ts +0 -4
  13. package/dist/core/core.method.signal.d.ts.map +1 -1
  14. package/dist/core.automatic.cjs +1 -1
  15. package/dist/core.automatic.cjs.map +1 -1
  16. package/dist/core.automatic.mjs +1 -20
  17. package/dist/core.automatic.mjs.map +1 -1
  18. package/dist/core.cjs +1 -1
  19. package/dist/core.cjs.map +1 -1
  20. package/dist/core.logger.cjs +2 -0
  21. package/dist/core.logger.cjs.map +1 -0
  22. package/dist/core.logger.mjs +48 -0
  23. package/dist/core.logger.mjs.map +1 -0
  24. package/dist/core.method.computed.cjs +1 -1
  25. package/dist/core.method.computed.cjs.map +1 -1
  26. package/dist/core.method.computed.mjs +110 -46
  27. package/dist/core.method.computed.mjs.map +1 -1
  28. package/dist/core.method.signal.cjs +1 -1
  29. package/dist/core.method.signal.cjs.map +1 -1
  30. package/dist/core.method.signal.mjs +6 -10
  31. package/dist/core.method.signal.mjs.map +1 -1
  32. package/dist/core.mjs +31 -43
  33. package/dist/core.mjs.map +1 -1
  34. package/dist/react/index.cjs +1 -1
  35. package/dist/react/index.cjs.map +1 -1
  36. package/dist/react/index.d.ts +2 -2
  37. package/dist/react/index.d.ts.map +1 -1
  38. package/dist/react/index.mjs +1 -1
  39. package/dist/react/index.mjs.map +1 -1
  40. package/dist/reactive-engine.umd.js +2 -2
  41. package/dist/reactive-engine.umd.js.map +1 -1
  42. package/dist/vue/index.cjs +1 -1
  43. package/dist/vue/index.cjs.map +1 -1
  44. package/dist/vue/index.d.ts +3 -3
  45. package/dist/vue/index.d.ts.map +1 -1
  46. package/dist/vue/index.mjs +3 -1
  47. package/dist/vue/index.mjs.map +1 -1
  48. package/package.json +1 -1
@@ -2,75 +2,139 @@
2
2
  function e(e, t, n) {
3
3
  let r = e.computedCache.get(t)?.deref();
4
4
  if (r) return r;
5
- let i, a = !0, o = 0, s = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Map(), l = (e) => {
5
+ let i, a = !0, o = 0, s = !1, c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map(), u = (e) => {
6
6
  if (!e) return;
7
7
  let t = e._node || e;
8
8
  if (t.dependencies && t.dependencies.size > 0) {
9
9
  let n = Array.from(t.dependencies);
10
10
  t.dependencies.clear(), t.depVersions && t.depVersions.clear(), n.forEach((n) => {
11
11
  let r = n._node || n;
12
- r.subscribers && (r.subscribers.delete(t), r.subscribers.delete(e), r.subscribers.delete(d), r.type === "computed" && r.subscribers.size === 0 && l(r));
12
+ r.subscribers && (r.subscribers.delete(t), r.subscribers.delete(e), r.subscribers.delete(p), r.type === "computed" && r.subscribers.size === 0 && u(r));
13
13
  });
14
14
  }
15
- }, u = new class extends Set {
15
+ }, d = new class extends Set {
16
16
  delete(n) {
17
17
  let r = super.delete(n);
18
- return this.size === 0 && (a = !0, l(d), e.computedCache.delete(t)), r;
18
+ return this.size === 0 && (a = !0, s = !0, u(p), e.computedCache.delete(t)), r;
19
19
  }
20
- }(), d = {
20
+ }(), f = (t) => {
21
+ if (!t) return !1;
22
+ let n = t._node || t, r = n.subscribers && n.subscribers.size > 0;
23
+ if (r && !n.versionCheckRequired) return !1;
24
+ let i = !1, a = Array.from(n.dependencies || []);
25
+ for (let e of a) {
26
+ let t = e._node || e;
27
+ t.type === "computed" && (t.versionCheckRequired || !r) && f(t);
28
+ }
29
+ let o = e.activeConsumer;
30
+ for (let t of a) {
31
+ let a = t._node || t;
32
+ if (a.type === "computed" && (a.isDirty || a.versionCheckRequired || !r)) {
33
+ e.activeConsumer = a;
34
+ try {
35
+ a.run();
36
+ } finally {
37
+ e.activeConsumer = o;
38
+ }
39
+ }
40
+ let s = a.version === void 0 ? t.version === void 0 ? e.epoch : t.version : a.version;
41
+ (!n.depVersions.has(t) || s !== n.depVersions.get(t)) && (i = !0), n.depVersions.set(t, s);
42
+ }
43
+ return e.activeConsumer = o, n.versionCheckRequired = !1, i;
44
+ }, p = {
21
45
  id: e.subscriberId++,
22
- dependencies: s,
23
- subscribers: u,
46
+ dependencies: c,
47
+ subscribers: d,
24
48
  depth: 1,
25
49
  type: "computed",
26
50
  fn: t,
27
51
  get version() {
28
52
  return o;
29
53
  },
54
+ get versionCheckRequired() {
55
+ return s;
56
+ },
57
+ set versionCheckRequired(e) {
58
+ s = e;
59
+ },
60
+ get depVersions() {
61
+ return l;
62
+ },
30
63
  run: () => {
31
- if (e.cycleDetectionStack.has(d)) throw Error("[Graph Error] Cyclic dependency detected");
32
- e.cycleDetectionStack.add(d);
33
- let n = e.activeConsumer;
34
- e.activeConsumer = d, s.forEach((e) => {
64
+ if (e.cycleDetectionStack.has(p)) throw Error("[Graph Error] Cyclic dependency detected");
65
+ e.cycleDetectionStack.add(p);
66
+ let r = e.activeConsumer;
67
+ e.activeConsumer = p;
68
+ let u = Array.from(c), f = new Map(l);
69
+ c.forEach((e) => {
35
70
  let t = e._node || e;
36
- t.subscribers && t.subscribers.delete(d);
37
- }), s.clear(), c.clear();
71
+ t.subscribers && t.subscribers.delete(p);
72
+ }), c.clear(), l.clear();
38
73
  try {
39
- let n = t(), r = i && typeof i == "object", l = a || !r && i !== n || r && JSON.stringify(i) !== JSON.stringify(n);
40
- l ? (i = n, o++, u.forEach((t) => {
41
- t.isDirty = !0, e.pendingEffects.add(t);
42
- })) : u.forEach((e) => {
43
- e.isDirty = !1;
44
- }), a = !1;
45
- let f = 0;
46
- return s.forEach((t) => {
74
+ let r = t(), h = a || i && typeof i == "object" || r && typeof r == "object" || i !== r;
75
+ if (h) {
76
+ let s = a ? void 0 : typeof i == "object" && i ? JSON.parse(JSON.stringify(i)) : i;
77
+ i = r, o++, e.log && e.log({
78
+ type: "computed",
79
+ label: n || `computed:[${t.name || p.id}]`,
80
+ details: {
81
+ from: s,
82
+ to: r
83
+ }
84
+ }), d.forEach((t) => {
85
+ let n = t._node || t;
86
+ n.isDirty = !0, n.type === "effect" && e.pendingEffects.add(t), n.markDirty && n.markDirty();
87
+ });
88
+ } else d.forEach((t) => {
47
89
  let n = t._node || t;
48
- c.set(t, n.version === void 0 ? e.epoch : n.version), n.depth !== void 0 && n.depth > f && (f = n.depth);
49
- }), d.depth = f + 1, l;
90
+ n.depVersions && n.depVersions.set(m, o), n.type === "effect" && (n.isDirty = !1, e.pendingEffects.delete(t));
91
+ });
92
+ a = !1, s = !1;
93
+ let g = 0, _ = c.size === u.length;
94
+ return c.forEach((t) => {
95
+ let n = t._node || t, r = n.version === void 0 ? t.version === void 0 ? e.epoch : t.version : n.version;
96
+ l.set(t, r), n.depth !== void 0 && n.depth > g && (g = n.depth), _ && !u.includes(t) && (_ = !1);
97
+ }), (_ && f.size > 0 || !_ && f.size > 0) && f.forEach((e, t) => {
98
+ if (l.has(t)) {
99
+ let n = t._node || t;
100
+ l.set(t, n.version === void 0 ? e : n.version);
101
+ }
102
+ }), p.depth = g + 1, h;
50
103
  } finally {
51
- e.activeConsumer = n, e.cycleDetectionStack.delete(d);
104
+ e.activeConsumer = r, e.cycleDetectionStack.delete(p);
52
105
  }
53
106
  },
54
107
  markDirty: () => {
55
- a || (a = !0, u.forEach((t) => {
56
- let n = t.isDirty;
57
- t.isDirty = !0, e.pendingEffects.add(t), !n && t.subscribers && t.subscribers.forEach((t) => {
58
- t.isDirty = !0, e.pendingEffects.add(t);
59
- });
108
+ s || (s = !0, d.forEach((t) => {
109
+ let n = t._node || t;
110
+ n.isDirty = !0, n.type === "effect" && e.pendingEffects.add(t), n.markDirty && n.markDirty();
60
111
  }));
61
112
  }
62
- }, f = {
113
+ }, m = {
63
114
  get value() {
64
- e.activeConsumer && e.activeConsumer !== d && (d.subscribers.add(e.activeConsumer), e.activeConsumer.dependencies.add(d));
65
- let t = a;
66
- if (!t && s.size > 0) for (let n of Array.from(s)) {
67
- let r = n._node || n;
68
- if ((r.version === void 0 ? n.version === void 0 ? e.epoch : n.version : r.version) !== c.get(n)) {
69
- t = !0;
115
+ e.activeConsumer && e.activeConsumer !== p && (p.subscribers.add(e.activeConsumer), e.activeConsumer.dependencies.add(p));
116
+ let r = f(p), u = a || r;
117
+ if (!u && c.size > 0) for (let t of Array.from(c)) {
118
+ let n = t._node || t;
119
+ if ((n.version === void 0 ? t.version === void 0 ? e.epoch : t.version : n.version) !== l.get(t)) {
120
+ u = !0;
70
121
  break;
71
122
  }
72
123
  }
73
- return t && d.run(), i;
124
+ return u ? p.run() : (s && e.log && e.log({
125
+ type: "computed",
126
+ label: n || `computed:[${t.name || p.id}]`,
127
+ details: {
128
+ from: i,
129
+ to: i
130
+ }
131
+ }), s = !1, d.forEach((e) => {
132
+ let t = e._node || e;
133
+ t.depVersions && t.depVersions.set(m, o);
134
+ })), i;
135
+ },
136
+ get valueWithoutTracking() {
137
+ return i;
74
138
  },
75
139
  get version() {
76
140
  return o;
@@ -84,21 +148,21 @@ function e(e, t, n) {
84
148
  type: "effect",
85
149
  run: () => {
86
150
  if (!n.isDisposed) try {
87
- t(f.value);
151
+ t(m.value);
88
152
  } catch (e) {
89
153
  console.error(e);
90
154
  }
91
155
  }
92
156
  };
93
- return d.subscribers.add(n), t(f.value), () => {
94
- n.isDisposed = !0, d.subscribers.delete(n);
157
+ return p.subscribers.add(n), t(m.value), () => {
158
+ n.isDisposed = !0, p.subscribers.delete(n);
95
159
  };
96
160
  },
97
161
  subscribeState(e) {
98
- return f.subscribe(e);
162
+ return m.subscribe(e);
99
163
  },
100
164
  destroy: () => {
101
- d.subscribers.clear(), l(d), e.computedCache.delete(t), a = !0;
165
+ p.subscribers.clear(), u(p), e.computedCache.delete(t), a = !0;
102
166
  },
103
167
  __subscribe(t) {
104
168
  let n = {
@@ -107,14 +171,14 @@ function e(e, t, n) {
107
171
  run: t,
108
172
  isDirty: !1
109
173
  };
110
- return d.subscribers.add(n), () => {
111
- u.delete(n);
174
+ return p.subscribers.add(n), () => {
175
+ d.delete(n);
112
176
  };
113
177
  }
114
178
  };
115
- return f._node = d, f.subscribers = u, f.dependencies = s, f._isDirty = () => a, f.type = "computed", f.run = () => d.run(), d.destroy = () => {
179
+ return m._node = p, m.subscribers = d, m.dependencies = c, m._isDirty = () => a || s, m.type = "computed", m.run = () => p.run(), p.destroy = () => {
116
180
  e.computedCache.delete(t);
117
- }, e.computedCache.set(t, new WeakRef(f)), f;
181
+ }, e.computedCache.set(t, new WeakRef(m)), m;
118
182
  }
119
183
  //#endregion
120
184
  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\n/**\n * Изолированная фабрика computed-узлов реактивного графа.\n * Гарантирует O(1) кэширование, ленивые вычисления и стабильный каскадный Garbage Collection.\n */\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const cachedRef = engine.computedCache.get(fn)\n const existing = cachedRef?.deref()\n if (existing) return existing as Computed<T>\n \n let value: T\n let isDirty = true\n let version = 0\n \n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n \n // Канонический рекурсивный сборщик мертвых связей графа (Cascade GC)\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 const snapshotDeps = Array.from(actNode.dependencies)\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n \n snapshotDeps.forEach((dep: any) => {\n const rawDepNode = dep._node || dep\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 }\n }\n\n // Строго типизированный кастомный Set подписчиков с GC-триггером на уровне ноды ядра\n const subscribers = new class extends Set<any> {\n override delete(val: any): boolean {\n const res = super.delete(val)\n if (this.size === 0) {\n isDirty = true\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n }\n return res\n }\n }()\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n run: () => {\n if (engine.cycleDetectionStack.has(computedNode)) throw new Error('[Graph Error] Cyclic dependency detected')\n engine.cycleDetectionStack.add(computedNode)\n const prevConsumer = engine.activeConsumer\n engine.activeConsumer = computedNode\n \n // Динамическое ленивое отсечение старых ребер перед каждым пересчетом (Dynamic Deps)\n dependencies.forEach(dep => {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n })\n dependencies.clear()\n depVersions.clear()\n \n try {\n const newValue = fn()\n const isObj = value && typeof value === 'object'\n const changed = isDirty || (!isObj && value !== newValue) || (isObj && JSON.stringify(value) !== JSON.stringify(newValue))\n \n if (changed) {\n value = newValue\n version++\n \n subscribers.forEach(sub => {\n sub.isDirty = true\n engine.pendingEffects.add(sub)\n })\n } else {\n subscribers.forEach(sub => {\n sub.isDirty = false\n })\n }\n isDirty = false\n \n // 🟢 ИСПРАВЛЕНО (Dynamic Deps & #22): Фиксируем слепки версий СТРОГО внутри run(),\n // когда актуальный граф зависимостей текущего кадра сформирован окончательно.\n // Мапа depVersions всегда содержит только живые ребра без фантомных хвостов!\n let maxDepDepth = 0\n dependencies.forEach(dep => {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version !== undefined ? rawNode.version : engine.epoch)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) maxDepDepth = rawNode.depth\n })\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.cycleDetectionStack.delete(computedNode)\n }\n },\n markDirty: () => {\n if (!isDirty) {\n isDirty = true\n subscribers.forEach(sub => {\n const wasDirty = sub.isDirty\n sub.isDirty = true\n engine.pendingEffects.add(sub)\n if (!wasDirty && sub.subscribers) {\n sub.subscribers.forEach((s: any) => {\n s.isDirty = true\n engine.pendingEffects.add(s)\n })\n }\n })\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n // Регистрируем любой активный консьюмер графа на фазе ленивого Pull-чтения\n if (engine.activeConsumer && engine.activeConsumer !== computedNode) {\n computedNode.subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(computedNode)\n }\n \n let needsUpdate = isDirty\n \n // Сверяем сохраненные версии зависимостей. Если родитель изменился, версия не совпадет\n if (!needsUpdate && dependencies.size > 0) {\n for (const dep of Array.from(dependencies)) {\n const rawNode = (dep as any)._node || dep\n const currentVer = rawNode.version !== undefined ? rawNode.version : (dep.version !== undefined ? dep.version : engine.epoch)\n if (currentVer !== depVersions.get(dep)) {\n needsUpdate = true\n break\n }\n }\n }\n \n if (needsUpdate) {\n computedNode.run()\n }\n return value\n },\n get version() {\n return version\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 computedNode.subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n computedNode.subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n computedNode.subscribers.clear()\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n isDirty = true\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 computedNode.subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n\n ;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n ;(computedInstance as any).dependencies = dependencies\n \n computedInstance._isDirty = () => isDirty\n computedInstance.type = 'computed'\n computedInstance.run = () => computedNode.run()\n \n computedNode.destroy = () => {\n engine.computedCache.delete(fn)\n }\n\n engine.computedCache.set(fn, new WeakRef(computedInstance as any))\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":["import { Computed, CleanupFn } from './types'\n\nexport function createComputed<T>(\n engine: any,\n fn: () => T,\n signalName?: string\n): Computed<T> {\n const cachedRef = engine.computedCache.get(fn)\n const existing = cachedRef?.deref()\n if (existing) return existing as Computed<T>\n\n let value: T\n let isDirty = true\n let version = 0\n let versionCheckRequired = false\n\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n\n const releaseNode = (node: any): void => {\n if (!node) return\n const actNode = node._node || node\n if (actNode.dependencies && actNode.dependencies.size > 0) {\n const snapshotDeps = Array.from(actNode.dependencies)\n actNode.dependencies.clear()\n if (actNode.depVersions) actNode.depVersions.clear()\n\n snapshotDeps.forEach((dep: any) => {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) {\n rawDepNode.subscribers.delete(actNode)\n rawDepNode.subscribers.delete(node)\n rawDepNode.subscribers.delete(computedNode)\n if (rawDepNode.type === 'computed' && rawDepNode.subscribers.size === 0) {\n releaseNode(rawDepNode)\n }\n }\n })\n }\n }\n\n const subscribers = new class extends Set<any> {\n override delete(val: any): boolean {\n const res = super.delete(val)\n if (this.size === 0) {\n isDirty = true\n versionCheckRequired = true\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n }\n return res\n }\n }()\n\n // 🟢 КАНОНИЧЕСКИЙ ТОПОЛОГИЧЕСКИЙ ВАЛИДАТОР ГРАФА (Сверху Вниз)\n // Рекурсивно проверяет родителей и возвращает true, если выше по цепочке была хоть одна мутация.\n const checkUpstreamModifications = (node: any): boolean => {\n if (!node) return false\n const actNode = node._node || node\n\n // Чисто ленивые цепочки без эффектов (subscribers.size === 0) обязаны всегда рекурсивно\n // опрашивать предков, так как до них ленивое клеймение markDirty физически не долетает!\n const hasActiveSubscribers = actNode.subscribers && actNode.subscribers.size > 0\n if (hasActiveSubscribers && !actNode.versionCheckRequired) {\n return false\n }\n\n let hasChangedParent = false\n const depsArray = Array.from(actNode.dependencies || [])\n\n // 1. ФАЗА 1: Рекурсивно погружаемся в дедушек до самых корней графа\n for (const dep of depsArray) {\n const rawDep = (dep as any)._node || dep\n if (rawDep.type === 'computed' && (rawDep.versionCheckRequired || !hasActiveSubscribers)) {\n checkUpstreamModifications(rawDep)\n }\n }\n\n // 2. ФАЗА 2: Атомарно сверяем версии рёбер графа строго после схождения верхних каскадов.\n // Временная подмена activeConsumer гарантирует кристальную чистоту Dynamic Deps!\n const savedConsumer = engine.activeConsumer\n for (const dep of depsArray) {\n const rawDep = (dep as any)._node || dep\n\n if (rawDep.type === 'computed' && (rawDep.isDirty || rawDep.versionCheckRequired || !hasActiveSubscribers)) {\n engine.activeConsumer = rawDep\n try {\n rawDep.run()\n } finally {\n engine.activeConsumer = savedConsumer\n }\n }\n\n const currentVer = rawDep.version !== undefined ? rawDep.version : ((dep as any).version !== undefined ? (dep as any).version : engine.epoch)\n\n // СИНХРОНИЗАЦИЯ РЕБРА СВЯЗИ ВРЕМЕНИ ГРАФА:\n // Сверяем актуальную версию родителя со старым слепком в депо-версиях ребенка.\n if (!actNode.depVersions.has(dep) || currentVer !== actNode.depVersions.get(dep)) {\n hasChangedParent = true\n }\n\n // Атомарно перезаписываем свежую актуальную версию родителя в локальный слепок ребенка,\n // намертво защищая глубокие ленивые матрешки от протухания кэша!\n actNode.depVersions.set(dep, currentVer)\n }\n engine.activeConsumer = savedConsumer\n\n actNode.versionCheckRequired = false\n return hasChangedParent\n }\n\n const computedNode: any = {\n id: engine.subscriberId++,\n dependencies,\n subscribers,\n depth: 1,\n type: 'computed',\n fn,\n get version() { return version },\n get versionCheckRequired() { return versionCheckRequired },\n set versionCheckRequired(val: boolean) { versionCheckRequired = val },\n get depVersions() { return depVersions },\n run: () => {\n if (engine.cycleDetectionStack.has(computedNode)) throw new Error('[Graph Error] Cyclic dependency detected')\n engine.cycleDetectionStack.add(computedNode)\n const prevConsumer = engine.activeConsumer\n engine.activeConsumer = computedNode\n\n const oldDeps = Array.from(dependencies)\n const oldVersions = new Map(depVersions)\n\n dependencies.forEach(dep => {\n const rawDepNode = dep._node || dep\n if (rawDepNode.subscribers) rawDepNode.subscribers.delete(computedNode)\n })\n dependencies.clear()\n depVersions.clear()\n\n try {\n const newValue = fn()\n const isObj = (value && typeof value === 'object') || (newValue && typeof newValue === 'object')\n\n // КРИСТАЛЬНО ЧИСТОЕ СРАВНЕНИЕ ИЗМЕНЕНИЙ ПО ЗНАЧЕНИЮ (Value Equality)\n const changed = isDirty || isObj || 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) {\n engine.log({\n type: 'computed',\n label: signalName || `computed:[${fn.name || computedNode.id}]`,\n details: { from: previousValueSnapshot, to: newValue }\n })\n }\n\n subscribers.forEach(sub => {\n const rawSub = sub._node || sub\n rawSub.isDirty = true\n if (rawSub.type === 'effect') {\n engine.pendingEffects.add(sub)\n }\n if (rawSub.markDirty) rawSub.markDirty()\n })\n } else {\n // VALUE EQUALITY CUT: Значение примитива не изменилось!\n subscribers.forEach(sub => {\n const rawSub = sub._node || sub\n if (rawSub.depVersions) {\n rawSub.depVersions.set(computedInstance, version)\n }\n if (rawSub.type === 'effect') {\n rawSub.isDirty = false\n engine.pendingEffects.delete(sub)\n }\n })\n }\n\n isDirty = false\n versionCheckRequired = false\n\n let maxDepDepth = 0\n let hasSameDeps = dependencies.size === oldDeps.length\n\n dependencies.forEach(dep => {\n const rawNode = dep._node || dep\n const currentVer = rawNode.version !== undefined ? rawNode.version : (dep.version !== undefined ? dep.version : engine.epoch)\n depVersions.set(dep, currentVer)\n if (rawNode.depth !== undefined && rawNode.depth > maxDepDepth) maxDepDepth = rawNode.depth\n if (hasSameDeps && !oldDeps.includes(dep)) hasSameDeps = false\n })\n\n // ПАТТЕРН МЕЖКАДРОВОЙ СИНХРОНИЗАЦИИ: Если состав родителей стабилен, мы восстанавливаем\n // точные числовые тайминги версий из старого кадра, спасая длинные ленивые цепочки!\n if (hasSameDeps && oldVersions.size > 0) {\n oldVersions.forEach((ver, dep) => {\n if (depVersions.has(dep)) {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version !== undefined ? rawNode.version : ver)\n }\n })\n } else if (!hasSameDeps && oldVersions.size > 0) {\n oldVersions.forEach((ver, dep) => {\n if (depVersions.has(dep)) {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version !== undefined ? rawNode.version : ver)\n }\n })\n }\n\n computedNode.depth = maxDepDepth + 1\n return changed\n } finally {\n engine.activeConsumer = prevConsumer\n engine.cycleDetectionStack.delete(computedNode)\n }\n },\n markDirty: () => {\n if (!versionCheckRequired) {\n versionCheckRequired = true\n subscribers.forEach(sub => {\n const rawSub = sub._node || sub\n rawSub.isDirty = true\n if (rawSub.type === 'effect') {\n engine.pendingEffects.add(sub)\n }\n if (rawSub.markDirty) rawSub.markDirty()\n })\n }\n }\n }\n\n const computedInstance: Computed<T> = {\n get value() {\n if (engine.activeConsumer && engine.activeConsumer !== computedNode) {\n computedNode.subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(computedNode)\n }\n\n // 1. ФАЗА СВЕРХУ ВНИЗ: Рекурсивно опрашиваем родителей, выявляя сквозные мутации версий\n const upstreamChanged = checkUpstreamModifications(computedNode)\n\n // 2. ВТОРАЯ ФАЗА: Строгая атомарная сверка версий ребер графа строго после Pull каскада\n let needsUpdate = isDirty || upstreamChanged\n\n if (!needsUpdate && dependencies.size > 0) {\n for (const dep of Array.from(dependencies)) {\n const rawNode = (dep as any)._node || dep\n const currentVer = rawNode.version !== undefined ? rawNode.version : (dep.version !== undefined ? dep.version : engine.epoch)\n if (currentVer !== depVersions.get(dep)) {\n needsUpdate = true\n break\n }\n }\n }\n\n if (needsUpdate) {\n computedNode.run()\n } else {\n // Логируем холостой проход строго на уровне геттера для полной прозрачной отладки кэша\n if (versionCheckRequired && engine.log) {\n engine.log({\n type: 'computed',\n label: signalName || `computed:[${fn.name || computedNode.id}]`,\n details: { from: value, to: value }\n })\n }\n versionCheckRequired = false\n subscribers.forEach(sub => {\n const rawSub = sub._node || sub\n if (rawSub.depVersions) {\n rawSub.depVersions.set(computedInstance, version)\n }\n })\n }\n return value\n },\n get valueWithoutTracking() { return value },\n get version() { return version },\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 computedNode.subscribers.add(fakeEffect)\n cb(computedInstance.value)\n return () => {\n fakeEffect.isDisposed = true\n computedNode.subscribers.delete(fakeEffect)\n }\n },\n subscribeState(cb: () => void): CleanupFn {\n return (computedInstance as any).subscribe(cb)\n },\n destroy: () => {\n computedNode.subscribers.clear()\n releaseNode(computedNode)\n engine.computedCache.delete(fn)\n isDirty = true\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 computedNode.subscribers.add(hookEffect)\n return () => {\n subscribers.delete(hookEffect)\n }\n }\n } as any\n;(computedInstance as any)._node = computedNode\n ;(computedInstance as any).subscribers = subscribers\n ;(computedInstance as any).dependencies = dependencies\n computedInstance._isDirty = () => isDirty || versionCheckRequired\n computedInstance.type = 'computed'\n computedInstance.run = () => computedNode.run()\n computedNode.destroy = () => {\n engine.computedCache.delete(fn)\n }\n engine.computedCache.set(fn, new WeakRef(computedInstance as any))\n return computedInstance\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("./utils/getExtractedValues.cjs");function t(t,n,r){let i=n,a=0,o=new Set,s=typeof r==`string`?r:r?.name||``,c=e.getExtractedValues({tested:[s],expectedKey:`CORE_INTERNAL_SIGNAL`,valueType:`number`})?.toString()===`1`||!1,l={subscribers:o,id:t.subscriberId++,depth:0,type:`signal`,get version(){return a}},u={get value(){return t.activeConsumer&&(o.add(t.activeConsumer),t.activeConsumer.dependencies.add(l)),i},set value(e){if(i===e&&!(i&&typeof i==`object`))return;if(r&&typeof r==`object`&&r.validate){let t=r.validate(e);if(t!==!0){console.error(typeof t==`string`?t:`[Validation Error]`);return}}let n=i;i=e,a++,t.epoch++,t.log({type:`signal`,label:s||`signal`,details:{from:n,to:e},isInternalCoreSignal:c});let o=e=>{e.subscribers.forEach(e=>{if(e===t.activeConsumer)return;let n=e.isDirty;e.isDirty=!0,e.type===`effect`?t.pendingEffects.add(e):(t.pendingEffects.add(e),e.markDirty?e.markDirty():!n&&e.subscribers&&o(e))})};o(l),t.batchDepth===0&&t.flushEffects()},get version(){return a},subscribe(e){let n={id:t.subscriberId++,isDirty:!0,depth:9999,dependencies:new Set,run:()=>{if(!n.isDisposed)try{e(i)}catch(e){console.error(e)}}};return o.add(n),e(i),()=>{n.isDisposed=!0,o.delete(n)}}};return u._node=l,u}exports.createSignal=t;
1
+ const e=require("./utils/getExtractedValues.cjs");function t(t,n,r){let i=n,a=0,o=new Set,s=typeof r==`string`?r:r?.name||``,c=e.getExtractedValues({tested:[s],expectedKey:`CORE_INTERNAL_SIGNAL`,valueType:`number`})?.[0]===`1`||!1,l={subscribers:o,id:t.subscriberId++,depth:0,type:`signal`,get version(){return a}},u={get value(){return t.activeConsumer&&(o.add(t.activeConsumer),t.activeConsumer.dependencies.add(l)),i},set value(e){if(i===e&&!(i&&typeof i==`object`))return;if(r&&typeof r==`object`&&r.validate){let t=r.validate(e);if(t!==!0){console.error(typeof t==`string`?t:`[Validation Error]`);return}}let n=i;i=e,a++,t.epoch++,t.log({type:`signal`,label:s||`signal`,details:{from:n,to:e},isInternalCoreSignal:c}),o.forEach(e=>{let n=e._node||e;n.isDirty=!0,n.type===`effect`&&t.pendingEffects.add(e),n.markDirty&&n.markDirty()}),t.batchDepth===0&&t.flushEffects()},get version(){return a},subscribe(e){let n={id:t.subscriberId++,isDirty:!0,depth:9999,dependencies:new Set,type:`effect`,run:()=>{if(!n.isDisposed)try{e(i)}catch(e){console.error(e)}}};return o.add(n),e(i),()=>{n.isDisposed=!0,o.delete(n)}}};return u._node=l,u}exports.createSignal=t;
2
2
  //# sourceMappingURL=core.method.signal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.signal.cjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, CleanupFn, SignalOptions } from './types'\n\n/**\n * Изолированная фабрика сигналов реактивного графа.\n * Полностью отвязана от лексического контекста класса для абсолютной чистоты V8.\n */\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: string | SignalOptions<T>\n): Signal<T> {\n let value = initialValue\n let version = 0\n const subscribers = new Set<any>()\n const name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name || ''\n \n const isInternalCoreSignal = getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.toString() === '1' || false\n\n const signalNode = {\n subscribers,\n id: engine.subscriberId++,\n depth: 0,\n type: 'signal',\n get version() { return version }\n }\n\n const sigInstance = {\n get value() {\n if (engine.activeConsumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalNode)\n }\n return value\n },\n set value(newValue: T) {\n const isObj = value && typeof value === 'object'\n if (value === newValue && !isObj) return\n \n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n \n const oldValue = value\n value = newValue\n version++\n engine.epoch++\n engine.log({ type: 'signal', label: name || 'signal', details: { from: oldValue, to: newValue }, isInternalCoreSignal })\n \n const markDirtyNode = (node: any) => {\n node.subscribers.forEach((sub: any) => {\n if (sub === engine.activeConsumer) return\n \n const wasDirty = sub.isDirty\n sub.isDirty = true\n \n if (sub.type === 'effect') {\n engine.pendingEffects.add(sub)\n } else {\n engine.pendingEffects.add(sub)\n // 🟢 ИСПРАВЛЕНО: Если подписчик — это компьютед, делегируем каскад инвалидации его нативному методу markDirty\n if (sub.markDirty) {\n sub.markDirty()\n } else if (!wasDirty && sub.subscribers) {\n markDirtyNode(sub)\n }\n }\n })\n }\n \n markDirtyNode(signalNode)\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n get version() { return version },\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 run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(value) } catch (err) { console.error(err) }\n }\n }\n subscribers.add(fakeEffect)\n cb(value)\n return () => {\n fakeEffect.isDisposed = true\n subscribers.delete(fakeEffect)\n }\n }\n }\n\n ;(sigInstance as any)._node = signalNode\n return sigInstance as any\n}\n"],"mappings":"kDAOA,SAAgB,EACd,EACA,EACA,EACW,CACX,IAAI,EAAQ,EACR,EAAU,EACR,EAAc,IAAI,IAClB,EAAO,OAAO,GAAkB,SAAW,EAAgB,GAAe,MAAQ,GAElF,EAAuB,EAAA,mBAAmB,CAC9C,OAAQ,CAAC,CAAI,EACb,YAAa,uBACb,UAAW,QACb,CAAC,CAAC,EAAE,SAAS,IAAM,KAAO,GAEpB,EAAa,CACjB,cACA,GAAI,EAAO,eACX,MAAO,EACP,KAAM,SACN,IAAI,SAAU,CAAE,OAAO,CAAQ,CACjC,EAEM,EAAc,CAClB,IAAI,OAAQ,CAKV,OAJI,EAAO,iBACT,EAAY,IAAI,EAAO,cAAc,EACrC,EAAO,eAAe,aAAa,IAAI,CAAU,GAE5C,CACT,EACA,IAAI,MAAM,EAAa,CAErB,GAAI,IAAU,GAAY,EADZ,GAAS,OAAO,GAAU,UACN,OAElC,GAAI,GAAiB,OAAO,GAAkB,UAAY,EAAc,SAAU,CAChF,IAAM,EAAa,EAAc,SAAS,CAAQ,EAClD,GAAI,IAAe,GAAM,CACvB,QAAQ,MAAM,OAAO,GAAe,SAAW,EAAa,oBAAoB,EAChF,MACF,CACF,CAEA,IAAM,EAAW,EACjB,EAAQ,EACR,IACA,EAAO,QACP,EAAO,IAAI,CAAE,KAAM,SAAU,MAAO,GAAQ,SAAU,QAAS,CAAE,KAAM,EAAU,GAAI,CAAS,EAAG,sBAAqB,CAAC,EAEvH,IAAM,EAAiB,GAAc,CACnC,EAAK,YAAY,QAAS,GAAa,CACrC,GAAI,IAAQ,EAAO,eAAgB,OAEnC,IAAM,EAAW,EAAI,QACrB,EAAI,QAAU,GAEV,EAAI,OAAS,SACf,EAAO,eAAe,IAAI,CAAG,GAE7B,EAAO,eAAe,IAAI,CAAG,EAEzB,EAAI,UACN,EAAI,UAAU,EACL,CAAC,GAAY,EAAI,aAC1B,EAAc,CAAG,EAGvB,CAAC,CACH,EAEA,EAAc,CAAU,EACpB,EAAO,aAAe,GAAG,EAAO,aAAa,CACnD,EACA,IAAI,SAAU,CAAE,OAAO,CAAQ,EAC/B,UAAU,EAAiC,CACzC,IAAM,EAAkB,CACtB,GAAI,EAAO,eACX,QAAS,GACT,MAAO,KACP,aAAc,IAAI,IAClB,QAAW,CACL,MAAW,WACf,GAAI,CAAE,EAAG,CAAK,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CACrD,CACF,EAGA,OAFA,EAAY,IAAI,CAAU,EAC1B,EAAG,CAAK,MACK,CACX,EAAW,WAAa,GACxB,EAAY,OAAO,CAAU,CAC/B,CACF,CACF,EAGA,MADC,GAAqB,MAAQ,EACvB,CACT"}
1
+ {"version":3,"file":"core.method.signal.cjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, CleanupFn, SignalOptions } from './types'\n\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: string | SignalOptions<T>\n): Signal<T> {\n let value = initialValue\n let version = 0\n const subscribers = new Set<any>()\n const name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name || ''\n\n const isInternalCoreSignal = getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.[0] === '1' || false\n\n const signalNode = {\n subscribers,\n id: engine.subscriberId++,\n depth: 0,\n type: 'signal',\n get version() { return version }\n }\n\n const sigInstance = {\n get value() {\n if (engine.activeConsumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalNode)\n }\n return value\n },\n set value(newValue: T) {\n const isObj = value && typeof value === 'object'\n if (value === newValue && !isObj) return\n\n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n\n const oldValue = value\n value = newValue\n\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal',\n details: { from: oldValue, to: newValue },\n isInternalCoreSignal\n })\n\n // ⚛️ Синхронное каскадное уведомление подписчиков\n subscribers.forEach((sub: any) => {\n const rawSub = sub._node || sub\n\n rawSub.isDirty = true\n if (rawSub.type === 'effect') {\n engine.pendingEffects.add(sub)\n }\n if (rawSub.markDirty) {\n rawSub.markDirty()\n }\n })\n\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n get version() { return version },\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(value) } catch (err) { console.error(err) }\n }\n }\n subscribers.add(fakeEffect)\n cb(value)\n return () => {\n fakeEffect.isDisposed = true\n subscribers.delete(fakeEffect)\n }\n }\n }\n\n ;(sigInstance as any)._node = signalNode\n return sigInstance as any\n}\n"],"mappings":"kDAGA,SAAgB,EACd,EACA,EACA,EACW,CACX,IAAI,EAAQ,EACR,EAAU,EACR,EAAc,IAAI,IAClB,EAAO,OAAO,GAAkB,SAAW,EAAgB,GAAe,MAAQ,GAElF,EAAuB,EAAA,mBAAmB,CAC9C,OAAQ,CAAC,CAAI,EACb,YAAa,uBACb,UAAW,QACb,CAAC,CAAC,GAAG,KAAO,KAAO,GAEb,EAAa,CACjB,cACA,GAAI,EAAO,eACX,MAAO,EACP,KAAM,SACN,IAAI,SAAU,CAAE,OAAO,CAAQ,CACjC,EAEM,EAAc,CAClB,IAAI,OAAQ,CAKV,OAJI,EAAO,iBACT,EAAY,IAAI,EAAO,cAAc,EACrC,EAAO,eAAe,aAAa,IAAI,CAAU,GAE5C,CACT,EACA,IAAI,MAAM,EAAa,CAErB,GAAI,IAAU,GAAY,EADZ,GAAS,OAAO,GAAU,UACN,OAElC,GAAI,GAAiB,OAAO,GAAkB,UAAY,EAAc,SAAU,CAChF,IAAM,EAAa,EAAc,SAAS,CAAQ,EAClD,GAAI,IAAe,GAAM,CACvB,QAAQ,MAAM,OAAO,GAAe,SAAW,EAAa,oBAAoB,EAChF,MACF,CACF,CAEA,IAAM,EAAW,EACjB,EAAQ,EAER,IACA,EAAO,QAEP,EAAO,IAAI,CACT,KAAM,SACN,MAAO,GAAQ,SACf,QAAS,CAAE,KAAM,EAAU,GAAI,CAAS,EACxC,sBACF,CAAC,EAGD,EAAY,QAAS,GAAa,CAChC,IAAM,EAAS,EAAI,OAAS,EAE5B,EAAO,QAAU,GACb,EAAO,OAAS,UAClB,EAAO,eAAe,IAAI,CAAG,EAE3B,EAAO,WACT,EAAO,UAAU,CAErB,CAAC,EAEG,EAAO,aAAe,GAAG,EAAO,aAAa,CACnD,EACA,IAAI,SAAU,CAAE,OAAO,CAAQ,EAC/B,UAAU,EAAiC,CACzC,IAAM,EAAkB,CACtB,GAAI,EAAO,eACX,QAAS,GACT,MAAO,KACP,aAAc,IAAI,IAClB,KAAM,SACN,QAAW,CACL,MAAW,WACf,GAAI,CAAE,EAAG,CAAK,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CACrD,CACF,EAGA,OAFA,EAAY,IAAI,CAAU,EAC1B,EAAG,CAAK,MACK,CACX,EAAW,WAAa,GACxB,EAAY,OAAO,CAAU,CAC/B,CACF,CACF,EAGA,MADC,GAAqB,MAAQ,EACvB,CACT"}
@@ -5,7 +5,7 @@ function t(t, n, r) {
5
5
  tested: [s],
6
6
  expectedKey: "CORE_INTERNAL_SIGNAL",
7
7
  valueType: "number"
8
- })?.toString() === "1" || !1, l = {
8
+ })?.[0] === "1" || !1, l = {
9
9
  subscribers: o,
10
10
  id: t.subscriberId++,
11
11
  depth: 0,
@@ -35,15 +35,10 @@ function t(t, n, r) {
35
35
  to: e
36
36
  },
37
37
  isInternalCoreSignal: c
38
- });
39
- let o = (e) => {
40
- e.subscribers.forEach((e) => {
41
- if (e === t.activeConsumer) return;
42
- let n = e.isDirty;
43
- e.isDirty = !0, e.type === "effect" ? t.pendingEffects.add(e) : (t.pendingEffects.add(e), e.markDirty ? e.markDirty() : !n && e.subscribers && o(e));
44
- });
45
- };
46
- o(l), t.batchDepth === 0 && t.flushEffects();
38
+ }), o.forEach((e) => {
39
+ let n = e._node || e;
40
+ n.isDirty = !0, n.type === "effect" && t.pendingEffects.add(e), n.markDirty && n.markDirty();
41
+ }), t.batchDepth === 0 && t.flushEffects();
47
42
  },
48
43
  get version() {
49
44
  return a;
@@ -54,6 +49,7 @@ function t(t, n, r) {
54
49
  isDirty: !0,
55
50
  depth: 9999,
56
51
  dependencies: /* @__PURE__ */ new Set(),
52
+ type: "effect",
57
53
  run: () => {
58
54
  if (!n.isDisposed) try {
59
55
  e(i);
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.signal.mjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, CleanupFn, SignalOptions } from './types'\n\n/**\n * Изолированная фабрика сигналов реактивного графа.\n * Полностью отвязана от лексического контекста класса для абсолютной чистоты V8.\n */\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: string | SignalOptions<T>\n): Signal<T> {\n let value = initialValue\n let version = 0\n const subscribers = new Set<any>()\n const name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name || ''\n \n const isInternalCoreSignal = getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.toString() === '1' || false\n\n const signalNode = {\n subscribers,\n id: engine.subscriberId++,\n depth: 0,\n type: 'signal',\n get version() { return version }\n }\n\n const sigInstance = {\n get value() {\n if (engine.activeConsumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalNode)\n }\n return value\n },\n set value(newValue: T) {\n const isObj = value && typeof value === 'object'\n if (value === newValue && !isObj) return\n \n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n \n const oldValue = value\n value = newValue\n version++\n engine.epoch++\n engine.log({ type: 'signal', label: name || 'signal', details: { from: oldValue, to: newValue }, isInternalCoreSignal })\n \n const markDirtyNode = (node: any) => {\n node.subscribers.forEach((sub: any) => {\n if (sub === engine.activeConsumer) return\n \n const wasDirty = sub.isDirty\n sub.isDirty = true\n \n if (sub.type === 'effect') {\n engine.pendingEffects.add(sub)\n } else {\n engine.pendingEffects.add(sub)\n // 🟢 ИСПРАВЛЕНО: Если подписчик — это компьютед, делегируем каскад инвалидации его нативному методу markDirty\n if (sub.markDirty) {\n sub.markDirty()\n } else if (!wasDirty && sub.subscribers) {\n markDirtyNode(sub)\n }\n }\n })\n }\n \n markDirtyNode(signalNode)\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n get version() { return version },\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 run: () => {\n if (fakeEffect.isDisposed) return\n try { cb(value) } catch (err) { console.error(err) }\n }\n }\n subscribers.add(fakeEffect)\n cb(value)\n return () => {\n fakeEffect.isDisposed = true\n subscribers.delete(fakeEffect)\n }\n }\n }\n\n ;(sigInstance as any)._node = signalNode\n return sigInstance as any\n}\n"],"mappings":";;AAOA,SAAgB,EACd,GACA,GACA,GACW;CACX,IAAI,IAAQ,GACR,IAAU,GACR,oBAAc,IAAI,IAAS,GAC3B,IAAO,OAAO,KAAkB,WAAW,IAAgB,GAAe,QAAQ,IAElF,IAAuB,EAAmB;EAC9C,QAAQ,CAAC,CAAI;EACb,aAAa;EACb,WAAW;CACb,CAAC,CAAC,EAAE,SAAS,MAAM,OAAO,IAEpB,IAAa;EACjB;EACA,IAAI,EAAO;EACX,OAAO;EACP,MAAM;EACN,IAAI,UAAU;GAAE,OAAO;EAAQ;CACjC,GAEM,IAAc;EAClB,IAAI,QAAQ;GAKV,OAJI,EAAO,mBACT,EAAY,IAAI,EAAO,cAAc,GACrC,EAAO,eAAe,aAAa,IAAI,CAAU,IAE5C;EACT;EACA,IAAI,MAAM,GAAa;GAErB,IAAI,MAAU,KAAY,EADZ,KAAS,OAAO,KAAU,WACN;GAElC,IAAI,KAAiB,OAAO,KAAkB,YAAY,EAAc,UAAU;IAChF,IAAM,IAAa,EAAc,SAAS,CAAQ;IAClD,IAAI,MAAe,IAAM;KACvB,QAAQ,MAAM,OAAO,KAAe,WAAW,IAAa,oBAAoB;KAChF;IACF;GACF;GAEA,IAAM,IAAW;GAIjB,AAHA,IAAQ,GACR,KACA,EAAO,SACP,EAAO,IAAI;IAAE,MAAM;IAAU,OAAO,KAAQ;IAAU,SAAS;KAAE,MAAM;KAAU,IAAI;IAAS;IAAG;GAAqB,CAAC;GAEvH,IAAM,KAAiB,MAAc;IACnC,EAAK,YAAY,SAAS,MAAa;KACrC,IAAI,MAAQ,EAAO,gBAAgB;KAEnC,IAAM,IAAW,EAAI;KAGrB,AAFA,EAAI,UAAU,IAEV,EAAI,SAAS,WACf,EAAO,eAAe,IAAI,CAAG,KAE7B,EAAO,eAAe,IAAI,CAAG,GAEzB,EAAI,YACN,EAAI,UAAU,IACL,CAAC,KAAY,EAAI,eAC1B,EAAc,CAAG;IAGvB,CAAC;GACH;GAGA,AADA,EAAc,CAAU,GACpB,EAAO,eAAe,KAAG,EAAO,aAAa;EACnD;EACA,IAAI,UAAU;GAAE,OAAO;EAAQ;EAC/B,UAAU,GAAiC;GACzC,IAAM,IAAkB;IACtB,IAAI,EAAO;IACX,SAAS;IACT,OAAO;IACP,8BAAc,IAAI,IAAI;IACtB,WAAW;KACL,OAAW,YACf,IAAI;MAAE,EAAG,CAAK;KAAE,SAAS,GAAK;MAAE,QAAQ,MAAM,CAAG;KAAE;IACrD;GACF;GAGA,OAFA,EAAY,IAAI,CAAU,GAC1B,EAAG,CAAK,SACK;IAEX,AADA,EAAW,aAAa,IACxB,EAAY,OAAO,CAAU;GAC/B;EACF;CACF;CAGA,OADC,EAAqB,QAAQ,GACvB;AACT"}
1
+ {"version":3,"file":"core.method.signal.mjs","names":[],"sources":["../src/core/core.method.signal.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, CleanupFn, SignalOptions } from './types'\n\nexport function createSignal<T>(\n engine: any,\n initialValue: T,\n optionsOrName?: string | SignalOptions<T>\n): Signal<T> {\n let value = initialValue\n let version = 0\n const subscribers = new Set<any>()\n const name = typeof optionsOrName === 'string' ? optionsOrName : optionsOrName?.name || ''\n\n const isInternalCoreSignal = getExtractedValues({\n tested: [name],\n expectedKey: 'CORE_INTERNAL_SIGNAL',\n valueType: 'number',\n })?.[0] === '1' || false\n\n const signalNode = {\n subscribers,\n id: engine.subscriberId++,\n depth: 0,\n type: 'signal',\n get version() { return version }\n }\n\n const sigInstance = {\n get value() {\n if (engine.activeConsumer) {\n subscribers.add(engine.activeConsumer)\n engine.activeConsumer.dependencies.add(signalNode)\n }\n return value\n },\n set value(newValue: T) {\n const isObj = value && typeof value === 'object'\n if (value === newValue && !isObj) return\n\n if (optionsOrName && typeof optionsOrName === 'object' && optionsOrName.validate) {\n const validation = optionsOrName.validate(newValue)\n if (validation !== true) {\n console.error(typeof validation === 'string' ? validation : '[Validation Error]')\n return\n }\n }\n\n const oldValue = value\n value = newValue\n\n version++\n engine.epoch++\n\n engine.log({\n type: 'signal',\n label: name || 'signal',\n details: { from: oldValue, to: newValue },\n isInternalCoreSignal\n })\n\n // ⚛️ Синхронное каскадное уведомление подписчиков\n subscribers.forEach((sub: any) => {\n const rawSub = sub._node || sub\n\n rawSub.isDirty = true\n if (rawSub.type === 'effect') {\n engine.pendingEffects.add(sub)\n }\n if (rawSub.markDirty) {\n rawSub.markDirty()\n }\n })\n\n if (engine.batchDepth === 0) engine.flushEffects()\n },\n get version() { return version },\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(value) } catch (err) { console.error(err) }\n }\n }\n subscribers.add(fakeEffect)\n cb(value)\n return () => {\n fakeEffect.isDisposed = true\n subscribers.delete(fakeEffect)\n }\n }\n }\n\n ;(sigInstance as any)._node = signalNode\n return sigInstance as any\n}\n"],"mappings":";;AAGA,SAAgB,EACd,GACA,GACA,GACW;CACX,IAAI,IAAQ,GACR,IAAU,GACR,oBAAc,IAAI,IAAS,GAC3B,IAAO,OAAO,KAAkB,WAAW,IAAgB,GAAe,QAAQ,IAElF,IAAuB,EAAmB;EAC9C,QAAQ,CAAC,CAAI;EACb,aAAa;EACb,WAAW;CACb,CAAC,CAAC,GAAG,OAAO,OAAO,IAEb,IAAa;EACjB;EACA,IAAI,EAAO;EACX,OAAO;EACP,MAAM;EACN,IAAI,UAAU;GAAE,OAAO;EAAQ;CACjC,GAEM,IAAc;EAClB,IAAI,QAAQ;GAKV,OAJI,EAAO,mBACT,EAAY,IAAI,EAAO,cAAc,GACrC,EAAO,eAAe,aAAa,IAAI,CAAU,IAE5C;EACT;EACA,IAAI,MAAM,GAAa;GAErB,IAAI,MAAU,KAAY,EADZ,KAAS,OAAO,KAAU,WACN;GAElC,IAAI,KAAiB,OAAO,KAAkB,YAAY,EAAc,UAAU;IAChF,IAAM,IAAa,EAAc,SAAS,CAAQ;IAClD,IAAI,MAAe,IAAM;KACvB,QAAQ,MAAM,OAAO,KAAe,WAAW,IAAa,oBAAoB;KAChF;IACF;GACF;GAEA,IAAM,IAAW;GA0BjB,AAzBA,IAAQ,GAER,KACA,EAAO,SAEP,EAAO,IAAI;IACT,MAAM;IACN,OAAO,KAAQ;IACf,SAAS;KAAE,MAAM;KAAU,IAAI;IAAS;IACxC;GACF,CAAC,GAGD,EAAY,SAAS,MAAa;IAChC,IAAM,IAAS,EAAI,SAAS;IAM5B,AAJA,EAAO,UAAU,IACb,EAAO,SAAS,YAClB,EAAO,eAAe,IAAI,CAAG,GAE3B,EAAO,aACT,EAAO,UAAU;GAErB,CAAC,GAEG,EAAO,eAAe,KAAG,EAAO,aAAa;EACnD;EACA,IAAI,UAAU;GAAE,OAAO;EAAQ;EAC/B,UAAU,GAAiC;GACzC,IAAM,IAAkB;IACtB,IAAI,EAAO;IACX,SAAS;IACT,OAAO;IACP,8BAAc,IAAI,IAAI;IACtB,MAAM;IACN,WAAW;KACL,OAAW,YACf,IAAI;MAAE,EAAG,CAAK;KAAE,SAAS,GAAK;MAAE,QAAQ,MAAM,CAAG;KAAE;IACrD;GACF;GAGA,OAFA,EAAY,IAAI,CAAU,GAC1B,EAAG,CAAK,SACK;IAEX,AADA,EAAW,aAAa,IACxB,EAAY,OAAO,CAAU;GAC/B;EACF;CACF;CAGA,OADC,EAAqB,QAAQ,GACvB;AACT"}
package/dist/core.mjs CHANGED
@@ -5,16 +5,17 @@ import { executeBatch as r } from "./core.method.batch.mjs";
5
5
  import { executeUntrack as i } from "./core.method.untrack.mjs";
6
6
  import { createReactive as a } from "./core.method.reactive.mjs";
7
7
  import { createEffect as o } from "./core.method.effect.mjs";
8
+ import { ReactiveDebounceLogger as s } from "./core.logger.mjs";
8
9
  //#region src/core/core.ts
9
- var s = {
10
+ var c = {
10
11
  signal: "background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;",
11
12
  computed: "background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;",
12
13
  effect: "background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;",
13
14
  batch: "background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;",
14
15
  resource: "background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;",
15
16
  reactive: "background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;"
16
- }, c = null;
17
- function l(e) {
17
+ }, l = null;
18
+ function u(e) {
18
19
  if (e === null) return "null";
19
20
  if (e === void 0) return "undefined";
20
21
  if (typeof e == "object") try {
@@ -24,12 +25,12 @@ function l(e) {
24
25
  }
25
26
  return String(e);
26
27
  }
27
- function u(e, t, n) {
28
- c || (c = {
28
+ function d(e, t, n) {
29
+ l || (l = {
29
30
  id: Math.random().toString(36).substring(2, 9),
30
31
  pendingLogQueue: [],
31
32
  isFlushing: !1
32
- }, queueMicrotask(() => d())), c.pendingLogQueue.push({
33
+ }, queueMicrotask(() => f())), l.pendingLogQueue.push({
33
34
  type: e,
34
35
  label: t,
35
36
  from: n?.from,
@@ -38,22 +39,22 @@ function u(e, t, n) {
38
39
  timestamp: Date.now()
39
40
  });
40
41
  }
41
- function d() {
42
- if (!c || c.isFlushing) return;
43
- c.isFlushing = !0;
44
- let e = c.pendingLogQueue;
42
+ function f() {
43
+ if (!l || l.isFlushing) return;
44
+ l.isFlushing = !0;
45
+ let e = l.pendingLogQueue;
45
46
  if (e.length === 0) {
46
- c = null;
47
+ l = null;
47
48
  return;
48
49
  }
49
- console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${c.id}] (${e.length} operations)`, "background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;", "color: #888; font-weight: normal;");
50
+ console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${l.id}] (${e.length} operations)`, "background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;", "color: #888; font-weight: normal;");
50
51
  for (let t of e) {
51
- let e = s[t.type], n = t.from !== void 0 || t.to !== void 0, r = `%c${t.type.toUpperCase()}%c ${t.label}`;
52
- n && (t.from ? r += `(${l(t.from)} → ${l(t.to)})` : r += `(${l(t.to)})`), t.payload === void 0 ? console.log(r, e, "color: inherit;") : (console.groupCollapsed(r, e, "color: inherit;"), console.log("Payload:", t.payload), console.groupEnd());
52
+ let e = c[t.type], n = t.from !== void 0 || t.to !== void 0, r = `%c${t.type.toUpperCase()}%c ${t.label}`;
53
+ n && (t.from ? r += ` ${u(t.from)} → ${u(t.to)}` : r += ` (${u(t.to)})`), t.payload === void 0 ? console.log(r, e, "color: inherit;") : (console.groupCollapsed(r, e, "color: inherit;"), console.log("Payload:", t.payload), console.groupEnd());
53
54
  }
54
- console.groupEnd(), c = null;
55
+ console.groupEnd(), l = null;
55
56
  }
56
- var f = class {
57
+ var p = class {
57
58
  frameworkPrefix = "core";
58
59
  logger;
59
60
  epoch = 0;
@@ -72,7 +73,7 @@ var f = class {
72
73
  this.logger = e?.logger || { isEnabled: !1 };
73
74
  }
74
75
  queueLog(e, t, n) {
75
- u(e, t, n);
76
+ d(e, t, n);
76
77
  }
77
78
  flushEffects() {
78
79
  if (this.batchDepth > 0) return;
@@ -84,7 +85,9 @@ var f = class {
84
85
  if (t.dependencies && t.dependencies.size > 0) for (let e of t.dependencies) {
85
86
  let t = e._node || e;
86
87
  if (t.type === "computed" && t._isDirty && t._isDirty()) try {
87
- t.run();
88
+ this.untrack(() => {
89
+ e.value;
90
+ });
88
91
  } catch (e) {
89
92
  if (this.batchDepth === 0) throw e;
90
93
  }
@@ -103,8 +106,12 @@ var f = class {
103
106
  return r(this, e);
104
107
  }
105
108
  log({ type: e, label: t, details: n, isInternalCoreSignal: r = !1 }) {
106
- let i = this.logger.isEnabled, a = this.logger.isCoreOptimizationDebugEnabled;
107
- i && (r ? a && u(e, t, n) : u(e, t, n));
109
+ s.processLog(this.logger, d, {
110
+ type: e,
111
+ label: t,
112
+ details: n,
113
+ isInternalCoreSignal: r
114
+ });
108
115
  }
109
116
  signal(e, t) {
110
117
  return n(this, e, t);
@@ -183,26 +190,7 @@ var f = class {
183
190
  }), u.value = e;
184
191
  }, f = async (n, r, i = !1) => {
185
192
  if (r.aborted) return;
186
- let f = o.validateBeforeFetch ? o.validateBeforeFetch(n) : !0;
187
- if (f === !1) {
188
- u.value = {
189
- loading: !1,
190
- data: null,
191
- error: null,
192
- isRetrying: !1
193
- };
194
- return;
195
- }
196
- if (typeof f == "string") {
197
- u.value = {
198
- loading: !1,
199
- data: null,
200
- error: "Core internal stopper",
201
- isRetrying: !1
202
- };
203
- return;
204
- }
205
- if (l) {
193
+ if (o.validateBeforeFetch && o.validateBeforeFetch(n), l) {
206
194
  let e = l(n);
207
195
  if (e === !1 || typeof e == "string") {
208
196
  if (r.aborted) return;
@@ -216,9 +204,9 @@ var f = class {
216
204
  return;
217
205
  }
218
206
  }
219
- let p = i && s ? null : this.untrack(() => u.value.data);
207
+ let f = i && s ? null : this.untrack(() => u.value.data);
220
208
  d({
221
- data: p,
209
+ data: f,
222
210
  loading: !0,
223
211
  error: null,
224
212
  isRetrying: !1
@@ -321,6 +309,6 @@ var f = class {
321
309
  }
322
310
  };
323
311
  //#endregion
324
- export { f as ReactiveEngine, f as ReactiveEngineAutomatic, f as ReactiveEngineCore, d as flushLogs, u as queueLog };
312
+ export { p as ReactiveEngine, p as ReactiveEngineAutomatic, p as ReactiveEngineCore, f as flushLogs, d as queueLog };
325
313
 
326
314
  //# sourceMappingURL=core.mjs.map