@qwik.dev/core 2.0.0-beta.21 → 2.0.0-beta.23

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/core.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * @qwik.dev/core 2.0.0-beta.21-dev+c008e88
3
+ * @qwik.dev/core 2.0.0-beta.23-dev+03de42d
4
4
  * Copyright QwikDev. All Rights Reserved.
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://github.com/QwikDev/qwik/blob/main/LICENSE
@@ -14,7 +14,7 @@ import { p } from '@qwik.dev/core/preloader';
14
14
  *
15
15
  * @public
16
16
  */
17
- const version = "2.0.0-beta.21-dev+c008e88";
17
+ const version = "2.0.0-beta.23-dev+03de42d";
18
18
 
19
19
  // same as isDev but separate so we can test
20
20
  const qDev = globalThis.qDev !== false;
@@ -230,7 +230,6 @@ const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
230
230
  // Attributes namespaces
231
231
  const XLINK_NS = 'http://www.w3.org/1999/xlink';
232
232
  const XML_NS = 'http://www.w3.org/XML/1998/namespace';
233
- const ResourceEvent = 'qResource';
234
233
  const RenderEvent = 'qRender';
235
234
  const TaskEvent = 'qTask';
236
235
  /** `<q:slot name="...">` */
@@ -396,11 +395,6 @@ const maybeThen = (valueOrPromise, thenFn) => {
396
395
  ? valueOrPromise.then(thenFn)
397
396
  : thenFn(valueOrPromise);
398
397
  };
