@estjs/template 0.0.15-beta.13 → 0.0.15-beta.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/template.cjs.js +2 -2
- package/dist/template.cjs.js.map +1 -1
- package/dist/template.d.cts +71 -42
- package/dist/template.d.ts +71 -42
- package/dist/template.dev.cjs.js +127 -129
- package/dist/template.dev.cjs.js.map +1 -1
- package/dist/template.dev.esm.js +127 -129
- package/dist/template.dev.esm.js.map +1 -1
- package/dist/template.esm.js +2 -2
- package/dist/template.esm.js.map +1 -1
- package/package.json +3 -3
package/dist/template.d.cts
CHANGED
|
@@ -24,30 +24,16 @@ declare function provide<T>(key: InjectionKey<T> | string | number, value: T): v
|
|
|
24
24
|
*/
|
|
25
25
|
declare function inject<T>(key: InjectionKey<T> | string | number, defaultValue?: T): T;
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Scope represents an execution context in the component tree.
|
|
29
|
-
* It manages provides, cleanup functions, and lifecycle hooks.
|
|
30
|
-
*/
|
|
31
27
|
interface Scope {
|
|
32
|
-
/** Unique identifier for debugging */
|
|
33
28
|
readonly id: number;
|
|
34
|
-
/** Parent scope in the hierarchy */
|
|
35
29
|
parent: Scope | null;
|
|
36
|
-
|
|
37
|
-
children: Set<Scope> | null;
|
|
38
|
-
/** Provided values (lazy initialized) */
|
|
30
|
+
children: Scope[] | null;
|
|
39
31
|
provides: Map<InjectionKey<unknown> | string | number | symbol, unknown> | null;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/** Update lifecycle hooks (lazy initialized) */
|
|
45
|
-
onUpdate: Set<() => void | Promise<void>> | null;
|
|
46
|
-
/** Destroy lifecycle hooks (lazy initialized) */
|
|
47
|
-
onDestroy: Set<() => void | Promise<void>> | null;
|
|
48
|
-
/** Whether the scope has been mounted */
|
|
32
|
+
cleanup: (() => void)[] | null;
|
|
33
|
+
onMount: (() => void | Promise<void>)[] | null;
|
|
34
|
+
onUpdate: (() => void | Promise<void>)[] | null;
|
|
35
|
+
onDestroy: (() => void | Promise<void>)[] | null;
|
|
49
36
|
isMounted: boolean;
|
|
50
|
-
/** Whether the scope has been destroyed */
|
|
51
37
|
isDestroyed: boolean;
|
|
52
38
|
}
|
|
53
39
|
/**
|
|
@@ -60,13 +46,6 @@ declare function getActiveScope(): Scope | null;
|
|
|
60
46
|
* @param scope - The scope to set as active
|
|
61
47
|
*/
|
|
62
48
|
declare function setActiveScope(scope: Scope | null): void;
|
|
63
|
-
/**
|
|
64
|
-
* Create a new scope with optional parent.
|
|
65
|
-
* If no parent is provided, uses the current active scope as parent.
|
|
66
|
-
*
|
|
67
|
-
* @param parent - Optional parent scope (defaults to active scope)
|
|
68
|
-
* @returns A new scope instance
|
|
69
|
-
*/
|
|
70
49
|
declare function createScope(parent?: Scope | null): Scope;
|
|
71
50
|
/**
|
|
72
51
|
* Run a function within a scope, ensuring proper cleanup.
|
|
@@ -78,17 +57,42 @@ declare function createScope(parent?: Scope | null): Scope;
|
|
|
78
57
|
*/
|
|
79
58
|
declare function runWithScope<T>(scope: Scope, fn: () => T): T;
|
|
80
59
|
/**
|
|
81
|
-
* Dispose a scope and all
|
|
82
|
-
*
|
|
60
|
+
* Dispose a scope and recursively dispose all child scopes.
|
|
61
|
+
* Performs the following cleanup in order:
|
|
62
|
+
* 1. Recursively disposes all children (depth-first)
|
|
63
|
+
* 2. Executes destroy lifecycle hooks
|
|
64
|
+
* 3. Executes registered cleanup functions
|
|
65
|
+
* 4. Removes scope from parent's children list
|
|
66
|
+
* 5. Clears all internal collections and resets state
|
|
67
|
+
*
|
|
68
|
+
* Safe to call multiple times (idempotent).
|
|
83
69
|
*
|
|
84
70
|
* @param scope - The scope to dispose
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* const scope = createScope(parent);
|
|
75
|
+
* // ... use scope ...
|
|
76
|
+
* disposeScope(scope); // Cleanup everything
|
|
77
|
+
* ```
|
|
85
78
|
*/
|
|
86
79
|
declare function disposeScope(scope: Scope): void;
|
|
87
80
|
/**
|
|
88
|
-
* Register a cleanup function
|
|
89
|
-
*
|
|
81
|
+
* Register a cleanup function to be executed when the scope is disposed.
|
|
82
|
+
* Useful for cleaning up timers, subscriptions, event listeners, etc.
|
|
90
83
|
*
|
|
91
|
-
*
|
|
84
|
+
* Cleanup functions are executed in LIFO order (last registered, first executed).
|
|
85
|
+
* Cleanup errors don't prevent other cleanups from running.
|
|
86
|
+
*
|
|
87
|
+
* @param fn - The cleanup function to register
|
|
88
|
+
*
|
|
89
|
+
* @throws Error in dev mode if called outside a scope
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const timerId = setInterval(() => {}, 1000);
|
|
94
|
+
* onCleanup(() => clearInterval(timerId));
|
|
95
|
+
* ```
|
|
92
96
|
*/
|
|
93
97
|
declare function onCleanup(fn: () => void): void;
|
|
94
98
|
|
|
@@ -170,28 +174,54 @@ declare function template(html: string): () => Node;
|
|
|
170
174
|
*/
|
|
171
175
|
declare function createApp<P extends ComponentProps = {}>(component: ComponentFn<P> | Component<P>, target: string | Element): Component<P> | undefined;
|
|
172
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Lifecycle hook type: returns void or a Promise that resolves when complete.
|
|
179
|
+
* Hooks can perform cleanup by returning a cleanup function.
|
|
180
|
+
*/
|
|
173
181
|
type LifecycleHook = () => void | Promise<void>;
|
|
174
182
|
/**
|
|
175
183
|
* Register a mount lifecycle hook.
|
|
176
|
-
*
|
|
184
|
+
* Runs after component is mounted and virtual tree is committed.
|
|
185
|
+
* If the scope is already mounted, the hook executes immediately.
|
|
177
186
|
*
|
|
178
|
-
* @
|
|
187
|
+
* @throws Error in dev mode if called outside a scope
|
|
188
|
+
* @example
|
|
189
|
+
* ```tsx
|
|
190
|
+
* onMount(() => {
|
|
191
|
+
* console.log('Component mounted');
|
|
192
|
+
* return () => console.log('Cleanup');
|
|
193
|
+
* });
|
|
194
|
+
* ```
|
|
179
195
|
*/
|
|
180
196
|
declare function onMount(hook: LifecycleHook): void;
|
|
181
197
|
/**
|
|
182
|
-
* Register
|
|
183
|
-
*
|
|
198
|
+
* Register an update lifecycle hook.
|
|
199
|
+
* Runs whenever the component re-renders due to prop or state changes.
|
|
184
200
|
*
|
|
185
|
-
* @
|
|
201
|
+
* @throws Error in dev mode if called outside a scope
|
|
202
|
+
* @example
|
|
203
|
+
* ```tsx
|
|
204
|
+
* onUpdate(() => {
|
|
205
|
+
* console.log('Component updated');
|
|
206
|
+
* });
|
|
207
|
+
* ```
|
|
186
208
|
*/
|
|
187
|
-
declare function
|
|
209
|
+
declare function onUpdate(hook: LifecycleHook): void;
|
|
188
210
|
/**
|
|
189
|
-
* Register
|
|
190
|
-
*
|
|
211
|
+
* Register a destroy lifecycle hook.
|
|
212
|
+
* Runs before scope is disposed and resources are cleaned up.
|
|
213
|
+
* Perfect for resetting external state, unsubscribing from events, etc.
|
|
191
214
|
*
|
|
192
|
-
* @
|
|
215
|
+
* @throws Error in dev mode if called outside a scope
|
|
216
|
+
* @example
|
|
217
|
+
* ```tsx
|
|
218
|
+
* onDestroy(() => {
|
|
219
|
+
* unsubscribe();
|
|
220
|
+
* clearTimeout(timerId);
|
|
221
|
+
* });
|
|
222
|
+
* ```
|
|
193
223
|
*/
|
|
194
|
-
declare function
|
|
224
|
+
declare function onDestroy(hook: LifecycleHook): void;
|
|
195
225
|
|
|
196
226
|
/**
|
|
197
227
|
* Add event listener with automatic cleanup on scope destruction
|
|
@@ -217,7 +247,6 @@ declare function bindElement(node: Element, key: string, defaultValue: unknown,
|
|
|
217
247
|
* @param parent Parent node
|
|
218
248
|
* @param nodeFactory Node factory function or static node
|
|
219
249
|
* @param before Reference node for insertion position
|
|
220
|
-
* @param options Insertion options
|
|
221
250
|
*
|
|
222
251
|
* @example
|
|
223
252
|
* ```typescript
|
package/dist/template.d.ts
CHANGED
|
@@ -24,30 +24,16 @@ declare function provide<T>(key: InjectionKey<T> | string | number, value: T): v
|
|
|
24
24
|
*/
|
|
25
25
|
declare function inject<T>(key: InjectionKey<T> | string | number, defaultValue?: T): T;
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Scope represents an execution context in the component tree.
|
|
29
|
-
* It manages provides, cleanup functions, and lifecycle hooks.
|
|
30
|
-
*/
|
|
31
27
|
interface Scope {
|
|
32
|
-
/** Unique identifier for debugging */
|
|
33
28
|
readonly id: number;
|
|
34
|
-
/** Parent scope in the hierarchy */
|
|
35
29
|
parent: Scope | null;
|
|
36
|
-
|
|
37
|
-
children: Set<Scope> | null;
|
|
38
|
-
/** Provided values (lazy initialized) */
|
|
30
|
+
children: Scope[] | null;
|
|
39
31
|
provides: Map<InjectionKey<unknown> | string | number | symbol, unknown> | null;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/** Update lifecycle hooks (lazy initialized) */
|
|
45
|
-
onUpdate: Set<() => void | Promise<void>> | null;
|
|
46
|
-
/** Destroy lifecycle hooks (lazy initialized) */
|
|
47
|
-
onDestroy: Set<() => void | Promise<void>> | null;
|
|
48
|
-
/** Whether the scope has been mounted */
|
|
32
|
+
cleanup: (() => void)[] | null;
|
|
33
|
+
onMount: (() => void | Promise<void>)[] | null;
|
|
34
|
+
onUpdate: (() => void | Promise<void>)[] | null;
|
|
35
|
+
onDestroy: (() => void | Promise<void>)[] | null;
|
|
49
36
|
isMounted: boolean;
|
|
50
|
-
/** Whether the scope has been destroyed */
|
|
51
37
|
isDestroyed: boolean;
|
|
52
38
|
}
|
|
53
39
|
/**
|
|
@@ -60,13 +46,6 @@ declare function getActiveScope(): Scope | null;
|
|
|
60
46
|
* @param scope - The scope to set as active
|
|
61
47
|
*/
|
|
62
48
|
declare function setActiveScope(scope: Scope | null): void;
|
|
63
|
-
/**
|
|
64
|
-
* Create a new scope with optional parent.
|
|
65
|
-
* If no parent is provided, uses the current active scope as parent.
|
|
66
|
-
*
|
|
67
|
-
* @param parent - Optional parent scope (defaults to active scope)
|
|
68
|
-
* @returns A new scope instance
|
|
69
|
-
*/
|
|
70
49
|
declare function createScope(parent?: Scope | null): Scope;
|
|
71
50
|
/**
|
|
72
51
|
* Run a function within a scope, ensuring proper cleanup.
|
|
@@ -78,17 +57,42 @@ declare function createScope(parent?: Scope | null): Scope;
|
|
|
78
57
|
*/
|
|
79
58
|
declare function runWithScope<T>(scope: Scope, fn: () => T): T;
|
|
80
59
|
/**
|
|
81
|
-
* Dispose a scope and all
|
|
82
|
-
*
|
|
60
|
+
* Dispose a scope and recursively dispose all child scopes.
|
|
61
|
+
* Performs the following cleanup in order:
|
|
62
|
+
* 1. Recursively disposes all children (depth-first)
|
|
63
|
+
* 2. Executes destroy lifecycle hooks
|
|
64
|
+
* 3. Executes registered cleanup functions
|
|
65
|
+
* 4. Removes scope from parent's children list
|
|
66
|
+
* 5. Clears all internal collections and resets state
|
|
67
|
+
*
|
|
68
|
+
* Safe to call multiple times (idempotent).
|
|
83
69
|
*
|
|
84
70
|
* @param scope - The scope to dispose
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* const scope = createScope(parent);
|
|
75
|
+
* // ... use scope ...
|
|
76
|
+
* disposeScope(scope); // Cleanup everything
|
|
77
|
+
* ```
|
|
85
78
|
*/
|
|
86
79
|
declare function disposeScope(scope: Scope): void;
|
|
87
80
|
/**
|
|
88
|
-
* Register a cleanup function
|
|
89
|
-
*
|
|
81
|
+
* Register a cleanup function to be executed when the scope is disposed.
|
|
82
|
+
* Useful for cleaning up timers, subscriptions, event listeners, etc.
|
|
90
83
|
*
|
|
91
|
-
*
|
|
84
|
+
* Cleanup functions are executed in LIFO order (last registered, first executed).
|
|
85
|
+
* Cleanup errors don't prevent other cleanups from running.
|
|
86
|
+
*
|
|
87
|
+
* @param fn - The cleanup function to register
|
|
88
|
+
*
|
|
89
|
+
* @throws Error in dev mode if called outside a scope
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const timerId = setInterval(() => {}, 1000);
|
|
94
|
+
* onCleanup(() => clearInterval(timerId));
|
|
95
|
+
* ```
|
|
92
96
|
*/
|
|
93
97
|
declare function onCleanup(fn: () => void): void;
|
|
94
98
|
|
|
@@ -170,28 +174,54 @@ declare function template(html: string): () => Node;
|
|
|
170
174
|
*/
|
|
171
175
|
declare function createApp<P extends ComponentProps = {}>(component: ComponentFn<P> | Component<P>, target: string | Element): Component<P> | undefined;
|
|
172
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Lifecycle hook type: returns void or a Promise that resolves when complete.
|
|
179
|
+
* Hooks can perform cleanup by returning a cleanup function.
|
|
180
|
+
*/
|
|
173
181
|
type LifecycleHook = () => void | Promise<void>;
|
|
174
182
|
/**
|
|
175
183
|
* Register a mount lifecycle hook.
|
|
176
|
-
*
|
|
184
|
+
* Runs after component is mounted and virtual tree is committed.
|
|
185
|
+
* If the scope is already mounted, the hook executes immediately.
|
|
177
186
|
*
|
|
178
|
-
* @
|
|
187
|
+
* @throws Error in dev mode if called outside a scope
|
|
188
|
+
* @example
|
|
189
|
+
* ```tsx
|
|
190
|
+
* onMount(() => {
|
|
191
|
+
* console.log('Component mounted');
|
|
192
|
+
* return () => console.log('Cleanup');
|
|
193
|
+
* });
|
|
194
|
+
* ```
|
|
179
195
|
*/
|
|
180
196
|
declare function onMount(hook: LifecycleHook): void;
|
|
181
197
|
/**
|
|
182
|
-
* Register
|
|
183
|
-
*
|
|
198
|
+
* Register an update lifecycle hook.
|
|
199
|
+
* Runs whenever the component re-renders due to prop or state changes.
|
|
184
200
|
*
|
|
185
|
-
* @
|
|
201
|
+
* @throws Error in dev mode if called outside a scope
|
|
202
|
+
* @example
|
|
203
|
+
* ```tsx
|
|
204
|
+
* onUpdate(() => {
|
|
205
|
+
* console.log('Component updated');
|
|
206
|
+
* });
|
|
207
|
+
* ```
|
|
186
208
|
*/
|
|
187
|
-
declare function
|
|
209
|
+
declare function onUpdate(hook: LifecycleHook): void;
|
|
188
210
|
/**
|
|
189
|
-
* Register
|
|
190
|
-
*
|
|
211
|
+
* Register a destroy lifecycle hook.
|
|
212
|
+
* Runs before scope is disposed and resources are cleaned up.
|
|
213
|
+
* Perfect for resetting external state, unsubscribing from events, etc.
|
|
191
214
|
*
|
|
192
|
-
* @
|
|
215
|
+
* @throws Error in dev mode if called outside a scope
|
|
216
|
+
* @example
|
|
217
|
+
* ```tsx
|
|
218
|
+
* onDestroy(() => {
|
|
219
|
+
* unsubscribe();
|
|
220
|
+
* clearTimeout(timerId);
|
|
221
|
+
* });
|
|
222
|
+
* ```
|
|
193
223
|
*/
|
|
194
|
-
declare function
|
|
224
|
+
declare function onDestroy(hook: LifecycleHook): void;
|
|
195
225
|
|
|
196
226
|
/**
|
|
197
227
|
* Add event listener with automatic cleanup on scope destruction
|
|
@@ -217,7 +247,6 @@ declare function bindElement(node: Element, key: string, defaultValue: unknown,
|
|
|
217
247
|
* @param parent Parent node
|
|
218
248
|
* @param nodeFactory Node factory function or static node
|
|
219
249
|
* @param before Reference node for insertion position
|
|
220
|
-
* @param options Insertion options
|
|
221
250
|
*
|
|
222
251
|
* @example
|
|
223
252
|
* ```typescript
|
package/dist/template.dev.cjs.js
CHANGED
|
@@ -39,6 +39,108 @@ var __async = (__this, __arguments, generator) => {
|
|
|
39
39
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
|
+
var LIFECYCLE = {
|
|
43
|
+
mount: "mount",
|
|
44
|
+
destroy: "destroy",
|
|
45
|
+
update: "update"
|
|
46
|
+
};
|
|
47
|
+
function registerScopedHook(scope, listKey, hook) {
|
|
48
|
+
let hookList = scope[listKey];
|
|
49
|
+
if (!hookList) {
|
|
50
|
+
hookList = scope[listKey] = [];
|
|
51
|
+
}
|
|
52
|
+
if (!hookList.includes(hook)) {
|
|
53
|
+
hookList.push(hook);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function executeHooks(hooks, scopeId2, phase) {
|
|
57
|
+
const len = hooks.length;
|
|
58
|
+
if (len === 0) return;
|
|
59
|
+
let pending;
|
|
60
|
+
for (let i = 0; i < len; i++) {
|
|
61
|
+
try {
|
|
62
|
+
const result = hooks[i]();
|
|
63
|
+
if (shared.isPromise(result)) {
|
|
64
|
+
const safePromise = result.catch((error_) => {
|
|
65
|
+
if (true) {
|
|
66
|
+
shared.error(`Scope(${scopeId2}): Async ${phase} hook rejected:`, error_);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
(pending != null ? pending : pending = []).push(safePromise);
|
|
70
|
+
}
|
|
71
|
+
} catch (error_) {
|
|
72
|
+
{
|
|
73
|
+
shared.error(`Scope(${scopeId2}): Error in ${phase} hook:`, error_);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!pending) return;
|
|
78
|
+
return Promise.all(pending).then(() => void 0);
|
|
79
|
+
}
|
|
80
|
+
function onMount(hook) {
|
|
81
|
+
const scope = getActiveScope();
|
|
82
|
+
if (!scope) {
|
|
83
|
+
shared.error("onMount() must be called within a scope");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (scope.isMounted) {
|
|
87
|
+
try {
|
|
88
|
+
const result = hook();
|
|
89
|
+
if (shared.isPromise(result)) {
|
|
90
|
+
result.catch((error_) => {
|
|
91
|
+
if (true) shared.error(`Scope(${scope.id}): Async ${LIFECYCLE.mount} hook rejected:`, error_);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
} catch (error_) {
|
|
95
|
+
shared.error(`Scope(${scope.id}): Error in ${LIFECYCLE.mount} hook:`, error_);
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
registerScopedHook(scope, "onMount", hook);
|
|
100
|
+
}
|
|
101
|
+
function onUpdate(hook) {
|
|
102
|
+
const scope = getActiveScope();
|
|
103
|
+
if (!scope) {
|
|
104
|
+
shared.error("onUpdate() must be called within a scope");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
registerScopedHook(scope, "onUpdate", hook);
|
|
108
|
+
}
|
|
109
|
+
function onDestroy(hook) {
|
|
110
|
+
const scope = getActiveScope();
|
|
111
|
+
if (!scope) {
|
|
112
|
+
shared.error("onDestroy() must be called within a scope");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
registerScopedHook(scope, "onDestroy", hook);
|
|
116
|
+
}
|
|
117
|
+
function triggerMountHooks(scope) {
|
|
118
|
+
var _a2;
|
|
119
|
+
if (scope.isDestroyed || !((_a2 = scope.onMount) == null ? void 0 : _a2.length)) {
|
|
120
|
+
scope.isMounted = true;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const mountHooks = scope.onMount;
|
|
124
|
+
const result = runWithScope(scope, () => executeHooks(mountHooks, scope.id, LIFECYCLE.mount));
|
|
125
|
+
mountHooks.length = 0;
|
|
126
|
+
scope.isMounted = true;
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
function triggerUpdateHooks(scope) {
|
|
130
|
+
var _a2;
|
|
131
|
+
if (scope.isDestroyed || !((_a2 = scope.onUpdate) == null ? void 0 : _a2.length)) return;
|
|
132
|
+
const updateHooks = scope.onUpdate;
|
|
133
|
+
const result = runWithScope(scope, () => executeHooks(updateHooks, scope.id, "update"));
|
|
134
|
+
updateHooks.length = 0;
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
function triggerDestroyHooks(scope) {
|
|
138
|
+
var _a2;
|
|
139
|
+
if (scope.isDestroyed || !((_a2 = scope.onDestroy) == null ? void 0 : _a2.length)) return;
|
|
140
|
+
return runWithScope(scope, () => executeHooks(scope.onDestroy, scope.id, "destroy"));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/scope.ts
|
|
42
144
|
var activeScope = null;
|
|
43
145
|
var scopeId = 0;
|
|
44
146
|
function getActiveScope() {
|
|
@@ -52,25 +154,19 @@ function createScope(parent = activeScope) {
|
|
|
52
154
|
id: ++scopeId,
|
|
53
155
|
parent,
|
|
54
156
|
children: null,
|
|
55
|
-
// Lazy initialized
|
|
56
157
|
provides: null,
|
|
57
|
-
// Lazy initialized
|
|
58
158
|
cleanup: null,
|
|
59
|
-
// Lazy initialized
|
|
60
159
|
onMount: null,
|
|
61
|
-
// Lazy initialized
|
|
62
160
|
onUpdate: null,
|
|
63
|
-
// Lazy initialized
|
|
64
161
|
onDestroy: null,
|
|
65
|
-
// Lazy initialized
|
|
66
162
|
isMounted: false,
|
|
67
163
|
isDestroyed: false
|
|
68
164
|
};
|
|
69
165
|
if (parent) {
|
|
70
166
|
if (!parent.children) {
|
|
71
|
-
parent.children =
|
|
167
|
+
parent.children = [];
|
|
72
168
|
}
|
|
73
|
-
parent.children.
|
|
169
|
+
parent.children.push(scope);
|
|
74
170
|
}
|
|
75
171
|
return scope;
|
|
76
172
|
}
|
|
@@ -84,31 +180,22 @@ function runWithScope(scope, fn) {
|
|
|
84
180
|
}
|
|
85
181
|
}
|
|
86
182
|
function disposeScope(scope) {
|
|
87
|
-
var _a2, _b, _c
|
|
183
|
+
var _a2, _b, _c;
|
|
88
184
|
if (!scope || scope.isDestroyed) {
|
|
89
185
|
return;
|
|
90
186
|
}
|
|
187
|
+
const parentScope = scope.parent;
|
|
91
188
|
if (scope.children) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (child) {
|
|
95
|
-
disposeScope(child);
|
|
96
|
-
}
|
|
189
|
+
for (const child of scope.children) {
|
|
190
|
+
disposeScope(child);
|
|
97
191
|
}
|
|
192
|
+
scope.children.length = 0;
|
|
98
193
|
}
|
|
99
|
-
if (scope.onDestroy) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
hook();
|
|
103
|
-
} catch (error_) {
|
|
104
|
-
{
|
|
105
|
-
shared.error(`Scope(${scope.id}): Error in destroy hook:`, error_);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
scope.onDestroy.clear();
|
|
194
|
+
if ((_a2 = scope.onDestroy) == null ? void 0 : _a2.length) {
|
|
195
|
+
triggerDestroyHooks(scope);
|
|
196
|
+
scope.onDestroy.length = 0;
|
|
110
197
|
}
|
|
111
|
-
if (scope.cleanup) {
|
|
198
|
+
if ((_b = scope.cleanup) == null ? void 0 : _b.length) {
|
|
112
199
|
for (const fn of scope.cleanup) {
|
|
113
200
|
try {
|
|
114
201
|
fn();
|
|
@@ -118,18 +205,22 @@ function disposeScope(scope) {
|
|
|
118
205
|
}
|
|
119
206
|
}
|
|
120
207
|
}
|
|
121
|
-
scope.cleanup.
|
|
208
|
+
scope.cleanup.length = 0;
|
|
122
209
|
}
|
|
123
|
-
if (
|
|
124
|
-
|
|
210
|
+
if (parentScope == null ? void 0 : parentScope.children) {
|
|
211
|
+
const idx = parentScope.children.indexOf(scope);
|
|
212
|
+
if (idx !== -1) {
|
|
213
|
+
parentScope.children.splice(idx, 1);
|
|
214
|
+
}
|
|
125
215
|
}
|
|
126
|
-
(_b = scope.children) == null ? void 0 : _b.clear();
|
|
127
216
|
(_c = scope.provides) == null ? void 0 : _c.clear();
|
|
128
|
-
(
|
|
129
|
-
(
|
|
130
|
-
setActiveScope(scope.parent);
|
|
217
|
+
if (scope.onMount) scope.onMount.length = 0;
|
|
218
|
+
if (scope.onUpdate) scope.onUpdate.length = 0;
|
|
131
219
|
scope.parent = null;
|
|
132
220
|
scope.isDestroyed = true;
|
|
221
|
+
if (activeScope === scope) {
|
|
222
|
+
activeScope = parentScope;
|
|
223
|
+
}
|
|
133
224
|
}
|
|
134
225
|
function onCleanup(fn) {
|
|
135
226
|
const scope = activeScope;
|
|
@@ -140,9 +231,9 @@ function onCleanup(fn) {
|
|
|
140
231
|
return;
|
|
141
232
|
}
|
|
142
233
|
if (!scope.cleanup) {
|
|
143
|
-
scope.cleanup =
|
|
234
|
+
scope.cleanup = [];
|
|
144
235
|
}
|
|
145
|
-
scope.cleanup.
|
|
236
|
+
scope.cleanup.push(fn);
|
|
146
237
|
}
|
|
147
238
|
|
|
148
239
|
// src/constants.ts
|
|
@@ -749,99 +840,6 @@ function mapNodes(template2, indexes) {
|
|
|
749
840
|
walk(template2);
|
|
750
841
|
return tree;
|
|
751
842
|
}
|
|
752
|
-
function registerMountHook(hook) {
|
|
753
|
-
const scope = getActiveScope();
|
|
754
|
-
if (!scope) {
|
|
755
|
-
{
|
|
756
|
-
shared.error("onMount() must be called within a scope");
|
|
757
|
-
}
|
|
758
|
-
return;
|
|
759
|
-
}
|
|
760
|
-
if (scope.isMounted) {
|
|
761
|
-
try {
|
|
762
|
-
hook();
|
|
763
|
-
} catch (error_) {
|
|
764
|
-
{
|
|
765
|
-
shared.error(`Scope(${scope.id}): Error in mount hook:`, error_);
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
if (!scope.onMount) {
|
|
771
|
-
scope.onMount = /* @__PURE__ */ new Set();
|
|
772
|
-
}
|
|
773
|
-
scope.onMount.add(hook);
|
|
774
|
-
}
|
|
775
|
-
function registerUpdateHook(hook) {
|
|
776
|
-
const scope = getActiveScope();
|
|
777
|
-
if (!scope) {
|
|
778
|
-
{
|
|
779
|
-
shared.error("onUpdate() must be called within a scope");
|
|
780
|
-
}
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
if (!scope.onUpdate) {
|
|
784
|
-
scope.onUpdate = /* @__PURE__ */ new Set();
|
|
785
|
-
}
|
|
786
|
-
scope.onUpdate.add(hook);
|
|
787
|
-
}
|
|
788
|
-
function registerDestroyHook(hook) {
|
|
789
|
-
const scope = getActiveScope();
|
|
790
|
-
if (!scope) {
|
|
791
|
-
{
|
|
792
|
-
shared.error("onDestroy() must be called within a scope");
|
|
793
|
-
}
|
|
794
|
-
return;
|
|
795
|
-
}
|
|
796
|
-
if (!scope.onDestroy) {
|
|
797
|
-
scope.onDestroy = /* @__PURE__ */ new Set();
|
|
798
|
-
}
|
|
799
|
-
scope.onDestroy.add(hook);
|
|
800
|
-
}
|
|
801
|
-
function triggerMountHooks(scope) {
|
|
802
|
-
if (!scope || scope.isDestroyed || scope.isMounted) {
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
scope.isMounted = true;
|
|
806
|
-
if (scope.onMount) {
|
|
807
|
-
runWithScope(scope, () => {
|
|
808
|
-
for (const hook of scope.onMount) {
|
|
809
|
-
try {
|
|
810
|
-
hook();
|
|
811
|
-
} catch (error_) {
|
|
812
|
-
if (true) {
|
|
813
|
-
shared.error(`Scope(${scope.id}): Error in mount hook:`, error_);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
function triggerUpdateHooks(scope) {
|
|
821
|
-
if (!scope || scope.isDestroyed) {
|
|
822
|
-
return;
|
|
823
|
-
}
|
|
824
|
-
if (scope.onUpdate) {
|
|
825
|
-
for (const hook of scope.onUpdate) {
|
|
826
|
-
try {
|
|
827
|
-
hook();
|
|
828
|
-
} catch (error_) {
|
|
829
|
-
{
|
|
830
|
-
shared.error(`Scope(${scope.id}): Error in update hook:`, error_);
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
function onMount(hook) {
|
|
837
|
-
registerMountHook(hook);
|
|
838
|
-
}
|
|
839
|
-
function onDestroy(hook) {
|
|
840
|
-
registerDestroyHook(hook);
|
|
841
|
-
}
|
|
842
|
-
function onUpdate(hook) {
|
|
843
|
-
registerUpdateHook(hook);
|
|
844
|
-
}
|
|
845
843
|
|
|
846
844
|
// src/component.ts
|
|
847
845
|
var _a;
|
|
@@ -1586,7 +1584,7 @@ function Portal(props) {
|
|
|
1586
1584
|
onMount(() => {
|
|
1587
1585
|
const targetElement = shared.isString(props.target) ? document.querySelector(props.target) : props.target;
|
|
1588
1586
|
if (!targetElement) {
|
|
1589
|
-
{
|
|
1587
|
+
if (true) {
|
|
1590
1588
|
shared.warn(`[Portal] Target element not found: ${props.target}`);
|
|
1591
1589
|
}
|
|
1592
1590
|
return;
|