@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,121 +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, OutputBinding, OutputChange } from './types';
|
|
31
|
-
/**
|
|
32
|
-
* StateBindingManager - Manages automatic binding between component state and provider outputs
|
|
33
|
-
*
|
|
34
|
-
* Key Features:
|
|
35
|
-
* - Automatic binding detection when setState is called with provider outputs
|
|
36
|
-
* - State update propagation when provider outputs change
|
|
37
|
-
* - Binding validation and cleanup
|
|
38
|
-
* - Tracks which state variables are bound to which provider outputs
|
|
39
|
-
*/
|
|
40
|
-
export declare class StateBindingManager {
|
|
41
|
-
private stateBindings;
|
|
42
|
-
private outputToBindings;
|
|
43
|
-
/**
|
|
44
|
-
* Automatically bind state to output when setState is called with a provider output value
|
|
45
|
-
* This is called internally when setState detects it's being set to a provider output
|
|
46
|
-
*/
|
|
47
|
-
bindStateToOutput(fiber: FiberNode, hookIndex: number, nodeId: string, outputKey: string, initialValue: any): void;
|
|
48
|
-
/**
|
|
49
|
-
* Check if a specific state hook is bound to a provider output
|
|
50
|
-
*/
|
|
51
|
-
isStateBoundToOutput(fiber: FiberNode, hookIndex: number): boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Get the output binding for a specific state hook
|
|
54
|
-
*/
|
|
55
|
-
getStateBinding(fiber: FiberNode, hookIndex: number): OutputBinding | undefined;
|
|
56
|
-
/**
|
|
57
|
-
* Update bound state when provider outputs change
|
|
58
|
-
* Returns list of fibers that were affected by the change
|
|
59
|
-
*
|
|
60
|
-
* REQ-4.2, 4.4, 4.5: Use internal setState to prevent circular dependencies
|
|
61
|
-
*/
|
|
62
|
-
updateBoundState(nodeId: string, outputKey: string, newValue: any): FiberNode[];
|
|
63
|
-
/**
|
|
64
|
-
* Fallback method for direct hook update when setState callback is not available
|
|
65
|
-
* REQ-4.5: Proper error handling and recovery
|
|
66
|
-
*
|
|
67
|
-
* @private
|
|
68
|
-
*/
|
|
69
|
-
private fallbackDirectUpdate;
|
|
70
|
-
/**
|
|
71
|
-
* Detect if a value is a provider output by checking if it has output-like properties
|
|
72
|
-
* This is used for automatic binding detection
|
|
73
|
-
*/
|
|
74
|
-
isProviderOutput(value: any): {
|
|
75
|
-
nodeId: string;
|
|
76
|
-
outputKey: string;
|
|
77
|
-
} | null;
|
|
78
|
-
/**
|
|
79
|
-
* Process output changes and return affected fibers
|
|
80
|
-
* This is called after deployment when provider outputs change
|
|
81
|
-
* Includes error isolation so one faulty fiber doesn't block the whole batch
|
|
82
|
-
*/
|
|
83
|
-
processOutputChanges(changes: OutputChange[]): FiberNode[];
|
|
84
|
-
/**
|
|
85
|
-
* Remove bindings for a specific fiber (cleanup)
|
|
86
|
-
* Note: With WeakMap, the fiber binding will be automatically garbage collected
|
|
87
|
-
* when the fiber is no longer referenced. This method cleans up reverse mappings.
|
|
88
|
-
*/
|
|
89
|
-
removeBindingsForFiber(fiber: FiberNode): void;
|
|
90
|
-
/**
|
|
91
|
-
* Remove bindings for a specific output (when resource is deleted)
|
|
92
|
-
*/
|
|
93
|
-
removeBindingsForOutput(nodeId: string, outputKey: string): void;
|
|
94
|
-
/**
|
|
95
|
-
* Validate all bindings and remove invalid ones
|
|
96
|
-
* This should be called periodically to clean up stale bindings
|
|
97
|
-
*/
|
|
98
|
-
validateBindings(validNodes: Set<string>): void;
|
|
99
|
-
/**
|
|
100
|
-
* Get all bindings for debugging/inspection
|
|
101
|
-
*/
|
|
102
|
-
getAllBindings(): Map<string, Array<{
|
|
103
|
-
fiber: FiberNode;
|
|
104
|
-
hookIndex: number;
|
|
105
|
-
binding: OutputBinding;
|
|
106
|
-
}>>;
|
|
107
|
-
/**
|
|
108
|
-
* Get statistics about current bindings
|
|
109
|
-
* Note: With WeakMap, we can't directly count bound fibers, so we estimate from reverse mappings
|
|
110
|
-
*/
|
|
111
|
-
getBindingStats(): {
|
|
112
|
-
totalBindings: number;
|
|
113
|
-
boundFibers: number;
|
|
114
|
-
boundOutputs: number;
|
|
115
|
-
};
|
|
116
|
-
/**
|
|
117
|
-
* Clear all bindings (for testing/cleanup)
|
|
118
|
-
* Note: WeakMap doesn't have clear(), so we clear the reverse mappings only
|
|
119
|
-
*/
|
|
120
|
-
clearAllBindings(): void;
|
|
121
|
-
}
|
|
@@ -1,309 +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.StateBindingManager = void 0;
|
|
33
|
-
const naming_1 = require("../utils/naming");
|
|
34
|
-
const Logger_1 = require("../utils/Logger");
|
|
35
|
-
const logger = Logger_1.LoggerFactory.getLogger('hooks');
|
|
36
|
-
/**
|
|
37
|
-
* StateBindingManager - Manages automatic binding between component state and provider outputs
|
|
38
|
-
*
|
|
39
|
-
* Key Features:
|
|
40
|
-
* - Automatic binding detection when setState is called with provider outputs
|
|
41
|
-
* - State update propagation when provider outputs change
|
|
42
|
-
* - Binding validation and cleanup
|
|
43
|
-
* - Tracks which state variables are bound to which provider outputs
|
|
44
|
-
*/
|
|
45
|
-
class StateBindingManager {
|
|
46
|
-
constructor() {
|
|
47
|
-
this.stateBindings = new WeakMap();
|
|
48
|
-
this.outputToBindings = new Map();
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Automatically bind state to output when setState is called with a provider output value
|
|
52
|
-
* This is called internally when setState detects it's being set to a provider output
|
|
53
|
-
*/
|
|
54
|
-
bindStateToOutput(fiber, hookIndex, nodeId, outputKey, initialValue) {
|
|
55
|
-
// Initialize fiber bindings if not exists
|
|
56
|
-
if (!this.stateBindings.has(fiber)) {
|
|
57
|
-
this.stateBindings.set(fiber, new Map());
|
|
58
|
-
}
|
|
59
|
-
// Create the binding
|
|
60
|
-
const binding = {
|
|
61
|
-
nodeId,
|
|
62
|
-
outputKey,
|
|
63
|
-
lastValue: initialValue,
|
|
64
|
-
bindTime: Date.now(),
|
|
65
|
-
};
|
|
66
|
-
// Store the binding
|
|
67
|
-
this.stateBindings.get(fiber).set(hookIndex, binding);
|
|
68
|
-
// Create reverse mapping for efficient lookups
|
|
69
|
-
const bindingKey = (0, naming_1.generateBindingKey)(nodeId, outputKey);
|
|
70
|
-
if (!this.outputToBindings.has(bindingKey)) {
|
|
71
|
-
this.outputToBindings.set(bindingKey, new Set());
|
|
72
|
-
}
|
|
73
|
-
this.outputToBindings.get(bindingKey).add({ fiber, hookIndex });
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Check if a specific state hook is bound to a provider output
|
|
77
|
-
*/
|
|
78
|
-
isStateBoundToOutput(fiber, hookIndex) {
|
|
79
|
-
const fiberBindings = this.stateBindings.get(fiber);
|
|
80
|
-
return fiberBindings?.has(hookIndex) ?? false;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Get the output binding for a specific state hook
|
|
84
|
-
*/
|
|
85
|
-
getStateBinding(fiber, hookIndex) {
|
|
86
|
-
return this.stateBindings.get(fiber)?.get(hookIndex);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Update bound state when provider outputs change
|
|
90
|
-
* Returns list of fibers that were affected by the change
|
|
91
|
-
*
|
|
92
|
-
* REQ-4.2, 4.4, 4.5: Use internal setState to prevent circular dependencies
|
|
93
|
-
*/
|
|
94
|
-
updateBoundState(nodeId, outputKey, newValue) {
|
|
95
|
-
const bindingKey = (0, naming_1.generateBindingKey)(nodeId, outputKey);
|
|
96
|
-
const bindings = this.outputToBindings.get(bindingKey);
|
|
97
|
-
if (!bindings) {
|
|
98
|
-
return []; // No bindings for this output
|
|
99
|
-
}
|
|
100
|
-
const affectedFibers = [];
|
|
101
|
-
Array.from(bindings).forEach(({ fiber, hookIndex }) => {
|
|
102
|
-
const binding = this.stateBindings.get(fiber)?.get(hookIndex);
|
|
103
|
-
if (!binding) {
|
|
104
|
-
return; // Binding was removed
|
|
105
|
-
}
|
|
106
|
-
// Only update if value actually changed
|
|
107
|
-
if (binding.lastValue !== newValue) {
|
|
108
|
-
// REQ-4.2, 4.4: Use stored setState callback with isInternalUpdate=true
|
|
109
|
-
// This prevents infinite binding loops
|
|
110
|
-
const setStateCallbacks = fiber.setStateCallbacks;
|
|
111
|
-
if (setStateCallbacks && setStateCallbacks[hookIndex]) {
|
|
112
|
-
try {
|
|
113
|
-
// Call setState with isInternalUpdate=true to skip binding creation
|
|
114
|
-
setStateCallbacks[hookIndex](newValue, true);
|
|
115
|
-
binding.lastValue = newValue;
|
|
116
|
-
binding.lastUpdate = Date.now();
|
|
117
|
-
affectedFibers.push(fiber);
|
|
118
|
-
logger.debug(`Updated bound state via internal setState: ${bindingKey}`);
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
logger.error(`Error calling internal setState for ${bindingKey}:`, error);
|
|
122
|
-
// REQ-4.5: Fallback to direct hook update if callback fails
|
|
123
|
-
this.fallbackDirectUpdate(fiber, hookIndex, newValue, binding, affectedFibers);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
// REQ-4.5: Fallback to direct hook update if callback not available
|
|
128
|
-
logger.debug(`No setState callback found, using direct update: ${bindingKey}`);
|
|
129
|
-
this.fallbackDirectUpdate(fiber, hookIndex, newValue, binding, affectedFibers);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
return affectedFibers;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Fallback method for direct hook update when setState callback is not available
|
|
137
|
-
* REQ-4.5: Proper error handling and recovery
|
|
138
|
-
*
|
|
139
|
-
* @private
|
|
140
|
-
*/
|
|
141
|
-
fallbackDirectUpdate(fiber, hookIndex, newValue, binding, affectedFibers) {
|
|
142
|
-
if (fiber.hooks && fiber.hooks[hookIndex] !== newValue) {
|
|
143
|
-
fiber.hooks[hookIndex] = newValue;
|
|
144
|
-
binding.lastValue = newValue;
|
|
145
|
-
binding.lastUpdate = Date.now();
|
|
146
|
-
affectedFibers.push(fiber);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Detect if a value is a provider output by checking if it has output-like properties
|
|
151
|
-
* This is used for automatic binding detection
|
|
152
|
-
*/
|
|
153
|
-
isProviderOutput(value) {
|
|
154
|
-
// Check if value has provider output metadata
|
|
155
|
-
if (value && typeof value === 'object' && value.__providerOutput) {
|
|
156
|
-
return {
|
|
157
|
-
nodeId: value.__providerOutput.nodeId,
|
|
158
|
-
outputKey: value.__providerOutput.outputKey,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
// Check if value is a CloudDOMNode output reference
|
|
162
|
-
if (value && typeof value === 'object' && value.__cloudDOMOutput) {
|
|
163
|
-
return {
|
|
164
|
-
nodeId: value.__cloudDOMOutput.nodeId,
|
|
165
|
-
outputKey: value.__cloudDOMOutput.outputKey,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Process output changes and return affected fibers
|
|
172
|
-
* This is called after deployment when provider outputs change
|
|
173
|
-
* Includes error isolation so one faulty fiber doesn't block the whole batch
|
|
174
|
-
*/
|
|
175
|
-
processOutputChanges(changes) {
|
|
176
|
-
const allAffectedFibers = new Set();
|
|
177
|
-
for (const change of changes) {
|
|
178
|
-
try {
|
|
179
|
-
const affectedFibers = this.updateBoundState(change.nodeId, change.outputKey, change.newValue);
|
|
180
|
-
affectedFibers.forEach((fiber) => allAffectedFibers.add(fiber));
|
|
181
|
-
}
|
|
182
|
-
catch (err) {
|
|
183
|
-
logger.warn(`Error updating bound state for ${change.nodeId}.${change.outputKey}:`, err);
|
|
184
|
-
// Continue processing other changes even if one fails
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return Array.from(allAffectedFibers);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Remove bindings for a specific fiber (cleanup)
|
|
191
|
-
* Note: With WeakMap, the fiber binding will be automatically garbage collected
|
|
192
|
-
* when the fiber is no longer referenced. This method cleans up reverse mappings.
|
|
193
|
-
*/
|
|
194
|
-
removeBindingsForFiber(fiber) {
|
|
195
|
-
const fiberBindings = this.stateBindings.get(fiber);
|
|
196
|
-
if (!fiberBindings) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
// Remove from reverse mappings
|
|
200
|
-
Array.from(fiberBindings.entries()).forEach(([hookIndex, binding]) => {
|
|
201
|
-
const bindingKey = (0, naming_1.generateBindingKey)(binding.nodeId, binding.outputKey);
|
|
202
|
-
const bindings = this.outputToBindings.get(bindingKey);
|
|
203
|
-
if (bindings) {
|
|
204
|
-
// Find and remove the specific binding
|
|
205
|
-
Array.from(bindings).forEach((bindingRef) => {
|
|
206
|
-
if (bindingRef.fiber === fiber && bindingRef.hookIndex === hookIndex) {
|
|
207
|
-
bindings.delete(bindingRef);
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
// Clean up empty sets
|
|
211
|
-
if (bindings.size === 0) {
|
|
212
|
-
this.outputToBindings.delete(bindingKey);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
// Remove fiber bindings
|
|
217
|
-
this.stateBindings.delete(fiber);
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Remove bindings for a specific output (when resource is deleted)
|
|
221
|
-
*/
|
|
222
|
-
removeBindingsForOutput(nodeId, outputKey) {
|
|
223
|
-
const bindingKey = (0, naming_1.generateBindingKey)(nodeId, outputKey);
|
|
224
|
-
const bindings = this.outputToBindings.get(bindingKey);
|
|
225
|
-
if (!bindings) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
// Remove from fiber bindings
|
|
229
|
-
Array.from(bindings).forEach(({ fiber, hookIndex }) => {
|
|
230
|
-
const fiberBindings = this.stateBindings.get(fiber);
|
|
231
|
-
if (fiberBindings) {
|
|
232
|
-
fiberBindings.delete(hookIndex);
|
|
233
|
-
// Clean up empty fiber bindings
|
|
234
|
-
if (fiberBindings.size === 0) {
|
|
235
|
-
this.stateBindings.delete(fiber);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
// Remove reverse mapping
|
|
240
|
-
this.outputToBindings.delete(bindingKey);
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Validate all bindings and remove invalid ones
|
|
244
|
-
* This should be called periodically to clean up stale bindings
|
|
245
|
-
*/
|
|
246
|
-
validateBindings(validNodes) {
|
|
247
|
-
const invalidBindings = [];
|
|
248
|
-
// Find invalid bindings
|
|
249
|
-
Array.from(this.outputToBindings.keys()).forEach((bindingKey) => {
|
|
250
|
-
const { nodeId, outputKey } = (0, naming_1.parseBindingKey)(bindingKey);
|
|
251
|
-
if (!validNodes.has(nodeId)) {
|
|
252
|
-
invalidBindings.push({ nodeId, outputKey });
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
// Remove invalid bindings
|
|
256
|
-
for (const { nodeId, outputKey } of invalidBindings) {
|
|
257
|
-
this.removeBindingsForOutput(nodeId, outputKey);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Get all bindings for debugging/inspection
|
|
262
|
-
*/
|
|
263
|
-
getAllBindings() {
|
|
264
|
-
const result = new Map();
|
|
265
|
-
Array.from(this.outputToBindings.entries()).forEach(([bindingKey, bindings]) => {
|
|
266
|
-
const bindingList = [];
|
|
267
|
-
Array.from(bindings).forEach(({ fiber, hookIndex }) => {
|
|
268
|
-
const binding = this.stateBindings.get(fiber)?.get(hookIndex);
|
|
269
|
-
if (binding) {
|
|
270
|
-
bindingList.push({ fiber, hookIndex, binding });
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
if (bindingList.length > 0) {
|
|
274
|
-
result.set(bindingKey, bindingList);
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
return result;
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Get statistics about current bindings
|
|
281
|
-
* Note: With WeakMap, we can't directly count bound fibers, so we estimate from reverse mappings
|
|
282
|
-
*/
|
|
283
|
-
getBindingStats() {
|
|
284
|
-
let totalBindings = 0;
|
|
285
|
-
const uniqueFibers = new Set();
|
|
286
|
-
// Count bindings and unique fibers from reverse mappings
|
|
287
|
-
Array.from(this.outputToBindings.values()).forEach((bindings) => {
|
|
288
|
-
totalBindings += bindings.size;
|
|
289
|
-
Array.from(bindings).forEach(({ fiber }) => {
|
|
290
|
-
uniqueFibers.add(fiber);
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
return {
|
|
294
|
-
totalBindings,
|
|
295
|
-
boundFibers: uniqueFibers.size,
|
|
296
|
-
boundOutputs: this.outputToBindings.size,
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Clear all bindings (for testing/cleanup)
|
|
301
|
-
* Note: WeakMap doesn't have clear(), so we clear the reverse mappings only
|
|
302
|
-
*/
|
|
303
|
-
clearAllBindings() {
|
|
304
|
-
// WeakMap doesn't have clear() method, but clearing outputToBindings
|
|
305
|
-
// will effectively orphan all the WeakMap entries for GC
|
|
306
|
-
this.outputToBindings.clear();
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
exports.StateBindingManager = StateBindingManager;
|