@zenithbuild/runtime 0.6.5 → 0.6.7
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 +61 -57
- 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 +15 -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,57 +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
|
+
function _readProcessEnv(name) {
|
|
83
|
+
const runtime = typeof globalThis !== 'undefined' ? globalThis : {};
|
|
84
|
+
const runtimeProcess = typeof process !== 'undefined'
|
|
85
|
+
? process
|
|
86
|
+
: runtime.process;
|
|
87
|
+
if (!runtimeProcess || typeof runtimeProcess !== 'object' || !runtimeProcess.env) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const value = runtimeProcess.env[name];
|
|
91
|
+
return typeof value === 'string' ? value : undefined;
|
|
92
|
+
}
|
|
93
|
+
function _shouldLogRuntimeError() {
|
|
94
|
+
if (_readProcessEnv('ZENITH_LOG_RUNTIME_ERRORS') === '1') {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
const isTestMode = _readProcessEnv('NODE_ENV') === 'test'
|
|
98
|
+
|| _readProcessEnv('ZENITH_TEST_MODE') === '1';
|
|
99
|
+
return !isTestMode;
|
|
100
|
+
}
|
|
82
101
|
function _isDevDiagnosticsMode() {
|
|
83
102
|
const runtime = typeof globalThis !== 'undefined' ? globalThis : {};
|
|
84
103
|
if (runtime.__ZENITH_RUNTIME_DEV__ === true || runtime.__ZENITH_DEV__ === true) {
|
|
@@ -98,11 +117,11 @@ function _isDevDiagnosticsMode() {
|
|
|
98
117
|
}
|
|
99
118
|
return false;
|
|
100
119
|
}
|
|
101
|
-
|
|
102
120
|
function _renderOverlay(payload) {
|
|
103
|
-
if (!_isDevDiagnosticsMode())
|
|
104
|
-
|
|
105
|
-
|
|
121
|
+
if (!_isDevDiagnosticsMode())
|
|
122
|
+
return;
|
|
123
|
+
if (typeof document === 'undefined' || !document.body)
|
|
124
|
+
return;
|
|
106
125
|
let overlay = document.getElementById(OVERLAY_ID);
|
|
107
126
|
if (!overlay) {
|
|
108
127
|
overlay = document.createElement('aside');
|
|
@@ -125,7 +144,6 @@ function _renderOverlay(payload) {
|
|
|
125
144
|
overlay.style.fontSize = '12px';
|
|
126
145
|
overlay.style.lineHeight = '1.45';
|
|
127
146
|
overlay.style.boxShadow = '0 12px 40px rgba(0,0,0,0.45)';
|
|
128
|
-
|
|
129
147
|
const copyButton = document.createElement('button');
|
|
130
148
|
copyButton.type = 'button';
|
|
131
149
|
copyButton.setAttribute('data-zx-runtime-copy', 'true');
|
|
@@ -138,17 +156,14 @@ function _renderOverlay(payload) {
|
|
|
138
156
|
copyButton.style.cursor = 'pointer';
|
|
139
157
|
copyButton.textContent = 'Copy JSON';
|
|
140
158
|
overlay.appendChild(copyButton);
|
|
141
|
-
|
|
142
159
|
document.body.appendChild(overlay);
|
|
143
160
|
}
|
|
144
|
-
|
|
145
161
|
const textLines = [
|
|
146
162
|
'Zenith Runtime Error',
|
|
147
163
|
`phase: ${payload.phase}`,
|
|
148
164
|
`code: ${payload.code}`,
|
|
149
165
|
`message: ${payload.message}`
|
|
150
166
|
];
|
|
151
|
-
|
|
152
167
|
if (payload.marker) {
|
|
153
168
|
textLines.push(`marker: ${payload.marker.type}#${payload.marker.id}`);
|
|
154
169
|
}
|
|
@@ -158,10 +173,8 @@ function _renderOverlay(payload) {
|
|
|
158
173
|
if (payload.hint) {
|
|
159
174
|
textLines.push(`hint: ${payload.hint}`);
|
|
160
175
|
}
|
|
161
|
-
|
|
162
176
|
const jsonText = _safeJson(payload);
|
|
163
177
|
const panelText = textLines.join('\n');
|
|
164
|
-
|
|
165
178
|
let pre = overlay.querySelector('pre[data-zx-runtime-error]');
|
|
166
179
|
if (!pre) {
|
|
167
180
|
pre = document.createElement('pre');
|
|
@@ -172,7 +185,6 @@ function _renderOverlay(payload) {
|
|
|
172
185
|
overlay.insertBefore(pre, overlay.firstChild);
|
|
173
186
|
}
|
|
174
187
|
pre.textContent = panelText;
|
|
175
|
-
|
|
176
188
|
const copyButton = overlay.querySelector('button[data-zx-runtime-copy="true"]');
|
|
177
189
|
if (copyButton) {
|
|
178
190
|
copyButton.onclick = () => {
|
|
@@ -183,11 +195,9 @@ function _renderOverlay(payload) {
|
|
|
183
195
|
};
|
|
184
196
|
}
|
|
185
197
|
}
|
|
186
|
-
|
|
187
198
|
function _mapLegacyError(error, fallback) {
|
|
188
199
|
const rawMessage = _extractErrorMessage(error);
|
|
189
200
|
const safeMessage = _sanitizeMessage(rawMessage);
|
|
190
|
-
|
|
191
201
|
const details = {
|
|
192
202
|
phase: VALID_PHASES.has(fallback.phase) ? fallback.phase : 'hydrate',
|
|
193
203
|
code: VALID_CODES.has(fallback.code) ? fallback.code : 'BINDING_APPLY_FAILED',
|
|
@@ -196,12 +206,12 @@ function _mapLegacyError(error, fallback) {
|
|
|
196
206
|
path: _sanitizePath(fallback.path),
|
|
197
207
|
hint: _sanitizeHint(fallback.hint)
|
|
198
208
|
};
|
|
199
|
-
|
|
200
209
|
if (/failed to resolve expression literal/i.test(rawMessage)) {
|
|
201
210
|
details.phase = 'bind';
|
|
202
211
|
details.code = 'UNRESOLVED_EXPRESSION';
|
|
203
212
|
details.hint = details.hint || 'Verify expression scope keys and signal aliases.';
|
|
204
|
-
}
|
|
213
|
+
}
|
|
214
|
+
else if (/non-renderable (object|function)/i.test(rawMessage)) {
|
|
205
215
|
details.phase = 'render';
|
|
206
216
|
details.code = 'NON_RENDERABLE_VALUE';
|
|
207
217
|
const match = rawMessage.match(/at\s+([A-Za-z0-9_\[\].-]+)/);
|
|
@@ -209,7 +219,8 @@ function _mapLegacyError(error, fallback) {
|
|
|
209
219
|
details.path = _sanitizePath(match[1]);
|
|
210
220
|
}
|
|
211
221
|
details.hint = details.hint || 'Use map() to render object fields into nodes.';
|
|
212
|
-
}
|
|
222
|
+
}
|
|
223
|
+
else if (/unresolved .* marker index/i.test(rawMessage)) {
|
|
213
224
|
details.phase = 'bind';
|
|
214
225
|
details.code = 'MARKER_MISSING';
|
|
215
226
|
const markerMatch = rawMessage.match(/unresolved\s+(\w+)\s+marker index\s+(\d+)/i);
|
|
@@ -221,40 +232,33 @@ function _mapLegacyError(error, fallback) {
|
|
|
221
232
|
}
|
|
222
233
|
details.hint = details.hint || 'Confirm SSR markers and client selector tables match.';
|
|
223
234
|
}
|
|
224
|
-
|
|
225
235
|
return details;
|
|
226
236
|
}
|
|
227
|
-
|
|
228
237
|
export function isZenithRuntimeError(error) {
|
|
229
|
-
return !!(
|
|
230
|
-
error &&
|
|
238
|
+
return !!(error &&
|
|
231
239
|
typeof error === 'object' &&
|
|
232
240
|
error.zenithRuntimeError &&
|
|
233
|
-
error.zenithRuntimeError.kind === 'ZENITH_RUNTIME_ERROR'
|
|
234
|
-
);
|
|
241
|
+
error.zenithRuntimeError.kind === 'ZENITH_RUNTIME_ERROR');
|
|
235
242
|
}
|
|
236
|
-
|
|
237
243
|
export function createZenithRuntimeError(details, cause) {
|
|
238
244
|
const phase = VALID_PHASES.has(details?.phase) ? details.phase : 'hydrate';
|
|
239
245
|
const code = VALID_CODES.has(details?.code) ? details.code : 'BINDING_APPLY_FAILED';
|
|
240
246
|
const message = _sanitizeMessage(details?.message || 'Runtime failure');
|
|
241
|
-
|
|
242
247
|
const payload = {
|
|
243
248
|
kind: 'ZENITH_RUNTIME_ERROR',
|
|
244
249
|
phase,
|
|
245
250
|
code,
|
|
246
251
|
message
|
|
247
252
|
};
|
|
248
|
-
|
|
249
253
|
const marker = _normalizeMarker(details?.marker);
|
|
250
|
-
if (marker)
|
|
251
|
-
|
|
254
|
+
if (marker)
|
|
255
|
+
payload.marker = marker;
|
|
252
256
|
const path = _sanitizePath(details?.path);
|
|
253
|
-
if (path)
|
|
254
|
-
|
|
257
|
+
if (path)
|
|
258
|
+
payload.path = path;
|
|
255
259
|
const hint = _sanitizeHint(details?.hint);
|
|
256
|
-
if (hint)
|
|
257
|
-
|
|
260
|
+
if (hint)
|
|
261
|
+
payload.hint = hint;
|
|
258
262
|
const error = new Error(`[Zenith Runtime] ${code}: ${message}`);
|
|
259
263
|
error.name = 'ZenithRuntimeError';
|
|
260
264
|
error.zenithRuntimeError = payload;
|
|
@@ -264,23 +268,24 @@ export function createZenithRuntimeError(details, cause) {
|
|
|
264
268
|
error.toJSON = () => payload;
|
|
265
269
|
return error;
|
|
266
270
|
}
|
|
267
|
-
|
|
268
271
|
function _reportRuntimeError(error) {
|
|
269
|
-
if (!error || error.__zenithRuntimeErrorReported === true)
|
|
272
|
+
if (!error || error.__zenithRuntimeErrorReported === true)
|
|
273
|
+
return;
|
|
270
274
|
error.__zenithRuntimeErrorReported = true;
|
|
271
275
|
const payload = error.zenithRuntimeError;
|
|
272
|
-
if (payload
|
|
276
|
+
if (payload
|
|
277
|
+
&& _shouldLogRuntimeError()
|
|
278
|
+
&& typeof console !== 'undefined'
|
|
279
|
+
&& typeof console.error === 'function') {
|
|
273
280
|
console.error('[Zenith Runtime]', payload);
|
|
274
281
|
}
|
|
275
282
|
_renderOverlay(payload);
|
|
276
283
|
}
|
|
277
|
-
|
|
278
284
|
export function throwZenithRuntimeError(details, cause) {
|
|
279
285
|
const error = createZenithRuntimeError(details, cause);
|
|
280
286
|
_reportRuntimeError(error);
|
|
281
287
|
throw error;
|
|
282
288
|
}
|
|
283
|
-
|
|
284
289
|
export function rethrowZenithRuntimeError(error, fallback = {}) {
|
|
285
290
|
if (isZenithRuntimeError(error)) {
|
|
286
291
|
const payload = error.zenithRuntimeError || {};
|
|
@@ -288,7 +293,6 @@ export function rethrowZenithRuntimeError(error, fallback = {}) {
|
|
|
288
293
|
const marker = !payload.marker ? _normalizeMarker(fallback.marker) : payload.marker;
|
|
289
294
|
const path = !payload.path ? _sanitizePath(fallback.path) : payload.path;
|
|
290
295
|
const hint = !payload.hint ? _sanitizeHint(fallback.hint) : payload.hint;
|
|
291
|
-
|
|
292
296
|
if (marker || path || hint) {
|
|
293
297
|
updatedPayload = {
|
|
294
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;
|