@creact-labs/creact 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -22
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +88 -0
- package/dist/index.d.ts +19 -44
- package/dist/index.js +20 -68
- package/dist/jsx/index.d.ts +2 -0
- package/dist/jsx/index.js +1 -0
- package/dist/jsx/jsx-dev-runtime.d.ts +4 -0
- package/dist/jsx/jsx-dev-runtime.js +4 -0
- package/dist/jsx/jsx-runtime.d.ts +38 -0
- package/dist/jsx/jsx-runtime.js +38 -0
- package/dist/jsx/types.d.ts +12 -0
- package/dist/jsx/types.js +4 -0
- package/dist/primitives/context.d.ts +34 -0
- package/dist/primitives/context.js +63 -0
- package/dist/primitives/index.d.ts +3 -0
- package/dist/primitives/index.js +3 -0
- package/dist/primitives/instance.d.ts +72 -0
- package/dist/primitives/instance.js +235 -0
- package/dist/primitives/store.d.ts +22 -0
- package/dist/primitives/store.js +97 -0
- package/dist/provider/backend.d.ts +110 -0
- package/dist/provider/backend.js +37 -0
- package/dist/provider/interface.d.ts +48 -0
- package/dist/provider/interface.js +39 -0
- package/dist/reactive/effect.d.ts +11 -0
- package/dist/reactive/effect.js +42 -0
- package/dist/reactive/index.d.ts +3 -0
- package/dist/reactive/index.js +3 -0
- package/dist/reactive/signal.d.ts +32 -0
- package/dist/reactive/signal.js +60 -0
- package/dist/reactive/tracking.d.ts +41 -0
- package/dist/reactive/tracking.js +161 -0
- package/dist/runtime/fiber.d.ts +21 -0
- package/dist/runtime/fiber.js +16 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/reconcile.d.ts +66 -0
- package/dist/runtime/reconcile.js +210 -0
- package/dist/runtime/render.d.ts +42 -0
- package/dist/runtime/render.js +231 -0
- package/dist/runtime/run.d.ts +119 -0
- package/dist/runtime/run.js +334 -0
- package/dist/runtime/state-machine.d.ts +95 -0
- package/dist/runtime/state-machine.js +209 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.js +4 -0
- package/package.json +29 -24
- package/dist/cli/commands/BuildCommand.d.ts +0 -40
- package/dist/cli/commands/BuildCommand.js +0 -151
- package/dist/cli/commands/DeployCommand.d.ts +0 -38
- package/dist/cli/commands/DeployCommand.js +0 -194
- package/dist/cli/commands/DevCommand.d.ts +0 -52
- package/dist/cli/commands/DevCommand.js +0 -394
- package/dist/cli/commands/PlanCommand.d.ts +0 -39
- package/dist/cli/commands/PlanCommand.js +0 -164
- package/dist/cli/commands/index.d.ts +0 -36
- package/dist/cli/commands/index.js +0 -43
- package/dist/cli/core/ArgumentParser.d.ts +0 -46
- package/dist/cli/core/ArgumentParser.js +0 -127
- package/dist/cli/core/BaseCommand.d.ts +0 -75
- package/dist/cli/core/BaseCommand.js +0 -95
- package/dist/cli/core/CLIContext.d.ts +0 -68
- package/dist/cli/core/CLIContext.js +0 -183
- package/dist/cli/core/CommandRegistry.d.ts +0 -64
- package/dist/cli/core/CommandRegistry.js +0 -89
- package/dist/cli/core/index.d.ts +0 -36
- package/dist/cli/core/index.js +0 -43
- package/dist/cli/index.d.ts +0 -35
- package/dist/cli/index.js +0 -100
- package/dist/cli/output.d.ts +0 -204
- package/dist/cli/output.js +0 -437
- package/dist/cli/utils.d.ts +0 -59
- package/dist/cli/utils.js +0 -76
- package/dist/context/createContext.d.ts +0 -90
- package/dist/context/createContext.js +0 -113
- package/dist/context/index.d.ts +0 -30
- package/dist/context/index.js +0 -35
- package/dist/core/CReact.d.ts +0 -409
- package/dist/core/CReact.js +0 -1151
- package/dist/core/CloudDOMBuilder.d.ts +0 -447
- package/dist/core/CloudDOMBuilder.js +0 -1234
- package/dist/core/ContextDependencyTracker.d.ts +0 -165
- package/dist/core/ContextDependencyTracker.js +0 -448
- package/dist/core/ErrorRecoveryManager.d.ts +0 -145
- package/dist/core/ErrorRecoveryManager.js +0 -443
- package/dist/core/EventBus.d.ts +0 -91
- package/dist/core/EventBus.js +0 -185
- package/dist/core/ProviderOutputTracker.d.ts +0 -211
- package/dist/core/ProviderOutputTracker.js +0 -476
- package/dist/core/ReactiveUpdateQueue.d.ts +0 -76
- package/dist/core/ReactiveUpdateQueue.js +0 -121
- package/dist/core/Reconciler.d.ts +0 -415
- package/dist/core/Reconciler.js +0 -1044
- package/dist/core/RenderScheduler.d.ts +0 -153
- package/dist/core/RenderScheduler.js +0 -519
- package/dist/core/Renderer.d.ts +0 -336
- package/dist/core/Renderer.js +0 -944
- package/dist/core/Runtime.d.ts +0 -246
- package/dist/core/Runtime.js +0 -640
- package/dist/core/StateBindingManager.d.ts +0 -121
- package/dist/core/StateBindingManager.js +0 -309
- package/dist/core/StateMachine.d.ts +0 -441
- package/dist/core/StateMachine.js +0 -883
- package/dist/core/StructuralChangeDetector.d.ts +0 -140
- package/dist/core/StructuralChangeDetector.js +0 -363
- package/dist/core/Validator.d.ts +0 -127
- package/dist/core/Validator.js +0 -279
- package/dist/core/errors.d.ts +0 -153
- package/dist/core/errors.js +0 -202
- package/dist/core/index.d.ts +0 -38
- package/dist/core/index.js +0 -64
- package/dist/core/types.d.ts +0 -265
- package/dist/core/types.js +0 -48
- package/dist/hooks/context.d.ts +0 -147
- package/dist/hooks/context.js +0 -334
- package/dist/hooks/useContext.d.ts +0 -113
- package/dist/hooks/useContext.js +0 -169
- package/dist/hooks/useEffect.d.ts +0 -105
- package/dist/hooks/useEffect.js +0 -540
- package/dist/hooks/useInstance.d.ts +0 -139
- package/dist/hooks/useInstance.js +0 -455
- package/dist/hooks/useState.d.ts +0 -120
- package/dist/hooks/useState.js +0 -298
- package/dist/jsx.d.ts +0 -143
- package/dist/jsx.js +0 -76
- package/dist/providers/DummyBackendProvider.d.ts +0 -193
- package/dist/providers/DummyBackendProvider.js +0 -189
- package/dist/providers/DummyCloudProvider.d.ts +0 -128
- package/dist/providers/DummyCloudProvider.js +0 -157
- package/dist/providers/IBackendProvider.d.ts +0 -177
- package/dist/providers/IBackendProvider.js +0 -31
- package/dist/providers/ICloudProvider.d.ts +0 -230
- package/dist/providers/ICloudProvider.js +0 -31
- package/dist/providers/index.d.ts +0 -31
- package/dist/providers/index.js +0 -31
- package/dist/test-event-callbacks.d.ts +0 -0
- package/dist/test-event-callbacks.js +0 -1
- package/dist/utils/Logger.d.ts +0 -144
- package/dist/utils/Logger.js +0 -220
- package/dist/utils/Output.d.ts +0 -161
- package/dist/utils/Output.js +0 -401
- package/dist/utils/deepEqual.d.ts +0 -71
- package/dist/utils/deepEqual.js +0 -276
- package/dist/utils/naming.d.ts +0 -241
- package/dist/utils/naming.js +0 -376
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
|
|
8
|
-
* You may obtain a copy of the License at
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
-
|
|
18
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
-
|
|
20
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
-
|
|
22
|
-
* See the License for the specific language governing permissions and
|
|
23
|
-
|
|
24
|
-
* limitations under the License.
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
* Copyright 2025 Daniel Coutinho Ribeiro
|
|
29
|
-
|
|
30
|
-
*/
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.ProviderOutputTracker = void 0;
|
|
33
|
-
const Logger_1 = require("../utils/Logger");
|
|
34
|
-
const logger = Logger_1.LoggerFactory.getLogger('hooks');
|
|
35
|
-
/**
|
|
36
|
-
* ProviderOutputTracker - Tracks useInstance calls and their output dependencies
|
|
37
|
-
*
|
|
38
|
-
* Key Features:
|
|
39
|
-
* - Track which components use which provider instances
|
|
40
|
-
* - Detect when provider outputs change
|
|
41
|
-
* - Notify bound components of output changes
|
|
42
|
-
* - Event hook integration for tooling and debugging
|
|
43
|
-
* - REQ-6.2, 6.3, 6.4: Track output reads for automatic binding creation
|
|
44
|
-
*/
|
|
45
|
-
class ProviderOutputTracker {
|
|
46
|
-
constructor(eventHooks) {
|
|
47
|
-
this.instanceBindings = new Map();
|
|
48
|
-
this.instanceOutputs = new Map();
|
|
49
|
-
// REQ-6.2, 6.3: Access tracking sessions for dependency analysis
|
|
50
|
-
this.activeSessions = new Map();
|
|
51
|
-
this.eventHooks = eventHooks;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Track a useInstance call - bind a fiber to a CloudDOM node
|
|
55
|
-
* This is called whenever useInstance is called in a component
|
|
56
|
-
*/
|
|
57
|
-
trackInstance(node, fiber) {
|
|
58
|
-
// Initialize bindings for this instance if not exists
|
|
59
|
-
if (!this.instanceBindings.has(node.id)) {
|
|
60
|
-
this.instanceBindings.set(node.id, new Set());
|
|
61
|
-
}
|
|
62
|
-
// Add the fiber to the bindings
|
|
63
|
-
this.instanceBindings.get(node.id).add(fiber);
|
|
64
|
-
// Store initial outputs if available
|
|
65
|
-
if (node.outputs) {
|
|
66
|
-
this.instanceOutputs.set(node.id, { ...node.outputs });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get all fibers bound to a specific instance
|
|
71
|
-
*/
|
|
72
|
-
getBindingsForInstance(nodeId) {
|
|
73
|
-
return this.instanceBindings.get(nodeId) || new Set();
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Update outputs for an instance and detect changes
|
|
77
|
-
* Returns array of output changes that occurred
|
|
78
|
-
*/
|
|
79
|
-
updateInstanceOutputs(nodeId, newOutputs) {
|
|
80
|
-
const previousOutputs = this.instanceOutputs.get(nodeId) || {};
|
|
81
|
-
const changes = [];
|
|
82
|
-
const boundFibers = Array.from(this.getBindingsForInstance(nodeId));
|
|
83
|
-
// Check for changed outputs
|
|
84
|
-
for (const [outputKey, newValue] of Object.entries(newOutputs)) {
|
|
85
|
-
const previousValue = previousOutputs[outputKey];
|
|
86
|
-
if (previousValue !== newValue) {
|
|
87
|
-
changes.push({
|
|
88
|
-
nodeId,
|
|
89
|
-
outputKey,
|
|
90
|
-
previousValue,
|
|
91
|
-
newValue,
|
|
92
|
-
affectedFibers: boundFibers,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Check for removed outputs
|
|
97
|
-
for (const [outputKey, previousValue] of Object.entries(previousOutputs)) {
|
|
98
|
-
if (!(outputKey in newOutputs)) {
|
|
99
|
-
changes.push({
|
|
100
|
-
nodeId,
|
|
101
|
-
outputKey,
|
|
102
|
-
previousValue,
|
|
103
|
-
newValue: undefined,
|
|
104
|
-
affectedFibers: boundFibers,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// Update stored outputs
|
|
109
|
-
this.instanceOutputs.set(nodeId, { ...newOutputs });
|
|
110
|
-
return changes;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Notify bound components of output changes
|
|
114
|
-
* This triggers re-renders for affected components
|
|
115
|
-
*/
|
|
116
|
-
notifyOutputChanges(changes) {
|
|
117
|
-
for (const change of changes) {
|
|
118
|
-
const boundFibers = this.getBindingsForInstance(change.nodeId);
|
|
119
|
-
for (const fiber of boundFibers) {
|
|
120
|
-
try {
|
|
121
|
-
// Emit render start event for tooling
|
|
122
|
-
this.eventHooks?.onRenderStart(fiber);
|
|
123
|
-
// Mark fiber as needing re-render due to output change
|
|
124
|
-
if (!fiber.reactiveState) {
|
|
125
|
-
fiber.reactiveState = {
|
|
126
|
-
renderCount: 0,
|
|
127
|
-
isDirty: true,
|
|
128
|
-
updatePending: true,
|
|
129
|
-
lastRenderReason: 'output-update',
|
|
130
|
-
lastRenderTime: Date.now(),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
fiber.reactiveState.lastRenderReason = 'output-update';
|
|
135
|
-
fiber.reactiveState.lastRenderTime = Date.now();
|
|
136
|
-
fiber.reactiveState.isDirty = true;
|
|
137
|
-
fiber.reactiveState.updatePending = true;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
this.eventHooks?.onError(error, fiber);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Process a batch of CloudDOM nodes and detect all output changes
|
|
148
|
-
* This is typically called after deployment completes
|
|
149
|
-
*/
|
|
150
|
-
processCloudDOMOutputs(nodes) {
|
|
151
|
-
const allChanges = [];
|
|
152
|
-
for (const node of nodes) {
|
|
153
|
-
if (node.outputs) {
|
|
154
|
-
const changes = this.updateInstanceOutputs(node.id, node.outputs);
|
|
155
|
-
allChanges.push(...changes);
|
|
156
|
-
}
|
|
157
|
-
// Process child nodes recursively
|
|
158
|
-
if (node.children && node.children.length > 0) {
|
|
159
|
-
const childChanges = this.processCloudDOMOutputs(node.children);
|
|
160
|
-
allChanges.push(...childChanges);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return allChanges;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Remove bindings for a specific fiber (cleanup)
|
|
167
|
-
*/
|
|
168
|
-
removeBindingsForFiber(fiber) {
|
|
169
|
-
for (const [nodeId, bindings] of this.instanceBindings) {
|
|
170
|
-
bindings.delete(fiber);
|
|
171
|
-
// Clean up empty binding sets
|
|
172
|
-
if (bindings.size === 0) {
|
|
173
|
-
this.instanceBindings.delete(nodeId);
|
|
174
|
-
this.instanceOutputs.delete(nodeId);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Remove bindings for a specific instance (when resource is deleted)
|
|
180
|
-
*/
|
|
181
|
-
removeBindingsForInstance(nodeId) {
|
|
182
|
-
this.instanceBindings.delete(nodeId);
|
|
183
|
-
this.instanceOutputs.delete(nodeId);
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Validate bindings and remove invalid ones
|
|
187
|
-
* This should be called periodically to clean up stale bindings
|
|
188
|
-
*/
|
|
189
|
-
validateBindings(validNodes) {
|
|
190
|
-
const invalidNodeIds = [];
|
|
191
|
-
for (const nodeId of this.instanceBindings.keys()) {
|
|
192
|
-
if (!validNodes.has(nodeId)) {
|
|
193
|
-
invalidNodeIds.push(nodeId);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
// Remove invalid bindings
|
|
197
|
-
for (const nodeId of invalidNodeIds) {
|
|
198
|
-
this.removeBindingsForInstance(nodeId);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Get current outputs for an instance
|
|
203
|
-
*/
|
|
204
|
-
getInstanceOutputs(nodeId) {
|
|
205
|
-
return this.instanceOutputs.get(nodeId);
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Check if an instance has any bound components
|
|
209
|
-
*/
|
|
210
|
-
hasBindings(nodeId) {
|
|
211
|
-
const bindings = this.instanceBindings.get(nodeId);
|
|
212
|
-
return bindings ? bindings.size > 0 : false;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Get all tracked instances
|
|
216
|
-
*/
|
|
217
|
-
getTrackedInstances() {
|
|
218
|
-
return Array.from(this.instanceBindings.keys());
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Get statistics about current bindings
|
|
222
|
-
*/
|
|
223
|
-
getBindingStats() {
|
|
224
|
-
let totalBindings = 0;
|
|
225
|
-
for (const bindings of this.instanceBindings.values()) {
|
|
226
|
-
totalBindings += bindings.size;
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
totalInstances: this.instanceBindings.size,
|
|
230
|
-
totalBindings,
|
|
231
|
-
instancesWithOutputs: this.instanceOutputs.size,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Get all bindings for debugging/inspection
|
|
236
|
-
*/
|
|
237
|
-
getAllBindings() {
|
|
238
|
-
const result = new Map();
|
|
239
|
-
for (const [nodeId, bindings] of this.instanceBindings) {
|
|
240
|
-
result.set(nodeId, {
|
|
241
|
-
fibers: Array.from(bindings),
|
|
242
|
-
outputs: this.instanceOutputs.get(nodeId),
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
return result;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Clear all bindings (for testing/cleanup)
|
|
249
|
-
*/
|
|
250
|
-
clearAllBindings() {
|
|
251
|
-
this.instanceBindings.clear();
|
|
252
|
-
this.instanceOutputs.clear();
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Create a snapshot of current state for comparison
|
|
256
|
-
* Useful for detecting changes between deployments
|
|
257
|
-
*/
|
|
258
|
-
createSnapshot() {
|
|
259
|
-
const bindingsSnapshot = new Map();
|
|
260
|
-
const outputsSnapshot = new Map();
|
|
261
|
-
// Create bindings snapshot with fiber paths instead of fiber objects
|
|
262
|
-
for (const [nodeId, fibers] of this.instanceBindings) {
|
|
263
|
-
bindingsSnapshot.set(nodeId, Array.from(fibers).map((f) => f.path.join('.')));
|
|
264
|
-
}
|
|
265
|
-
// Create outputs snapshot
|
|
266
|
-
for (const [nodeId, outputs] of this.instanceOutputs) {
|
|
267
|
-
outputsSnapshot.set(nodeId, { ...outputs });
|
|
268
|
-
}
|
|
269
|
-
return {
|
|
270
|
-
bindings: bindingsSnapshot,
|
|
271
|
-
outputs: outputsSnapshot,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Compare with a previous snapshot to detect changes
|
|
276
|
-
*/
|
|
277
|
-
compareWithSnapshot(snapshot) {
|
|
278
|
-
const bindingChanges = {
|
|
279
|
-
added: [],
|
|
280
|
-
removed: [],
|
|
281
|
-
modified: [],
|
|
282
|
-
};
|
|
283
|
-
const outputChanges = [];
|
|
284
|
-
// Check for binding changes
|
|
285
|
-
const currentNodeIds = new Set(this.instanceBindings.keys());
|
|
286
|
-
const snapshotNodeIds = new Set(snapshot.bindings.keys());
|
|
287
|
-
// Added instances
|
|
288
|
-
for (const nodeId of currentNodeIds) {
|
|
289
|
-
if (!snapshotNodeIds.has(nodeId)) {
|
|
290
|
-
bindingChanges.added.push(nodeId);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
// Removed instances
|
|
294
|
-
for (const nodeId of snapshotNodeIds) {
|
|
295
|
-
if (!currentNodeIds.has(nodeId)) {
|
|
296
|
-
bindingChanges.removed.push(nodeId);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
// Modified instances (binding changes)
|
|
300
|
-
for (const nodeId of currentNodeIds) {
|
|
301
|
-
if (snapshotNodeIds.has(nodeId)) {
|
|
302
|
-
const currentPaths = Array.from(this.instanceBindings.get(nodeId)).map((f) => f.path.join('.'));
|
|
303
|
-
const snapshotPaths = snapshot.bindings.get(nodeId);
|
|
304
|
-
if (JSON.stringify(currentPaths.sort()) !== JSON.stringify(snapshotPaths.sort())) {
|
|
305
|
-
bindingChanges.modified.push(nodeId);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
// Check for output changes
|
|
310
|
-
for (const nodeId of currentNodeIds) {
|
|
311
|
-
const currentOutputs = this.instanceOutputs.get(nodeId) || {};
|
|
312
|
-
const snapshotOutputs = snapshot.outputs.get(nodeId) || {};
|
|
313
|
-
const changes = this.compareOutputs(nodeId, snapshotOutputs, currentOutputs);
|
|
314
|
-
outputChanges.push(...changes);
|
|
315
|
-
}
|
|
316
|
-
return { bindingChanges, outputChanges };
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Compare two output objects and return changes
|
|
320
|
-
*/
|
|
321
|
-
compareOutputs(nodeId, previousOutputs, currentOutputs) {
|
|
322
|
-
const changes = [];
|
|
323
|
-
const boundFibers = Array.from(this.getBindingsForInstance(nodeId));
|
|
324
|
-
// Check for changed/added outputs
|
|
325
|
-
for (const [outputKey, currentValue] of Object.entries(currentOutputs)) {
|
|
326
|
-
const previousValue = previousOutputs[outputKey];
|
|
327
|
-
if (previousValue !== currentValue) {
|
|
328
|
-
changes.push({
|
|
329
|
-
nodeId,
|
|
330
|
-
outputKey,
|
|
331
|
-
previousValue,
|
|
332
|
-
newValue: currentValue,
|
|
333
|
-
affectedFibers: boundFibers,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
// Check for removed outputs
|
|
338
|
-
for (const [outputKey, previousValue] of Object.entries(previousOutputs)) {
|
|
339
|
-
if (!(outputKey in currentOutputs)) {
|
|
340
|
-
changes.push({
|
|
341
|
-
nodeId,
|
|
342
|
-
outputKey,
|
|
343
|
-
previousValue,
|
|
344
|
-
newValue: undefined,
|
|
345
|
-
affectedFibers: boundFibers,
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
return changes;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Extract output references for automatic state binding
|
|
353
|
-
* Creates proxy objects that can be used to automatically bind state to outputs
|
|
354
|
-
*/
|
|
355
|
-
extractOutputReferences(node) {
|
|
356
|
-
const outputReferences = {};
|
|
357
|
-
if (!node.outputs) {
|
|
358
|
-
return outputReferences;
|
|
359
|
-
}
|
|
360
|
-
// Create output reference objects for each output
|
|
361
|
-
for (const [outputKey, value] of Object.entries(node.outputs)) {
|
|
362
|
-
outputReferences[outputKey] = {
|
|
363
|
-
__providerOutput: {
|
|
364
|
-
nodeId: node.id,
|
|
365
|
-
outputKey,
|
|
366
|
-
value,
|
|
367
|
-
},
|
|
368
|
-
// Also include the actual value for direct access
|
|
369
|
-
valueOf: () => value,
|
|
370
|
-
toString: () => String(value),
|
|
371
|
-
// Make it behave like the actual value in most contexts
|
|
372
|
-
[Symbol.toPrimitive]: () => value,
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
return outputReferences;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Update outputs for a specific node and return changes
|
|
379
|
-
* This is an alias for updateInstanceOutputs for compatibility
|
|
380
|
-
*/
|
|
381
|
-
updateNodeOutputs(nodeId, newOutputs) {
|
|
382
|
-
return this.updateInstanceOutputs(nodeId, newOutputs);
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Process output changes and return affected fibers
|
|
386
|
-
* This is an alias for processCloudDOMOutputs for single node updates
|
|
387
|
-
*/
|
|
388
|
-
processOutputChanges(changes) {
|
|
389
|
-
const affectedFibers = new Set();
|
|
390
|
-
for (const change of changes) {
|
|
391
|
-
change.affectedFibers.forEach((fiber) => affectedFibers.add(fiber));
|
|
392
|
-
}
|
|
393
|
-
// Notify about the changes
|
|
394
|
-
this.notifyOutputChanges(changes);
|
|
395
|
-
return affectedFibers;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Get current outputs for a node
|
|
399
|
-
* This is an alias for getInstanceOutputs for compatibility
|
|
400
|
-
*/
|
|
401
|
-
getNodeOutputs(nodeId) {
|
|
402
|
-
return this.getInstanceOutputs(nodeId) || {};
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Start an access tracking session for a fiber
|
|
406
|
-
* REQ-6.2, 6.3: Track which outputs are accessed during execution
|
|
407
|
-
*
|
|
408
|
-
* @param fiber - Fiber node to track
|
|
409
|
-
*/
|
|
410
|
-
startAccessTracking(fiber) {
|
|
411
|
-
this.activeSessions.set(fiber, {
|
|
412
|
-
fiber,
|
|
413
|
-
startTime: Date.now(),
|
|
414
|
-
trackedOutputs: new Set(),
|
|
415
|
-
isActive: true,
|
|
416
|
-
});
|
|
417
|
-
logger.debug(`Started access tracking for ${fiber.path.join('.')}`);
|
|
418
|
-
}
|
|
419
|
-
/**
|
|
420
|
-
* End an access tracking session and return tracked outputs
|
|
421
|
-
* REQ-6.3, 6.4: Collect tracked outputs for binding creation
|
|
422
|
-
*
|
|
423
|
-
* @param fiber - Fiber node to end tracking for
|
|
424
|
-
* @returns Set of binding keys that were accessed
|
|
425
|
-
*/
|
|
426
|
-
endAccessTracking(fiber) {
|
|
427
|
-
const session = this.activeSessions.get(fiber);
|
|
428
|
-
if (!session) {
|
|
429
|
-
return new Set();
|
|
430
|
-
}
|
|
431
|
-
session.isActive = false;
|
|
432
|
-
this.activeSessions.delete(fiber);
|
|
433
|
-
logger.debug(`Ended access tracking for ${fiber.path.join('.')}, tracked ${session.trackedOutputs.size} outputs`);
|
|
434
|
-
return session.trackedOutputs;
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Track an output read during an active session
|
|
438
|
-
* REQ-6.2, 6.4: Record when outputs are accessed for binding creation
|
|
439
|
-
*
|
|
440
|
-
* @param nodeId - CloudDOM node ID
|
|
441
|
-
* @param outputKey - Output key that was accessed
|
|
442
|
-
* @param fiber - Fiber node that accessed the output
|
|
443
|
-
*/
|
|
444
|
-
trackOutputRead(nodeId, outputKey, fiber) {
|
|
445
|
-
const session = this.activeSessions.get(fiber);
|
|
446
|
-
if (session?.isActive) {
|
|
447
|
-
// Generate binding key for this output
|
|
448
|
-
const bindingKey = `${nodeId}.${outputKey}`;
|
|
449
|
-
session.trackedOutputs.add(bindingKey);
|
|
450
|
-
logger.debug(`Tracked output read: ${bindingKey} by ${fiber.path.join('.')}`);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Check if a fiber has an active tracking session
|
|
455
|
-
*
|
|
456
|
-
* @param fiber - Fiber node to check
|
|
457
|
-
* @returns True if tracking is active for this fiber
|
|
458
|
-
*/
|
|
459
|
-
isTrackingActive(fiber) {
|
|
460
|
-
const session = this.activeSessions.get(fiber);
|
|
461
|
-
return session?.isActive ?? false;
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Get all active tracking sessions (for debugging)
|
|
465
|
-
*/
|
|
466
|
-
getActiveSessions() {
|
|
467
|
-
return Array.from(this.activeSessions.values());
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Clear all active tracking sessions (for cleanup/testing)
|
|
471
|
-
*/
|
|
472
|
-
clearActiveSessions() {
|
|
473
|
-
this.activeSessions.clear();
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
exports.ProviderOutputTracker = ProviderOutputTracker;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
-
|
|
17
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
-
|
|
19
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
-
|
|
21
|
-
* See the License for the specific language governing permissions and
|
|
22
|
-
|
|
23
|
-
* limitations under the License.
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
* Copyright 2025 Daniel Coutinho Ribeiro
|
|
28
|
-
|
|
29
|
-
*/
|
|
30
|
-
import { FiberNode } from './types';
|
|
31
|
-
/**
|
|
32
|
-
* Global queue for tracking fibers that need re-rendering
|
|
33
|
-
*/
|
|
34
|
-
declare class ReactiveUpdateQueue {
|
|
35
|
-
private dirtyFibers;
|
|
36
|
-
private isProcessing;
|
|
37
|
-
/**
|
|
38
|
-
* Enqueue a fiber for re-rendering due to state change
|
|
39
|
-
* Uses Set to automatically deduplicate multiple setState calls
|
|
40
|
-
*
|
|
41
|
-
* @param fiber - Fiber node that needs re-rendering
|
|
42
|
-
*/
|
|
43
|
-
enqueue(fiber: FiberNode): void;
|
|
44
|
-
/**
|
|
45
|
-
* Flush the queue and return all dirty fibers
|
|
46
|
-
* Clears the queue after returning
|
|
47
|
-
*
|
|
48
|
-
* @returns Array of dirty fibers that need re-rendering
|
|
49
|
-
*/
|
|
50
|
-
flush(): FiberNode[];
|
|
51
|
-
/**
|
|
52
|
-
* Check if a fiber is in the queue
|
|
53
|
-
*
|
|
54
|
-
* @param fiber - Fiber to check
|
|
55
|
-
* @returns True if fiber is queued for re-render
|
|
56
|
-
*/
|
|
57
|
-
has(fiber: FiberNode): boolean;
|
|
58
|
-
/**
|
|
59
|
-
* Get current queue size
|
|
60
|
-
*
|
|
61
|
-
* @returns Number of fibers in queue
|
|
62
|
-
*/
|
|
63
|
-
size(): number;
|
|
64
|
-
/**
|
|
65
|
-
* Clear the queue without processing
|
|
66
|
-
* Used for cleanup or error recovery
|
|
67
|
-
*/
|
|
68
|
-
clear(): void;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Get the global reactive update queue
|
|
72
|
-
*
|
|
73
|
-
* @returns Global ReactiveUpdateQueue instance
|
|
74
|
-
*/
|
|
75
|
-
export declare function getReactiveUpdateQueue(): ReactiveUpdateQueue;
|
|
76
|
-
export {};
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
|
|
8
|
-
* You may obtain a copy of the License at
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
-
|
|
18
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
-
|
|
20
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
-
|
|
22
|
-
* See the License for the specific language governing permissions and
|
|
23
|
-
|
|
24
|
-
* limitations under the License.
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
* Copyright 2025 Daniel Coutinho Ribeiro
|
|
29
|
-
|
|
30
|
-
*/
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.getReactiveUpdateQueue = getReactiveUpdateQueue;
|
|
33
|
-
/**
|
|
34
|
-
* ReactiveUpdateQueue - Tracks fibers that need re-rendering due to state changes
|
|
35
|
-
*
|
|
36
|
-
* This queue handles user-triggered state changes (via useState) separately from
|
|
37
|
-
* provider-driven output changes. It enables the reactivity phase to detect and
|
|
38
|
-
* re-render components that have internal state changes.
|
|
39
|
-
*
|
|
40
|
-
* REQ-4.4: Fiber dirty tracking for state-driven re-renders
|
|
41
|
-
*/
|
|
42
|
-
const Logger_1 = require("../utils/Logger");
|
|
43
|
-
const logger = Logger_1.LoggerFactory.getLogger('hooks');
|
|
44
|
-
/**
|
|
45
|
-
* Global queue for tracking fibers that need re-rendering
|
|
46
|
-
*/
|
|
47
|
-
class ReactiveUpdateQueue {
|
|
48
|
-
constructor() {
|
|
49
|
-
this.dirtyFibers = new Set();
|
|
50
|
-
this.isProcessing = false;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Enqueue a fiber for re-rendering due to state change
|
|
54
|
-
* Uses Set to automatically deduplicate multiple setState calls
|
|
55
|
-
*
|
|
56
|
-
* @param fiber - Fiber node that needs re-rendering
|
|
57
|
-
*/
|
|
58
|
-
enqueue(fiber) {
|
|
59
|
-
if (this.isProcessing) {
|
|
60
|
-
// Don't enqueue during processing to avoid infinite loops
|
|
61
|
-
logger.debug(`Skipping enqueue during processing: ${fiber.path?.join('.')}`);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
this.dirtyFibers.add(fiber);
|
|
65
|
-
logger.debug(`Enqueued fiber: ${fiber.path?.join('.')} (queue size: ${this.dirtyFibers.size})`);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Flush the queue and return all dirty fibers
|
|
69
|
-
* Clears the queue after returning
|
|
70
|
-
*
|
|
71
|
-
* @returns Array of dirty fibers that need re-rendering
|
|
72
|
-
*/
|
|
73
|
-
flush() {
|
|
74
|
-
if (this.isProcessing) {
|
|
75
|
-
logger.debug('Already processing, returning empty array');
|
|
76
|
-
return [];
|
|
77
|
-
}
|
|
78
|
-
this.isProcessing = true;
|
|
79
|
-
const fibers = Array.from(this.dirtyFibers);
|
|
80
|
-
this.dirtyFibers.clear();
|
|
81
|
-
this.isProcessing = false;
|
|
82
|
-
logger.debug(`Flushed ${fibers.length} dirty fibers`);
|
|
83
|
-
return fibers;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Check if a fiber is in the queue
|
|
87
|
-
*
|
|
88
|
-
* @param fiber - Fiber to check
|
|
89
|
-
* @returns True if fiber is queued for re-render
|
|
90
|
-
*/
|
|
91
|
-
has(fiber) {
|
|
92
|
-
return this.dirtyFibers.has(fiber);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Get current queue size
|
|
96
|
-
*
|
|
97
|
-
* @returns Number of fibers in queue
|
|
98
|
-
*/
|
|
99
|
-
size() {
|
|
100
|
-
return this.dirtyFibers.size;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Clear the queue without processing
|
|
104
|
-
* Used for cleanup or error recovery
|
|
105
|
-
*/
|
|
106
|
-
clear() {
|
|
107
|
-
this.dirtyFibers.clear();
|
|
108
|
-
this.isProcessing = false;
|
|
109
|
-
logger.debug('Queue cleared');
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Global singleton instance
|
|
113
|
-
const globalQueue = new ReactiveUpdateQueue();
|
|
114
|
-
/**
|
|
115
|
-
* Get the global reactive update queue
|
|
116
|
-
*
|
|
117
|
-
* @returns Global ReactiveUpdateQueue instance
|
|
118
|
-
*/
|
|
119
|
-
function getReactiveUpdateQueue() {
|
|
120
|
-
return globalQueue;
|
|
121
|
-
}
|