@jay-framework/runtime 0.17.3 → 0.18.0

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/index.d.ts CHANGED
@@ -475,25 +475,6 @@ declare function isForEach<ViewState, Item>(c: Conditional<ViewState> | When<Vie
475
475
  declare function isWhen<ViewState, Item>(c: Conditional<ViewState> | When<ViewState, any> | ForEach<ViewState, Item> | WithData<ViewState, any> | TextElement<ViewState> | BaseJayElement<ViewState>): c is When<ViewState, any>;
476
476
  declare function isWithData<ViewState, ChildViewState>(c: Conditional<ViewState> | When<ViewState, any> | ForEach<ViewState, any> | WithData<ViewState, ChildViewState> | TextElement<ViewState> | BaseJayElement<ViewState>): c is WithData<ViewState, ChildViewState>;
477
477
  declare function forEach<T, Item>(getItems: (T: any) => Array<Item>, elemCreator: (Item: any) => BaseJayElement<Item>, matchBy: string): ForEach<T, Item>;
478
- /**
479
- * Runtime support for pre-rendered slow arrays (slowForEach in jay-html).
480
- *
481
- * This function is used when a forEach loop has been pre-rendered at slow phase.
482
- * The array items are statically embedded in the jay-html, but we still need to:
483
- * 1. Set up the correct data context for each item (so bindings work)
484
- * 2. Enable fast/interactive updates within each item
485
- * 3. Support event handling with the correct item coordinates
486
- *
487
- * The key insight is that slowForEachItem switches the data context to the
488
- * specific array item, so child bindings like {price} work correctly
489
- * (they resolve to item.price, not viewState.price).
490
- *
491
- * @param getItems - Function to get the array from the parent ViewState (handles nested paths)
492
- * @param index - The jayIndex value (position in the pre-rendered array)
493
- * @param trackByValue - The jayTrackBy value (identity for reconciliation)
494
- * @param elementCreator - Function that creates the pre-rendered element (called within item context)
495
- */
496
- declare function slowForEachItem<ParentVS, ItemVS>(getItems: (parentData: ParentVS) => ItemVS[], index: number, trackByValue: string, elementCreator: () => BaseJayElement<ItemVS>): BaseJayElement<ParentVS>;
497
478
  interface ForEach<ViewState, Item> {
498
479
  getItems: (T: any) => Array<Item>;
499
480
  elemCreator: (Item: any, String: any) => BaseJayElement<Item>;
@@ -586,7 +567,7 @@ declare class ConstructContext<ViewState> {
586
567
  get dataIds(): Coordinate;
587
568
  coordinate: (refName: string) => Coordinate;
588
569
  /**
589
- * Create a child context for a forEach/slowForEach item.
570
+ * Create a child context for a forEach item.
590
571
  *
591
572
  * With scoped coordinates (DL#126), coordinateBase is NOT accumulated —
592
573
  * scoped coordinates are fully qualified within each scope. Only dataIds
@@ -742,4 +723,4 @@ declare function hydrateForEach<ViewState, Item>(accessor: (vs: ViewState) => It
742
723
  */
743
724
  declare function childCompHydrate<ParentVS, Props, ChildT, ChildElement extends BaseJayElement<ChildT>, ChildComp extends JayComponent<Props, ChildT, ChildElement>>(compCreator: JayComponentConstructor<Props>, getProps: (t: ParentVS) => Props, scopeRootCoordinate?: string, ref?: PrivateRef<ParentVS, ChildComp>): BaseJayElement<ParentVS>;
744
725
 
745
- export { type Attribute, type Attributes, type BaseJayElement, BaseReferencesManager, type ComponentCollectionProxy, ComponentCollectionRefImpl, type ComponentProxy, ComponentRefImpl, ComponentRefsImpl, type Conditional, ConstructContext, type ContextMarker, type Coordinate, type DynamicAttributeOrProperty, EVENT_TRAP, type ElementFrom, type EventEmitter, type EventTypeFrom, type ExtractFastViewState, type ExtractInteractiveViewState, type ExtractProps, type ExtractRefs, type ExtractSlowViewState, type ExtractViewState, type ForEach, GetTrapProxy, type GlobalJayEvents, type HTMLElementCollectionProxy, type HTMLElementCollectionProxyTarget, type HTMLElementProxy, type HTMLElementProxyTarget, type HTMLNativeExec, type HeadLink, type HtmlContent, type JayComponent, type JayComponentConstructor, type JayContract, type JayElement, type JayEvent, type JayEventHandler, type JayEventHandlerWrapper, type JayLog, type JayNativeEventBuilder, type JayNativeFunction, LogType, type ManagedRefConstructor, ManagedRefType, type ManagedRefs, type MapEventEmitterViewState, type MountFunc, type OnlyEventEmitters, type PreRenderElement, type PrivateRef, type PrivateRefConstructor, PrivateRefs, type PropsFrom, ReferencesManager, type RenderElement, type RenderElementOptions, STATIC, type TextElement, VIEW_STATE_CHANGE_EVENT, type ViewStateFrom, type When, WhenRole, type WithData, adoptDynamicElement, adoptElement, adoptText, applyHtmlContent, booleanAttribute, childComp, childCompHydrate, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicHtml, dynamicProperty, dynamicText, element, findContext, forEach, hydrateConditional, hydrateForEach, injectHeadLinks, isCondition, isForEach, isHtmlContent, isWhen, isWithData, jayLog, mathMLDynamicElement, mathMLElement, mkUpdateCollection, noop, noopMount, noopUpdate, normalizeMount, normalizeUpdates, pending, registerGlobalContext, rejected, resolved, restoreContext, saveContext, slowForEachItem, svgDynamicElement, svgElement, type updateFunc, useContext, useGlobalContext, withContext, withData };
726
+ export { type Attribute, type Attributes, type BaseJayElement, BaseReferencesManager, type ComponentCollectionProxy, ComponentCollectionRefImpl, type ComponentProxy, ComponentRefImpl, ComponentRefsImpl, type Conditional, ConstructContext, type ContextMarker, type Coordinate, type DynamicAttributeOrProperty, EVENT_TRAP, type ElementFrom, type EventEmitter, type EventTypeFrom, type ExtractFastViewState, type ExtractInteractiveViewState, type ExtractProps, type ExtractRefs, type ExtractSlowViewState, type ExtractViewState, type ForEach, GetTrapProxy, type GlobalJayEvents, type HTMLElementCollectionProxy, type HTMLElementCollectionProxyTarget, type HTMLElementProxy, type HTMLElementProxyTarget, type HTMLNativeExec, type HeadLink, type HtmlContent, type JayComponent, type JayComponentConstructor, type JayContract, type JayElement, type JayEvent, type JayEventHandler, type JayEventHandlerWrapper, type JayLog, type JayNativeEventBuilder, type JayNativeFunction, LogType, type ManagedRefConstructor, ManagedRefType, type ManagedRefs, type MapEventEmitterViewState, type MountFunc, type OnlyEventEmitters, type PreRenderElement, type PrivateRef, type PrivateRefConstructor, PrivateRefs, type PropsFrom, ReferencesManager, type RenderElement, type RenderElementOptions, STATIC, type TextElement, VIEW_STATE_CHANGE_EVENT, type ViewStateFrom, type When, WhenRole, type WithData, adoptDynamicElement, adoptElement, adoptText, applyHtmlContent, booleanAttribute, childComp, childCompHydrate, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicHtml, dynamicProperty, dynamicText, element, findContext, forEach, hydrateConditional, hydrateForEach, injectHeadLinks, isCondition, isForEach, isHtmlContent, isWhen, isWithData, jayLog, mathMLDynamicElement, mathMLElement, mkUpdateCollection, noop, noopMount, noopUpdate, normalizeMount, normalizeUpdates, pending, registerGlobalContext, rejected, resolved, restoreContext, saveContext, svgDynamicElement, svgElement, type updateFunc, useContext, useGlobalContext, withContext, withData };
package/dist/index.js CHANGED
@@ -199,7 +199,7 @@ class ConstructContext {
199
199
  return this._dataIds;
200
200
  }
201
201
  /**
202
- * Create a child context for a forEach/slowForEach item.
202
+ * Create a child context for a forEach item.
203
203
  *
204
204
  * With scoped coordinates (DL#126), coordinateBase is NOT accumulated —
205
205
  * scoped coordinates are fully qualified within each scope. Only dataIds
@@ -556,33 +556,6 @@ function mkWhenPendingCondition(when2, group) {
556
556
  function forEach(getItems, elemCreator, matchBy) {
557
557
  return { getItems, elemCreator, trackBy: matchBy };
558
558
  }
559
- function slowForEachItem(getItems, index, trackByValue, elementCreator) {
560
- const parentContext = currentConstructionContext();
561
- const savedContext = saveContext();
562
- const parentData = parentContext.currData;
563
- const array = getItems(parentData);
564
- const initialItem = array?.[index];
565
- const childContext = parentContext.forItem(initialItem, trackByValue);
566
- const element2 = withContext(CONSTRUCTION_CONTEXT_MARKER, childContext, elementCreator);
567
- const originalUpdate = element2.update;
568
- const update = (newParentData) => {
569
- const newArray = getItems(newParentData);
570
- const newItem = newArray?.[index];
571
- const updateChildContext = parentContext.forItem(newItem, trackByValue);
572
- restoreContext(
573
- savedContext,
574
- () => withContext(CONSTRUCTION_CONTEXT_MARKER, updateChildContext, () => {
575
- originalUpdate(newItem);
576
- })
577
- );
578
- };
579
- return {
580
- dom: element2.dom,
581
- update,
582
- mount: element2.mount,
583
- unmount: element2.unmount
584
- };
585
- }
586
559
  function withData(accessor, elem) {
587
560
  return { accessor, elem };
588
561
  }
@@ -975,7 +948,10 @@ class HTMLElementRefsImpl extends PrivateRefs {
975
948
  return newHTMLElementPublicApiProxy(this);
976
949
  }
977
950
  exec$(handler) {
978
- return [...this.elements][0].exec$(handler);
951
+ const first = [...this.elements][0];
952
+ if (!first)
953
+ return Promise.resolve(void 0);
954
+ return first.exec$(handler);
979
955
  }
980
956
  }
981
957
  class ComponentRefsImpl extends PrivateRefs {
@@ -1058,6 +1034,8 @@ class HTMLElementRefImpl extends RefImpl {
1058
1034
  return newHTMLElementPublicApiProxy(this);
1059
1035
  }
1060
1036
  exec$(handler) {
1037
+ if (!this.element)
1038
+ return Promise.resolve(void 0);
1061
1039
  return new Promise((resolve, reject) => {
1062
1040
  try {
1063
1041
  resolve(handler(this.element, this.viewState));
@@ -1682,7 +1660,6 @@ export {
1682
1660
  resolved,
1683
1661
  restoreContext,
1684
1662
  saveContext,
1685
- slowForEachItem,
1686
1663
  svgDynamicElement,
1687
1664
  svgElement,
1688
1665
  useContext,
package/docs/refs.md CHANGED
@@ -101,7 +101,9 @@ interface HTMLElementProxy<ViewState, ElementType extends HTMLElement>
101
101
  - `addEventListener`: registers a new event handlers.
102
102
  - `removeEventListener`: registers a new event handlers.
103
103
  - `exec$`: runs a code function against the DOM element. The function must match compiler patterns (see the compiler security section)
104
- to be property run in secure applications. In non-secure applications, the function just runs with the DOM element.
104
+ to be properly run in secure applications. In non-secure applications, the function just runs with the DOM element.
105
+ **Important:** `exec$` must only be used inside event handlers — never at top-level component creation or in effects,
106
+ because elements don't exist yet at that point. Top-level `exec$` calls silently resolve to `undefined`.
105
107
 
106
108
  ## HTMLElementCollectionProxy
107
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/runtime",
3
- "version": "0.17.3",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -23,11 +23,11 @@
23
23
  "test:watch": "vitest"
24
24
  },
25
25
  "dependencies": {
26
- "@jay-framework/list-compare": "^0.17.3",
27
- "@jay-framework/reactive": "^0.17.3"
26
+ "@jay-framework/list-compare": "^0.18.0",
27
+ "@jay-framework/reactive": "^0.18.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@jay-framework/dev-environment": "^0.17.3",
30
+ "@jay-framework/dev-environment": "^0.18.0",
31
31
  "@testing-library/jest-dom": "^6.2.0",
32
32
  "@types/jsdom": "^21.1.6",
33
33
  "@types/node": "^20.11.5",