399
- const delay = (timeout) => {
400
- return new Promise((resolve) => {
401
- setTimeout(resolve, timeout);
402
- });
403
- };
404
398
  const checkError = (e) => {
405
399
  if (isServer && e instanceof ReferenceError && e.message.includes('window')) {
406
400
  e.message = 'It seems like you forgot to add "if (isBrowser) {...}" here:' + e.message;
@@ -577,40 +571,6 @@ const vnode_getElementNamespaceFlags = (element) => {
577
571
  return 0 /* VNodeFlags.NS_html */;
578
572
  }
579
573
  };
580
- function vnode_getDomChildrenWithCorrectNamespacesToInsert(journal, domParentVNode, newChild) {
581
- const { elementNamespace, elementNamespaceFlag } = getNewElementNamespaceData(domParentVNode, newChild);
582
- let domChildren = [];
583
- if (elementNamespace === HTML_NS) {
584
- // parent is in the default namespace, so just get the dom children. This is the fast path.
585
- domChildren = vnode_getDOMChildNodes(journal, newChild, true);
586
- }
587
- else {
588
- // parent is in a different namespace, so we need to clone the children with the correct namespace.
589
- // The namespace cannot be changed on nodes, so we need to clone these nodes
590
- const children = vnode_getDOMChildNodes(journal, newChild, true);
591
- for (let i = 0; i < children.length; i++) {
592
- const childVNode = children[i];
593
- if (vnode_isTextVNode(childVNode)) {
594
- // text nodes are always in the default namespace
595
- domChildren.push(childVNode);
596
- continue;
597
- }
598
- if ((childVNode.flags & 1536 /* VNodeFlags.NAMESPACE_MASK */) ===
599
- (domParentVNode.flags & 1536 /* VNodeFlags.NAMESPACE_MASK */)) {
600
- // if the child and parent have the same namespace, we don't need to clone the element
601
- domChildren.push(childVNode);
602
- continue;
603
- }
604
- // clone the element with the correct namespace
605
- const newChildElement = vnode_cloneElementWithNamespace(childVNode, domParentVNode, elementNamespace, elementNamespaceFlag);
606
- if (newChildElement) {
607
- childVNode.node = newChildElement;
608
- domChildren.push(childVNode);
609
- }
610
- }
611
- }
612
- return domChildren;
613
- }
614
574
  /** This function clones an element with a different namespace, including the children */
615
575
  function cloneDomTreeWithNamespace(element, elementName, namespace, deep = false) {
616
576
  const newElement = element.ownerDocument.createElementNS(namespace, elementName);
@@ -963,8 +923,7 @@ class TextVNode extends VNode {
963
923
  const globalCursorQueue = [];
964
924
  const pausedCursorQueue = [];
965
925
  /**
966
- * Adds a cursor to the global queue. If the cursor already exists, it's removed and re-added to
967
- * maintain correct priority order.
926
+ * Adds a cursor to the global queue.
968
927
  *
969
928
  * @param cursor - The cursor to add
970
929
  */
@@ -979,7 +938,7 @@ function addCursorToQueue(container, cursor) {
979
938
  }
980
939
  }
981
940
  globalCursorQueue.splice(insertIndex, 0, cursor);
982
- container.$cursorCount$++;
941
+ container.$pendingCount$++;
983
942
  container.$renderPromise$ ||= new Promise((r) => (container.$resolveRenderPromise$ = r));
984
943
  }
985
944
  /**
@@ -1007,7 +966,7 @@ function getHighestPriorityCursor() {
1007
966
  function pauseCursor(cursor, container) {
1008
967
  pausedCursorQueue.push(cursor);
1009
968
  removeCursorFromQueue(cursor, container, true);
1010
- container.$pausedCursorCount$++;
969
+ container.$pendingCount$++;
1011
970
  }
1012
971
  function resumeCursor(cursor, container) {
1013
972
  const index = pausedCursorQueue.indexOf(cursor);
@@ -1017,7 +976,7 @@ function resumeCursor(cursor, container) {
1017
976
  pausedCursorQueue[index] = pausedCursorQueue[lastIndex];
1018
977
  }
1019
978
  pausedCursorQueue.pop();
1020
- container.$pausedCursorCount$--;
979
+ container.$pendingCount$--;
1021
980
  }
1022
981
  addCursorToQueue(container, cursor);
1023
982
  }
@@ -1040,7 +999,7 @@ function removeCursorFromQueue(cursor, container, keepCursorFlag) {
1040
999
  // }
1041
1000
  // globalCursorQueue.pop();
1042
1001
  globalCursorQueue.splice(index, 1);
1043
- container.$cursorCount$--;
1002
+ container.$pendingCount$--;
1044
1003
  }
1045
1004
  }
1046
1005
 
@@ -1129,7 +1088,7 @@ class SignalImpl {
1129
1088
  $container$ = null;
1130
1089
  $wrappedSignal$ = null;
1131
1090
  constructor(container, value) {
1132
- this.$container$ = container;
1091
+ this.$container$ = container || tryGetInvokeContext()?.$container$ || null;
1133
1092
  this.$untrackedValue$ = value;
1134
1093
  }
1135
1094
  /**
@@ -1147,14 +1106,13 @@ class SignalImpl {
1147
1106
  this.$untrackedValue$ = value;
1148
1107
  }
1149
1108
  get value() {
1109
+ // Important: first read, then subscribe. Otherwise, initial compute invalidation will cause the reading subscriber to be marked invalid.
1110
+ const val = this.untrackedValue;
1150
1111
  const ctx = tryGetInvokeContext();
1151
1112
  if (!ctx) {
1152
- return this.untrackedValue;
1113
+ return val;
1153
1114
  }
1154
1115
  if (this.$container$ === null) {
1155
- if (!ctx.$container$) {
1156
- return this.untrackedValue;
1157
- }
1158
1116
  // Grab the container now we have access to it
1159
1117
  this.$container$ = ctx.$container$;
1160
1118
  }
@@ -1175,7 +1133,7 @@ class SignalImpl {
1175
1133
  (import.meta.env.TEST ? !isDomContainer(this.$container$) : isServer) &&
1176
1134
  addQrlToSerializationCtx(effectSubscriber, this.$container$);
1177
1135
  }
1178
- return this.untrackedValue;
1136
+ return val;
1179
1137
  }
1180
1138
  set value(value) {
1181
1139
  if (value !== this.$untrackedValue$) {
@@ -1191,10 +1149,15 @@ class SignalImpl {
1191
1149
  }
1192
1150
  toString() {
1193
1151
  if (isDev) {
1194
- return (`[${this.constructor.name}${this.$flags$ & 1 /* SignalFlags.INVALID */ ? ' INVALID' : ''} ${String(this.$untrackedValue$)}]` +
1195
- (Array.from(this.$effects$ || [])
1196
- .map((e) => '\n -> ' + pad(qwikDebugToString(e.consumer), ' '))
1197
- .join('\n') || ''));
1152
+ try {
1153
+ return (`[${this.constructor.name}${this.$flags$ & 1 /* SignalFlags.INVALID */ ? ' INVALID' : ''} ${this.$untrackedValue$}]` +
1154
+ (Array.from(this.$effects$ || [])
1155
+ .map((e) => '\n -> ' + pad(qwikDebugToString(e.consumer), ' '))
1156
+ .join('\n') || ''));
1157
+ }
1158
+ catch (e) {
1159
+ return `[${this.constructor.name} <cannot stringify>]`;
1160
+ }
1198
1161
  }
1199
1162
  else {
1200
1163
  return this.constructor.name;
@@ -1204,35 +1167,27 @@ class SignalImpl {
1204
1167
  return { value: this.$untrackedValue$ };
1205
1168
  }
1206
1169
  }
1207
- const setupSignalValueAccess = (target, effectsFn, returnValueFn) => {
1170
+ const setupSignalValueAccess = (target, effectsProp, valueProp) => {
1208
1171
  const ctx = tryGetInvokeContext();
1209
- if (!ctx) {
1210
- return returnValueFn();
1211
- }
1212
- if (target.$container$ === null) {
1213
- if (!ctx.$container$) {
1214
- return returnValueFn();
1215
- }
1216
- // Grab the container now we have access to it
1217
- target.$container$ = ctx.$container$;
1218
- }
1219
- else {
1172
+ // We need a container for this
1173
+ // Grab the container if we have access to it
1174
+ if (ctx && (target.$container$ ||= ctx.$container$ || null)) {
1220
1175
  isDev &&
1221
1176
  assertTrue(!ctx.$container$ || ctx.$container$ === target.$container$, 'Do not use signals across containers');
1177
+ const effectSubscriber = ctx.$effectSubscriber$;
1178
+ if (effectSubscriber) {
1179
+ // Let's make sure that we have a reference to this effect.
1180
+ // Adding reference is essentially adding a subscription, so if the signal
1181
+ // changes we know who to notify.
1182
+ ensureContainsSubscription((target[effectsProp] ||= new Set()), effectSubscriber);
1183
+ // But when effect is scheduled in needs to be able to know which signals
1184
+ // to unsubscribe from. So we need to store the reference from the effect back
1185
+ // to this signal.
1186
+ ensureContainsBackRef(effectSubscriber, target);
1187
+ addQrlToSerializationCtx(effectSubscriber, target.$container$);
1188
+ }
1222
1189
  }
1223
- const effectSubscriber = ctx.$effectSubscriber$;
1224
- if (effectSubscriber) {
1225
- // Let's make sure that we have a reference to this effect.
1226
- // Adding reference is essentially adding a subscription, so if the signal
1227
- // changes we know who to notify.
1228
- ensureContainsSubscription(effectsFn(), effectSubscriber);
1229
- // But when effect is scheduled in needs to be able to know which signals
1230
- // to unsubscribe from. So we need to store the reference from the effect back
1231
- // to this signal.
1232
- ensureContainsBackRef(effectSubscriber, target);
1233
- addQrlToSerializationCtx(effectSubscriber, target.$container$);
1234
- }
1235
- return returnValueFn();
1190
+ return target[valueProp];
1236
1191
  };
1237
1192
 
1238
1193
  /** @internal */
@@ -1461,19 +1416,6 @@ const isPropsProxy = (obj) => {
1461
1416
  return obj && _VAR_PROPS in obj;
1462
1417
  };
1463
1418
 
1464
- const cleanupDestroyable = (destroyable) => {
1465
- const destroy = destroyable.$destroy$;
1466
- if (destroy) {
1467
- destroyable.$destroy$ = null;
1468
- try {
1469
- destroy();
1470
- }
1471
- catch (err) {
1472
- logError(err);
1473
- }
1474
- }
1475
- };
1476
-
1477
1419
  /**
1478
1420
  * # ================================
1479
1421
  *
@@ -1594,14 +1536,19 @@ const trackFn = (target, container) => (obj, prop) => {
1594
1536
  }
1595
1537
  });
1596
1538
  };
1539
+ /**
1540
+ * This adds $destroy$ to the target if a cleanup function is registered. It must be called before
1541
+ * running any computations again.
1542
+ */
1597
1543
  const cleanupFn = (target, handleError) => {
1598
1544
  let cleanupFns = null;
1599
1545
  const cleanup = (fn) => {
1600
1546
  if (typeof fn == 'function') {
1601
1547
  if (!cleanupFns) {
1602
1548
  cleanupFns = [];
1603
- target.$destroy$ = noSerialize(() => {
1549
+ target.$destroy$ = () => {
1604
1550
  target.$destroy$ = null;
1551
+ // TODO handle promises
1605
1552
  for (const fn of cleanupFns) {
1606
1553
  try {
1607
1554
  fn();
@@ -1610,7 +1557,7 @@ const cleanupFn = (target, handleError) => {
1610
1557
  handleError(err);
1611
1558
  }
1612
1559
  }
1613
- });
1560
+ };
1614
1561
  }
1615
1562
  cleanupFns.push(fn);
1616
1563
  }
@@ -1618,9 +1565,9 @@ const cleanupFn = (target, handleError) => {
1618
1565
  return [cleanup, cleanupFns ?? []];
1619
1566
  };
1620
1567
 
1621
- const DEBUG = false;
1568
+ const DEBUG$1 = false;
1622
1569
  // eslint-disable-next-line no-console
1623
- const log = (...args) => console.log('COMPUTED SIGNAL', ...args.map(qwikDebugToString));
1570
+ const log$1 = (...args) => console.log('COMPUTED SIGNAL', ...args.map(qwikDebugToString));
1624
1571
  /**
1625
1572
  * A signal which is computed from other signals.
1626
1573
  *
@@ -1643,7 +1590,7 @@ class ComputedSignalImpl extends SignalImpl {
1643
1590
  16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */) {
1644
1591
  // The value is used for comparison when signals trigger, which can only happen
1645
1592
  // when it was calculated before. Therefore we can pass whatever we like.
1646
- super(container, NEEDS_COMPUTATION);
1593
+ super(container || fn.$container$, NEEDS_COMPUTATION);
1647
1594
  this.$computeQrl$ = fn;
1648
1595
  this.$flags$ = flags;
1649
1596
  }
@@ -1651,20 +1598,18 @@ class ComputedSignalImpl extends SignalImpl {
1651
1598
  this.$flags$ |= 1 /* SignalFlags.INVALID */;
1652
1599
  const ctx = newInvokeContext();
1653
1600
  ctx.$container$ = this.$container$ || undefined;
1654
- maybeThen(retryOnPromise(() => invoke.call(this, ctx, this.$computeIfNeeded$)), () => {
1655
- if (this.$flags$ & 2 /* SignalFlags.RUN_EFFECTS */) {
1656
- this.$flags$ &= -3 /* SignalFlags.RUN_EFFECTS */;
1657
- scheduleEffects(this.$container$, this, this.$effects$);
1658
- }
1659
- });
1660
- }
1661
- /**
1662
- * Use this to force running subscribers, for example when the calculated value has mutated but
1663
- * remained the same object
1664
- */
1665
- force() {
1666
- this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1667
- super.force();
1601
+ // @ts-expect-error it's confused about args any[] vs []
1602
+ const running = retryOnPromise(invokeApply.bind(this, ctx, this.$computeIfNeeded$));
1603
+ if (running) {
1604
+ running.catch((err) => {
1605
+ if (this.$container$) {
1606
+ this.$container$.handleError(err, null);
1607
+ }
1608
+ else {
1609
+ console.error('Error during computation', err);
1610
+ }
1611
+ });
1612
+ }
1668
1613
  }
1669
1614
  get untrackedValue() {
1670
1615
  this.$computeIfNeeded$();
@@ -1692,16 +1637,9 @@ class ComputedSignalImpl extends SignalImpl {
1692
1637
  computeQrl.$hash$,
1693
1638
  ]);
1694
1639
  }
1695
- DEBUG && log('Signal.$compute$', untrackedValue);
1640
+ DEBUG$1 && log$1('Signal.$compute$', untrackedValue);
1696
1641
  this.$flags$ &= ~1 /* SignalFlags.INVALID */;
1697
- const didChange = untrackedValue !== this.$untrackedValue$;
1698
- if (didChange) {
1699
- // skip first computation when value is not changed
1700
- if (this.$untrackedValue$ !== NEEDS_COMPUTATION) {
1701
- this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1702
- }
1703
- this.$untrackedValue$ = untrackedValue;
1704
- }
1642
+ super.value = untrackedValue;
1705
1643
  }
1706
1644
  finally {
1707
1645
  if (ctx) {
@@ -1711,6 +1649,51 @@ class ComputedSignalImpl extends SignalImpl {
1711
1649
  }
1712
1650
  }
1713
1651
 
1652
+ /**
1653
+ * Planned features:
1654
+ *
1655
+ * - `eagerCleanup`: boolean - whether to run cleanups eagerly when there are no more subscribers, or
1656
+ * to wait until the next computation/destroy.
1657
+ */
1658
+ const DEBUG = false;
1659
+ const log = (...args) =>
1660
+ // eslint-disable-next-line no-console
1661
+ console.log('ASYNC COMPUTED SIGNAL', ...args.map(qwikDebugToString));
1662
+ /** Retains job metadata and also serves as the argument for the compute function */
1663
+ class AsyncJob {
1664
+ $signal$;
1665
+ /** First holds the compute promise and then the cleanup promise */
1666
+ $promise$ = null;
1667
+ $cleanupRequested$ = false;
1668
+ $canWrite$ = true;
1669
+ $track$;
1670
+ $cleanups$;
1671
+ $abortController$;
1672
+ constructor($signal$) {
1673
+ this.$signal$ = $signal$;
1674
+ }
1675
+ get track() {
1676
+ return (this.$track$ ||= trackFn(this.$signal$, this.$signal$.$container$));
1677
+ }
1678
+ get abortSignal() {
1679
+ return (this.$abortController$ ||= new AbortController()).signal;
1680
+ }
1681
+ /** Backward compatible cache method for resource */
1682
+ cache() {
1683
+ console.error('useResource cache() method does not do anything. Use `useAsync$` instead of `useResource$`, use the `interval` option for polling behavior.');
1684
+ }
1685
+ get previous() {
1686
+ const val = this.$signal$.$untrackedValue$;
1687
+ if (val !== NEEDS_COMPUTATION) {
1688
+ return val;
1689
+ }
1690
+ }
1691
+ cleanup(callback) {
1692
+ if (typeof callback === 'function') {
1693
+ (this.$cleanups$ ||= []).push(callback);
1694
+ }
1695
+ }
1696
+ }
1714
1697
  /**
1715
1698
  * # ================================
1716
1699
  *
@@ -1723,19 +1706,45 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1723
1706
  $untrackedError$ = undefined;
1724
1707
  $loadingEffects$ = undefined;
1725
1708
  $errorEffects$ = undefined;
1726
- $destroy$;
1727
- $promiseValue$ = NEEDS_COMPUTATION;
1728
- $promise$ = null;
1709
+ $current$ = null;
1710
+ // TODO only create the array if concurrency > 1
1711
+ $jobs$ = [];
1712
+ $concurrency$ = 1;
1713
+ $interval$ = 0;
1714
+ $pollTimeoutId$ = undefined;
1715
+ $timeoutMs$;
1716
+ $computationTimeoutId$;
1729
1717
  [_EFFECT_BACK_REF] = undefined;
1730
- constructor(container, fn, flags = 1 /* SignalFlags.INVALID */) {
1718
+ constructor(container, fn, flags = 1 /* SignalFlags.INVALID */ |
1719
+ 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */, options) {
1731
1720
  super(container, fn, flags);
1721
+ const interval = options?.interval || 0;
1722
+ const concurrency = options?.concurrency ?? 1;
1723
+ const initial = options?.initial;
1724
+ const timeout = options?.timeout;
1725
+ const eagerCleanup = options?.eagerCleanup;
1726
+ // Handle initial value - eagerly evaluate if function, set $untrackedValue$ and $promiseValue$
1727
+ // Do NOT call setValue() which would clear the INVALID flag and prevent async computation
1728
+ if (initial !== undefined) {
1729
+ const initialValue = typeof initial === 'function' ? initial() : initial;
1730
+ this.$untrackedValue$ = initialValue;
1731
+ }
1732
+ this.$concurrency$ = concurrency;
1733
+ this.$timeoutMs$ = timeout;
1734
+ if (eagerCleanup) {
1735
+ this.$flags$ |= 32 /* AsyncSignalFlags.EAGER_CLEANUP */;
1736
+ }
1737
+ this.interval = interval;
1732
1738
  }
1733
1739
  /**
1734
1740
  * Loading is true if the signal is still waiting for the promise to resolve, false if the promise
1735
1741
  * has resolved or rejected.
1742
+ *
1743
+ * Accessing .loading will trigger computation if needed, since it's often used like
1744
+ * `signal.loading ? <Loading /> : signal.value`.
1736
1745
  */
1737
1746
  get loading() {
1738
- return setupSignalValueAccess(this, () => (this.$loadingEffects$ ||= new Set()), () => this.untrackedLoading);
1747
+ return setupSignalValueAccess(this, '$loadingEffects$', 'untrackedLoading');
1739
1748
  }
1740
1749
  set untrackedLoading(value) {
1741
1750
  if (value !== this.$untrackedLoading$) {
@@ -1744,11 +1753,17 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1744
1753
  }
1745
1754
  }
1746
1755
  get untrackedLoading() {
1756
+ // reading `.loading` means someone is interested in the result, so we should trigger the computation. The alternative is eager computation or imperative calls to invalidate; this seems nicer.
1757
+ this.$computeIfNeeded$();
1758
+ // During SSR there's no such thing as loading state, we must render complete results
1759
+ if ((import.meta.env.TEST ? isServerPlatform() : isServer) && this.$current$?.$promise$) {
1760
+ throw this.$current$?.$promise$;
1761
+ }
1747
1762
  return this.$untrackedLoading$;
1748
1763
  }
1749
1764
  /** The error that occurred when the signal was resolved. */
1750
1765
  get error() {
1751
- return setupSignalValueAccess(this, () => (this.$errorEffects$ ||= new Set()), () => this.untrackedError);
1766
+ return setupSignalValueAccess(this, '$errorEffects$', 'untrackedError');
1752
1767
  }
1753
1768
  set untrackedError(value) {
1754
1769
  if (value !== this.$untrackedError$) {
@@ -1759,123 +1774,205 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1759
1774
  get untrackedError() {
1760
1775
  return this.$untrackedError$;
1761
1776
  }
1762
- invalidate() {
1763
- // clear the promise, we need to get function again
1764
- this.$promise$ = null;
1765
- super.invalidate();
1777
+ get interval() {
1778
+ return this.$interval$;
1779
+ }
1780
+ set interval(value) {
1781
+ this.$clearNextPoll$();
1782
+ this.$interval$ = value;
1783
+ if (this.$interval$ > 0 && this.$effects$?.size) {
1784
+ this.$scheduleNextPoll$();
1785
+ }
1786
+ }
1787
+ /** Invalidates the signal, causing it to re-compute its value. */
1788
+ async invalidate() {
1789
+ this.$flags$ |= 1 /* SignalFlags.INVALID */;
1790
+ this.$clearNextPoll$();
1791
+ if (this.$effects$?.size || this.$loadingEffects$?.size || this.$errorEffects$?.size) {
1792
+ // compute in next microtask
1793
+ await true;
1794
+ this.$computeIfNeeded$();
1795
+ }
1766
1796
  }
1797
+ /** Abort the current computation and run cleanups if needed. */
1798
+ abort(reason) {
1799
+ if (this.$current$) {
1800
+ this.$requestCleanups$(this.$current$, reason);
1801
+ }
1802
+ }
1803
+ /** Schedule eager cleanup on next macro task if no subscribers remain. */
1804
+ $scheduleEagerCleanup$() {
1805
+ if (!(this.$flags$ & 32 /* AsyncSignalFlags.EAGER_CLEANUP */) || this.$hasSubscribers$()) {
1806
+ return;
1807
+ }
1808
+ if (!(import.meta.env.TEST ? !isServerPlatform() : isBrowser)) {
1809
+ return;
1810
+ }
1811
+ setTimeout(() => {
1812
+ if (!this.$hasSubscribers$()) {
1813
+ this.abort();
1814
+ }
1815
+ });
1816
+ }
1817
+ /** Returns a promise resolves when the signal finished computing. */
1767
1818
  async promise() {
1768
- // make sure we get a new promise during the next computation
1769
- this.$promise$ = null;
1770
- await retryOnPromise(this.$computeIfNeeded$.bind(this));
1771
- return this.$untrackedValue$;
1819
+ this.$computeIfNeeded$();
1820
+ // Wait for the current computation to finish, but if we became invalid while running, we need to wait for the new computation instead. So we loop until we are no longer invalid
1821
+ while (this.$current$?.$promise$) {
1822
+ await this.$current$?.$promise$;
1823
+ }
1772
1824
  }
1825
+ /** Run the computation if needed */
1773
1826
  $computeIfNeeded$() {
1774
1827
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1775
1828
  return;
1776
1829
  }
1777
- const untrackedValue =
1778
- // first time
1779
- this.$promiseValue$ === NEEDS_COMPUTATION ||
1780
- // or after invalidation
1781
- this.$promise$ === null
1782
- ? this.$promiseComputation$()
1783
- : this.$promiseValue$;
1784
- if (isPromise(untrackedValue)) {
1785
- const isFirstComputation = this.$promiseValue$ === NEEDS_COMPUTATION;
1786
- this.untrackedLoading = true;
1787
- this.untrackedError = undefined;
1788
- if (this.$promiseValue$ !== NEEDS_COMPUTATION) {
1789
- // skip cleanup after resuming
1790
- cleanupDestroyable(this);
1791
- }
1792
- const promise = untrackedValue
1793
- .then((promiseValue) => {
1794
- this.$promiseValue$ = promiseValue;
1795
- this.untrackedLoading = false;
1796
- this.untrackedError = undefined;
1797
- if (this.setValue(promiseValue)) {
1798
- this.$flags$ &= -3 /* SignalFlags.RUN_EFFECTS */;
1799
- scheduleEffects(this.$container$, this, this.$effects$);
1800
- }
1801
- })
1802
- .catch((err) => {
1803
- if (isPromise(err)) {
1804
- // ignore promise errors, they will be handled
1805
- return;
1830
+ this.$clearNextPoll$();
1831
+ if (this.$current$) {
1832
+ this.$requestCleanups$(this.$current$);
1833
+ }
1834
+ const limit = this.$concurrency$ === 0 ? Number.POSITIVE_INFINITY : this.$concurrency$;
1835
+ if (this.$jobs$.length >= limit) {
1836
+ // We requested cleanups for all the previous jobs, once one finishes it will be removed from the jobs array and trigger computeIfNeeded
1837
+ return;
1838
+ }
1839
+ this.$flags$ &= -2 /* SignalFlags.INVALID */;
1840
+ // We put the actual computation in a separate method so we can easily retain the promise
1841
+ const running = new AsyncJob(this);
1842
+ this.$current$ = running;
1843
+ this.$jobs$.push(running);
1844
+ running.$promise$ = this.$runComputation$(running);
1845
+ }
1846
+ async $runComputation$(running) {
1847
+ const isCurrent = () => running === this.$current$;
1848
+ this.untrackedLoading = true;
1849
+ const fn = this.$computeQrl$.resolved || (await this.$computeQrl$.resolve());
1850
+ try {
1851
+ if (this.$timeoutMs$) {
1852
+ this.$computationTimeoutId$ = setTimeout(() => {
1853
+ running.$abortController$?.abort();
1854
+ const error = new Error(`timeout`);
1855
+ if (isCurrent()) {
1856
+ this.untrackedError = error;
1857
+ running.$canWrite$ = false;
1858
+ }
1859
+ }, this.$timeoutMs$);
1860
+ }
1861
+ const value = await retryOnPromise(fn.bind(null, running));
1862
+ running.$promise$ = null;
1863
+ if (running.$canWrite$) {
1864
+ const index = this.$jobs$.indexOf(running);
1865
+ if (index !== -1) {
1866
+ for (let i = 0; i < index; i++) {
1867
+ this.$jobs$[i].$canWrite$ = false;
1868
+ }
1806
1869
  }
1807
- this.$promiseValue$ = err;
1808
- this.untrackedLoading = false;
1870
+ DEBUG && log('Promise resolved', value);
1871
+ // we leave error as-is until result
1872
+ // Note that these assignments run setters
1873
+ this.untrackedError = undefined;
1874
+ this.value = value;
1875
+ }
1876
+ }
1877
+ catch (err) {
1878
+ running.$promise$ = null;
1879
+ if (isCurrent()) {
1809
1880
  this.untrackedError = err;
1810
- });
1811
- if (isFirstComputation) {
1812
- // we want to throw only the first time
1813
- // the next time we will return stale value
1814
- throw promise;
1881
+ }
1882
+ }
1883
+ if (isCurrent()) {
1884
+ clearTimeout(this.$computationTimeoutId$);
1885
+ if (this.$flags$ & 1 /* SignalFlags.INVALID */) {
1886
+ // we became invalid again while running, so we need to re-run the computation to get the new promise
1887
+ this.$computeIfNeeded$();
1815
1888
  }
1816
1889
  else {
1817
- // Return the promise so the scheduler can track it as a running chore
1818
- return promise;
1890
+ this.untrackedLoading = false;
1891
+ this.$scheduleNextPoll$();
1819
1892
  }
1820
1893
  }
1821
- else {
1822
- this.setValue(untrackedValue);
1894
+ }
1895
+ /** Called after SSR/unmount */
1896
+ async $destroy$() {
1897
+ this.$clearNextPoll$();
1898
+ clearTimeout(this.$computationTimeoutId$);
1899
+ if (this.$current$) {
1900
+ await this.$requestCleanups$(this.$current$);
1823
1901
  }
1902
+ await Promise.all(this.$jobs$.map((job) => job.$promise$));
1824
1903
  }
1825
- async $promiseComputation$() {
1826
- if (!this.$promise$) {
1827
- const [cleanup] = cleanupFn(this, (err) => this.$container$?.handleError(err, null));
1828
- this.$promise$ = this.$computeQrl$.getFn()({
1829
- track: trackFn(this, this.$container$),
1830
- cleanup,
1831
- });
1832
- // TODO implement these
1833
- // const arg: {
1834
- // track: Tracker;
1835
- // cleanup: ReturnType<typeof cleanupFn>[0];
1836
- // poll: (ms: number) => void;
1837
- // } = {
1838
- // poll: (ms: number) => {
1839
- // setTimeout(() => {
1840
- // super.invalidate();
1841
- // if (this.$effects$?.size) {
1842
- // this.$computeIfNeeded$();
1843
- // }
1844
- // }, ms);
1845
- // },
1846
- // } as any;
1847
- // Object.defineProperty(arg, 'track', {
1848
- // get() {
1849
- // const fn = trackFn(this, this.$container$);
1850
- // arg.track = fn;
1851
- // return fn;
1852
- // },
1853
- // configurable: true,
1854
- // enumerable: true,
1855
- // writable: true,
1856
- // });
1857
- // Object.defineProperty(arg, 'cleanup', {
1858
- // get() {
1859
- // const [fn] = cleanupFn(this, (err) => this.$container$?.handleError(err, null!));
1860
- // arg.cleanup = fn;
1861
- // return fn;
1862
- // },
1863
- // configurable: true,
1864
- // enumerable: true,
1865
- // writable: true,
1866
- // });
1867
- // this.$promise$ = this.$computeQrl$.getFn()(arg) as ValueOrPromise<T>;
1868
- }
1869
- return this.$promise$;
1870
- }
1871
- setValue(value) {
1872
- this.$flags$ &= -2 /* SignalFlags.INVALID */;
1873
- const didChange = value !== this.$untrackedValue$;
1874
- if (didChange) {
1875
- this.$untrackedValue$ = value;
1876
- this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1904
+ get untrackedValue() {
1905
+ this.$computeIfNeeded$();
1906
+ if (this.$current$?.$promise$) {
1907
+ if (this.$untrackedValue$ === NEEDS_COMPUTATION ||
1908
+ (import.meta.env.TEST ? isServerPlatform() : isServer)) {
1909
+ throw this.$current$?.$promise$;
1910
+ }
1911
+ return this.$untrackedValue$;
1912
+ }
1913
+ if (this.$untrackedError$) {
1914
+ throw this.$untrackedError$;
1915
+ }
1916
+ return this.$untrackedValue$;
1917
+ }
1918
+ $clearNextPoll$() {
1919
+ if (this.$pollTimeoutId$ !== undefined) {
1920
+ clearTimeout(this.$pollTimeoutId$);
1921
+ this.$pollTimeoutId$ = undefined;
1922
+ }
1923
+ }
1924
+ $scheduleNextPoll$() {
1925
+ if ((import.meta.env.TEST ? !isServerPlatform() : isBrowser) && this.$interval$ > 0) {
1926
+ this.$clearNextPoll$();
1927
+ this.$pollTimeoutId$ = setTimeout(this.invalidate.bind(this), this.$interval$);
1928
+ this.$pollTimeoutId$?.unref?.();
1929
+ }
1930
+ }
1931
+ $hasSubscribers$() {
1932
+ return !!(this.$effects$?.size || this.$loadingEffects$?.size || this.$errorEffects$?.size);
1933
+ }
1934
+ async $requestCleanups$(job, reason) {
1935
+ if (job.$cleanupRequested$) {
1936
+ return job.$promise$;
1937
+ }
1938
+ job.$cleanupRequested$ = true;
1939
+ job.$abortController$?.abort(reason);
1940
+ job.$promise$ = Promise.resolve(job.$promise$).then(() => (job.$promise$ = this.$runCleanups$(job)));
1941
+ }
1942
+ /** Clean up and trigger signal compute once complete */
1943
+ async $runCleanups$(job) {
1944
+ const cleanups = job.$cleanups$;
1945
+ if (cleanups?.length) {
1946
+ const onError = (err) => {
1947
+ const handleError = this.$container$?.handleError;
1948
+ if (handleError) {
1949
+ handleError(err, null);
1950
+ }
1951
+ else {
1952
+ console.error('Error in async signal cleanup', err);
1953
+ }
1954
+ };
1955
+ // Keep this sync-ish so sync functions run immediately.
1956
+ await Promise.all(cleanups.map((fn) => {
1957
+ try {
1958
+ const result = fn();
1959
+ if (isPromise(result)) {
1960
+ return result.catch(onError);
1961
+ }
1962
+ }
1963
+ catch (err) {
1964
+ onError(err);
1965
+ }
1966
+ }));
1967
+ cleanups.length = 0;
1968
+ }
1969
+ // Now trigger compute
1970
+ const jobs = this.$jobs$;
1971
+ const idx = jobs.indexOf(job);
1972
+ if (idx !== -1) {
1973
+ jobs.splice(idx, 1);
1877
1974
  }
1878
- return didChange;
1975
+ this.$computeIfNeeded$();
1879
1976
  }
1880
1977
  }
1881
1978
 
@@ -1941,6 +2038,7 @@ class SerializerSignalImpl extends ComputedSignalImpl {
1941
2038
  return;
1942
2039
  }
1943
2040
  throwIfQRLNotResolved(this.$computeQrl$);
2041
+ this.$flags$ &= -2 /* SignalFlags.INVALID */;
1944
2042
  let arg = this.$computeQrl$.resolved;
1945
2043
  if (typeof arg === 'function') {
1946
2044
  arg = arg();
@@ -1951,13 +2049,13 @@ class SerializerSignalImpl extends ComputedSignalImpl {
1951
2049
  const untrackedValue = trackSignal(() => this.$didInitialize$
1952
2050
  ? update?.(currentValue) || currentValue
1953
2051
  : deserialize(currentValue), this, "." /* EffectProperty.VNODE */, this.$container$);
2052
+ this.$didInitialize$ = true;
2053
+ // We allow forcing the update of the signal without changing the value, for example when the deserialized value is the same reference as the old value but its internals have changed. In that case we want to trigger effects that depend on this signal, even though the value is the same.
1954
2054
  const didChange = (this.$didInitialize$ && untrackedValue !== 'undefined') ||
1955
2055
  untrackedValue !== this.$untrackedValue$;
1956
- this.$flags$ &= -2 /* SignalFlags.INVALID */;
1957
- this.$didInitialize$ = true;
1958
2056
  if (didChange) {
1959
- this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1960
2057
  this.$untrackedValue$ = untrackedValue;
2058
+ scheduleEffects(this.$container$, this, this.$effects$);
1961
2059
  }
1962
2060
  }
1963
2061
  }
@@ -1972,7 +2070,7 @@ const createComputedSignal = (qrl, options) => {
1972
2070
  };
1973
2071
  /** @internal */
1974
2072
  const createAsyncSignal = (qrl, options) => {
1975
- return new AsyncSignalImpl(options?.container || null, qrl, getComputedSignalFlags(options?.serializationStrategy || 'never'));
2073
+ return new AsyncSignalImpl(options?.container || null, qrl, getComputedSignalFlags(options?.serializationStrategy || 'always'), options);
1976
2074
  };
1977
2075
  /** @internal */
1978
2076
  const createSerializerSignal = (arg) => {
@@ -1994,23 +2092,18 @@ const createSignal = createSignal$1;
1994
2092
  * The QRL must be a function which returns the value of the signal. The function must not have side
1995
2093
  * effects, and it must be synchronous.
1996
2094
  *
1997
- * If you need the function to be async, use `useAsync$` instead.
2095
+ * If you need the function to be async, use `createAsync$` instead (don't forget to use `track()`).
1998
2096
  *
1999
2097
  * @public
2000
2098
  */
2001
2099
  const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedSignal);
2002
2100
  /**
2003
- * Create an async computed signal which is calculated from the given QRL. A computed signal is a
2004
- * signal which is calculated from other signals or async operation. When the signals change, the
2005
- * computed signal is recalculated.
2006
- *
2007
- * The QRL must be a function which returns the value of the signal. The function must not have side
2008
- * effects, and it can be async.
2101
+ * Create a signal holding a `.value` which is calculated from the given async function (QRL). The
2102
+ * standalone version of `useAsync$`.
2009
2103
  *
2010
2104
  * @public
2011
2105
  */
2012
- const createAsync$ =
2013
- /*#__PURE__*/ implicit$FirstArg(createAsyncSignal);
2106
+ const createAsync$ = /*#__PURE__*/ implicit$FirstArg(createAsyncSignal);
2014
2107
  /**
2015
2108
  * Create a signal that holds a custom serializable value. See {@link useSerializer$} for more
2016
2109
  * details.
@@ -2135,17 +2228,6 @@ class WrappedSignalImpl extends SignalImpl {
2135
2228
  scheduleEffects(this.$container$, this, this.$effects$);
2136
2229
  }
2137
2230
  }
2138
- /**
2139
- * Use this to force running subscribers, for example when the calculated value has mutated but
2140
- * remained the same object.
2141
- */
2142
- force() {
2143
- this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
2144
- if (this.$container$ && this.$hostElement$) {
2145
- this.$container$.setHostProp(this.$hostElement$, HOST_SIGNAL, this);
2146
- markVNodeDirty(this.$container$, this.$hostElement$, 16 /* ChoreBits.COMPUTE */);
2147
- }
2148
- }
2149
2231
  get untrackedValue() {
2150
2232
  this.$computeIfNeeded$();
2151
2233
  isDev && assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
@@ -2243,6 +2325,11 @@ function clearAsyncSignal(producer, effect) {
2243
2325
  if (pendingEffects && pendingEffects.has(effect)) {
2244
2326
  pendingEffects.delete(effect);
2245
2327
  }
2328
+ const errorEffects = producer.$errorEffects$;
2329
+ if (errorEffects && errorEffects.has(effect)) {
2330
+ errorEffects.delete(effect);
2331
+ }
2332
+ producer.$scheduleEagerCleanup$();
2246
2333
  }
2247
2334
  function clearStoreOrProps(producer, effect) {
2248
2335
  const effects = producer?.$effects$;
@@ -2298,6 +2385,25 @@ function _chk(_, element) {
2298
2385
  const signal = _captures[0];
2299
2386
  signal.value = element.checked;
2300
2387
  }
2388
+ /**
2389
+ * Resumes selected state (e.g. polling AsyncSignals) by deserializing captures. Used for
2390
+ * document:onQIdle to resume async signals with active polling.
2391
+ *
2392
+ * @internal
2393
+ */
2394
+ function _res(_, element) {
2395
+ maybeScopeFromQL(this, element);
2396
+ // Captures are deserialized, signals are now resumed
2397
+ }
2398
+
2399
+ const isObjectEmpty = (obj) => {
2400
+ for (const key in obj) {
2401
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
2402
+ return false;
2403
+ }
2404
+ }
2405
+ return true;
2406
+ };
2301
2407
 
2302
2408
  const _hasOwnProperty$2 = Object.prototype.hasOwnProperty;
2303
2409
  // TODO store props as the arrays the vnodes also use?
@@ -2315,8 +2421,8 @@ class JSXNodeImpl {
2315
2421
  this.children = children;
2316
2422
  this.toSort = !!toSort;
2317
2423
  this.key = key === null || key === undefined ? null : typeof key === 'string' ? key : '' + key;
2318
- this.varProps = !varProps || isEmpty(varProps) ? EMPTY_OBJ : varProps;
2319
- this.constProps = !constProps || isEmpty(constProps) ? null : constProps;
2424
+ this.varProps = !varProps || isObjectEmpty(varProps) ? EMPTY_OBJ : varProps;
2425
+ this.constProps = !constProps || isObjectEmpty(constProps) ? null : constProps;
2320
2426
  if (qDev && dev) {
2321
2427
  this.dev = {
2322
2428
  ...dev,
@@ -2365,9 +2471,6 @@ const isJSXNode = (n) => {
2365
2471
  return n instanceof JSXNodeImpl;
2366
2472
  }
2367
2473
  };
2368
- const isEmpty = (obj) => {
2369
- return Object.keys(obj).length === 0;
2370
- };
2371
2474
 
2372
2475
  const BIND_VALUE = 'bind:value';
2373
2476
  const BIND_CHECKED = 'bind:checked';
@@ -2811,7 +2914,7 @@ function addUseOnEvent(jsxElement, key, value) {
2811
2914
  props[key] = undefined;
2812
2915
  }
2813
2916
  }
2814
- const getValue$1 = (o) => o.value;
2917
+ const getValue = (o) => o.value;
2815
2918
  /**
2816
2919
  * Finds the first element node in the JSX output.
2817
2920
  *
@@ -2835,7 +2938,7 @@ function findFirstElementNode(jsx) {
2835
2938
  return maybeThen(jsx, (jsx) => findFirstElementNode(jsx));
2836
2939
  }
2837
2940
  else if (isSignal(jsx)) {
2838
- return findFirstElementNode(untrack(getValue$1, jsx));
2941
+ return findFirstElementNode(untrack(getValue, jsx));
2839
2942
  }
2840
2943
  }
2841
2944
  return null;
@@ -3263,6 +3366,18 @@ const createSetTextOperation = (target, text) => new SetTextOperation(target, te
3263
3366
  const createInsertOrMoveOperation = (target, parent, beforeTarget) => new InsertOrMoveOperation(target, parent, beforeTarget);
3264
3367
  const createSetAttributeOperation = (target, attrName, attrValue, scopedStyleIdPrefix = null, isSvg = false) => new SetAttributeOperation(target, attrName, attrValue, scopedStyleIdPrefix, isSvg);
3265
3368
 
3369
+ const cleanupDestroyable = (destroyable) => {
3370
+ if (destroyable.$destroy$) {
3371
+ try {
3372
+ destroyable.$destroy$();
3373
+ }
3374
+ catch (err) {
3375
+ logError(err);
3376
+ }
3377
+ destroyable.$destroy$ = null;
3378
+ }
3379
+ };
3380
+
3266
3381
  /**
3267
3382
  * This safely calls an event handler, handling errors and retrying on thrown Promises, and
3268
3383
  * providing extra parameters defined on the elements as arguments (used for loop optimization)
@@ -3747,25 +3862,24 @@ function expectSlot(diffContext) {
3747
3862
  )
3748
3863
  : null;
3749
3864
  if (vProjectedNode == null) {
3750
- // Nothing to project, so render content of the slot.
3751
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
3865
+ diffContext.vNewNode = vnode_newVirtual();
3752
3866
  vnode_setProp(diffContext.vNewNode, QSlot, slotNameKey);
3753
3867
  vHost && vnode_setProp(vHost, slotNameKey, diffContext.vNewNode);
3754
3868
  isDev &&
3755
- vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, "P" /* VirtualType.Projection */);
3756
- isDev && vnode_setProp(diffContext.vNewNode, 'q:code', 'expectSlot' + count++);
3869
+ vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, "P" /* VirtualType.Projection */); // Nothing to project, so render content of the slot.
3870
+ vnode_insertBefore(diffContext.journal, diffContext.vParent, diffContext.vNewNode, diffContext.vCurrent && getInsertBefore(diffContext));
3757
3871
  return false;
3758
3872
  }
3759
3873
  else if (vProjectedNode === diffContext.vCurrent) ;
3760
3874
  else {
3761
3875
  // move from q:template to the target node
3762
3876
  const oldParent = vProjectedNode.parent;
3763
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vProjectedNode), diffContext.vCurrent && getInsertBefore(diffContext));
3877
+ diffContext.vNewNode = vProjectedNode;
3764
3878
  vnode_setProp(diffContext.vNewNode, QSlot, slotNameKey);
3765
3879
  vHost && vnode_setProp(vHost, slotNameKey, diffContext.vNewNode);
3766
3880
  isDev &&
3767
3881
  vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, "P" /* VirtualType.Projection */);
3768
- isDev && vnode_setProp(diffContext.vNewNode, 'q:code', 'expectSlot' + count++);
3882
+ vnode_insertBefore(diffContext.journal, diffContext.vParent, diffContext.vNewNode, diffContext.vCurrent && getInsertBefore(diffContext));
3769
3883
  // If we moved from a q:template and it's now empty, remove it
3770
3884
  if (oldParent &&
3771
3885
  vnode_isElementVNode(oldParent) &&
@@ -3942,20 +4056,34 @@ function createNewElement(diffContext, jsx, elementName, currentFile) {
3942
4056
  element.setAttribute('class', diffContext.scopedStyleIdPrefix);
3943
4057
  }
3944
4058
  }
3945
- vnode_insertBefore(diffContext.journal, diffContext.vParent, diffContext.vNewNode, diffContext.vCurrent);
4059
+ vnode_insertElementBefore(diffContext.journal, diffContext.vParent, diffContext.vNewNode, diffContext.vCurrent);
3946
4060
  }
3947
4061
  function registerEventHandlers(key, value, element, vnode, diffContext) {
3948
4062
  const scopedKebabName = key.slice(2);
3949
- if (!Array.isArray(value)) {
3950
- value = [value];
3951
- }
3952
- const handlers = [];
3953
- for (const handler of value.flat(2)) {
3954
- if (handler) {
3955
- handlers.push(runEventHandlerQRL.bind(null, handler));
4063
+ if (Array.isArray(value)) {
4064
+ const arr = value;
4065
+ const handlers = [];
4066
+ for (let i = 0; i < arr.length; i++) {
4067
+ const item = arr[i];
4068
+ if (Array.isArray(item)) {
4069
+ for (let j = 0; j < item.length; j++) {
4070
+ const handler = item[j];
4071
+ if (handler) {
4072
+ handlers.push(runEventHandlerQRL.bind(null, handler));
4073
+ }
4074
+ }
4075
+ }
4076
+ else if (item) {
4077
+ handlers.push(runEventHandlerQRL.bind(null, item));
4078
+ }
3956
4079
  }
4080
+ (element._qDispatch ||= {})[scopedKebabName] = handlers;
4081
+ }
4082
+ else if (value) {
4083
+ (element._qDispatch ||= {})[scopedKebabName] = [
4084
+ runEventHandlerQRL.bind(null, value),
4085
+ ];
3957
4086
  }
3958
- (element._qDispatch ||= {})[scopedKebabName] = handlers;
3959
4087
  // window and document events need attrs so qwik loader can find them
3960
4088
  // TODO only do these when not already present
3961
4089
  if (key.charAt(2) !== 'e') {
@@ -4274,13 +4402,13 @@ function expectVirtual(diffContext, type, jsxKey) {
4274
4402
  }
4275
4403
  // For fragments without a key, always create a new virtual node (ensures rerender semantics)
4276
4404
  if (jsxKey === null || diffContext.isCreationMode) {
4277
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4405
+ vnode_insertVirtualBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4278
4406
  diffContext.vNewNode.key = jsxKey;
4279
4407
  isDev && vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, type);
4280
4408
  return;
4281
4409
  }
4282
4410
  if (moveOrCreateKeyedNode(diffContext, null, jsxKey, getSideBufferKey(null, jsxKey), diffContext.vParent, true)) {
4283
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4411
+ vnode_insertVirtualBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4284
4412
  diffContext.vNewNode.key = jsxKey;
4285
4413
  isDev && vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, type);
4286
4414
  }
@@ -4374,7 +4502,7 @@ function insertNewComponent(diffContext, host, componentQRL, jsxProps) {
4374
4502
  if (host) {
4375
4503
  clearAllEffects(diffContext.container, host);
4376
4504
  }
4377
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4505
+ vnode_insertVirtualBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4378
4506
  const jsxNode = diffContext.jsxValue;
4379
4507
  isDev && vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, "C" /* VirtualType.Component */);
4380
4508
  vnode_setProp(diffContext.vNewNode, OnRenderProp, componentQRL);
@@ -4382,7 +4510,7 @@ function insertNewComponent(diffContext, host, componentQRL, jsxProps) {
4382
4510
  diffContext.vNewNode.key = jsxNode.key;
4383
4511
  }
4384
4512
  function insertNewInlineComponent(diffContext) {
4385
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4513
+ vnode_insertVirtualBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newVirtual()), diffContext.vCurrent && getInsertBefore(diffContext));
4386
4514
  const jsxNode = diffContext.jsxValue;
4387
4515
  isDev &&
4388
4516
  vnode_setProp(diffContext.vNewNode, DEBUG_TYPE, "I" /* VirtualType.InlineComponent */);
@@ -4402,7 +4530,7 @@ function expectText(diffContext, text) {
4402
4530
  return;
4403
4531
  }
4404
4532
  }
4405
- vnode_insertBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newText((import.meta.env.TEST ? diffContext.container.document : document).createTextNode(text), text)), diffContext.vCurrent);
4533
+ vnode_insertElementBefore(diffContext.journal, diffContext.vParent, (diffContext.vNewNode = vnode_newText((import.meta.env.TEST ? diffContext.container.document : document).createTextNode(text), text)), diffContext.vCurrent);
4406
4534
  }
4407
4535
  /**
4408
4536
  * Retrieve the key from the VNode.
@@ -4531,7 +4659,7 @@ function isPropsEmpty(props) {
4531
4659
  if (!props) {
4532
4660
  return true;
4533
4661
  }
4534
- return Object.keys(props).length === 0;
4662
+ return isObjectEmpty(props);
4535
4663
  }
4536
4664
  /**
4537
4665
  * If vnode is removed, it is necessary to release all subscriptions associated with it.
@@ -4570,7 +4698,7 @@ function cleanup(container, journal, vNode, cursorRoot = null) {
4570
4698
  if (isObject(obj)) {
4571
4699
  const objIsTask = isTask(obj);
4572
4700
  if (objIsTask && obj.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
4573
- obj.$flags$ |= 32 /* TaskFlags.NEEDS_CLEANUP */;
4701
+ obj.$flags$ |= 16 /* TaskFlags.NEEDS_CLEANUP */;
4574
4702
  markVNodeDirty(container, vCursor, 64 /* ChoreBits.CLEANUP */, cursorRoot);
4575
4703
  // don't call cleanupDestroyable yet, do it by the scheduler
4576
4704
  continue;
@@ -4724,281 +4852,6 @@ function containsWrappedSignal(data, signal) {
4724
4852
  }
4725
4853
  return false;
4726
4854
  }
4727
- let count = 0;
4728
-
4729
- /**
4730
- * @internal
4731
- * The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
4732
- */
4733
- const useSequentialScope = () => {
4734
- const iCtx = useInvokeContext();
4735
- const hostElement = iCtx.$hostElement$;
4736
- const host = hostElement;
4737
- let seq = iCtx.$container$.getHostProp(host, ELEMENT_SEQ);
4738
- if (seq === null) {
4739
- seq = [];
4740
- iCtx.$container$.setHostProp(host, ELEMENT_SEQ, seq);
4741
- }
4742
- let seqIdx = iCtx.$container$.getHostProp(host, ELEMENT_SEQ_IDX);
4743
- if (seqIdx === null) {
4744
- seqIdx = 0;
4745
- }
4746
- iCtx.$container$.setHostProp(host, ELEMENT_SEQ_IDX, seqIdx + 1);
4747
- while (seq.length <= seqIdx) {
4748
- seq.push(undefined);
4749
- }
4750
- const set = (value) => {
4751
- if (qDev && qSerialize) {
4752
- verifySerializable(value);
4753
- }
4754
- return (seq[seqIdx] = value);
4755
- };
4756
- return {
4757
- val: seq[seqIdx],
4758
- set,
4759
- i: seqIdx,
4760
- iCtx,
4761
- };
4762
- };
4763
-
4764
- /** @internal */
4765
- const useResourceQrl = (qrl, opts) => {
4766
- const { val, set, i, iCtx } = useSequentialScope();
4767
- if (val != null) {
4768
- return val.$state$;
4769
- }
4770
- assertQrl(qrl);
4771
- const container = iCtx.$container$;
4772
- const resource = createResourceReturn(container, opts);
4773
- const el = iCtx.$hostElement$;
4774
- const task = new Task(8 /* TaskFlags.DIRTY */ | 4 /* TaskFlags.RESOURCE */, i, el, qrl, resource, null);
4775
- set(task);
4776
- runResource(task, container, el);
4777
- return resource;
4778
- };
4779
- // <docs markdown="../readme.md#useResource">
4780
- // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
4781
- // (edit ../readme.md#useResource instead and run `pnpm docs.sync`)
4782
- /**
4783
- * This method works like an async memoized function that runs whenever some tracked value changes
4784
- * and returns some data.
4785
- *
4786
- * `useResource` however returns immediate a `ResourceReturn` object that contains the data and a
4787
- * state that indicates if the data is available or not.
4788
- *
4789
- * The status can be one of the following:
4790
- *
4791
- * - `pending` - the data is not yet available.
4792
- * - `resolved` - the data is available.
4793
- * - `rejected` - the data is not available due to an error or timeout.
4794
- *
4795
- * Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
4796
- * re-throw it (or a new Error), the resource status will never be `rejected`.
4797
- *
4798
- * ### Example
4799
- *
4800
- * Example showing how `useResource` to perform a fetch to request the weather, whenever the input
4801
- * city name changes.
4802
- *
4803
- * ```tsx
4804
- * const Cmp = component$(() => {
4805
- * const cityS = useSignal('');
4806
- *
4807
- * const weatherResource = useResource$(async ({ track, cleanup }) => {
4808
- * const cityName = track(cityS);
4809
- * const abortController = new AbortController();
4810
- * cleanup(() => abortController.abort('cleanup'));
4811
- * const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
4812
- * signal: abortController.signal,
4813
- * });
4814
- * const data = await res.json();
4815
- * return data as { temp: number };
4816
- * });
4817
- *
4818
- * return (
4819
- * <div>
4820
- * <input name="city" bind:value={cityS} />
4821
- * <Resource
4822
- * value={weatherResource}
4823
- * onResolved={(weather) => {
4824
- * return <div>Temperature: {weather.temp}</div>;
4825
- * }}
4826
- * />
4827
- * </div>
4828
- * );
4829
- * });
4830
- * ```
4831
- *
4832
- * @public
4833
- * @see Resource
4834
- * @see ResourceReturn
4835
- */
4836
- // </docs>
4837
- const Resource = (props) => {
4838
- // Resource path
4839
- return _jsxSorted(Fragment, null, null, getResourceValueAsPromise(props), 0, null);
4840
- };
4841
- const getResolved = (resource) => resource._resolved;
4842
- const getValue = (resource) => resource.value;
4843
- const getLoading = (resource) => resource.loading;
4844
- function getResourceValueAsPromise(props) {
4845
- const resource = props.value;
4846
- if (isResourceReturn(resource)) {
4847
- // create a subscription for the resource._state changes
4848
- const state = resource._state;
4849
- const isBrowser = !isServerPlatform();
4850
- if (isBrowser) {
4851
- if (state === 'pending' && props.onPending) {
4852
- resource.value.catch(() => { });
4853
- return Promise.resolve().then(useBindInvokeContext(props.onPending));
4854
- }
4855
- else if (state === 'rejected' && props.onRejected) {
4856
- return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
4857
- }
4858
- else {
4859
- const resolvedValue = untrack(getResolved, resource);
4860
- if (resolvedValue !== undefined) {
4861
- // resolved, pending without onPending prop or rejected without onRejected prop
4862
- return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
4863
- }
4864
- }
4865
- }
4866
- return untrack(getValue, resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
4867
- }
4868
- else if (isPromise(resource)) {
4869
- return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
4870
- }
4871
- else if (isSignal(resource)) {
4872
- const value = retryOnPromise(() => resource.value);
4873
- const promise = isPromise(value) ? value : Promise.resolve(value);
4874
- return promise.then(useBindInvokeContext(props.onResolved));
4875
- }
4876
- else {
4877
- return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved));
4878
- }
4879
- }
4880
- const _createResourceReturn = (opts) => {
4881
- const resource = {
4882
- __brand: 'resource',
4883
- value: undefined,
4884
- loading: !isServerPlatform(),
4885
- _resolved: undefined,
4886
- _error: undefined,
4887
- _state: 'pending',
4888
- _timeout: opts?.timeout ?? -1,
4889
- _cache: 0,
4890
- _generation: 0,
4891
- };
4892
- return resource;
4893
- };
4894
- const createResourceReturn = (container, opts, initialPromise) => {
4895
- const result = _createResourceReturn(opts);
4896
- result.value = initialPromise;
4897
- return createStore(container, result, 1 /* StoreFlags.RECURSIVE */);
4898
- };
4899
- const isResourceReturn = (obj) => {
4900
- return isObject(obj) && (getStoreTarget(obj) || obj).__brand === 'resource';
4901
- };
4902
- const runResource = (task, container, host) => {
4903
- task.$flags$ &= -9 /* TaskFlags.DIRTY */;
4904
- cleanupDestroyable(task);
4905
- const iCtx = newInvokeContext(container.$locale$, host, ResourceEvent);
4906
- iCtx.$container$ = container;
4907
- const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
4908
- const resource = task.$state$;
4909
- isDev &&
4910
- assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
4911
- const track = trackFn(task, container);
4912
- const [cleanup, cleanups] = cleanupFn(task, (reason) => container.handleError(reason, host));
4913
- const resourceTarget = unwrapStore(resource);
4914
- const opts = {
4915
- track,
4916
- cleanup,
4917
- cache(policy) {
4918
- let milliseconds = 0;
4919
- if (policy === 'immutable') {
4920
- milliseconds = Infinity;
4921
- }
4922
- else {
4923
- milliseconds = policy;
4924
- }
4925
- resource._cache = milliseconds;
4926
- },
4927
- previous: resourceTarget._resolved,
4928
- };
4929
- let resolve;
4930
- let reject;
4931
- let done = false;
4932
- // Increment generation to track this execution
4933
- const currentGeneration = ++resourceTarget._generation;
4934
- const setState = (resolved, value) => {
4935
- // Ignore results from outdated executions
4936
- if (done || resourceTarget._generation !== currentGeneration) {
4937
- return false;
4938
- }
4939
- done = true;
4940
- if (resolved) {
4941
- resourceTarget.loading = false;
4942
- resourceTarget._state = 'resolved';
4943
- resourceTarget._resolved = value;
4944
- resourceTarget._error = undefined;
4945
- resolve(value);
4946
- }
4947
- else {
4948
- resourceTarget.loading = false;
4949
- resourceTarget._state = 'rejected';
4950
- resourceTarget._error = value;
4951
- reject(value);
4952
- }
4953
- if (!isServerPlatform()) {
4954
- forceStoreEffects(resource, '_state');
4955
- }
4956
- return true;
4957
- };
4958
- /**
4959
- * Add cleanup to resolve the resource if we are trying to run the same resource again while the
4960
- * previous one is not resolved yet. The next `runResource` run will call this cleanup
4961
- */
4962
- cleanups.push(() => {
4963
- if (untrack(getLoading, resource) === true) {
4964
- const value = untrack(getResolved, resource);
4965
- setState(true, value);
4966
- }
4967
- });
4968
- // Execute mutation inside empty invocation
4969
- // TODO: is it right? why we need to invoke inside context and trigger effects?
4970
- invoke(iCtx, () => {
4971
- // console.log('RESOURCE.pending: ');
4972
- resource._state = 'pending';
4973
- resource.loading = !isServerPlatform();
4974
- resource.value = new Promise((r, re) => {
4975
- resolve = r;
4976
- reject = re;
4977
- });
4978
- });
4979
- const promise = safeCall(() => taskFn(opts), (value) => {
4980
- setState(true, value);
4981
- }, (err) => {
4982
- if (isPromise(err)) {
4983
- return err.then(() => runResource(task, container, host));
4984
- }
4985
- else {
4986
- setState(false, err);
4987
- }
4988
- });
4989
- const timeout = resourceTarget._timeout;
4990
- if (timeout > 0) {
4991
- return Promise.race([
4992
- promise,
4993
- delay(timeout).then(() => {
4994
- if (setState(false, new Error('timeout'))) {
4995
- cleanupDestroyable(task);
4996
- }
4997
- }),
4998
- ]);
4999
- }
5000
- return promise;
5001
- };
5002
4855
 
5003
4856
  /**
5004
4857
  * Executes tasks for a vNode if the TASKS dirty bit is set. Tasks are stored in the ELEMENT_SEQ
@@ -5030,21 +4883,16 @@ function executeTasks(vNode, container, cursorData) {
5030
4883
  if (item instanceof Task) {
5031
4884
  const task = item;
5032
4885
  // Skip if task is not dirty
5033
- if (!(task.$flags$ & 8 /* TaskFlags.DIRTY */)) {
4886
+ if (!(task.$flags$ & 4 /* TaskFlags.DIRTY */)) {
5034
4887
  continue;
5035
4888
  }
5036
- // Check if it's a resource
5037
- if (task.$flags$ & 4 /* TaskFlags.RESOURCE */) {
5038
- // Resources: just run, don't save promise anywhere
5039
- runResource(task, container, vNode);
5040
- }
5041
- else if (task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
4889
+ if (task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
5042
4890
  // VisibleTasks: store for execution after flush (don't execute now)
5043
4891
  (cursorData.afterFlushTasks ||= []).push(task);
5044
4892
  }
5045
4893
  else {
5046
4894
  // Regular tasks: chain promises only between each other
5047
- const isRenderBlocking = !!(task.$flags$ & 16 /* TaskFlags.RENDER_BLOCKING */);
4895
+ const isRenderBlocking = !!(task.$flags$ & 8 /* TaskFlags.RENDER_BLOCKING */);
5048
4896
  const result = runTask(task, container, vNode);
5049
4897
  if (isPromise(result)) {
5050
4898
  if (isRenderBlocking) {
@@ -5204,8 +5052,8 @@ function executeCleanup(vNode, container) {
5204
5052
  }
5205
5053
  for (const item of elementSeq) {
5206
5054
  if (item instanceof Task) {
5207
- if (item.$flags$ & 32 /* TaskFlags.NEEDS_CLEANUP */) {
5208
- item.$flags$ &= -33 /* TaskFlags.NEEDS_CLEANUP */;
5055
+ if (item.$flags$ & 16 /* TaskFlags.NEEDS_CLEANUP */) {
5056
+ item.$flags$ &= -17 /* TaskFlags.NEEDS_CLEANUP */;
5209
5057
  const task = item;
5210
5058
  cleanupDestroyable(task);
5211
5059
  }
@@ -5273,8 +5121,8 @@ function _flushJournal(journal) {
5273
5121
  else {
5274
5122
  const doc = batchParent.ownerDocument || batchParent;
5275
5123
  const fragment = doc.createDocumentFragment();
5276
- for (const node of batchNodes) {
5277
- fragment.appendChild(node);
5124
+ for (let i = 0; i < batchNodes.length; i++) {
5125
+ fragment.appendChild(batchNodes[i]);
5278
5126
  }
5279
5127
  fastInsertBefore(batchParent, fragment, batchBefore);
5280
5128
  }
@@ -5284,7 +5132,8 @@ function _flushJournal(journal) {
5284
5132
  batchSet.clear();
5285
5133
  }
5286
5134
  };
5287
- for (const operation of journal) {
5135
+ for (let i = 0; i < journal.length; i++) {
5136
+ const operation = journal[i];
5288
5137
  if (operation instanceof InsertOrMoveOperation) {
5289
5138
  if (batchParent === operation.parent && batchBefore === operation.beforeTarget) {
5290
5139
  if (!batchNodes) {
@@ -5642,12 +5491,7 @@ function finishWalk(container, cursor, cursorData, isServer) {
5642
5491
  }
5643
5492
  }
5644
5493
  function resolveCursor(container) {
5645
- // TODO streaming as a cursor? otherwise we need to wait separately for it
5646
- // or just ignore and resolve manually
5647
- if (container.$cursorCount$ === 0 && container.$pausedCursorCount$ === 0) {
5648
- container.$resolveRenderPromise$();
5649
- container.$renderPromise$ = null;
5650
- }
5494
+ container.$checkPendingCount$();
5651
5495
  }
5652
5496
  /**
5653
5497
  * Partitions dirtyChildren array so non-projections come first, projections last. Uses in-place
@@ -5820,17 +5664,10 @@ function executeTasksChore(container, ssrNode) {
5820
5664
  if (item instanceof Task) {
5821
5665
  const task = item;
5822
5666
  // Skip if task is not dirty
5823
- if (!(task.$flags$ & 8 /* TaskFlags.DIRTY */)) {
5667
+ if (!(task.$flags$ & 4 /* TaskFlags.DIRTY */)) {
5824
5668
  continue;
5825
5669
  }
5826
- let result;
5827
- // Check if it's a resource
5828
- if (task.$flags$ & 4 /* TaskFlags.RESOURCE */) {
5829
- result = runResource(task, container, ssrNode);
5830
- }
5831
- else {
5832
- result = runTask(task, container, ssrNode);
5833
- }
5670
+ const result = runTask(task, container, ssrNode);
5834
5671
  promise = promise ? promise.then(() => result) : result;
5835
5672
  }
5836
5673
  }
@@ -6334,6 +6171,24 @@ function registerQrlHandlers(attr, key, container, element) {
6334
6171
  });
6335
6172
  (element._qDispatch ||= {})[scopedKebabName] = handlers;
6336
6173
  }
6174
+ /** Walks the direct children of a parent node and calls the callback for each child. */
6175
+ function vnode_walkDirectChildren(journal, vParent, callback) {
6176
+ let vNode = vnode_getFirstChild(vParent);
6177
+ while (vNode) {
6178
+ if (vnode_isTextVNode(vNode)) {
6179
+ vnode_ensureTextInflated(journal, vNode);
6180
+ callback(vNode, vParent);
6181
+ }
6182
+ else if (vnode_isElementVNode(vNode)) {
6183
+ callback(vNode, vParent);
6184
+ }
6185
+ else {
6186
+ // for virtual nodes, we need to walk their children
6187
+ vnode_walkDirectChildren(journal, vNode, callback);
6188
+ }
6189
+ vNode = vNode.nextSibling;
6190
+ }
6191
+ }
6337
6192
  /** Walks the VNode tree and materialize it using `vnode_getFirstChild`. */
6338
6193
  function vnode_walkVNode(vNode, callback) {
6339
6194
  let vCursor = vNode;
@@ -6383,52 +6238,15 @@ function vnode_walkVNode(vNode, callback) {
6383
6238
  }
6384
6239
  } while (true);
6385
6240
  }
6386
- function vnode_getDOMChildNodes(journal, root, isVNode = false, childNodes = []) {
6387
- if (vnode_isElementOrTextVNode(root)) {
6388
- if (vnode_isTextVNode(root)) {
6389
- /**
6390
- * If we are collecting text nodes, we need to ensure that they are inflated. If not inflated
6391
- * we would return a single text node which represents many actual text nodes, or removing a
6392
- * single text node would remove many text nodes.
6393
- */
6394
- vnode_ensureTextInflated(journal, root);
6395
- }
6396
- childNodes.push(isVNode ? root : vnode_getNode(root));
6397
- return childNodes;
6398
- }
6399
- let vNode = vnode_getFirstChild(root);
6400
- while (vNode) {
6401
- if (vnode_isElementVNode(vNode)) {
6402
- childNodes.push(isVNode ? vNode : vnode_getNode(vNode));
6403
- }
6404
- else if (vnode_isTextVNode(vNode)) {
6405
- /**
6406
- * If we are collecting text nodes, we need to ensure that they are inflated. If not inflated
6407
- * we would return a single text node which represents many actual text nodes, or removing a
6408
- * single text node would remove many text nodes.
6409
- */
6410
- vnode_ensureTextInflated(journal, vNode);
6411
- childNodes.push(isVNode ? vNode : vnode_getNode(vNode));
6412
- }
6413
- else {
6414
- isVNode
6415
- ? vnode_getDOMChildNodes(journal, vNode, true, childNodes)
6416
- : vnode_getDOMChildNodes(journal, vNode, false, childNodes);
6417
- }
6418
- vNode = vNode.nextSibling;
6419
- }
6420
- return childNodes;
6421
- }
6422
6241
  function vnode_getDOMContainer(vNode) {
6423
6242
  let cursor = vNode;
6424
6243
  while (cursor) {
6425
6244
  if (vnode_isElementVNode(cursor)) {
6426
- try {
6427
- return getDomContainer(cursor.node);
6428
- }
6429
- catch {
6245
+ const qContainerElement = _getQContainerElement(cursor.node);
6246
+ if (!qContainerElement) {
6430
6247
  return null;
6431
6248
  }
6249
+ return getDomContainerFromQContainerElement(qContainerElement);
6432
6250
  }
6433
6251
  cursor = cursor.parent;
6434
6252
  }
@@ -6696,27 +6514,71 @@ const indexOfAlphanumeric = (id, length) => {
6696
6514
  idx++;
6697
6515
  }
6698
6516
  else {
6699
- return idx;
6517
+ return idx;
6518
+ }
6519
+ }
6520
+ return length;
6521
+ };
6522
+ const vnode_createErrorDiv = (journal, document, host, err) => {
6523
+ const errorDiv = document.createElement('errored-host');
6524
+ if (err && err instanceof Error) {
6525
+ errorDiv.props = { error: err };
6526
+ }
6527
+ errorDiv.setAttribute('q:key', '_error_');
6528
+ const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
6529
+ if (vnode_isElementOrTextVNode(host)) {
6530
+ vnode_insertBefore(journal, vErrorDiv, host, null);
6531
+ }
6532
+ else {
6533
+ // first collect all the children, we can't move them while walking the children
6534
+ const children = [];
6535
+ vnode_walkDirectChildren(journal, host, (vNode) => {
6536
+ children.push(vNode);
6537
+ });
6538
+ for (let i = 0; i < children.length; i++) {
6539
+ vnode_insertBefore(journal, vErrorDiv, children[i], null);
6540
+ }
6541
+ }
6542
+ return vErrorDiv;
6543
+ };
6544
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
6545
+ const vnode_insertElementBefore = (journal, parent, newChild, insertBefore) => {
6546
+ ensureElementOrVirtualVNode(parent);
6547
+ const parentIsElement = vnode_isElementVNode(parent);
6548
+ if (parentIsElement) {
6549
+ ensureMaterialized(parent);
6550
+ }
6551
+ const newChildCurrentParent = newChild.parent;
6552
+ if (newChild === insertBefore) {
6553
+ // invalid insertBefore. We can't insert before self reference
6554
+ // prevent infinity loop and putting self reference to next sibling
6555
+ if (newChildCurrentParent) {
6556
+ // early return, as the newChild is already in the tree and we are already in the correct position
6557
+ return;
6558
+ }
6559
+ else {
6560
+ // if the newChild is not in the tree, than we insert it at the end of the list
6561
+ insertBefore = null;
6700
6562
  }
6701
6563
  }
6702
- return length;
6703
- };
6704
- const vnode_createErrorDiv = (journal, document, host, err) => {
6705
- const errorDiv = document.createElement('errored-host');
6706
- if (err && err instanceof Error) {
6707
- errorDiv.props = { error: err };
6564
+ vnode_unlinkFromOldParent(journal, newChildCurrentParent, parent, newChild);
6565
+ const childNode = newChild.node;
6566
+ const parentIsDeleted = parent.flags & 32 /* VNodeFlags.Deleted */;
6567
+ const parentNode = parentIsElement ? parent.node : vnode_getDomParent(parent, false);
6568
+ if (parentNode && !parentIsDeleted) {
6569
+ addVNodeOperation(journal, createInsertOrMoveOperation(childNode, parentNode, vnode_findInsertBefore(journal, parent, insertBefore)?.node ?? null));
6570
+ }
6571
+ // link newChild into the previous/next list
6572
+ vnode_connectSiblings(parent, newChild, insertBefore);
6573
+ if (parentIsDeleted) {
6574
+ // if the parent is deleted, then the new child is also deleted
6575
+ newChild.flags |= 32 /* VNodeFlags.Deleted */;
6708
6576
  }
6709
- errorDiv.setAttribute('q:key', '_error_');
6710
- const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
6711
- vnode_getDOMChildNodes(journal, host, true).forEach((child) => {
6712
- vnode_insertBefore(journal, vErrorDiv, child, null);
6713
- });
6714
- return vErrorDiv;
6715
6577
  };
6716
- //////////////////////////////////////////////////////////////////////////////////////////////////////
6717
- const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
6578
+ const vnode_insertVirtualBefore = (journal, parent, newChild, insertBefore) => {
6718
6579
  ensureElementOrVirtualVNode(parent);
6719
- if (vnode_isElementVNode(parent)) {
6580
+ const parentIsElement = vnode_isElementVNode(parent);
6581
+ if (parentIsElement) {
6720
6582
  ensureMaterialized(parent);
6721
6583
  }
6722
6584
  const newChildCurrentParent = newChild.parent;
@@ -6732,32 +6594,106 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
6732
6594
  insertBefore = null;
6733
6595
  }
6734
6596
  }
6735
- /**
6736
- * Find the parent node and the dom children with the correct namespaces before we unlink the
6737
- * previous node. If we don't do this, we will end up with situations where we inflate text nodes
6738
- * from shared text node not correctly.
6739
- *
6740
- * Example:
6741
- *
6742
- * ```
6743
- * <Component>
6744
- * <Projection>a</Projection>
6745
- * <Projection>b</Projection>
6746
- * </Component>
6747
- * ```
6748
- *
6749
- * Projection nodes are virtual nodes, so they don't have a dom parent. They will be written to
6750
- * the q:template element if not visible at the start. Inside the q:template element, the
6751
- * projection nodes will be streamed as single text node "ab". We need to split it, but if we
6752
- * unlink the previous or next sibling, we don't know that after "a" node is "b". So we need to
6753
- * find children first (and inflate them).
6754
- */
6755
- const domParentVNode = vnode_getDomParentVNode(parent, false);
6756
- const parentNode = domParentVNode && domParentVNode.node;
6757
- let domChildren = null;
6758
- if (domParentVNode) {
6759
- domChildren = vnode_getDomChildrenWithCorrectNamespacesToInsert(journal, domParentVNode, newChild);
6597
+ vnode_unlinkFromOldParent(journal, newChildCurrentParent, parent, newChild);
6598
+ const parentIsDeleted = parent.flags & 32 /* VNodeFlags.Deleted */;
6599
+ const domParentVNode = parentIsElement ? parent : vnode_getDomParentVNode(parent, false);
6600
+ const parentNode = domParentVNode?.node;
6601
+ const adjustedInsertBefore = vnode_findInsertBefore(journal, parent, insertBefore);
6602
+ const adjustedInsertBeforeNode = adjustedInsertBefore?.node ?? null;
6603
+ const isProjection = vnode_isProjection(newChild);
6604
+ if (isProjection && domParentVNode && (domParentVNode.flags & 1536 /* VNodeFlags.NAMESPACE_MASK */) !== 0) {
6605
+ const domParentVNode = vnode_getDomParentVNode(parent, false);
6606
+ const adjustedInsertBeforeNode = vnode_findInsertBefore(journal, parent, insertBefore)?.node ?? null;
6607
+ /**
6608
+ * Find the parent node and the dom children with the correct namespaces before we unlink the
6609
+ * previous node. If we don't do this, we will end up with situations where we inflate text
6610
+ * nodes from shared text node not correctly.
6611
+ *
6612
+ * Example:
6613
+ *
6614
+ * ```
6615
+ * <Component>
6616
+ * <Projection>a</Projection>
6617
+ * <Projection>b</Projection>
6618
+ * </Component>
6619
+ * ```
6620
+ *
6621
+ * Projection nodes are virtual nodes, so they don't have a dom parent. They will be written to
6622
+ * the q:template element if not visible at the start. Inside the q:template element, the
6623
+ * projection nodes will be streamed as single text node "ab". We need to split it, but if we
6624
+ * unlink the previous or next sibling, we don't know that after "a" node is "b". So we need to
6625
+ * find children first (and inflate them).
6626
+ */
6627
+ const { elementNamespace, elementNamespaceFlag } = getNewElementNamespaceData(domParentVNode, newChild);
6628
+ vnode_walkDirectChildren(journal, newChild, (vNode) => {
6629
+ if (vnode_isTextVNode(vNode)) {
6630
+ addVNodeOperation(journal, createInsertOrMoveOperation(vNode.node, parentNode, adjustedInsertBeforeNode));
6631
+ }
6632
+ else {
6633
+ if ((vNode.flags & 1536 /* VNodeFlags.NAMESPACE_MASK */) !== elementNamespaceFlag) {
6634
+ const newChildElement = vnode_cloneElementWithNamespace(vNode, domParentVNode, elementNamespace, elementNamespaceFlag);
6635
+ if (newChildElement) {
6636
+ vNode.node = newChildElement;
6637
+ }
6638
+ }
6639
+ addVNodeOperation(journal, createInsertOrMoveOperation(vNode.node, parentNode, adjustedInsertBeforeNode));
6640
+ }
6641
+ });
6642
+ }
6643
+ else if (
6644
+ // for projection there can be no parent node
6645
+ parentNode &&
6646
+ !parentIsDeleted) {
6647
+ vnode_walkDirectChildren(journal, newChild, (vNode) => {
6648
+ addVNodeOperation(journal, createInsertOrMoveOperation(vNode.node, parentNode, adjustedInsertBeforeNode));
6649
+ });
6650
+ }
6651
+ vnode_connectSiblings(parent, newChild, insertBefore);
6652
+ if (parentIsDeleted) {
6653
+ // if the parent is deleted, then the new child is also deleted
6654
+ newChild.flags |= 32 /* VNodeFlags.Deleted */;
6655
+ }
6656
+ };
6657
+ const vnode_findInsertBefore = (journal, parent, insertBefore) => {
6658
+ let adjustedInsertBefore = null;
6659
+ if (insertBefore == null) {
6660
+ if (vnode_isVirtualVNode(parent)) {
6661
+ // If `insertBefore` is null, than we need to insert at the end of the list.
6662
+ // Well, not quite. If the parent is a virtual node, our "last node" is not the same
6663
+ // as the DOM "last node". So in that case we need to look for the "next node" from
6664
+ // our parent.
6665
+ adjustedInsertBefore = vnode_getDomSibling(parent, true, false);
6666
+ }
6667
+ }
6668
+ else if (vnode_isVirtualVNode(insertBefore)) {
6669
+ // If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
6670
+ adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
6671
+ }
6672
+ else {
6673
+ adjustedInsertBefore = insertBefore;
6674
+ }
6675
+ adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
6676
+ return adjustedInsertBefore;
6677
+ };
6678
+ const vnode_connectSiblings = (parent, vNode, vNext) => {
6679
+ const vPrevious = vNext ? vNext.previousSibling : parent.lastChild;
6680
+ if (vNext) {
6681
+ vNext.previousSibling = vNode;
6682
+ }
6683
+ else {
6684
+ parent.lastChild = vNode;
6685
+ }
6686
+ if (vPrevious) {
6687
+ vPrevious.nextSibling = vNode;
6688
+ }
6689
+ else {
6690
+ parent.firstChild = vNode;
6760
6691
  }
6692
+ vNode.previousSibling = vPrevious;
6693
+ vNode.nextSibling = vNext;
6694
+ vNode.parent = parent;
6695
+ };
6696
+ const vnode_unlinkFromOldParent = (journal, currentParent, newParent, newChild) => {
6761
6697
  /**
6762
6698
  * Ensure that the previous node is unlinked.
6763
6699
  *
@@ -6795,58 +6731,17 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
6795
6731
  * <p>Test content</p> // <-- to remove
6796
6732
  * ```
