@blac/core 2.0.0-rc-7 → 2.0.0-rc-10
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/index.cjs.js +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +194 -7
- package/dist/index.es.js +1096 -563
- package/dist/index.es.js.map +1 -1
- package/package.json +5 -4
- package/src/Blac.ts +204 -99
- package/src/BlacObserver.ts +62 -25
- package/src/Bloc.ts +166 -149
- package/src/BlocBase.ts +269 -85
- package/src/Cubit.ts +1 -1
- package/src/__tests__/Bloc.event.test.ts +419 -0
- package/src/__tests__/BlocBase.lifecycle.test.ts +441 -0
- package/src/__tests__/Cubit.test.ts +473 -0
- package/src/adapter/BlacAdapter.ts +262 -0
- package/src/adapter/ConsumerTracker.ts +241 -0
- package/src/adapter/ProxyFactory.ts +308 -0
- package/src/adapter/__tests__/BlacAdapter.test.ts +561 -0
- package/src/adapter/__tests__/ConsumerTracker.test.ts +562 -0
- package/src/adapter/__tests__/ProxyFactory.test.ts +655 -0
- package/src/adapter/index.ts +3 -0
- package/src/index.ts +2 -1
- package/src/testing.ts +60 -47
- package/src/types.ts +21 -6
- package/src/utils/uuid.ts +4 -4
- package/src/BlacEvent.ts +0 -5
package/dist/index.es.js
CHANGED
|
@@ -1,360 +1,15 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
getInstance() {
|
|
6
|
-
return u._instance || (u._instance = new l({ __unsafe_ignore_singleton: !0 })), u._instance;
|
|
7
|
-
}
|
|
8
|
-
setInstance(e) {
|
|
9
|
-
u._instance = e;
|
|
10
|
-
}
|
|
11
|
-
resetInstance() {
|
|
12
|
-
const e = u._instance;
|
|
13
|
-
if (u._instance = new l({ __unsafe_ignore_singleton: !0 }), e)
|
|
14
|
-
for (const t of e.keepAliveBlocs)
|
|
15
|
-
u._instance.keepAliveBlocs.add(t), u._instance.uidRegistry.set(t.uid, t);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
i(u, "_instance");
|
|
19
|
-
let v = u, g = new v();
|
|
20
|
-
function M(d) {
|
|
21
|
-
g = d;
|
|
22
|
-
}
|
|
23
|
-
const c = class c {
|
|
24
|
-
/**
|
|
25
|
-
* Creates a new Blac instance.
|
|
26
|
-
* @param options - Configuration options including singleton control
|
|
27
|
-
*/
|
|
28
|
-
constructor(e = {}) {
|
|
29
|
-
/** Timestamp when the instance was created */
|
|
30
|
-
i(this, "createdAt", Date.now());
|
|
31
|
-
/** Map storing all registered bloc instances by their class name and ID */
|
|
32
|
-
i(this, "blocInstanceMap", /* @__PURE__ */ new Map());
|
|
33
|
-
/** Map storing isolated bloc instances grouped by their constructor */
|
|
34
|
-
i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
|
|
35
|
-
/** Map for O(1) lookup of isolated blocs by UID */
|
|
36
|
-
i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
|
|
37
|
-
/** Map tracking UIDs to prevent memory leaks */
|
|
38
|
-
i(this, "uidRegistry", /* @__PURE__ */ new Map());
|
|
39
|
-
/** Set of keep-alive blocs for controlled cleanup */
|
|
40
|
-
i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
|
|
41
|
-
/** Flag to control whether changes should be posted to document */
|
|
42
|
-
i(this, "postChangesToDocument", !1);
|
|
43
|
-
/**
|
|
44
|
-
* Logs messages to console when logging is enabled
|
|
45
|
-
* @param args - Arguments to log
|
|
46
|
-
*/
|
|
47
|
-
i(this, "log", (...e) => {
|
|
48
|
-
c.enableLog && console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...e);
|
|
49
|
-
});
|
|
50
|
-
/**
|
|
51
|
-
* Logs a warning message
|
|
52
|
-
* @param message - Warning message
|
|
53
|
-
* @param args - Additional arguments
|
|
54
|
-
*/
|
|
55
|
-
i(this, "warn", (e, ...t) => {
|
|
56
|
-
c.enableLog && console.warn(`🚨 [Blac ${String(c.instance.createdAt)}]`, e, ...t);
|
|
57
|
-
});
|
|
58
|
-
/**
|
|
59
|
-
* Logs an error message
|
|
60
|
-
* @param message - Error message
|
|
61
|
-
* @param args - Additional arguments
|
|
62
|
-
*/
|
|
63
|
-
i(this, "error", (e, ...t) => {
|
|
64
|
-
c.enableLog && console.error(`🚨 [Blac ${String(c.instance.createdAt)}]`, e, ...t);
|
|
65
|
-
});
|
|
66
|
-
/**
|
|
67
|
-
* Resets the Blac instance to a new one, disposing non-keepAlive blocs
|
|
68
|
-
* from the old instance.
|
|
69
|
-
*/
|
|
70
|
-
i(this, "resetInstance", () => {
|
|
71
|
-
this.log("Reset Blac instance");
|
|
72
|
-
const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
|
|
73
|
-
e.forEach((s) => {
|
|
74
|
-
!s._keepAlive && s._disposalState === "active" && this.disposeBloc(s);
|
|
75
|
-
}), t.forEach((s) => {
|
|
76
|
-
s.forEach((n) => {
|
|
77
|
-
!n._keepAlive && n._disposalState === "active" && this.disposeBloc(n);
|
|
78
|
-
});
|
|
79
|
-
}), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), g.resetInstance();
|
|
80
|
-
});
|
|
81
|
-
/**
|
|
82
|
-
* Disposes of a bloc instance by removing it from the appropriate registry
|
|
83
|
-
* @param bloc - The bloc instance to dispose
|
|
84
|
-
*/
|
|
85
|
-
i(this, "disposeBloc", (e) => {
|
|
86
|
-
if (e._disposalState !== "active") {
|
|
87
|
-
this.log(`[${e._name}:${String(e._id)}] disposeBloc called on already disposed bloc`);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const t = e.constructor, s = this.createBlocInstanceMapKey(e._name, e._id);
|
|
91
|
-
this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(t.isolated)}`), e._dispose(), t.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(s)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
|
|
92
|
-
});
|
|
93
|
-
i(this, "activateBloc", (e) => {
|
|
94
|
-
const t = e.constructor;
|
|
95
|
-
(e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(`[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
|
|
96
|
-
});
|
|
97
|
-
/**
|
|
98
|
-
* Gets or creates a bloc instance based on the provided class and options.
|
|
99
|
-
* If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
|
|
100
|
-
*
|
|
101
|
-
* @param blocClass - The bloc class to get or create
|
|
102
|
-
* @param options - Options including:
|
|
103
|
-
* - id: The instance ID (defaults to class name if not provided)
|
|
104
|
-
* - props: Properties to pass to the bloc constructor
|
|
105
|
-
* - instanceRef: Optional reference string for the instance
|
|
106
|
-
* @returns The bloc instance
|
|
107
|
-
*/
|
|
108
|
-
i(this, "getBloc", (e, t = {}) => {
|
|
109
|
-
const { id: s } = t, n = e, o = s ?? e.name;
|
|
110
|
-
if (n.isolated) {
|
|
111
|
-
const r = this.findIsolatedBlocInstance(e, o);
|
|
112
|
-
if (r)
|
|
113
|
-
return this.log(`[${e.name}:${String(o)}] (getBloc) Found existing isolated instance.`, t), r;
|
|
114
|
-
if (t.throwIfNotFound)
|
|
115
|
-
throw new Error(`Isolated bloc ${e.name} not found`);
|
|
116
|
-
} else {
|
|
117
|
-
const r = this.findRegisteredBlocInstance(e, o);
|
|
118
|
-
if (r)
|
|
119
|
-
return this.log(`[${e.name}:${String(o)}] (getBloc) Found existing registered instance.`, t), r;
|
|
120
|
-
if (t.throwIfNotFound)
|
|
121
|
-
throw new Error(`Registered bloc ${e.name} not found`);
|
|
122
|
-
}
|
|
123
|
-
const a = this.createNewBlocInstance(
|
|
124
|
-
e,
|
|
125
|
-
o,
|
|
126
|
-
t
|
|
127
|
-
);
|
|
128
|
-
if (this.log(`[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`, t, a), !a)
|
|
129
|
-
throw new Error(`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`);
|
|
130
|
-
return a;
|
|
131
|
-
});
|
|
132
|
-
/**
|
|
133
|
-
* Gets a bloc instance or throws an error if it doesn't exist
|
|
134
|
-
* @param blocClass - The bloc class to get
|
|
135
|
-
* @param options - Options including:
|
|
136
|
-
* - id: The instance ID (defaults to class name if not provided)
|
|
137
|
-
* - props: Properties to pass to the bloc constructor
|
|
138
|
-
* - instanceRef: Optional reference string for the instance
|
|
139
|
-
*/
|
|
140
|
-
i(this, "getBlocOrThrow", (e, t = {}) => {
|
|
141
|
-
const s = e.isolated, n = t.id || e.name, o = s ? this.findIsolatedBlocInstance(e, n) : this.findRegisteredBlocInstance(e, n);
|
|
142
|
-
if (o)
|
|
143
|
-
return o;
|
|
144
|
-
throw new Error(`Bloc ${e.name} not found`);
|
|
145
|
-
});
|
|
146
|
-
/**
|
|
147
|
-
* Gets all instances of a specific bloc class
|
|
148
|
-
* @param blocClass - The bloc class to search for
|
|
149
|
-
* @param options - Options including:
|
|
150
|
-
* - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
|
|
151
|
-
* @returns Array of matching bloc instances
|
|
152
|
-
*/
|
|
153
|
-
i(this, "getAllBlocs", (e, t = {}) => {
|
|
154
|
-
const s = [];
|
|
155
|
-
if (this.blocInstanceMap.forEach((n) => {
|
|
156
|
-
n.constructor === e && s.push(n);
|
|
157
|
-
}), t.searchIsolated !== !1) {
|
|
158
|
-
const n = this.isolatedBlocMap.get(e);
|
|
159
|
-
n && s.push(...n.map((o) => o));
|
|
160
|
-
}
|
|
161
|
-
return s;
|
|
162
|
-
});
|
|
163
|
-
/**
|
|
164
|
-
* Disposes all keep-alive blocs of a specific type
|
|
165
|
-
* @param blocClass - The bloc class to dispose
|
|
166
|
-
*/
|
|
167
|
-
i(this, "disposeKeepAliveBlocs", (e) => {
|
|
168
|
-
const t = [];
|
|
169
|
-
for (const s of this.keepAliveBlocs)
|
|
170
|
-
(!e || s.constructor === e) && t.push(s);
|
|
171
|
-
t.forEach((s) => s._dispose());
|
|
172
|
-
});
|
|
173
|
-
/**
|
|
174
|
-
* Disposes all blocs matching a pattern
|
|
175
|
-
* @param predicate - Function to test each bloc for disposal
|
|
176
|
-
*/
|
|
177
|
-
i(this, "disposeBlocs", (e) => {
|
|
178
|
-
const t = [];
|
|
179
|
-
for (const s of this.blocInstanceMap.values())
|
|
180
|
-
e(s) && t.push(s);
|
|
181
|
-
for (const s of this.isolatedBlocMap.values())
|
|
182
|
-
for (const n of s)
|
|
183
|
-
e(n) && t.push(n);
|
|
184
|
-
t.forEach((s) => s._dispose());
|
|
185
|
-
});
|
|
186
|
-
/**
|
|
187
|
-
* Gets memory usage statistics for debugging
|
|
188
|
-
*/
|
|
189
|
-
i(this, "getMemoryStats", () => ({
|
|
190
|
-
totalBlocs: this.uidRegistry.size,
|
|
191
|
-
registeredBlocs: this.blocInstanceMap.size,
|
|
192
|
-
isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce((e, t) => e + t.length, 0),
|
|
193
|
-
keepAliveBlocs: this.keepAliveBlocs.size,
|
|
194
|
-
isolatedBlocTypes: this.isolatedBlocMap.size
|
|
195
|
-
}));
|
|
196
|
-
/**
|
|
197
|
-
* Validates consumer references and cleans up orphaned consumers
|
|
198
|
-
*/
|
|
199
|
-
i(this, "validateConsumers", () => {
|
|
200
|
-
for (const e of this.uidRegistry.values())
|
|
201
|
-
e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === "active" && setTimeout(() => {
|
|
202
|
-
e._consumers.size === 0 && !e._keepAlive && e._disposalState === "active" && this.disposeBloc(e);
|
|
203
|
-
}, 1e3);
|
|
204
|
-
});
|
|
205
|
-
const { __unsafe_ignore_singleton: t = !1 } = e;
|
|
206
|
-
if (!t)
|
|
207
|
-
return c.instance;
|
|
208
|
-
g.setInstance(this);
|
|
209
|
-
}
|
|
210
|
-
/** @deprecated Use getInstance() instead */
|
|
211
|
-
static get instance() {
|
|
212
|
-
return g.getInstance();
|
|
213
|
-
}
|
|
214
|
-
static get getAllBlocs() {
|
|
215
|
-
return c.instance.getAllBlocs;
|
|
216
|
-
}
|
|
217
|
-
static get log() {
|
|
218
|
-
return c.instance.log;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Gets the current Blac instance
|
|
222
|
-
* @returns The Blac instance
|
|
223
|
-
*/
|
|
224
|
-
static getInstance() {
|
|
225
|
-
return g.getInstance();
|
|
226
|
-
}
|
|
227
|
-
static get warn() {
|
|
228
|
-
return c.instance.warn;
|
|
229
|
-
}
|
|
230
|
-
static get error() {
|
|
231
|
-
return c.instance.error;
|
|
232
|
-
}
|
|
233
|
-
static get disposeBloc() {
|
|
234
|
-
return c.instance.disposeBloc;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
|
|
238
|
-
* @param blocClassName - The name of the bloc class
|
|
239
|
-
* @param id - The instance ID
|
|
240
|
-
* @returns A unique key string in the format "className:id"
|
|
241
|
-
*/
|
|
242
|
-
createBlocInstanceMapKey(e, t) {
|
|
243
|
-
return `${e}:${String(t)}`;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Unregister a bloc instance from the main registry
|
|
247
|
-
* @param bloc - The bloc instance to unregister
|
|
248
|
-
*/
|
|
249
|
-
unregisterBlocInstance(e) {
|
|
250
|
-
const t = this.createBlocInstanceMapKey(e._name, e._id);
|
|
251
|
-
this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Registers a bloc instance in the main registry
|
|
255
|
-
* @param bloc - The bloc instance to register
|
|
256
|
-
*/
|
|
257
|
-
registerBlocInstance(e) {
|
|
258
|
-
const t = this.createBlocInstanceMapKey(e._name, e._id);
|
|
259
|
-
this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Finds a registered bloc instance by its class and ID
|
|
263
|
-
* @param blocClass - The bloc class to search for
|
|
264
|
-
* @param id - The instance ID
|
|
265
|
-
* @returns The found bloc instance or undefined if not found
|
|
266
|
-
*/
|
|
267
|
-
findRegisteredBlocInstance(e, t) {
|
|
268
|
-
if (e.isolated) return;
|
|
269
|
-
const n = this.createBlocInstanceMapKey(e.name, t);
|
|
270
|
-
return this.blocInstanceMap.get(n);
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Registers an isolated bloc instance in the isolated registry
|
|
274
|
-
* @param bloc - The isolated bloc instance to register
|
|
275
|
-
*/
|
|
276
|
-
registerIsolatedBlocInstance(e) {
|
|
277
|
-
const t = e.constructor, s = this.isolatedBlocMap.get(t);
|
|
278
|
-
s ? s.push(e) : this.isolatedBlocMap.set(t, [e]), this.isolatedBlocIndex.set(e.uid, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Unregister an isolated bloc instance from the isolated registry
|
|
282
|
-
* @param bloc - The isolated bloc instance to unregister
|
|
283
|
-
*/
|
|
284
|
-
unregisterIsolatedBlocInstance(e) {
|
|
285
|
-
const t = e.constructor, s = this.isolatedBlocMap.get(t);
|
|
286
|
-
let n = !1;
|
|
287
|
-
if (s) {
|
|
288
|
-
const a = s.findIndex((r) => r.uid === e.uid);
|
|
289
|
-
a !== -1 && (s.splice(a, 1), n = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
|
|
290
|
-
}
|
|
291
|
-
const o = this.isolatedBlocIndex.delete(e.uid);
|
|
292
|
-
this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), n !== o && this.warn(
|
|
293
|
-
`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${n}, Index removal: ${o}`
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Finds an isolated bloc instance by its class and ID (O(n) lookup)
|
|
298
|
-
*/
|
|
299
|
-
findIsolatedBlocInstance(e, t) {
|
|
300
|
-
if (!e.isolated) return;
|
|
301
|
-
const n = this.isolatedBlocMap.get(e);
|
|
302
|
-
return n ? n.find((a) => a._id === t) : void 0;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Finds an isolated bloc instance by UID (O(1) lookup)
|
|
306
|
-
*/
|
|
307
|
-
findIsolatedBlocInstanceByUid(e) {
|
|
308
|
-
return this.isolatedBlocIndex.get(e);
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Creates a new bloc instance and registers it in the appropriate registry
|
|
312
|
-
* @param blocClass - The bloc class to instantiate
|
|
313
|
-
* @param id - The instance ID
|
|
314
|
-
* @param props - Properties to pass to the bloc constructor
|
|
315
|
-
* @param instanceRef - Optional reference string for the instance
|
|
316
|
-
* @returns The newly created bloc instance
|
|
317
|
-
*/
|
|
318
|
-
createNewBlocInstance(e, t, s = {}) {
|
|
319
|
-
const { props: n, instanceRef: o } = s, a = new e(n);
|
|
320
|
-
return a._instanceRef = o, a.props = n || null, a._updateId(t), a._setDisposalHandler((r) => this.disposeBloc(r)), a.isIsolated ? (this.registerIsolatedBlocInstance(a), a) : (this.registerBlocInstance(a), a);
|
|
321
|
-
}
|
|
322
|
-
static get activateBloc() {
|
|
323
|
-
return c.instance.activateBloc;
|
|
324
|
-
}
|
|
325
|
-
static get getBloc() {
|
|
326
|
-
return c.instance.getBloc;
|
|
327
|
-
}
|
|
328
|
-
static get getBlocOrThrow() {
|
|
329
|
-
return c.instance.getBlocOrThrow;
|
|
330
|
-
}
|
|
331
|
-
static get disposeKeepAliveBlocs() {
|
|
332
|
-
return c.instance.disposeKeepAliveBlocs;
|
|
333
|
-
}
|
|
334
|
-
static get disposeBlocs() {
|
|
335
|
-
return c.instance.disposeBlocs;
|
|
336
|
-
}
|
|
337
|
-
static get getMemoryStats() {
|
|
338
|
-
return c.instance.getMemoryStats;
|
|
339
|
-
}
|
|
340
|
-
static get validateConsumers() {
|
|
341
|
-
return c.instance.validateConsumers;
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
/** Flag to enable/disable logging */
|
|
345
|
-
i(c, "enableLog", !1), i(c, "resetInstance", () => {
|
|
346
|
-
g.resetInstance();
|
|
347
|
-
});
|
|
348
|
-
let l = c;
|
|
349
|
-
class w {
|
|
1
|
+
var M = Object.defineProperty;
|
|
2
|
+
var P = (u, e, t) => e in u ? M(u, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[e] = t;
|
|
3
|
+
var n = (u, e, t) => P(u, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
class E {
|
|
350
5
|
/**
|
|
351
6
|
* Creates a new BlacObservable instance
|
|
352
7
|
* @param bloc - The Bloc instance to observe
|
|
353
8
|
*/
|
|
354
9
|
constructor(e) {
|
|
355
10
|
/** The Bloc instance this observable is associated with */
|
|
356
|
-
|
|
357
|
-
|
|
11
|
+
n(this, "bloc");
|
|
12
|
+
n(this, "_observers", /* @__PURE__ */ new Set());
|
|
358
13
|
this.bloc = e;
|
|
359
14
|
}
|
|
360
15
|
/**
|
|
@@ -377,16 +32,38 @@ class w {
|
|
|
377
32
|
* @returns A function that can be called to unsubscribe the observer
|
|
378
33
|
*/
|
|
379
34
|
subscribe(e) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
35
|
+
const t = this.bloc._disposalState;
|
|
36
|
+
return t === _.DISPOSED || t === _.DISPOSING ? (f.log(
|
|
37
|
+
"BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",
|
|
38
|
+
this.bloc,
|
|
39
|
+
e
|
|
40
|
+
), () => {
|
|
41
|
+
}) : (f.log(
|
|
42
|
+
"BlacObservable.subscribe: Subscribing observer.",
|
|
43
|
+
this.bloc,
|
|
44
|
+
e
|
|
45
|
+
), this._observers.add(e), t === _.DISPOSAL_REQUESTED && (f.log(
|
|
46
|
+
"BlacObservable.subscribe: Cancelling disposal due to new subscription.",
|
|
47
|
+
this.bloc
|
|
48
|
+
), this.bloc._atomicStateTransition(
|
|
49
|
+
_.DISPOSAL_REQUESTED,
|
|
50
|
+
_.ACTIVE
|
|
51
|
+
)), () => {
|
|
52
|
+
f.log(
|
|
53
|
+
"BlacObservable.subscribe: Unsubscribing observer.",
|
|
54
|
+
this.bloc,
|
|
55
|
+
e
|
|
56
|
+
), this.unsubscribe(e);
|
|
57
|
+
});
|
|
383
58
|
}
|
|
384
59
|
/**
|
|
385
60
|
* Unsubscribes an observer from state changes
|
|
386
61
|
* @param observer - The observer to unsubscribe
|
|
387
62
|
*/
|
|
388
63
|
unsubscribe(e) {
|
|
389
|
-
this._observers.delete(e), this.size === 0 &&
|
|
64
|
+
this._observers.delete(e), this.size === 0 && (f.log("BlacObservable.unsubscribe: No observers left.", this.bloc), this.bloc._consumers.size === 0 && !this.bloc._keepAlive && this.bloc._disposalState === _.ACTIVE && (f.log(
|
|
65
|
+
`[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`
|
|
66
|
+
), this.bloc._scheduleDisposal()));
|
|
390
67
|
}
|
|
391
68
|
/**
|
|
392
69
|
* Notifies all observers of a state change
|
|
@@ -395,32 +72,28 @@ class w {
|
|
|
395
72
|
* @param action - Optional action that triggered the state change
|
|
396
73
|
*/
|
|
397
74
|
notify(e, t, s) {
|
|
398
|
-
this._observers.forEach((
|
|
399
|
-
let
|
|
400
|
-
if (
|
|
401
|
-
const a =
|
|
75
|
+
this._observers.forEach((i) => {
|
|
76
|
+
let r = !1;
|
|
77
|
+
if (i.dependencyArray) {
|
|
78
|
+
const a = i.lastState, o = i.dependencyArray(
|
|
79
|
+
e,
|
|
80
|
+
t,
|
|
81
|
+
this.bloc
|
|
82
|
+
);
|
|
402
83
|
if (!a)
|
|
403
|
-
|
|
404
|
-
else if (a.length !==
|
|
405
|
-
|
|
84
|
+
r = !0;
|
|
85
|
+
else if (a.length !== o.length)
|
|
86
|
+
r = !0;
|
|
406
87
|
else
|
|
407
|
-
for (let
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
o = !0;
|
|
88
|
+
for (let l = 0; l < o.length; l++)
|
|
89
|
+
if (!Object.is(a[l], o[l])) {
|
|
90
|
+
r = !0;
|
|
411
91
|
break;
|
|
412
92
|
}
|
|
413
|
-
|
|
414
|
-
if (!Object.is(_[f], p[f])) {
|
|
415
|
-
o = !0;
|
|
416
|
-
break;
|
|
417
|
-
}
|
|
418
|
-
if (o) break;
|
|
419
|
-
}
|
|
420
|
-
n.lastState = r;
|
|
93
|
+
i.lastState = o;
|
|
421
94
|
} else
|
|
422
|
-
|
|
423
|
-
|
|
95
|
+
r = !0;
|
|
96
|
+
r && i.fn(e, t, s);
|
|
424
97
|
});
|
|
425
98
|
}
|
|
426
99
|
/**
|
|
@@ -430,97 +103,103 @@ class w {
|
|
|
430
103
|
this._observers.clear();
|
|
431
104
|
}
|
|
432
105
|
}
|
|
433
|
-
function
|
|
434
|
-
return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(
|
|
106
|
+
function R() {
|
|
107
|
+
return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(u) {
|
|
435
108
|
const e = Math.random() * 16 | 0;
|
|
436
|
-
return (
|
|
109
|
+
return (u === "x" ? e : e & 3 | 8).toString(16);
|
|
437
110
|
});
|
|
438
111
|
}
|
|
439
|
-
|
|
112
|
+
var _ = /* @__PURE__ */ ((u) => (u.ACTIVE = "active", u.DISPOSAL_REQUESTED = "disposal_requested", u.DISPOSING = "disposing", u.DISPOSED = "disposed", u))(_ || {});
|
|
113
|
+
class k {
|
|
440
114
|
/**
|
|
441
115
|
* Creates a new BlocBase instance with the given initial state.
|
|
442
116
|
* Sets up the observer, registers with the Blac manager, and initializes addons.
|
|
443
|
-
*
|
|
117
|
+
*
|
|
444
118
|
* @param initialState The initial state value for this Bloc
|
|
445
119
|
*/
|
|
446
120
|
constructor(e) {
|
|
447
|
-
|
|
121
|
+
n(this, "uid", R());
|
|
448
122
|
/**
|
|
449
123
|
* Defines how dependencies are selected from the state for efficient updates.
|
|
450
124
|
* When provided, observers will only be notified when selected dependencies change.
|
|
451
125
|
*/
|
|
452
|
-
|
|
126
|
+
n(this, "defaultDependencySelector");
|
|
453
127
|
/**
|
|
454
128
|
* @internal
|
|
455
129
|
* Indicates if this specific Bloc instance is isolated from others of the same type.
|
|
456
130
|
*/
|
|
457
|
-
|
|
131
|
+
n(this, "_isolated", !1);
|
|
458
132
|
/**
|
|
459
133
|
* @internal
|
|
460
134
|
* Observable responsible for managing state listeners and notifying consumers.
|
|
461
135
|
*/
|
|
462
|
-
|
|
136
|
+
n(this, "_observer");
|
|
463
137
|
/**
|
|
464
138
|
* The unique identifier for this Bloc instance.
|
|
465
139
|
* Defaults to the class name, but can be customized.
|
|
466
140
|
*/
|
|
467
|
-
|
|
141
|
+
n(this, "_id");
|
|
468
142
|
/**
|
|
469
143
|
* @internal
|
|
470
144
|
* Reference string used internally for tracking and debugging.
|
|
471
145
|
*/
|
|
472
|
-
|
|
146
|
+
n(this, "_instanceRef");
|
|
473
147
|
/**
|
|
474
148
|
* @internal
|
|
475
149
|
* Indicates if this specific Bloc instance should be kept alive when no consumers are present.
|
|
476
150
|
*/
|
|
477
|
-
|
|
151
|
+
n(this, "_keepAlive", !1);
|
|
478
152
|
/**
|
|
479
153
|
* @readonly
|
|
480
154
|
* Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
|
|
481
155
|
*/
|
|
482
|
-
|
|
156
|
+
n(this, "_createdAt", Date.now());
|
|
483
157
|
/**
|
|
484
158
|
* @internal
|
|
485
|
-
*
|
|
159
|
+
* Atomic disposal state to prevent race conditions
|
|
486
160
|
*/
|
|
487
|
-
|
|
161
|
+
n(this, "_disposalState", "active");
|
|
162
|
+
/**
|
|
163
|
+
* @internal
|
|
164
|
+
* Timestamp when disposal was requested (for React Strict Mode grace period)
|
|
165
|
+
*/
|
|
166
|
+
n(this, "_disposalRequestTime", 0);
|
|
488
167
|
/**
|
|
489
168
|
* @internal
|
|
490
169
|
* The current state of the Bloc.
|
|
491
170
|
*/
|
|
492
|
-
|
|
171
|
+
n(this, "_state");
|
|
493
172
|
/**
|
|
494
173
|
* @internal
|
|
495
174
|
* The previous state of the Bloc, maintained for comparison and history.
|
|
496
175
|
*/
|
|
497
|
-
|
|
176
|
+
n(this, "_oldState");
|
|
498
177
|
/**
|
|
499
178
|
* Props passed during Bloc instance creation.
|
|
500
179
|
* Can be used to configure or parameterize the Bloc's behavior.
|
|
501
180
|
*/
|
|
502
|
-
|
|
181
|
+
n(this, "props", null);
|
|
503
182
|
/**
|
|
504
183
|
* @internal
|
|
505
184
|
* Flag to prevent batching race conditions
|
|
506
185
|
*/
|
|
507
|
-
|
|
186
|
+
n(this, "_batchingLock", !1);
|
|
508
187
|
/**
|
|
509
188
|
* @internal
|
|
510
189
|
* Pending batched updates
|
|
511
190
|
*/
|
|
512
|
-
|
|
191
|
+
n(this, "_pendingUpdates", []);
|
|
513
192
|
/**
|
|
514
193
|
* @internal
|
|
515
194
|
* Map of consumer IDs to their WeakRef objects for proper cleanup
|
|
516
195
|
*/
|
|
517
|
-
|
|
196
|
+
n(this, "_consumerRefs", /* @__PURE__ */ new Map());
|
|
518
197
|
/**
|
|
519
198
|
* @internal
|
|
520
199
|
* Validates that all consumer references are still alive
|
|
521
200
|
* Removes dead consumers automatically
|
|
522
201
|
*/
|
|
523
|
-
|
|
202
|
+
n(this, "_validateConsumers", () => {
|
|
524
203
|
const e = [];
|
|
525
204
|
for (const [t, s] of this._consumerRefs)
|
|
526
205
|
s.deref() === void 0 && e.push(t);
|
|
@@ -532,10 +211,10 @@ class B {
|
|
|
532
211
|
* @internal
|
|
533
212
|
* Updates the Bloc instance's ID to a new value.
|
|
534
213
|
* Only updates if the new ID is defined and different from the current one.
|
|
535
|
-
*
|
|
214
|
+
*
|
|
536
215
|
* @param id The new ID to assign to this Bloc instance
|
|
537
216
|
*/
|
|
538
|
-
|
|
217
|
+
n(this, "_updateId", (e) => {
|
|
539
218
|
const t = this._id;
|
|
540
219
|
!e || e === t || (this._id = e);
|
|
541
220
|
});
|
|
@@ -543,168 +222,631 @@ class B {
|
|
|
543
222
|
* @internal
|
|
544
223
|
* Optional function to be called when the Bloc is disposed.
|
|
545
224
|
*/
|
|
546
|
-
|
|
225
|
+
n(this, "onDispose");
|
|
547
226
|
/**
|
|
548
227
|
* @internal
|
|
549
228
|
* Set of consumer IDs currently listening to this Bloc's state changes.
|
|
550
229
|
*/
|
|
551
|
-
|
|
230
|
+
n(this, "_consumers", /* @__PURE__ */ new Set());
|
|
552
231
|
/**
|
|
553
232
|
* @internal
|
|
554
233
|
* Registers a new consumer to this Bloc instance.
|
|
555
234
|
* Notifies the Blac manager that a consumer has been added.
|
|
556
|
-
*
|
|
235
|
+
*
|
|
557
236
|
* @param consumerId The unique ID of the consumer being added
|
|
558
237
|
* @param consumerRef Optional reference to the consumer object for cleanup validation
|
|
559
238
|
*/
|
|
560
|
-
|
|
561
|
-
|
|
239
|
+
n(this, "_addConsumer", (e, t) => {
|
|
240
|
+
var s;
|
|
241
|
+
return this._disposalState !== "active" ? !1 : (this._consumers.has(e) || (this._consumers.add(e), t && this._consumerRefs.set(e, new WeakRef(t)), (s = globalThis.Blac) == null || s.log(
|
|
242
|
+
`[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`
|
|
243
|
+
)), !0);
|
|
562
244
|
});
|
|
563
245
|
/**
|
|
564
246
|
* @internal
|
|
565
247
|
* Unregisters a consumer from this Bloc instance.
|
|
566
248
|
* Notifies the Blac manager that a consumer has been removed.
|
|
567
|
-
*
|
|
249
|
+
*
|
|
568
250
|
* @param consumerId The unique ID of the consumer being removed
|
|
569
251
|
*/
|
|
570
|
-
|
|
571
|
-
|
|
252
|
+
n(this, "_removeConsumer", (e) => {
|
|
253
|
+
var t, s;
|
|
254
|
+
this._consumers.has(e) && (this._consumers.delete(e), this._consumerRefs.delete(e), (t = globalThis.Blac) == null || t.log(
|
|
255
|
+
`[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`
|
|
256
|
+
), this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && ((s = globalThis.Blac) == null || s.log(
|
|
257
|
+
`[${this._name}:${this._id}] No consumers left and not keep-alive. Scheduling disposal.`
|
|
258
|
+
), this._scheduleDisposal()));
|
|
572
259
|
});
|
|
573
260
|
/**
|
|
574
261
|
* @internal
|
|
575
262
|
* Handler function for disposal (can be set by Blac manager)
|
|
576
263
|
*/
|
|
577
|
-
|
|
578
|
-
|
|
264
|
+
n(this, "_disposalHandler");
|
|
265
|
+
n(this, "lastUpdate", Date.now());
|
|
579
266
|
/**
|
|
580
267
|
* @internal
|
|
581
268
|
* Flag to indicate if batching is enabled for this bloc
|
|
582
269
|
*/
|
|
583
|
-
|
|
270
|
+
n(this, "_batchingEnabled", !1);
|
|
271
|
+
/**
|
|
272
|
+
* @internal
|
|
273
|
+
* Updates the state and notifies all observers of the change.
|
|
274
|
+
*
|
|
275
|
+
* @param newState The new state to be set
|
|
276
|
+
* @param oldState The previous state for comparison
|
|
277
|
+
* @param action Optional metadata about what caused the state change
|
|
278
|
+
*/
|
|
279
|
+
n(this, "_pushState", (e, t, s) => {
|
|
280
|
+
if (e !== void 0 && !(s !== void 0 && typeof s != "object" && typeof s != "function")) {
|
|
281
|
+
if (this._batchingEnabled) {
|
|
282
|
+
this._pendingUpdates.push({ newState: e, oldState: t, action: s }), this._oldState = t, this._state = e;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
/**
|
|
289
|
+
* Enables batching for multiple state updates
|
|
290
|
+
* @param batchFn Function to execute with batching enabled
|
|
291
|
+
*/
|
|
292
|
+
n(this, "batch", (e) => {
|
|
293
|
+
if (this._batchingLock)
|
|
294
|
+
return e();
|
|
295
|
+
this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
|
|
296
|
+
try {
|
|
297
|
+
const t = e();
|
|
298
|
+
if (this._pendingUpdates.length > 0) {
|
|
299
|
+
const s = this._pendingUpdates[this._pendingUpdates.length - 1];
|
|
300
|
+
this._observer.notify(
|
|
301
|
+
s.newState,
|
|
302
|
+
s.oldState,
|
|
303
|
+
s.action
|
|
304
|
+
), this.lastUpdate = Date.now();
|
|
305
|
+
}
|
|
306
|
+
return t;
|
|
307
|
+
} finally {
|
|
308
|
+
this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
this._state = e, this._observer = new E(this), this._id = this.constructor.name;
|
|
312
|
+
const t = this.constructor;
|
|
313
|
+
this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1;
|
|
314
|
+
}
|
|
315
|
+
get isIsolated() {
|
|
316
|
+
return this._isolated;
|
|
317
|
+
}
|
|
318
|
+
get isKeepAlive() {
|
|
319
|
+
return this._keepAlive;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Returns the current state of the Bloc.
|
|
323
|
+
* Use this getter to access the state in a read-only manner.
|
|
324
|
+
* Returns the state even during transitional lifecycle states for React compatibility.
|
|
325
|
+
*/
|
|
326
|
+
get state() {
|
|
327
|
+
return this._disposalState === "disposed" ? this._state : this._state;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Returns whether this Bloc instance has been disposed.
|
|
331
|
+
* @returns true if the bloc is in DISPOSED state
|
|
332
|
+
*/
|
|
333
|
+
get isDisposed() {
|
|
334
|
+
return this._disposalState === "disposed";
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* @internal
|
|
338
|
+
* Returns the name of the Bloc class for identification and debugging.
|
|
339
|
+
*/
|
|
340
|
+
get _name() {
|
|
341
|
+
return this.constructor.name;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* @internal
|
|
345
|
+
* Performs atomic state transition using compare-and-swap semantics
|
|
346
|
+
* @param expectedState The expected current state
|
|
347
|
+
* @param newState The desired new state
|
|
348
|
+
* @returns Result indicating success/failure and state information
|
|
349
|
+
*/
|
|
350
|
+
_atomicStateTransition(e, t) {
|
|
351
|
+
var s, i, r, a;
|
|
352
|
+
if (this._disposalState === e) {
|
|
353
|
+
const o = this._disposalState;
|
|
354
|
+
return this._disposalState = t, (s = globalThis.Blac) != null && s.enableLog && ((i = globalThis.Blac) == null || i.log(
|
|
355
|
+
`[${this._name}:${this._id}] State transition: ${o} -> ${t} (SUCCESS)`
|
|
356
|
+
)), {
|
|
357
|
+
success: !0,
|
|
358
|
+
currentState: t,
|
|
359
|
+
previousState: o
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
return (r = globalThis.Blac) != null && r.enableLog && ((a = globalThis.Blac) == null || a.log(
|
|
363
|
+
`[${this._name}:${this._id}] State transition failed: expected ${e}, current ${this._disposalState}`
|
|
364
|
+
)), {
|
|
365
|
+
success: !1,
|
|
366
|
+
currentState: this._disposalState,
|
|
367
|
+
previousState: e
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* @internal
|
|
372
|
+
* Cleans up resources and removes this Bloc from the system.
|
|
373
|
+
* Notifies the Blac manager and clears all observers.
|
|
374
|
+
*/
|
|
375
|
+
_dispose() {
|
|
376
|
+
var t;
|
|
377
|
+
let e = this._atomicStateTransition(
|
|
378
|
+
"active",
|
|
379
|
+
"disposing"
|
|
380
|
+
/* DISPOSING */
|
|
381
|
+
);
|
|
382
|
+
if (e.success || (e = this._atomicStateTransition(
|
|
383
|
+
"disposal_requested",
|
|
384
|
+
"disposing"
|
|
385
|
+
/* DISPOSING */
|
|
386
|
+
)), !e.success)
|
|
387
|
+
return !1;
|
|
388
|
+
try {
|
|
389
|
+
return this._consumers.clear(), this._consumerRefs.clear(), this._observer.clear(), (t = this.onDispose) == null || t.call(this), this._atomicStateTransition(
|
|
390
|
+
"disposing",
|
|
391
|
+
"disposed"
|
|
392
|
+
/* DISPOSED */
|
|
393
|
+
).success;
|
|
394
|
+
} catch (s) {
|
|
395
|
+
throw this._disposalState = "active", s;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* @internal
|
|
400
|
+
* Sets the disposal handler for this bloc
|
|
401
|
+
*/
|
|
402
|
+
_setDisposalHandler(e) {
|
|
403
|
+
this._disposalHandler = e;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* @internal
|
|
407
|
+
* Schedules disposal of this bloc instance if it has no consumers
|
|
408
|
+
* Uses atomic state transitions to prevent race conditions
|
|
409
|
+
*/
|
|
410
|
+
_scheduleDisposal() {
|
|
411
|
+
if (!this._atomicStateTransition(
|
|
412
|
+
"active",
|
|
413
|
+
"disposal_requested"
|
|
414
|
+
/* DISPOSAL_REQUESTED */
|
|
415
|
+
).success)
|
|
416
|
+
return;
|
|
417
|
+
if (!(this._consumers.size === 0 && !this._keepAlive)) {
|
|
418
|
+
this._atomicStateTransition(
|
|
419
|
+
"disposal_requested",
|
|
420
|
+
"active"
|
|
421
|
+
/* ACTIVE */
|
|
422
|
+
);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this._disposalRequestTime = Date.now(), queueMicrotask(() => {
|
|
426
|
+
this._consumers.size === 0 && !this._keepAlive && this._observer.size === 0 && this._disposalState === "disposal_requested" ? this._disposalHandler ? this._disposalHandler(this) : this._dispose() : this._atomicStateTransition(
|
|
427
|
+
"disposal_requested",
|
|
428
|
+
"active"
|
|
429
|
+
/* ACTIVE */
|
|
430
|
+
);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* When true, every consumer will receive its own unique instance of this Bloc.
|
|
436
|
+
* Use this when state should not be shared between components.
|
|
437
|
+
* @default false
|
|
438
|
+
*/
|
|
439
|
+
n(k, "isolated", !1), /**
|
|
440
|
+
* When true, the Bloc instance persists even when there are no active consumers.
|
|
441
|
+
* Useful for maintaining state between component unmount/remount cycles.
|
|
442
|
+
* @default false
|
|
443
|
+
*/
|
|
444
|
+
n(k, "keepAlive", !1);
|
|
445
|
+
const I = class I {
|
|
446
|
+
getInstance() {
|
|
447
|
+
return I._instance || (I._instance = new f({
|
|
448
|
+
__unsafe_ignore_singleton: !0
|
|
449
|
+
})), I._instance;
|
|
450
|
+
}
|
|
451
|
+
setInstance(e) {
|
|
452
|
+
I._instance = e;
|
|
453
|
+
}
|
|
454
|
+
resetInstance() {
|
|
455
|
+
const e = I._instance;
|
|
456
|
+
if (I._instance = new f({
|
|
457
|
+
__unsafe_ignore_singleton: !0
|
|
458
|
+
}), e)
|
|
459
|
+
for (const t of e.keepAliveBlocs)
|
|
460
|
+
I._instance.keepAliveBlocs.add(t), I._instance.uidRegistry.set(t.uid, t);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
n(I, "_instance");
|
|
464
|
+
let T = I, b = new T();
|
|
465
|
+
function L(u) {
|
|
466
|
+
b = u;
|
|
467
|
+
}
|
|
468
|
+
const c = class c {
|
|
469
|
+
/**
|
|
470
|
+
* Creates a new Blac instance.
|
|
471
|
+
* @param options - Configuration options including singleton control
|
|
472
|
+
*/
|
|
473
|
+
constructor(e = {}) {
|
|
474
|
+
/** Timestamp when the instance was created */
|
|
475
|
+
n(this, "createdAt", Date.now());
|
|
476
|
+
/** Map storing all registered bloc instances by their class name and ID */
|
|
477
|
+
n(this, "blocInstanceMap", /* @__PURE__ */ new Map());
|
|
478
|
+
/** Map storing isolated bloc instances grouped by their constructor */
|
|
479
|
+
// Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
|
|
480
|
+
// different bloc types in the same map. The 'any' allows proper polymorphic storage
|
|
481
|
+
// while maintaining type safety at usage sites through the BlocConstructor constraint.
|
|
482
|
+
n(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
|
|
483
|
+
/** Map for O(1) lookup of isolated blocs by UID */
|
|
484
|
+
n(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
|
|
485
|
+
/** Map tracking UIDs to prevent memory leaks */
|
|
486
|
+
n(this, "uidRegistry", /* @__PURE__ */ new Map());
|
|
487
|
+
/** Set of keep-alive blocs for controlled cleanup */
|
|
488
|
+
n(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
|
|
489
|
+
/** Flag to control whether changes should be posted to document */
|
|
490
|
+
n(this, "postChangesToDocument", !1);
|
|
491
|
+
/**
|
|
492
|
+
* Logs messages to console when logging is enabled
|
|
493
|
+
* @param args - Arguments to log
|
|
494
|
+
*/
|
|
495
|
+
n(this, "log", (...e) => {
|
|
496
|
+
c.logSpy && c.logSpy(e), c.enableLog && c.logLevel, c.enableLog && c.logLevel;
|
|
497
|
+
});
|
|
498
|
+
/**
|
|
499
|
+
* Logs a warning message
|
|
500
|
+
* @param message - Warning message
|
|
501
|
+
* @param args - Additional arguments
|
|
502
|
+
*/
|
|
503
|
+
n(this, "warn", (e, ...t) => {
|
|
504
|
+
c.enableLog;
|
|
505
|
+
});
|
|
506
|
+
/**
|
|
507
|
+
* Logs an error message
|
|
508
|
+
* @param message - Error message
|
|
509
|
+
* @param args - Additional arguments
|
|
510
|
+
*/
|
|
511
|
+
n(this, "error", (e, ...t) => {
|
|
512
|
+
c.enableLog;
|
|
513
|
+
});
|
|
514
|
+
/**
|
|
515
|
+
* Resets the Blac instance to a new one, disposing non-keepAlive blocs
|
|
516
|
+
* from the old instance.
|
|
517
|
+
*/
|
|
518
|
+
n(this, "resetInstance", () => {
|
|
519
|
+
this.log("Reset Blac instance");
|
|
520
|
+
const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
|
|
521
|
+
e.forEach((s) => {
|
|
522
|
+
!s._keepAlive && s._disposalState === _.ACTIVE && this.disposeBloc(s);
|
|
523
|
+
}), t.forEach((s) => {
|
|
524
|
+
s.forEach((i) => {
|
|
525
|
+
!i._keepAlive && i._disposalState === _.ACTIVE && this.disposeBloc(i);
|
|
526
|
+
});
|
|
527
|
+
}), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), b.resetInstance();
|
|
528
|
+
});
|
|
529
|
+
/**
|
|
530
|
+
* Disposes of a bloc instance by removing it from the appropriate registry
|
|
531
|
+
* @param bloc - The bloc instance to dispose
|
|
532
|
+
*/
|
|
533
|
+
n(this, "disposeBloc", (e) => {
|
|
534
|
+
const t = e._disposalState;
|
|
535
|
+
if (![
|
|
536
|
+
_.ACTIVE,
|
|
537
|
+
_.DISPOSAL_REQUESTED
|
|
538
|
+
].includes(t)) {
|
|
539
|
+
this.log(
|
|
540
|
+
`[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`
|
|
541
|
+
);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
const i = e.constructor, r = this.createBlocInstanceMapKey(e._name, e._id);
|
|
545
|
+
this.log(
|
|
546
|
+
`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(i.isolated)}`
|
|
547
|
+
), e._dispose(), i.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(r)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
|
|
548
|
+
});
|
|
549
|
+
n(this, "activateBloc", (e) => {
|
|
550
|
+
if (e._disposalState !== _.ACTIVE) {
|
|
551
|
+
this.log(
|
|
552
|
+
`[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
|
|
553
|
+
);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const t = e.constructor;
|
|
557
|
+
(e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(
|
|
558
|
+
`[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`
|
|
559
|
+
), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
|
|
560
|
+
});
|
|
561
|
+
/**
|
|
562
|
+
* Gets or creates a bloc instance based on the provided class and options.
|
|
563
|
+
* If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
|
|
564
|
+
*
|
|
565
|
+
* @param blocClass - The bloc class to get or create
|
|
566
|
+
* @param options - Options including:
|
|
567
|
+
* - id: The instance ID (defaults to class name if not provided)
|
|
568
|
+
* - props: Properties to pass to the bloc constructor
|
|
569
|
+
* - instanceRef: Optional reference string for the instance
|
|
570
|
+
* @returns The bloc instance
|
|
571
|
+
*/
|
|
572
|
+
n(this, "getBloc", (e, t = {}) => {
|
|
573
|
+
const { id: s, forceNewInstance: i } = t, r = e, a = s ?? e.name;
|
|
574
|
+
if (this.log(`[${e.name}:${String(a)}] (getBloc) Called:`, {
|
|
575
|
+
options: t,
|
|
576
|
+
base: r
|
|
577
|
+
}), !i)
|
|
578
|
+
if (r.isolated) {
|
|
579
|
+
const l = this.findIsolatedBlocInstance(
|
|
580
|
+
e,
|
|
581
|
+
t.instanceRef ?? a
|
|
582
|
+
);
|
|
583
|
+
if (l)
|
|
584
|
+
return l;
|
|
585
|
+
if (t.throwIfNotFound)
|
|
586
|
+
throw new Error(`Isolated bloc ${e.name} not found`);
|
|
587
|
+
} else {
|
|
588
|
+
const l = this.findRegisteredBlocInstance(
|
|
589
|
+
e,
|
|
590
|
+
a
|
|
591
|
+
);
|
|
592
|
+
if (l)
|
|
593
|
+
return l;
|
|
594
|
+
if (t.throwIfNotFound)
|
|
595
|
+
throw new Error(`Registered bloc ${e.name} not found`);
|
|
596
|
+
}
|
|
597
|
+
const o = this.createNewBlocInstance(e, a, t);
|
|
598
|
+
if (this.log(
|
|
599
|
+
`[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`,
|
|
600
|
+
t,
|
|
601
|
+
o
|
|
602
|
+
), !o)
|
|
603
|
+
throw new Error(
|
|
604
|
+
`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
|
|
605
|
+
);
|
|
606
|
+
return o;
|
|
607
|
+
});
|
|
608
|
+
/**
|
|
609
|
+
* Gets a bloc instance or throws an error if it doesn't exist
|
|
610
|
+
* @param blocClass - The bloc class to get
|
|
611
|
+
* @param options - Options including:
|
|
612
|
+
* - id: The instance ID (defaults to class name if not provided)
|
|
613
|
+
* - props: Properties to pass to the bloc constructor
|
|
614
|
+
* - instanceRef: Optional reference string for the instance
|
|
615
|
+
*/
|
|
616
|
+
n(this, "getBlocOrThrow", (e, t = {}) => {
|
|
617
|
+
const s = e.isolated, i = t.id || e.name, r = s ? this.findIsolatedBlocInstance(e, i) : this.findRegisteredBlocInstance(e, i);
|
|
618
|
+
if (r)
|
|
619
|
+
return r;
|
|
620
|
+
throw new Error(`Bloc ${e.name} not found`);
|
|
621
|
+
});
|
|
622
|
+
/**
|
|
623
|
+
* Gets all instances of a specific bloc class
|
|
624
|
+
* @param blocClass - The bloc class to search for
|
|
625
|
+
* @param options - Options including:
|
|
626
|
+
* - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
|
|
627
|
+
* @returns Array of matching bloc instances
|
|
628
|
+
*/
|
|
629
|
+
n(this, "getAllBlocs", (e, t = {}) => {
|
|
630
|
+
const s = [];
|
|
631
|
+
if (this.blocInstanceMap.forEach((i) => {
|
|
632
|
+
i.constructor === e && s.push(i);
|
|
633
|
+
}), t.searchIsolated !== !1) {
|
|
634
|
+
const i = this.isolatedBlocMap.get(e);
|
|
635
|
+
i && s.push(...i.map((r) => r));
|
|
636
|
+
}
|
|
637
|
+
return s;
|
|
638
|
+
});
|
|
639
|
+
/**
|
|
640
|
+
* Disposes all keep-alive blocs of a specific type
|
|
641
|
+
* @param blocClass - The bloc class to dispose
|
|
642
|
+
*/
|
|
643
|
+
n(this, "disposeKeepAliveBlocs", (e) => {
|
|
644
|
+
const t = [];
|
|
645
|
+
for (const s of this.keepAliveBlocs)
|
|
646
|
+
(!e || s.constructor === e) && t.push(s);
|
|
647
|
+
t.forEach((s) => s._dispose());
|
|
648
|
+
});
|
|
584
649
|
/**
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
* @param newState The new state to be set
|
|
589
|
-
* @param oldState The previous state for comparison
|
|
590
|
-
* @param action Optional metadata about what caused the state change
|
|
650
|
+
* Disposes all blocs matching a pattern
|
|
651
|
+
* @param predicate - Function to test each bloc for disposal
|
|
591
652
|
*/
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
if (this._batchingEnabled) {
|
|
602
|
-
this._pendingUpdates.push({ newState: e, oldState: t, action: s }), this._oldState = t, this._state = e;
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
|
-
this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
|
|
653
|
+
n(this, "disposeBlocs", (e) => {
|
|
654
|
+
const t = [];
|
|
655
|
+
for (const s of this.blocInstanceMap.values())
|
|
656
|
+
e(s) && t.push(s);
|
|
657
|
+
for (const s of this.isolatedBlocMap.values())
|
|
658
|
+
for (const i of s)
|
|
659
|
+
e(i) && t.push(i);
|
|
660
|
+
t.forEach((s) => s._dispose());
|
|
606
661
|
});
|
|
607
662
|
/**
|
|
608
|
-
*
|
|
609
|
-
* @param batchFn Function to execute with batching enabled
|
|
663
|
+
* Gets memory usage statistics for debugging
|
|
610
664
|
*/
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
665
|
+
n(this, "getMemoryStats", () => ({
|
|
666
|
+
totalBlocs: this.uidRegistry.size,
|
|
667
|
+
registeredBlocs: this.blocInstanceMap.size,
|
|
668
|
+
isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
|
|
669
|
+
(e, t) => e + t.length,
|
|
670
|
+
0
|
|
671
|
+
),
|
|
672
|
+
keepAliveBlocs: this.keepAliveBlocs.size,
|
|
673
|
+
isolatedBlocTypes: this.isolatedBlocMap.size
|
|
674
|
+
}));
|
|
675
|
+
/**
|
|
676
|
+
* Validates consumer references and cleans up orphaned consumers
|
|
677
|
+
*/
|
|
678
|
+
n(this, "validateConsumers", () => {
|
|
679
|
+
for (const e of this.uidRegistry.values())
|
|
680
|
+
e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === _.ACTIVE && setTimeout(() => {
|
|
681
|
+
e._consumers.size === 0 && !e._keepAlive && e._disposalState === _.ACTIVE && this.disposeBloc(e);
|
|
682
|
+
}, 1e3);
|
|
625
683
|
});
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
684
|
+
const { __unsafe_ignore_singleton: t = !1 } = e;
|
|
685
|
+
if (!t)
|
|
686
|
+
return c.instance;
|
|
687
|
+
b.setInstance(this);
|
|
629
688
|
}
|
|
630
|
-
get
|
|
631
|
-
return
|
|
689
|
+
static get instance() {
|
|
690
|
+
return b.getInstance();
|
|
632
691
|
}
|
|
633
|
-
get
|
|
634
|
-
return
|
|
692
|
+
static get getAllBlocs() {
|
|
693
|
+
return c.instance.getAllBlocs;
|
|
694
|
+
}
|
|
695
|
+
static get log() {
|
|
696
|
+
return c.instance.log;
|
|
635
697
|
}
|
|
636
698
|
/**
|
|
637
|
-
*
|
|
638
|
-
*
|
|
699
|
+
* Gets the current Blac instance
|
|
700
|
+
* @returns The Blac instance
|
|
639
701
|
*/
|
|
640
|
-
|
|
641
|
-
return
|
|
702
|
+
static getInstance() {
|
|
703
|
+
return b.getInstance();
|
|
704
|
+
}
|
|
705
|
+
static get warn() {
|
|
706
|
+
return c.instance.warn;
|
|
707
|
+
}
|
|
708
|
+
static get error() {
|
|
709
|
+
return c.instance.error;
|
|
710
|
+
}
|
|
711
|
+
static get disposeBloc() {
|
|
712
|
+
return c.instance.disposeBloc;
|
|
642
713
|
}
|
|
643
714
|
/**
|
|
644
|
-
*
|
|
645
|
-
*
|
|
715
|
+
* Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
|
|
716
|
+
* @param blocClassName - The name of the bloc class
|
|
717
|
+
* @param id - The instance ID
|
|
718
|
+
* @returns A unique key string in the format "className:id"
|
|
646
719
|
*/
|
|
647
|
-
|
|
648
|
-
return
|
|
720
|
+
createBlocInstanceMapKey(e, t) {
|
|
721
|
+
return `${e}:${String(t)}`;
|
|
649
722
|
}
|
|
650
723
|
/**
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
* Notifies the Blac manager and clears all observers.
|
|
724
|
+
* Unregister a bloc instance from the main registry
|
|
725
|
+
* @param bloc - The bloc instance to unregister
|
|
654
726
|
*/
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
this.
|
|
727
|
+
unregisterBlocInstance(e) {
|
|
728
|
+
const t = this.createBlocInstanceMapKey(e._name, e._id);
|
|
729
|
+
this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
|
|
658
730
|
}
|
|
659
731
|
/**
|
|
660
|
-
*
|
|
661
|
-
*
|
|
732
|
+
* Registers a bloc instance in the main registry
|
|
733
|
+
* @param bloc - The bloc instance to register
|
|
662
734
|
*/
|
|
663
|
-
|
|
664
|
-
|
|
735
|
+
registerBlocInstance(e) {
|
|
736
|
+
const t = this.createBlocInstanceMapKey(e._name, e._id);
|
|
737
|
+
this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
|
|
665
738
|
}
|
|
666
739
|
/**
|
|
667
|
-
*
|
|
668
|
-
*
|
|
740
|
+
* Finds a registered bloc instance by its class and ID
|
|
741
|
+
* @param blocClass - The bloc class to search for
|
|
742
|
+
* @param id - The instance ID
|
|
743
|
+
* @returns The found bloc instance or undefined if not found
|
|
669
744
|
*/
|
|
670
|
-
|
|
671
|
-
|
|
745
|
+
findRegisteredBlocInstance(e, t) {
|
|
746
|
+
if (e.isolated) return;
|
|
747
|
+
const i = this.createBlocInstanceMapKey(e.name, t);
|
|
748
|
+
return this.blocInstanceMap.get(i);
|
|
672
749
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
750
|
+
/**
|
|
751
|
+
* Registers an isolated bloc instance in the isolated registry
|
|
752
|
+
* @param bloc - The isolated bloc instance to register
|
|
753
|
+
*/
|
|
754
|
+
registerIsolatedBlocInstance(e) {
|
|
755
|
+
const t = e.constructor, s = this.isolatedBlocMap.get(t);
|
|
756
|
+
s ? s.push(e) : this.isolatedBlocMap.set(t, [e]), this.isolatedBlocIndex.set(e.uid, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Unregister an isolated bloc instance from the isolated registry
|
|
760
|
+
* @param bloc - The isolated bloc instance to unregister
|
|
761
|
+
*/
|
|
762
|
+
unregisterIsolatedBlocInstance(e) {
|
|
763
|
+
const t = e.constructor, s = this.isolatedBlocMap.get(t);
|
|
764
|
+
let i = !1;
|
|
765
|
+
if (s) {
|
|
766
|
+
const a = s.findIndex((o) => o.uid === e.uid);
|
|
767
|
+
a !== -1 && (s.splice(a, 1), i = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
|
|
768
|
+
}
|
|
769
|
+
const r = this.isolatedBlocIndex.delete(e.uid);
|
|
770
|
+
this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), i !== r && this.warn(
|
|
771
|
+
`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${i}, Index removal: ${r}`
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Finds an isolated bloc instance by its class and ID (O(n) lookup)
|
|
776
|
+
*/
|
|
777
|
+
findIsolatedBlocInstance(e, t) {
|
|
778
|
+
if (!e.isolated) return;
|
|
779
|
+
const i = this.isolatedBlocMap.get(e);
|
|
780
|
+
return i ? i.find((a) => a._id === t) : void 0;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Finds an isolated bloc instance by UID (O(1) lookup)
|
|
784
|
+
*/
|
|
785
|
+
findIsolatedBlocInstanceByUid(e) {
|
|
786
|
+
return this.isolatedBlocIndex.get(e);
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Creates a new bloc instance and registers it in the appropriate registry
|
|
790
|
+
* @param blocClass - The bloc class to instantiate
|
|
791
|
+
* @param id - The instance ID
|
|
792
|
+
* @param props - Properties to pass to the bloc constructor
|
|
793
|
+
* @param instanceRef - Optional reference string for the instance
|
|
794
|
+
* @returns The newly created bloc instance
|
|
795
|
+
*/
|
|
796
|
+
createNewBlocInstance(e, t, s = {}) {
|
|
797
|
+
const { props: i, instanceRef: r } = s, a = new e(i);
|
|
798
|
+
return a._instanceRef = r, a.props = i || null, a._updateId(t), a._setDisposalHandler((o) => this.disposeBloc(o)), a.isIsolated ? (this.registerIsolatedBlocInstance(a), a) : (this.registerBlocInstance(a), a);
|
|
799
|
+
}
|
|
800
|
+
static get activateBloc() {
|
|
801
|
+
return c.instance.activateBloc;
|
|
802
|
+
}
|
|
803
|
+
static get getBloc() {
|
|
804
|
+
return c.instance.getBloc;
|
|
805
|
+
}
|
|
806
|
+
static get getBlocOrThrow() {
|
|
807
|
+
return c.instance.getBlocOrThrow;
|
|
808
|
+
}
|
|
809
|
+
static get disposeKeepAliveBlocs() {
|
|
810
|
+
return c.instance.disposeKeepAliveBlocs;
|
|
811
|
+
}
|
|
812
|
+
static get disposeBlocs() {
|
|
813
|
+
return c.instance.disposeBlocs;
|
|
814
|
+
}
|
|
815
|
+
static get getMemoryStats() {
|
|
816
|
+
return c.instance.getMemoryStats;
|
|
817
|
+
}
|
|
818
|
+
static get validateConsumers() {
|
|
819
|
+
return c.instance.validateConsumers;
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
/** Flag to enable/disable logging */
|
|
823
|
+
n(c, "enableLog", !1), n(c, "logLevel", "warn"), n(c, "logSpy", null), n(c, "resetInstance", () => {
|
|
824
|
+
b.resetInstance();
|
|
825
|
+
});
|
|
826
|
+
let f = c;
|
|
827
|
+
class O extends k {
|
|
686
828
|
constructor() {
|
|
687
829
|
super(...arguments);
|
|
688
830
|
// Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>
|
|
689
831
|
// The handler's event parameter will be correctly typed to the specific EventConstructor
|
|
690
832
|
// by the 'on' method's signature.
|
|
691
|
-
|
|
833
|
+
n(this, "eventHandlers", /* @__PURE__ */ new Map());
|
|
692
834
|
/**
|
|
693
835
|
* @internal
|
|
694
836
|
* Event queue to ensure sequential processing of async events
|
|
695
837
|
*/
|
|
696
|
-
|
|
838
|
+
n(this, "_eventQueue", []);
|
|
697
839
|
/**
|
|
698
840
|
* @internal
|
|
699
841
|
* Flag indicating if an event is currently being processed
|
|
700
842
|
*/
|
|
701
|
-
|
|
843
|
+
n(this, "_isProcessingEvent", !1);
|
|
702
844
|
/**
|
|
703
845
|
* Dispatches an action/event to the Bloc.
|
|
704
846
|
* Events are queued and processed sequentially to prevent race conditions.
|
|
705
847
|
* @param action The action/event instance to be processed.
|
|
706
848
|
*/
|
|
707
|
-
|
|
849
|
+
n(this, "add", async (t) => {
|
|
708
850
|
this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
|
|
709
851
|
});
|
|
710
852
|
}
|
|
@@ -716,7 +858,7 @@ class b extends B {
|
|
|
716
858
|
* The 'event' parameter in the handler will be typed to the specific eventConstructor.
|
|
717
859
|
*/
|
|
718
860
|
on(t, s) {
|
|
719
|
-
this.eventHandlers.has(t) &&
|
|
861
|
+
this.eventHandlers.has(t) && f.warn(
|
|
720
862
|
`[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
|
|
721
863
|
), this.eventHandlers.set(
|
|
722
864
|
t,
|
|
@@ -745,35 +887,35 @@ class b extends B {
|
|
|
745
887
|
* Processes a single event
|
|
746
888
|
*/
|
|
747
889
|
async _processEvent(t) {
|
|
748
|
-
const s = t.constructor,
|
|
749
|
-
if (
|
|
750
|
-
const
|
|
751
|
-
const
|
|
752
|
-
this._pushState(a,
|
|
890
|
+
const s = t.constructor, i = this.eventHandlers.get(s);
|
|
891
|
+
if (i) {
|
|
892
|
+
const r = (a) => {
|
|
893
|
+
const o = this.state;
|
|
894
|
+
this._pushState(a, o, t);
|
|
753
895
|
};
|
|
754
896
|
try {
|
|
755
|
-
await
|
|
897
|
+
await i(t, r);
|
|
756
898
|
} catch (a) {
|
|
757
|
-
const
|
|
899
|
+
const o = t.constructor.name || "UnnamedConstructor", l = {
|
|
758
900
|
blocName: this._name,
|
|
759
901
|
blocId: String(this._id),
|
|
760
|
-
eventType:
|
|
902
|
+
eventType: o,
|
|
761
903
|
currentState: this.state,
|
|
762
904
|
action: t,
|
|
763
905
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
764
906
|
};
|
|
765
|
-
if (
|
|
766
|
-
`[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${
|
|
907
|
+
if (f.error(
|
|
908
|
+
`[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${o}':`,
|
|
767
909
|
a,
|
|
768
910
|
"Context:",
|
|
769
|
-
|
|
911
|
+
l
|
|
770
912
|
), a instanceof Error && a.name === "CriticalError")
|
|
771
913
|
throw a;
|
|
772
914
|
}
|
|
773
915
|
} else {
|
|
774
|
-
const
|
|
775
|
-
|
|
776
|
-
`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${
|
|
916
|
+
const r = t.constructor.name || "UnnamedConstructor";
|
|
917
|
+
f.warn(
|
|
918
|
+
`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${r}'.`,
|
|
777
919
|
"Registered handlers:",
|
|
778
920
|
Array.from(this.eventHandlers.keys()).map((a) => a.name),
|
|
779
921
|
"Action was:",
|
|
@@ -782,7 +924,7 @@ class b extends B {
|
|
|
782
924
|
}
|
|
783
925
|
}
|
|
784
926
|
}
|
|
785
|
-
class
|
|
927
|
+
class V extends k {
|
|
786
928
|
/**
|
|
787
929
|
* Updates the current state and notifies all observers of the change.
|
|
788
930
|
* If the new state is identical to the current state (using Object.is),
|
|
@@ -798,14 +940,14 @@ class k extends B {
|
|
|
798
940
|
/**
|
|
799
941
|
* Partially updates the current state by merging it with the provided state patch.
|
|
800
942
|
* This method is only applicable when the state is an object type.
|
|
801
|
-
*
|
|
943
|
+
*
|
|
802
944
|
* @param statePatch - A partial state object containing only the properties to update
|
|
803
945
|
* @param ignoreChangeCheck - If true, skips checking if the state has actually changed
|
|
804
946
|
* @throws {TypeError} If the state is not an object type
|
|
805
947
|
*/
|
|
806
948
|
patch(e, t = !1) {
|
|
807
949
|
if (typeof this.state != "object" || this.state === null) {
|
|
808
|
-
|
|
950
|
+
f.warn(
|
|
809
951
|
"Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
|
|
810
952
|
);
|
|
811
953
|
return;
|
|
@@ -814,10 +956,10 @@ class k extends B {
|
|
|
814
956
|
if (t)
|
|
815
957
|
s = !0;
|
|
816
958
|
else
|
|
817
|
-
for (const
|
|
818
|
-
if (Object.prototype.hasOwnProperty.call(e,
|
|
819
|
-
const a = this.state[
|
|
820
|
-
if (!Object.is(e[
|
|
959
|
+
for (const i in e)
|
|
960
|
+
if (Object.prototype.hasOwnProperty.call(e, i)) {
|
|
961
|
+
const a = this.state[i];
|
|
962
|
+
if (!Object.is(e[i], a)) {
|
|
821
963
|
s = !0;
|
|
822
964
|
break;
|
|
823
965
|
}
|
|
@@ -828,78 +970,86 @@ class k extends B {
|
|
|
828
970
|
});
|
|
829
971
|
}
|
|
830
972
|
}
|
|
831
|
-
class
|
|
973
|
+
class U {
|
|
832
974
|
/**
|
|
833
975
|
* Sets up a clean test environment
|
|
834
976
|
*/
|
|
835
977
|
static setUp() {
|
|
836
|
-
this.originalInstance =
|
|
978
|
+
this.originalInstance = f.instance, f.resetInstance(), f.enableLog = !1;
|
|
837
979
|
}
|
|
838
980
|
/**
|
|
839
981
|
* Tears down the test environment and restores original state
|
|
840
982
|
*/
|
|
841
983
|
static tearDown() {
|
|
842
|
-
|
|
984
|
+
f.resetInstance();
|
|
843
985
|
}
|
|
844
986
|
/**
|
|
845
987
|
* Creates a test bloc with automatic cleanup
|
|
846
988
|
*/
|
|
847
989
|
static createBloc(e, ...t) {
|
|
848
990
|
const s = new e(...t);
|
|
849
|
-
return
|
|
991
|
+
return f.activateBloc(s), s;
|
|
850
992
|
}
|
|
851
993
|
/**
|
|
852
994
|
* Waits for a bloc to emit a specific state
|
|
853
995
|
*/
|
|
854
996
|
static async waitForState(e, t, s = 5e3) {
|
|
855
|
-
return new Promise((
|
|
997
|
+
return new Promise((i, r) => {
|
|
856
998
|
const a = setTimeout(() => {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
999
|
+
r(
|
|
1000
|
+
new Error(
|
|
1001
|
+
`Timeout waiting for state matching predicate after ${s}ms`
|
|
1002
|
+
)
|
|
1003
|
+
);
|
|
1004
|
+
}, s), o = e._observer.subscribe({
|
|
1005
|
+
id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
1006
|
+
fn: (l) => {
|
|
1007
|
+
t(l) && (clearTimeout(a), o(), i(l));
|
|
862
1008
|
}
|
|
863
1009
|
});
|
|
864
|
-
t(e.state) && (clearTimeout(a),
|
|
1010
|
+
t(e.state) && (clearTimeout(a), o(), i(e.state));
|
|
865
1011
|
});
|
|
866
1012
|
}
|
|
867
1013
|
/**
|
|
868
1014
|
* Expects a bloc to emit specific states in order
|
|
869
1015
|
*/
|
|
870
1016
|
static async expectStates(e, t, s = 5e3) {
|
|
871
|
-
const
|
|
872
|
-
return new Promise((
|
|
873
|
-
const
|
|
874
|
-
a(
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1017
|
+
const i = [];
|
|
1018
|
+
return new Promise((r, a) => {
|
|
1019
|
+
const o = setTimeout(() => {
|
|
1020
|
+
a(
|
|
1021
|
+
new Error(
|
|
1022
|
+
`Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`
|
|
1023
|
+
)
|
|
1024
|
+
);
|
|
1025
|
+
}, s), l = e._observer.subscribe({
|
|
878
1026
|
id: `test-expecter-${crypto.randomUUID()}`,
|
|
879
|
-
fn: (
|
|
880
|
-
if (
|
|
881
|
-
clearTimeout(
|
|
882
|
-
for (let
|
|
883
|
-
const
|
|
884
|
-
if (JSON.stringify(
|
|
885
|
-
a(
|
|
886
|
-
|
|
887
|
-
|
|
1027
|
+
fn: (p) => {
|
|
1028
|
+
if (i.push(p), i.length === t.length) {
|
|
1029
|
+
clearTimeout(o), l();
|
|
1030
|
+
for (let d = 0; d < t.length; d++) {
|
|
1031
|
+
const m = t[d], v = i[d];
|
|
1032
|
+
if (JSON.stringify(m) !== JSON.stringify(v)) {
|
|
1033
|
+
a(
|
|
1034
|
+
new Error(
|
|
1035
|
+
`State mismatch at index ${d}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`
|
|
1036
|
+
)
|
|
1037
|
+
);
|
|
888
1038
|
return;
|
|
889
1039
|
}
|
|
890
1040
|
}
|
|
891
|
-
|
|
1041
|
+
r();
|
|
892
1042
|
}
|
|
893
1043
|
}
|
|
894
1044
|
});
|
|
895
1045
|
});
|
|
896
1046
|
}
|
|
897
1047
|
}
|
|
898
|
-
|
|
899
|
-
class
|
|
1048
|
+
n(U, "originalInstance");
|
|
1049
|
+
class z extends O {
|
|
900
1050
|
constructor(t) {
|
|
901
1051
|
super(t);
|
|
902
|
-
|
|
1052
|
+
n(this, "mockHandlers", /* @__PURE__ */ new Map());
|
|
903
1053
|
}
|
|
904
1054
|
/**
|
|
905
1055
|
* Mock an event handler for testing
|
|
@@ -920,10 +1070,10 @@ class A extends b {
|
|
|
920
1070
|
return this.eventHandlers.has(t);
|
|
921
1071
|
}
|
|
922
1072
|
}
|
|
923
|
-
class
|
|
1073
|
+
class j extends V {
|
|
924
1074
|
constructor(t) {
|
|
925
1075
|
super(t);
|
|
926
|
-
|
|
1076
|
+
n(this, "stateHistory", []);
|
|
927
1077
|
this.stateHistory.push(t);
|
|
928
1078
|
}
|
|
929
1079
|
/**
|
|
@@ -945,16 +1095,16 @@ class E extends k {
|
|
|
945
1095
|
this.stateHistory = [this.state];
|
|
946
1096
|
}
|
|
947
1097
|
}
|
|
948
|
-
class
|
|
1098
|
+
class K {
|
|
949
1099
|
constructor() {
|
|
950
|
-
|
|
951
|
-
this.initialStats =
|
|
1100
|
+
n(this, "initialStats");
|
|
1101
|
+
this.initialStats = f.getMemoryStats();
|
|
952
1102
|
}
|
|
953
1103
|
/**
|
|
954
1104
|
* Check for memory leaks and return a report
|
|
955
1105
|
*/
|
|
956
1106
|
checkForLeaks() {
|
|
957
|
-
const e =
|
|
1107
|
+
const e = f.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
|
|
958
1108
|
Memory Leak Detection Report:
|
|
959
1109
|
- Initial registered blocs: ${this.initialStats.registeredBlocs}
|
|
960
1110
|
- Current registered blocs: ${e.registeredBlocs}
|
|
@@ -971,17 +1121,400 @@ Memory Leak Detection Report:
|
|
|
971
1121
|
};
|
|
972
1122
|
}
|
|
973
1123
|
}
|
|
1124
|
+
class H {
|
|
1125
|
+
constructor() {
|
|
1126
|
+
n(this, "consumers", /* @__PURE__ */ new WeakMap());
|
|
1127
|
+
n(this, "registrationCount", 0);
|
|
1128
|
+
n(this, "activeConsumers", 0);
|
|
1129
|
+
}
|
|
1130
|
+
register(e, t) {
|
|
1131
|
+
this.registrationCount++, this.consumers.get(e) || this.activeConsumers++, this.consumers.set(e, {
|
|
1132
|
+
id: t,
|
|
1133
|
+
lastNotified: Date.now(),
|
|
1134
|
+
hasRendered: !1,
|
|
1135
|
+
stateAccesses: /* @__PURE__ */ new Set(),
|
|
1136
|
+
classAccesses: /* @__PURE__ */ new Set(),
|
|
1137
|
+
stateValues: /* @__PURE__ */ new Map(),
|
|
1138
|
+
classValues: /* @__PURE__ */ new Map(),
|
|
1139
|
+
accessCount: 0,
|
|
1140
|
+
lastAccessTime: 0,
|
|
1141
|
+
firstAccessTime: 0
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
unregister(e) {
|
|
1145
|
+
e && this.consumers.get(e) && (this.consumers.delete(e), this.activeConsumers = Math.max(0, this.activeConsumers - 1));
|
|
1146
|
+
}
|
|
1147
|
+
trackAccess(e, t, s, i) {
|
|
1148
|
+
const r = this.consumers.get(e);
|
|
1149
|
+
if (!r) return;
|
|
1150
|
+
const a = Date.now();
|
|
1151
|
+
r.firstAccessTime || (r.firstAccessTime = a), r.accessCount++, r.lastAccessTime = a, t === "state" ? (r.stateAccesses.add(s), i !== void 0 && r.stateValues.set(s, { value: i, lastAccessTime: a })) : (r.classAccesses.add(s), i !== void 0 && r.classValues.set(s, { value: i, lastAccessTime: a }));
|
|
1152
|
+
}
|
|
1153
|
+
resetTracking(e) {
|
|
1154
|
+
const t = this.consumers.get(e);
|
|
1155
|
+
t && (t.stateAccesses.clear(), t.classAccesses.clear(), t.stateValues.clear(), t.classValues.clear(), t.accessCount = 0, t.firstAccessTime = 0);
|
|
1156
|
+
}
|
|
1157
|
+
getDependencies(e) {
|
|
1158
|
+
const t = this.consumers.get(e);
|
|
1159
|
+
return t ? {
|
|
1160
|
+
statePaths: Array.from(t.stateAccesses),
|
|
1161
|
+
classPaths: Array.from(t.classAccesses)
|
|
1162
|
+
} : null;
|
|
1163
|
+
}
|
|
1164
|
+
hasValuesChanged(e, t, s) {
|
|
1165
|
+
const i = this.consumers.get(e);
|
|
1166
|
+
if (!i) return !0;
|
|
1167
|
+
let r = !1;
|
|
1168
|
+
const a = Date.now();
|
|
1169
|
+
if (i.stateValues.size === 0 && i.classValues.size === 0 && (i.stateAccesses.size > 0 || i.classAccesses.size > 0))
|
|
1170
|
+
return !0;
|
|
1171
|
+
for (const [o, l] of i.stateValues)
|
|
1172
|
+
try {
|
|
1173
|
+
const p = this.getValueAtPath(t, o);
|
|
1174
|
+
p !== l.value && (i.stateValues.set(o, {
|
|
1175
|
+
value: p,
|
|
1176
|
+
lastAccessTime: a
|
|
1177
|
+
}), r = !0);
|
|
1178
|
+
} catch {
|
|
1179
|
+
r = !0;
|
|
1180
|
+
}
|
|
1181
|
+
for (const [o, l] of i.classValues)
|
|
1182
|
+
try {
|
|
1183
|
+
const p = this.getValueAtPath(s, o);
|
|
1184
|
+
p !== l.value && (i.classValues.set(o, {
|
|
1185
|
+
value: p,
|
|
1186
|
+
lastAccessTime: a
|
|
1187
|
+
}), r = !0);
|
|
1188
|
+
} catch {
|
|
1189
|
+
r = !0;
|
|
1190
|
+
}
|
|
1191
|
+
return r;
|
|
1192
|
+
}
|
|
1193
|
+
shouldNotifyConsumer(e, t) {
|
|
1194
|
+
const s = this.consumers.get(e);
|
|
1195
|
+
if (!s) return !1;
|
|
1196
|
+
for (const i of t) {
|
|
1197
|
+
if (s.stateAccesses.has(i) || s.classAccesses.has(i)) return !0;
|
|
1198
|
+
for (const r of s.stateAccesses)
|
|
1199
|
+
if (i.startsWith(r + ".") || r.startsWith(i + "."))
|
|
1200
|
+
return !0;
|
|
1201
|
+
}
|
|
1202
|
+
return !1;
|
|
1203
|
+
}
|
|
1204
|
+
updateLastNotified(e) {
|
|
1205
|
+
const t = this.consumers.get(e);
|
|
1206
|
+
t && (t.lastNotified = Date.now());
|
|
1207
|
+
}
|
|
1208
|
+
getConsumerInfo(e) {
|
|
1209
|
+
return this.consumers.get(e);
|
|
1210
|
+
}
|
|
1211
|
+
setHasRendered(e, t) {
|
|
1212
|
+
const s = this.consumers.get(e);
|
|
1213
|
+
s && (s.hasRendered = t);
|
|
1214
|
+
}
|
|
1215
|
+
hasConsumer(e) {
|
|
1216
|
+
return this.consumers.has(e);
|
|
1217
|
+
}
|
|
1218
|
+
getStats() {
|
|
1219
|
+
return {
|
|
1220
|
+
totalRegistrations: this.registrationCount,
|
|
1221
|
+
activeConsumers: this.activeConsumers
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
getValueAtPath(e, t) {
|
|
1225
|
+
const s = t.split(".");
|
|
1226
|
+
let i = e;
|
|
1227
|
+
for (const r of s) {
|
|
1228
|
+
if (i == null) return;
|
|
1229
|
+
i = i[r];
|
|
1230
|
+
}
|
|
1231
|
+
return i;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
const w = /* @__PURE__ */ new WeakMap();
|
|
1235
|
+
let h = {
|
|
1236
|
+
stateProxiesCreated: 0,
|
|
1237
|
+
classProxiesCreated: 0,
|
|
1238
|
+
cacheHits: 0,
|
|
1239
|
+
cacheMisses: 0,
|
|
1240
|
+
propertyAccesses: 0,
|
|
1241
|
+
nestedProxiesCreated: 0,
|
|
1242
|
+
totalProxiesCreated: 0,
|
|
1243
|
+
createdAt: Date.now()
|
|
1244
|
+
};
|
|
1245
|
+
class y {
|
|
1246
|
+
static createStateProxy(e) {
|
|
1247
|
+
const { target: t, consumerRef: s, consumerTracker: i, path: r = "" } = e;
|
|
1248
|
+
if (!s || !i || typeof t != "object" || t === null)
|
|
1249
|
+
return t;
|
|
1250
|
+
let a = w.get(t);
|
|
1251
|
+
a || (a = /* @__PURE__ */ new WeakMap(), w.set(t, a));
|
|
1252
|
+
const o = a.get(s);
|
|
1253
|
+
if (o)
|
|
1254
|
+
return h.cacheHits++, o;
|
|
1255
|
+
h.cacheMisses++;
|
|
1256
|
+
const l = {
|
|
1257
|
+
get(d, m) {
|
|
1258
|
+
if (typeof m == "symbol" || m === "constructor")
|
|
1259
|
+
return Reflect.get(d, m);
|
|
1260
|
+
const v = r ? `${r}.${m}` : m;
|
|
1261
|
+
h.propertyAccesses++;
|
|
1262
|
+
const g = Reflect.get(d, m), S = g && typeof g === "object" && g !== null ? void 0 : g;
|
|
1263
|
+
if (i.trackAccess(s, "state", v, S), g && typeof g == "object" && g !== null) {
|
|
1264
|
+
const B = Object.getPrototypeOf(g) === Object.prototype, D = Array.isArray(g);
|
|
1265
|
+
if (B || D)
|
|
1266
|
+
return h.nestedProxiesCreated++, y.createStateProxy({
|
|
1267
|
+
target: g,
|
|
1268
|
+
consumerRef: s,
|
|
1269
|
+
consumerTracker: i,
|
|
1270
|
+
path: v
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
return g;
|
|
1274
|
+
},
|
|
1275
|
+
has(d, m) {
|
|
1276
|
+
return m in d;
|
|
1277
|
+
},
|
|
1278
|
+
ownKeys(d) {
|
|
1279
|
+
return Reflect.ownKeys(d);
|
|
1280
|
+
},
|
|
1281
|
+
getOwnPropertyDescriptor(d, m) {
|
|
1282
|
+
return Reflect.getOwnPropertyDescriptor(d, m);
|
|
1283
|
+
},
|
|
1284
|
+
set() {
|
|
1285
|
+
return !1;
|
|
1286
|
+
},
|
|
1287
|
+
deleteProperty() {
|
|
1288
|
+
return !1;
|
|
1289
|
+
}
|
|
1290
|
+
}, p = new Proxy(t, l);
|
|
1291
|
+
return a.set(s, p), h.stateProxiesCreated++, h.totalProxiesCreated++, p;
|
|
1292
|
+
}
|
|
1293
|
+
static createClassProxy(e) {
|
|
1294
|
+
const { target: t, consumerRef: s, consumerTracker: i } = e;
|
|
1295
|
+
if (!s || !i)
|
|
1296
|
+
return t;
|
|
1297
|
+
let r = w.get(t);
|
|
1298
|
+
r || (r = /* @__PURE__ */ new WeakMap(), w.set(t, r));
|
|
1299
|
+
const a = r.get(s);
|
|
1300
|
+
if (a)
|
|
1301
|
+
return h.cacheHits++, a;
|
|
1302
|
+
h.cacheMisses++;
|
|
1303
|
+
const o = {
|
|
1304
|
+
get(p, d) {
|
|
1305
|
+
const m = Reflect.get(p, d);
|
|
1306
|
+
let v = !1, g = p;
|
|
1307
|
+
const A = /* @__PURE__ */ new WeakSet(), C = 10;
|
|
1308
|
+
let S = 0;
|
|
1309
|
+
for (; g && !v && S < C && !A.has(g); ) {
|
|
1310
|
+
A.add(g);
|
|
1311
|
+
try {
|
|
1312
|
+
const x = Object.getOwnPropertyDescriptor(
|
|
1313
|
+
g,
|
|
1314
|
+
d
|
|
1315
|
+
);
|
|
1316
|
+
if (x && x.get) {
|
|
1317
|
+
v = !0;
|
|
1318
|
+
break;
|
|
1319
|
+
}
|
|
1320
|
+
g = Object.getPrototypeOf(g), S++;
|
|
1321
|
+
} catch {
|
|
1322
|
+
break;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
if (!v)
|
|
1326
|
+
return m;
|
|
1327
|
+
h.propertyAccesses++;
|
|
1328
|
+
const B = m, $ = B !== null && typeof B != "object" ? B : void 0;
|
|
1329
|
+
return i.trackAccess(
|
|
1330
|
+
s,
|
|
1331
|
+
"class",
|
|
1332
|
+
String(d),
|
|
1333
|
+
$
|
|
1334
|
+
), m;
|
|
1335
|
+
},
|
|
1336
|
+
has(p, d) {
|
|
1337
|
+
return d in p;
|
|
1338
|
+
},
|
|
1339
|
+
ownKeys(p) {
|
|
1340
|
+
return Reflect.ownKeys(p);
|
|
1341
|
+
},
|
|
1342
|
+
getOwnPropertyDescriptor(p, d) {
|
|
1343
|
+
return Reflect.getOwnPropertyDescriptor(p, d);
|
|
1344
|
+
}
|
|
1345
|
+
}, l = new Proxy(t, o);
|
|
1346
|
+
return r.set(s, l), h.classProxiesCreated++, h.totalProxiesCreated++, l;
|
|
1347
|
+
}
|
|
1348
|
+
static getProxyState(e) {
|
|
1349
|
+
return y.createStateProxy({
|
|
1350
|
+
target: e.state,
|
|
1351
|
+
consumerRef: e.consumerRef,
|
|
1352
|
+
consumerTracker: e.consumerTracker
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
static getProxyBlocInstance(e) {
|
|
1356
|
+
return y.createClassProxy({
|
|
1357
|
+
target: e.blocInstance,
|
|
1358
|
+
consumerRef: e.consumerRef,
|
|
1359
|
+
consumerTracker: e.consumerTracker
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
static getStats() {
|
|
1363
|
+
const e = Date.now() - h.createdAt;
|
|
1364
|
+
return {
|
|
1365
|
+
...h,
|
|
1366
|
+
totalProxies: h.stateProxiesCreated + h.classProxiesCreated,
|
|
1367
|
+
cacheEfficiency: h.cacheHits + h.cacheMisses > 0 ? `${(h.cacheHits / (h.cacheHits + h.cacheMisses) * 100).toFixed(1)}%` : "N/A",
|
|
1368
|
+
lifetime: `${e}ms`,
|
|
1369
|
+
proxiesPerSecond: e > 0 ? (h.totalProxiesCreated / (e / 1e3)).toFixed(2) : "N/A"
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
static resetStats() {
|
|
1373
|
+
h = {
|
|
1374
|
+
stateProxiesCreated: 0,
|
|
1375
|
+
classProxiesCreated: 0,
|
|
1376
|
+
cacheHits: 0,
|
|
1377
|
+
cacheMisses: 0,
|
|
1378
|
+
propertyAccesses: 0,
|
|
1379
|
+
nestedProxiesCreated: 0,
|
|
1380
|
+
totalProxiesCreated: 0,
|
|
1381
|
+
createdAt: Date.now()
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
class q {
|
|
1386
|
+
constructor(e, t) {
|
|
1387
|
+
n(this, "id", `consumer-${R()}`);
|
|
1388
|
+
n(this, "blocConstructor");
|
|
1389
|
+
n(this, "componentRef", { current: {} });
|
|
1390
|
+
n(this, "blocInstance");
|
|
1391
|
+
// Core components
|
|
1392
|
+
n(this, "consumerTracker");
|
|
1393
|
+
n(this, "unmountTime", 0);
|
|
1394
|
+
n(this, "mountTime", 0);
|
|
1395
|
+
// Dependency tracking
|
|
1396
|
+
n(this, "dependencyValues");
|
|
1397
|
+
n(this, "isUsingDependencies", !1);
|
|
1398
|
+
// Lifecycle state
|
|
1399
|
+
n(this, "hasMounted", !1);
|
|
1400
|
+
n(this, "mountCount", 0);
|
|
1401
|
+
n(this, "options");
|
|
1402
|
+
n(this, "createStateProxy", (e) => y.createStateProxy({
|
|
1403
|
+
target: e.target,
|
|
1404
|
+
consumerRef: this.componentRef.current,
|
|
1405
|
+
consumerTracker: this
|
|
1406
|
+
}));
|
|
1407
|
+
n(this, "createClassProxy", (e) => y.createClassProxy({
|
|
1408
|
+
target: e.target,
|
|
1409
|
+
consumerRef: this.componentRef.current,
|
|
1410
|
+
consumerTracker: this
|
|
1411
|
+
}));
|
|
1412
|
+
n(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
|
|
1413
|
+
id: this.id,
|
|
1414
|
+
fn: (s, i) => {
|
|
1415
|
+
var r;
|
|
1416
|
+
if (this.isUsingDependencies && ((r = this.options) != null && r.dependencies)) {
|
|
1417
|
+
const a = this.options.dependencies(this.blocInstance);
|
|
1418
|
+
if (!this.hasDependencyValuesChanged(
|
|
1419
|
+
this.dependencyValues,
|
|
1420
|
+
a
|
|
1421
|
+
))
|
|
1422
|
+
return;
|
|
1423
|
+
this.dependencyValues = a;
|
|
1424
|
+
} else {
|
|
1425
|
+
const a = this.consumerTracker.getConsumerInfo(
|
|
1426
|
+
this.componentRef.current
|
|
1427
|
+
);
|
|
1428
|
+
if (a && a.hasRendered && !this.consumerTracker.hasValuesChanged(
|
|
1429
|
+
this.componentRef.current,
|
|
1430
|
+
s,
|
|
1431
|
+
this.blocInstance
|
|
1432
|
+
))
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
e.onChange();
|
|
1436
|
+
}
|
|
1437
|
+
}));
|
|
1438
|
+
n(this, "mount", () => {
|
|
1439
|
+
var e, t;
|
|
1440
|
+
if (this.isUsingDependencies && ((e = this.options) != null && e.dependencies) && (this.dependencyValues = this.options.dependencies(this.blocInstance)), this.mountCount++, this.blocInstance._addConsumer(this.id, this.componentRef.current), !this.hasMounted && (this.hasMounted = !0, this.mountTime = Date.now(), (t = this.options) != null && t.onMount))
|
|
1441
|
+
try {
|
|
1442
|
+
this.options.onMount(this.blocInstance);
|
|
1443
|
+
} catch (s) {
|
|
1444
|
+
throw s;
|
|
1445
|
+
}
|
|
1446
|
+
});
|
|
1447
|
+
n(this, "unmount", () => {
|
|
1448
|
+
var e;
|
|
1449
|
+
if (this.unmountTime = Date.now(), this.consumerTracker.unregister(this.componentRef.current), this.blocInstance._removeConsumer(this.id), (e = this.options) != null && e.onUnmount)
|
|
1450
|
+
try {
|
|
1451
|
+
this.options.onUnmount(this.blocInstance);
|
|
1452
|
+
} catch {
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
n(this, "getProxyState", (e) => this.isUsingDependencies ? e : y.getProxyState({
|
|
1456
|
+
state: e,
|
|
1457
|
+
consumerRef: this.componentRef.current,
|
|
1458
|
+
consumerTracker: this
|
|
1459
|
+
}));
|
|
1460
|
+
n(this, "getProxyBlocInstance", () => this.isUsingDependencies ? this.blocInstance : y.getProxyBlocInstance({
|
|
1461
|
+
blocInstance: this.blocInstance,
|
|
1462
|
+
consumerRef: this.componentRef.current,
|
|
1463
|
+
consumerTracker: this
|
|
1464
|
+
}));
|
|
1465
|
+
this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!(t != null && t.dependencies), this.consumerTracker = new H(), this.blocInstance = this.updateBlocInstance(), this.consumerTracker.register(e.componentRef.current, this.id), this.isUsingDependencies && (t != null && t.dependencies) && (this.dependencyValues = t.dependencies(this.blocInstance));
|
|
1466
|
+
}
|
|
1467
|
+
trackAccess(e, t, s, i) {
|
|
1468
|
+
this.consumerTracker.trackAccess(e, t, s, i);
|
|
1469
|
+
}
|
|
1470
|
+
getConsumerDependencies(e) {
|
|
1471
|
+
return this.consumerTracker.getDependencies(e);
|
|
1472
|
+
}
|
|
1473
|
+
shouldNotifyConsumer(e, t) {
|
|
1474
|
+
const s = this.consumerTracker.getConsumerInfo(e);
|
|
1475
|
+
return !s || !s.hasRendered ? !0 : this.consumerTracker.shouldNotifyConsumer(e, t);
|
|
1476
|
+
}
|
|
1477
|
+
updateLastNotified(e) {
|
|
1478
|
+
this.consumerTracker.updateLastNotified(e), this.consumerTracker.setHasRendered(e, !0);
|
|
1479
|
+
}
|
|
1480
|
+
resetConsumerTracking() {
|
|
1481
|
+
this.consumerTracker.resetTracking(this.componentRef.current);
|
|
1482
|
+
}
|
|
1483
|
+
updateBlocInstance() {
|
|
1484
|
+
var e, t;
|
|
1485
|
+
return this.blocInstance = f.instance.getBloc(this.blocConstructor, {
|
|
1486
|
+
props: (e = this.options) == null ? void 0 : e.props,
|
|
1487
|
+
id: (t = this.options) == null ? void 0 : t.id,
|
|
1488
|
+
instanceRef: this.id
|
|
1489
|
+
}), this.blocInstance;
|
|
1490
|
+
}
|
|
1491
|
+
// Expose calledOnMount for backward compatibility
|
|
1492
|
+
get calledOnMount() {
|
|
1493
|
+
return this.hasMounted;
|
|
1494
|
+
}
|
|
1495
|
+
hasDependencyValuesChanged(e, t) {
|
|
1496
|
+
if (!e || e.length !== t.length) return !0;
|
|
1497
|
+
for (let s = 0; s < e.length; s++)
|
|
1498
|
+
if (!Object.is(e[s], t[s]))
|
|
1499
|
+
return !0;
|
|
1500
|
+
return !1;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
974
1503
|
export {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1504
|
+
f as Blac,
|
|
1505
|
+
q as BlacAdapter,
|
|
1506
|
+
E as BlacObservable,
|
|
1507
|
+
O as Bloc,
|
|
1508
|
+
k as BlocBase,
|
|
1509
|
+
_ as BlocLifecycleState,
|
|
1510
|
+
U as BlocTest,
|
|
1511
|
+
H as ConsumerTracker,
|
|
1512
|
+
V as Cubit,
|
|
1513
|
+
K as MemoryLeakDetector,
|
|
1514
|
+
z as MockBloc,
|
|
1515
|
+
j as MockCubit,
|
|
1516
|
+
y as ProxyFactory,
|
|
1517
|
+
R as generateUUID,
|
|
1518
|
+
L as setBlacInstanceManager
|
|
986
1519
|
};
|
|
987
1520
|
//# sourceMappingURL=index.es.js.map
|