@blac/core 2.0.0-rc-11 → 2.0.0-rc-14
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 +739 -260
- package/dist/index.es.js +1924 -1237
- package/dist/index.es.js.map +1 -1
- package/package.json +6 -7
- package/src/Blac.ts +82 -69
- package/src/Bloc.ts +45 -3
- package/src/BlocBase.ts +263 -454
- package/src/Cubit.ts +1 -16
- package/src/__tests__/Blac.config.test.ts +10 -17
- package/src/__tests__/Bloc.event.test.ts +27 -52
- package/src/__tests__/BlocBase.subscription.test.ts +349 -0
- package/src/__tests__/Cubit.test.ts +39 -50
- package/src/__tests__/memory-leaks.test.ts +383 -0
- package/src/__tests__/plugins.test.ts +464 -0
- package/src/adapter/BlacAdapter.ts +347 -207
- package/src/adapter/ProxyFactory.ts +196 -255
- package/src/adapter/__tests__/BlacAdapter.test.ts +71 -77
- package/src/adapter/__tests__/ProxyFactory.test.ts +1 -1
- package/src/adapter/index.ts +0 -1
- package/src/errors/BlacError.ts +69 -0
- package/src/errors/ErrorManager.ts +101 -0
- package/src/errors/handleError.ts +114 -0
- package/src/errors/index.ts +13 -0
- package/src/events.ts +7 -1
- package/src/index.ts +10 -1
- package/src/lifecycle/BlocLifecycle.ts +156 -0
- package/src/lifecycle/index.ts +1 -0
- package/src/plugins/BlocPluginRegistry.ts +240 -0
- package/src/plugins/SystemPluginRegistry.ts +242 -0
- package/src/plugins/__tests__/BlocPluginRegistry.test.ts +450 -0
- package/src/plugins/__tests__/SystemPluginRegistry.test.ts +404 -0
- package/src/plugins/index.ts +8 -0
- package/src/plugins/types.ts +129 -0
- package/src/subscription/README.md +132 -0
- package/src/subscription/SubscriptionManager.ts +395 -0
- package/src/subscription/__tests__/SubscriptionManager.test.ts +355 -0
- package/src/subscription/index.ts +2 -0
- package/src/subscription/types.ts +90 -0
- package/src/testing.ts +31 -37
- package/src/types.ts +4 -21
- package/src/utils/BatchingManager.ts +59 -0
- package/src/utils/RerenderLogger.ts +265 -0
- package/src/utils/__tests__/generateInstanceId.test.ts +104 -0
- package/src/utils/__tests__/shallowEqual.test.ts +171 -0
- package/src/utils/__tests__/uuid.test.ts +144 -0
- package/src/utils/generateInstanceId.ts +54 -0
- package/src/utils/shallowEqual.ts +1 -1
- package/README.md +0 -329
- package/src/BlacObserver.ts +0 -186
- package/src/__tests__/BlocBase.lifecycle.test.ts +0 -441
- package/src/__tests__/props.test.ts +0 -256
- package/src/adapter/ConsumerTracker.ts +0 -241
- package/src/adapter/__tests__/ConsumerTracker.test.ts +0 -562
package/dist/index.es.js
CHANGED
|
@@ -1,697 +1,361 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
var u = /* @__PURE__ */ ((r) => (r.ACTIVE = "active", r.DISPOSAL_REQUESTED = "disposal_requested", r.DISPOSING = "disposing", r.DISPOSED = "disposed", r))(u || {});
|
|
2
|
+
class B {
|
|
3
|
+
disposalState = "active";
|
|
4
|
+
disposalLock = !1;
|
|
5
|
+
disposalTimer;
|
|
6
|
+
disposalHandler;
|
|
7
|
+
get currentState() {
|
|
8
|
+
return this.disposalState;
|
|
9
|
+
}
|
|
10
|
+
get isDisposed() {
|
|
11
|
+
return this.disposalState === "disposed";
|
|
12
|
+
}
|
|
5
13
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @param bloc - The Bloc instance to observe
|
|
14
|
+
* Atomic state transition for disposal
|
|
8
15
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
atomicStateTransition(e, t) {
|
|
17
|
+
if (this.disposalLock)
|
|
18
|
+
return {
|
|
19
|
+
success: !1,
|
|
20
|
+
currentState: this.disposalState,
|
|
21
|
+
previousState: this.disposalState
|
|
22
|
+
};
|
|
23
|
+
this.disposalLock = !0;
|
|
24
|
+
try {
|
|
25
|
+
if (this.disposalState !== e)
|
|
26
|
+
return {
|
|
27
|
+
success: !1,
|
|
28
|
+
currentState: this.disposalState,
|
|
29
|
+
previousState: this.disposalState
|
|
30
|
+
};
|
|
31
|
+
const s = this.disposalState;
|
|
32
|
+
return this.disposalState = t, {
|
|
33
|
+
success: !0,
|
|
34
|
+
currentState: t,
|
|
35
|
+
previousState: s
|
|
36
|
+
};
|
|
37
|
+
} finally {
|
|
38
|
+
this.disposalLock = !1;
|
|
39
|
+
}
|
|
14
40
|
}
|
|
15
41
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @returns The number of observers currently subscribed
|
|
42
|
+
* Schedule disposal after a delay
|
|
18
43
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
44
|
+
scheduleDisposal(e, t, s) {
|
|
45
|
+
this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0), this.atomicStateTransition(
|
|
46
|
+
"active",
|
|
47
|
+
"disposal_requested"
|
|
48
|
+
/* DISPOSAL_REQUESTED */
|
|
49
|
+
).success && (this.disposalTimer = setTimeout(() => {
|
|
50
|
+
t() && this.disposalState === "disposal_requested" ? s() : this.atomicStateTransition(
|
|
51
|
+
"disposal_requested",
|
|
52
|
+
"active"
|
|
53
|
+
/* ACTIVE */
|
|
54
|
+
);
|
|
55
|
+
}, e));
|
|
21
56
|
}
|
|
22
57
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @returns The Set of all BlacObserver instances
|
|
58
|
+
* Cancel disposal if in disposal requested state
|
|
25
59
|
*/
|
|
26
|
-
|
|
27
|
-
return this.
|
|
60
|
+
cancelDisposal() {
|
|
61
|
+
return this.disposalState === "disposal_requested" ? (this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0), this.atomicStateTransition(
|
|
62
|
+
"disposal_requested",
|
|
63
|
+
"active"
|
|
64
|
+
/* ACTIVE */
|
|
65
|
+
).success) : !1;
|
|
28
66
|
}
|
|
29
67
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @param observer - The observer to subscribe
|
|
32
|
-
* @returns A function that can be called to unsubscribe the observer
|
|
68
|
+
* Set disposal handler
|
|
33
69
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return t === _.DISPOSED || t === _.DISPOSING ? (d.log(
|
|
37
|
-
"BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",
|
|
38
|
-
this.bloc,
|
|
39
|
-
e
|
|
40
|
-
), () => {
|
|
41
|
-
}) : (d.log(
|
|
42
|
-
"BlacObservable.subscribe: Subscribing observer.",
|
|
43
|
-
this.bloc,
|
|
44
|
-
e
|
|
45
|
-
), this._observers.add(e), t === _.DISPOSAL_REQUESTED && (d.log(
|
|
46
|
-
"BlacObservable.subscribe: Cancelling disposal due to new subscription.",
|
|
47
|
-
this.bloc
|
|
48
|
-
), this.bloc._atomicStateTransition(
|
|
49
|
-
_.DISPOSAL_REQUESTED,
|
|
50
|
-
_.ACTIVE
|
|
51
|
-
)), () => {
|
|
52
|
-
d.log(
|
|
53
|
-
"BlacObservable.subscribe: Unsubscribing observer.",
|
|
54
|
-
this.bloc,
|
|
55
|
-
e
|
|
56
|
-
), this.unsubscribe(e);
|
|
57
|
-
});
|
|
70
|
+
setDisposalHandler(e) {
|
|
71
|
+
this.disposalHandler = e;
|
|
58
72
|
}
|
|
59
73
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @param observer - The observer to unsubscribe
|
|
74
|
+
* Get disposal handler
|
|
62
75
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
`[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`
|
|
66
|
-
), this.bloc._scheduleDisposal()));
|
|
76
|
+
getDisposalHandler() {
|
|
77
|
+
return this.disposalHandler;
|
|
67
78
|
}
|
|
68
79
|
/**
|
|
69
|
-
*
|
|
70
|
-
* @param newState - The new state value
|
|
71
|
-
* @param oldState - The previous state value
|
|
72
|
-
* @param action - Optional action that triggered the state change
|
|
80
|
+
* Clear disposal timer
|
|
73
81
|
*/
|
|
74
|
-
|
|
75
|
-
this.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
82
|
+
clearDisposalTimer() {
|
|
83
|
+
this.disposalTimer && (clearTimeout(this.disposalTimer), this.disposalTimer = void 0);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
class T {
|
|
87
|
+
plugins = /* @__PURE__ */ new Map();
|
|
88
|
+
metrics = /* @__PURE__ */ new Map();
|
|
89
|
+
executionOrder = [];
|
|
90
|
+
/**
|
|
91
|
+
* Add a system plugin
|
|
92
|
+
*/
|
|
93
|
+
add(e) {
|
|
94
|
+
if (this.plugins.has(e.name))
|
|
95
|
+
throw new Error(`Plugin '${e.name}' is already registered`);
|
|
96
|
+
this.plugins.set(e.name, e), this.executionOrder.push(e.name), this.initializeMetrics(e.name);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Remove a system plugin
|
|
100
|
+
*/
|
|
101
|
+
remove(e) {
|
|
102
|
+
return this.plugins.get(e) ? (this.plugins.delete(e), this.metrics.delete(e), this.executionOrder = this.executionOrder.filter(
|
|
103
|
+
(s) => s !== e
|
|
104
|
+
), !0) : !1;
|
|
98
105
|
}
|
|
99
106
|
/**
|
|
100
|
-
*
|
|
107
|
+
* Get a plugin by name
|
|
108
|
+
*/
|
|
109
|
+
get(e) {
|
|
110
|
+
return this.plugins.get(e);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get all plugins in execution order
|
|
114
|
+
*/
|
|
115
|
+
getAll() {
|
|
116
|
+
return this.executionOrder.map((e) => this.plugins.get(e));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Clear all plugins
|
|
101
120
|
*/
|
|
102
121
|
clear() {
|
|
103
|
-
this.
|
|
122
|
+
this.plugins.clear(), this.metrics.clear(), this.executionOrder = [];
|
|
104
123
|
}
|
|
105
|
-
}
|
|
106
|
-
function $() {
|
|
107
|
-
return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
|
108
|
-
const e = Math.random() * 16 | 0;
|
|
109
|
-
return (c === "x" ? e : e & 3 | 8).toString(16);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
var _ = /* @__PURE__ */ ((c) => (c.ACTIVE = "active", c.DISPOSAL_REQUESTED = "disposal_requested", c.DISPOSING = "disposing", c.DISPOSED = "disposed", c))(_ || {});
|
|
113
|
-
class x {
|
|
114
124
|
/**
|
|
115
|
-
*
|
|
116
|
-
* Sets up the observer, registers with the Blac manager, and initializes addons.
|
|
117
|
-
*
|
|
118
|
-
* @param initialState The initial state value for this Bloc
|
|
125
|
+
* Execute a hook on all plugins
|
|
119
126
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
*/
|
|
126
|
-
i(this, "defaultDependencySelector");
|
|
127
|
-
/**
|
|
128
|
-
* @internal
|
|
129
|
-
* Indicates if this specific Bloc instance is isolated from others of the same type.
|
|
130
|
-
*/
|
|
131
|
-
i(this, "_isolated", !1);
|
|
132
|
-
/**
|
|
133
|
-
* @internal
|
|
134
|
-
* Observable responsible for managing state listeners and notifying consumers.
|
|
135
|
-
*/
|
|
136
|
-
i(this, "_observer");
|
|
137
|
-
/**
|
|
138
|
-
* The unique identifier for this Bloc instance.
|
|
139
|
-
* Defaults to the class name, but can be customized.
|
|
140
|
-
*/
|
|
141
|
-
i(this, "_id");
|
|
142
|
-
/**
|
|
143
|
-
* @internal
|
|
144
|
-
* Reference string used internally for tracking and debugging.
|
|
145
|
-
*/
|
|
146
|
-
i(this, "_instanceRef");
|
|
147
|
-
/**
|
|
148
|
-
* @internal
|
|
149
|
-
* Indicates if this specific Bloc instance should be kept alive when no consumers are present.
|
|
150
|
-
*/
|
|
151
|
-
i(this, "_keepAlive", !1);
|
|
152
|
-
/**
|
|
153
|
-
* @readonly
|
|
154
|
-
* Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
|
|
155
|
-
*/
|
|
156
|
-
i(this, "_createdAt", Date.now());
|
|
157
|
-
/**
|
|
158
|
-
* @internal
|
|
159
|
-
* Atomic disposal state to prevent race conditions
|
|
160
|
-
*/
|
|
161
|
-
i(this, "_disposalState", "active");
|
|
162
|
-
/**
|
|
163
|
-
* @internal
|
|
164
|
-
* Timestamp when disposal was requested (for React Strict Mode grace period)
|
|
165
|
-
*/
|
|
166
|
-
i(this, "_disposalRequestTime", 0);
|
|
167
|
-
/**
|
|
168
|
-
* @internal
|
|
169
|
-
* The current state of the Bloc.
|
|
170
|
-
*/
|
|
171
|
-
i(this, "_state");
|
|
172
|
-
/**
|
|
173
|
-
* @internal
|
|
174
|
-
* The previous state of the Bloc, maintained for comparison and history.
|
|
175
|
-
*/
|
|
176
|
-
i(this, "_oldState");
|
|
177
|
-
/**
|
|
178
|
-
* Props passed during Bloc instance creation.
|
|
179
|
-
* Can be used to configure or parameterize the Bloc's behavior.
|
|
180
|
-
*/
|
|
181
|
-
i(this, "props", null);
|
|
182
|
-
/**
|
|
183
|
-
* @internal
|
|
184
|
-
* Flag to prevent batching race conditions
|
|
185
|
-
*/
|
|
186
|
-
i(this, "_batchingLock", !1);
|
|
187
|
-
/**
|
|
188
|
-
* @internal
|
|
189
|
-
* Pending batched updates
|
|
190
|
-
*/
|
|
191
|
-
i(this, "_pendingUpdates", []);
|
|
192
|
-
/**
|
|
193
|
-
* @internal
|
|
194
|
-
* Map of consumer IDs to their WeakRef objects for proper cleanup
|
|
195
|
-
*/
|
|
196
|
-
i(this, "_consumerRefs", /* @__PURE__ */ new Map());
|
|
197
|
-
/**
|
|
198
|
-
* @internal
|
|
199
|
-
* Validates that all consumer references are still alive
|
|
200
|
-
* Removes dead consumers automatically
|
|
201
|
-
*/
|
|
202
|
-
i(this, "_validateConsumers", () => {
|
|
203
|
-
const e = [];
|
|
204
|
-
for (const [t, s] of this._consumerRefs)
|
|
205
|
-
s.deref() === void 0 && e.push(t);
|
|
206
|
-
for (const t of e)
|
|
207
|
-
this._consumers.delete(t), this._consumerRefs.delete(t);
|
|
208
|
-
this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && this._scheduleDisposal();
|
|
209
|
-
});
|
|
210
|
-
/**
|
|
211
|
-
* @internal
|
|
212
|
-
* Updates the Bloc instance's ID to a new value.
|
|
213
|
-
* Only updates if the new ID is defined and different from the current one.
|
|
214
|
-
*
|
|
215
|
-
* @param id The new ID to assign to this Bloc instance
|
|
216
|
-
*/
|
|
217
|
-
i(this, "_updateId", (e) => {
|
|
218
|
-
const t = this._id;
|
|
219
|
-
!e || e === t || (this._id = e);
|
|
220
|
-
});
|
|
221
|
-
/**
|
|
222
|
-
* @internal
|
|
223
|
-
* Optional function to be called when the Bloc is disposed.
|
|
224
|
-
*/
|
|
225
|
-
i(this, "onDispose");
|
|
226
|
-
/**
|
|
227
|
-
* @internal
|
|
228
|
-
* Set of consumer IDs currently listening to this Bloc's state changes.
|
|
229
|
-
*/
|
|
230
|
-
i(this, "_consumers", /* @__PURE__ */ new Set());
|
|
231
|
-
/**
|
|
232
|
-
* @internal
|
|
233
|
-
* Registers a new consumer to this Bloc instance.
|
|
234
|
-
* Notifies the Blac manager that a consumer has been added.
|
|
235
|
-
*
|
|
236
|
-
* @param consumerId The unique ID of the consumer being added
|
|
237
|
-
* @param consumerRef Optional reference to the consumer object for cleanup validation
|
|
238
|
-
*/
|
|
239
|
-
i(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);
|
|
244
|
-
});
|
|
245
|
-
/**
|
|
246
|
-
* @internal
|
|
247
|
-
* Unregisters a consumer from this Bloc instance.
|
|
248
|
-
* Notifies the Blac manager that a consumer has been removed.
|
|
249
|
-
*
|
|
250
|
-
* @param consumerId The unique ID of the consumer being removed
|
|
251
|
-
*/
|
|
252
|
-
i(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()));
|
|
259
|
-
});
|
|
260
|
-
/**
|
|
261
|
-
* @internal
|
|
262
|
-
* Handler function for disposal (can be set by Blac manager)
|
|
263
|
-
*/
|
|
264
|
-
i(this, "_disposalHandler");
|
|
265
|
-
i(this, "lastUpdate", Date.now());
|
|
266
|
-
/**
|
|
267
|
-
* @internal
|
|
268
|
-
* Flag to indicate if batching is enabled for this bloc
|
|
269
|
-
*/
|
|
270
|
-
i(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
|
-
i(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
|
-
i(this, "batch", (e) => {
|
|
293
|
-
if (this._batchingLock)
|
|
294
|
-
return e();
|
|
295
|
-
this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
|
|
127
|
+
executeHook(e, t, s) {
|
|
128
|
+
for (const i of this.executionOrder) {
|
|
129
|
+
const n = this.plugins.get(i), a = n[e];
|
|
130
|
+
if (typeof a != "function") continue;
|
|
131
|
+
const c = performance.now();
|
|
296
132
|
try {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
s.action
|
|
304
|
-
), this.lastUpdate = Date.now();
|
|
305
|
-
}
|
|
306
|
-
return t;
|
|
307
|
-
} finally {
|
|
308
|
-
this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
|
|
133
|
+
a.apply(n, t), this.recordSuccess(i, e, c);
|
|
134
|
+
} catch (l) {
|
|
135
|
+
this.recordError(i, e, l), s ? s(l, n) : console.error(
|
|
136
|
+
`Plugin '${i}' error in hook '${e}':`,
|
|
137
|
+
l
|
|
138
|
+
);
|
|
309
139
|
}
|
|
310
|
-
}
|
|
311
|
-
this._state = e, this._observer = new V(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;
|
|
140
|
+
}
|
|
314
141
|
}
|
|
315
|
-
|
|
316
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Bootstrap all plugins
|
|
144
|
+
*/
|
|
145
|
+
bootstrap() {
|
|
146
|
+
this.executeHook("beforeBootstrap", []), this.executeHook("afterBootstrap", []);
|
|
317
147
|
}
|
|
318
|
-
|
|
319
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Shutdown all plugins
|
|
150
|
+
*/
|
|
151
|
+
shutdown() {
|
|
152
|
+
this.executeHook("beforeShutdown", []), this.executeHook("afterShutdown", []);
|
|
320
153
|
}
|
|
321
154
|
/**
|
|
322
|
-
*
|
|
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.
|
|
155
|
+
* Notify plugins of bloc creation
|
|
325
156
|
*/
|
|
326
|
-
|
|
327
|
-
|
|
157
|
+
notifyBlocCreated(e) {
|
|
158
|
+
this.executeHook("onBlocCreated", [e]);
|
|
328
159
|
}
|
|
329
160
|
/**
|
|
330
|
-
*
|
|
331
|
-
* @returns true if the bloc is in DISPOSED state
|
|
161
|
+
* Notify plugins of bloc disposal
|
|
332
162
|
*/
|
|
333
|
-
|
|
334
|
-
|
|
163
|
+
notifyBlocDisposed(e) {
|
|
164
|
+
this.executeHook("onBlocDisposed", [e]);
|
|
335
165
|
}
|
|
336
166
|
/**
|
|
337
|
-
*
|
|
338
|
-
* Returns the name of the Bloc class for identification and debugging.
|
|
167
|
+
* Notify plugins of state change
|
|
339
168
|
*/
|
|
340
|
-
|
|
341
|
-
|
|
169
|
+
notifyStateChanged(e, t, s) {
|
|
170
|
+
this.executeHook("onStateChanged", [e, t, s]);
|
|
342
171
|
}
|
|
343
172
|
/**
|
|
344
|
-
*
|
|
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
|
|
173
|
+
* Notify plugins of event addition
|
|
349
174
|
*/
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
175
|
+
notifyEventAdded(e, t) {
|
|
176
|
+
this.executeHook("onEventAdded", [e, t]);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Notify plugins of errors
|
|
180
|
+
*/
|
|
181
|
+
notifyError(e, t, s) {
|
|
182
|
+
this.executeHook("onError", [e, t, s], (i, n) => {
|
|
183
|
+
console.error(`Plugin '${n.name}' error handler failed:`, i);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Notify plugins of adapter lifecycle events
|
|
188
|
+
*/
|
|
189
|
+
notifyAdapterCreated(e, t) {
|
|
190
|
+
this.executeHook("onAdapterCreated", [e, t]);
|
|
191
|
+
}
|
|
192
|
+
notifyAdapterMount(e, t) {
|
|
193
|
+
this.executeHook("onAdapterMount", [e, t]);
|
|
194
|
+
}
|
|
195
|
+
notifyAdapterUnmount(e, t) {
|
|
196
|
+
this.executeHook("onAdapterUnmount", [e, t]);
|
|
197
|
+
}
|
|
198
|
+
notifyAdapterRender(e, t) {
|
|
199
|
+
this.executeHook("onAdapterRender", [e, t]);
|
|
200
|
+
}
|
|
201
|
+
notifyAdapterDisposed(e, t) {
|
|
202
|
+
this.executeHook("onAdapterDisposed", [e, t]);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get metrics for a plugin
|
|
206
|
+
*/
|
|
207
|
+
getMetrics(e) {
|
|
208
|
+
return this.metrics.get(e);
|
|
209
|
+
}
|
|
210
|
+
initializeMetrics(e) {
|
|
211
|
+
this.metrics.set(e, /* @__PURE__ */ new Map());
|
|
212
|
+
}
|
|
213
|
+
recordSuccess(e, t, s) {
|
|
214
|
+
const i = this.metrics.get(e), n = i.get(t) || {
|
|
215
|
+
executionTime: 0,
|
|
216
|
+
executionCount: 0,
|
|
217
|
+
errorCount: 0
|
|
218
|
+
}, a = performance.now() - s;
|
|
219
|
+
i.set(t, {
|
|
220
|
+
...n,
|
|
221
|
+
executionTime: n.executionTime + a,
|
|
222
|
+
executionCount: n.executionCount + 1,
|
|
223
|
+
lastExecutionTime: a
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
recordError(e, t, s) {
|
|
227
|
+
const i = this.metrics.get(e), n = i.get(t) || {
|
|
228
|
+
executionTime: 0,
|
|
229
|
+
executionCount: 0,
|
|
230
|
+
errorCount: 0
|
|
368
231
|
};
|
|
232
|
+
i.set(t, {
|
|
233
|
+
...n,
|
|
234
|
+
errorCount: n.errorCount + 1,
|
|
235
|
+
lastError: s
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
var v = /* @__PURE__ */ ((r) => (r.LIFECYCLE = "LIFECYCLE", r.STATE = "STATE", r.PLUGIN = "PLUGIN", r.VALIDATION = "VALIDATION", r.DISPOSAL = "DISPOSAL", r.CONSUMER = "CONSUMER", r))(v || {}), y = /* @__PURE__ */ ((r) => (r.FATAL = "FATAL", r.ERROR = "ERROR", r.WARNING = "WARNING", r.INFO = "INFO", r))(y || {});
|
|
240
|
+
class m extends Error {
|
|
241
|
+
constructor(e, t, s, i, n) {
|
|
242
|
+
super(e), this.category = t, this.severity = s, this.context = i, this.cause = n, this.name = "BlacError", Object.setPrototypeOf(this, m.prototype);
|
|
243
|
+
}
|
|
244
|
+
toString() {
|
|
245
|
+
const e = this.context ? ` [${Object.entries(this.context).filter(([t, s]) => s !== void 0).map(([t, s]) => `${t}: ${s}`).join(", ")}]` : "";
|
|
246
|
+
return `${this.name} [${this.severity}/${this.category}]: ${this.message}${e}`;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const P = {
|
|
250
|
+
shouldPropagate: (r) => r.severity === "FATAL",
|
|
251
|
+
shouldLog: (r) => r.severity !== "INFO",
|
|
252
|
+
handle: (r) => {
|
|
253
|
+
P.shouldLog(r) && console.error(r.toString(), r.cause);
|
|
369
254
|
}
|
|
255
|
+
};
|
|
256
|
+
class f {
|
|
257
|
+
static instance;
|
|
258
|
+
handlers = /* @__PURE__ */ new Set();
|
|
259
|
+
strategy = P;
|
|
370
260
|
/**
|
|
371
|
-
*
|
|
372
|
-
* Cleans up resources and removes this Bloc from the system.
|
|
373
|
-
* Notifies the Blac manager and clears all observers.
|
|
261
|
+
* Get the singleton instance of ErrorManager
|
|
374
262
|
*/
|
|
375
|
-
|
|
376
|
-
|
|
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
|
-
}
|
|
263
|
+
static getInstance() {
|
|
264
|
+
return f.instance || (f.instance = new f()), f.instance;
|
|
397
265
|
}
|
|
398
266
|
/**
|
|
399
|
-
*
|
|
400
|
-
* Sets the disposal handler for this bloc
|
|
267
|
+
* Set a custom error handling strategy
|
|
401
268
|
*/
|
|
402
|
-
|
|
403
|
-
this.
|
|
269
|
+
setStrategy(e) {
|
|
270
|
+
this.strategy = e;
|
|
404
271
|
}
|
|
405
272
|
/**
|
|
406
|
-
*
|
|
407
|
-
* Schedules disposal of this bloc instance if it has no consumers
|
|
408
|
-
* Uses atomic state transitions to prevent race conditions
|
|
273
|
+
* Add a custom error handler that will be called for all errors
|
|
409
274
|
*/
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
275
|
+
addHandler(e) {
|
|
276
|
+
this.handlers.add(e);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Remove a previously added error handler
|
|
280
|
+
*/
|
|
281
|
+
removeHandler(e) {
|
|
282
|
+
this.handlers.delete(e);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Process an error through all handlers and apply the configured strategy
|
|
286
|
+
*/
|
|
287
|
+
handle(e) {
|
|
288
|
+
if (this.handlers.forEach((t) => {
|
|
289
|
+
try {
|
|
290
|
+
t(e);
|
|
291
|
+
} catch (s) {
|
|
292
|
+
console.error("Error in error handler:", s);
|
|
293
|
+
}
|
|
294
|
+
}), this.strategy.handle(e), this.strategy.shouldPropagate(e))
|
|
295
|
+
throw e;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Convenience method for wrapping operations with error handling
|
|
299
|
+
*/
|
|
300
|
+
wrap(e, t) {
|
|
301
|
+
try {
|
|
302
|
+
return e();
|
|
303
|
+
} catch (s) {
|
|
304
|
+
const i = t(s);
|
|
305
|
+
this.handle(i);
|
|
416
306
|
return;
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Async version of wrap
|
|
311
|
+
*/
|
|
312
|
+
async wrapAsync(e, t) {
|
|
313
|
+
try {
|
|
314
|
+
return await e();
|
|
315
|
+
} catch (s) {
|
|
316
|
+
const i = t(s);
|
|
317
|
+
this.handle(i);
|
|
423
318
|
return;
|
|
424
319
|
}
|
|
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
320
|
}
|
|
433
321
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
* Use this when state should not be shared between components.
|
|
437
|
-
* @default false
|
|
438
|
-
*/
|
|
439
|
-
i(x, "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
|
-
i(x, "keepAlive", !1);
|
|
445
|
-
const y = class y {
|
|
322
|
+
class g {
|
|
323
|
+
static _instance;
|
|
446
324
|
getInstance() {
|
|
447
|
-
return
|
|
325
|
+
return g._instance || (g._instance = new o({
|
|
448
326
|
__unsafe_ignore_singleton: !0
|
|
449
|
-
})),
|
|
327
|
+
})), g._instance;
|
|
450
328
|
}
|
|
451
329
|
setInstance(e) {
|
|
452
|
-
|
|
330
|
+
g._instance = e;
|
|
453
331
|
}
|
|
454
332
|
resetInstance() {
|
|
455
|
-
const e =
|
|
456
|
-
if (
|
|
333
|
+
const e = g._instance;
|
|
334
|
+
if (g._instance = new o({
|
|
457
335
|
__unsafe_ignore_singleton: !0
|
|
458
336
|
}), e)
|
|
459
337
|
for (const t of e.keepAliveBlocs)
|
|
460
|
-
|
|
338
|
+
g._instance.keepAliveBlocs.add(t), g._instance.uidRegistry.set(t.uid, t);
|
|
461
339
|
}
|
|
462
|
-
};
|
|
463
|
-
i(y, "_instance");
|
|
464
|
-
let C = y, S = new C();
|
|
465
|
-
function q(c) {
|
|
466
|
-
S = c;
|
|
467
340
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
constructor(e = {}) {
|
|
474
|
-
/** Timestamp when the instance was created */
|
|
475
|
-
i(this, "createdAt", Date.now());
|
|
476
|
-
/** Map storing all registered bloc instances by their class name and ID */
|
|
477
|
-
i(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
|
-
i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
|
|
483
|
-
/** Map for O(1) lookup of isolated blocs by UID */
|
|
484
|
-
i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
|
|
485
|
-
/** Map tracking UIDs to prevent memory leaks */
|
|
486
|
-
i(this, "uidRegistry", /* @__PURE__ */ new Map());
|
|
487
|
-
/** Set of keep-alive blocs for controlled cleanup */
|
|
488
|
-
i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
|
|
489
|
-
/** Flag to control whether changes should be posted to document */
|
|
490
|
-
i(this, "postChangesToDocument", !1);
|
|
491
|
-
/**
|
|
492
|
-
* Logs messages to console when logging is enabled
|
|
493
|
-
* @param args - Arguments to log
|
|
494
|
-
*/
|
|
495
|
-
i(this, "log", (...e) => {
|
|
496
|
-
l.logSpy && l.logSpy(e), l.enableLog && l.logLevel, l.enableLog && l.logLevel;
|
|
497
|
-
});
|
|
498
|
-
/**
|
|
499
|
-
* Logs a warning message
|
|
500
|
-
* @param message - Warning message
|
|
501
|
-
* @param args - Additional arguments
|
|
502
|
-
*/
|
|
503
|
-
i(this, "warn", (e, ...t) => {
|
|
504
|
-
l.enableLog;
|
|
505
|
-
});
|
|
506
|
-
/**
|
|
507
|
-
* Logs an error message
|
|
508
|
-
* @param message - Error message
|
|
509
|
-
* @param args - Additional arguments
|
|
510
|
-
*/
|
|
511
|
-
i(this, "error", (e, ...t) => {
|
|
512
|
-
l.enableLog;
|
|
513
|
-
});
|
|
514
|
-
/**
|
|
515
|
-
* Resets the Blac instance to a new one, disposing non-keepAlive blocs
|
|
516
|
-
* from the old instance.
|
|
517
|
-
*/
|
|
518
|
-
i(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((n) => {
|
|
525
|
-
!n._keepAlive && n._disposalState === _.ACTIVE && this.disposeBloc(n);
|
|
526
|
-
});
|
|
527
|
-
}), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), S.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
|
-
i(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 n = e.constructor, r = this.createBlocInstanceMapKey(e._name, e._id);
|
|
545
|
-
this.log(
|
|
546
|
-
`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(n.isolated)}`
|
|
547
|
-
), e._dispose(), n.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(r)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
|
|
548
|
-
});
|
|
549
|
-
i(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
|
-
i(this, "getBloc", (e, t = {}) => {
|
|
573
|
-
const { id: s, forceNewInstance: n } = t, r = e, o = s ?? e.name;
|
|
574
|
-
if (this.log(`[${e.name}:${String(o)}] (getBloc) Called:`, {
|
|
575
|
-
options: t,
|
|
576
|
-
base: r
|
|
577
|
-
}), !n)
|
|
578
|
-
if (r.isolated) {
|
|
579
|
-
const u = this.findIsolatedBlocInstance(
|
|
580
|
-
e,
|
|
581
|
-
t.instanceRef ?? o
|
|
582
|
-
);
|
|
583
|
-
if (u)
|
|
584
|
-
return u;
|
|
585
|
-
if (t.throwIfNotFound)
|
|
586
|
-
throw new Error(`Isolated bloc ${e.name} not found`);
|
|
587
|
-
} else {
|
|
588
|
-
const u = this.findRegisteredBlocInstance(
|
|
589
|
-
e,
|
|
590
|
-
o
|
|
591
|
-
);
|
|
592
|
-
if (u)
|
|
593
|
-
return u;
|
|
594
|
-
if (t.throwIfNotFound)
|
|
595
|
-
throw new Error(`Registered bloc ${e.name} not found`);
|
|
596
|
-
}
|
|
597
|
-
const a = this.createNewBlocInstance(e, o, t);
|
|
598
|
-
if (this.log(
|
|
599
|
-
`[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`,
|
|
600
|
-
t,
|
|
601
|
-
a
|
|
602
|
-
), !a)
|
|
603
|
-
throw new Error(
|
|
604
|
-
`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
|
|
605
|
-
);
|
|
606
|
-
return a;
|
|
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
|
-
i(this, "getBlocOrThrow", (e, t = {}) => {
|
|
617
|
-
const s = e.isolated, n = t.id || e.name, r = s ? this.findIsolatedBlocInstance(e, n) : this.findRegisteredBlocInstance(e, n);
|
|
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
|
-
i(this, "getAllBlocs", (e, t = {}) => {
|
|
630
|
-
const s = [];
|
|
631
|
-
if (this.blocInstanceMap.forEach((n) => {
|
|
632
|
-
n.constructor === e && s.push(n);
|
|
633
|
-
}), t.searchIsolated !== !1) {
|
|
634
|
-
const n = this.isolatedBlocMap.get(e);
|
|
635
|
-
n && s.push(...n.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
|
-
i(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
|
-
});
|
|
649
|
-
/**
|
|
650
|
-
* Disposes all blocs matching a pattern
|
|
651
|
-
* @param predicate - Function to test each bloc for disposal
|
|
652
|
-
*/
|
|
653
|
-
i(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 n of s)
|
|
659
|
-
e(n) && t.push(n);
|
|
660
|
-
t.forEach((s) => s._dispose());
|
|
661
|
-
});
|
|
662
|
-
/**
|
|
663
|
-
* Gets memory usage statistics for debugging
|
|
664
|
-
*/
|
|
665
|
-
i(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
|
-
i(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);
|
|
683
|
-
});
|
|
684
|
-
const { __unsafe_ignore_singleton: t = !1 } = e;
|
|
685
|
-
if (!t)
|
|
686
|
-
return l.instance;
|
|
687
|
-
S.setInstance(this);
|
|
688
|
-
}
|
|
341
|
+
let b = new g();
|
|
342
|
+
function H(r) {
|
|
343
|
+
b = r;
|
|
344
|
+
}
|
|
345
|
+
class o {
|
|
689
346
|
static get instance() {
|
|
690
|
-
return
|
|
347
|
+
return b.getInstance();
|
|
691
348
|
}
|
|
349
|
+
/** Timestamp when the instance was created */
|
|
350
|
+
createdAt = Date.now();
|
|
351
|
+
errorManager = f.getInstance();
|
|
692
352
|
static get getAllBlocs() {
|
|
693
|
-
return
|
|
353
|
+
return o.instance.getAllBlocs;
|
|
694
354
|
}
|
|
355
|
+
/** Private static configuration */
|
|
356
|
+
static _config = {
|
|
357
|
+
proxyDependencyTracking: !0
|
|
358
|
+
};
|
|
695
359
|
/** Get current configuration */
|
|
696
360
|
static get config() {
|
|
697
361
|
return { ...this._config };
|
|
@@ -702,174 +366,1106 @@ const l = class l {
|
|
|
702
366
|
* @throws Error if configuration is invalid
|
|
703
367
|
*/
|
|
704
368
|
static setConfig(e) {
|
|
705
|
-
if (e.proxyDependencyTracking !== void 0 && typeof e.proxyDependencyTracking != "boolean")
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
369
|
+
if (e.proxyDependencyTracking !== void 0 && typeof e.proxyDependencyTracking != "boolean") {
|
|
370
|
+
const t = new m(
|
|
371
|
+
"BlacConfig.proxyDependencyTracking must be a boolean",
|
|
372
|
+
v.VALIDATION,
|
|
373
|
+
y.FATAL
|
|
374
|
+
);
|
|
375
|
+
this.instance.errorManager.handle(t);
|
|
376
|
+
}
|
|
709
377
|
this._config = {
|
|
710
378
|
...this._config,
|
|
711
379
|
...e
|
|
712
380
|
}, this.enableLog && this.instance.log("Blac config updated:", this._config);
|
|
713
381
|
}
|
|
382
|
+
/** Map storing all registered bloc instances by their class name and ID */
|
|
383
|
+
blocInstanceMap = /* @__PURE__ */ new Map();
|
|
384
|
+
/** Map storing isolated bloc instances grouped by their constructor */
|
|
385
|
+
// Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
|
|
386
|
+
// different bloc types in the same map. The 'any' allows proper polymorphic storage
|
|
387
|
+
// while maintaining type safety at usage sites through the BlocConstructor constraint.
|
|
388
|
+
isolatedBlocMap = /* @__PURE__ */ new Map();
|
|
389
|
+
/** Map for O(1) lookup of isolated blocs by UID */
|
|
390
|
+
isolatedBlocIndex = /* @__PURE__ */ new Map();
|
|
391
|
+
/** Map tracking UIDs to prevent memory leaks */
|
|
392
|
+
uidRegistry = /* @__PURE__ */ new Map();
|
|
393
|
+
/** Set of keep-alive blocs for controlled cleanup */
|
|
394
|
+
keepAliveBlocs = /* @__PURE__ */ new Set();
|
|
395
|
+
/** Flag to control whether changes should be posted to document */
|
|
396
|
+
postChangesToDocument = !1;
|
|
397
|
+
/** System plugin registry */
|
|
398
|
+
plugins = new T();
|
|
399
|
+
/**
|
|
400
|
+
* Creates a new Blac instance.
|
|
401
|
+
* @param options - Configuration options including singleton control
|
|
402
|
+
*/
|
|
403
|
+
constructor(e = {}) {
|
|
404
|
+
const { __unsafe_ignore_singleton: t = !1 } = e;
|
|
405
|
+
if (!t)
|
|
406
|
+
return o.instance;
|
|
407
|
+
b.setInstance(this), this.plugins.bootstrap();
|
|
408
|
+
}
|
|
409
|
+
/** Flag to enable/disable logging */
|
|
410
|
+
static enableLog = !1;
|
|
411
|
+
static logLevel = "warn";
|
|
412
|
+
static logSpy = null;
|
|
413
|
+
/**
|
|
414
|
+
* Logs messages to console when logging is enabled
|
|
415
|
+
* @param args - Arguments to log
|
|
416
|
+
*/
|
|
417
|
+
log = (...e) => {
|
|
418
|
+
o.logSpy && o.logSpy(e), o.enableLog && o.logLevel, o.enableLog && o.logLevel;
|
|
419
|
+
};
|
|
714
420
|
static get log() {
|
|
715
|
-
return
|
|
421
|
+
return o.instance.log;
|
|
716
422
|
}
|
|
717
423
|
/**
|
|
718
424
|
* Gets the current Blac instance
|
|
719
425
|
* @returns The Blac instance
|
|
720
426
|
*/
|
|
721
427
|
static getInstance() {
|
|
722
|
-
return
|
|
428
|
+
return b.getInstance();
|
|
723
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Logs a warning message
|
|
432
|
+
* @param message - Warning message
|
|
433
|
+
* @param args - Additional arguments
|
|
434
|
+
*/
|
|
435
|
+
warn = (e, ...t) => {
|
|
436
|
+
console.warn(e, ...t);
|
|
437
|
+
};
|
|
724
438
|
static get warn() {
|
|
725
|
-
return
|
|
439
|
+
return o.instance.warn;
|
|
726
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Logs an error message
|
|
443
|
+
* @param message - Error message
|
|
444
|
+
* @param args - Additional arguments
|
|
445
|
+
*/
|
|
446
|
+
error = (e, ...t) => {
|
|
447
|
+
o.enableLog && console.error(e, ...t);
|
|
448
|
+
};
|
|
727
449
|
static get error() {
|
|
728
|
-
return
|
|
450
|
+
return o.instance.error;
|
|
729
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* Resets the Blac instance to a new one, disposing non-keepAlive blocs
|
|
454
|
+
* from the old instance.
|
|
455
|
+
*/
|
|
456
|
+
resetInstance = () => {
|
|
457
|
+
this.log("Reset Blac instance");
|
|
458
|
+
const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
|
|
459
|
+
e.forEach((s) => {
|
|
460
|
+
!s._keepAlive && s._disposalState === u.ACTIVE && this.disposeBloc(s);
|
|
461
|
+
}), t.forEach((s) => {
|
|
462
|
+
s.forEach((i) => {
|
|
463
|
+
!i._keepAlive && i._disposalState === u.ACTIVE && this.disposeBloc(i);
|
|
464
|
+
});
|
|
465
|
+
}), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), b.resetInstance();
|
|
466
|
+
};
|
|
467
|
+
static resetInstance = () => {
|
|
468
|
+
b.resetInstance();
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Disposes of a bloc instance by removing it from the appropriate registry
|
|
472
|
+
* @param bloc - The bloc instance to dispose
|
|
473
|
+
*/
|
|
474
|
+
disposeBloc = (e) => {
|
|
475
|
+
const t = e._disposalState;
|
|
476
|
+
if (![
|
|
477
|
+
u.ACTIVE,
|
|
478
|
+
u.DISPOSAL_REQUESTED
|
|
479
|
+
].includes(t)) {
|
|
480
|
+
this.log(
|
|
481
|
+
`[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`
|
|
482
|
+
);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const i = e.constructor, n = this.createBlocInstanceMapKey(e._name, e._id);
|
|
486
|
+
this.log(
|
|
487
|
+
`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(i.isolated)}`
|
|
488
|
+
), e.dispose(), this.plugins.notifyBlocDisposed(e), i.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(n)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
|
|
489
|
+
};
|
|
730
490
|
static get disposeBloc() {
|
|
731
|
-
return
|
|
491
|
+
return o.instance.disposeBloc;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
|
|
495
|
+
* @param blocClassName - The name of the bloc class
|
|
496
|
+
* @param id - The instance ID
|
|
497
|
+
* @returns A unique key string in the format "className:id"
|
|
498
|
+
*/
|
|
499
|
+
createBlocInstanceMapKey(e, t) {
|
|
500
|
+
return `${e}:${String(t)}`;
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Unregister a bloc instance from the main registry
|
|
504
|
+
* @param bloc - The bloc instance to unregister
|
|
505
|
+
*/
|
|
506
|
+
unregisterBlocInstance(e) {
|
|
507
|
+
const t = this.createBlocInstanceMapKey(e._name, e._id);
|
|
508
|
+
this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Registers a bloc instance in the main registry
|
|
512
|
+
* @param bloc - The bloc instance to register
|
|
513
|
+
*/
|
|
514
|
+
registerBlocInstance(e) {
|
|
515
|
+
const t = this.createBlocInstanceMapKey(e._name, e._id);
|
|
516
|
+
this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Finds a registered bloc instance by its class and ID
|
|
520
|
+
* @param blocClass - The bloc class to search for
|
|
521
|
+
* @param id - The instance ID
|
|
522
|
+
* @returns The found bloc instance or undefined if not found
|
|
523
|
+
*/
|
|
524
|
+
findRegisteredBlocInstance(e, t) {
|
|
525
|
+
if (e.isolated) return;
|
|
526
|
+
const i = this.createBlocInstanceMapKey(e.name, t), n = this.blocInstanceMap.get(i);
|
|
527
|
+
if (!(n && n.isDisposed))
|
|
528
|
+
return n;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Registers an isolated bloc instance in the isolated registry
|
|
532
|
+
* @param bloc - The isolated bloc instance to register
|
|
533
|
+
*/
|
|
534
|
+
registerIsolatedBlocInstance(e) {
|
|
535
|
+
const t = e.constructor, s = this.isolatedBlocMap.get(t);
|
|
536
|
+
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);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Unregister an isolated bloc instance from the isolated registry
|
|
540
|
+
* @param bloc - The isolated bloc instance to unregister
|
|
541
|
+
*/
|
|
542
|
+
unregisterIsolatedBlocInstance(e) {
|
|
543
|
+
const t = e.constructor, s = this.isolatedBlocMap.get(t);
|
|
544
|
+
let i = !1;
|
|
545
|
+
if (s) {
|
|
546
|
+
const a = s.findIndex((c) => c.uid === e.uid);
|
|
547
|
+
a !== -1 && (s.splice(a, 1), i = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
|
|
548
|
+
}
|
|
549
|
+
const n = this.isolatedBlocIndex.delete(e.uid);
|
|
550
|
+
this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), i !== n && this.warn(
|
|
551
|
+
`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${i}, Index removal: ${n}`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Finds an isolated bloc instance by its class and ID (O(n) lookup)
|
|
556
|
+
*/
|
|
557
|
+
findIsolatedBlocInstance(e, t) {
|
|
558
|
+
if (!e.isolated) return;
|
|
559
|
+
const i = this.isolatedBlocMap.get(e);
|
|
560
|
+
return i ? i.find((a) => a._id === t && !a.isDisposed) : void 0;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Finds an isolated bloc instance by UID (O(1) lookup)
|
|
564
|
+
*/
|
|
565
|
+
findIsolatedBlocInstanceByUid(e) {
|
|
566
|
+
return this.isolatedBlocIndex.get(e);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Creates a new bloc instance and registers it in the appropriate registry
|
|
570
|
+
* @param blocClass - The bloc class to instantiate
|
|
571
|
+
* @param id - The instance ID
|
|
572
|
+
* @param props - Properties to pass to the bloc constructor
|
|
573
|
+
* @param instanceRef - Optional reference string for the instance
|
|
574
|
+
* @returns The newly created bloc instance
|
|
575
|
+
*/
|
|
576
|
+
createNewBlocInstance(e, t, s = {}) {
|
|
577
|
+
const { constructorParams: i, instanceRef: n } = s, a = new e(i);
|
|
578
|
+
return a.blacInstance = this, a._instanceRef = n, a._id = t, a.setDisposalHandler((c) => this.disposeBloc(c)), a.isIsolated ? this.registerIsolatedBlocInstance(a) : this.registerBlocInstance(a), this.plugins.notifyBlocCreated(a), a;
|
|
579
|
+
}
|
|
580
|
+
activateBloc = (e) => {
|
|
581
|
+
if (e._disposalState !== u.ACTIVE) {
|
|
582
|
+
this.log(
|
|
583
|
+
`[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
|
|
584
|
+
);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const t = e.constructor;
|
|
588
|
+
(e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(
|
|
589
|
+
`[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`
|
|
590
|
+
), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
|
|
591
|
+
};
|
|
592
|
+
static get activateBloc() {
|
|
593
|
+
return o.instance.activateBloc;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Gets or creates a bloc instance based on the provided class and options.
|
|
597
|
+
* If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
|
|
598
|
+
*
|
|
599
|
+
* @param blocClass - The bloc class to get or create
|
|
600
|
+
* @param options - Options including:
|
|
601
|
+
* - id: The instance ID (defaults to class name if not provided)
|
|
602
|
+
* - props: Properties to pass to the bloc constructor
|
|
603
|
+
* - instanceRef: Optional reference string for the instance
|
|
604
|
+
* @returns The bloc instance
|
|
605
|
+
*/
|
|
606
|
+
getBloc = (e, t = {}) => {
|
|
607
|
+
const { id: s, forceNewInstance: i } = t, n = e, a = s ?? e.name;
|
|
608
|
+
if (this.log(`[${e.name}:${String(a)}] (getBloc) Called:`, {
|
|
609
|
+
options: t,
|
|
610
|
+
base: n
|
|
611
|
+
}), !i)
|
|
612
|
+
if (n.isolated) {
|
|
613
|
+
const l = this.findIsolatedBlocInstance(
|
|
614
|
+
e,
|
|
615
|
+
t.instanceRef ?? a
|
|
616
|
+
);
|
|
617
|
+
if (l)
|
|
618
|
+
return l;
|
|
619
|
+
if (t.throwIfNotFound)
|
|
620
|
+
throw new Error(`Isolated bloc ${e.name} not found`);
|
|
621
|
+
} else {
|
|
622
|
+
const l = this.findRegisteredBlocInstance(
|
|
623
|
+
e,
|
|
624
|
+
a
|
|
625
|
+
);
|
|
626
|
+
if (l)
|
|
627
|
+
return l;
|
|
628
|
+
if (t.throwIfNotFound)
|
|
629
|
+
throw new Error(`Registered bloc ${e.name} not found`);
|
|
630
|
+
}
|
|
631
|
+
const c = this.createNewBlocInstance(e, a, t);
|
|
632
|
+
if (this.log(
|
|
633
|
+
`[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`,
|
|
634
|
+
t,
|
|
635
|
+
c
|
|
636
|
+
), !c)
|
|
637
|
+
throw new Error(
|
|
638
|
+
`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
|
|
639
|
+
);
|
|
640
|
+
return c;
|
|
641
|
+
};
|
|
642
|
+
static get getBloc() {
|
|
643
|
+
return o.instance.getBloc;
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Gets all instances of a specific bloc class
|
|
647
|
+
* @param blocClass - The bloc class to search for
|
|
648
|
+
* @param options - Options including:
|
|
649
|
+
* - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
|
|
650
|
+
* @returns Array of matching bloc instances
|
|
651
|
+
*/
|
|
652
|
+
getAllBlocs = (e, t = {}) => {
|
|
653
|
+
const s = [];
|
|
654
|
+
if (this.blocInstanceMap.forEach((i) => {
|
|
655
|
+
i.constructor === e && s.push(i);
|
|
656
|
+
}), t.searchIsolated !== !1) {
|
|
657
|
+
const i = this.isolatedBlocMap.get(e);
|
|
658
|
+
i && s.push(...i.map((n) => n));
|
|
659
|
+
}
|
|
660
|
+
return s;
|
|
661
|
+
};
|
|
662
|
+
/**
|
|
663
|
+
* Disposes all keep-alive blocs of a specific type
|
|
664
|
+
* @param blocClass - The bloc class to dispose
|
|
665
|
+
*/
|
|
666
|
+
disposeKeepAliveBlocs = (e) => {
|
|
667
|
+
const t = [];
|
|
668
|
+
for (const s of this.keepAliveBlocs)
|
|
669
|
+
(!e || s.constructor === e) && t.push(s);
|
|
670
|
+
t.forEach((s) => s.dispose());
|
|
671
|
+
};
|
|
672
|
+
static get disposeKeepAliveBlocs() {
|
|
673
|
+
return o.instance.disposeKeepAliveBlocs;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Disposes all blocs matching a pattern
|
|
677
|
+
* @param predicate - Function to test each bloc for disposal
|
|
678
|
+
*/
|
|
679
|
+
disposeBlocs = (e) => {
|
|
680
|
+
const t = [];
|
|
681
|
+
for (const s of this.blocInstanceMap.values())
|
|
682
|
+
e(s) && t.push(s);
|
|
683
|
+
for (const s of this.isolatedBlocMap.values())
|
|
684
|
+
for (const i of s)
|
|
685
|
+
e(i) && t.push(i);
|
|
686
|
+
t.forEach((s) => s.dispose());
|
|
687
|
+
};
|
|
688
|
+
static get disposeBlocs() {
|
|
689
|
+
return o.instance.disposeBlocs;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Gets memory usage statistics for debugging
|
|
693
|
+
*/
|
|
694
|
+
getMemoryStats = () => ({
|
|
695
|
+
totalBlocs: this.uidRegistry.size,
|
|
696
|
+
registeredBlocs: this.blocInstanceMap.size,
|
|
697
|
+
isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
|
|
698
|
+
(e, t) => e + t.length,
|
|
699
|
+
0
|
|
700
|
+
),
|
|
701
|
+
keepAliveBlocs: this.keepAliveBlocs.size,
|
|
702
|
+
isolatedBlocTypes: this.isolatedBlocMap.size
|
|
703
|
+
});
|
|
704
|
+
static get getMemoryStats() {
|
|
705
|
+
return o.instance.getMemoryStats;
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Validates subscription references and cleans up orphaned blocs
|
|
709
|
+
*/
|
|
710
|
+
validateConsumers = () => {
|
|
711
|
+
for (const e of this.uidRegistry.values())
|
|
712
|
+
e.subscriptionCount === 0 && !e._keepAlive && e._disposalState === u.ACTIVE && setTimeout(() => {
|
|
713
|
+
e.subscriptionCount === 0 && !e._keepAlive && e._disposalState === u.ACTIVE && this.disposeBloc(e);
|
|
714
|
+
}, 1e3);
|
|
715
|
+
};
|
|
716
|
+
static get validateConsumers() {
|
|
717
|
+
return o.instance.validateConsumers;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Bootstrap the Blac instance and all plugins
|
|
721
|
+
*/
|
|
722
|
+
bootstrap() {
|
|
723
|
+
this.plugins.bootstrap();
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Shutdown the Blac instance and all plugins
|
|
727
|
+
*/
|
|
728
|
+
shutdown() {
|
|
729
|
+
this.plugins.shutdown();
|
|
730
|
+
for (const e of this.blocInstanceMap.values())
|
|
731
|
+
e._keepAlive || this.disposeBloc(e);
|
|
732
|
+
for (const e of this.isolatedBlocMap.values())
|
|
733
|
+
for (const t of e)
|
|
734
|
+
t._keepAlive || this.disposeBloc(t);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
function A() {
|
|
738
|
+
return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(r) {
|
|
739
|
+
const e = Math.random() * 16 | 0;
|
|
740
|
+
return (r === "x" ? e : e & 3 | 8).toString(16);
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
const x = {
|
|
744
|
+
fatal: (r, e, t, s) => {
|
|
745
|
+
const i = new m(
|
|
746
|
+
r,
|
|
747
|
+
e,
|
|
748
|
+
y.FATAL,
|
|
749
|
+
t,
|
|
750
|
+
s
|
|
751
|
+
);
|
|
752
|
+
throw f.getInstance().handle(i), i;
|
|
753
|
+
},
|
|
754
|
+
error: (r, e, t, s) => {
|
|
755
|
+
const i = new m(
|
|
756
|
+
r,
|
|
757
|
+
e,
|
|
758
|
+
y.ERROR,
|
|
759
|
+
t,
|
|
760
|
+
s
|
|
761
|
+
);
|
|
762
|
+
f.getInstance().handle(i);
|
|
763
|
+
},
|
|
764
|
+
warn: (r, e, t, s) => {
|
|
765
|
+
const i = new m(
|
|
766
|
+
r,
|
|
767
|
+
e,
|
|
768
|
+
y.WARNING,
|
|
769
|
+
t,
|
|
770
|
+
s
|
|
771
|
+
);
|
|
772
|
+
f.getInstance().handle(i);
|
|
773
|
+
},
|
|
774
|
+
info: (r, e, t) => {
|
|
775
|
+
const s = new m(r, e, y.INFO, t);
|
|
776
|
+
f.getInstance().handle(s);
|
|
777
|
+
},
|
|
778
|
+
/**
|
|
779
|
+
* Wraps a function to catch and handle errors
|
|
780
|
+
*/
|
|
781
|
+
wrap: (r, e, t, s = y.ERROR) => {
|
|
782
|
+
try {
|
|
783
|
+
return r();
|
|
784
|
+
} catch (i) {
|
|
785
|
+
const n = i instanceof Error ? i.message : String(i), a = new m(n, e, s, t, i);
|
|
786
|
+
f.getInstance().handle(a);
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
/**
|
|
791
|
+
* Wraps an async function to catch and handle errors
|
|
792
|
+
*/
|
|
793
|
+
wrapAsync: async (r, e, t, s = y.ERROR) => {
|
|
794
|
+
try {
|
|
795
|
+
return await r();
|
|
796
|
+
} catch (i) {
|
|
797
|
+
const n = i instanceof Error ? i.message : String(i), a = new m(n, e, s, t, i);
|
|
798
|
+
f.getInstance().handle(a);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
class w {
|
|
804
|
+
plugins = /* @__PURE__ */ new Map();
|
|
805
|
+
executionOrder = [];
|
|
806
|
+
attached = !1;
|
|
807
|
+
/**
|
|
808
|
+
* Add a bloc plugin
|
|
809
|
+
*/
|
|
810
|
+
add(e) {
|
|
811
|
+
if (this.plugins.has(e.name))
|
|
812
|
+
throw new Error(`Plugin '${e.name}' is already registered`);
|
|
813
|
+
e.capabilities && this.validateCapabilities(e), this.plugins.set(e.name, e), this.executionOrder.push(e.name);
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Remove a bloc plugin
|
|
817
|
+
*/
|
|
818
|
+
remove(e) {
|
|
819
|
+
const t = this.plugins.get(e);
|
|
820
|
+
return t ? (this.attached && t.onDetach && x.wrap(() => t.onDetach(), v.PLUGIN, {
|
|
821
|
+
pluginName: e,
|
|
822
|
+
operation: "onDetach"
|
|
823
|
+
}), this.plugins.delete(e), this.executionOrder = this.executionOrder.filter(
|
|
824
|
+
(s) => s !== e
|
|
825
|
+
), !0) : !1;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Get a plugin by name
|
|
829
|
+
*/
|
|
830
|
+
get(e) {
|
|
831
|
+
return this.plugins.get(e);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Get all plugins in execution order
|
|
835
|
+
*/
|
|
836
|
+
getAll() {
|
|
837
|
+
return this.executionOrder.map((e) => this.plugins.get(e));
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Clear all plugins
|
|
841
|
+
*/
|
|
842
|
+
clear() {
|
|
843
|
+
if (this.attached)
|
|
844
|
+
for (const e of this.getAll())
|
|
845
|
+
e.onDetach && x.wrap(() => e.onDetach(), v.PLUGIN, {
|
|
846
|
+
pluginName: e.name,
|
|
847
|
+
operation: "onDetach"
|
|
848
|
+
});
|
|
849
|
+
this.plugins.clear(), this.executionOrder = [], this.attached = !1;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Attach all plugins to a bloc
|
|
853
|
+
*/
|
|
854
|
+
attach(e) {
|
|
855
|
+
if (this.attached)
|
|
856
|
+
throw new Error("Plugins are already attached");
|
|
857
|
+
for (const t of this.getAll())
|
|
858
|
+
if (t.onAttach)
|
|
859
|
+
try {
|
|
860
|
+
t.onAttach(e);
|
|
861
|
+
} catch (s) {
|
|
862
|
+
console.error(`Plugin '${t.name}' error in onAttach:`, s), this.remove(t.name);
|
|
863
|
+
}
|
|
864
|
+
this.attached = !0;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Transform state through all plugins
|
|
868
|
+
*/
|
|
869
|
+
transformState(e, t) {
|
|
870
|
+
let s = t;
|
|
871
|
+
for (const i of this.getAll())
|
|
872
|
+
if (i.transformState && this.canTransformState(i))
|
|
873
|
+
try {
|
|
874
|
+
s = i.transformState(
|
|
875
|
+
e,
|
|
876
|
+
s
|
|
877
|
+
);
|
|
878
|
+
} catch (n) {
|
|
879
|
+
console.error(
|
|
880
|
+
`Plugin '${i.name}' error in transformState:`,
|
|
881
|
+
n
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
return s;
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Transform event through all plugins
|
|
888
|
+
*/
|
|
889
|
+
transformEvent(e) {
|
|
890
|
+
let t = e;
|
|
891
|
+
for (const s of this.getAll()) {
|
|
892
|
+
if (t === null) break;
|
|
893
|
+
if (s.transformEvent && this.canInterceptEvents(s))
|
|
894
|
+
try {
|
|
895
|
+
t = s.transformEvent(t);
|
|
896
|
+
} catch (i) {
|
|
897
|
+
console.error(
|
|
898
|
+
`Plugin '${s.name}' error in transformEvent:`,
|
|
899
|
+
i
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return t;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Notify plugins of state change
|
|
907
|
+
*/
|
|
908
|
+
notifyStateChange(e, t) {
|
|
909
|
+
for (const s of this.getAll())
|
|
910
|
+
if (s.onStateChange && this.canReadState(s))
|
|
911
|
+
try {
|
|
912
|
+
s.onStateChange(e, t);
|
|
913
|
+
} catch (i) {
|
|
914
|
+
console.error(
|
|
915
|
+
`Plugin '${s.name}' error in onStateChange:`,
|
|
916
|
+
i
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Notify plugins of event
|
|
922
|
+
*/
|
|
923
|
+
notifyEvent(e) {
|
|
924
|
+
for (const t of this.getAll())
|
|
925
|
+
if (t.onEvent && this.canReadState(t))
|
|
926
|
+
try {
|
|
927
|
+
t.onEvent(e);
|
|
928
|
+
} catch (s) {
|
|
929
|
+
console.error(`Plugin '${t.name}' error in onEvent:`, s);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Notify plugins of error
|
|
934
|
+
*/
|
|
935
|
+
notifyError(e, t) {
|
|
936
|
+
for (const s of this.getAll())
|
|
937
|
+
if (s.onError)
|
|
938
|
+
try {
|
|
939
|
+
s.onError(e, t);
|
|
940
|
+
} catch (i) {
|
|
941
|
+
console.error(`Plugin '${s.name}' error in onError:`, i);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
validateCapabilities(e) {
|
|
945
|
+
const t = e.capabilities;
|
|
946
|
+
if (t.transformState && !t.readState)
|
|
947
|
+
throw new Error(
|
|
948
|
+
`Plugin '${e.name}': transformState requires readState capability`
|
|
949
|
+
);
|
|
950
|
+
if (t.interceptEvents && !t.readState)
|
|
951
|
+
throw new Error(
|
|
952
|
+
`Plugin '${e.name}': interceptEvents requires readState capability`
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
canReadState(e) {
|
|
956
|
+
return !e.capabilities || e.capabilities.readState !== !1;
|
|
957
|
+
}
|
|
958
|
+
canTransformState(e) {
|
|
959
|
+
return !e.capabilities || e.capabilities.transformState === !0;
|
|
960
|
+
}
|
|
961
|
+
canInterceptEvents(e) {
|
|
962
|
+
return !e.capabilities || e.capabilities.interceptEvents === !0;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
class E {
|
|
966
|
+
constructor(e) {
|
|
967
|
+
this.bloc = e;
|
|
968
|
+
}
|
|
969
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
970
|
+
pathToSubscriptions = /* @__PURE__ */ new Map();
|
|
971
|
+
weakRefCleanupScheduled = !1;
|
|
972
|
+
totalNotifications = 0;
|
|
973
|
+
/**
|
|
974
|
+
* Subscribe to state changes
|
|
975
|
+
*/
|
|
976
|
+
subscribe(e) {
|
|
977
|
+
const t = `${e.type}-${A()}`, s = {
|
|
978
|
+
id: t,
|
|
979
|
+
type: e.type,
|
|
980
|
+
selector: e.selector,
|
|
981
|
+
equalityFn: e.equalityFn || Object.is,
|
|
982
|
+
notify: e.notify,
|
|
983
|
+
priority: e.priority ?? 0,
|
|
984
|
+
weakRef: e.weakRef,
|
|
985
|
+
dependencies: /* @__PURE__ */ new Set(),
|
|
986
|
+
metadata: {
|
|
987
|
+
lastNotified: Date.now(),
|
|
988
|
+
hasRendered: !1,
|
|
989
|
+
accessCount: 0,
|
|
990
|
+
firstAccessTime: Date.now()
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
if (s.selector)
|
|
994
|
+
try {
|
|
995
|
+
s.lastValue = s.selector(
|
|
996
|
+
this.bloc.state,
|
|
997
|
+
this.bloc
|
|
998
|
+
);
|
|
999
|
+
} catch (i) {
|
|
1000
|
+
o.error(`SubscriptionManager: Error in selector for ${t}:`, i);
|
|
1001
|
+
}
|
|
1002
|
+
return this.subscriptions.set(t, s), o.log(
|
|
1003
|
+
`[${this.bloc._name}:${this.bloc._id}] Subscription added: ${t}. Total: ${this.subscriptions.size}`
|
|
1004
|
+
), this.bloc._cancelDisposalIfRequested(), () => this.unsubscribe(t);
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Unsubscribe by ID
|
|
1008
|
+
*/
|
|
1009
|
+
unsubscribe(e) {
|
|
1010
|
+
const t = this.subscriptions.get(e);
|
|
1011
|
+
if (t) {
|
|
1012
|
+
if (t.dependencies)
|
|
1013
|
+
for (const s of t.dependencies) {
|
|
1014
|
+
const i = this.pathToSubscriptions.get(s);
|
|
1015
|
+
i && (i.delete(e), i.size === 0 && this.pathToSubscriptions.delete(s));
|
|
1016
|
+
}
|
|
1017
|
+
this.subscriptions.delete(e), o.log(
|
|
1018
|
+
`[${this.bloc._name}:${this.bloc._id}] Subscription removed: ${e}. Remaining: ${this.subscriptions.size}`
|
|
1019
|
+
), this.bloc.checkDisposal();
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Notify all subscriptions of state change
|
|
1024
|
+
*/
|
|
1025
|
+
notify(e, t, s) {
|
|
1026
|
+
this.cleanupDeadReferences();
|
|
1027
|
+
const i = Array.from(this.subscriptions.values()).sort(
|
|
1028
|
+
(n, a) => (a.priority ?? 0) - (n.priority ?? 0)
|
|
1029
|
+
);
|
|
1030
|
+
for (const n of i) {
|
|
1031
|
+
if (n.weakRef && !n.weakRef.deref()) {
|
|
1032
|
+
this.scheduleWeakRefCleanup();
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
let a = !1, c, l;
|
|
1036
|
+
if (n.selector)
|
|
1037
|
+
try {
|
|
1038
|
+
c = n.selector(e, this.bloc), l = n.lastValue, a = !(n.equalityFn || Object.is)(l, c), a && (n.lastValue = c);
|
|
1039
|
+
} catch (h) {
|
|
1040
|
+
o.error(
|
|
1041
|
+
`SubscriptionManager: Error in selector for ${n.id}:`,
|
|
1042
|
+
h
|
|
1043
|
+
);
|
|
1044
|
+
continue;
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
if (n.dependencies && n.dependencies.size > 0) {
|
|
1048
|
+
const h = this.getChangedPaths(t, e);
|
|
1049
|
+
a = this.shouldNotifyForPaths(
|
|
1050
|
+
n.id,
|
|
1051
|
+
h
|
|
1052
|
+
), o.config.logLevel === "debug" && (o.log(
|
|
1053
|
+
`[SubscriptionManager] Subscription ${n.id} dependencies:`,
|
|
1054
|
+
Array.from(n.dependencies)
|
|
1055
|
+
), o.log(
|
|
1056
|
+
"[SubscriptionManager] Changed paths:",
|
|
1057
|
+
Array.from(h)
|
|
1058
|
+
), o.log("[SubscriptionManager] Should notify:", a));
|
|
1059
|
+
} else
|
|
1060
|
+
a = !0;
|
|
1061
|
+
c = e, l = t;
|
|
1062
|
+
}
|
|
1063
|
+
if (a)
|
|
1064
|
+
try {
|
|
1065
|
+
n.notify(c, l, s), this.totalNotifications++, n.metadata && (n.metadata.lastNotified = Date.now(), n.metadata.hasRendered = !0);
|
|
1066
|
+
} catch (h) {
|
|
1067
|
+
o.error(
|
|
1068
|
+
`SubscriptionManager: Error in notify for ${n.id}:`,
|
|
1069
|
+
h
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Track a path access for a subscription
|
|
1076
|
+
*/
|
|
1077
|
+
trackAccess(e, t, s) {
|
|
1078
|
+
const i = this.subscriptions.get(e);
|
|
1079
|
+
if (!i) return;
|
|
1080
|
+
i.dependencies || (i.dependencies = /* @__PURE__ */ new Set()), i.dependencies.add(t);
|
|
1081
|
+
let n = this.pathToSubscriptions.get(t);
|
|
1082
|
+
n || (n = /* @__PURE__ */ new Set(), this.pathToSubscriptions.set(t, n)), n.add(e), i.metadata && (i.metadata.accessCount = (i.metadata.accessCount || 0) + 1, i.metadata.lastAccessTime = Date.now());
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Get the paths that changed between two states
|
|
1086
|
+
*/
|
|
1087
|
+
getChangedPaths(e, t, s = "") {
|
|
1088
|
+
const i = /* @__PURE__ */ new Set();
|
|
1089
|
+
if (e === t) return i;
|
|
1090
|
+
if (typeof e != "object" || typeof t != "object" || e === null || t === null)
|
|
1091
|
+
return s && i.add(s), i;
|
|
1092
|
+
const n = /* @__PURE__ */ new Set([
|
|
1093
|
+
...Object.keys(e),
|
|
1094
|
+
...Object.keys(t)
|
|
1095
|
+
]);
|
|
1096
|
+
for (const a of n) {
|
|
1097
|
+
const c = s ? `${s}.${a}` : a, l = e[a], h = t[a];
|
|
1098
|
+
l !== h && (i.add(c), typeof l == "object" && typeof h == "object" && l !== null && h !== null && this.getChangedPaths(
|
|
1099
|
+
l,
|
|
1100
|
+
h,
|
|
1101
|
+
c
|
|
1102
|
+
).forEach((S) => i.add(S)));
|
|
1103
|
+
}
|
|
1104
|
+
return i;
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Check if a subscription should be notified based on changed paths
|
|
1108
|
+
*/
|
|
1109
|
+
shouldNotifyForPaths(e, t) {
|
|
1110
|
+
const s = this.subscriptions.get(e);
|
|
1111
|
+
if (!s || !s.dependencies) return !0;
|
|
1112
|
+
for (const i of s.dependencies) {
|
|
1113
|
+
if (i.startsWith("_class.")) {
|
|
1114
|
+
if (t.size > 0)
|
|
1115
|
+
return !0;
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1118
|
+
if (t.has(i)) return !0;
|
|
1119
|
+
for (const n of t)
|
|
1120
|
+
if (n.startsWith(i + ".") || i.startsWith(n + "."))
|
|
1121
|
+
return !0;
|
|
1122
|
+
}
|
|
1123
|
+
return !1;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Get statistics about subscriptions
|
|
1127
|
+
*/
|
|
1128
|
+
getStats() {
|
|
1129
|
+
let e = 0, t = 0;
|
|
1130
|
+
for (const s of this.subscriptions.values())
|
|
1131
|
+
s.type === "consumer" ? e++ : t++;
|
|
1132
|
+
return {
|
|
1133
|
+
activeSubscriptions: this.subscriptions.size,
|
|
1134
|
+
consumerCount: e,
|
|
1135
|
+
observerCount: t,
|
|
1136
|
+
totalNotifications: this.totalNotifications,
|
|
1137
|
+
trackedDependencies: this.pathToSubscriptions.size
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Clear all subscriptions
|
|
1142
|
+
*/
|
|
1143
|
+
clear() {
|
|
1144
|
+
this.subscriptions.clear(), this.pathToSubscriptions.clear();
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Get subscription by ID
|
|
1148
|
+
*/
|
|
1149
|
+
getSubscription(e) {
|
|
1150
|
+
return this.subscriptions.get(e);
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Check if there are any active subscriptions
|
|
1154
|
+
*/
|
|
1155
|
+
get hasSubscriptions() {
|
|
1156
|
+
return this.subscriptions.size > 0;
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Get count of active subscriptions
|
|
1160
|
+
*/
|
|
1161
|
+
get size() {
|
|
1162
|
+
return this.subscriptions.size;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Clean up subscriptions with dead weak references
|
|
1166
|
+
*/
|
|
1167
|
+
cleanupDeadReferences() {
|
|
1168
|
+
if (!this.weakRefCleanupScheduled) return;
|
|
1169
|
+
const e = [];
|
|
1170
|
+
for (const [t, s] of this.subscriptions)
|
|
1171
|
+
s.weakRef && !s.weakRef.deref() && e.push(t);
|
|
1172
|
+
for (const t of e)
|
|
1173
|
+
this.unsubscribe(t);
|
|
1174
|
+
this.weakRefCleanupScheduled = !1;
|
|
1175
|
+
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Schedule weak reference cleanup for next tick
|
|
1178
|
+
*/
|
|
1179
|
+
scheduleWeakRefCleanup() {
|
|
1180
|
+
this.weakRefCleanupScheduled || (this.weakRefCleanupScheduled = !0, queueMicrotask(() => this.cleanupDeadReferences()));
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
class D {
|
|
1184
|
+
pendingUpdates = [];
|
|
1185
|
+
isBatching = !1;
|
|
1186
|
+
/**
|
|
1187
|
+
* Execute a callback with batched updates
|
|
1188
|
+
*/
|
|
1189
|
+
batchUpdates(e, t) {
|
|
1190
|
+
if (this.isBatching) {
|
|
1191
|
+
e();
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
this.isBatching = !0, this.pendingUpdates = [];
|
|
1195
|
+
try {
|
|
1196
|
+
if (e(), this.pendingUpdates.length > 0) {
|
|
1197
|
+
const s = this.pendingUpdates[this.pendingUpdates.length - 1];
|
|
1198
|
+
t(s);
|
|
1199
|
+
}
|
|
1200
|
+
} finally {
|
|
1201
|
+
this.isBatching = !1, this.pendingUpdates = [];
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Add an update to the batch
|
|
1206
|
+
*/
|
|
1207
|
+
addUpdate(e) {
|
|
1208
|
+
this.isBatching && this.pendingUpdates.push(e);
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Check if currently batching
|
|
1212
|
+
*/
|
|
1213
|
+
get isCurrentlyBatching() {
|
|
1214
|
+
return this.isBatching;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
class C {
|
|
1218
|
+
uid = A();
|
|
1219
|
+
blacInstance;
|
|
1220
|
+
static isolated = !1;
|
|
1221
|
+
get isIsolated() {
|
|
1222
|
+
return this._isolated;
|
|
1223
|
+
}
|
|
1224
|
+
static keepAlive = !1;
|
|
1225
|
+
get isKeepAlive() {
|
|
1226
|
+
return this._keepAlive;
|
|
1227
|
+
}
|
|
1228
|
+
_isolated = !1;
|
|
1229
|
+
_id;
|
|
1230
|
+
_instanceRef;
|
|
1231
|
+
_name;
|
|
1232
|
+
/**
|
|
1233
|
+
* Unified subscription manager for all state notifications
|
|
1234
|
+
*/
|
|
1235
|
+
_subscriptionManager;
|
|
1236
|
+
_state;
|
|
1237
|
+
_lifecycleManager = new B();
|
|
1238
|
+
_batchingManager = new D();
|
|
1239
|
+
_keepAlive = !1;
|
|
1240
|
+
lastUpdate;
|
|
1241
|
+
_plugins = new w();
|
|
1242
|
+
onDispose;
|
|
1243
|
+
/**
|
|
1244
|
+
* Creates a new BlocBase instance with unified subscription management
|
|
1245
|
+
*/
|
|
1246
|
+
constructor(e) {
|
|
1247
|
+
this._state = e, this._id = this.constructor.name, this._name = this.constructor.name, this._subscriptionManager = new E(this);
|
|
1248
|
+
const t = this.constructor;
|
|
1249
|
+
if (this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1, this._plugins = new w(), t.plugins && Array.isArray(t.plugins))
|
|
1250
|
+
for (const s of t.plugins)
|
|
1251
|
+
this._plugins.add(s);
|
|
1252
|
+
this._plugins.attach(this);
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Returns the current state
|
|
1256
|
+
*/
|
|
1257
|
+
get state() {
|
|
1258
|
+
return this._lifecycleManager.isDisposed ? this._state : this._state;
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Subscribe to all state changes
|
|
1262
|
+
*/
|
|
1263
|
+
subscribe(e) {
|
|
1264
|
+
return this._subscriptionManager.subscribe({
|
|
1265
|
+
type: "observer",
|
|
1266
|
+
notify: (t) => e(t)
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
/**
|
|
1270
|
+
* Subscribe with a selector for optimized updates
|
|
1271
|
+
*/
|
|
1272
|
+
subscribeWithSelector(e, t, s) {
|
|
1273
|
+
return this._subscriptionManager.subscribe({
|
|
1274
|
+
type: "consumer",
|
|
1275
|
+
selector: e,
|
|
1276
|
+
equalityFn: s,
|
|
1277
|
+
notify: (i) => t(i)
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Subscribe with React component reference for automatic cleanup
|
|
1282
|
+
*/
|
|
1283
|
+
subscribeComponent(e, t) {
|
|
1284
|
+
return this._subscriptionManager.subscribe({
|
|
1285
|
+
type: "consumer",
|
|
1286
|
+
weakRef: e,
|
|
1287
|
+
notify: t
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* Get current subscription count
|
|
1292
|
+
*/
|
|
1293
|
+
get subscriptionCount() {
|
|
1294
|
+
return this._subscriptionManager.size;
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Track property access for a subscription
|
|
1298
|
+
*/
|
|
1299
|
+
trackAccess(e, t, s) {
|
|
1300
|
+
this._subscriptionManager.trackAccess(e, t, s);
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Emit a new state
|
|
1304
|
+
*/
|
|
1305
|
+
emit(e, t) {
|
|
1306
|
+
this._pushState(e, this._state, t);
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Internal state push method used by Bloc
|
|
1310
|
+
*/
|
|
1311
|
+
_pushState(e, t, s) {
|
|
1312
|
+
if (this._lifecycleManager.currentState !== u.ACTIVE) {
|
|
1313
|
+
this.blacInstance?.error(
|
|
1314
|
+
`[${this._name}:${this._id}] Attempted state update on ${this._lifecycleManager.currentState} bloc. Update ignored.`
|
|
1315
|
+
);
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
if (e === void 0)
|
|
1319
|
+
return;
|
|
1320
|
+
this._state = e;
|
|
1321
|
+
const i = this._plugins.transformState(
|
|
1322
|
+
t,
|
|
1323
|
+
e
|
|
1324
|
+
);
|
|
1325
|
+
if (this._state = i, this._plugins.notifyStateChange(t, i), this.blacInstance?.plugins.notifyStateChanged(
|
|
1326
|
+
this,
|
|
1327
|
+
t,
|
|
1328
|
+
i
|
|
1329
|
+
), this._batchingManager.isCurrentlyBatching) {
|
|
1330
|
+
this._batchingManager.addUpdate({
|
|
1331
|
+
newState: i,
|
|
1332
|
+
oldState: t,
|
|
1333
|
+
action: s
|
|
1334
|
+
});
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
this._subscriptionManager.notify(i, t, s), this.lastUpdate = Date.now();
|
|
1338
|
+
}
|
|
1339
|
+
_batchUpdates(e) {
|
|
1340
|
+
this._batchingManager.batchUpdates(e, (t) => {
|
|
1341
|
+
this._subscriptionManager.notify(
|
|
1342
|
+
t.newState,
|
|
1343
|
+
t.oldState,
|
|
1344
|
+
t.action
|
|
1345
|
+
);
|
|
1346
|
+
});
|
|
732
1347
|
}
|
|
733
1348
|
/**
|
|
734
|
-
*
|
|
735
|
-
* @param blocClassName - The name of the bloc class
|
|
736
|
-
* @param id - The instance ID
|
|
737
|
-
* @returns A unique key string in the format "className:id"
|
|
1349
|
+
* Add a plugin
|
|
738
1350
|
*/
|
|
739
|
-
|
|
740
|
-
|
|
1351
|
+
addPlugin(e) {
|
|
1352
|
+
if (this._plugins.add(e), this._plugins.attached && e.onAttach)
|
|
1353
|
+
try {
|
|
1354
|
+
e.onAttach(this);
|
|
1355
|
+
} catch (t) {
|
|
1356
|
+
console.error(`Plugin '${e.name}' error in onAttach:`, t);
|
|
1357
|
+
}
|
|
741
1358
|
}
|
|
742
1359
|
/**
|
|
743
|
-
*
|
|
744
|
-
* @param bloc - The bloc instance to unregister
|
|
1360
|
+
* Remove a plugin
|
|
745
1361
|
*/
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
|
|
1362
|
+
removePlugin(e) {
|
|
1363
|
+
this._plugins.remove(e.name);
|
|
749
1364
|
}
|
|
750
1365
|
/**
|
|
751
|
-
*
|
|
752
|
-
* @param bloc - The bloc instance to register
|
|
1366
|
+
* Get all plugins
|
|
753
1367
|
*/
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
|
|
1368
|
+
get plugins() {
|
|
1369
|
+
return this._plugins.getAll();
|
|
757
1370
|
}
|
|
758
1371
|
/**
|
|
759
|
-
*
|
|
760
|
-
* @param blocClass - The bloc class to search for
|
|
761
|
-
* @param id - The instance ID
|
|
762
|
-
* @returns The found bloc instance or undefined if not found
|
|
1372
|
+
* Disposal management
|
|
763
1373
|
*/
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const n = this.createBlocInstanceMapKey(e.name, t);
|
|
767
|
-
return this.blocInstanceMap.get(n);
|
|
1374
|
+
get isDisposed() {
|
|
1375
|
+
return this._lifecycleManager.isDisposed;
|
|
768
1376
|
}
|
|
769
1377
|
/**
|
|
770
|
-
*
|
|
771
|
-
* @param bloc - The isolated bloc instance to register
|
|
1378
|
+
* Atomic state transition for disposal
|
|
772
1379
|
*/
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
1380
|
+
_atomicStateTransition(e, t) {
|
|
1381
|
+
return this._lifecycleManager.atomicStateTransition(
|
|
1382
|
+
e,
|
|
1383
|
+
t
|
|
1384
|
+
);
|
|
776
1385
|
}
|
|
777
1386
|
/**
|
|
778
|
-
*
|
|
779
|
-
* @param bloc - The isolated bloc instance to unregister
|
|
1387
|
+
* Dispose the bloc and clean up resources
|
|
780
1388
|
*/
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1389
|
+
async dispose() {
|
|
1390
|
+
if (!this._lifecycleManager.atomicStateTransition(
|
|
1391
|
+
u.ACTIVE,
|
|
1392
|
+
u.DISPOSING
|
|
1393
|
+
).success)
|
|
1394
|
+
if (this._lifecycleManager.currentState === u.DISPOSAL_REQUESTED)
|
|
1395
|
+
this._lifecycleManager.atomicStateTransition(
|
|
1396
|
+
u.DISPOSAL_REQUESTED,
|
|
1397
|
+
u.DISPOSING
|
|
1398
|
+
);
|
|
1399
|
+
else
|
|
1400
|
+
return;
|
|
1401
|
+
try {
|
|
1402
|
+
this._subscriptionManager.clear(), this.onDispose && this.onDispose();
|
|
1403
|
+
for (const s of this._plugins.getAll())
|
|
1404
|
+
try {
|
|
1405
|
+
"onDispose" in s && typeof s.onDispose == "function" && s.onDispose(this);
|
|
1406
|
+
} catch (i) {
|
|
1407
|
+
console.error("Plugin disposal error:", i);
|
|
1408
|
+
}
|
|
1409
|
+
const t = this._lifecycleManager.getDisposalHandler();
|
|
1410
|
+
t && t(this);
|
|
1411
|
+
} finally {
|
|
1412
|
+
this._lifecycleManager.atomicStateTransition(
|
|
1413
|
+
u.DISPOSING,
|
|
1414
|
+
u.DISPOSED
|
|
1415
|
+
);
|
|
787
1416
|
}
|
|
788
|
-
const r = this.isolatedBlocIndex.delete(e.uid);
|
|
789
|
-
this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), n !== r && this.warn(
|
|
790
|
-
`[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${n}, Index removal: ${r}`
|
|
791
|
-
);
|
|
792
1417
|
}
|
|
793
1418
|
/**
|
|
794
|
-
*
|
|
1419
|
+
* Schedule disposal when no subscriptions remain
|
|
795
1420
|
*/
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
1421
|
+
_scheduleDisposal() {
|
|
1422
|
+
this._subscriptionManager.size === 0 && !this._keepAlive && this._lifecycleManager.scheduleDisposal(
|
|
1423
|
+
16,
|
|
1424
|
+
() => this._subscriptionManager.size === 0 && !this._keepAlive,
|
|
1425
|
+
() => this.dispose()
|
|
1426
|
+
);
|
|
800
1427
|
}
|
|
801
1428
|
/**
|
|
802
|
-
*
|
|
1429
|
+
* Set disposal handler
|
|
803
1430
|
*/
|
|
804
|
-
|
|
805
|
-
|
|
1431
|
+
setDisposalHandler(e) {
|
|
1432
|
+
this._lifecycleManager.setDisposalHandler(
|
|
1433
|
+
e
|
|
1434
|
+
);
|
|
806
1435
|
}
|
|
807
1436
|
/**
|
|
808
|
-
*
|
|
809
|
-
* @param blocClass - The bloc class to instantiate
|
|
810
|
-
* @param id - The instance ID
|
|
811
|
-
* @param props - Properties to pass to the bloc constructor
|
|
812
|
-
* @param instanceRef - Optional reference string for the instance
|
|
813
|
-
* @returns The newly created bloc instance
|
|
1437
|
+
* Check if disposal should be scheduled (called by subscription manager)
|
|
814
1438
|
*/
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
return o._instanceRef = r, o.props = n || null, o._updateId(t), o._setDisposalHandler((a) => this.disposeBloc(a)), o.isIsolated ? (this.registerIsolatedBlocInstance(o), o) : (this.registerBlocInstance(o), o);
|
|
818
|
-
}
|
|
819
|
-
static get activateBloc() {
|
|
820
|
-
return l.instance.activateBloc;
|
|
1439
|
+
checkDisposal() {
|
|
1440
|
+
this._subscriptionManager.size === 0 && !this._keepAlive && this._lifecycleManager.currentState === u.ACTIVE && this._scheduleDisposal();
|
|
821
1441
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
return l.instance.getMemoryStats;
|
|
836
|
-
}
|
|
837
|
-
static get validateConsumers() {
|
|
838
|
-
return l.instance.validateConsumers;
|
|
839
|
-
}
|
|
840
|
-
};
|
|
841
|
-
/** Private static configuration */
|
|
842
|
-
i(l, "_config", {
|
|
843
|
-
exposeBlacInstance: !1,
|
|
844
|
-
proxyDependencyTracking: !0
|
|
845
|
-
}), /** Flag to enable/disable logging */
|
|
846
|
-
i(l, "enableLog", !1), i(l, "logLevel", "warn"), i(l, "logSpy", null), i(l, "resetInstance", () => {
|
|
847
|
-
S.resetInstance();
|
|
848
|
-
});
|
|
849
|
-
let d = l;
|
|
850
|
-
class U extends x {
|
|
851
|
-
constructor() {
|
|
852
|
-
super(...arguments);
|
|
853
|
-
i(this, "eventHandlers", /* @__PURE__ */ new Map());
|
|
854
|
-
/**
|
|
855
|
-
* @internal
|
|
856
|
-
* Event queue to ensure sequential processing of async events
|
|
857
|
-
*/
|
|
858
|
-
i(this, "_eventQueue", []);
|
|
859
|
-
/**
|
|
860
|
-
* @internal
|
|
861
|
-
* Flag indicating if an event is currently being processed
|
|
862
|
-
*/
|
|
863
|
-
i(this, "_isProcessingEvent", !1);
|
|
864
|
-
/**
|
|
865
|
-
* Dispatches an action/event to the Bloc.
|
|
866
|
-
* Events are queued and processed sequentially to prevent race conditions.
|
|
867
|
-
* @param action The action/event instance to be processed.
|
|
868
|
-
*/
|
|
869
|
-
i(this, "add", async (t) => {
|
|
870
|
-
this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
|
|
871
|
-
});
|
|
1442
|
+
/**
|
|
1443
|
+
* Cancel disposal if bloc is in disposal_requested state
|
|
1444
|
+
*/
|
|
1445
|
+
_cancelDisposalIfRequested() {
|
|
1446
|
+
this.blacInstance?.log(
|
|
1447
|
+
`[${this._name}:${this._id}] _cancelDisposalIfRequested called. Current state: ${this._lifecycleManager.currentState}`
|
|
1448
|
+
), this._lifecycleManager.cancelDisposal() ? this.blacInstance?.log(
|
|
1449
|
+
`[${this._name}:${this._id}] Disposal cancelled - new subscription added`
|
|
1450
|
+
) : this._lifecycleManager.currentState === u.DISPOSAL_REQUESTED ? this.blacInstance?.warn(
|
|
1451
|
+
`[${this._name}:${this._id}] Failed to cancel disposal. Current state: ${this._lifecycleManager.currentState}`
|
|
1452
|
+
) : this._lifecycleManager.isDisposed && this.blacInstance?.error(
|
|
1453
|
+
`[${this._name}:${this._id}] Cannot cancel disposal - bloc is already disposed`
|
|
1454
|
+
);
|
|
872
1455
|
}
|
|
1456
|
+
}
|
|
1457
|
+
class R extends C {
|
|
1458
|
+
eventHandlers = /* @__PURE__ */ new Map();
|
|
1459
|
+
/**
|
|
1460
|
+
* @internal
|
|
1461
|
+
* Event queue to ensure sequential processing of async events
|
|
1462
|
+
*/
|
|
1463
|
+
_eventQueue = [];
|
|
1464
|
+
/**
|
|
1465
|
+
* @internal
|
|
1466
|
+
* Flag indicating if an event is currently being processed
|
|
1467
|
+
*/
|
|
1468
|
+
_isProcessingEvent = !1;
|
|
873
1469
|
/**
|
|
874
1470
|
* Registers an event handler for a specific event type.
|
|
875
1471
|
* This method is typically called in the constructor of a derived Bloc class.
|
|
@@ -877,14 +1473,35 @@ class U extends x {
|
|
|
877
1473
|
* @param handler A function that processes the event and can emit new states.
|
|
878
1474
|
* The 'event' parameter in the handler will be typed to the specific eventConstructor.
|
|
879
1475
|
*/
|
|
880
|
-
on(
|
|
881
|
-
this.eventHandlers.has(
|
|
882
|
-
`[Bloc ${this._name}:${String(this._id)}] Handler for event '${
|
|
1476
|
+
on(e, t) {
|
|
1477
|
+
this.eventHandlers.has(e) && o.warn(
|
|
1478
|
+
`[Bloc ${this._name}:${String(this._id)}] Handler for event '${e.name}' already registered. It will be overwritten.`
|
|
883
1479
|
), this.eventHandlers.set(
|
|
884
|
-
|
|
885
|
-
|
|
1480
|
+
e,
|
|
1481
|
+
t
|
|
886
1482
|
);
|
|
887
1483
|
}
|
|
1484
|
+
/**
|
|
1485
|
+
* Dispatches an action/event to the Bloc.
|
|
1486
|
+
* Events are queued and processed sequentially to prevent race conditions.
|
|
1487
|
+
* @param action The action/event instance to be processed.
|
|
1488
|
+
*/
|
|
1489
|
+
add = async (e) => {
|
|
1490
|
+
let t = e;
|
|
1491
|
+
try {
|
|
1492
|
+
t = this._plugins.transformEvent(e);
|
|
1493
|
+
} catch (s) {
|
|
1494
|
+
console.error("Error transforming event:", s);
|
|
1495
|
+
}
|
|
1496
|
+
if (t !== null) {
|
|
1497
|
+
try {
|
|
1498
|
+
this._plugins.notifyEvent(t);
|
|
1499
|
+
} catch (s) {
|
|
1500
|
+
console.error("Error notifying plugins of event:", s);
|
|
1501
|
+
}
|
|
1502
|
+
o.instance.plugins.notifyEventAdded(this, t), this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
|
|
1503
|
+
}
|
|
1504
|
+
};
|
|
888
1505
|
/**
|
|
889
1506
|
* @internal
|
|
890
1507
|
* Processes events from the queue sequentially
|
|
@@ -894,8 +1511,8 @@ class U extends x {
|
|
|
894
1511
|
this._isProcessingEvent = !0;
|
|
895
1512
|
try {
|
|
896
1513
|
for (; this._eventQueue.length > 0; ) {
|
|
897
|
-
const
|
|
898
|
-
await this._processEvent(
|
|
1514
|
+
const e = this._eventQueue.shift();
|
|
1515
|
+
await this._processEvent(e);
|
|
899
1516
|
}
|
|
900
1517
|
} finally {
|
|
901
1518
|
this._isProcessingEvent = !1;
|
|
@@ -906,54 +1523,59 @@ class U extends x {
|
|
|
906
1523
|
* @internal
|
|
907
1524
|
* Processes a single event
|
|
908
1525
|
*/
|
|
909
|
-
async _processEvent(
|
|
910
|
-
const
|
|
911
|
-
if (
|
|
912
|
-
const
|
|
1526
|
+
async _processEvent(e) {
|
|
1527
|
+
const t = e.constructor, s = this.eventHandlers.get(t);
|
|
1528
|
+
if (s) {
|
|
1529
|
+
const i = (n) => {
|
|
913
1530
|
const a = this.state;
|
|
914
|
-
this._pushState(
|
|
1531
|
+
this._pushState(n, a, e);
|
|
915
1532
|
};
|
|
916
1533
|
try {
|
|
917
|
-
await
|
|
918
|
-
} catch (
|
|
919
|
-
const a =
|
|
1534
|
+
await s(e, i);
|
|
1535
|
+
} catch (n) {
|
|
1536
|
+
const a = e.constructor.name || "UnnamedConstructor", c = {
|
|
920
1537
|
blocName: this._name,
|
|
921
1538
|
blocId: String(this._id),
|
|
922
1539
|
eventType: a,
|
|
923
1540
|
currentState: this.state,
|
|
924
|
-
action:
|
|
1541
|
+
action: e,
|
|
925
1542
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
926
1543
|
};
|
|
927
|
-
if (
|
|
1544
|
+
if (o.error(
|
|
928
1545
|
`[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${a}':`,
|
|
929
|
-
|
|
1546
|
+
n,
|
|
930
1547
|
"Context:",
|
|
931
|
-
|
|
932
|
-
),
|
|
933
|
-
|
|
1548
|
+
c
|
|
1549
|
+
), n instanceof Error)
|
|
1550
|
+
try {
|
|
1551
|
+
this._plugins.notifyError(n, {
|
|
1552
|
+
phase: "event-processing",
|
|
1553
|
+
operation: "handler",
|
|
1554
|
+
metadata: { event: e }
|
|
1555
|
+
}), o.instance.plugins.notifyError(n, this, {
|
|
1556
|
+
phase: "event-processing",
|
|
1557
|
+
operation: "handler",
|
|
1558
|
+
metadata: { event: e }
|
|
1559
|
+
});
|
|
1560
|
+
} catch (l) {
|
|
1561
|
+
console.error("Error notifying plugins:", l);
|
|
1562
|
+
}
|
|
1563
|
+
if (n instanceof Error && n.name === "CriticalError")
|
|
1564
|
+
throw n;
|
|
934
1565
|
}
|
|
935
1566
|
} else {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${
|
|
1567
|
+
const i = e.constructor.name || "UnnamedConstructor";
|
|
1568
|
+
o.warn(
|
|
1569
|
+
`[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${i}'.`,
|
|
939
1570
|
"Registered handlers:",
|
|
940
|
-
Array.from(this.eventHandlers.keys()).map((
|
|
1571
|
+
Array.from(this.eventHandlers.keys()).map((n) => n.name),
|
|
941
1572
|
"Action was:",
|
|
942
|
-
|
|
1573
|
+
e
|
|
943
1574
|
);
|
|
944
1575
|
}
|
|
945
1576
|
}
|
|
946
1577
|
}
|
|
947
|
-
class
|
|
948
|
-
/**
|
|
949
|
-
* @internal
|
|
950
|
-
* Protected method for useBloc to call
|
|
951
|
-
*/
|
|
952
|
-
_updateProps(e) {
|
|
953
|
-
var s;
|
|
954
|
-
const t = this.props;
|
|
955
|
-
this.props = e, (s = this.onPropsChanged) == null || s.call(this, t, e);
|
|
956
|
-
}
|
|
1578
|
+
class O extends C {
|
|
957
1579
|
/**
|
|
958
1580
|
* Updates the current state and notifies all observers of the change.
|
|
959
1581
|
* If the new state is identical to the current state (using Object.is),
|
|
@@ -976,7 +1598,7 @@ class H extends x {
|
|
|
976
1598
|
*/
|
|
977
1599
|
patch(e, t = !1) {
|
|
978
1600
|
if (typeof this.state != "object" || this.state === null) {
|
|
979
|
-
|
|
1601
|
+
o.warn(
|
|
980
1602
|
"Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
|
|
981
1603
|
);
|
|
982
1604
|
return;
|
|
@@ -985,10 +1607,10 @@ class H extends x {
|
|
|
985
1607
|
if (t)
|
|
986
1608
|
s = !0;
|
|
987
1609
|
else
|
|
988
|
-
for (const
|
|
989
|
-
if (Object.prototype.hasOwnProperty.call(e,
|
|
990
|
-
const
|
|
991
|
-
if (!Object.is(e[
|
|
1610
|
+
for (const i in e)
|
|
1611
|
+
if (Object.prototype.hasOwnProperty.call(e, i)) {
|
|
1612
|
+
const a = this.state[i];
|
|
1613
|
+
if (!Object.is(e[i], a)) {
|
|
992
1614
|
s = !0;
|
|
993
1615
|
break;
|
|
994
1616
|
}
|
|
@@ -999,112 +1621,237 @@ class H extends x {
|
|
|
999
1621
|
});
|
|
1000
1622
|
}
|
|
1001
1623
|
}
|
|
1002
|
-
class
|
|
1624
|
+
class L {
|
|
1003
1625
|
constructor(e) {
|
|
1004
1626
|
this.props = e;
|
|
1005
1627
|
}
|
|
1006
1628
|
}
|
|
1007
|
-
function
|
|
1008
|
-
if (Object.is(
|
|
1629
|
+
function V(r, e) {
|
|
1630
|
+
if (Object.is(r, e))
|
|
1009
1631
|
return !0;
|
|
1010
|
-
if (typeof
|
|
1632
|
+
if (typeof r != "object" || r === null || typeof e != "object" || e === null)
|
|
1011
1633
|
return !1;
|
|
1012
|
-
const t = Object.keys(
|
|
1634
|
+
const t = Object.keys(r), s = Object.keys(e);
|
|
1013
1635
|
if (t.length !== s.length)
|
|
1014
1636
|
return !1;
|
|
1015
|
-
for (let
|
|
1016
|
-
const
|
|
1017
|
-
if (!Object.prototype.hasOwnProperty.call(e,
|
|
1637
|
+
for (let i = 0; i < t.length; i++) {
|
|
1638
|
+
const n = t[i];
|
|
1639
|
+
if (!Object.prototype.hasOwnProperty.call(e, n) || !Object.is(r[n], e[n]))
|
|
1018
1640
|
return !1;
|
|
1019
1641
|
}
|
|
1020
1642
|
return !0;
|
|
1021
1643
|
}
|
|
1022
|
-
|
|
1644
|
+
function N(r) {
|
|
1645
|
+
if (!r || typeof r != "object")
|
|
1646
|
+
return;
|
|
1647
|
+
const e = [];
|
|
1648
|
+
for (const [s, i] of Object.entries(r)) {
|
|
1649
|
+
const n = typeof i;
|
|
1650
|
+
(n === "string" || n === "number" || n === "boolean" || i === null || i === void 0) && e.push([s, i]);
|
|
1651
|
+
}
|
|
1652
|
+
if (e.length === 0)
|
|
1653
|
+
return;
|
|
1654
|
+
e.sort(([s], [i]) => s.localeCompare(i));
|
|
1655
|
+
const t = [];
|
|
1656
|
+
for (const [s, i] of e)
|
|
1657
|
+
i === null ? t.push(`${s}:null`) : i === void 0 ? t.push(`${s}:undefined`) : t.push(`${s}:${String(i)}`);
|
|
1658
|
+
return t.join("|");
|
|
1659
|
+
}
|
|
1660
|
+
class F {
|
|
1661
|
+
static componentRenderCounts = /* @__PURE__ */ new Map();
|
|
1662
|
+
static lastRenderTimestamps = /* @__PURE__ */ new Map();
|
|
1663
|
+
static groupedLogs = /* @__PURE__ */ new Map();
|
|
1664
|
+
static groupTimeouts = /* @__PURE__ */ new Map();
|
|
1665
|
+
/**
|
|
1666
|
+
* Log a component rerender with detailed information
|
|
1667
|
+
*/
|
|
1668
|
+
static logRerender(e) {
|
|
1669
|
+
const t = o._config?.rerenderLogging;
|
|
1670
|
+
if (!t) return;
|
|
1671
|
+
const s = this.parseConfig(t);
|
|
1672
|
+
if (!s.enabled || s.filter && !s.filter({
|
|
1673
|
+
componentName: e.componentName,
|
|
1674
|
+
blocName: e.blocName
|
|
1675
|
+
}))
|
|
1676
|
+
return;
|
|
1677
|
+
const i = `${e.componentName}-${e.blocId}`, n = this.componentRenderCounts.get(i) || 0;
|
|
1678
|
+
this.componentRenderCounts.set(i, n + 1), e.renderCount = n + 1;
|
|
1679
|
+
const a = this.lastRenderTimestamps.get(i);
|
|
1680
|
+
a && (e.duration = e.timestamp - a), this.lastRenderTimestamps.set(i, e.timestamp), s.includeStackTrace && s.level === "detailed" && (e.stackTrace = new Error().stack), s.groupRerenders ? this.logGrouped(e, s) : this.logImmediate(e, s);
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Parse the logging configuration
|
|
1684
|
+
*/
|
|
1685
|
+
static parseConfig(e) {
|
|
1686
|
+
return e === !0 ? { enabled: !0, level: "normal" } : typeof e == "string" ? {
|
|
1687
|
+
enabled: !0,
|
|
1688
|
+
level: e === "minimal" ? "minimal" : "detailed"
|
|
1689
|
+
} : {
|
|
1690
|
+
enabled: e.enabled,
|
|
1691
|
+
level: e.level || "normal",
|
|
1692
|
+
filter: e.filter,
|
|
1693
|
+
includeStackTrace: e.includeStackTrace,
|
|
1694
|
+
groupRerenders: e.groupRerenders
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Log immediately without grouping
|
|
1699
|
+
*/
|
|
1700
|
+
static logImmediate(e, t) {
|
|
1701
|
+
const s = this.formatMessage(e, t.level);
|
|
1702
|
+
t.level === "detailed" ? (console.group(s.header), s.details && console.log(s.details), s.values && console.table(s.values), e.stackTrace && console.log("Stack trace:", e.stackTrace), console.groupEnd()) : console.log(s.header, s.details || "");
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Log with grouping (batch multiple rerenders)
|
|
1706
|
+
*/
|
|
1707
|
+
static logGrouped(e, t) {
|
|
1708
|
+
const s = `${e.componentName}-${e.blocId}`, i = this.groupTimeouts.get(s);
|
|
1709
|
+
i && clearTimeout(i);
|
|
1710
|
+
const n = this.groupedLogs.get(s) || [];
|
|
1711
|
+
n.push(e), this.groupedLogs.set(s, n);
|
|
1712
|
+
const a = setTimeout(() => {
|
|
1713
|
+
const c = this.groupedLogs.get(s) || [];
|
|
1714
|
+
this.groupedLogs.delete(s), this.groupTimeouts.delete(s), c.length === 1 ? this.logImmediate(c[0], t) : (console.group(
|
|
1715
|
+
`🔄 ${e.componentName} rendered ${c.length} times (${e.blocName})`
|
|
1716
|
+
), c.forEach((l, h) => {
|
|
1717
|
+
const p = this.formatMessage(l, t.level);
|
|
1718
|
+
console.log(` ${h + 1}. ${p.details || p.header}`);
|
|
1719
|
+
}), console.groupEnd());
|
|
1720
|
+
}, 50);
|
|
1721
|
+
this.groupTimeouts.set(s, a);
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Format the log message based on level
|
|
1725
|
+
*/
|
|
1726
|
+
static formatMessage(e, t) {
|
|
1727
|
+
const s = this.getReasonEmoji(e.reason.type);
|
|
1728
|
+
if (t === "minimal")
|
|
1729
|
+
return {
|
|
1730
|
+
header: `${s} ${e.componentName} #${e.renderCount}`,
|
|
1731
|
+
details: null,
|
|
1732
|
+
values: null
|
|
1733
|
+
};
|
|
1734
|
+
const i = `${s} ${e.componentName} rerender #${e.renderCount} (${e.blocName})`;
|
|
1735
|
+
let n = `Reason: ${e.reason.description || e.reason.type}`;
|
|
1736
|
+
e.duration !== void 0 && (n += ` | Time since last: ${e.duration}ms`), t === "normal" && e.reason.changedPaths && e.reason.changedPaths.length > 0 && (n += ` | Changed: ${e.reason.changedPaths.join(", ")}`);
|
|
1737
|
+
let a = null;
|
|
1738
|
+
return t === "detailed" && e.reason.changedPaths && e.reason.changedPaths.length > 0 && (a = {}, e.reason.changedPaths.forEach((c) => {
|
|
1739
|
+
a[c] = {
|
|
1740
|
+
old: e.reason.oldValues?.[c],
|
|
1741
|
+
new: e.reason.newValues?.[c]
|
|
1742
|
+
};
|
|
1743
|
+
}), Object.keys(a).length === 0 && (a = null)), { header: i, details: n, values: a };
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Get emoji for reason type
|
|
1747
|
+
*/
|
|
1748
|
+
static getReasonEmoji(e) {
|
|
1749
|
+
switch (e) {
|
|
1750
|
+
case "state-change":
|
|
1751
|
+
return "📊";
|
|
1752
|
+
case "dependency-change":
|
|
1753
|
+
return "🔗";
|
|
1754
|
+
case "mount":
|
|
1755
|
+
return "🚀";
|
|
1756
|
+
case "props-change":
|
|
1757
|
+
return "📦";
|
|
1758
|
+
default:
|
|
1759
|
+
return "🔄";
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Clear all tracking data
|
|
1764
|
+
*/
|
|
1765
|
+
static clear() {
|
|
1766
|
+
this.componentRenderCounts.clear(), this.lastRenderTimestamps.clear(), this.groupedLogs.clear(), this.groupTimeouts.forEach((e) => clearTimeout(e)), this.groupTimeouts.clear();
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Get render count for a component
|
|
1770
|
+
*/
|
|
1771
|
+
static getRenderCount(e, t) {
|
|
1772
|
+
return this.componentRenderCounts.get(`${e}-${t}`) || 0;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
class j {
|
|
1776
|
+
static originalInstance;
|
|
1023
1777
|
/**
|
|
1024
1778
|
* Sets up a clean test environment
|
|
1025
1779
|
*/
|
|
1026
1780
|
static setUp() {
|
|
1027
|
-
this.originalInstance =
|
|
1781
|
+
this.originalInstance = o.instance, o.resetInstance(), o.enableLog = !1;
|
|
1028
1782
|
}
|
|
1029
1783
|
/**
|
|
1030
1784
|
* Tears down the test environment and restores original state
|
|
1031
1785
|
*/
|
|
1032
1786
|
static tearDown() {
|
|
1033
|
-
|
|
1787
|
+
o.resetInstance();
|
|
1034
1788
|
}
|
|
1035
1789
|
/**
|
|
1036
1790
|
* Creates a test bloc with automatic cleanup
|
|
1037
1791
|
*/
|
|
1038
1792
|
static createBloc(e, ...t) {
|
|
1039
1793
|
const s = new e(...t);
|
|
1040
|
-
return
|
|
1794
|
+
return o.activateBloc(s), s;
|
|
1041
1795
|
}
|
|
1042
1796
|
/**
|
|
1043
1797
|
* Waits for a bloc to emit a specific state
|
|
1044
1798
|
*/
|
|
1045
1799
|
static async waitForState(e, t, s = 5e3) {
|
|
1046
|
-
return new Promise((
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1800
|
+
return new Promise((i, n) => {
|
|
1801
|
+
const a = setTimeout(() => {
|
|
1802
|
+
n(
|
|
1049
1803
|
new Error(
|
|
1050
1804
|
`Timeout waiting for state matching predicate after ${s}ms`
|
|
1051
1805
|
)
|
|
1052
1806
|
);
|
|
1053
|
-
}, s),
|
|
1054
|
-
|
|
1055
|
-
fn: (u) => {
|
|
1056
|
-
t(u) && (clearTimeout(o), a(), n(u));
|
|
1057
|
-
}
|
|
1807
|
+
}, s), c = e.subscribe((l) => {
|
|
1808
|
+
t(l) && (clearTimeout(a), c(), i(l));
|
|
1058
1809
|
});
|
|
1059
|
-
t(e.state) && (clearTimeout(
|
|
1810
|
+
t(e.state) && (clearTimeout(a), c(), i(e.state));
|
|
1060
1811
|
});
|
|
1061
1812
|
}
|
|
1062
1813
|
/**
|
|
1063
1814
|
* Expects a bloc to emit specific states in order
|
|
1064
1815
|
*/
|
|
1065
1816
|
static async expectStates(e, t, s = 5e3) {
|
|
1066
|
-
const
|
|
1067
|
-
return new Promise((
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1817
|
+
const i = [];
|
|
1818
|
+
return new Promise((n, a) => {
|
|
1819
|
+
const c = setTimeout(() => {
|
|
1820
|
+
a(
|
|
1070
1821
|
new Error(
|
|
1071
|
-
`Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(
|
|
1822
|
+
`Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`
|
|
1072
1823
|
)
|
|
1073
1824
|
);
|
|
1074
|
-
}, s),
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
);
|
|
1087
|
-
return;
|
|
1088
|
-
}
|
|
1825
|
+
}, s), l = e.subscribe((h) => {
|
|
1826
|
+
if (i.push(h), i.length === t.length) {
|
|
1827
|
+
clearTimeout(c), l();
|
|
1828
|
+
for (let p = 0; p < t.length; p++) {
|
|
1829
|
+
const S = t[p], k = i[p];
|
|
1830
|
+
if (JSON.stringify(S) !== JSON.stringify(k)) {
|
|
1831
|
+
a(
|
|
1832
|
+
new Error(
|
|
1833
|
+
`State mismatch at index ${p}. Expected: ${JSON.stringify(S)}, Received: ${JSON.stringify(k)}`
|
|
1834
|
+
)
|
|
1835
|
+
);
|
|
1836
|
+
return;
|
|
1089
1837
|
}
|
|
1090
|
-
r();
|
|
1091
1838
|
}
|
|
1839
|
+
n();
|
|
1092
1840
|
}
|
|
1093
1841
|
});
|
|
1094
1842
|
});
|
|
1095
1843
|
}
|
|
1096
1844
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
constructor(
|
|
1100
|
-
super(
|
|
1101
|
-
i(this, "mockHandlers", /* @__PURE__ */ new Map());
|
|
1845
|
+
class z extends R {
|
|
1846
|
+
mockHandlers = /* @__PURE__ */ new Map();
|
|
1847
|
+
constructor(e) {
|
|
1848
|
+
super(e);
|
|
1102
1849
|
}
|
|
1103
1850
|
/**
|
|
1104
1851
|
* Mock an event handler for testing
|
|
1105
1852
|
*/
|
|
1106
|
-
mockEventHandler(
|
|
1107
|
-
this.on(
|
|
1853
|
+
mockEventHandler(e, t) {
|
|
1854
|
+
this.on(e, t);
|
|
1108
1855
|
}
|
|
1109
1856
|
/**
|
|
1110
1857
|
* Get the number of registered handlers
|
|
@@ -1115,21 +1862,20 @@ class Q extends U {
|
|
|
1115
1862
|
/**
|
|
1116
1863
|
* Check if a handler is registered for an event type
|
|
1117
1864
|
*/
|
|
1118
|
-
hasHandler(
|
|
1119
|
-
return this.eventHandlers.has(
|
|
1865
|
+
hasHandler(e) {
|
|
1866
|
+
return this.eventHandlers.has(e);
|
|
1120
1867
|
}
|
|
1121
1868
|
}
|
|
1122
|
-
class
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
this.stateHistory.push(t);
|
|
1869
|
+
class q extends O {
|
|
1870
|
+
stateHistory = [];
|
|
1871
|
+
constructor(e) {
|
|
1872
|
+
super(e), this.stateHistory.push(e);
|
|
1127
1873
|
}
|
|
1128
1874
|
/**
|
|
1129
1875
|
* Override emit to track state history
|
|
1130
1876
|
*/
|
|
1131
|
-
emit(
|
|
1132
|
-
this.stateHistory.push(
|
|
1877
|
+
emit(e) {
|
|
1878
|
+
this.stateHistory.push(e), super.emit(e);
|
|
1133
1879
|
}
|
|
1134
1880
|
/**
|
|
1135
1881
|
* Get the history of all states
|
|
@@ -1144,16 +1890,16 @@ class W extends H {
|
|
|
1144
1890
|
this.stateHistory = [this.state];
|
|
1145
1891
|
}
|
|
1146
1892
|
}
|
|
1147
|
-
class
|
|
1893
|
+
class W {
|
|
1894
|
+
initialStats;
|
|
1148
1895
|
constructor() {
|
|
1149
|
-
|
|
1150
|
-
this.initialStats = d.getMemoryStats();
|
|
1896
|
+
this.initialStats = o.getMemoryStats();
|
|
1151
1897
|
}
|
|
1152
1898
|
/**
|
|
1153
1899
|
* Check for memory leaks and return a report
|
|
1154
1900
|
*/
|
|
1155
1901
|
checkForLeaks() {
|
|
1156
|
-
const e =
|
|
1902
|
+
const e = o.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
|
|
1157
1903
|
Memory Leak Detection Report:
|
|
1158
1904
|
- Initial registered blocs: ${this.initialStats.registeredBlocs}
|
|
1159
1905
|
- Current registered blocs: ${e.registeredBlocs}
|
|
@@ -1170,419 +1916,360 @@ Memory Leak Detection Report:
|
|
|
1170
1916
|
};
|
|
1171
1917
|
}
|
|
1172
1918
|
}
|
|
1173
|
-
|
|
1174
|
-
constructor() {
|
|
1175
|
-
i(this, "consumers", /* @__PURE__ */ new WeakMap());
|
|
1176
|
-
i(this, "registrationCount", 0);
|
|
1177
|
-
i(this, "activeConsumers", 0);
|
|
1178
|
-
}
|
|
1179
|
-
register(e, t) {
|
|
1180
|
-
this.registrationCount++, this.consumers.get(e) || this.activeConsumers++, this.consumers.set(e, {
|
|
1181
|
-
id: t,
|
|
1182
|
-
lastNotified: Date.now(),
|
|
1183
|
-
hasRendered: !1,
|
|
1184
|
-
stateAccesses: /* @__PURE__ */ new Set(),
|
|
1185
|
-
classAccesses: /* @__PURE__ */ new Set(),
|
|
1186
|
-
stateValues: /* @__PURE__ */ new Map(),
|
|
1187
|
-
classValues: /* @__PURE__ */ new Map(),
|
|
1188
|
-
accessCount: 0,
|
|
1189
|
-
lastAccessTime: 0,
|
|
1190
|
-
firstAccessTime: 0
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
unregister(e) {
|
|
1194
|
-
e && this.consumers.get(e) && (this.consumers.delete(e), this.activeConsumers = Math.max(0, this.activeConsumers - 1));
|
|
1195
|
-
}
|
|
1196
|
-
trackAccess(e, t, s, n) {
|
|
1197
|
-
const r = this.consumers.get(e);
|
|
1198
|
-
if (!r) return;
|
|
1199
|
-
const o = Date.now();
|
|
1200
|
-
r.firstAccessTime || (r.firstAccessTime = o), r.accessCount++, r.lastAccessTime = o, t === "state" ? (r.stateAccesses.add(s), n !== void 0 && r.stateValues.set(s, { value: n, lastAccessTime: o })) : (r.classAccesses.add(s), n !== void 0 && r.classValues.set(s, { value: n, lastAccessTime: o }));
|
|
1201
|
-
}
|
|
1202
|
-
resetTracking(e) {
|
|
1203
|
-
const t = this.consumers.get(e);
|
|
1204
|
-
t && (t.stateAccesses.clear(), t.classAccesses.clear(), t.stateValues.clear(), t.classValues.clear(), t.accessCount = 0, t.firstAccessTime = 0);
|
|
1205
|
-
}
|
|
1206
|
-
getDependencies(e) {
|
|
1207
|
-
const t = this.consumers.get(e);
|
|
1208
|
-
return t ? {
|
|
1209
|
-
statePaths: Array.from(t.stateAccesses),
|
|
1210
|
-
classPaths: Array.from(t.classAccesses)
|
|
1211
|
-
} : null;
|
|
1212
|
-
}
|
|
1213
|
-
hasValuesChanged(e, t, s) {
|
|
1214
|
-
const n = this.consumers.get(e);
|
|
1215
|
-
if (!n) return !0;
|
|
1216
|
-
let r = !1;
|
|
1217
|
-
const o = Date.now();
|
|
1218
|
-
if (n.stateValues.size === 0 && n.classValues.size === 0 && (n.stateAccesses.size > 0 || n.classAccesses.size > 0))
|
|
1219
|
-
return !0;
|
|
1220
|
-
for (const [a, u] of n.stateValues)
|
|
1221
|
-
try {
|
|
1222
|
-
const p = this.getValueAtPath(t, a);
|
|
1223
|
-
p !== u.value && (n.stateValues.set(a, {
|
|
1224
|
-
value: p,
|
|
1225
|
-
lastAccessTime: o
|
|
1226
|
-
}), r = !0);
|
|
1227
|
-
} catch {
|
|
1228
|
-
r = !0;
|
|
1229
|
-
}
|
|
1230
|
-
for (const [a, u] of n.classValues)
|
|
1231
|
-
try {
|
|
1232
|
-
const p = this.getValueAtPath(s, a);
|
|
1233
|
-
p !== u.value && (n.classValues.set(a, {
|
|
1234
|
-
value: p,
|
|
1235
|
-
lastAccessTime: o
|
|
1236
|
-
}), r = !0);
|
|
1237
|
-
} catch {
|
|
1238
|
-
r = !0;
|
|
1239
|
-
}
|
|
1240
|
-
return r;
|
|
1241
|
-
}
|
|
1242
|
-
shouldNotifyConsumer(e, t) {
|
|
1243
|
-
const s = this.consumers.get(e);
|
|
1244
|
-
if (!s) return !1;
|
|
1245
|
-
for (const n of t) {
|
|
1246
|
-
if (s.stateAccesses.has(n) || s.classAccesses.has(n)) return !0;
|
|
1247
|
-
for (const r of s.stateAccesses)
|
|
1248
|
-
if (n.startsWith(r + ".") || r.startsWith(n + "."))
|
|
1249
|
-
return !0;
|
|
1250
|
-
}
|
|
1251
|
-
return !1;
|
|
1252
|
-
}
|
|
1253
|
-
updateLastNotified(e) {
|
|
1254
|
-
const t = this.consumers.get(e);
|
|
1255
|
-
t && (t.lastNotified = Date.now());
|
|
1256
|
-
}
|
|
1257
|
-
getConsumerInfo(e) {
|
|
1258
|
-
return this.consumers.get(e);
|
|
1259
|
-
}
|
|
1260
|
-
setHasRendered(e, t) {
|
|
1261
|
-
const s = this.consumers.get(e);
|
|
1262
|
-
s && (s.hasRendered = t);
|
|
1263
|
-
}
|
|
1264
|
-
hasConsumer(e) {
|
|
1265
|
-
return this.consumers.has(e);
|
|
1266
|
-
}
|
|
1267
|
-
getStats() {
|
|
1268
|
-
return {
|
|
1269
|
-
totalRegistrations: this.registrationCount,
|
|
1270
|
-
activeConsumers: this.activeConsumers
|
|
1271
|
-
};
|
|
1272
|
-
}
|
|
1273
|
-
getValueAtPath(e, t) {
|
|
1274
|
-
const s = t.split(".");
|
|
1275
|
-
let n = e;
|
|
1276
|
-
for (const r of s) {
|
|
1277
|
-
if (n == null) return;
|
|
1278
|
-
n = n[r];
|
|
1279
|
-
}
|
|
1280
|
-
return n;
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
const k = /* @__PURE__ */ new WeakMap();
|
|
1284
|
-
let f = {
|
|
1919
|
+
const I = /* @__PURE__ */ new WeakMap(), d = {
|
|
1285
1920
|
stateProxiesCreated: 0,
|
|
1286
1921
|
classProxiesCreated: 0,
|
|
1287
1922
|
cacheHits: 0,
|
|
1288
1923
|
cacheMisses: 0,
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
const
|
|
1297
|
-
if (!s || !n || typeof t != "object" || t === null)
|
|
1298
|
-
return t;
|
|
1299
|
-
let o = k.get(t);
|
|
1300
|
-
o || (o = /* @__PURE__ */ new WeakMap(), k.set(t, o));
|
|
1301
|
-
const a = o.get(s);
|
|
1924
|
+
totalProxiesCreated: 0
|
|
1925
|
+
}, _ = (r, e, t, s = "") => {
|
|
1926
|
+
if (!e || !t || typeof r != "object" || r === null)
|
|
1927
|
+
return r;
|
|
1928
|
+
if (!s) {
|
|
1929
|
+
let n = I.get(r);
|
|
1930
|
+
n || (n = /* @__PURE__ */ new WeakMap(), I.set(r, n));
|
|
1931
|
+
const a = n.get(e);
|
|
1302
1932
|
if (a)
|
|
1303
|
-
return
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
return o.set(s, p), f.stateProxiesCreated++, f.totalProxiesCreated++, p;
|
|
1341
|
-
}
|
|
1342
|
-
static createClassProxy(e) {
|
|
1343
|
-
const { target: t, consumerRef: s, consumerTracker: n } = e;
|
|
1344
|
-
if (!s || !n)
|
|
1345
|
-
return t;
|
|
1346
|
-
let r = k.get(t);
|
|
1347
|
-
r || (r = /* @__PURE__ */ new WeakMap(), k.set(t, r));
|
|
1348
|
-
const o = r.get(s);
|
|
1349
|
-
if (o)
|
|
1350
|
-
return f.cacheHits++, o;
|
|
1351
|
-
f.cacheMisses++;
|
|
1352
|
-
const a = {
|
|
1353
|
-
get(p, h) {
|
|
1354
|
-
const m = Reflect.get(p, h);
|
|
1355
|
-
let I = !1, g = p;
|
|
1356
|
-
const A = /* @__PURE__ */ new WeakSet(), D = 10;
|
|
1357
|
-
let w = 0;
|
|
1358
|
-
for (; g && !I && w < D && !A.has(g); ) {
|
|
1359
|
-
A.add(g);
|
|
1360
|
-
try {
|
|
1361
|
-
const T = Object.getOwnPropertyDescriptor(
|
|
1362
|
-
g,
|
|
1363
|
-
h
|
|
1364
|
-
);
|
|
1365
|
-
if (T && T.get) {
|
|
1366
|
-
I = !0;
|
|
1367
|
-
break;
|
|
1368
|
-
}
|
|
1369
|
-
g = Object.getPrototypeOf(g), w++;
|
|
1370
|
-
} catch {
|
|
1371
|
-
break;
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
if (!I)
|
|
1375
|
-
return m;
|
|
1376
|
-
f.propertyAccesses++;
|
|
1377
|
-
const B = m, M = B !== null && typeof B != "object" ? B : void 0;
|
|
1378
|
-
return n.trackAccess(
|
|
1379
|
-
s,
|
|
1933
|
+
return d.cacheHits++, a;
|
|
1934
|
+
d.cacheMisses++;
|
|
1935
|
+
}
|
|
1936
|
+
const i = new Proxy(r, {
|
|
1937
|
+
get(n, a) {
|
|
1938
|
+
if (typeof a == "symbol" || a === "constructor")
|
|
1939
|
+
return Reflect.get(n, a);
|
|
1940
|
+
const c = s ? `${s}.${a}` : a, l = Reflect.get(n, a), h = l && typeof l == "object";
|
|
1941
|
+
return t.trackAccess(
|
|
1942
|
+
e,
|
|
1943
|
+
"state",
|
|
1944
|
+
c,
|
|
1945
|
+
h ? void 0 : l
|
|
1946
|
+
), h && (Array.isArray(l) || Object.getPrototypeOf(l) === Object.prototype) ? _(l, e, t, c) : l;
|
|
1947
|
+
},
|
|
1948
|
+
set: () => !1,
|
|
1949
|
+
// State should be immutable
|
|
1950
|
+
deleteProperty: () => !1
|
|
1951
|
+
// State properties should not be deleted
|
|
1952
|
+
});
|
|
1953
|
+
return s || (I.get(r).set(e, i), d.stateProxiesCreated++, d.totalProxiesCreated++), i;
|
|
1954
|
+
}, M = (r, e, t) => {
|
|
1955
|
+
if (!e || !t)
|
|
1956
|
+
return r;
|
|
1957
|
+
let s = I.get(r);
|
|
1958
|
+
s || (s = /* @__PURE__ */ new WeakMap(), I.set(r, s));
|
|
1959
|
+
const i = s.get(e);
|
|
1960
|
+
if (i)
|
|
1961
|
+
return d.cacheHits++, i;
|
|
1962
|
+
d.cacheMisses++;
|
|
1963
|
+
const n = new Proxy(r, {
|
|
1964
|
+
get(a, c) {
|
|
1965
|
+
const l = Reflect.get(a, c);
|
|
1966
|
+
if (U(a, c)?.get) {
|
|
1967
|
+
const p = l !== null && typeof l != "object";
|
|
1968
|
+
t.trackAccess(
|
|
1969
|
+
e,
|
|
1380
1970
|
"class",
|
|
1381
|
-
String(
|
|
1382
|
-
|
|
1383
|
-
)
|
|
1384
|
-
},
|
|
1385
|
-
has(p, h) {
|
|
1386
|
-
return h in p;
|
|
1387
|
-
},
|
|
1388
|
-
ownKeys(p) {
|
|
1389
|
-
return Reflect.ownKeys(p);
|
|
1390
|
-
},
|
|
1391
|
-
getOwnPropertyDescriptor(p, h) {
|
|
1392
|
-
return Reflect.getOwnPropertyDescriptor(p, h);
|
|
1971
|
+
String(c),
|
|
1972
|
+
p ? l : void 0
|
|
1973
|
+
);
|
|
1393
1974
|
}
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1975
|
+
return l;
|
|
1976
|
+
}
|
|
1977
|
+
});
|
|
1978
|
+
return s.set(e, n), d.classProxiesCreated++, d.totalProxiesCreated++, n;
|
|
1979
|
+
}, U = (r, e, t = 10) => {
|
|
1980
|
+
let s = r, i = 0;
|
|
1981
|
+
for (; s && i < t; ) {
|
|
1982
|
+
const n = Object.getOwnPropertyDescriptor(s, e);
|
|
1983
|
+
if (n) return n;
|
|
1984
|
+
s = Object.getPrototypeOf(s), i++;
|
|
1985
|
+
}
|
|
1986
|
+
}, $ = {
|
|
1987
|
+
createStateProxy: (r) => _(
|
|
1988
|
+
r.target,
|
|
1989
|
+
r.consumerRef,
|
|
1990
|
+
r.consumerTracker,
|
|
1991
|
+
r.path
|
|
1992
|
+
),
|
|
1993
|
+
createClassProxy: (r) => M(
|
|
1994
|
+
r.target,
|
|
1995
|
+
r.consumerRef,
|
|
1996
|
+
r.consumerTracker
|
|
1997
|
+
),
|
|
1998
|
+
getProxyState: (r) => _(
|
|
1999
|
+
r.state,
|
|
2000
|
+
r.consumerRef,
|
|
2001
|
+
r.consumerTracker
|
|
2002
|
+
),
|
|
2003
|
+
getProxyBlocInstance: (r) => M(
|
|
2004
|
+
r.blocInstance,
|
|
2005
|
+
r.consumerRef,
|
|
2006
|
+
r.consumerTracker
|
|
2007
|
+
),
|
|
2008
|
+
// Compatibility functions that return expected structure
|
|
2009
|
+
getStats: () => ({
|
|
2010
|
+
...d,
|
|
2011
|
+
propertyAccesses: 0,
|
|
2012
|
+
nestedProxiesCreated: 0,
|
|
2013
|
+
cacheEfficiency: d.cacheHits + d.cacheMisses > 0 ? `${(d.cacheHits / (d.cacheHits + d.cacheMisses) * 100).toFixed(1)}%` : "N/A",
|
|
2014
|
+
lifetime: "0ms",
|
|
2015
|
+
proxiesPerSecond: "N/A"
|
|
2016
|
+
}),
|
|
2017
|
+
resetStats: () => {
|
|
2018
|
+
d.stateProxiesCreated = 0, d.classProxiesCreated = 0, d.cacheHits = 0, d.cacheMisses = 0, d.totalProxiesCreated = 0;
|
|
1432
2019
|
}
|
|
1433
|
-
}
|
|
1434
|
-
|
|
2020
|
+
};
|
|
2021
|
+
class G {
|
|
2022
|
+
id = `adapter-${A()}`;
|
|
2023
|
+
blocConstructor;
|
|
2024
|
+
componentRef = { current: {} };
|
|
2025
|
+
blocInstance;
|
|
2026
|
+
unmountTime = 0;
|
|
2027
|
+
mountTime = 0;
|
|
2028
|
+
// Subscription management
|
|
2029
|
+
subscriptionId;
|
|
2030
|
+
unsubscribe;
|
|
2031
|
+
// Dependency tracking
|
|
2032
|
+
dependencyValues;
|
|
2033
|
+
isUsingDependencies = !1;
|
|
2034
|
+
trackedPaths = /* @__PURE__ */ new Set();
|
|
2035
|
+
pendingTrackedPaths = /* @__PURE__ */ new Set();
|
|
2036
|
+
// Paths tracked before subscription exists
|
|
2037
|
+
// Proxy caching
|
|
2038
|
+
cachedStateProxy;
|
|
2039
|
+
cachedBlocProxy;
|
|
2040
|
+
lastProxiedState;
|
|
2041
|
+
// Lifecycle state
|
|
2042
|
+
hasMounted = !1;
|
|
2043
|
+
mountCount = 0;
|
|
2044
|
+
// Rerender tracking
|
|
2045
|
+
lastState;
|
|
2046
|
+
lastDependencyValues;
|
|
2047
|
+
componentName;
|
|
2048
|
+
renderCount = 0;
|
|
2049
|
+
lastDependenciesFn;
|
|
2050
|
+
options;
|
|
1435
2051
|
constructor(e, t) {
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
i(this, "blocInstance");
|
|
1440
|
-
// Core components
|
|
1441
|
-
i(this, "consumerTracker");
|
|
1442
|
-
i(this, "lastProps");
|
|
1443
|
-
i(this, "unmountTime", 0);
|
|
1444
|
-
i(this, "mountTime", 0);
|
|
1445
|
-
// Dependency tracking
|
|
1446
|
-
i(this, "dependencyValues");
|
|
1447
|
-
i(this, "isUsingDependencies", !1);
|
|
1448
|
-
// Lifecycle state
|
|
1449
|
-
i(this, "hasMounted", !1);
|
|
1450
|
-
i(this, "mountCount", 0);
|
|
1451
|
-
i(this, "options");
|
|
1452
|
-
i(this, "createStateProxy", (e) => b.createStateProxy({
|
|
1453
|
-
target: e.target,
|
|
1454
|
-
consumerRef: this.componentRef.current,
|
|
1455
|
-
consumerTracker: this
|
|
1456
|
-
}));
|
|
1457
|
-
i(this, "createClassProxy", (e) => b.createClassProxy({
|
|
1458
|
-
target: e.target,
|
|
1459
|
-
consumerRef: this.componentRef.current,
|
|
1460
|
-
consumerTracker: this
|
|
1461
|
-
}));
|
|
1462
|
-
i(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
|
|
1463
|
-
id: this.id,
|
|
1464
|
-
fn: (s, n) => {
|
|
1465
|
-
var r;
|
|
1466
|
-
if (this.isUsingDependencies && ((r = this.options) != null && r.dependencies)) {
|
|
1467
|
-
const o = this.options.dependencies(this.blocInstance);
|
|
1468
|
-
if (!this.hasDependencyValuesChanged(
|
|
1469
|
-
this.dependencyValues,
|
|
1470
|
-
o
|
|
1471
|
-
))
|
|
1472
|
-
return;
|
|
1473
|
-
this.dependencyValues = o;
|
|
1474
|
-
} else if (d.config.proxyDependencyTracking) {
|
|
1475
|
-
const o = this.consumerTracker.getConsumerInfo(
|
|
1476
|
-
this.componentRef.current
|
|
1477
|
-
);
|
|
1478
|
-
if (o && o.hasRendered && !this.consumerTracker.hasValuesChanged(
|
|
1479
|
-
this.componentRef.current,
|
|
1480
|
-
s,
|
|
1481
|
-
this.blocInstance
|
|
1482
|
-
))
|
|
1483
|
-
return;
|
|
1484
|
-
} else {
|
|
1485
|
-
e.onChange();
|
|
1486
|
-
return;
|
|
1487
|
-
}
|
|
1488
|
-
e.onChange();
|
|
1489
|
-
}
|
|
1490
|
-
}));
|
|
1491
|
-
i(this, "mount", () => {
|
|
1492
|
-
var e, t;
|
|
1493
|
-
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))
|
|
1494
|
-
try {
|
|
1495
|
-
this.options.onMount(this.blocInstance);
|
|
1496
|
-
} catch (s) {
|
|
1497
|
-
throw s;
|
|
1498
|
-
}
|
|
1499
|
-
});
|
|
1500
|
-
i(this, "unmount", () => {
|
|
1501
|
-
var e;
|
|
1502
|
-
if (this.unmountTime = Date.now(), this.consumerTracker.unregister(this.componentRef.current), this.blocInstance._removeConsumer(this.id), v.propsOwners.get(this.blocInstance) === this.id && v.propsOwners.delete(this.blocInstance), (e = this.options) != null && e.onUnmount)
|
|
1503
|
-
try {
|
|
1504
|
-
this.options.onUnmount(this.blocInstance);
|
|
1505
|
-
} catch {
|
|
1506
|
-
}
|
|
1507
|
-
});
|
|
1508
|
-
i(this, "getProxyState", (e) => this.isUsingDependencies || !d.config.proxyDependencyTracking ? e : b.getProxyState({
|
|
1509
|
-
state: e,
|
|
1510
|
-
consumerRef: this.componentRef.current,
|
|
1511
|
-
consumerTracker: this
|
|
1512
|
-
}));
|
|
1513
|
-
i(this, "getProxyBlocInstance", () => this.isUsingDependencies || !d.config.proxyDependencyTracking ? this.blocInstance : b.getProxyBlocInstance({
|
|
1514
|
-
blocInstance: this.blocInstance,
|
|
1515
|
-
consumerRef: this.componentRef.current,
|
|
1516
|
-
consumerTracker: this
|
|
1517
|
-
}));
|
|
1518
|
-
this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!(t != null && t.dependencies), this.consumerTracker = new z(), this.blocInstance = this.updateBlocInstance(), this.consumerTracker.register(e.componentRef.current, this.id), this.isUsingDependencies && (t != null && t.dependencies) && (this.dependencyValues = t.dependencies(this.blocInstance)), (t == null ? void 0 : t.props) !== void 0 && this.updateProps(t.props);
|
|
1519
|
-
}
|
|
1520
|
-
trackAccess(e, t, s, n) {
|
|
1521
|
-
this.consumerTracker.trackAccess(e, t, s, n);
|
|
2052
|
+
this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!t?.dependencies, this.updateBlocInstance(), this.isUsingDependencies && t?.dependencies && (this.dependencyValues = t.dependencies(this.blocInstance));
|
|
2053
|
+
const s = this.getAdapterMetadata();
|
|
2054
|
+
o.getInstance().plugins.notifyAdapterCreated(this, s);
|
|
1522
2055
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
shouldNotifyConsumer(e, t) {
|
|
1527
|
-
const s = this.consumerTracker.getConsumerInfo(e);
|
|
1528
|
-
return !s || !s.hasRendered ? !0 : this.consumerTracker.shouldNotifyConsumer(e, t);
|
|
1529
|
-
}
|
|
1530
|
-
updateLastNotified(e) {
|
|
1531
|
-
this.consumerTracker.updateLastNotified(e), this.consumerTracker.setHasRendered(e, !0);
|
|
1532
|
-
}
|
|
1533
|
-
resetConsumerTracking() {
|
|
1534
|
-
this.consumerTracker.resetTracking(this.componentRef.current);
|
|
2056
|
+
trackAccess(e, t, s, i) {
|
|
2057
|
+
const n = t === "class" ? `_class.${s}` : s;
|
|
2058
|
+
this.trackedPaths.add(n), this.subscriptionId ? this.blocInstance.trackAccess(this.subscriptionId, n, i) : (this.pendingTrackedPaths.add(n), o.config.logLevel === "debug" && o.log(`[BlacAdapter] trackAccess storing pending path: ${s}`));
|
|
1535
2059
|
}
|
|
1536
2060
|
updateBlocInstance() {
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
2061
|
+
let e = this.options?.instanceId;
|
|
2062
|
+
if (!e && this.options?.staticProps) {
|
|
2063
|
+
const t = N(this.options.staticProps);
|
|
2064
|
+
t && (e = t);
|
|
2065
|
+
}
|
|
2066
|
+
return this.blocInstance = o.instance.getBloc(this.blocConstructor, {
|
|
2067
|
+
constructorParams: this.options?.staticProps,
|
|
2068
|
+
id: e,
|
|
1541
2069
|
instanceRef: this.id
|
|
1542
2070
|
}), this.blocInstance;
|
|
1543
2071
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
2072
|
+
createSubscription = (e) => {
|
|
2073
|
+
if (this.isUsingDependencies && this.options?.dependencies)
|
|
2074
|
+
this.unsubscribe = this.blocInstance.subscribeWithSelector(
|
|
2075
|
+
(t) => this.options.dependencies(this.blocInstance),
|
|
2076
|
+
(t) => {
|
|
2077
|
+
this.hasDependencyValuesChanged(
|
|
2078
|
+
this.dependencyValues,
|
|
2079
|
+
t
|
|
2080
|
+
) && (this.dependencyValues = t, e.onChange());
|
|
2081
|
+
}
|
|
1553
2082
|
);
|
|
1554
|
-
|
|
2083
|
+
else {
|
|
2084
|
+
const t = new WeakRef(this.componentRef.current);
|
|
2085
|
+
this.unsubscribe = this.blocInstance.subscribeComponent(
|
|
2086
|
+
t,
|
|
2087
|
+
e.onChange
|
|
2088
|
+
);
|
|
2089
|
+
const s = this.blocInstance._subscriptionManager.subscriptions;
|
|
2090
|
+
if (this.subscriptionId = Array.from(s.keys()).pop(), this.subscriptionId && this.pendingTrackedPaths.size > 0) {
|
|
2091
|
+
for (const i of this.pendingTrackedPaths)
|
|
2092
|
+
this.blocInstance.trackAccess(this.subscriptionId, i);
|
|
2093
|
+
this.pendingTrackedPaths.clear();
|
|
2094
|
+
}
|
|
1555
2095
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
2096
|
+
return () => {
|
|
2097
|
+
this.unsubscribe && (this.unsubscribe(), this.unsubscribe = void 0, this.subscriptionId = void 0);
|
|
2098
|
+
};
|
|
2099
|
+
};
|
|
2100
|
+
hasDependencyValuesChanged = (e, t) => {
|
|
1559
2101
|
if (!e || e.length !== t.length) return !0;
|
|
1560
2102
|
for (let s = 0; s < e.length; s++)
|
|
1561
2103
|
if (!Object.is(e[s], t[s]))
|
|
1562
2104
|
return !0;
|
|
1563
2105
|
return !1;
|
|
2106
|
+
};
|
|
2107
|
+
getStateProxy = () => {
|
|
2108
|
+
if (this.isUsingDependencies || !o.config.proxyDependencyTracking)
|
|
2109
|
+
return this.blocInstance.state;
|
|
2110
|
+
const e = this.blocInstance.state;
|
|
2111
|
+
return this.cachedStateProxy && this.lastProxiedState === e ? this.cachedStateProxy : (this.lastProxiedState = e, this.cachedStateProxy = this.createStateProxy({ target: e }), this.cachedStateProxy);
|
|
2112
|
+
};
|
|
2113
|
+
getBlocProxy = () => this.isUsingDependencies || !o.config.proxyDependencyTracking ? this.blocInstance : this.cachedBlocProxy ? this.cachedBlocProxy : (this.cachedBlocProxy = this.createClassProxy({ target: this.blocInstance }), this.cachedBlocProxy);
|
|
2114
|
+
createStateProxy = (e) => $.createStateProxy({
|
|
2115
|
+
target: e.target,
|
|
2116
|
+
consumerRef: this.componentRef.current,
|
|
2117
|
+
consumerTracker: this
|
|
2118
|
+
});
|
|
2119
|
+
createClassProxy = (e) => $.createClassProxy({
|
|
2120
|
+
target: e.target,
|
|
2121
|
+
consumerRef: this.componentRef.current,
|
|
2122
|
+
consumerTracker: this
|
|
2123
|
+
});
|
|
2124
|
+
// Lifecycle methods
|
|
2125
|
+
mount = () => {
|
|
2126
|
+
this.hasMounted = !0, this.mountCount++, this.mountTime = Date.now(), this.options?.onMount && this.options.onMount(this.blocInstance), this.isUsingDependencies && this.options?.dependencies && (this.dependencyValues = this.options.dependencies(this.blocInstance));
|
|
2127
|
+
const e = this.getAdapterMetadata();
|
|
2128
|
+
o.getInstance().plugins.notifyAdapterMount(this, e);
|
|
2129
|
+
};
|
|
2130
|
+
unmount = () => {
|
|
2131
|
+
if (this.unmountTime = Date.now(), this.unsubscribe && (this.unsubscribe(), this.unsubscribe = void 0, this.subscriptionId = void 0), this.options?.onUnmount)
|
|
2132
|
+
try {
|
|
2133
|
+
this.options.onUnmount(this.blocInstance);
|
|
2134
|
+
} catch (t) {
|
|
2135
|
+
console.error("Error in onUnmount hook:", t);
|
|
2136
|
+
}
|
|
2137
|
+
const e = this.getAdapterMetadata();
|
|
2138
|
+
o.getInstance().plugins.notifyAdapterUnmount(this, e);
|
|
2139
|
+
};
|
|
2140
|
+
// Reset tracking for next render
|
|
2141
|
+
resetTracking() {
|
|
2142
|
+
if (this.trackedPaths.clear(), this.pendingTrackedPaths.clear(), this.subscriptionId) {
|
|
2143
|
+
const e = this.blocInstance._subscriptionManager.subscriptions.get(this.subscriptionId);
|
|
2144
|
+
e && e.dependencies && e.dependencies.clear();
|
|
2145
|
+
}
|
|
1564
2146
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
2147
|
+
// Set component name for rerender logging
|
|
2148
|
+
setComponentName(e) {
|
|
2149
|
+
this.componentName = e;
|
|
2150
|
+
}
|
|
2151
|
+
// Notify plugins about render
|
|
2152
|
+
notifyRender() {
|
|
2153
|
+
this.renderCount++, this.isUsingDependencies && this.options?.dependencies && (this.lastDependencyValues = this.dependencyValues, this.dependencyValues = this.options.dependencies(this.blocInstance));
|
|
2154
|
+
const e = this.getAdapterMetadata();
|
|
2155
|
+
o.getInstance().plugins.notifyAdapterRender(this, e);
|
|
2156
|
+
}
|
|
2157
|
+
// Get adapter metadata for plugins
|
|
2158
|
+
getAdapterMetadata() {
|
|
2159
|
+
return {
|
|
2160
|
+
componentName: this.componentName,
|
|
2161
|
+
blocInstance: this.blocInstance,
|
|
2162
|
+
renderCount: this.renderCount,
|
|
2163
|
+
trackedPaths: Array.from(this.trackedPaths),
|
|
2164
|
+
isUsingDependencies: this.isUsingDependencies,
|
|
2165
|
+
lastState: this.lastState,
|
|
2166
|
+
lastDependencyValues: this.lastDependencyValues,
|
|
2167
|
+
currentDependencyValues: this.dependencyValues
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
// Get value at a dot-notated path
|
|
2171
|
+
getValueAtPath(e, t) {
|
|
2172
|
+
const s = t.split(".");
|
|
2173
|
+
let i = e;
|
|
2174
|
+
for (const n of s) {
|
|
2175
|
+
if (i == null) return;
|
|
2176
|
+
i = i[n];
|
|
2177
|
+
}
|
|
2178
|
+
return i;
|
|
2179
|
+
}
|
|
2180
|
+
// Get paths that changed between states
|
|
2181
|
+
getStateChangedPaths(e, t) {
|
|
2182
|
+
const s = [];
|
|
2183
|
+
if (this.trackedPaths.size > 0)
|
|
2184
|
+
for (const i of this.trackedPaths) {
|
|
2185
|
+
if (i.startsWith("_class.")) continue;
|
|
2186
|
+
const n = this.getValueAtPath(e, i), a = this.getValueAtPath(t, i);
|
|
2187
|
+
Object.is(n, a) || s.push(i);
|
|
2188
|
+
}
|
|
2189
|
+
else if (e !== t) {
|
|
2190
|
+
const i = this.getDeepChangedPaths(e, t);
|
|
2191
|
+
if (i.length > 0)
|
|
2192
|
+
return i;
|
|
2193
|
+
s.push("(entire state)");
|
|
2194
|
+
}
|
|
2195
|
+
return s;
|
|
2196
|
+
}
|
|
2197
|
+
// Deep comparison to find all changed paths
|
|
2198
|
+
getDeepChangedPaths(e, t, s = "") {
|
|
2199
|
+
const i = [];
|
|
2200
|
+
if (e === t) return i;
|
|
2201
|
+
if (e == null || t == null)
|
|
2202
|
+
return i.push(s || "(root)"), i;
|
|
2203
|
+
if (typeof e != "object" || typeof t != "object")
|
|
2204
|
+
return e !== t && i.push(s || "(root)"), i;
|
|
2205
|
+
if (Array.isArray(e) || Array.isArray(t)) {
|
|
2206
|
+
if (!Array.isArray(e) || !Array.isArray(t) || e.length !== t.length)
|
|
2207
|
+
return i.push(s || "(root)"), i;
|
|
2208
|
+
for (let a = 0; a < e.length; a++) {
|
|
2209
|
+
const c = s ? `${s}[${a}]` : `[${a}]`;
|
|
2210
|
+
i.push(
|
|
2211
|
+
...this.getDeepChangedPaths(e[a], t[a], c)
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
2214
|
+
return i;
|
|
2215
|
+
}
|
|
2216
|
+
const n = /* @__PURE__ */ new Set([...Object.keys(e), ...Object.keys(t)]);
|
|
2217
|
+
for (const a of n) {
|
|
2218
|
+
const c = s ? `${s}.${a}` : a;
|
|
2219
|
+
if (!(a in e))
|
|
2220
|
+
i.push(`${c} (added)`);
|
|
2221
|
+
else if (!(a in t))
|
|
2222
|
+
i.push(`${c} (removed)`);
|
|
2223
|
+
else {
|
|
2224
|
+
const l = e[a], h = t[a];
|
|
2225
|
+
if (!Object.is(l, h))
|
|
2226
|
+
if (typeof l != "object" || typeof h != "object" || l === null || h === null)
|
|
2227
|
+
i.push(c);
|
|
2228
|
+
else {
|
|
2229
|
+
const p = this.getDeepChangedPaths(
|
|
2230
|
+
l,
|
|
2231
|
+
h,
|
|
2232
|
+
c
|
|
2233
|
+
);
|
|
2234
|
+
p.length > 0 ? i.push(...p) : i.push(c);
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return i;
|
|
2239
|
+
}
|
|
2240
|
+
// Get last rerender reason
|
|
2241
|
+
getLastRerenderReason() {
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
1569
2244
|
export {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
2245
|
+
o as Blac,
|
|
2246
|
+
G as BlacAdapter,
|
|
2247
|
+
m as BlacError,
|
|
2248
|
+
R as Bloc,
|
|
2249
|
+
C as BlocBase,
|
|
2250
|
+
B as BlocLifecycleManager,
|
|
2251
|
+
u as BlocLifecycleState,
|
|
2252
|
+
w as BlocPluginRegistry,
|
|
2253
|
+
j as BlocTest,
|
|
2254
|
+
O as Cubit,
|
|
2255
|
+
P as DefaultErrorStrategy,
|
|
2256
|
+
v as ErrorCategory,
|
|
2257
|
+
f as ErrorManager,
|
|
2258
|
+
y as ErrorSeverity,
|
|
2259
|
+
W as MemoryLeakDetector,
|
|
2260
|
+
z as MockBloc,
|
|
2261
|
+
q as MockCubit,
|
|
2262
|
+
L as PropsUpdated,
|
|
2263
|
+
$ as ProxyFactory,
|
|
2264
|
+
F as RerenderLogger,
|
|
2265
|
+
E as SubscriptionManager,
|
|
2266
|
+
T as SystemPluginRegistry,
|
|
2267
|
+
M as createBlocProxy,
|
|
2268
|
+
_ as createStateProxy,
|
|
2269
|
+
N as generateInstanceIdFromProps,
|
|
2270
|
+
A as generateUUID,
|
|
2271
|
+
x as handleError,
|
|
2272
|
+
H as setBlacInstanceManager,
|
|
2273
|
+
V as shallowEqual
|
|
1587
2274
|
};
|
|
1588
2275
|
//# sourceMappingURL=index.es.js.map
|