6797
6733
  */
6798
- if (newChildCurrentParent &&
6799
- (newChild.previousSibling || newChild.nextSibling || newChildCurrentParent !== parent)) {
6800
- vnode_remove(journal, newChildCurrentParent, newChild, false);
6801
- }
6802
- const parentIsDeleted = parent.flags & 32 /* VNodeFlags.Deleted */;
6803
- let adjustedInsertBefore = null;
6804
- // if the parent is deleted, then we don't need to insert the new child
6805
- if (!parentIsDeleted) {
6806
- if (insertBefore == null) {
6807
- if (vnode_isVirtualVNode(parent)) {
6808
- // If `insertBefore` is null, than we need to insert at the end of the list.
6809
- // Well, not quite. If the parent is a virtual node, our "last node" is not the same
6810
- // as the DOM "last node". So in that case we need to look for the "next node" from
6811
- // our parent.
6812
- adjustedInsertBefore = vnode_getDomSibling(parent, true, false);
6813
- }
6814
- }
6815
- else if (vnode_isVirtualVNode(insertBefore)) {
6816
- // If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
6817
- adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
6818
- }
6819
- else {
6820
- adjustedInsertBefore = insertBefore;
6821
- }
6822
- adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
6823
- if (domChildren && domChildren.length) {
6824
- for (const child of domChildren) {
6825
- addVNodeOperation(journal, createInsertOrMoveOperation(child.node, parentNode, vnode_getNode(adjustedInsertBefore)));
6826
- }
6827
- }
6828
- }
6829
- // link newChild into the previous/next list
6830
- const vNext = insertBefore;
6831
- const vPrevious = vNext ? vNext.previousSibling : parent.lastChild;
6832
- if (vNext) {
6833
- vNext.previousSibling = newChild;
6734
+ if (currentParent &&
6735
+ (newChild.previousSibling || newChild.nextSibling || currentParent !== newParent)) {
6736
+ vnode_remove(journal, currentParent, newChild, false);
6834
6737
  }
6835
- else {
6836
- parent.lastChild = newChild;
6837
- }
6838
- if (vPrevious) {
6839
- vPrevious.nextSibling = newChild;
6738
+ };
6739
+ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
6740
+ if (vnode_isElementOrTextVNode(newChild)) {
6741
+ vnode_insertElementBefore(journal, parent, newChild, insertBefore);
6840
6742
  }
6841
6743
  else {
6842
- parent.firstChild = newChild;
6843
- }
6844
- newChild.previousSibling = vPrevious;
6845
- newChild.nextSibling = vNext;
6846
- newChild.parent = parent;
6847
- if (parentIsDeleted) {
6848
- // if the parent is deleted, then the new child is also deleted
6849
- newChild.flags |= 32 /* VNodeFlags.Deleted */;
6744
+ vnode_insertVirtualBefore(journal, parent, newChild, insertBefore);
6850
6745
  }
6851
6746
  };
