@zenithbuild/runtime 0.7.5 → 0.7.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/hydrate.js CHANGED
@@ -10,7 +10,7 @@ import { createNodeResolver } from './scanner.js';
10
10
  import { bindEventMarkers } from './events.js';
11
11
  import { _applyMarkerValue } from './render.js';
12
12
  export { _createContextualFragment, _coerceText } from './render.js';
13
- // Raw HTML boundary enforcement lives in render.js:
13
+ // Raw HTML boundary lock lives in render.js:
14
14
  // attrName.toLowerCase() === 'innerhtml'
15
15
  // innerHTML bindings are forbidden in Zenith
16
16
  // attrName.toLowerCase() === 'unsafehtml'
@@ -19,7 +19,7 @@ export function hydrate(payload) {
19
19
  try {
20
20
  const normalized = _validatePayload(payload);
21
21
  _deepFreezePayload(payload);
22
- const { root, expressions, markers, events, refs, stateValues, stateKeys, signals, components, route, params, ssrData, props, exprFns } = normalized;
22
+ const { root, expressions, markers, events, refs, stateValues, stateKeys, signals, components, params, ssrData, props, exprFns } = normalized;
23
23
  const componentBindings = Object.create(null);
24
24
  const resolveNodes = createNodeResolver(root);
25
25
  const signalMap = _createSignalMap(signals, stateValues);
@@ -28,12 +28,10 @@ export function hydrate(payload) {
28
28
  components,
29
29
  signalMap,
30
30
  componentBindings,
31
- route,
32
31
  resolveNodes
33
32
  });
34
- const markerState = _hydrateMarkers({
33
+ const runtimeContext = {
35
34
  expressions,
36
- markers,
37
35
  stateValues,
38
36
  stateKeys,
39
37
  signalMap,
@@ -43,22 +41,16 @@ export function hydrate(payload) {
43
41
  props,
44
42
  exprFns,
45
43
  resolveNodes
44
+ };
45
+ const markerState = _hydrateMarkers({
46
+ ...runtimeContext,
47
+ markers
46
48
  });
47
- const renderMarkerByIndex = (index) => _renderMarker({
48
- index,
49
- root,
50
- expressions,
51
- stateValues,
52
- stateKeys,
53
- signalMap,
54
- componentBindings,
55
- params,
56
- ssrData,
57
- props,
58
- exprFns,
59
- resolveNodes,
49
+ const renderContext = {
50
+ ...runtimeContext,
60
51
  ...markerState
61
- });
52
+ };
53
+ const renderMarkerByIndex = (index) => _renderMarker(renderContext, index);
62
54
  _bindSignalSubscriptions(expressions, signalMap, stateValues, renderMarkerByIndex);
63
55
  _bindComponentSignalSubscriptions(expressions, componentBindings, renderMarkerByIndex);
64
56
  bindEventMarkers({
@@ -82,7 +74,7 @@ export function hydrate(payload) {
82
74
  rethrowZenithRuntimeError(error, {
83
75
  phase: 'hydrate',
84
76
  code: 'BINDING_APPLY_FAILED',
85
- hint: 'Inspect marker tables, expression bindings, and the runtime overlay diagnostics.',
77
+ hint: 'Inspect marker tables, expression bindings, and runtime diagnostics.',
86
78
  docsLink: DOCS_LINKS.markerTable
87
79
  });
88
80
  }
@@ -121,13 +113,10 @@ function _hydrateRefs(refs, stateValues, resolveNodes) {
121
113
  });
122
114
  }
123
115
  function _mountComponents(context) {
124
- const { components, signalMap, componentBindings, route, resolveNodes } = context;
116
+ const { components, signalMap, componentBindings, resolveNodes } = context;
125
117
  for (let i = 0; i < components.length; i++) {
126
118
  const component = components[i];
127
- const resolvedProps = Object.freeze(_resolveComponentProps(component.props || [], signalMap, {
128
- component: component.instance,
129
- route
130
- }));
119
+ const resolvedProps = Object.freeze(_resolveComponentProps(component.props || [], signalMap));
131
120
  const hosts = resolveNodes(component.selector, i, 'component', component.source);
132
121
  for (let j = 0; j < hosts.length; j++) {
133
122
  try {
@@ -176,7 +165,7 @@ function _mountComponents(context) {
176
165
  code: 'COMPONENT_BOOTSTRAP_FAILED',
177
166
  message: `Component bootstrap failed for "${component.instance}"`,
178
167
  path: `component[${component.instance}]`,
179
- hint: 'Fix the failing component and refresh; other components continue mounting.',
168
+ hint: 'Fix the failing component and refresh.',
180
169
  docsLink: DOCS_LINKS.componentBootstrap,
181
170
  source: component.source
182
171
  });
@@ -188,49 +177,31 @@ function _mountComponents(context) {
188
177
  }
189
178
  }
190
179
  function _hydrateMarkers(context) {
191
- const { expressions, markers, stateValues, stateKeys, signalMap, componentBindings, params, ssrData, props, exprFns, resolveNodes } = context;
180
+ const { expressions, markers, resolveNodes } = context;
192
181
  const markerByIndex = new Map();
193
182
  const markerNodesByIndex = new Map();
194
- const markerIndices = new Set();
195
- const expressionMarkerIndices = new Set();
196
- for (let i = 0; i < expressions.length; i++) {
197
- const expression = expressions[i];
198
- if (expressionMarkerIndices.has(expression.marker_index)) {
199
- throw new Error(`[Zenith Runtime] duplicate expression marker_index ${expression.marker_index}`);
200
- }
201
- expressionMarkerIndices.add(expression.marker_index);
202
- }
203
183
  for (let i = 0; i < markers.length; i++) {
204
184
  const marker = markers[i];
205
- if (markerIndices.has(marker.index)) {
206
- throw new Error(`[Zenith Runtime] duplicate marker index ${marker.index}`);
207
- }
208
- markerIndices.add(marker.index);
209
185
  markerByIndex.set(marker.index, marker);
210
186
  if (marker.kind === 'event') {
211
187
  continue;
212
188
  }
213
189
  const nodes = resolveNodes(marker.selector, marker.index, marker.kind, marker.source);
214
190
  markerNodesByIndex.set(marker.index, nodes);
215
- const value = _evaluateExpression(expressions[marker.index], stateValues, stateKeys, signalMap, componentBindings, params, ssrData, marker.kind, props, exprFns, marker, null);
191
+ const value = _evaluateMarkerBinding(context, expressions[marker.index], marker);
216
192
  _applyMarkerValue(nodes, marker, value);
217
193
  }
218
- for (let i = 0; i < expressions.length; i++) {
219
- if (!markerIndices.has(i)) {
220
- throw new Error(`[Zenith Runtime] missing marker index ${i}`);
221
- }
222
- }
223
194
  return { markerByIndex, markerNodesByIndex };
224
195
  }
225
- function _renderMarker(context) {
226
- const marker = context.markerByIndex.get(context.index);
196
+ function _renderMarker(context, index) {
197
+ const marker = context.markerByIndex.get(index);
227
198
  if (!marker || marker.kind === 'event') {
228
199
  return;
229
200
  }
230
- const nodes = context.markerNodesByIndex.get(context.index)
201
+ const nodes = context.markerNodesByIndex.get(index)
231
202
  || context.resolveNodes(marker.selector, marker.index, marker.kind, marker.source);
232
- context.markerNodesByIndex.set(context.index, nodes);
233
- const value = _evaluateExpression(context.expressions[context.index], context.stateValues, context.stateKeys, context.signalMap, context.componentBindings, context.params, context.ssrData, marker.kind, context.props, context.exprFns, marker, null);
203
+ context.markerNodesByIndex.set(index, nodes);
204
+ const value = _evaluateMarkerBinding(context, context.expressions[index], marker);
234
205
  _applyMarkerValue(nodes, marker, value);
235
206
  }
236
207
  function _isSignalLike(candidate) {
@@ -265,16 +236,7 @@ function _bindSignalSubscriptions(expressions, signalMap, stateValues, renderMar
265
236
  _recordSignalMarkerDependency(dependentMarkersBySignal, stateValues[expression.state_index], expression.marker_index);
266
237
  }
267
238
  }
268
- for (const [targetSignal, markerIndexes] of dependentMarkersBySignal.entries()) {
269
- const unsubscribe = targetSignal.subscribe(() => {
270
- for (let i = 0; i < markerIndexes.length; i++) {
271
- renderMarkerByIndex(markerIndexes[i]);
272
- }
273
- });
274
- if (typeof unsubscribe === 'function') {
275
- _registerDisposer(unsubscribe);
276
- }
277
- }
239
+ _subscribeMarkerDependencies(dependentMarkersBySignal, renderMarkerByIndex);
278
240
  }
279
241
  function _bindComponentSignalSubscriptions(expressions, componentBindings, renderMarkerByIndex) {
280
242
  const dependentMarkersByComponentSignal = new Map();
@@ -285,10 +247,7 @@ function _bindComponentSignalSubscriptions(expressions, componentBindings, rende
285
247
  }
286
248
  const instanceBindings = componentBindings[expression.component_instance];
287
249
  const candidate = instanceBindings?.[expression.component_binding];
288
- if (!candidate || typeof candidate !== 'object') {
289
- continue;
290
- }
291
- if (typeof candidate.get !== 'function' || typeof candidate.subscribe !== 'function') {
250
+ if (!_isSignalLike(candidate)) {
292
251
  continue;
293
252
  }
294
253
  if (!dependentMarkersByComponentSignal.has(candidate)) {
@@ -296,8 +255,14 @@ function _bindComponentSignalSubscriptions(expressions, componentBindings, rende
296
255
  }
297
256
  dependentMarkersByComponentSignal.get(candidate).push(expression.marker_index);
298
257
  }
299
- for (const [componentSignal, markerIndexes] of dependentMarkersByComponentSignal.entries()) {
300
- const unsubscribe = componentSignal.subscribe(() => {
258
+ _subscribeMarkerDependencies(dependentMarkersByComponentSignal, renderMarkerByIndex);
259
+ }
260
+ function _evaluateMarkerBinding(context, expression, marker) {
261
+ return _evaluateExpression(expression, context.stateValues, context.stateKeys, context.signalMap, context.componentBindings, context.params, context.ssrData, marker.kind, context.props, context.exprFns, marker, null);
262
+ }
263
+ function _subscribeMarkerDependencies(dependencies, renderMarkerByIndex) {
264
+ for (const [targetSignal, markerIndexes] of dependencies.entries()) {
265
+ const unsubscribe = targetSignal.subscribe(() => {
301
266
  for (let i = 0; i < markerIndexes.length; i++) {
302
267
  renderMarkerByIndex(markerIndexes[i]);
303
268
  }
package/dist/markup.js CHANGED
@@ -30,7 +30,7 @@ export function _fragment(strings, ...values) {
30
30
  phase: 'render',
31
31
  code: 'NON_RENDERABLE_VALUE',
32
32
  message: '__zenith_fragment must be called as a tagged template literal',
33
- hint: 'This helper only accepts tagged template syntax.'
33
+ hint: 'This helper only accepts tagged templates.'
34
34
  });
35
35
  }
36
36
  let result = '';
@@ -46,7 +46,7 @@ export function _fragment(strings, ...values) {
46
46
  phase: 'render',
47
47
  code: 'NON_RENDERABLE_VALUE',
48
48
  message: 'Embedded markup expression contains forbidden <script> tag',
49
- hint: 'Script tags are not allowed in embedded markup expressions.'
49
+ hint: 'Script tags are not allowed in embedded markup.'
50
50
  });
51
51
  }
52
52
  if (_FRAGMENT_EVENT_ATTR_RE.test(result)) {
@@ -54,7 +54,7 @@ export function _fragment(strings, ...values) {
54
54
  phase: 'render',
55
55
  code: 'NON_RENDERABLE_VALUE',
56
56
  message: 'Embedded markup expression contains inline event handler (on*=)',
57
- hint: 'Use on:event={handler} bindings instead of inline event attributes.'
57
+ hint: 'Use on:event={handler} instead of inline event attributes.'
58
58
  });
59
59
  }
60
60
  if (_FRAGMENT_JS_URL_RE.test(result)) {
@@ -62,7 +62,7 @@ export function _fragment(strings, ...values) {
62
62
  phase: 'render',
63
63
  code: 'NON_RENDERABLE_VALUE',
64
64
  message: 'Embedded markup expression contains javascript: URL',
65
- hint: 'javascript: URLs are forbidden in embedded markup.'
65
+ hint: 'javascript: URLs are forbidden.'
66
66
  });
67
67
  }
68
68
  result = result.replace(_FRAGMENT_SCRIPT_CLOSE_RE, '<\\/script');
@@ -99,7 +99,7 @@ function _fragmentInterpolate(val, interpolationIndex) {
99
99
  phase: 'render',
100
100
  code: 'NON_RENDERABLE_VALUE',
101
101
  message: `Embedded markup interpolation[${interpolationIndex}] contains forbidden key "${keys[k]}"`,
102
- hint: 'Prototype pollution keys are forbidden in embedded markup expressions.'
102
+ hint: 'Prototype pollution keys are forbidden in embedded markup.'
103
103
  });
104
104
  }
105
105
  }
@@ -107,14 +107,14 @@ function _fragmentInterpolate(val, interpolationIndex) {
107
107
  phase: 'render',
108
108
  code: 'NON_RENDERABLE_VALUE',
109
109
  message: `Embedded markup interpolation[${interpolationIndex}] resolved to a non-renderable object`,
110
- hint: 'Only strings, numbers, booleans, null, undefined, arrays, and compiler-owned fragments are allowed.'
110
+ hint: 'Only primitives, arrays, and compiler-owned fragments are allowed.'
111
111
  });
112
112
  }
113
113
  throwZenithRuntimeError({
114
114
  phase: 'render',
115
115
  code: 'NON_RENDERABLE_VALUE',
116
116
  message: `Embedded markup interpolation[${interpolationIndex}] resolved to type "${typeof val}"`,
117
- hint: 'Only strings, numbers, booleans, null, undefined, arrays, and compiler-owned fragments are allowed.'
117
+ hint: 'Only primitives, arrays, and compiler-owned fragments are allowed.'
118
118
  });
119
119
  }
120
120
  function _escapeFragmentHtml(input) {
package/dist/payload.d.ts CHANGED
@@ -1,20 +1,19 @@
1
- export function _validatePayload(payload: any): Readonly<{
1
+ export function _validatePayload(payload: any): {
2
2
  root: any;
3
- expressions: any[];
4
- markers: any[];
5
- events: any[];
3
+ expressions: any;
4
+ markers: any;
5
+ events: any;
6
6
  refs: any;
7
- stateValues: any[];
8
- stateKeys: any[];
9
- signals: any[];
7
+ stateValues: any;
8
+ stateKeys: any;
9
+ signals: any;
10
10
  components: any;
11
- route: any;
12
11
  params: any;
13
12
  ssrData: any;
14
13
  props: any;
15
14
  exprFns: any;
16
- }>;
17
- export function _resolveComponentProps(propTable: any, signalMap: any, context?: {}): any;
15
+ };
16
+ export function _resolveComponentProps(propTable: any, signalMap: any): any;
18
17
  export function _deepFreezePayload(obj: any): void;
19
18
  export function _isHydrationRefObject(obj: any): boolean;
20
19
  export function _isPlainObject(value: any): boolean;