@zenithbuild/runtime 0.6.6 → 0.6.9
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/cleanup.d.ts +31 -0
- package/dist/cleanup.js +0 -11
- package/dist/diagnostics.d.ts +4 -0
- package/dist/diagnostics.js +41 -65
- package/dist/effect.d.ts +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.js +1 -11
- package/dist/events.d.ts +8 -0
- package/dist/events.js +2 -6
- package/dist/hydrate.d.ts +57 -0
- package/dist/hydrate.js +110 -351
- package/dist/index.d.ts +6 -0
- package/dist/platform.d.ts +11 -0
- package/dist/platform.js +18 -45
- package/dist/ref.d.ts +4 -0
- package/dist/ref.js +1 -9
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.js +8 -12
- package/dist/signal.d.ts +7 -0
- package/dist/signal.js +3 -15
- package/dist/state.d.ts +10 -0
- package/dist/state.js +4 -20
- package/dist/template.d.ts +2 -0
- package/dist/template.js +0 -10
- package/dist/zeneffect.d.ts +17 -0
- package/dist/zeneffect.js +26 -126
- package/package.json +6 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register an effect disposer for later cleanup.
|
|
3
|
+
*
|
|
4
|
+
* @param {function} dispose
|
|
5
|
+
*/
|
|
6
|
+
export function _registerDisposer(dispose: Function): void;
|
|
7
|
+
/**
|
|
8
|
+
* Register an event listener for later cleanup.
|
|
9
|
+
*
|
|
10
|
+
* @param {Element} element
|
|
11
|
+
* @param {string} event
|
|
12
|
+
* @param {function} handler
|
|
13
|
+
*/
|
|
14
|
+
export function _registerListener(element: Element, event: string, handler: Function): void;
|
|
15
|
+
/**
|
|
16
|
+
* Tear down all active effects and event listeners.
|
|
17
|
+
*
|
|
18
|
+
* - Disposes all effects (clears subscriber sets)
|
|
19
|
+
* - Removes all event listeners
|
|
20
|
+
* - Clears registries
|
|
21
|
+
* - Idempotent: calling twice is a no-op
|
|
22
|
+
*/
|
|
23
|
+
export function cleanup(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Get counts for testing/debugging.
|
|
26
|
+
* @returns {{ effects: number, listeners: number }}
|
|
27
|
+
*/
|
|
28
|
+
export function _getCounts(): {
|
|
29
|
+
effects: number;
|
|
30
|
+
listeners: number;
|
|
31
|
+
};
|
package/dist/cleanup.js
CHANGED
|
@@ -10,17 +10,12 @@
|
|
|
10
10
|
// cleanup() removes everything.
|
|
11
11
|
// Calling cleanup() twice is a no-op.
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
13
|
import { resetGlobalSideEffects } from './zeneffect.js';
|
|
15
|
-
|
|
16
14
|
/** @type {function[]} */
|
|
17
15
|
const _disposers = [];
|
|
18
|
-
|
|
19
16
|
/** @type {{ element: Element, event: string, handler: function }[]} */
|
|
20
17
|
const _listeners = [];
|
|
21
|
-
|
|
22
18
|
let _cleaned = false;
|
|
23
|
-
|
|
24
19
|
/**
|
|
25
20
|
* Register an effect disposer for later cleanup.
|
|
26
21
|
*
|
|
@@ -30,7 +25,6 @@ export function _registerDisposer(dispose) {
|
|
|
30
25
|
_disposers.push(dispose);
|
|
31
26
|
_cleaned = false;
|
|
32
27
|
}
|
|
33
|
-
|
|
34
28
|
/**
|
|
35
29
|
* Register an event listener for later cleanup.
|
|
36
30
|
*
|
|
@@ -42,7 +36,6 @@ export function _registerListener(element, event, handler) {
|
|
|
42
36
|
_listeners.push({ element, event, handler });
|
|
43
37
|
_cleaned = false;
|
|
44
38
|
}
|
|
45
|
-
|
|
46
39
|
/**
|
|
47
40
|
* Tear down all active effects and event listeners.
|
|
48
41
|
*
|
|
@@ -59,23 +52,19 @@ export function cleanup() {
|
|
|
59
52
|
resetGlobalSideEffects();
|
|
60
53
|
return;
|
|
61
54
|
}
|
|
62
|
-
|
|
63
55
|
// 1. Dispose all effects
|
|
64
56
|
for (let i = 0; i < _disposers.length; i++) {
|
|
65
57
|
_disposers[i]();
|
|
66
58
|
}
|
|
67
59
|
_disposers.length = 0;
|
|
68
|
-
|
|
69
60
|
// 2. Remove all event listeners
|
|
70
61
|
for (let i = 0; i < _listeners.length; i++) {
|
|
71
62
|
const { element, event, handler } = _listeners[i];
|
|
72
63
|
element.removeEventListener(event, handler);
|
|
73
64
|
}
|
|
74
65
|
_listeners.length = 0;
|
|
75
|
-
|
|
76
66
|
_cleaned = true;
|
|
77
67
|
}
|
|
78
|
-
|
|
79
68
|
/**
|
|
80
69
|
* Get counts for testing/debugging.
|
|
81
70
|
* @returns {{ effects: number, listeners: number }}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export function isZenithRuntimeError(error: any): boolean;
|
|
2
|
+
export function createZenithRuntimeError(details: any, cause: any): Error;
|
|
3
|
+
export function throwZenithRuntimeError(details: any, cause: any): void;
|
|
4
|
+
export function rethrowZenithRuntimeError(error: any, fallback?: {}): void;
|
package/dist/diagnostics.js
CHANGED
|
@@ -2,7 +2,6 @@ const OVERLAY_ID = '__zenith_runtime_error_overlay';
|
|
|
2
2
|
const MAX_MESSAGE_LENGTH = 120;
|
|
3
3
|
const MAX_HINT_LENGTH = 140;
|
|
4
4
|
const MAX_PATH_LENGTH = 120;
|
|
5
|
-
|
|
6
5
|
const VALID_PHASES = new Set(['hydrate', 'bind', 'render', 'event']);
|
|
7
6
|
const VALID_CODES = new Set([
|
|
8
7
|
'UNRESOLVED_EXPRESSION',
|
|
@@ -12,13 +11,12 @@ const VALID_CODES = new Set([
|
|
|
12
11
|
'BINDING_APPLY_FAILED',
|
|
13
12
|
'EVENT_HANDLER_FAILED'
|
|
14
13
|
]);
|
|
15
|
-
|
|
16
14
|
function _truncate(input, maxLength) {
|
|
17
15
|
const text = String(input ?? '');
|
|
18
|
-
if (text.length <= maxLength)
|
|
16
|
+
if (text.length <= maxLength)
|
|
17
|
+
return text;
|
|
19
18
|
return `${text.slice(0, maxLength - 3)}...`;
|
|
20
19
|
}
|
|
21
|
-
|
|
22
20
|
function _sanitizeAbsolutePaths(value) {
|
|
23
21
|
return String(value ?? '')
|
|
24
22
|
.replace(/[A-Za-z]:\\[^\s"'`]+/g, '<path>')
|
|
@@ -28,80 +26,78 @@ function _sanitizeAbsolutePaths(value) {
|
|
|
28
26
|
.replace(/\/tmp\/[^\s"'`]+/g, '<path>')
|
|
29
27
|
.replace(/\/var\/folders\/[^\s"'`]+/g, '<path>');
|
|
30
28
|
}
|
|
31
|
-
|
|
32
29
|
function _sanitizeMessage(value) {
|
|
33
30
|
const compact = _sanitizeAbsolutePaths(value).replace(/\s+/g, ' ').trim();
|
|
34
31
|
return _truncate(compact || 'Runtime failure', MAX_MESSAGE_LENGTH);
|
|
35
32
|
}
|
|
36
|
-
|
|
37
33
|
function _sanitizeHint(value) {
|
|
38
34
|
if (value === null || value === undefined || value === false) {
|
|
39
35
|
return undefined;
|
|
40
36
|
}
|
|
41
37
|
const compact = _sanitizeAbsolutePaths(value).replace(/\s+/g, ' ').trim();
|
|
42
|
-
if (!compact)
|
|
38
|
+
if (!compact)
|
|
39
|
+
return undefined;
|
|
43
40
|
return _truncate(compact, MAX_HINT_LENGTH);
|
|
44
41
|
}
|
|
45
|
-
|
|
46
42
|
function _sanitizePath(value) {
|
|
47
43
|
if (value === null || value === undefined || value === false) {
|
|
48
44
|
return undefined;
|
|
49
45
|
}
|
|
50
46
|
const compact = _sanitizeAbsolutePaths(value).replace(/\s+/g, ' ').trim();
|
|
51
|
-
if (!compact)
|
|
47
|
+
if (!compact)
|
|
48
|
+
return undefined;
|
|
52
49
|
return _truncate(compact, MAX_PATH_LENGTH);
|
|
53
50
|
}
|
|
54
|
-
|
|
55
51
|
function _normalizeMarker(marker) {
|
|
56
|
-
if (!marker || typeof marker !== 'object')
|
|
52
|
+
if (!marker || typeof marker !== 'object')
|
|
53
|
+
return undefined;
|
|
57
54
|
const markerType = _truncate(_sanitizeAbsolutePaths(marker.type || 'data-zx'), 48);
|
|
58
55
|
const markerId = marker.id;
|
|
59
|
-
if (markerId === null || markerId === undefined || markerId === '')
|
|
56
|
+
if (markerId === null || markerId === undefined || markerId === '')
|
|
57
|
+
return undefined;
|
|
60
58
|
if (typeof markerId === 'number') {
|
|
61
59
|
return { type: markerType, id: markerId };
|
|
62
60
|
}
|
|
63
61
|
return { type: markerType, id: _truncate(_sanitizeAbsolutePaths(markerId), 48) };
|
|
64
62
|
}
|
|
65
|
-
|
|
66
63
|
function _extractErrorMessage(error) {
|
|
67
|
-
if (!error)
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
|
|
64
|
+
if (!error)
|
|
65
|
+
return '';
|
|
66
|
+
if (typeof error === 'string')
|
|
67
|
+
return error;
|
|
68
|
+
if (error instanceof Error && typeof error.message === 'string')
|
|
69
|
+
return error.message;
|
|
70
|
+
if (typeof error.message === 'string')
|
|
71
|
+
return error.message;
|
|
71
72
|
return String(error);
|
|
72
73
|
}
|
|
73
|
-
|
|
74
74
|
function _safeJson(payload) {
|
|
75
75
|
try {
|
|
76
76
|
return JSON.stringify(payload, null, 2);
|
|
77
|
-
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
78
79
|
return '{"kind":"ZENITH_RUNTIME_ERROR","message":"Unable to serialize runtime error payload"}';
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
|
-
|
|
82
82
|
function _readProcessEnv(name) {
|
|
83
83
|
const runtime = typeof globalThis !== 'undefined' ? globalThis : {};
|
|
84
84
|
const runtimeProcess = typeof process !== 'undefined'
|
|
85
85
|
? process
|
|
86
86
|
: runtime.process;
|
|
87
|
-
|
|
88
87
|
if (!runtimeProcess || typeof runtimeProcess !== 'object' || !runtimeProcess.env) {
|
|
89
88
|
return undefined;
|
|
90
89
|
}
|
|
91
90
|
const value = runtimeProcess.env[name];
|
|
92
91
|
return typeof value === 'string' ? value : undefined;
|
|
93
92
|
}
|
|
94
|
-
|
|
95
93
|
function _shouldLogRuntimeError() {
|
|
96
94
|
if (_readProcessEnv('ZENITH_LOG_RUNTIME_ERRORS') === '1') {
|
|
97
95
|
return true;
|
|
98
96
|
}
|
|
99
|
-
const isTestMode =
|
|
100
|
-
_readProcessEnv('NODE_ENV') === 'test'
|
|
97
|
+
const isTestMode = _readProcessEnv('NODE_ENV') === 'test'
|
|
101
98
|
|| _readProcessEnv('ZENITH_TEST_MODE') === '1';
|
|
102
99
|
return !isTestMode;
|
|
103
100
|
}
|
|
104
|
-
|
|
105
101
|
function _isDevDiagnosticsMode() {
|
|
106
102
|
const runtime = typeof globalThis !== 'undefined' ? globalThis : {};
|
|
107
103
|
if (runtime.__ZENITH_RUNTIME_DEV__ === true || runtime.__ZENITH_DEV__ === true) {
|
|
@@ -121,11 +117,11 @@ function _isDevDiagnosticsMode() {
|
|
|
121
117
|
}
|
|
122
118
|
return false;
|
|
123
119
|
}
|
|
124
|
-
|
|
125
120
|
function _renderOverlay(payload) {
|
|
126
|
-
if (!_isDevDiagnosticsMode())
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
if (!_isDevDiagnosticsMode())
|
|
122
|
+
return;
|
|
123
|
+
if (typeof document === 'undefined' || !document.body)
|
|
124
|
+
return;
|
|
129
125
|
let overlay = document.getElementById(OVERLAY_ID);
|
|
130
126
|
if (!overlay) {
|
|
131
127
|
overlay = document.createElement('aside');
|
|
@@ -148,7 +144,6 @@ function _renderOverlay(payload) {
|
|
|
148
144
|
overlay.style.fontSize = '12px';
|
|
149
145
|
overlay.style.lineHeight = '1.45';
|
|
150
146
|
overlay.style.boxShadow = '0 12px 40px rgba(0,0,0,0.45)';
|
|
151
|
-
|
|
152
147
|
const copyButton = document.createElement('button');
|
|
153
148
|
copyButton.type = 'button';
|
|
154
149
|
copyButton.setAttribute('data-zx-runtime-copy', 'true');
|
|
@@ -161,17 +156,14 @@ function _renderOverlay(payload) {
|
|
|
161
156
|
copyButton.style.cursor = 'pointer';
|
|
162
157
|
copyButton.textContent = 'Copy JSON';
|
|
163
158
|
overlay.appendChild(copyButton);
|
|
164
|
-
|
|
165
159
|
document.body.appendChild(overlay);
|
|
166
160
|
}
|
|
167
|
-
|
|
168
161
|
const textLines = [
|
|
169
162
|
'Zenith Runtime Error',
|
|
170
163
|
`phase: ${payload.phase}`,
|
|
171
164
|
`code: ${payload.code}`,
|
|
172
165
|
`message: ${payload.message}`
|
|
173
166
|
];
|
|
174
|
-
|
|
175
167
|
if (payload.marker) {
|
|
176
168
|
textLines.push(`marker: ${payload.marker.type}#${payload.marker.id}`);
|
|
177
169
|
}
|
|
@@ -181,10 +173,8 @@ function _renderOverlay(payload) {
|
|
|
181
173
|
if (payload.hint) {
|
|
182
174
|
textLines.push(`hint: ${payload.hint}`);
|
|
183
175
|
}
|
|
184
|
-
|
|
185
176
|
const jsonText = _safeJson(payload);
|
|
186
177
|
const panelText = textLines.join('\n');
|
|
187
|
-
|
|
188
178
|
let pre = overlay.querySelector('pre[data-zx-runtime-error]');
|
|
189
179
|
if (!pre) {
|
|
190
180
|
pre = document.createElement('pre');
|
|
@@ -195,7 +185,6 @@ function _renderOverlay(payload) {
|
|
|
195
185
|
overlay.insertBefore(pre, overlay.firstChild);
|
|
196
186
|
}
|
|
197
187
|
pre.textContent = panelText;
|
|
198
|
-
|
|
199
188
|
const copyButton = overlay.querySelector('button[data-zx-runtime-copy="true"]');
|
|
200
189
|
if (copyButton) {
|
|
201
190
|
copyButton.onclick = () => {
|
|
@@ -206,11 +195,9 @@ function _renderOverlay(payload) {
|
|
|
206
195
|
};
|
|
207
196
|
}
|
|
208
197
|
}
|
|
209
|
-
|
|
210
198
|
function _mapLegacyError(error, fallback) {
|
|
211
199
|
const rawMessage = _extractErrorMessage(error);
|
|
212
200
|
const safeMessage = _sanitizeMessage(rawMessage);
|
|
213
|
-
|
|
214
201
|
const details = {
|
|
215
202
|
phase: VALID_PHASES.has(fallback.phase) ? fallback.phase : 'hydrate',
|
|
216
203
|
code: VALID_CODES.has(fallback.code) ? fallback.code : 'BINDING_APPLY_FAILED',
|
|
@@ -219,12 +206,12 @@ function _mapLegacyError(error, fallback) {
|
|
|
219
206
|
path: _sanitizePath(fallback.path),
|
|
220
207
|
hint: _sanitizeHint(fallback.hint)
|
|
221
208
|
};
|
|
222
|
-
|
|
223
209
|
if (/failed to resolve expression literal/i.test(rawMessage)) {
|
|
224
210
|
details.phase = 'bind';
|
|
225
211
|
details.code = 'UNRESOLVED_EXPRESSION';
|
|
226
212
|
details.hint = details.hint || 'Verify expression scope keys and signal aliases.';
|
|
227
|
-
}
|
|
213
|
+
}
|
|
214
|
+
else if (/non-renderable (object|function)/i.test(rawMessage)) {
|
|
228
215
|
details.phase = 'render';
|
|
229
216
|
details.code = 'NON_RENDERABLE_VALUE';
|
|
230
217
|
const match = rawMessage.match(/at\s+([A-Za-z0-9_\[\].-]+)/);
|
|
@@ -232,7 +219,8 @@ function _mapLegacyError(error, fallback) {
|
|
|
232
219
|
details.path = _sanitizePath(match[1]);
|
|
233
220
|
}
|
|
234
221
|
details.hint = details.hint || 'Use map() to render object fields into nodes.';
|
|
235
|
-
}
|
|
222
|
+
}
|
|
223
|
+
else if (/unresolved .* marker index/i.test(rawMessage)) {
|
|
236
224
|
details.phase = 'bind';
|
|
237
225
|
details.code = 'MARKER_MISSING';
|
|
238
226
|
const markerMatch = rawMessage.match(/unresolved\s+(\w+)\s+marker index\s+(\d+)/i);
|
|
@@ -244,40 +232,33 @@ function _mapLegacyError(error, fallback) {
|
|
|
244
232
|
}
|
|
245
233
|
details.hint = details.hint || 'Confirm SSR markers and client selector tables match.';
|
|
246
234
|
}
|
|
247
|
-
|
|
248
235
|
return details;
|
|
249
236
|
}
|
|
250
|
-
|
|
251
237
|
export function isZenithRuntimeError(error) {
|
|
252
|
-
return !!(
|
|
253
|
-
error &&
|
|
238
|
+
return !!(error &&
|
|
254
239
|
typeof error === 'object' &&
|
|
255
240
|
error.zenithRuntimeError &&
|
|
256
|
-
error.zenithRuntimeError.kind === 'ZENITH_RUNTIME_ERROR'
|
|
257
|
-
);
|
|
241
|
+
error.zenithRuntimeError.kind === 'ZENITH_RUNTIME_ERROR');
|
|
258
242
|
}
|
|
259
|
-
|
|
260
243
|
export function createZenithRuntimeError(details, cause) {
|
|
261
244
|
const phase = VALID_PHASES.has(details?.phase) ? details.phase : 'hydrate';
|
|
262
245
|
const code = VALID_CODES.has(details?.code) ? details.code : 'BINDING_APPLY_FAILED';
|
|
263
246
|
const message = _sanitizeMessage(details?.message || 'Runtime failure');
|
|
264
|
-
|
|
265
247
|
const payload = {
|
|
266
248
|
kind: 'ZENITH_RUNTIME_ERROR',
|
|
267
249
|
phase,
|
|
268
250
|
code,
|
|
269
251
|
message
|
|
270
252
|
};
|
|
271
|
-
|
|
272
253
|
const marker = _normalizeMarker(details?.marker);
|
|
273
|
-
if (marker)
|
|
274
|
-
|
|
254
|
+
if (marker)
|
|
255
|
+
payload.marker = marker;
|
|
275
256
|
const path = _sanitizePath(details?.path);
|
|
276
|
-
if (path)
|
|
277
|
-
|
|
257
|
+
if (path)
|
|
258
|
+
payload.path = path;
|
|
278
259
|
const hint = _sanitizeHint(details?.hint);
|
|
279
|
-
if (hint)
|
|
280
|
-
|
|
260
|
+
if (hint)
|
|
261
|
+
payload.hint = hint;
|
|
281
262
|
const error = new Error(`[Zenith Runtime] ${code}: ${message}`);
|
|
282
263
|
error.name = 'ZenithRuntimeError';
|
|
283
264
|
error.zenithRuntimeError = payload;
|
|
@@ -287,28 +268,24 @@ export function createZenithRuntimeError(details, cause) {
|
|
|
287
268
|
error.toJSON = () => payload;
|
|
288
269
|
return error;
|
|
289
270
|
}
|
|
290
|
-
|
|
291
271
|
function _reportRuntimeError(error) {
|
|
292
|
-
if (!error || error.__zenithRuntimeErrorReported === true)
|
|
272
|
+
if (!error || error.__zenithRuntimeErrorReported === true)
|
|
273
|
+
return;
|
|
293
274
|
error.__zenithRuntimeErrorReported = true;
|
|
294
275
|
const payload = error.zenithRuntimeError;
|
|
295
|
-
if (
|
|
296
|
-
payload
|
|
276
|
+
if (payload
|
|
297
277
|
&& _shouldLogRuntimeError()
|
|
298
278
|
&& typeof console !== 'undefined'
|
|
299
|
-
&& typeof console.error === 'function'
|
|
300
|
-
) {
|
|
279
|
+
&& typeof console.error === 'function') {
|
|
301
280
|
console.error('[Zenith Runtime]', payload);
|
|
302
281
|
}
|
|
303
282
|
_renderOverlay(payload);
|
|
304
283
|
}
|
|
305
|
-
|
|
306
284
|
export function throwZenithRuntimeError(details, cause) {
|
|
307
285
|
const error = createZenithRuntimeError(details, cause);
|
|
308
286
|
_reportRuntimeError(error);
|
|
309
287
|
throw error;
|
|
310
288
|
}
|
|
311
|
-
|
|
312
289
|
export function rethrowZenithRuntimeError(error, fallback = {}) {
|
|
313
290
|
if (isZenithRuntimeError(error)) {
|
|
314
291
|
const payload = error.zenithRuntimeError || {};
|
|
@@ -316,7 +293,6 @@ export function rethrowZenithRuntimeError(error, fallback = {}) {
|
|
|
316
293
|
const marker = !payload.marker ? _normalizeMarker(fallback.marker) : payload.marker;
|
|
317
294
|
const path = !payload.path ? _sanitizePath(fallback.path) : payload.path;
|
|
318
295
|
const hint = !payload.hint ? _sanitizeHint(fallback.hint) : payload.hint;
|
|
319
|
-
|
|
320
296
|
if (marker || path || hint) {
|
|
321
297
|
updatedPayload = {
|
|
322
298
|
...payload,
|
package/dist/effect.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { zeneffect as effect } from "./zeneffect.js";
|
package/dist/env.d.ts
ADDED
package/dist/env.js
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// env.
|
|
2
|
+
// env.ts — Zenith Runtime canonical environment accessors
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
// SSR-safe access to window and document. Returns null when not in browser.
|
|
5
5
|
// Use zenWindow() / zenDocument() instead of direct window/document access.
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* SSR-safe window accessor.
|
|
10
|
-
* @returns {Window | null}
|
|
11
|
-
*/
|
|
12
7
|
export function zenWindow() {
|
|
13
8
|
return typeof window === 'undefined' ? null : window;
|
|
14
9
|
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* SSR-safe document accessor.
|
|
18
|
-
* @returns {Document | null}
|
|
19
|
-
*/
|
|
20
10
|
export function zenDocument() {
|
|
21
11
|
return typeof document === 'undefined' ? null : document;
|
|
22
12
|
}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bind an event listener to a DOM element.
|
|
3
|
+
*
|
|
4
|
+
* @param {Element} element - The DOM element
|
|
5
|
+
* @param {string} eventName - The event name (e.g. "click")
|
|
6
|
+
* @param {() => any} exprFn - Pre-bound expression function that must resolve to a handler
|
|
7
|
+
*/
|
|
8
|
+
export function bindEvent(element: Element, eventName: string, exprFn: () => any): void;
|
package/dist/events.js
CHANGED
|
@@ -14,10 +14,8 @@
|
|
|
14
14
|
// No delegation.
|
|
15
15
|
// No wrapping.
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
|
-
|
|
18
17
|
import { _registerListener } from './cleanup.js';
|
|
19
18
|
import { rethrowZenithRuntimeError, throwZenithRuntimeError } from './diagnostics.js';
|
|
20
|
-
|
|
21
19
|
/**
|
|
22
20
|
* Bind an event listener to a DOM element.
|
|
23
21
|
*
|
|
@@ -27,7 +25,6 @@ import { rethrowZenithRuntimeError, throwZenithRuntimeError } from './diagnostic
|
|
|
27
25
|
*/
|
|
28
26
|
export function bindEvent(element, eventName, exprFn) {
|
|
29
27
|
const resolved = exprFn();
|
|
30
|
-
|
|
31
28
|
if (typeof resolved !== 'function') {
|
|
32
29
|
throwZenithRuntimeError({
|
|
33
30
|
phase: 'bind',
|
|
@@ -38,11 +35,11 @@ export function bindEvent(element, eventName, exprFn) {
|
|
|
38
35
|
hint: 'Bind events to function references.'
|
|
39
36
|
});
|
|
40
37
|
}
|
|
41
|
-
|
|
42
38
|
const wrapped = function zenithBoundEvent(event) {
|
|
43
39
|
try {
|
|
44
40
|
return resolved.call(this, event);
|
|
45
|
-
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
46
43
|
rethrowZenithRuntimeError(error, {
|
|
47
44
|
phase: 'event',
|
|
48
45
|
code: 'EVENT_HANDLER_FAILED',
|
|
@@ -53,7 +50,6 @@ export function bindEvent(element, eventName, exprFn) {
|
|
|
53
50
|
});
|
|
54
51
|
}
|
|
55
52
|
};
|
|
56
|
-
|
|
57
53
|
element.addEventListener(eventName, wrapped);
|
|
58
54
|
_registerListener(element, eventName, wrapped);
|
|
59
55
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hydrate a pre-rendered DOM tree using explicit payload tables.
|
|
3
|
+
*
|
|
4
|
+
* @param {{
|
|
5
|
+
* ir_version: number,
|
|
6
|
+
* root: Document | Element,
|
|
7
|
+
* expressions: Array<{ marker_index: number, signal_index?: number|null, state_index?: number|null, component_instance?: string|null, component_binding?: string|null, literal?: string|null }>,
|
|
8
|
+
* markers: Array<{ index: number, kind: 'text' | 'attr' | 'event', selector: string, attr?: string }>,
|
|
9
|
+
* events: Array<{ index: number, event: string, selector: string }>,
|
|
10
|
+
* refs?: Array<{ index: number, state_index: number, selector: string }>,
|
|
11
|
+
* state_values: Array<*>,
|
|
12
|
+
* state_keys?: Array<string>,
|
|
13
|
+
* signals: Array<{ id: number, kind: 'signal', state_index: number }>,
|
|
14
|
+
* components?: Array<{ instance: string, selector: string, create: Function }>
|
|
15
|
+
* }} payload
|
|
16
|
+
* @returns {() => void}
|
|
17
|
+
*/
|
|
18
|
+
export function hydrate(payload: {
|
|
19
|
+
ir_version: number;
|
|
20
|
+
root: Document | Element;
|
|
21
|
+
expressions: Array<{
|
|
22
|
+
marker_index: number;
|
|
23
|
+
signal_index?: number | null;
|
|
24
|
+
state_index?: number | null;
|
|
25
|
+
component_instance?: string | null;
|
|
26
|
+
component_binding?: string | null;
|
|
27
|
+
literal?: string | null;
|
|
28
|
+
}>;
|
|
29
|
+
markers: Array<{
|
|
30
|
+
index: number;
|
|
31
|
+
kind: "text" | "attr" | "event";
|
|
32
|
+
selector: string;
|
|
33
|
+
attr?: string;
|
|
34
|
+
}>;
|
|
35
|
+
events: Array<{
|
|
36
|
+
index: number;
|
|
37
|
+
event: string;
|
|
38
|
+
selector: string;
|
|
39
|
+
}>;
|
|
40
|
+
refs?: Array<{
|
|
41
|
+
index: number;
|
|
42
|
+
state_index: number;
|
|
43
|
+
selector: string;
|
|
44
|
+
}>;
|
|
45
|
+
state_values: Array<any>;
|
|
46
|
+
state_keys?: Array<string>;
|
|
47
|
+
signals: Array<{
|
|
48
|
+
id: number;
|
|
49
|
+
kind: "signal";
|
|
50
|
+
state_index: number;
|
|
51
|
+
}>;
|
|
52
|
+
components?: Array<{
|
|
53
|
+
instance: string;
|
|
54
|
+
selector: string;
|
|
55
|
+
create: Function;
|
|
56
|
+
}>;
|
|
57
|
+
}): () => void;
|