6852
6747
  const vnode_getDomParent = (vnode, includeProjection) => {
@@ -6865,18 +6760,18 @@ const vnode_remove = (journal, vParent, vToRemove, removeDOM) => {
6865
6760
  vnode_ensureTextInflated(journal, vToRemove);
6866
6761
  }
6867
6762
  if (removeDOM) {
6868
- const domParent = vnode_getDomParent(vParent, false);
6869
6763
  const isInnerHTMLParent = vnode_getProp(vParent, dangerouslySetInnerHTML, null) !== null;
6870
6764
  if (isInnerHTMLParent) {
6871
6765
  // ignore children, as they are inserted via innerHTML
6872
6766
  return;
6873
6767
  }
6874
- const children = vnode_getDOMChildNodes(journal, vToRemove, true);
6875
- //&& //journal.push(VNodeOperationType.Remove, domParent, ...children);
6876
- if (domParent && children.length) {
6877
- for (const child of children) {
6878
- addVNodeOperation(journal, createDeleteOperation(child.node));
6879
- }
6768
+ if (vnode_isElementOrTextVNode(vToRemove)) {
6769
+ addVNodeOperation(journal, createDeleteOperation(vToRemove.node));
6770
+ }
6771
+ else {
6772
+ vnode_walkDirectChildren(journal, vToRemove, (vNode) => {
6773
+ addVNodeOperation(journal, createDeleteOperation(vNode.node));
6774
+ });
6880
6775
  }
6881
6776
  }
6882
6777
  const vPrevious = vToRemove.previousSibling;
@@ -6900,16 +6795,13 @@ const vnode_truncate = (journal, vParent, vDelete, removeDOM = true) => {
6900
6795
  isDev && assertDefined(vDelete, 'Missing vDelete.');
6901
6796
  const parent = vnode_getDomParent(vParent, true);
6902
6797
  if (parent && removeDOM) {
6903
- if (vnode_isElementVNode(vParent)) {
6798
+ if (vnode_isElementOrTextVNode(vParent)) {
6904
6799
  addVNodeOperation(journal, createRemoveAllChildrenOperation(vParent.node));
6905
6800
  }
6906
6801
  else {
6907
- const children = vnode_getDOMChildNodes(journal, vParent, true);
6908
- if (children.length) {
6909
- for (const child of children) {
6910
- addVNodeOperation(journal, createDeleteOperation(child.node));
6911
- }
6912
- }
6802
+ vnode_walkDirectChildren(journal, vParent, (vNode) => {
6803
+ addVNodeOperation(journal, createDeleteOperation(vNode.node));
6804
+ });
6913
6805
  }
6914
6806
  }
6915
6807
  const vPrevious = vDelete.previousSibling;
@@ -7284,7 +7176,7 @@ const vnode_getAttrKeys = (container, vnode) => {
7284
7176
  const keys = [];
7285
7177
  const props = vnode.props;
7286
7178
  if (props) {
7287
- for (const key of Object.keys(props)) {
7179
+ for (const key in props) {
7288
7180
  if (!key.startsWith(Q_PROPS_SEPARATOR)) {
7289
7181
  keys.push(key);
7290
7182
  }
@@ -7314,7 +7206,15 @@ const vnode_getNode = (vnode) => {
7314
7206
  return vnode.node;
7315
7207
  };
7316
7208
  /** @internal */
7317
- function vnode_toString(depth = 20, offset = '', materialize = false, siblings = false, colorize = true, container = this && vnode_getDOMContainer(this)) {
7209
+ function vnode_toString(depth = 20, offset = '', materialize = false, siblings = false, colorize = true, container = null) {
7210
+ if (this && !container) {
7211
+ try {
7212
+ container = vnode_getDOMContainer(this);
7213
+ }
7214
+ catch {
7215
+ // ignore, as this is only for debugging
7216
+ }
7217
+ }
7318
7218
  let vnode = this;
7319
7219
  if (depth === 0) {
7320
7220
  return '...';
@@ -7338,12 +7238,14 @@ function vnode_toString(depth = 20, offset = '', materialize = false, siblings =
7338
7238
  if (vnode.dirty) {
7339
7239
  attrs.push(` dirty:${vnode.dirty}`);
7340
7240
  }
7341
- vnode_getAttrKeys(container, vnode).forEach((key) => {
7342
- if (key !== DEBUG_TYPE && key !== debugStyleScopeIdPrefixAttr) {
7343
- const value = vnode_getProp(vnode, key, null);
7344
- attrs.push(' ' + key + '=' + qwikDebugToString(value));
7345
- }
7346
- });
7241
+ if (container) {
7242
+ vnode_getAttrKeys(container, vnode).forEach((key) => {
7243
+ if (key !== DEBUG_TYPE && key !== debugStyleScopeIdPrefixAttr) {
7244
+ const value = vnode_getProp(vnode, key, null);
7245
+ attrs.push(' ' + key + '=' + qwikDebugToString(value));
7246
+ }
7247
+ });
7248
+ }
7347
7249
  const name = (colorize ? NAME_COL_PREFIX : '') +
7348
7250
  (VirtualTypeName[vnode_getProp(vnode, DEBUG_TYPE, null) || "V" /* VirtualType.Virtual */] ||
7349
7251
  VirtualTypeName["V" /* VirtualType.Virtual */]) +
@@ -7366,7 +7268,7 @@ function vnode_toString(depth = 20, offset = '', materialize = false, siblings =
7366
7268
  if (vnode.dirtyChildren) {
7367
7269
  attrs.push(` dirtyChildren[${vnode.dirtyChildren.length}]`);
7368
7270
  }
7369
- const keys = vnode_getAttrKeys(container, vnode);
7271
+ const keys = container ? vnode_getAttrKeys(container, vnode) : [];
7370
7272
  for (const key of keys) {
7371
7273
  const value = vnode_getProp(vnode, key, null);
7372
7274
  attrs.push(' ' + key + '=' + qwikDebugToString(value));
@@ -7566,8 +7468,8 @@ function materializeFromVNodeData(vParent, vData, element, child) {
7566
7468
  if (!container) {
7567
7469
  container = getDomContainer(element);
7568
7470
  }
7569
- for (const component of components) {
7570
- container.ensureProjectionResolved(component);
7471
+ for (let i = 0; i < components.length; i++) {
7472
+ container.ensureProjectionResolved(components[i]);
7571
7473
  }
7572
7474
  components = null;
7573
7475
  }
@@ -7723,15 +7625,6 @@ const useInvokeContext = () => {
7723
7625
  isDev && assertDefined(ctx.$effectSubscriber$, `invoke: $effectSubscriber$ must be defined`, ctx);
7724
7626
  return ctx;
7725
7627
  };
7726
- function useBindInvokeContext(fn) {
7727
- if (fn == null) {
7728
- return fn;
7729
- }
7730
- const ctx = getInvokeContext();
7731
- return function (...args) {
7732
- return (invokeApply).call(this, ctx, fn, args);
7733
- };
7734
- }
7735
7628
  /** Call a function with the given InvokeContext and given arguments. */
7736
7629
  function invoke(context, fn, ...args) {
7737
7630
  return invokeApply.call(this, context, fn, args);
@@ -7831,7 +7724,7 @@ const trackSignal = (fn, subscriber, property, container, data) => {
7831
7724
  try {
7832
7725
  trackInvocation.$effectSubscriber$ = getSubscriber(subscriber, property, data);
7833
7726
  trackInvocation.$container$ = container;
7834
- return invoke(trackInvocation, fn);
7727
+ return invokeApply(trackInvocation, fn);
7835
7728
  }
7836
7729
  finally {
7837
7730
  trackInvocation.$effectSubscriber$ = previousSubscriber;
@@ -7875,6 +7768,41 @@ const _waitUntilRendered = (container) => {
7875
7768
  return container.$renderPromise$ || Promise.resolve();
7876
7769
  };
7877
7770
 
7771
+ /**
7772
+ * @internal
7773
+ * The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
7774
+ */
7775
+ const useSequentialScope = () => {
7776
+ const iCtx = useInvokeContext();
7777
+ const hostElement = iCtx.$hostElement$;
7778
+ const host = hostElement;
7779
+ let seq = iCtx.$container$.getHostProp(host, ELEMENT_SEQ);
7780
+ if (seq === null) {
7781
+ seq = [];
7782
+ iCtx.$container$.setHostProp(host, ELEMENT_SEQ, seq);
7783
+ }
7784
+ let seqIdx = iCtx.$container$.getHostProp(host, ELEMENT_SEQ_IDX);
7785
+ if (seqIdx === null) {
7786
+ seqIdx = 0;
7787
+ }
7788
+ iCtx.$container$.setHostProp(host, ELEMENT_SEQ_IDX, seqIdx + 1);
7789
+ while (seq.length <= seqIdx) {
7790
+ seq.push(undefined);
7791
+ }
7792
+ const set = (value) => {
7793
+ if (qDev && qSerialize) {
7794
+ verifySerializable(value);
7795
+ }
7796
+ return (seq[seqIdx] = value);
7797
+ };
7798
+ return {
7799
+ val: seq[seqIdx],
7800
+ set,
7801
+ i: seqIdx,
7802
+ iCtx,
7803
+ };
7804
+ };
7805
+
7878
7806
  // <docs markdown="../readme.md#createContextId">
7879
7807
  // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
7880
7808
  // (edit ../readme.md#createContextId instead and run `pnpm docs.sync`)
@@ -8165,7 +8093,6 @@ const _typeIdNames = [
8165
8093
  'Map',
8166
8094
  'Uint8Array',
8167
8095
  'Task',
8168
- 'Resource',
8169
8096
  'Component',
8170
8097
  'Signal',
8171
8098
  'WrappedSignal',
@@ -8300,13 +8227,6 @@ const allocate = (container, typeId, value) => {
8300
8227
  }
8301
8228
  case 20 /* TypeIds.Task */:
8302
8229
  return new Task(-1, -1, null, null, null, null);
8303
- case 21 /* TypeIds.Resource */: {
8304
- const res = createResourceReturn(container,
8305
- // we don't care about the timeout value
8306
- undefined, undefined);
8307
- res.loading = false;
8308
- return res;
8309
- }
8310
8230
  case 6 /* TypeIds.URL */:
8311
8231
  return new URL(value);
8312
8232
  case 7 /* TypeIds.Date */:
@@ -8316,19 +8236,19 @@ const allocate = (container, typeId, value) => {
8316
8236
  return new RegExp(value.slice(1, idx), value.slice(idx + 1));
8317
8237
  case 15 /* TypeIds.Error */:
8318
8238
  return new Error();
8319
- case 22 /* TypeIds.Component */:
8239
+ case 21 /* TypeIds.Component */:
8320
8240
  return componentQrl(null);
8321
- case 23 /* TypeIds.Signal */:
8241
+ case 22 /* TypeIds.Signal */:
8322
8242
  return new SignalImpl(container, 0);
8323
- case 24 /* TypeIds.WrappedSignal */:
8243
+ case 23 /* TypeIds.WrappedSignal */:
8324
8244
  return new WrappedSignalImpl(container, null, null, null);
8325
- case 25 /* TypeIds.ComputedSignal */:
8245
+ case 24 /* TypeIds.ComputedSignal */:
8326
8246
  return new ComputedSignalImpl(container, null);
8327
- case 26 /* TypeIds.AsyncSignal */:
8328
- return new AsyncSignalImpl(container, null);
8329
- case 27 /* TypeIds.SerializerSignal */:
8247
+ case 25 /* TypeIds.AsyncSignal */:
8248
+ return new AsyncSignalImpl(container, null, undefined, { interval: 0 });
8249
+ case 26 /* TypeIds.SerializerSignal */:
8330
8250
  return new SerializerSignalImpl(container, null);
8331
- case 28 /* TypeIds.Store */: {
8251
+ case 27 /* TypeIds.Store */: {
8332
8252
  const data = value;
8333
8253
  // We need to allocate the store first, before we inflate its data, because the data can
8334
8254
  // reference the store itself (circular)
@@ -8347,9 +8267,9 @@ const allocate = (container, typeId, value) => {
8347
8267
  }
8348
8268
  case 13 /* TypeIds.URLSearchParams */:
8349
8269
  return new URLSearchParams(value);
8350
- case 29 /* TypeIds.FormData */:
8270
+ case 28 /* TypeIds.FormData */:
8351
8271
  return new FormData();
8352
- case 30 /* TypeIds.JSXNode */:
8272
+ case 29 /* TypeIds.JSXNode */:
8353
8273
  return new JSXNodeImpl(null, null, null, null, null);
8354
8274
  case 12 /* TypeIds.BigInt */:
8355
8275
  return BigInt(value);
@@ -8374,7 +8294,7 @@ const allocate = (container, typeId, value) => {
8374
8294
  const rest = encodedLength & 3;
8375
8295
  const decodedLength = blocks * 3 + (rest ? rest - 1 : 0);
8376
8296
  return new Uint8Array(decodedLength);
8377
- case 31 /* TypeIds.PropsProxy */:
8297
+ case 30 /* TypeIds.PropsProxy */:
8378
8298
  return createPropsProxy(null);
8379
8299
  case 10 /* TypeIds.VNode */:
8380
8300
  return retrieveVNodeOrDocument(container, value);
@@ -8412,9 +8332,9 @@ const allocate = (container, typeId, value) => {
8412
8332
  else {
8413
8333
  throw qError(17 /* QError.serializeErrorExpectedVNode */, [typeof vNode]);
8414
8334
  }
8415
- case 32 /* TypeIds.SubscriptionData */:
8335
+ case 31 /* TypeIds.SubscriptionData */:
8416
8336
  return new SubscriptionData({});
8417
- case 33 /* TypeIds.EffectSubscription */:
8337
+ case 32 /* TypeIds.EffectSubscription */:
8418
8338
  return new EffectSubscription(null, null, null, null);
8419
8339
  default:
8420
8340
  throw qError(18 /* QError.serializeErrorCannotAllocate */, [typeId]);
@@ -8759,7 +8679,7 @@ async function serialize(serializationContext) {
8759
8679
  else if (isQwikComponent(value)) {
8760
8680
  const [qrl] = value[SERIALIZABLE_STATE];
8761
8681
  serializationContext.$renderSymbols$.add(qrl.$symbol$);
8762
- output(22 /* TypeIds.Component */, [qrl]);
8682
+ output(21 /* TypeIds.Component */, [qrl]);
8763
8683
  }
8764
8684
  else {
8765
8685
  throw qError(34 /* QError.serializeErrorCannotSerializeFunction */, [value.toString()]);
@@ -8797,7 +8717,7 @@ async function serialize(serializationContext) {
8797
8717
  const writeObjectValue = (value) => {
8798
8718
  if (isPropsProxy(value)) {
8799
8719
  const owner = value[_OWNER];
8800
- output(31 /* TypeIds.PropsProxy */, [
8720
+ output(30 /* TypeIds.PropsProxy */, [
8801
8721
  _serializationWeakRef(owner),
8802
8722
  owner.varProps,
8803
8723
  owner.constProps,
@@ -8805,10 +8725,10 @@ async function serialize(serializationContext) {
8805
8725
  ]);
8806
8726
  }
8807
8727
  else if (value instanceof SubscriptionData) {
8808
- output(32 /* TypeIds.SubscriptionData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
8728
+ output(31 /* TypeIds.SubscriptionData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
8809
8729
  }
8810
8730
  else if (value instanceof EffectSubscription) {
8811
- output(33 /* TypeIds.EffectSubscription */, [
8731
+ output(32 /* TypeIds.EffectSubscription */, [
8812
8732
  value.consumer,
8813
8733
  value.property,
8814
8734
  value.backRef,
@@ -8816,41 +8736,30 @@ async function serialize(serializationContext) {
8816
8736
  ]);
8817
8737
  }
8818
8738
  else if (isStore(value)) {
8819
- if (isResource(value)) {
8820
- // let render know about the resource
8821
- serializationContext.$resources$.add(value);
8822
- // TODO the effects include the resource return which has duplicate data
8823
- const forwardRefId = resolvePromise(value.value, $addRoot$, (resolved, resolvedValue) => {
8824
- return new PromiseResult(21 /* TypeIds.Resource */, resolved, resolvedValue, getStoreHandler(value).$effects$);
8825
- });
8826
- output(2 /* TypeIds.ForwardRef */, forwardRefId);
8827
- }
8828
- else {
8829
- const storeHandler = getStoreHandler(value);
8830
- const storeTarget = getStoreTarget(value);
8831
- const flags = storeHandler.$flags$;
8832
- const effects = storeHandler.$effects$;
8833
- // We need to retain the nested stores too, they won't be found from the target
8834
- const innerStores = [];
8835
- for (const prop in storeTarget) {
8836
- const propValue = storeTarget[prop];
8837
- const innerStore = $storeProxyMap$.get(propValue);
8838
- if (innerStore) {
8839
- innerStores.push(innerStore);
8840
- }
8841
- }
8842
- const out = [storeTarget, flags, effects, ...innerStores];
8843
- while (out[out.length - 1] === undefined) {
8844
- out.pop();
8845
- }
8846
- output(28 /* TypeIds.Store */, out);
8739
+ const storeHandler = getStoreHandler(value);
8740
+ const storeTarget = getStoreTarget(value);
8741
+ const flags = storeHandler.$flags$;
8742
+ const effects = storeHandler.$effects$;
8743
+ // We need to retain the nested stores too, they won't be found from the target
8744
+ const innerStores = [];
8745
+ for (const prop in storeTarget) {
8746
+ const propValue = storeTarget[prop];
8747
+ const innerStore = $storeProxyMap$.get(propValue);
8748
+ if (innerStore) {
8749
+ innerStores.push(innerStore);
8750
+ }
8751
+ }
8752
+ const out = [storeTarget, flags, effects, ...innerStores];
8753
+ while (out[out.length - 1] === undefined) {
8754
+ out.pop();
8847
8755
  }
8756
+ output(27 /* TypeIds.Store */, out);
8848
8757
  }
8849
8758
  else if (isSerializerObj(value)) {
8850
8759
  const result = value[SerializerSymbol](value);
8851
8760
  if (isPromise(result)) {
8852
8761
  const forwardRef = resolvePromise(result, $addRoot$, (resolved, resolvedValue) => {
8853
- return new PromiseResult(27 /* TypeIds.SerializerSignal */, resolved, resolvedValue, undefined, undefined);
8762
+ return new PromiseResult(26 /* TypeIds.SerializerSignal */, resolved, resolvedValue, undefined, undefined);
8854
8763
  });
8855
8764
  output(2 /* TypeIds.ForwardRef */, forwardRef);
8856
8765
  }
@@ -8887,12 +8796,12 @@ async function serialize(serializationContext) {
8887
8796
  const maybeValue = getCustomSerializerPromise(value, value.$untrackedValue$);
8888
8797
  if (isPromise(maybeValue)) {
8889
8798
  const forwardRefId = resolvePromise(maybeValue, $addRoot$, (resolved, resolvedValue) => {
8890
- return new PromiseResult(27 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
8799
+ return new PromiseResult(26 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
8891
8800
  });
8892
8801
  output(2 /* TypeIds.ForwardRef */, forwardRefId);
8893
8802
  }
8894
8803
  else {
8895
- output(27 /* TypeIds.SerializerSignal */, [
8804
+ output(26 /* TypeIds.SerializerSignal */, [
8896
8805
  value.$computeQrl$,
8897
8806
  filterEffectBackRefs(value[_EFFECT_BACK_REF]),
8898
8807
  value.$effects$,
@@ -8902,7 +8811,7 @@ async function serialize(serializationContext) {
8902
8811
  return;
8903
8812
  }
8904
8813
  if (value instanceof WrappedSignalImpl) {
8905
- output(24 /* TypeIds.WrappedSignal */, [
8814
+ output(23 /* TypeIds.WrappedSignal */, [
8906
8815
  ...serializeWrappingFn(serializationContext, value),
8907
8816
  filterEffectBackRefs(value[_EFFECT_BACK_REF]),
8908
8817
  value.$flags$,
@@ -8916,28 +8825,36 @@ async function serialize(serializationContext) {
8916
8825
  const shouldNeverSerialize = value.$flags$ & 8 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
8917
8826
  const isInvalid = value.$flags$ & 1 /* SignalFlags.INVALID */;
8918
8827
  const isSkippable = fastSkipSerialize(value.$untrackedValue$);
8919
- if (shouldAlwaysSerialize) {
8828
+ const isAsync = value instanceof AsyncSignalImpl;
8829
+ const interval = isAsync && value.$interval$ > 0 ? value.$interval$ : undefined;
8830
+ const concurrency = isAsync && value.$concurrency$ !== 1 ? value.$concurrency$ : undefined;
8831
+ const timeout = isAsync && value.$timeoutMs$ !== 0 ? value.$timeoutMs$ : undefined;
8832
+ const eagerCleanup = isAsync && value.$flags$ & 32 /* AsyncSignalFlags.EAGER_CLEANUP */ ? true : undefined;
8833
+ if (isInvalid || isSkippable) {
8834
+ v = NEEDS_COMPUTATION;
8835
+ }
8836
+ else if (shouldAlwaysSerialize) {
8920
8837
  v = value.$untrackedValue$;
8921
8838
  }
8922
8839
  else if (shouldNeverSerialize) {
8923
8840
  v = NEEDS_COMPUTATION;
8924
8841
  }
8925
- else if (isInvalid || isSkippable) {
8926
- v = NEEDS_COMPUTATION;
8927
- }
8928
8842
  const out = [
8929
8843
  value.$computeQrl$,
8930
8844
  filterEffectBackRefs(value[_EFFECT_BACK_REF]),
8931
8845
  value.$effects$,
8932
8846
  ];
8933
- const isAsync = value instanceof AsyncSignalImpl;
8934
8847
  if (isAsync) {
8935
- out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedLoading$, value.$untrackedError$);
8848
+ // After SSR, the signal is never loading, so no need to send it
8849
+ out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedError$);
8936
8850
  }
8937
8851
  let keepUndefined = false;
8938
- if (v !== NEEDS_COMPUTATION) {
8852
+ if (v !== NEEDS_COMPUTATION ||
8853
+ interval !== undefined ||
8854
+ concurrency !== undefined ||
8855
+ timeout !== undefined) {
8939
8856
  out.push(v);
8940
- if (!isAsync && v === undefined) {
8857
+ if (v === undefined) {
8941
8858
  /**
8942
8859
  * If value is undefined, we need to keep it in the output. If we don't do that, later
8943
8860
  * during resuming, the value will be set to symbol(invalid) with flag invalid, and
@@ -8946,7 +8863,13 @@ async function serialize(serializationContext) {
8946
8863
  keepUndefined = true;
8947
8864
  }
8948
8865
  }
8949
- output(isAsync ? 26 /* TypeIds.AsyncSignal */ : 25 /* TypeIds.ComputedSignal */, out, keepUndefined);
8866
+ if (isAsync) {
8867
+ out.push(interval);
8868
+ out.push(concurrency);
8869
+ out.push(timeout);
8870
+ out.push(eagerCleanup);
8871
+ }
8872
+ output(isAsync ? 25 /* TypeIds.AsyncSignal */ : 24 /* TypeIds.ComputedSignal */, out, keepUndefined);
8950
8873
  }
8951
8874
  else {
8952
8875
  const v = value.$untrackedValue$;
@@ -8955,7 +8878,7 @@ async function serialize(serializationContext) {
8955
8878
  if (value.$effects$) {
8956
8879
  out.push(...value.$effects$);
8957
8880
  }
8958
- output(23 /* TypeIds.Signal */, out, keepUndefined);
8881
+ output(22 /* TypeIds.Signal */, out, keepUndefined);
8959
8882
  }
8960
8883
  }
8961
8884
  else if (value instanceof URL) {
@@ -9017,7 +8940,7 @@ async function serialize(serializationContext) {
9017
8940
  array.push(key, value.name);
9018
8941
  }
9019
8942
  });
9020
- output(29 /* TypeIds.FormData */, array);
8943
+ output(28 /* TypeIds.FormData */, array);
9021
8944
  }
9022
8945
  else if (value instanceof URLSearchParams) {
9023
8946
  output(13 /* TypeIds.URLSearchParams */, value.toString());
@@ -9044,7 +8967,7 @@ async function serialize(serializationContext) {
9044
8967
  while (out[out.length - 1] === undefined) {
9045
8968
  out.pop();
9046
8969
  }
9047
- output(30 /* TypeIds.JSXNode */, out);
8970
+ output(29 /* TypeIds.JSXNode */, out);
9048
8971
  }
9049
8972
  else if (value instanceof Task) {
9050
8973
  const out = [
@@ -9067,12 +8990,9 @@ async function serialize(serializationContext) {
9067
8990
  output(2 /* TypeIds.ForwardRef */, forwardRefId);
9068
8991
  }
9069
8992
  else if (value instanceof PromiseResult) {
9070
- if (value.$type$ === 21 /* TypeIds.Resource */) {
9071
- output(21 /* TypeIds.Resource */, [value.$resolved$, value.$value$, value.$effects$]);
9072
- }
9073
- else if (value.$type$ === 27 /* TypeIds.SerializerSignal */) {
8993
+ if (value.$type$ === 26 /* TypeIds.SerializerSignal */) {
9074
8994
  if (value.$qrl$) {
9075
- output(27 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
8995
+ output(26 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
9076
8996
  }
9077
8997
  else if (value.$resolved$) {
9078
8998
  // We replace ourselves with this value
@@ -9247,9 +9167,6 @@ function isObjectLiteral(obj) {
9247
9167
  const prototype = Object.getPrototypeOf(obj);
9248
9168
  return prototype == null || prototype === Object.prototype || prototype === Array.prototype;
9249
9169
  }
9250
- function isResource(value) {
9251
- return '__brand' in value && value.__brand === 'resource';
9252
- }
9253
9170
  function serializeWrappingFn(serializationContext, value) {
9254
9171
  // if value is an object then we need to wrap this in ()
9255
9172
  if (value.$funcStr$ && value.$funcStr$[0] === '{') {
@@ -9313,6 +9230,7 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
9313
9230
  const syncFnMap = new Map();
9314
9231
  const syncFns = [];
9315
9232
  const roots = [];
9233
+ const eagerResume = new Set();
9316
9234
  const getSeenRef = (obj) => seenObjsMap.get(obj);
9317
9235
  const $markSeen$ = (obj, parent, index) => {
9318
9236
  const ref = { $index$: index, $parent$: parent };
@@ -9408,9 +9326,10 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
9408
9326
  $writer$: writer,
9409
9327
  $eventQrls$: new Set(),
9410
9328
  $eventNames$: new Set(),
9411
- $resources$: new Set(),
9412
9329
  $renderSymbols$: new Set(),
9413
9330
  $storeProxyMap$: storeProxyMap,
9331
+ $eagerResume$: eagerResume,
9332
+ $resources$: new Set(),
9414
9333
  $getProp$: getProp,
9415
9334
  $setProp$: setProp,
9416
9335
  };
@@ -9430,8 +9349,7 @@ class _SharedContainer {
9430
9349
  $buildBase$ = null;
9431
9350
  $renderPromise$ = null;
9432
9351
  $resolveRenderPromise$ = null;
9433
- $cursorCount$ = 0;
9434
- $pausedCursorCount$ = 0;
9352
+ $pendingCount$ = 0;
9435
9353
  constructor(serverData, locale) {
9436
9354
  this.$serverData$ = serverData;
9437
9355
  this.$locale$ = locale;
@@ -9447,6 +9365,12 @@ class _SharedContainer {
9447
9365
  serializationCtxFactory(NodeConstructor, DomRefConstructor, symbolToChunkResolver, writer) {
9448
9366
  return createSerializationContext(NodeConstructor, DomRefConstructor, symbolToChunkResolver, this.getHostProp.bind(this), this.setHostProp.bind(this), this.$storeProxyMap$, writer);
9449
9367
  }
9368
+ $checkPendingCount$() {
9369
+ if (this.$pendingCount$ === 0) {
9370
+ this.$resolveRenderPromise$?.();
9371
+ this.$renderPromise$ = null;
9372
+ }
9373
+ }
9450
9374
  }
9451
9375
 
9452
9376
  function isAsyncGenerator(value) {
@@ -9540,6 +9464,7 @@ function processJSXNode(ssr, enqueue, value, options) {
9540
9464
  }
9541
9465
  }
9542
9466
  else if (isSignal(value)) {
9467
+ maybeAddPollingAsyncSignalToEagerResume(ssr.serializationCtx, value);
9543
9468
  ssr.openFragment(isDev ? [DEBUG_TYPE, "S" /* VirtualType.WrappedSignal */] : EMPTY_ARRAY);
9544
9469
  const signalNode = ssr.getOrCreateLastNode();
9545
9470
  const unwrappedSignal = value instanceof WrappedSignalImpl ? value.$unwrapIfSignal$() : value;
@@ -9728,6 +9653,7 @@ function toSsrAttrs(record, options) {
9728
9653
  return;
9729
9654
  }
9730
9655
  if (isSignal(value)) {
9656
+ maybeAddPollingAsyncSignalToEagerResume(options.serializationCtx, value);
9731
9657
  // write signal as is. We will track this signal inside `writeAttrs`
9732
9658
  if (isClassAttr(key)) {
9733
9659
  // additionally append styleScopedId for class attr
@@ -9816,6 +9742,19 @@ function addPreventDefaultEventToSerializationContext(serializationCtx, key) {
9816
9742
  serializationCtx.$eventNames$.add(eventName);
9817
9743
  }
9818
9744
  }
9745
+ function maybeAddPollingAsyncSignalToEagerResume(serializationCtx, signal) {
9746
+ // Unwrap if it's a WrappedSignalImpl
9747
+ const unwrappedSignal = signal instanceof WrappedSignalImpl ? signal.$unwrapIfSignal$() : signal;
9748
+ if (unwrappedSignal instanceof AsyncSignalImpl) {
9749
+ const interval = unwrappedSignal.$interval$;
9750
+ // Don't check for $effects$ here - effects are added later during tracking.
9751
+ // The AsyncSignal's polling mechanism will check for effects before scheduling.
9752
+ if (interval > 0) {
9753
+ serializationCtx.$addRoot$(unwrappedSignal);
9754
+ serializationCtx.$eagerResume$.add(unwrappedSignal);
9755
+ }
9756
+ }
9757
+ }
9819
9758
  function getSlotName(host, jsx, ssr) {
9820
9759
  const constProps = jsx.constProps;
9821
9760
  if (constProps && typeof constProps == 'object' && 'name' in constProps) {
@@ -9853,7 +9792,7 @@ function appendClassIfScopedStyleExists(jsx, styleScoped) {
9853
9792
  * NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
9854
9793
  * (before any `await` statements.)
9855
9794
  *
9856
- * @deprecated Read from `_captures` directly instead.
9795
+ * @deprecated Use `_captures` instead.
9857
9796
  * @internal
9858
9797
  */
9859
9798
  // </docs>
@@ -9862,6 +9801,117 @@ const useLexicalScope = () => {
9862
9801
  return _captures;
9863
9802
  };
9864
9803
 
9804
+ /**
9805
+ * The resource function wrapper
9806
+ *
9807
+ * @internal
9808
+ */
9809
+ const _rsc = async (arg) => {
9810
+ const [fn, ref] = _captures;
9811
+ const result = await fn(arg);
9812
+ if (result && typeof result === 'object') {
9813
+ if (ref.r) {
9814
+ Object.assign(ref.r, result);
9815
+ }
9816
+ else {
9817
+ // We need lazy creation because we don't know if it will be an array or an object, and we want to preserve the original reference for reactivity to work
9818
+ ref.r = createStore(fn.$container$, result, 1 /* StoreFlags.RECURSIVE */);
9819
+ }
9820
+ }
9821
+ else {
9822
+ ref.r = result;
9823
+ }
9824
+ return { r: ref.r };
9825
+ };
9826
+ /** @internal */
9827
+ const useResourceQrl = (qrl, opts) => {
9828
+ assertQrl(qrl);
9829
+ const { val, set, iCtx } = useSequentialScope();
9830
+ if (val) {
9831
+ return val;
9832
+ }
9833
+ const ref = {};
9834
+ // Wrap the function so we can maintain a stable reference to the store
9835
+ const wrapped = createQRL(null, '_rsc', _rsc, null, [qrl, ref]);
9836
+ qrl.$container$ = iCtx.$container$;
9837
+ const asyncSignal = createAsyncSignal(wrapped, {
9838
+ timeout: opts?.timeout,
9839
+ container: iCtx.$container$,
9840
+ concurrency: 0,
9841
+ });
9842
+ // Resource is eager
9843
+ asyncSignal.$computeIfNeeded$();
9844
+ // Create a wrapper that presents the Promise-based ResourceReturn API
9845
+ const resource = {
9846
+ __brand: 'resource',
9847
+ signal: asyncSignal,
9848
+ get value() {
9849
+ return asyncSignal
9850
+ .promise()
9851
+ .then(() => (asyncSignal.error ? Promise.reject(asyncSignal.error) : asyncSignal.value.r));
9852
+ },
9853
+ get loading() {
9854
+ return asyncSignal.loading;
9855
+ },
9856
+ };
9857
+ set(resource);
9858
+ return resource;
9859
+ };
9860
+ /**
9861
+ * ```tsx
9862
+ * const Cmp = component$(() => {
9863
+ * const city = useSignal('');
9864
+ *
9865
+ * const weather = useAsync$(async ({ track, cleanup, abortSignal }) => {
9866
+ * const cityName = track(city);
9867
+ * const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
9868
+ * signal: abortSignal,
9869
+ * });
9870
+ * const temp = (await res.json()) as { temp: number };
9871
+ * return temp;
9872
+ * });
9873
+ *
9874
+ * return (
9875
+ * <div>
9876
+ * <input name="city" bind:value={city} />
9877
+ * <div>
9878
+ * Temperature:{' '}
9879
+ * {weather.loading
9880
+ * ? 'Loading...'
9881
+ * : weather.error
9882
+ * ? `Error: ${weather.error.message}`
9883
+ * : weather.value.temp}
9884
+ * </div>
9885
+ * </div>
9886
+ * );
9887
+ * });
9888
+ * ```
9889
+ *
9890
+ * @deprecated Use `useAsync$` instead, which is more efficient, and has a more flexible API. Just
9891
+ * read the `loading` and `error` properties from the returned signal to determine the status.
9892
+ * @public
9893
+ */
9894
+ const Resource = ({ value, onResolved, onPending, onRejected, }) => {
9895
+ if (isPromise(value)) {
9896
+ return value.then(onResolved, onRejected);
9897
+ }
9898
+ const isRes = isResourceReturn(value);
9899
+ const signal = isRes ? value.signal : value;
9900
+ if (onPending && signal.loading) {
9901
+ return onPending();
9902
+ }
9903
+ if (onRejected && signal.error) {
9904
+ return onRejected(signal.error);
9905
+ }
9906
+ const val = isRes ? signal.value?.r : signal.value;
9907
+ return (isPromise(val)
9908
+ ? val.then(onResolved, onRejected)
9909
+ : onResolved(val));
9910
+ };
9911
+ const isResourceReturn = (obj) => {
9912
+ return obj && obj.__brand === 'resource';
9913
+ };
9914
+
9865
9915
  let loading = Promise.resolve();
9866
9916
  const inflate = (container, target, typeId, data) => {
9867
9917
  if (typeId === 0 /* TypeIds.Plain */) {
@@ -9898,25 +9948,10 @@ const inflate = (container, target, typeId, data) => {
9898
9948
  task[_EFFECT_BACK_REF] = v[4];
9899
9949
  task.$state$ = v[5];
9900
9950
  break;
9901
- case 21 /* TypeIds.Resource */:
9902
- const [resolved, result, effects] = data;
9903
- const resource = target;
9904
- if (resolved) {
9905
- resource.value = Promise.resolve(result);
9906
- resource._resolved = result;
9907
- resource._state = 'resolved';
9908
- }
9909
- else {
9910
- resource.value = Promise.reject(result);
9911
- resource._error = result;
9912
- resource._state = 'rejected';
9913
- }
9914
- getStoreHandler(target).$effects$ = effects;
9915
- break;
9916
- case 22 /* TypeIds.Component */:
9951
+ case 21 /* TypeIds.Component */:
9917
9952
  target[SERIALIZABLE_STATE][0] = data[0];
9918
9953
  break;
9919
- case 28 /* TypeIds.Store */: {
9954
+ case 27 /* TypeIds.Store */: {
9920
9955
  // Inflate the store target
9921
9956
  const store = unwrapStore(target);
9922
9957
  const storeTarget = pendingStoreTargets.get(store);
@@ -9934,14 +9969,14 @@ const inflate = (container, target, typeId, data) => {
9934
9969
  storeHandler.$effects$ = effects;
9935
9970
  break;
9936
9971
  }
9937
- case 23 /* TypeIds.Signal */: {
9972
+ case 22 /* TypeIds.Signal */: {
9938
9973
  const signal = target;
9939
9974
  const d = data;
9940
9975
  signal.$untrackedValue$ = d[0];
9941
9976
  signal.$effects$ = new Set(d.slice(1));
9942
9977
  break;
9943
9978
  }
9944
- case 24 /* TypeIds.WrappedSignal */: {
9979
+ case 23 /* TypeIds.WrappedSignal */: {
9945
9980
  const signal = target;
9946
9981
  const d = data;
9947
9982
  signal.$func$ = container.getSyncFn(d[0]);
@@ -9955,7 +9990,7 @@ const inflate = (container, target, typeId, data) => {
9955
9990
  inflateWrappedSignalValue(signal);
9956
9991
  break;
9957
9992
  }
9958
- case 26 /* TypeIds.AsyncSignal */: {
9993
+ case 25 /* TypeIds.AsyncSignal */: {
9959
9994
  const asyncSignal = target;
9960
9995
  const d = data;
9961
9996
  asyncSignal.$computeQrl$ = d[0];
@@ -9963,19 +9998,27 @@ const inflate = (container, target, typeId, data) => {
9963
9998
  asyncSignal.$effects$ = new Set(d[2]);
9964
9999
  asyncSignal.$loadingEffects$ = new Set(d[3]);
9965
10000
  asyncSignal.$errorEffects$ = new Set(d[4]);
9966
- asyncSignal.$untrackedLoading$ = d[5];
9967
- asyncSignal.$untrackedError$ = d[6];
9968
- const hasValue = d.length > 7;
10001
+ asyncSignal.$untrackedError$ = d[5];
10002
+ const hasValue = d.length > 6;
9969
10003
  if (hasValue) {
9970
- asyncSignal.$untrackedValue$ = d[7];
9971
- asyncSignal.$promiseValue$ = d[7];
10004
+ asyncSignal.$untrackedValue$ = d[6];
10005
+ }
10006
+ if (asyncSignal.$untrackedValue$ !== NEEDS_COMPUTATION) {
10007
+ // If we have a value after SSR, it will always be mean the signal was not invalid
10008
+ asyncSignal.$flags$ &= -2 /* SignalFlags.INVALID */;
10009
+ }
10010
+ // Note, we use the setter so that it schedules polling if needed
10011
+ asyncSignal.interval = d[7] ?? 0;
10012
+ asyncSignal.$concurrency$ = d[8] ?? 1;
10013
+ asyncSignal.$timeoutMs$ = d[9] ?? 0;
10014
+ if (d[10]) {
10015
+ asyncSignal.$flags$ |= 32 /* AsyncSignalFlags.EAGER_CLEANUP */;
9972
10016
  }
9973
- asyncSignal.$flags$ |= 1 /* SignalFlags.INVALID */;
9974
10017
  break;
9975
10018
  }
9976
10019
  // Inflating a SerializerSignal is the same as inflating a ComputedSignal
9977
- case 27 /* TypeIds.SerializerSignal */:
9978
- case 25 /* TypeIds.ComputedSignal */: {
10020
+ case 26 /* TypeIds.SerializerSignal */:
10021
+ case 24 /* TypeIds.ComputedSignal */: {
9979
10022
  const computed = target;
9980
10023
  const d = data;
9981
10024
  computed.$computeQrl$ = d[0];
@@ -9995,13 +10038,11 @@ const inflate = (container, target, typeId, data) => {
9995
10038
  const hasValue = d.length > 3;
9996
10039
  if (hasValue) {
9997
10040
  computed.$untrackedValue$ = d[3];
9998
- // The serialized signal is always invalid so it can recreate the custom object
9999
- if (typeId === 27 /* TypeIds.SerializerSignal */) {
10000
- computed.$flags$ |= 1 /* SignalFlags.INVALID */;
10001
- }
10002
10041
  }
10003
- else {
10004
- computed.$flags$ |= 1 /* SignalFlags.INVALID */;
10042
+ if (typeId !== 26 /* TypeIds.SerializerSignal */ && computed.$untrackedValue$ !== NEEDS_COMPUTATION) {
10043
+ // If we have a value after SSR, it will always be mean the signal was not invalid
10044
+ // The serialized signal is always left invalid so it can recreate the custom object
10045
+ computed.$flags$ &= -2 /* SignalFlags.INVALID */;
10005
10046
  }
10006
10047
  break;
10007
10048
  }
@@ -10013,7 +10054,7 @@ const inflate = (container, target, typeId, data) => {
10013
10054
  }
10014
10055
  break;
10015
10056
  }
10016
- case 29 /* TypeIds.FormData */: {
10057
+ case 28 /* TypeIds.FormData */: {
10017
10058
  const formData = target;
10018
10059
  const d = data;
10019
10060
  for (let i = 0; i < d.length; i++) {
@@ -10021,7 +10062,7 @@ const inflate = (container, target, typeId, data) => {
10021
10062
  }
10022
10063
  break;
10023
10064
  }
10024
- case 30 /* TypeIds.JSXNode */: {
10065
+ case 29 /* TypeIds.JSXNode */: {
10025
10066
  const jsx = target;
10026
10067
  const [type, key, varProps, constProps, children, toSort] = data;
10027
10068
  jsx.type = type;
@@ -10068,7 +10109,7 @@ const inflate = (container, target, typeId, data) => {
10068
10109
  bytes[i++] = s.charCodeAt(0);
10069
10110
  }
10070
10111
  break;
10071
- case 31 /* TypeIds.PropsProxy */:
10112
+ case 30 /* TypeIds.PropsProxy */:
10072
10113
  const propsProxy = target;
10073
10114
  const d = data;
10074
10115
  let owner = d[0];
@@ -10079,13 +10120,13 @@ const inflate = (container, target, typeId, data) => {
10079
10120
  propsProxy[_OWNER] = owner;
10080
10121
  propsProxy[_PROPS_HANDLER].$effects$ = d[3];
10081
10122
  break;
10082
- case 32 /* TypeIds.SubscriptionData */: {
10123
+ case 31 /* TypeIds.SubscriptionData */: {
10083
10124
  const effectData = target;
10084
10125
  effectData.data.$scopedStyleIdPrefix$ = data[0];
10085
10126
  effectData.data.$isConst$ = data[1];
10086
10127
  break;
10087
10128
  }
10088
- case 33 /* TypeIds.EffectSubscription */: {
10129
+ case 32 /* TypeIds.EffectSubscription */: {
10089
10130
  const effectSub = target;
10090
10131
  const d = data;
10091
10132
  effectSub.consumer = d[0];
@@ -10658,7 +10699,7 @@ class DomContainer extends _SharedContainer {
10658
10699
  const insertHost = vnode_isElementVNode(vHost) ? vHostParent || vHost : vHost;
10659
10700
  // If the host is different then we need to insert errored-host in the same position as the host.
10660
10701
  const insertBefore = insertHost === vHost ? null : vHostNextSibling;
10661
- vnode_insertBefore(journal, insertHost, vErrorDiv, insertBefore);
10702
+ vnode_insertElementBefore(journal, insertHost, vErrorDiv, insertBefore);
10662
10703
  };
10663
10704
  this.$renderPromise$ ? this.$renderPromise$.then(createErrorWrapper) : createErrorWrapper();
10664
10705
  }
@@ -10808,8 +10849,8 @@ const useTaskQrl = (qrl, opts) => {
10808
10849
  set(1);
10809
10850
  const taskFlags =
10810
10851
  // enabled by default
10811
- opts?.deferUpdates === false ? 0 : 16 /* TaskFlags.RENDER_BLOCKING */;
10812
- const task = new Task(8 /* TaskFlags.DIRTY */ | 2 /* TaskFlags.TASK */ | taskFlags, i, iCtx.$hostElement$, qrl, undefined, null);
10852
+ opts?.deferUpdates === false ? 0 : 8 /* TaskFlags.RENDER_BLOCKING */;
10853
+ const task = new Task(4 /* TaskFlags.DIRTY */ | 2 /* TaskFlags.TASK */ | taskFlags, i, iCtx.$hostElement$, qrl, undefined, null);
10813
10854
  // In V2 we add the task to the sequential scope. We need to do this
10814
10855
  // in order to be able to retrieve it later when the parent element is
10815
10856
  // deleted and we need to be able to release the task subscriptions.
@@ -10822,7 +10863,7 @@ const useTaskQrl = (qrl, opts) => {
10822
10863
  }
10823
10864
  };
10824
10865
  const runTask = (task, container, host) => {
10825
- task.$flags$ &= -9 /* TaskFlags.DIRTY */;
10866
+ task.$flags$ &= -5 /* TaskFlags.DIRTY */;
10826
10867
  cleanupDestroyable(task);
10827
10868
  const iCtx = newInvokeContext(container.$locale$, host, TaskEvent);
10828
10869
  iCtx.$container$ = container;
@@ -10873,7 +10914,7 @@ function scheduleTask(_event, element) {
10873
10914
  setCaptures(deserializeCaptures(container, this));
10874
10915
  }
10875
10916
  const task = _captures[0];
10876
- task.$flags$ |= 8 /* TaskFlags.DIRTY */;
10917
+ task.$flags$ |= 4 /* TaskFlags.DIRTY */;
10877
10918
  markVNodeDirty(container, task.$el$, 1 /* ChoreBits.TASKS */);
10878
10919
  }
10879
10920
 
@@ -10900,7 +10941,7 @@ const ensureContainsBackRef = (array, value) => {
10900
10941
  (array.backRef ||= new Set()).add(value);
10901
10942
  };
10902
10943
  const addQrlToSerializationCtx = (effectSubscriber, container) => {
10903
- if (container) {
10944
+ if (container?.serializationCtx) {
10904
10945
  const effect = effectSubscriber.consumer;
10905
10946
  const property = effectSubscriber.property;
10906
10947
  let qrl = null;
@@ -10926,7 +10967,7 @@ const scheduleEffects = (container, signal, effects) => {
10926
10967
  const property = effectSubscription.property;
10927
10968
  isDev && assertDefined(container, 'Container must be defined.');
10928
10969
  if (isTask(consumer)) {
10929
- consumer.$flags$ |= 8 /* TaskFlags.DIRTY */;
10970
+ consumer.$flags$ |= 4 /* TaskFlags.DIRTY */;
10930
10971
  markVNodeDirty(container, consumer.$el$, 1 /* ChoreBits.TASKS */);
10931
10972
  }
10932
10973
  else if (consumer instanceof SignalImpl) {
@@ -11605,14 +11646,11 @@ function preprocessState(data, container) {
11605
11646
  /**
11606
11647
  * Serialize data to string using SerializationContext.
11607
11648
  *
11608
- * @param data - Data to serialize
11609
11649
  * @internal
11610
11650
  */
11611
11651
  async function _serialize(data) {
11612
11652
  const serializationContext = createSerializationContext(null, null, () => '', () => '', () => { }, new WeakMap());
11613
- for (const root of data) {
11614
- serializationContext.$addRoot$(root);
11615
- }
11653
+ serializationContext.$addRoot$(data);
11616
11654
  await serializationContext.$serialize$();
11617
11655
  return serializationContext.$writer$.toString();
11618
11656
  }
@@ -11624,18 +11662,14 @@ async function _serialize(data) {
11624
11662
  */
11625
11663
  function _deserialize(rawStateData) {
11626
11664
  if (rawStateData == null) {
11627
- return [];
11665
+ throw new Error('No state data to deserialize');
11628
11666
  }
11629
11667
  const stateData = JSON.parse(rawStateData);
11630
- if (!Array.isArray(stateData)) {
11631
- return [];
11668
+ if (!Array.isArray(stateData) || stateData.length < 2 || typeof stateData[0] !== 'number') {
11669
+ throw new Error('Invalid state data');
11632
11670
  }
11633
11671
  const container = _createDeserializeContainer(stateData);
11634
- const output = [];
11635
- for (let i = 0; i < stateData.length; i += 2) {
11636
- output[i / 2] = deserializeData(container, stateData[i], stateData[i + 1]);
11637
- }
11638
- return output;
11672
+ return deserializeData(container, stateData[0], stateData[1]);
11639
11673
  }
11640
11674
  function getObjectById(id, stateData) {
11641
11675
  if (typeof id === 'string') {
@@ -11709,6 +11743,10 @@ const _verifySerializable = (value, seen, ctx, preMessage) => {
11709
11743
  });
11710
11744
  return value;
11711
11745
  }
11746
+ // We don't want to walk internal objects, assume we already checked the contents
11747
+ if (unwrapped.__brand) {
11748
+ return value;
11749
+ }
11712
11750
  if (isSerializableObject(unwrapped)) {
11713
11751
  for (const [key, item] of Object.entries(unwrapped)) {
11714
11752
  _verifySerializable(item, seen, ctx + '.' + key);
@@ -13166,8 +13204,8 @@ const useVisibleTaskQrl = (qrl, opts) => {
13166
13204
  const { val, set, i, iCtx } = useSequentialScope();
13167
13205
  const eagerness = opts?.strategy ?? 'intersection-observer';
13168
13206
  if (val) {
13169
- if (!(val.$flags$ & 64 /* TaskFlags.EVENTS_REGISTERED */) && !isServerPlatform()) {
13170
- val.$flags$ |= 64 /* TaskFlags.EVENTS_REGISTERED */;
13207
+ if (!(val.$flags$ & 32 /* TaskFlags.EVENTS_REGISTERED */) && !isServerPlatform()) {
13208
+ val.$flags$ |= 32 /* TaskFlags.EVENTS_REGISTERED */;
13171
13209
  useRegisterTaskEvents(val, eagerness);
13172
13210
  }
13173
13211
  return;
@@ -13176,7 +13214,7 @@ const useVisibleTaskQrl = (qrl, opts) => {
13176
13214
  let flags;
13177
13215
  if (!isServerPlatform()) {
13178
13216
  // In DOM we immediately execute
13179
- flags = 1 /* TaskFlags.VISIBLE_TASK */ | 8 /* TaskFlags.DIRTY */;
13217
+ flags = 1 /* TaskFlags.VISIBLE_TASK */ | 4 /* TaskFlags.DIRTY */;
13180
13218
  qrl.resolve();
13181
13219
  markVNodeDirty(iCtx.$container$, iCtx.$hostElement$, 1 /* ChoreBits.TASKS */);
13182
13220
  }
@@ -13222,48 +13260,16 @@ const getTaskHandlerQrl = (task) => {
13222
13260
  * Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
13223
13261
  * re-throw it (or a new Error), the resource status will never be `rejected`.
13224
13262
  *
13225
- * ### Example
13226
- *
13227
- * Example showing how `useResource` to perform a fetch to request the weather, whenever the input
13228
- * city name changes.
13229
- *
13230
- * ```tsx
13231
- * const Cmp = component$(() => {
13232
- * const cityS = useSignal('');
13233
- *
13234
- * const weatherResource = useResource$(async ({ track, cleanup }) => {
13235
- * const cityName = track(cityS);
13236
- * const abortController = new AbortController();
13237
- * cleanup(() => abortController.abort('cleanup'));
13238
- * const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
13239
- * signal: abortController.signal,
13240
- * });
13241
- * const data = await res.json();
13242
- * return data as { temp: number };
13243
- * });
13244
- *
13245
- * return (
13246
- * <div>
13247
- * <input name="city" bind:value={cityS} />
13248
- * <Resource
13249
- * value={weatherResource}
13250
- * onResolved={(weather) => {
13251
- * return <div>Temperature: {weather.temp}</div>;
13252
- * }}
13253
- * />
13254
- * </div>
13255
- * );
13256
- * });
13257
- * ```
13258
- *
13263
+ * @deprecated Use `useAsync$` instead, which is more powerful and flexible. `useResource$` is still
13264
+ * available for backward compatibility but it is recommended to migrate to `useAsync$` for new
13265
+ * code and when updating existing code.
13259
13266
  * @public
13267
+ * @see useAsync$
13260
13268
  * @see Resource
13261
13269
  * @see ResourceReturn
13262
13270
  */
13263
13271
  // </docs>
13264
- const useResource$ = (generatorFn, opts) => {
13265
- return useResourceQrl(dollar(generatorFn), opts);
13266
- };
13272
+ const useResource$ = implicit$FirstArg(useResourceQrl);
13267
13273
 
13268
13274
  // <docs markdown="../readme.md#useTask">
13269
13275
  // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
@@ -13495,5 +13501,5 @@ if (import.meta.hot) {
13495
13501
  });
13496
13502
  }
13497
13503
 
13498
- export { $, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _captures, _chk, _deserialize, _dumpState, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, _regSymbol, _resolveContextWithoutSequentialScope, _restProps, _run, _serialize, scheduleTask as _task, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsync$, createAsyncSignal as createAsyncQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsync$, useAsyncQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
13504
+ export { $, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _captures, _chk, createQRL as _createQRL, _deserialize, _dumpState, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, qrlToString as _qrlToString, _regSymbol, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, scheduleTask as _task, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsync$, createAsyncSignal as createAsyncQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsync$, useAsyncQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
13499
13505
  //# sourceMappingURL=core.mjs.map