@vib3code/sdk 2.0.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/CHANGELOG.md +118 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
- package/DOCS/CI_TESTING.md +38 -0
- package/DOCS/CLI_ONBOARDING.md +75 -0
- package/DOCS/CONTROL_REFERENCE.md +64 -0
- package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
- package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
- package/DOCS/ENV_SETUP.md +189 -0
- package/DOCS/EXPORT_FORMATS.md +417 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
- package/DOCS/LICENSING_TIERS.md +275 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
- package/DOCS/OBS_SETUP_GUIDE.md +98 -0
- package/DOCS/PROJECT_SETUP.md +66 -0
- package/DOCS/RENDERER_LIFECYCLE.md +40 -0
- package/DOCS/REPO_MANIFEST.md +121 -0
- package/DOCS/SESSION_014_PLAN.md +195 -0
- package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
- package/DOCS/SYSTEM_INVENTORY.md +520 -0
- package/DOCS/TELEMETRY_EXPORTS.md +34 -0
- package/DOCS/WEBGPU_STATUS.md +38 -0
- package/DOCS/XR_BENCHMARKS.md +608 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/docs/.nojekyll +0 -0
- package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/02-hyperspatial_ego_death.html +346 -0
- package/docs/03-post_cartesian_sublime.html +346 -0
- package/docs/04-crystalline_void_meditation.html +346 -0
- package/docs/05-quantum_decoherence_ballet.html +346 -0
- package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/07-hyperspatial_ego_death.html +346 -0
- package/docs/08-post_cartesian_sublime.html +346 -0
- package/docs/09-crystalline_void_meditation.html +346 -0
- package/docs/10-quantum_decoherence_ballet.html +346 -0
- package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/12-hyperspatial_ego_death.html +346 -0
- package/docs/13-post_cartesian_sublime.html +346 -0
- package/docs/index.html +794 -0
- package/docs/test-hub.html +441 -0
- package/docs/url-state.js +102 -0
- package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
- package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
- package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
- package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
- package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
- package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
- package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
- package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
- package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
- package/docs/vib3-exports/index.html +238 -0
- package/docs/webgpu-live.html +702 -0
- package/package.json +367 -0
- package/src/advanced/AIPresetGenerator.js +777 -0
- package/src/advanced/MIDIController.js +703 -0
- package/src/advanced/OffscreenWorker.js +1051 -0
- package/src/advanced/WebGPUCompute.js +1051 -0
- package/src/advanced/WebXRRenderer.js +680 -0
- package/src/agent/cli/AgentCLI.js +615 -0
- package/src/agent/cli/index.js +14 -0
- package/src/agent/index.js +73 -0
- package/src/agent/mcp/MCPServer.js +950 -0
- package/src/agent/mcp/index.js +9 -0
- package/src/agent/mcp/tools.js +548 -0
- package/src/agent/telemetry/EventStream.js +669 -0
- package/src/agent/telemetry/Instrumentation.js +618 -0
- package/src/agent/telemetry/TelemetryExporters.js +427 -0
- package/src/agent/telemetry/TelemetryService.js +464 -0
- package/src/agent/telemetry/index.js +52 -0
- package/src/benchmarks/BenchmarkRunner.js +381 -0
- package/src/benchmarks/MetricsCollector.js +299 -0
- package/src/benchmarks/index.js +9 -0
- package/src/benchmarks/scenes.js +259 -0
- package/src/cli/index.js +675 -0
- package/src/config/ApiConfig.js +88 -0
- package/src/core/CanvasManager.js +217 -0
- package/src/core/ErrorReporter.js +117 -0
- package/src/core/ParameterMapper.js +333 -0
- package/src/core/Parameters.js +396 -0
- package/src/core/RendererContracts.js +200 -0
- package/src/core/UnifiedResourceManager.js +370 -0
- package/src/core/VIB3Engine.js +636 -0
- package/src/core/renderers/FacetedRendererAdapter.js +32 -0
- package/src/core/renderers/HolographicRendererAdapter.js +29 -0
- package/src/core/renderers/QuantumRendererAdapter.js +29 -0
- package/src/core/renderers/RendererLifecycleManager.js +63 -0
- package/src/creative/ColorPresetsSystem.js +980 -0
- package/src/creative/ParameterTimeline.js +1061 -0
- package/src/creative/PostProcessingPipeline.js +1113 -0
- package/src/creative/TransitionAnimator.js +683 -0
- package/src/export/CSSExporter.js +226 -0
- package/src/export/CardGeneratorBase.js +279 -0
- package/src/export/ExportManager.js +580 -0
- package/src/export/FacetedCardGenerator.js +279 -0
- package/src/export/HolographicCardGenerator.js +543 -0
- package/src/export/LottieExporter.js +552 -0
- package/src/export/QuantumCardGenerator.js +315 -0
- package/src/export/SVGExporter.js +519 -0
- package/src/export/ShaderExporter.js +903 -0
- package/src/export/TradingCardGenerator.js +3055 -0
- package/src/export/TradingCardManager.js +181 -0
- package/src/export/VIB3PackageExporter.js +559 -0
- package/src/export/index.js +14 -0
- package/src/export/systems/TradingCardSystemFaceted.js +494 -0
- package/src/export/systems/TradingCardSystemHolographic.js +452 -0
- package/src/export/systems/TradingCardSystemQuantum.js +411 -0
- package/src/faceted/FacetedSystem.js +963 -0
- package/src/features/CollectionManager.js +433 -0
- package/src/gallery/CollectionManager.js +240 -0
- package/src/gallery/GallerySystem.js +485 -0
- package/src/geometry/GeometryFactory.js +314 -0
- package/src/geometry/GeometryLibrary.js +72 -0
- package/src/geometry/buffers/BufferBuilder.js +338 -0
- package/src/geometry/buffers/index.js +18 -0
- package/src/geometry/generators/Crystal.js +420 -0
- package/src/geometry/generators/Fractal.js +298 -0
- package/src/geometry/generators/KleinBottle.js +197 -0
- package/src/geometry/generators/Sphere.js +192 -0
- package/src/geometry/generators/Tesseract.js +160 -0
- package/src/geometry/generators/Tetrahedron.js +225 -0
- package/src/geometry/generators/Torus.js +304 -0
- package/src/geometry/generators/Wave.js +341 -0
- package/src/geometry/index.js +142 -0
- package/src/geometry/warp/HypersphereCore.js +211 -0
- package/src/geometry/warp/HypertetraCore.js +386 -0
- package/src/geometry/warp/index.js +57 -0
- package/src/holograms/HolographicVisualizer.js +1073 -0
- package/src/holograms/RealHolographicSystem.js +966 -0
- package/src/holograms/variantRegistry.js +69 -0
- package/src/integrations/FigmaPlugin.js +854 -0
- package/src/integrations/OBSMode.js +754 -0
- package/src/integrations/ThreeJsPackage.js +660 -0
- package/src/integrations/TouchDesignerExport.js +552 -0
- package/src/integrations/frameworks/Vib3React.js +591 -0
- package/src/integrations/frameworks/Vib3Svelte.js +654 -0
- package/src/integrations/frameworks/Vib3Vue.js +628 -0
- package/src/llm/LLMParameterInterface.js +240 -0
- package/src/llm/LLMParameterUI.js +577 -0
- package/src/math/Mat4x4.js +708 -0
- package/src/math/Projection.js +341 -0
- package/src/math/Rotor4D.js +637 -0
- package/src/math/Vec4.js +476 -0
- package/src/math/constants.js +164 -0
- package/src/math/index.js +68 -0
- package/src/math/projections.js +54 -0
- package/src/math/rotations.js +196 -0
- package/src/quantum/QuantumEngine.js +906 -0
- package/src/quantum/QuantumVisualizer.js +1103 -0
- package/src/reactivity/ReactivityConfig.js +499 -0
- package/src/reactivity/ReactivityManager.js +586 -0
- package/src/reactivity/SpatialInputSystem.js +1783 -0
- package/src/reactivity/index.js +93 -0
- package/src/render/CommandBuffer.js +465 -0
- package/src/render/MultiCanvasBridge.js +340 -0
- package/src/render/RenderCommand.js +514 -0
- package/src/render/RenderResourceRegistry.js +523 -0
- package/src/render/RenderState.js +552 -0
- package/src/render/RenderTarget.js +512 -0
- package/src/render/ShaderLoader.js +253 -0
- package/src/render/ShaderProgram.js +599 -0
- package/src/render/UnifiedRenderBridge.js +496 -0
- package/src/render/backends/WebGLBackend.js +1108 -0
- package/src/render/backends/WebGPUBackend.js +1409 -0
- package/src/render/commands/CommandBufferExecutor.js +607 -0
- package/src/render/commands/RenderCommandBuffer.js +661 -0
- package/src/render/commands/index.js +17 -0
- package/src/render/index.js +367 -0
- package/src/scene/Disposable.js +498 -0
- package/src/scene/MemoryPool.js +618 -0
- package/src/scene/Node4D.js +697 -0
- package/src/scene/ResourceManager.js +599 -0
- package/src/scene/Scene4D.js +540 -0
- package/src/scene/index.js +98 -0
- package/src/schemas/error.schema.json +84 -0
- package/src/schemas/extension.schema.json +88 -0
- package/src/schemas/index.js +214 -0
- package/src/schemas/parameters.schema.json +142 -0
- package/src/schemas/tool-pack.schema.json +44 -0
- package/src/schemas/tool-response.schema.json +127 -0
- package/src/shaders/common/fullscreen.vert.glsl +5 -0
- package/src/shaders/common/fullscreen.vert.wgsl +17 -0
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +85 -0
- package/src/shaders/common/rotation4d.wgsl +86 -0
- package/src/shaders/common/uniforms.glsl +44 -0
- package/src/shaders/common/uniforms.wgsl +48 -0
- package/src/shaders/faceted/faceted.frag.glsl +129 -0
- package/src/shaders/faceted/faceted.frag.wgsl +164 -0
- package/src/shaders/holographic/holographic.frag.glsl +406 -0
- package/src/shaders/holographic/holographic.frag.wgsl +185 -0
- package/src/shaders/quantum/quantum.frag.glsl +513 -0
- package/src/shaders/quantum/quantum.frag.wgsl +361 -0
- package/src/testing/ParallelTestFramework.js +519 -0
- package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
- package/src/testing/exportFormats.test.js +8 -0
- package/src/testing/projections.test.js +14 -0
- package/src/testing/rotations.test.js +37 -0
- package/src/ui/InteractivityMenu.js +516 -0
- package/src/ui/StatusManager.js +96 -0
- package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
- package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
- package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
- package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
- package/src/variations/VariationManager.js +431 -0
- package/src/viewer/AudioReactivity.js +505 -0
- package/src/viewer/CardBending.js +481 -0
- package/src/viewer/GalleryUI.js +832 -0
- package/src/viewer/ReactivityManager.js +590 -0
- package/src/viewer/TradingCardExporter.js +600 -0
- package/src/viewer/ViewerPortal.js +374 -0
- package/src/viewer/index.js +12 -0
- package/src/wasm/WasmLoader.js +296 -0
- package/src/wasm/index.js +132 -0
- package/tools/agentic/mcpTools.js +88 -0
- package/tools/cli/agent-cli.js +92 -0
- package/tools/export/formats.js +24 -0
- package/tools/math/rotation-baseline.mjs +64 -0
- package/tools/shader-sync-verify.js +937 -0
- package/tools/telemetry/manifestPipeline.js +141 -0
- package/tools/telemetry/telemetryEvents.js +35 -0
- package/types/adaptive-sdk.d.ts +185 -0
- package/types/advanced/AIPresetGenerator.d.ts +81 -0
- package/types/advanced/MIDIController.d.ts +100 -0
- package/types/advanced/OffscreenWorker.d.ts +82 -0
- package/types/advanced/WebGPUCompute.d.ts +52 -0
- package/types/advanced/WebXRRenderer.d.ts +77 -0
- package/types/advanced/index.d.ts +46 -0
- package/types/core/ErrorReporter.d.ts +50 -0
- package/types/core/VIB3Engine.d.ts +204 -0
- package/types/creative/ColorPresetsSystem.d.ts +91 -0
- package/types/creative/ParameterTimeline.d.ts +74 -0
- package/types/creative/PostProcessingPipeline.d.ts +109 -0
- package/types/creative/TransitionAnimator.d.ts +71 -0
- package/types/creative/index.d.ts +35 -0
- package/types/integrations/FigmaPlugin.d.ts +46 -0
- package/types/integrations/OBSMode.d.ts +74 -0
- package/types/integrations/ThreeJsPackage.d.ts +62 -0
- package/types/integrations/TouchDesignerExport.d.ts +36 -0
- package/types/integrations/Vib3React.d.ts +74 -0
- package/types/integrations/Vib3Svelte.d.ts +63 -0
- package/types/integrations/Vib3Vue.d.ts +55 -0
- package/types/integrations/index.d.ts +52 -0
- package/types/reactivity/SpatialInputSystem.d.ts +173 -0
- package/types/reactivity/index.d.ts +394 -0
- package/types/render/CommandBuffer.d.ts +169 -0
- package/types/render/RenderCommand.d.ts +312 -0
- package/types/render/RenderState.d.ts +279 -0
- package/types/render/RenderTarget.d.ts +254 -0
- package/types/render/ShaderProgram.d.ts +277 -0
- package/types/render/UnifiedRenderBridge.d.ts +143 -0
- package/types/render/WebGLBackend.d.ts +168 -0
- package/types/render/WebGPUBackend.d.ts +186 -0
- package/types/render/index.d.ts +141 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disposable - Cascade disposal system for scene objects
|
|
3
|
+
*
|
|
4
|
+
* Provides automatic resource cleanup with:
|
|
5
|
+
* - Dependency tracking
|
|
6
|
+
* - Cascade disposal
|
|
7
|
+
* - Safe disposal ordering
|
|
8
|
+
* - Memory leak detection
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Disposal state enum
|
|
13
|
+
*/
|
|
14
|
+
export const DisposalState = {
|
|
15
|
+
ACTIVE: 'active',
|
|
16
|
+
DISPOSING: 'disposing',
|
|
17
|
+
DISPOSED: 'disposed'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Base class for disposable objects
|
|
22
|
+
*/
|
|
23
|
+
export class Disposable {
|
|
24
|
+
constructor() {
|
|
25
|
+
/** @type {string} Current disposal state */
|
|
26
|
+
this._disposalState = DisposalState.ACTIVE;
|
|
27
|
+
|
|
28
|
+
/** @type {Set<Disposable>} Objects that depend on this one */
|
|
29
|
+
this._dependents = new Set();
|
|
30
|
+
|
|
31
|
+
/** @type {Set<Disposable>} Objects this one depends on */
|
|
32
|
+
this._dependencies = new Set();
|
|
33
|
+
|
|
34
|
+
/** @type {function[]} Callbacks to run on dispose */
|
|
35
|
+
this._disposeCallbacks = [];
|
|
36
|
+
|
|
37
|
+
/** @type {string|null} Debug label */
|
|
38
|
+
this._label = null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get disposal state
|
|
43
|
+
* @returns {string}
|
|
44
|
+
*/
|
|
45
|
+
get disposalState() {
|
|
46
|
+
return this._disposalState;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check if disposed
|
|
51
|
+
* @returns {boolean}
|
|
52
|
+
*/
|
|
53
|
+
get isDisposed() {
|
|
54
|
+
return this._disposalState === DisposalState.DISPOSED;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check if active (not disposed or disposing)
|
|
59
|
+
* @returns {boolean}
|
|
60
|
+
*/
|
|
61
|
+
get isActive() {
|
|
62
|
+
return this._disposalState === DisposalState.ACTIVE;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Set debug label
|
|
67
|
+
* @param {string} label
|
|
68
|
+
* @returns {this}
|
|
69
|
+
*/
|
|
70
|
+
setLabel(label) {
|
|
71
|
+
this._label = label;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Add a dependency (this object depends on other)
|
|
77
|
+
* @param {Disposable} other
|
|
78
|
+
* @returns {this}
|
|
79
|
+
*/
|
|
80
|
+
addDependency(other) {
|
|
81
|
+
if (other === this) {
|
|
82
|
+
throw new Error('Object cannot depend on itself');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (this._checkCircularDependency(other)) {
|
|
86
|
+
throw new Error('Circular dependency detected');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this._dependencies.add(other);
|
|
90
|
+
other._dependents.add(this);
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Remove a dependency
|
|
96
|
+
* @param {Disposable} other
|
|
97
|
+
* @returns {this}
|
|
98
|
+
*/
|
|
99
|
+
removeDependency(other) {
|
|
100
|
+
this._dependencies.delete(other);
|
|
101
|
+
other._dependents.delete(this);
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check for circular dependency
|
|
107
|
+
* @private
|
|
108
|
+
*/
|
|
109
|
+
_checkCircularDependency(other, visited = new Set()) {
|
|
110
|
+
if (visited.has(other)) return false;
|
|
111
|
+
if (other._dependencies.has(this)) return true;
|
|
112
|
+
|
|
113
|
+
visited.add(other);
|
|
114
|
+
for (const dep of other._dependencies) {
|
|
115
|
+
if (this._checkCircularDependency(dep, visited)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Add dispose callback
|
|
124
|
+
* @param {function(): void} callback
|
|
125
|
+
* @returns {function} Unsubscribe function
|
|
126
|
+
*/
|
|
127
|
+
onDispose(callback) {
|
|
128
|
+
this._disposeCallbacks.push(callback);
|
|
129
|
+
return () => {
|
|
130
|
+
const idx = this._disposeCallbacks.indexOf(callback);
|
|
131
|
+
if (idx !== -1) {
|
|
132
|
+
this._disposeCallbacks.splice(idx, 1);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Dispose this object and cascade to dependents
|
|
139
|
+
*/
|
|
140
|
+
dispose() {
|
|
141
|
+
if (this._disposalState !== DisposalState.ACTIVE) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this._disposalState = DisposalState.DISPOSING;
|
|
146
|
+
|
|
147
|
+
// First dispose all dependents (cascade)
|
|
148
|
+
for (const dependent of [...this._dependents]) {
|
|
149
|
+
dependent.dispose();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Run dispose callbacks
|
|
153
|
+
for (const callback of this._disposeCallbacks) {
|
|
154
|
+
try {
|
|
155
|
+
callback();
|
|
156
|
+
} catch (e) {
|
|
157
|
+
console.error(`Dispose callback error in ${this._label || 'unknown'}:`, e);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Perform actual disposal
|
|
162
|
+
this._doDispose();
|
|
163
|
+
|
|
164
|
+
// Remove from dependencies' dependent lists
|
|
165
|
+
for (const dep of this._dependencies) {
|
|
166
|
+
dep._dependents.delete(this);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Clear references
|
|
170
|
+
this._dependents.clear();
|
|
171
|
+
this._dependencies.clear();
|
|
172
|
+
this._disposeCallbacks = [];
|
|
173
|
+
|
|
174
|
+
this._disposalState = DisposalState.DISPOSED;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Override this to perform actual resource cleanup
|
|
179
|
+
* @protected
|
|
180
|
+
*/
|
|
181
|
+
_doDispose() {
|
|
182
|
+
// Subclasses implement this
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Assert object is not disposed
|
|
187
|
+
* @param {string} [operation] - Operation being attempted
|
|
188
|
+
*/
|
|
189
|
+
assertNotDisposed(operation = 'operation') {
|
|
190
|
+
if (this._disposalState !== DisposalState.ACTIVE) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`Cannot perform ${operation} on disposed object: ${this._label || 'unknown'}`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Manages disposal of multiple objects with dependency ordering
|
|
200
|
+
*/
|
|
201
|
+
export class DisposalManager {
|
|
202
|
+
constructor() {
|
|
203
|
+
/** @type {Set<Disposable>} Tracked objects */
|
|
204
|
+
this._tracked = new Set();
|
|
205
|
+
|
|
206
|
+
/** @type {boolean} Whether disposal is in progress */
|
|
207
|
+
this._disposing = false;
|
|
208
|
+
|
|
209
|
+
/** @type {Set<Disposable>} Objects pending disposal */
|
|
210
|
+
this._pendingDisposal = new Set();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Track an object for disposal
|
|
215
|
+
* @param {Disposable} obj
|
|
216
|
+
* @returns {this}
|
|
217
|
+
*/
|
|
218
|
+
track(obj) {
|
|
219
|
+
this._tracked.add(obj);
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Untrack an object
|
|
225
|
+
* @param {Disposable} obj
|
|
226
|
+
* @returns {this}
|
|
227
|
+
*/
|
|
228
|
+
untrack(obj) {
|
|
229
|
+
this._tracked.delete(obj);
|
|
230
|
+
return this;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Mark object for deferred disposal
|
|
235
|
+
* @param {Disposable} obj
|
|
236
|
+
* @returns {this}
|
|
237
|
+
*/
|
|
238
|
+
markForDisposal(obj) {
|
|
239
|
+
this._pendingDisposal.add(obj);
|
|
240
|
+
return this;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Process pending disposals
|
|
245
|
+
*/
|
|
246
|
+
processPending() {
|
|
247
|
+
if (this._disposing) return;
|
|
248
|
+
|
|
249
|
+
this._disposing = true;
|
|
250
|
+
|
|
251
|
+
// Sort by dependency order (dispose dependents first)
|
|
252
|
+
const sorted = this._topologicalSort([...this._pendingDisposal]);
|
|
253
|
+
|
|
254
|
+
for (const obj of sorted) {
|
|
255
|
+
if (obj.isActive) {
|
|
256
|
+
obj.dispose();
|
|
257
|
+
}
|
|
258
|
+
this._tracked.delete(obj);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
this._pendingDisposal.clear();
|
|
262
|
+
this._disposing = false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Topological sort for disposal order
|
|
267
|
+
* @private
|
|
268
|
+
*/
|
|
269
|
+
_topologicalSort(objects) {
|
|
270
|
+
const sorted = [];
|
|
271
|
+
const visited = new Set();
|
|
272
|
+
const visiting = new Set();
|
|
273
|
+
|
|
274
|
+
const visit = (obj) => {
|
|
275
|
+
if (visited.has(obj)) return;
|
|
276
|
+
if (visiting.has(obj)) {
|
|
277
|
+
console.warn('Circular dependency in disposal');
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
visiting.add(obj);
|
|
282
|
+
|
|
283
|
+
// Visit dependents first (they need to be disposed before this)
|
|
284
|
+
for (const dependent of obj._dependents) {
|
|
285
|
+
if (objects.includes(dependent)) {
|
|
286
|
+
visit(dependent);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
visiting.delete(obj);
|
|
291
|
+
visited.add(obj);
|
|
292
|
+
sorted.push(obj);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
for (const obj of objects) {
|
|
296
|
+
visit(obj);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return sorted;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Dispose all tracked objects
|
|
304
|
+
*/
|
|
305
|
+
disposeAll() {
|
|
306
|
+
// Add all tracked to pending
|
|
307
|
+
for (const obj of this._tracked) {
|
|
308
|
+
this._pendingDisposal.add(obj);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
this.processPending();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get statistics
|
|
316
|
+
* @returns {object}
|
|
317
|
+
*/
|
|
318
|
+
getStats() {
|
|
319
|
+
let activeCount = 0;
|
|
320
|
+
let disposedCount = 0;
|
|
321
|
+
|
|
322
|
+
for (const obj of this._tracked) {
|
|
323
|
+
if (obj.isActive) activeCount++;
|
|
324
|
+
else disposedCount++;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
tracked: this._tracked.size,
|
|
329
|
+
active: activeCount,
|
|
330
|
+
disposed: disposedCount,
|
|
331
|
+
pending: this._pendingDisposal.size
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Composite disposable - disposes multiple objects together
|
|
338
|
+
*/
|
|
339
|
+
export class CompositeDisposable extends Disposable {
|
|
340
|
+
constructor() {
|
|
341
|
+
super();
|
|
342
|
+
/** @type {Set<Disposable>} */
|
|
343
|
+
this._children = new Set();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Add a child disposable
|
|
348
|
+
* @param {Disposable} child
|
|
349
|
+
* @returns {this}
|
|
350
|
+
*/
|
|
351
|
+
add(child) {
|
|
352
|
+
this.assertNotDisposed('add');
|
|
353
|
+
this._children.add(child);
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Remove a child (does not dispose it)
|
|
359
|
+
* @param {Disposable} child
|
|
360
|
+
* @returns {boolean}
|
|
361
|
+
*/
|
|
362
|
+
remove(child) {
|
|
363
|
+
return this._children.delete(child);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* @override
|
|
368
|
+
*/
|
|
369
|
+
_doDispose() {
|
|
370
|
+
for (const child of this._children) {
|
|
371
|
+
child.dispose();
|
|
372
|
+
}
|
|
373
|
+
this._children.clear();
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Single assignment disposable - can only be assigned once
|
|
379
|
+
*/
|
|
380
|
+
export class SingleAssignmentDisposable extends Disposable {
|
|
381
|
+
constructor() {
|
|
382
|
+
super();
|
|
383
|
+
/** @type {Disposable|null} */
|
|
384
|
+
this._inner = null;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Set the inner disposable (can only be called once)
|
|
389
|
+
* @param {Disposable} disposable
|
|
390
|
+
*/
|
|
391
|
+
set(disposable) {
|
|
392
|
+
if (this._inner !== null) {
|
|
393
|
+
throw new Error('SingleAssignmentDisposable already assigned');
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (this.isDisposed) {
|
|
397
|
+
disposable.dispose();
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
this._inner = disposable;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* @override
|
|
406
|
+
*/
|
|
407
|
+
_doDispose() {
|
|
408
|
+
if (this._inner) {
|
|
409
|
+
this._inner.dispose();
|
|
410
|
+
this._inner = null;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Serial disposable - replaces previous disposable on assignment
|
|
417
|
+
*/
|
|
418
|
+
export class SerialDisposable extends Disposable {
|
|
419
|
+
constructor() {
|
|
420
|
+
super();
|
|
421
|
+
/** @type {Disposable|null} */
|
|
422
|
+
this._inner = null;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Set the inner disposable (disposes previous)
|
|
427
|
+
* @param {Disposable|null} disposable
|
|
428
|
+
*/
|
|
429
|
+
set(disposable) {
|
|
430
|
+
if (this.isDisposed) {
|
|
431
|
+
if (disposable) disposable.dispose();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (this._inner) {
|
|
436
|
+
this._inner.dispose();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
this._inner = disposable;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Get current inner
|
|
444
|
+
* @returns {Disposable|null}
|
|
445
|
+
*/
|
|
446
|
+
get() {
|
|
447
|
+
return this._inner;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @override
|
|
452
|
+
*/
|
|
453
|
+
_doDispose() {
|
|
454
|
+
if (this._inner) {
|
|
455
|
+
this._inner.dispose();
|
|
456
|
+
this._inner = null;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Callback disposable - runs a callback on dispose
|
|
463
|
+
*/
|
|
464
|
+
export class CallbackDisposable extends Disposable {
|
|
465
|
+
/**
|
|
466
|
+
* @param {function(): void} callback
|
|
467
|
+
*/
|
|
468
|
+
constructor(callback) {
|
|
469
|
+
super();
|
|
470
|
+
this._callback = callback;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* @override
|
|
475
|
+
*/
|
|
476
|
+
_doDispose() {
|
|
477
|
+
if (this._callback) {
|
|
478
|
+
this._callback();
|
|
479
|
+
this._callback = null;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Create a disposable from a cleanup function
|
|
486
|
+
* @param {function(): void} cleanup
|
|
487
|
+
* @returns {Disposable}
|
|
488
|
+
*/
|
|
489
|
+
export function createDisposable(cleanup) {
|
|
490
|
+
return new CallbackDisposable(cleanup);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Global disposal manager instance
|
|
495
|
+
*/
|
|
496
|
+
export const disposalManager = new DisposalManager();
|
|
497
|
+
|
|
498
|
+
export default Disposable;
|