@qwik.dev/core 2.0.0-beta.7 → 2.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/bindings/qwik.darwin-arm64.node +0 -0
  2. package/bindings/qwik.darwin-x64.node +0 -0
  3. package/bindings/qwik.linux-x64-gnu.node +0 -0
  4. package/bindings/qwik.win32-x64-msvc.node +0 -0
  5. package/bindings/qwik_wasm_bg.wasm +0 -0
  6. package/dist/backpatch/index.cjs +6 -0
  7. package/dist/backpatch/index.d.ts +2 -0
  8. package/dist/backpatch/index.mjs +5 -0
  9. package/dist/backpatch/package.json +8 -0
  10. package/dist/backpatch-executor.debug.js +34 -0
  11. package/dist/backpatch-executor.js +1 -0
  12. package/dist/build/package.json +1 -1
  13. package/dist/cli.cjs +17 -17
  14. package/dist/core-internal.d.ts +112 -56
  15. package/dist/core.cjs +1022 -469
  16. package/dist/core.cjs.map +1 -1
  17. package/dist/core.min.mjs +1 -1
  18. package/dist/core.mjs +1018 -469
  19. package/dist/core.mjs.map +1 -1
  20. package/dist/core.prod.cjs +654 -361
  21. package/dist/core.prod.mjs +729 -373
  22. package/dist/loader/index.cjs +2 -2
  23. package/dist/loader/index.mjs +2 -2
  24. package/dist/loader/package.json +1 -1
  25. package/dist/optimizer.cjs +78 -76
  26. package/dist/optimizer.mjs +78 -78
  27. package/dist/qwikloader.debug.js +0 -13
  28. package/dist/qwikloader.js +1 -1
  29. package/dist/server.cjs +217 -63
  30. package/dist/server.d.ts +9 -0
  31. package/dist/server.mjs +213 -63
  32. package/dist/starters/features/auth/package.json +1 -1
  33. package/dist/starters/features/localize/package.json +3 -3
  34. package/dist/starters/features/pandacss/package.json +1 -1
  35. package/dist/starters/features/playwright/playwright-report/index.html +943 -903
  36. package/dist/starters/features/postcss/postcss.config.js +1 -1
  37. package/dist/starters/features/tailwind/package.json +2 -2
  38. package/dist/starters/features/tailwind/prettier.config.js +10 -0
  39. package/dist/starters/features/tailwind-v3/package.json +1 -1
  40. package/dist/starters/features/tailwind-v3/prettier.config.js +10 -0
  41. package/dist/testing/index.cjs +3826 -952
  42. package/dist/testing/index.d.ts +972 -1
  43. package/dist/testing/index.mjs +3811 -946
  44. package/dist/testing/package.json +1 -1
  45. package/package.json +8 -6
  46. package/dist/starters/features/tailwind/.prettierrc.js +0 -3
package/dist/core.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * @qwik.dev/core 2.0.0-beta.7-dev+2dd89a6
3
+ * @qwik.dev/core 2.0.0-beta.9-dev+6b582c7
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
@@ -9,6 +9,13 @@ import { isDev, isServer, isBrowser } from '@qwik.dev/core/build';
9
9
  export { isBrowser, isDev, isServer } from '@qwik.dev/core/build';
10
10
  import { p } from '@qwik.dev/core/preloader';
11
11
 
12
+ /**
13
+ * QWIK_VERSION
14
+ *
15
+ * @public
16
+ */
17
+ const version = "2.0.0-beta.9-dev+6b582c7";
18
+
12
19
  // same as isDev but separate so we can test
13
20
  const qDev = globalThis.qDev !== false;
14
21
  const qInspector = globalThis.qInspector === true;
@@ -86,6 +93,9 @@ const isArray = (v) => {
86
93
  const isString = (v) => {
87
94
  return typeof v === 'string';
88
95
  };
96
+ const isNumber$1 = (v) => {
97
+ return typeof v === 'number';
98
+ };
89
99
  const isFunction = (v) => {
90
100
  return typeof v === 'function';
91
101
  };
@@ -288,13 +298,6 @@ const createPlatform = () => {
288
298
  });
289
299
  });
290
300
  },
291
- nextTick: (fn) => {
292
- return new Promise((resolve) => {
293
- setTimeout(() => {
294
- resolve(fn());
295
- });
296
- });
297
- },
298
301
  chunkForSymbol(symbolName, chunk) {
299
302
  return [symbolName, chunk ?? '_'];
300
303
  },
@@ -552,6 +555,13 @@ class SignalImpl {
552
555
  this.$container$ = container;
553
556
  this.$untrackedValue$ = value;
554
557
  }
558
+ /**
559
+ * Use this to force running subscribers, for example when the calculated value has mutated but
560
+ * remained the same object
561
+ */
562
+ force() {
563
+ this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
564
+ }
555
565
  get untrackedValue() {
556
566
  return this.$untrackedValue$;
557
567
  }
@@ -565,14 +575,7 @@ class SignalImpl {
565
575
  set value(value) {
566
576
  if (value !== this.$untrackedValue$) {
567
577
  this.$untrackedValue$ = value;
568
- // TODO: move this to the scheduler
569
- triggerEffects(this.$container$, this, this.$effects$);
570
- // this.$container$?.$scheduler$(
571
- // ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
572
- // null,
573
- // this,
574
- // this.$effects$
575
- // );
578
+ this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
576
579
  }
577
580
  }
578
581
  // prevent accidental use as value
@@ -634,12 +637,11 @@ class WrappedSignalImpl extends SignalImpl {
634
637
  $funcStr$;
635
638
  $flags$;
636
639
  $hostElement$ = null;
637
- $forceRunEffects$ = false;
638
640
  [_EFFECT_BACK_REF] = null;
639
641
  constructor(container, fn, args, fnStr,
640
642
  // We need a separate flag to know when the computation needs running because
641
643
  // we need the old value to know if effects need running after computation
642
- flags = 1 /* SignalFlags.INVALID */ | 2 /* WrappedSignalFlags.UNWRAP */) {
644
+ flags = 1 /* SignalFlags.INVALID */ | 4 /* WrappedSignalFlags.UNWRAP */) {
643
645
  super(container, NEEDS_COMPUTATION);
644
646
  this.$args$ = args;
645
647
  this.$func$ = fn;
@@ -648,7 +650,6 @@ class WrappedSignalImpl extends SignalImpl {
648
650
  }
649
651
  invalidate() {
650
652
  this.$flags$ |= 1 /* SignalFlags.INVALID */;
651
- this.$forceRunEffects$ = false;
652
653
  this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
653
654
  }
654
655
  /**
@@ -656,29 +657,26 @@ class WrappedSignalImpl extends SignalImpl {
656
657
  * remained the same object.
657
658
  */
658
659
  force() {
659
- this.$forceRunEffects$ = true;
660
+ this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
660
661
  this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
661
662
  }
662
663
  get untrackedValue() {
663
- const didChange = this.$computeIfNeeded$();
664
- if (didChange) {
665
- this.$forceRunEffects$ = didChange;
666
- }
664
+ this.$computeIfNeeded$();
667
665
  assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
668
666
  return this.$untrackedValue$;
669
667
  }
670
668
  $computeIfNeeded$() {
671
669
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
672
- return false;
670
+ return;
673
671
  }
674
672
  const untrackedValue = trackSignal(() => this.$func$(...this.$args$), this, "." /* EffectProperty.VNODE */, this.$container$);
675
- // TODO: we should remove invalid flag here
673
+ // TODO: we should remove invalid flag here, but some tests are failing
676
674
  // this.$flags$ &= ~SignalFlags.INVALID;
677
675
  const didChange = untrackedValue !== this.$untrackedValue$;
678
676
  if (didChange) {
677
+ this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
679
678
  this.$untrackedValue$ = untrackedValue;
680
679
  }
681
- return didChange;
682
680
  }
683
681
  // Make this signal read-only
684
682
  set value(_) {
@@ -873,12 +871,26 @@ const _jsxBranch = (input) => {
873
871
  };
874
872
  /** @internal */
875
873
  const _waitUntilRendered = (elm) => {
876
- const containerEl = _getQContainerElement(elm);
877
- if (!containerEl) {
874
+ const container = _getQContainerElement(elm)?.qContainer;
875
+ if (!container) {
878
876
  return Promise.resolve();
879
877
  }
880
- const container = containerEl.qContainer;
881
- return container?.renderDone ?? Promise.resolve();
878
+ // Multi-cycle idle: loop WAIT_FOR_QUEUE until the flush epoch stays stable
879
+ // across an extra microtask, which signals that no new work re-scheduled.
880
+ return (async () => {
881
+ for (;;) {
882
+ await container.$scheduler$(255 /* ChoreType.WAIT_FOR_QUEUE */).$returnValue$;
883
+ const firstEpoch = container.$flushEpoch$ || 0;
884
+ // Give a microtask for any immediate follow-up scheduling to enqueue
885
+ await Promise.resolve();
886
+ const secondEpoch = container.$flushEpoch$ || 0;
887
+ // If no epoch change occurred during and after WAIT_FOR_QUEUE, we are idle.
888
+ if (firstEpoch === secondEpoch) {
889
+ return;
890
+ }
891
+ // Continue loop if epoch advanced, meaning more work flushed.
892
+ }
893
+ })();
882
894
  };
883
895
 
884
896
  /**
@@ -956,7 +968,7 @@ function jsxEventToHtmlAttribute(jsxEvent) {
956
968
  }
957
969
  return null; // Return null if not matching expected format
958
970
  }
959
- function eventNameToJsxEvent(eventName, prefix, startIdx = 0) {
971
+ function eventNameToJsxEvent(eventName, prefix) {
960
972
  eventName = eventName.charAt(0).toUpperCase() + eventName.substring(1);
961
973
  return prefix + eventName + EVENT_SUFFIX;
962
974
  }
@@ -1245,13 +1257,6 @@ const isRecoverable = (err) => {
1245
1257
  return true;
1246
1258
  };
1247
1259
 
1248
- /**
1249
- * QWIK_VERSION
1250
- *
1251
- * @public
1252
- */
1253
- const version = "2.0.0-beta.7-dev+2dd89a6";
1254
-
1255
1260
  /** @internal */
1256
1261
  const EMPTY_ARRAY = [];
1257
1262
  const EMPTY_OBJ = {};
@@ -1392,7 +1397,7 @@ const useLexicalScope = () => {
1392
1397
  *
1393
1398
  * @internal
1394
1399
  */
1395
- const queueQRL = (...args) => {
1400
+ const _run = (...args) => {
1396
1401
  // This will already check container
1397
1402
  const [runQrl] = useLexicalScope();
1398
1403
  const context = getInvokeContext();
@@ -1406,7 +1411,9 @@ const queueQRL = (...args) => {
1406
1411
  if (!scheduler) {
1407
1412
  throw qError(1 /* QError.schedulerNotFound */);
1408
1413
  }
1409
- return scheduler(2 /* ChoreType.RUN_QRL */, hostElement, runQrl, args);
1414
+ // We don't return anything, the scheduler is in charge now
1415
+ const chore = scheduler(2 /* ChoreType.RUN_QRL */, hostElement, runQrl, args);
1416
+ return getChorePromise(chore);
1410
1417
  };
1411
1418
 
1412
1419
  /** @internal */
@@ -1430,17 +1437,17 @@ const mapApp_findIndx = (array, key, start) => {
1430
1437
  return (bottom << 1) ^ -1;
1431
1438
  };
1432
1439
  /** @internal */
1433
- const mapArray_set = (array, key, value, start) => {
1440
+ const mapArray_set = (array, key, value, start, allowNullValue = false) => {
1434
1441
  const indx = mapApp_findIndx(array, key, start);
1435
1442
  if (indx >= 0) {
1436
- if (value == null) {
1443
+ if (value == null && !allowNullValue) {
1437
1444
  array.splice(indx, 2);
1438
1445
  }
1439
1446
  else {
1440
1447
  array[indx + 1] = value;
1441
1448
  }
1442
1449
  }
1443
- else if (value != null) {
1450
+ else if (value != null || allowNullValue) {
1444
1451
  array.splice(indx ^ -1, 0, key, value);
1445
1452
  }
1446
1453
  };
@@ -1454,6 +1461,9 @@ const mapArray_get = (array, key, start) => {
1454
1461
  return null;
1455
1462
  }
1456
1463
  };
1464
+ const mapArray_has = (array, key, start) => {
1465
+ return mapApp_findIndx(array, key, start) >= 0;
1466
+ };
1457
1467
 
1458
1468
  /** @internal */
1459
1469
  const _CONST_PROPS = Symbol('CONST');
@@ -1527,13 +1537,12 @@ class ComputedSignalImpl extends SignalImpl {
1527
1537
  */
1528
1538
  $computeQrl$;
1529
1539
  $flags$;
1530
- $forceRunEffects$ = false;
1531
1540
  [_EFFECT_BACK_REF] = null;
1532
1541
  constructor(container, fn,
1533
1542
  // We need a separate flag to know when the computation needs running because
1534
1543
  // we need the old value to know if effects need running after computation
1535
1544
  flags = 1 /* SignalFlags.INVALID */ |
1536
- 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */) {
1545
+ 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */) {
1537
1546
  // The value is used for comparison when signals trigger, which can only happen
1538
1547
  // when it was calculated before. Therefore we can pass whatever we like.
1539
1548
  super(container, NEEDS_COMPUTATION);
@@ -1542,7 +1551,6 @@ class ComputedSignalImpl extends SignalImpl {
1542
1551
  }
1543
1552
  invalidate() {
1544
1553
  this.$flags$ |= 1 /* SignalFlags.INVALID */;
1545
- this.$forceRunEffects$ = false;
1546
1554
  this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
1547
1555
  }
1548
1556
  /**
@@ -1550,20 +1558,17 @@ class ComputedSignalImpl extends SignalImpl {
1550
1558
  * remained the same object
1551
1559
  */
1552
1560
  force() {
1553
- this.$forceRunEffects$ = true;
1554
- this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
1561
+ this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1562
+ super.force();
1555
1563
  }
1556
1564
  get untrackedValue() {
1557
- const didChange = this.$computeIfNeeded$();
1558
- if (didChange) {
1559
- this.$forceRunEffects$ = didChange;
1560
- }
1565
+ this.$computeIfNeeded$();
1561
1566
  assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
1562
1567
  return this.$untrackedValue$;
1563
1568
  }
1564
1569
  $computeIfNeeded$() {
1565
1570
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1566
- return false;
1571
+ return;
1567
1572
  }
1568
1573
  const computeQrl = this.$computeQrl$;
1569
1574
  throwIfQRLNotResolved(computeQrl);
@@ -1582,9 +1587,12 @@ class ComputedSignalImpl extends SignalImpl {
1582
1587
  this.$flags$ &= ~1 /* SignalFlags.INVALID */;
1583
1588
  const didChange = untrackedValue !== this.$untrackedValue$;
1584
1589
  if (didChange) {
1590
+ // skip first computation when value is not changed
1591
+ if (this.$untrackedValue$ !== NEEDS_COMPUTATION) {
1592
+ this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1593
+ }
1585
1594
  this.$untrackedValue$ = untrackedValue;
1586
1595
  }
1587
- return didChange;
1588
1596
  }
1589
1597
  finally {
1590
1598
  if (ctx) {
@@ -1610,12 +1618,12 @@ class ComputedSignalImpl extends SignalImpl {
1610
1618
  */
1611
1619
  class SerializerSignalImpl extends ComputedSignalImpl {
1612
1620
  constructor(container, argQrl) {
1613
- super(container, argQrl, 1 /* SignalFlags.INVALID */ | 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */);
1621
+ super(container, argQrl, 1 /* SignalFlags.INVALID */ | 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */);
1614
1622
  }
1615
1623
  $didInitialize$ = false;
1616
1624
  $computeIfNeeded$() {
1617
1625
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1618
- return false;
1626
+ return;
1619
1627
  }
1620
1628
  throwIfQRLNotResolved(this.$computeQrl$);
1621
1629
  let arg = this.$computeQrl$.resolved;
@@ -1633,9 +1641,9 @@ class SerializerSignalImpl extends ComputedSignalImpl {
1633
1641
  this.$flags$ &= -2 /* SignalFlags.INVALID */;
1634
1642
  this.$didInitialize$ = true;
1635
1643
  if (didChange) {
1644
+ this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1636
1645
  this.$untrackedValue$ = untrackedValue;
1637
1646
  }
1638
- return didChange;
1639
1647
  }
1640
1648
  }
1641
1649
 
@@ -1645,6 +1653,28 @@ const getStoreHandler = (value) => {
1645
1653
  const getStoreTarget = (value) => {
1646
1654
  return value?.[STORE_TARGET] || null;
1647
1655
  };
1656
+ /**
1657
+ * Force a store to recompute and schedule effects.
1658
+ *
1659
+ * @public
1660
+ */
1661
+ const forceStoreEffects = (value, prop) => {
1662
+ const handler = getStoreHandler(value);
1663
+ if (handler) {
1664
+ handler.force(prop);
1665
+ }
1666
+ };
1667
+ /**
1668
+ * @returns True if the store has effects for the given prop
1669
+ * @internal
1670
+ */
1671
+ const _hasStoreEffects = (value, prop) => {
1672
+ const handler = getStoreHandler(value);
1673
+ if (handler) {
1674
+ return (handler.$effects$?.get(prop)?.size ?? 0) > 0;
1675
+ }
1676
+ return false;
1677
+ };
1648
1678
  /**
1649
1679
  * Get the original object that was wrapped by the store. Useful if you want to clone a store
1650
1680
  * (structuredClone, IndexedDB,...)
@@ -1683,7 +1713,12 @@ class StoreHandler {
1683
1713
  toString() {
1684
1714
  return '[Store]';
1685
1715
  }
1716
+ force(prop) {
1717
+ const target = getStoreTarget(this);
1718
+ this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, getEffects(target, prop, this.$effects$));
1719
+ }
1686
1720
  get(target, prop) {
1721
+ // TODO(perf): handle better `slice` calls
1687
1722
  if (typeof prop === 'symbol') {
1688
1723
  if (prop === STORE_TARGET) {
1689
1724
  return target;
@@ -1746,7 +1781,11 @@ class StoreHandler {
1746
1781
  if (typeof prop != 'string' || !delete target[prop]) {
1747
1782
  return false;
1748
1783
  }
1749
- triggerEffects(this.$container$, this, getEffects(target, prop, this.$effects$));
1784
+ if (!Array.isArray(target)) {
1785
+ // If the target is an array, we don't need to trigger effects.
1786
+ // Changing the length property will trigger effects.
1787
+ this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, getEffects(target, prop, this.$effects$));
1788
+ }
1750
1789
  return true;
1751
1790
  }
1752
1791
  has(target, prop) {
@@ -1805,8 +1844,10 @@ function addStoreEffect(target, prop, store, effectSubscription) {
1805
1844
  }
1806
1845
  function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
1807
1846
  target[prop] = value;
1808
- // TODO: trigger effects through the scheduler
1809
- triggerEffects(currentStore.$container$, currentStore, getEffects(target, prop, currentStore.$effects$));
1847
+ const effects = getEffects(target, prop, currentStore.$effects$);
1848
+ if (effects) {
1849
+ currentStore.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, currentStore, effects);
1850
+ }
1810
1851
  }
1811
1852
  function getEffects(target, prop, storeEffects) {
1812
1853
  let effectsToTrigger;
@@ -1934,7 +1975,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
1934
1975
  }
1935
1976
  $computeIfNeeded$() {
1936
1977
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1937
- return false;
1978
+ return;
1938
1979
  }
1939
1980
  const computeQrl = this.$computeQrl$;
1940
1981
  throwIfQRLNotResolved(computeQrl);
@@ -1964,6 +2005,7 @@ class AsyncComputedSignalImpl extends ComputedSignalImpl {
1964
2005
  this.$flags$ &= -2 /* SignalFlags.INVALID */;
1965
2006
  const didChange = untrackedValue !== this.$untrackedValue$;
1966
2007
  if (didChange) {
2008
+ this.$flags$ |= 2 /* SignalFlags.RUN_EFFECTS */;
1967
2009
  this.$untrackedValue$ = untrackedValue;
1968
2010
  }
1969
2011
  return didChange;
@@ -2051,7 +2093,7 @@ const _wrapProp = (...args) => {
2051
2093
  if (!(obj instanceof AsyncComputedSignalImpl)) {
2052
2094
  assertEqual(prop, 'value', 'Left side is a signal, prop must be value');
2053
2095
  }
2054
- if (obj instanceof WrappedSignalImpl && obj.flags & 2 /* WrappedSignalFlags.UNWRAP */) {
2096
+ if (obj instanceof WrappedSignalImpl && obj.flags & 4 /* WrappedSignalFlags.UNWRAP */) {
2055
2097
  return obj;
2056
2098
  }
2057
2099
  return getWrapped(args);
@@ -2112,7 +2154,7 @@ function isSlotProp(prop) {
2112
2154
  return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
2113
2155
  }
2114
2156
  /** @internal */
2115
- const _restProps = (props, omit, target = {}) => {
2157
+ const _restProps = (props, omit = [], target = {}) => {
2116
2158
  let constPropsTarget = null;
2117
2159
  const constProps = props[_CONST_PROPS];
2118
2160
  if (constProps) {
@@ -2567,12 +2609,12 @@ function addUseOnEvents(jsx, useOnEvents) {
2567
2609
  }
2568
2610
  if (targetElement) {
2569
2611
  if (targetElement.type === 'script' && key === qVisibleEvent) {
2570
- eventKey = 'document:onQinit$';
2612
+ eventKey = 'document:onQInit$';
2571
2613
  logWarn('You are trying to add an event "' +
2572
2614
  key +
2573
2615
  '" using `useVisibleTask$` hook, ' +
2574
2616
  'but a node to which you can add an event is not found. ' +
2575
- 'Using document:onQinit$ instead.');
2617
+ 'Using document:onQInit$ instead.');
2576
2618
  }
2577
2619
  addUseOnEvent(targetElement, eventKey, useOnEvents[key]);
2578
2620
  }
@@ -2695,13 +2737,13 @@ const applyQwikComponentBody = (ssr, jsx, component) => {
2695
2737
  if (srcProps && srcProps.children) {
2696
2738
  delete srcProps.children;
2697
2739
  }
2698
- const scheduler = ssr.$scheduler$;
2699
2740
  host.setProp(OnRenderProp, componentQrl);
2700
2741
  host.setProp(ELEMENT_PROPS, srcProps);
2701
2742
  if (jsx.key !== null) {
2702
2743
  host.setProp(ELEMENT_KEY, jsx.key);
2703
2744
  }
2704
- return scheduler(6 /* ChoreType.COMPONENT */, host, componentQrl, srcProps);
2745
+ const componentChore = ssr.$scheduler$(6 /* ChoreType.COMPONENT */, host, componentQrl, srcProps);
2746
+ return getChorePromise(componentChore);
2705
2747
  };
2706
2748
 
2707
2749
  class ParentComponentData {
@@ -2809,7 +2851,14 @@ function processJSXNode(ssr, enqueue, value, options) {
2809
2851
  appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue);
2810
2852
  }
2811
2853
  }
2812
- const innerHTML = ssr.openElement(type, varPropsToSsrAttrs(jsx.varProps, jsx.constProps, ssr.serializationCtx, options.styleScoped, jsx.key), constPropsToSsrAttrs(jsx.constProps, jsx.varProps, ssr.serializationCtx, options.styleScoped), qwikInspectorAttrValue);
2854
+ const innerHTML = ssr.openElement(type, varPropsToSsrAttrs(jsx.varProps, jsx.constProps, {
2855
+ serializationCtx: ssr.serializationCtx,
2856
+ styleScopedId: options.styleScoped,
2857
+ key: jsx.key,
2858
+ }), constPropsToSsrAttrs(jsx.constProps, jsx.varProps, {
2859
+ serializationCtx: ssr.serializationCtx,
2860
+ styleScopedId: options.styleScoped,
2861
+ }), qwikInspectorAttrValue);
2813
2862
  if (innerHTML) {
2814
2863
  ssr.htmlNode(innerHTML);
2815
2864
  }
@@ -2925,16 +2974,17 @@ function processJSXNode(ssr, enqueue, value, options) {
2925
2974
  }
2926
2975
  }
2927
2976
  }
2928
- function varPropsToSsrAttrs(varProps, constProps, serializationCtx, styleScopedId, key) {
2929
- return toSsrAttrs(varProps, constProps, serializationCtx, true, styleScopedId, key);
2977
+ function varPropsToSsrAttrs(varProps, constProps, options) {
2978
+ return toSsrAttrs(varProps, constProps, false, options);
2930
2979
  }
2931
- function constPropsToSsrAttrs(constProps, varProps, serializationCtx, styleScopedId) {
2932
- return toSsrAttrs(constProps, varProps, serializationCtx, false, styleScopedId);
2980
+ function constPropsToSsrAttrs(constProps, varProps, options) {
2981
+ return toSsrAttrs(constProps, varProps, true, options);
2933
2982
  }
2934
- function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProps, styleScopedId, key) {
2983
+ function toSsrAttrs(record, anotherRecord, isConst, options) {
2935
2984
  if (record == null) {
2936
2985
  return null;
2937
2986
  }
2987
+ const pushMergedEventProps = !isConst;
2938
2988
  const ssrAttrs = [];
2939
2989
  for (const key in record) {
2940
2990
  let value = record[key];
@@ -2971,7 +3021,7 @@ function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProp
2971
3021
  }
2972
3022
  }
2973
3023
  }
2974
- const eventValue = setEvent(serializationCtx, key, value);
3024
+ const eventValue = setEvent(options.serializationCtx, key, value);
2975
3025
  if (eventValue) {
2976
3026
  ssrAttrs.push(jsxEventToHtmlAttribute(key), eventValue);
2977
3027
  }
@@ -2981,7 +3031,7 @@ function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProp
2981
3031
  // write signal as is. We will track this signal inside `writeAttrs`
2982
3032
  if (isClassAttr(key)) {
2983
3033
  // additionally append styleScopedId for class attr
2984
- ssrAttrs.push(key, [value, styleScopedId]);
3034
+ ssrAttrs.push(key, [value, options.styleScopedId]);
2985
3035
  }
2986
3036
  else {
2987
3037
  ssrAttrs.push(key, value);
@@ -2989,13 +3039,13 @@ function toSsrAttrs(record, anotherRecord, serializationCtx, pushMergedEventProp
2989
3039
  continue;
2990
3040
  }
2991
3041
  if (isPreventDefault(key)) {
2992
- addPreventDefaultEventToSerializationContext(serializationCtx, key);
3042
+ addPreventDefaultEventToSerializationContext(options.serializationCtx, key);
2993
3043
  }
2994
- value = serializeAttribute(key, value, styleScopedId);
3044
+ value = serializeAttribute(key, value, options.styleScopedId);
2995
3045
  ssrAttrs.push(key, value);
2996
3046
  }
2997
- if (key != null) {
2998
- ssrAttrs.push(ELEMENT_KEY, key);
3047
+ if (options.key != null) {
3048
+ ssrAttrs.push(ELEMENT_KEY, options.key);
2999
3049
  }
3000
3050
  return ssrAttrs;
3001
3051
  }
@@ -3044,7 +3094,7 @@ function setEvent(serializationCtx, key, rawValue) {
3044
3094
  * For internal qrls (starting with `_`) we assume that they do the right thing.
3045
3095
  */
3046
3096
  if (!qrl.$symbol$.startsWith('_') && (qrl.$captureRef$ || qrl.$capture$)) {
3047
- qrl = createQRL(null, '_run', queueQRL, null, null, [qrl]);
3097
+ qrl = createQRL(null, '_run', _run, null, null, [qrl]);
3048
3098
  }
3049
3099
  return qrlToString(serializationCtx, qrl);
3050
3100
  };
@@ -3124,10 +3174,9 @@ const useTaskQrl = (qrl) => {
3124
3174
  // deleted and we need to be able to release the task subscriptions.
3125
3175
  set(task);
3126
3176
  const container = iCtx.$container$;
3127
- const promise = container.$scheduler$(3 /* ChoreType.TASK */, task);
3128
- if (isPromise(promise)) {
3129
- // TODO: should we handle this differently?
3130
- promise.catch(() => { });
3177
+ const result = runTask(task, container, iCtx.$hostElement$);
3178
+ if (isPromise(result)) {
3179
+ throw result;
3131
3180
  }
3132
3181
  };
3133
3182
  const runTask = (task, container, host) => {
@@ -3139,7 +3188,7 @@ const runTask = (task, container, host) => {
3139
3188
  const track = trackFn(task, container);
3140
3189
  const [cleanup] = cleanupFn(task, (reason) => container.handleError(reason, host));
3141
3190
  const taskApi = { track, cleanup };
3142
- const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
3191
+ return safeCall(() => taskFn(taskApi), cleanup, (err) => {
3143
3192
  // If a Promise is thrown, that means we need to re-run the task.
3144
3193
  if (isPromise(err)) {
3145
3194
  return err.then(() => runTask(task, container, host));
@@ -3148,7 +3197,6 @@ const runTask = (task, container, host) => {
3148
3197
  throw err;
3149
3198
  }
3150
3199
  });
3151
- return result;
3152
3200
  };
3153
3201
  const cleanupTask = (task) => {
3154
3202
  const destroy = task.$destroy$;
@@ -3190,7 +3238,7 @@ const isTask = (value) => {
3190
3238
  */
3191
3239
  const scheduleTask = (_event, element) => {
3192
3240
  const [task] = useLexicalScope();
3193
- const type = task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */ ? 32 /* ChoreType.VISIBLE */ : 3 /* ChoreType.TASK */;
3241
+ const type = task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */ ? 16 /* ChoreType.VISIBLE */ : 3 /* ChoreType.TASK */;
3194
3242
  const container = getDomContainer(element);
3195
3243
  container.$scheduler$(type, task);
3196
3244
  };
@@ -3442,7 +3490,7 @@ class PropsProxyHandler {
3442
3490
  ? this.$constProps$[prop]
3443
3491
  : this.$varProps$[prop];
3444
3492
  // a proxied value that the optimizer made
3445
- return value instanceof WrappedSignalImpl && value.$flags$ & 2 /* WrappedSignalFlags.UNWRAP */
3493
+ return value instanceof WrappedSignalImpl && value.$flags$ & 4 /* WrappedSignalFlags.UNWRAP */
3446
3494
  ? value.value
3447
3495
  : value;
3448
3496
  }
@@ -3518,6 +3566,24 @@ class PropsProxyHandler {
3518
3566
  const directGetPropsProxyProp = (jsx, prop) => {
3519
3567
  return (jsx.constProps && prop in jsx.constProps ? jsx.constProps[prop] : jsx.varProps[prop]);
3520
3568
  };
3569
+ /** @internal */
3570
+ const _getVarProps = (props) => {
3571
+ if (!props) {
3572
+ return null;
3573
+ }
3574
+ return _VAR_PROPS in props
3575
+ ? 'children' in props
3576
+ ? { ...props[_VAR_PROPS], children: props.children }
3577
+ : props[_VAR_PROPS]
3578
+ : props;
3579
+ };
3580
+ /** @internal */
3581
+ const _getConstProps = (props) => {
3582
+ if (!props) {
3583
+ return null;
3584
+ }
3585
+ return _CONST_PROPS in props ? props[_CONST_PROPS] : null;
3586
+ };
3521
3587
 
3522
3588
  const isForeignObjectElement = (elementName) => {
3523
3589
  return isDev ? elementName.toLowerCase() === 'foreignobject' : elementName === 'foreignObject';
@@ -3838,6 +3904,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
3838
3904
  vNewNode = null;
3839
3905
  vCurrent = vnode_getFirstChild(vStartNode);
3840
3906
  stackPush(jsxNode, true);
3907
+ if (vParent[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */) {
3908
+ // Ignore diff if the parent is deleted.
3909
+ return;
3910
+ }
3841
3911
  while (stack.length) {
3842
3912
  while (jsxIdx < jsxCount) {
3843
3913
  assertFalse(vParent === vCurrent, "Parent and current can't be the same");
@@ -4266,8 +4336,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
4266
4336
  value = trackSignalAndAssignHost(value, vNewNode, key, container, signalData);
4267
4337
  }
4268
4338
  if (key === dangerouslySetInnerHTML) {
4269
- element.innerHTML = value;
4270
- element.setAttribute(QContainerAttr, "html" /* QContainerValue.HTML */);
4339
+ if (value) {
4340
+ element.innerHTML = String(value);
4341
+ element.setAttribute(QContainerAttr, "html" /* QContainerValue.HTML */);
4342
+ }
4271
4343
  continue;
4272
4344
  }
4273
4345
  if (elementName === 'textarea' && key === 'value') {
@@ -4368,8 +4440,13 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
4368
4440
  let returnValue = false;
4369
4441
  qrls.flat(2).forEach((qrl) => {
4370
4442
  if (qrl) {
4371
- const value = container.$scheduler$(2 /* ChoreType.RUN_QRL */, vNode, qrl, [event, element]);
4372
- returnValue = returnValue || value === true;
4443
+ if (isSyncQrl(qrl)) {
4444
+ qrl(event, element);
4445
+ }
4446
+ else {
4447
+ const value = container.$scheduler$(2 /* ChoreType.RUN_QRL */, vNode, qrl, [event, element]);
4448
+ returnValue = returnValue || value === true;
4449
+ }
4373
4450
  }
4374
4451
  });
4375
4452
  return returnValue;
@@ -4871,7 +4948,7 @@ function cleanup(container, vNode) {
4871
4948
  const task = obj;
4872
4949
  clearAllEffects(container, task);
4873
4950
  if (task.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
4874
- container.$scheduler$(48 /* ChoreType.CLEANUP_VISIBLE */, task);
4951
+ container.$scheduler$(32 /* ChoreType.CLEANUP_VISIBLE */, task);
4875
4952
  }
4876
4953
  else {
4877
4954
  cleanupTask(task);
@@ -4922,7 +4999,16 @@ function cleanup(container, vNode) {
4922
4999
  */
4923
5000
  const vFirstChild = vnode_getFirstChild(vCursor);
4924
5001
  if (vFirstChild) {
4925
- vnode_walkVNode(vFirstChild);
5002
+ vnode_walkVNode(vFirstChild, (vNode) => {
5003
+ /**
5004
+ * Instead of an ID, we store a direct reference to the VNode. This is necessary to
5005
+ * locate the slot's parent in a detached subtree, as the ID would become invalid.
5006
+ */
5007
+ if (vNode[0 /* VNodeProps.flags */] & 2 /* VNodeFlags.Virtual */) {
5008
+ // The QSlotParent is used to find the slot parent during scheduling
5009
+ vnode_getProp(vNode, QSlotParent, (id) => vnode_locate(container.rootVNode, id));
5010
+ }
5011
+ });
4926
5012
  return;
4927
5013
  }
4928
5014
  }
@@ -4999,8 +5085,8 @@ const useResourceQrl = (qrl, opts) => {
4999
5085
  const resource = createResourceReturn(container, opts);
5000
5086
  const el = iCtx.$hostElement$;
5001
5087
  const task = new Task(8 /* TaskFlags.DIRTY */ | 4 /* TaskFlags.RESOURCE */, i, el, qrl, resource, null);
5002
- container.$scheduler$(3 /* ChoreType.TASK */, task);
5003
5088
  set(resource);
5089
+ runResource(task, container, el);
5004
5090
  return resource;
5005
5091
  };
5006
5092
  // <docs markdown="../readme.md#useResource">
@@ -5068,10 +5154,10 @@ const Resource = (props) => {
5068
5154
  function getResourceValueAsPromise(props) {
5069
5155
  const resource = props.value;
5070
5156
  if (isResourceReturn(resource)) {
5157
+ // create a subscription for the resource._state changes
5158
+ const state = resource._state;
5071
5159
  const isBrowser = !isServerPlatform();
5072
5160
  if (isBrowser) {
5073
- // create a subscription for the resource._state changes
5074
- const state = resource._state;
5075
5161
  if (state === 'pending' && props.onPending) {
5076
5162
  return Promise.resolve().then(useBindInvokeContext(props.onPending));
5077
5163
  }
@@ -5086,14 +5172,7 @@ function getResourceValueAsPromise(props) {
5086
5172
  }
5087
5173
  }
5088
5174
  }
5089
- const value = resource.value;
5090
- if (value) {
5091
- return value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
5092
- }
5093
- else {
5094
- // this is temporary value until the `runResource` is executed and promise is assigned to the value
5095
- return Promise.resolve(undefined);
5096
- }
5175
+ return untrack(() => resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
5097
5176
  }
5098
5177
  else if (isPromise(resource)) {
5099
5178
  return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
@@ -5111,7 +5190,7 @@ const _createResourceReturn = (opts) => {
5111
5190
  const resource = {
5112
5191
  __brand: 'resource',
5113
5192
  value: undefined,
5114
- loading: isServerPlatform() ? false : true,
5193
+ loading: !isServerPlatform(),
5115
5194
  _resolved: undefined,
5116
5195
  _error: undefined,
5117
5196
  _state: 'pending',
@@ -5162,19 +5241,22 @@ const runResource = (task, container, host) => {
5162
5241
  done = true;
5163
5242
  if (resolved) {
5164
5243
  done = true;
5165
- resource.loading = false;
5166
- resource._state = 'resolved';
5167
- resource._resolved = value;
5168
- resource._error = undefined;
5244
+ resourceTarget.loading = false;
5245
+ resourceTarget._state = 'resolved';
5246
+ resourceTarget._resolved = value;
5247
+ resourceTarget._error = undefined;
5169
5248
  resolve(value);
5170
5249
  }
5171
5250
  else {
5172
5251
  done = true;
5173
- resource.loading = false;
5174
- resource._state = 'rejected';
5175
- resource._error = value;
5252
+ resourceTarget.loading = false;
5253
+ resourceTarget._state = 'rejected';
5254
+ resourceTarget._error = value;
5176
5255
  reject(value);
5177
5256
  }
5257
+ if (!isServerPlatform()) {
5258
+ forceStoreEffects(resource, '_state');
5259
+ }
5178
5260
  return true;
5179
5261
  }
5180
5262
  return false;
@@ -5190,17 +5272,17 @@ const runResource = (task, container, host) => {
5190
5272
  }
5191
5273
  });
5192
5274
  // Execute mutation inside empty invocation
5275
+ // TODO: is it right? why we need to invoke inside context and trigger effects?
5193
5276
  invoke(iCtx, () => {
5194
5277
  // console.log('RESOURCE.pending: ');
5195
5278
  resource._state = 'pending';
5196
5279
  resource.loading = !isServerPlatform();
5197
- const promise = (resource.value = new Promise((r, re) => {
5280
+ resource.value = new Promise((r, re) => {
5198
5281
  resolve = r;
5199
5282
  reject = re;
5200
- }));
5201
- promise.catch(ignoreErrorToPreventNodeFromCrashing);
5283
+ });
5202
5284
  });
5203
- const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
5285
+ const promise = safeCall(() => taskFn(opts), (value) => {
5204
5286
  setState(true, value);
5205
5287
  }, (err) => {
5206
5288
  if (isPromise(err)) {
@@ -5223,10 +5305,6 @@ const runResource = (task, container, host) => {
5223
5305
  }
5224
5306
  return promise;
5225
5307
  };
5226
- const ignoreErrorToPreventNodeFromCrashing = (err) => {
5227
- // ignore error to prevent node from crashing
5228
- // node will crash in promise is rejected and no one is listening to the rejection.
5229
- };
5230
5308
 
5231
5309
  /// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
5232
5310
  const aVNodePath = [];
@@ -5309,11 +5387,11 @@ const ssrNodeDocumentPosition = (a, b) => {
5309
5387
  let bDepth = -1;
5310
5388
  while (a) {
5311
5389
  const ssrNode = (aSsrNodePath[++aDepth] = a);
5312
- a = ssrNode.parentSsrNode;
5390
+ a = ssrNode.parentComponent;
5313
5391
  }
5314
5392
  while (b) {
5315
5393
  const ssrNode = (bSsrNodePath[++bDepth] = b);
5316
- b = ssrNode.parentSsrNode;
5394
+ b = ssrNode.parentComponent;
5317
5395
  }
5318
5396
  while (aDepth >= 0 && bDepth >= 0) {
5319
5397
  a = aSsrNodePath[aDepth];
@@ -5330,6 +5408,210 @@ const ssrNodeDocumentPosition = (a, b) => {
5330
5408
  return aDepth < bDepth ? -1 : 1;
5331
5409
  };
5332
5410
 
5411
+ /**
5412
+ * Rules for determining if a chore is blocked by another chore. Some chores can block other chores.
5413
+ * They cannot run until the blocking chore has completed.
5414
+ *
5415
+ * The match function is used to determine if the blocked chore is blocked by the blocking chore.
5416
+ * The match function is called with the blocked chore, the blocking chore, and the container.
5417
+ */
5418
+ const VISIBLE_BLOCKING_RULES = [
5419
+ // NODE_DIFF blocks VISIBLE on same host,
5420
+ // if the blocked chore is a child of the blocking chore
5421
+ // or the blocked chore is a sibling of the blocking chore
5422
+ {
5423
+ blockedType: 16 /* ChoreType.VISIBLE */,
5424
+ blockingType: 4 /* ChoreType.NODE_DIFF */,
5425
+ match: (blocked, blocking, container) => isDescendant(blocked, blocking, container) || isDescendant(blocking, blocked, container),
5426
+ },
5427
+ // COMPONENT blocks VISIBLE on same host
5428
+ // if the blocked chore is a child of the blocking chore
5429
+ // or the blocked chore is a sibling of the blocking chore
5430
+ {
5431
+ blockedType: 16 /* ChoreType.VISIBLE */,
5432
+ blockingType: 6 /* ChoreType.COMPONENT */,
5433
+ match: (blocked, blocking, container) => isDescendant(blocked, blocking, container) || isDescendant(blocking, blocked, container),
5434
+ },
5435
+ ];
5436
+ const BLOCKING_RULES = [
5437
+ // QRL_RESOLVE blocks RUN_QRL, TASK, VISIBLE on same host
5438
+ {
5439
+ blockedType: 2 /* ChoreType.RUN_QRL */,
5440
+ blockingType: 1 /* ChoreType.QRL_RESOLVE */,
5441
+ match: (blocked, blocking) => {
5442
+ const blockedQrl = blocked.$target$;
5443
+ const blockingQrl = blocking.$target$;
5444
+ return isSameHost(blocked, blocking) && isSameQrl(blockedQrl, blockingQrl);
5445
+ },
5446
+ },
5447
+ {
5448
+ blockedType: 3 /* ChoreType.TASK */,
5449
+ blockingType: 1 /* ChoreType.QRL_RESOLVE */,
5450
+ match: (blocked, blocking) => {
5451
+ const blockedTask = blocked.$payload$;
5452
+ const blockingQrl = blocking.$target$;
5453
+ return isSameHost(blocked, blocking) && isSameQrl(blockedTask.$qrl$, blockingQrl);
5454
+ },
5455
+ },
5456
+ {
5457
+ blockedType: 16 /* ChoreType.VISIBLE */,
5458
+ blockingType: 1 /* ChoreType.QRL_RESOLVE */,
5459
+ match: (blocked, blocking) => {
5460
+ const blockedTask = blocked.$payload$;
5461
+ const blockingQrl = blocking.$target$;
5462
+ return isSameHost(blocked, blocking) && isSameQrl(blockedTask.$qrl$, blockingQrl);
5463
+ },
5464
+ },
5465
+ // COMPONENT blocks NODE_DIFF, NODE_PROP on same host
5466
+ {
5467
+ blockedType: 4 /* ChoreType.NODE_DIFF */,
5468
+ blockingType: 6 /* ChoreType.COMPONENT */,
5469
+ match: (blocked, blocking) => blocked.$host$ === blocking.$host$,
5470
+ },
5471
+ {
5472
+ blockedType: 5 /* ChoreType.NODE_PROP */,
5473
+ blockingType: 6 /* ChoreType.COMPONENT */,
5474
+ match: (blocked, blocking) => blocked.$host$ === blocking.$host$,
5475
+ },
5476
+ ...VISIBLE_BLOCKING_RULES,
5477
+ // TASK blocks subsequent TASKs in the same component
5478
+ {
5479
+ blockedType: 3 /* ChoreType.TASK */,
5480
+ blockingType: 3 /* ChoreType.TASK */,
5481
+ match: (blocked, blocking, container) => {
5482
+ if (blocked.$host$ !== blocking.$host$) {
5483
+ return false;
5484
+ }
5485
+ const blockedIdx = blocked.$idx$;
5486
+ if (!isNumber$1(blockedIdx) || blockedIdx <= 0) {
5487
+ return false;
5488
+ }
5489
+ const previousTask = findPreviousTaskInComponent(blocked.$host$, blockedIdx, container);
5490
+ return previousTask === blocking.$payload$;
5491
+ },
5492
+ },
5493
+ ];
5494
+ function isDescendant(descendantChore, ancestorChore, container) {
5495
+ const descendantHost = descendantChore.$host$;
5496
+ const ancestorHost = ancestorChore.$host$;
5497
+ if (!vnode_isVNode(descendantHost) || !vnode_isVNode(ancestorHost)) {
5498
+ return false;
5499
+ }
5500
+ return vnode_isDescendantOf(descendantHost, ancestorHost, container.rootVNode);
5501
+ }
5502
+ function isSameHost(a, b) {
5503
+ return a.$host$ === b.$host$;
5504
+ }
5505
+ function isSameQrl(a, b) {
5506
+ return a.$symbol$ === b.$symbol$;
5507
+ }
5508
+ function findBlockingChoreInQueue(chore, choreQueue, container) {
5509
+ for (const candidate of choreQueue) {
5510
+ // everything after VISIBLE is not blocking. Visible task, task and resource should not block anything in this rule.
5511
+ if (candidate.$type$ >= 16 /* ChoreType.VISIBLE */ || candidate.$type$ === 3 /* ChoreType.TASK */) {
5512
+ continue;
5513
+ }
5514
+ if (isDescendant(chore, candidate, container)) {
5515
+ return candidate;
5516
+ }
5517
+ }
5518
+ return null;
5519
+ }
5520
+ function findBlockingChore(chore, choreQueue, blockedChores, runningChores, container) {
5521
+ const blockingChoreInChoreQueue = findBlockingChoreInQueue(chore, choreQueue, container);
5522
+ if (blockingChoreInChoreQueue) {
5523
+ return blockingChoreInChoreQueue;
5524
+ }
5525
+ const blockingChoreInBlockedChores = findBlockingChoreInQueue(chore, Array.from(blockedChores), container);
5526
+ if (blockingChoreInBlockedChores) {
5527
+ return blockingChoreInBlockedChores;
5528
+ }
5529
+ const blockingChoreInRunningChores = findBlockingChoreInQueue(chore, Array.from(runningChores), container);
5530
+ if (blockingChoreInRunningChores) {
5531
+ return blockingChoreInRunningChores;
5532
+ }
5533
+ for (const rule of BLOCKING_RULES) {
5534
+ if (chore.$type$ !== rule.blockedType) {
5535
+ continue;
5536
+ }
5537
+ // Check in choreQueue
5538
+ // TODO(perf): better to iterate in reverse order?
5539
+ for (const candidate of choreQueue) {
5540
+ if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
5541
+ return candidate;
5542
+ }
5543
+ }
5544
+ // Check in blockedChores
5545
+ for (const candidate of blockedChores) {
5546
+ if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
5547
+ return candidate;
5548
+ }
5549
+ }
5550
+ // Check in runningChores
5551
+ for (const candidate of runningChores) {
5552
+ if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
5553
+ return candidate;
5554
+ }
5555
+ }
5556
+ }
5557
+ return null;
5558
+ }
5559
+ function findPreviousTaskInComponent(host, currentTaskIdx, container) {
5560
+ const elementSeq = container.getHostProp(host, ELEMENT_SEQ);
5561
+ if (!elementSeq || elementSeq.length <= currentTaskIdx) {
5562
+ return null;
5563
+ }
5564
+ for (let i = currentTaskIdx - 1; i >= 0; i--) {
5565
+ const candidate = elementSeq[i];
5566
+ if (candidate instanceof Task && candidate.$flags$ & 2 /* TaskFlags.TASK */) {
5567
+ return candidate;
5568
+ }
5569
+ }
5570
+ return null;
5571
+ }
5572
+ function findBlockingChoreForVisible(chore, runningChores, container) {
5573
+ for (const rule of VISIBLE_BLOCKING_RULES) {
5574
+ if (chore.$type$ !== rule.blockedType) {
5575
+ continue;
5576
+ }
5577
+ for (const candidate of runningChores) {
5578
+ if (candidate.$type$ === rule.blockingType && rule.match(chore, candidate, container)) {
5579
+ return candidate;
5580
+ }
5581
+ }
5582
+ }
5583
+ return null;
5584
+ }
5585
+
5586
+ // This can't be in platform.ts because it uses MessageChannel which cannot post messages with functions
5587
+ // TODO: move this to platform.ts somehow
5588
+ const createNextTick = (fn) => {
5589
+ let nextTick;
5590
+ // according to the https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate#notes
5591
+ if (typeof setImmediate === 'function') {
5592
+ // setImmediate is the fastest way to schedule a task, but works only in node.js
5593
+ nextTick = () => {
5594
+ setImmediate(fn);
5595
+ };
5596
+ }
5597
+ else if (typeof MessageChannel !== 'undefined') {
5598
+ const channel = new MessageChannel();
5599
+ channel.port1.onmessage = () => {
5600
+ fn();
5601
+ };
5602
+ nextTick = () => {
5603
+ channel.port2.postMessage(null);
5604
+ };
5605
+ }
5606
+ else {
5607
+ // setTimeout is a fallback, creates 4ms delay
5608
+ nextTick = () => {
5609
+ setTimeout(fn);
5610
+ };
5611
+ }
5612
+ return nextTick;
5613
+ };
5614
+
5333
5615
  /**
5334
5616
  * Scheduler is responsible for running application code in predictable order.
5335
5617
  *
@@ -5413,29 +5695,43 @@ const ssrNodeDocumentPosition = (a, b) => {
5413
5695
  */
5414
5696
  // Turn this on to get debug output of what the scheduler is doing.
5415
5697
  const DEBUG = false;
5416
- const getPromise = (chore) => (chore.$promise$ ||= new Promise((resolve) => {
5417
- chore.$resolve$ = resolve;
5418
- }));
5419
- const createScheduler = (container, scheduleDrain, journalFlush) => {
5420
- const choreQueue = [];
5421
- const qrlRuns = [];
5422
- let currentChore = null;
5698
+ var ChoreState;
5699
+ (function (ChoreState) {
5700
+ ChoreState[ChoreState["NONE"] = 0] = "NONE";
5701
+ ChoreState[ChoreState["RUNNING"] = 1] = "RUNNING";
5702
+ ChoreState[ChoreState["FAILED"] = 2] = "FAILED";
5703
+ ChoreState[ChoreState["DONE"] = 3] = "DONE";
5704
+ })(ChoreState || (ChoreState = {}));
5705
+ const getChorePromise = (chore) => chore.$state$ === ChoreState.NONE
5706
+ ? (chore.$returnValue$ ||= new Promise((resolve, reject) => {
5707
+ chore.$resolve$ = resolve;
5708
+ chore.$reject$ = reject;
5709
+ }))
5710
+ : chore.$returnValue$;
5711
+ const createScheduler = (container, journalFlush, choreQueue = [], blockedChores = new Set(), runningChores = new Set()) => {
5712
+ let drainChore = null;
5423
5713
  let drainScheduled = false;
5714
+ let isDraining = false;
5715
+ let isJournalFlushRunning = false;
5716
+ let flushBudgetStart = 0;
5717
+ let currentTime = performance.now();
5718
+ const nextTick = createNextTick(drainChoreQueue);
5719
+ function drainInNextTick() {
5720
+ if (!drainScheduled) {
5721
+ drainScheduled = true;
5722
+ nextTick();
5723
+ }
5724
+ }
5725
+ // Drain for ~16.67ms, then apply journal flush for ~16.67ms, then repeat
5726
+ // We divide by 60 because we want to run at 60fps
5727
+ const FREQUENCY_MS = Math.floor(1000 / 60);
5424
5728
  return schedule;
5425
5729
  ///// IMPLEMENTATION /////
5426
5730
  function schedule(type, hostOrTask = null, targetOrQrl = null, payload = null) {
5427
- const isServer = !isDomContainer(container);
5428
- const isComponentSsr = isServer && type === 6 /* ChoreType.COMPONENT */;
5429
- const runLater = type !== 255 /* ChoreType.WAIT_FOR_ALL */ && !isComponentSsr && type !== 2 /* ChoreType.RUN_QRL */;
5430
- const isTask = type === 3 /* ChoreType.TASK */ || type === 32 /* ChoreType.VISIBLE */ || type === 48 /* ChoreType.CLEANUP_VISIBLE */;
5431
- const isClientOnly = type === 16 /* ChoreType.JOURNAL_FLUSH */ ||
5432
- type === 4 /* ChoreType.NODE_DIFF */ ||
5433
- type === 5 /* ChoreType.NODE_PROP */ ||
5434
- type === 1 /* ChoreType.QRL_RESOLVE */ ||
5435
- type === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */;
5436
- if (isServer && isClientOnly) {
5437
- return;
5731
+ if (type === 255 /* ChoreType.WAIT_FOR_QUEUE */ && drainChore) {
5732
+ return drainChore;
5438
5733
  }
5734
+ const isTask = type === 3 /* ChoreType.TASK */ || type === 16 /* ChoreType.VISIBLE */ || type === 32 /* ChoreType.CLEANUP_VISIBLE */;
5439
5735
  if (isTask) {
5440
5736
  hostOrTask.$flags$ |= 8 /* TaskFlags.DIRTY */;
5441
5737
  }
@@ -5449,167 +5745,310 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
5449
5745
  $host$: isTask ? hostOrTask.$el$ : hostOrTask,
5450
5746
  $target$: targetOrQrl,
5451
5747
  $payload$: isTask ? hostOrTask : payload,
5452
- $resolve$: null,
5453
- $promise$: null,
5748
+ $state$: ChoreState.NONE,
5749
+ $blockedChores$: null,
5750
+ $startTime$: undefined,
5751
+ $endTime$: undefined,
5752
+ $resolve$: undefined,
5753
+ $reject$: undefined,
5454
5754
  $returnValue$: null,
5455
- $executed$: false,
5456
5755
  };
5457
- chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
5458
- if (!drainScheduled && runLater) {
5459
- // If we are not currently draining, we need to schedule a drain.
5460
- drainScheduled = true;
5461
- schedule(16 /* ChoreType.JOURNAL_FLUSH */);
5462
- // Catch here to avoid unhandled promise rejection
5463
- scheduleDrain()?.catch?.(() => { });
5756
+ if (type === 255 /* ChoreType.WAIT_FOR_QUEUE */) {
5757
+ getChorePromise(chore);
5758
+ drainChore = chore;
5759
+ drainInNextTick();
5760
+ return chore;
5761
+ }
5762
+ const isServer = isServerPlatform();
5763
+ const isClientOnly = type === 4 /* ChoreType.NODE_DIFF */ || type === 1 /* ChoreType.QRL_RESOLVE */;
5764
+ if (isServer && isClientOnly) {
5765
+ // Mark skipped client-only chores as completed on the server
5766
+ finishChore(chore, undefined);
5767
+ return chore;
5768
+ }
5769
+ if (isServer && chore.$host$ && isSsrNode(chore.$host$)) {
5770
+ const isUpdatable = !!(chore.$host$.flags & 1 /* SsrNodeFlags.Updatable */);
5771
+ if (!isUpdatable) {
5772
+ if (
5773
+ // backpatching exceptions:
5774
+ // - node prop is allowed because it is used to update the node property
5775
+ // - recompute and schedule effects because it triggers effects (so node prop too)
5776
+ chore.$type$ !== 5 /* ChoreType.NODE_PROP */ &&
5777
+ chore.$type$ !== 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */) {
5778
+ // We are running on the server.
5779
+ // On server we can't schedule task for a different host!
5780
+ // Server is SSR, and therefore scheduling for anything but the current host
5781
+ // implies that things need to be re-run and that is not supported because of streaming.
5782
+ const warningMessage = `A '${choreTypeToName(chore.$type$)}' chore was scheduled on a host element that has already been streamed to the client.
5783
+ This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
5784
+
5785
+ Problematic chore:
5786
+ - Type: ${choreTypeToName(chore.$type$)}
5787
+ - Host: ${chore.$host$.toString()}
5788
+ - Nearest element location: ${chore.$host$.currentFile}
5789
+
5790
+ This is often caused by modifying a signal in an already rendered component during SSR.`;
5791
+ logWarn(warningMessage);
5792
+ return chore;
5793
+ }
5794
+ }
5795
+ }
5796
+ const blockingChore = findBlockingChore(chore, choreQueue, blockedChores, runningChores, container);
5797
+ if (blockingChore) {
5798
+ addBlockedChore(chore, blockingChore, blockedChores);
5799
+ return chore;
5464
5800
  }
5465
- // TODO figure out what to do with chore errors
5466
- if (runLater) {
5467
- return getPromise(chore);
5801
+ chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
5802
+ const runImmediately = (isServer && type === 6 /* ChoreType.COMPONENT */) || type === 2 /* ChoreType.RUN_QRL */;
5803
+ if (runImmediately && !isDraining) {
5804
+ immediateDrain();
5468
5805
  }
5469
5806
  else {
5470
- return drainUpTo(chore, isServer);
5471
- }
5472
- }
5473
- /** Execute all of the chores up to and including the given chore. */
5474
- function drainUpTo(runUptoChore, isServer) {
5475
- let maxRetries = 5000;
5476
- while (choreQueue.length) {
5477
- if (maxRetries-- < 0) {
5478
- throw new Error('drainUpTo: max retries reached');
5479
- }
5480
- if (currentChore) {
5481
- // Already running chore, which means we're waiting for async completion
5482
- return getPromise(currentChore)
5483
- .then(() => drainUpTo(runUptoChore, isServer))
5484
- .catch((e) => {
5485
- container.handleError(e, currentChore?.$host$);
5486
- });
5807
+ drainInNextTick();
5808
+ }
5809
+ return chore;
5810
+ }
5811
+ function immediateDrain() {
5812
+ drainScheduled = true;
5813
+ drainChoreQueue();
5814
+ }
5815
+ ////////////////////////////////////////////////////////////////////////////////
5816
+ // Drain queue helpers
5817
+ ////////////////////////////////////////////////////////////////////////////////
5818
+ function applyJournalFlush() {
5819
+ if (!isJournalFlushRunning) {
5820
+ // prevent multiple journal flushes from running at the same time
5821
+ isJournalFlushRunning = true;
5822
+ journalFlush();
5823
+ isJournalFlushRunning = false;
5824
+ flushBudgetStart = performance.now();
5825
+ }
5826
+ }
5827
+ function shouldApplyJournalFlush(isServer) {
5828
+ return !isServer && currentTime - flushBudgetStart >= FREQUENCY_MS;
5829
+ }
5830
+ function drainChoreQueue() {
5831
+ const isServer = isServerPlatform();
5832
+ drainScheduled = false;
5833
+ if (isDraining) {
5834
+ return;
5835
+ }
5836
+ // early return if the queue is empty
5837
+ if (!choreQueue.length) {
5838
+ applyJournalFlush();
5839
+ if (drainChore && !runningChores.size) {
5840
+ // resolve drainChore only if there are no running chores, because
5841
+ // we are sure that we are done
5842
+ drainChore.$resolve$(null);
5843
+ drainChore = null;
5487
5844
  }
5488
- const nextChore = choreQueue[0];
5489
- if (nextChore.$executed$) {
5490
- choreQueue.shift();
5491
- if (nextChore === runUptoChore) {
5492
- break;
5845
+ return;
5846
+ }
5847
+ isDraining = true;
5848
+ flushBudgetStart = performance.now();
5849
+ const maybeFinishDrain = () => {
5850
+ if (choreQueue.length) {
5851
+ drainInNextTick();
5852
+ return false;
5853
+ }
5854
+ if (drainChore && runningChores.size) {
5855
+ if (shouldApplyJournalFlush(isServer)) {
5856
+ // apply journal flush even if we are not finished draining the queue
5857
+ applyJournalFlush();
5493
5858
  }
5494
- continue;
5859
+ return false;
5495
5860
  }
5496
- if (vNodeAlreadyDeleted(nextChore) &&
5497
- // we need to process cleanup tasks for deleted nodes
5498
- nextChore.$type$ !== 48 /* ChoreType.CLEANUP_VISIBLE */) {
5499
- choreQueue.shift();
5500
- continue;
5861
+ currentChore = null;
5862
+ applyJournalFlush();
5863
+ drainChore?.$resolve$(null);
5864
+ drainChore = null;
5865
+ return true;
5866
+ };
5867
+ const scheduleBlockedChoresAndDrainIfNeeded = (chore) => {
5868
+ let blockedChoresScheduled = false;
5869
+ if (chore.$blockedChores$) {
5870
+ for (const blockedChore of chore.$blockedChores$) {
5871
+ const blockingChore = findBlockingChore(blockedChore, choreQueue, blockedChores, runningChores, container);
5872
+ if (blockingChore) {
5873
+ addBlockedChore(blockedChore, blockingChore, blockedChores);
5874
+ }
5875
+ else {
5876
+ blockedChores.delete(blockedChore);
5877
+ sortedInsert(choreQueue, blockedChore, container.rootVNode || null);
5878
+ blockedChoresScheduled = true;
5879
+ }
5880
+ }
5881
+ chore.$blockedChores$ = null;
5501
5882
  }
5502
- executeChore(nextChore, isServer);
5503
- }
5504
- return runUptoChore.$returnValue$;
5505
- }
5506
- function executeChore(chore, isServer) {
5507
- const host = chore.$host$;
5508
- assertEqual(currentChore, null, 'Chore already running.');
5509
- currentChore = chore;
5510
- let returnValue = null;
5883
+ if (blockedChoresScheduled && !isDraining) {
5884
+ drainInNextTick();
5885
+ }
5886
+ };
5887
+ let currentChore = null;
5511
5888
  try {
5512
- switch (chore.$type$) {
5513
- case 255 /* ChoreType.WAIT_FOR_ALL */:
5514
- {
5515
- if (isServer) {
5516
- drainScheduled = false;
5517
- }
5518
- }
5519
- break;
5520
- case 16 /* ChoreType.JOURNAL_FLUSH */:
5521
- {
5522
- returnValue = journalFlush();
5523
- drainScheduled = false;
5889
+ while (choreQueue.length) {
5890
+ currentTime = performance.now();
5891
+ const chore = (currentChore = choreQueue.shift());
5892
+ if (chore.$state$ !== ChoreState.NONE) {
5893
+ continue;
5894
+ }
5895
+ if (vNodeAlreadyDeleted(chore) &&
5896
+ // we need to process cleanup tasks for deleted nodes
5897
+ chore.$type$ !== 32 /* ChoreType.CLEANUP_VISIBLE */) {
5898
+ // skip deleted chore
5899
+ DEBUG && debugTrace('skip chore', chore, choreQueue, blockedChores);
5900
+ continue;
5901
+ }
5902
+ if (chore.$type$ === 16 /* ChoreType.VISIBLE */) {
5903
+ // ensure that the journal flush is applied before the visible chore is executed
5904
+ // so that the visible chore can see the latest DOM changes
5905
+ applyJournalFlush();
5906
+ const blockingChore = findBlockingChoreForVisible(chore, runningChores, container);
5907
+ if (blockingChore && blockingChore.$state$ === ChoreState.RUNNING) {
5908
+ addBlockedChore(chore, blockingChore, blockedChores);
5909
+ continue;
5524
5910
  }
5525
- break;
5526
- case 6 /* ChoreType.COMPONENT */:
5527
- {
5528
- returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
5529
- if (isServer) {
5530
- return jsx;
5911
+ }
5912
+ // Note that this never throws
5913
+ chore.$startTime$ = performance.now();
5914
+ const result = executeChore(chore, isServer);
5915
+ chore.$returnValue$ = result;
5916
+ if (isPromise(result)) {
5917
+ runningChores.add(chore);
5918
+ chore.$state$ = ChoreState.RUNNING;
5919
+ result
5920
+ .then((value) => {
5921
+ finishChore(chore, value);
5922
+ })
5923
+ .catch((e) => {
5924
+ if (chore.$state$ !== ChoreState.RUNNING) {
5925
+ // we already handled the error
5926
+ return;
5927
+ }
5928
+ handleError(chore, e);
5929
+ })
5930
+ .finally(() => {
5931
+ runningChores.delete(chore);
5932
+ // Note that we ignore failed chores so the app keeps working
5933
+ // TODO decide if this is ok and document it
5934
+ scheduleBlockedChoresAndDrainIfNeeded(chore);
5935
+ // If drainChore is not null, we are waiting for it to finish.
5936
+ // If there are no running chores, we can finish the drain.
5937
+ if (!runningChores.size) {
5938
+ let finished = false;
5939
+ if (drainChore) {
5940
+ finished = maybeFinishDrain();
5531
5941
  }
5532
- else {
5533
- const styleScopedId = container.getHostProp(host, QScopedStyle);
5534
- return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
5942
+ if (!finished && !isDraining) {
5943
+ // if finished, then journal flush is already applied
5944
+ applyJournalFlush();
5535
5945
  }
5536
- }, (err) => container.handleError(err, host));
5537
- }
5538
- break;
5539
- case 2 /* ChoreType.RUN_QRL */:
5540
- {
5541
- const fn = chore.$target$.getFn();
5542
- const result = retryOnPromise(() => fn(...chore.$payload$));
5543
- if (isPromise(result)) {
5544
- const handled = result
5545
- .finally(() => {
5546
- qrlRuns.splice(qrlRuns.indexOf(handled), 1);
5547
- })
5548
- .catch((error) => {
5549
- container.handleError(error, chore.$host$);
5550
- });
5551
- // Don't wait for the promise to resolve
5552
- // TODO come up with a better solution, we also want concurrent signal handling with tasks but serial tasks
5553
- qrlRuns.push(handled);
5554
- DEBUG &&
5555
- debugTrace('execute.DONE (but still running)', chore, currentChore, choreQueue);
5556
- chore.$returnValue$ = handled;
5557
- chore.$resolve$?.(handled);
5558
- currentChore = null;
5559
- chore.$executed$ = true;
5560
- // early out so we don't call after()
5561
- return;
5562
5946
  }
5563
- returnValue = null;
5564
- }
5565
- break;
5566
- case 3 /* ChoreType.TASK */:
5567
- case 32 /* ChoreType.VISIBLE */:
5568
- {
5569
- const payload = chore.$payload$;
5570
- if (payload.$flags$ & 4 /* TaskFlags.RESOURCE */) {
5571
- const result = runResource(payload, container, host);
5572
- // Don't await the return value of the resource, because async resources should not be awaited.
5573
- // The reason for this is that we should be able to update for example a node with loading
5574
- // text. If we await the resource, the loading text will not be displayed until the resource
5575
- // is loaded.
5576
- // Awaiting on the client also causes a deadlock.
5577
- // In any case, the resource will never throw.
5578
- returnValue = isServer ? result : null;
5947
+ });
5948
+ }
5949
+ else {
5950
+ finishChore(chore, result);
5951
+ scheduleBlockedChoresAndDrainIfNeeded(chore);
5952
+ }
5953
+ if (shouldApplyJournalFlush(isServer)) {
5954
+ applyJournalFlush();
5955
+ drainInNextTick();
5956
+ return;
5957
+ }
5958
+ }
5959
+ }
5960
+ catch (e) {
5961
+ handleError(currentChore, e);
5962
+ scheduleBlockedChoresAndDrainIfNeeded(currentChore);
5963
+ }
5964
+ finally {
5965
+ isDraining = false;
5966
+ maybeFinishDrain();
5967
+ }
5968
+ }
5969
+ function finishChore(chore, value) {
5970
+ chore.$endTime$ = performance.now();
5971
+ chore.$state$ = ChoreState.DONE;
5972
+ chore.$returnValue$ = value;
5973
+ chore.$resolve$?.(value);
5974
+ }
5975
+ function handleError(chore, e) {
5976
+ chore.$endTime$ = performance.now();
5977
+ chore.$state$ = ChoreState.FAILED;
5978
+ // If we used the result as promise, this won't exist
5979
+ chore.$reject$?.(e);
5980
+ container.handleError(e, chore.$host$);
5981
+ }
5982
+ function executeChore(chore, isServer) {
5983
+ const host = chore.$host$;
5984
+ let returnValue;
5985
+ switch (chore.$type$) {
5986
+ case 6 /* ChoreType.COMPONENT */:
5987
+ {
5988
+ returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
5989
+ if (isServer) {
5990
+ return jsx;
5579
5991
  }
5580
5992
  else {
5581
- returnValue = runTask(payload, container, host);
5993
+ const styleScopedId = container.getHostProp(host, QScopedStyle);
5994
+ return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
5582
5995
  }
5996
+ }, (err) => {
5997
+ handleError(chore, err);
5998
+ });
5999
+ }
6000
+ break;
6001
+ case 2 /* ChoreType.RUN_QRL */:
6002
+ {
6003
+ const fn = chore.$target$.getFn();
6004
+ returnValue = retryOnPromise(() => fn(...chore.$payload$));
6005
+ }
6006
+ break;
6007
+ case 3 /* ChoreType.TASK */:
6008
+ case 16 /* ChoreType.VISIBLE */:
6009
+ {
6010
+ const payload = chore.$payload$;
6011
+ if (payload.$flags$ & 4 /* TaskFlags.RESOURCE */) {
6012
+ returnValue = runResource(payload, container, host);
5583
6013
  }
5584
- break;
5585
- case 48 /* ChoreType.CLEANUP_VISIBLE */:
5586
- {
5587
- const task = chore.$payload$;
5588
- cleanupTask(task);
6014
+ else {
6015
+ returnValue = runTask(payload, container, host);
5589
6016
  }
5590
- break;
5591
- case 4 /* ChoreType.NODE_DIFF */:
5592
- {
5593
- const parentVirtualNode = chore.$target$;
5594
- let jsx = chore.$payload$;
5595
- if (isSignal(jsx)) {
5596
- jsx = jsx.value;
5597
- }
5598
- returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
6017
+ }
6018
+ break;
6019
+ case 32 /* ChoreType.CLEANUP_VISIBLE */:
6020
+ {
6021
+ const task = chore.$payload$;
6022
+ cleanupTask(task);
6023
+ }
6024
+ break;
6025
+ case 4 /* ChoreType.NODE_DIFF */:
6026
+ {
6027
+ const parentVirtualNode = chore.$target$;
6028
+ let jsx = chore.$payload$;
6029
+ if (isSignal(jsx)) {
6030
+ jsx = jsx.value;
5599
6031
  }
5600
- break;
5601
- case 5 /* ChoreType.NODE_PROP */:
5602
- {
5603
- const virtualNode = chore.$host$;
5604
- const payload = chore.$payload$;
5605
- let value = payload.$value$;
5606
- if (isSignal(value)) {
5607
- value = value.value;
5608
- }
5609
- const isConst = payload.$isConst$;
5610
- const journal = container.$journal$;
5611
- const property = chore.$idx$;
5612
- const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
6032
+ returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
6033
+ }
6034
+ break;
6035
+ case 5 /* ChoreType.NODE_PROP */:
6036
+ {
6037
+ const virtualNode = chore.$host$;
6038
+ const payload = chore.$payload$;
6039
+ let value = payload.$value$;
6040
+ if (isSignal(value)) {
6041
+ value = value.value;
6042
+ }
6043
+ const isConst = payload.$isConst$;
6044
+ const journal = container.$journal$;
6045
+ const property = chore.$idx$;
6046
+ const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
6047
+ if (isServer) {
6048
+ container.addBackpatchEntry(chore.$host$.id, property, serializedValue);
6049
+ returnValue = null;
6050
+ }
6051
+ else {
5613
6052
  if (isConst) {
5614
6053
  const element = virtualNode[6 /* ElementVNodeProps.element */];
5615
6054
  journal.push(2 /* VNodeJournalOpCode.SetAttribute */, element, property, serializedValue);
@@ -5617,64 +6056,49 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
5617
6056
  else {
5618
6057
  vnode_setAttr(journal, virtualNode, property, serializedValue);
5619
6058
  }
6059
+ returnValue = undefined;
5620
6060
  }
5621
- break;
5622
- case 1 /* ChoreType.QRL_RESOLVE */: {
5623
- {
5624
- const target = chore.$target$;
5625
- returnValue = !target.resolved ? target.resolve() : null;
5626
- }
5627
- break;
5628
6061
  }
5629
- case 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */: {
5630
- {
5631
- const target = chore.$target$;
5632
- const effects = chore.$payload$;
6062
+ break;
6063
+ case 1 /* ChoreType.QRL_RESOLVE */: {
6064
+ {
6065
+ const target = chore.$target$;
6066
+ returnValue = (!target.resolved ? target.resolve() : null);
6067
+ }
6068
+ break;
6069
+ }
6070
+ case 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */: {
6071
+ {
6072
+ const target = chore.$target$;
6073
+ const effects = chore.$payload$;
6074
+ if (!effects?.size) {
6075
+ break;
6076
+ }
6077
+ let shouldCompute = target instanceof ComputedSignalImpl || target instanceof WrappedSignalImpl;
6078
+ if (target instanceof AsyncComputedSignalImpl && effects !== target.$effects$) {
6079
+ shouldCompute = false;
6080
+ }
6081
+ if (shouldCompute) {
5633
6082
  const ctx = newInvokeContext();
5634
6083
  ctx.$container$ = container;
5635
- if (target instanceof ComputedSignalImpl || target instanceof WrappedSignalImpl) {
5636
- const forceRunEffects = target.$forceRunEffects$;
5637
- target.$forceRunEffects$ = false;
5638
- if (!effects?.size && !forceRunEffects) {
5639
- break;
6084
+ // needed for computed signals and throwing QRLs
6085
+ returnValue = maybeThen(retryOnPromise(() => invoke.call(target, ctx, target.$computeIfNeeded$)), () => {
6086
+ if (target.$flags$ & 2 /* SignalFlags.RUN_EFFECTS */) {
6087
+ target.$flags$ &= -3 /* SignalFlags.RUN_EFFECTS */;
6088
+ return retryOnPromise(() => triggerEffects(container, target, effects));
5640
6089
  }
5641
- // needed for computed signals and throwing QRLs
5642
- returnValue = maybeThen(retryOnPromise(() => invoke.call(target, ctx, target.$computeIfNeeded$)), (didChange) => {
5643
- if (didChange || forceRunEffects) {
5644
- return retryOnPromise(() => triggerEffects(container, target, effects));
5645
- }
5646
- });
5647
- }
5648
- else {
5649
- returnValue = retryOnPromise(() => triggerEffects(container, target, effects));
5650
- }
6090
+ });
6091
+ }
6092
+ else {
6093
+ returnValue = retryOnPromise(() => {
6094
+ triggerEffects(container, target, effects);
6095
+ });
5651
6096
  }
5652
- break;
5653
6097
  }
6098
+ break;
5654
6099
  }
5655
6100
  }
5656
- catch (e) {
5657
- returnValue = Promise.reject(e);
5658
- }
5659
- const after = (value, error) => {
5660
- currentChore = null;
5661
- chore.$executed$ = true;
5662
- if (error) {
5663
- container.handleError(error, host);
5664
- }
5665
- else {
5666
- chore.$returnValue$ = value;
5667
- chore.$resolve$?.(value);
5668
- }
5669
- };
5670
- if (isPromise(returnValue)) {
5671
- chore.$promise$ = returnValue.then(after, (error) => after(undefined, error));
5672
- chore.$resolve$?.(chore.$promise$);
5673
- chore.$resolve$ = undefined;
5674
- }
5675
- else {
5676
- after(returnValue);
5677
- }
6101
+ return returnValue;
5678
6102
  }
5679
6103
  /**
5680
6104
  * Compares two chores to determine their execution order in the scheduler's queue.
@@ -5703,15 +6127,6 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
5703
6127
  else {
5704
6128
  assertFalse(vnode_isVNode(aHost), 'expected aHost to be SSRNode but it is a VNode');
5705
6129
  assertFalse(vnode_isVNode(bHost), 'expected bHost to be SSRNode but it is a VNode');
5706
- // we are running on the server.
5707
- // On server we can't schedule task for a different host!
5708
- // Server is SSR, and therefore scheduling for anything but the current host
5709
- // implies that things need to be re-run nad that is not supported because of streaming.
5710
- const errorMessage = `SERVER: during HTML streaming, re-running tasks on a different host is not allowed.
5711
- You are attempting to change a state that has already been streamed to the client.
5712
- This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
5713
- Problematic Node: ${aHost.toString()}`;
5714
- logWarn(errorMessage);
5715
6130
  const hostDiff = ssrNodeDocumentPosition(aHost, bHost);
5716
6131
  if (hostDiff !== 0) {
5717
6132
  return hostDiff;
@@ -5735,8 +6150,14 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
5735
6150
  // 1 means that we are going to process chores as FIFO
5736
6151
  return 1;
5737
6152
  }
5738
- // If the chore is the same as the current chore, we will run it again
5739
- if (b === currentChore) {
6153
+ // ensure that the effect chores are scheduled for the same target
6154
+ // TODO: can we do this better?
6155
+ if (a.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
6156
+ b.$type$ === 7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */ &&
6157
+ ((a.$target$ instanceof StoreHandler && b.$target$ instanceof StoreHandler) ||
6158
+ (a.$target$ instanceof AsyncComputedSignalImpl &&
6159
+ b.$target$ instanceof AsyncComputedSignalImpl)) &&
6160
+ a.$payload$ !== b.$payload$) {
5740
6161
  return 1;
5741
6162
  }
5742
6163
  // The chores are the same and will run only once
@@ -5768,6 +6189,15 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
5768
6189
  /// We need to ensure that the `queue` is sorted by priority.
5769
6190
  /// 1. Find a place where to insert into.
5770
6191
  const idx = sortedFindIndex(sortedArray, value, rootVNode);
6192
+ if (idx < 0 && runningChores.size) {
6193
+ // 1.1. Check if the chore is already running.
6194
+ for (const chore of runningChores) {
6195
+ const comp = choreComparator(value, chore, rootVNode);
6196
+ if (comp === 0) {
6197
+ return chore;
6198
+ }
6199
+ }
6200
+ }
5771
6201
  if (idx < 0) {
5772
6202
  /// 2. Insert the chore into the queue.
5773
6203
  sortedArray.splice(~idx, 0, value);
@@ -5782,9 +6212,6 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
5782
6212
  if (existing.$payload$ !== value.$payload$) {
5783
6213
  existing.$payload$ = value.$payload$;
5784
6214
  }
5785
- if (existing.$executed$) {
5786
- existing.$executed$ = false;
5787
- }
5788
6215
  return existing;
5789
6216
  }
5790
6217
  };
@@ -5796,6 +6223,25 @@ function vNodeAlreadyDeleted(chore) {
5796
6223
  vnode_isVNode(chore.$host$) &&
5797
6224
  chore.$host$[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */);
5798
6225
  }
6226
+ function addBlockedChore(blockedChore, blockingChore, blockedChores) {
6227
+ blockingChore.$blockedChores$ ||= [];
6228
+ blockingChore.$blockedChores$.push(blockedChore);
6229
+ blockedChores.add(blockedChore);
6230
+ }
6231
+ function choreTypeToName(type) {
6232
+ return ({
6233
+ [1 /* ChoreType.QRL_RESOLVE */]: 'Resolve QRL',
6234
+ [2 /* ChoreType.RUN_QRL */]: 'Run QRL',
6235
+ [3 /* ChoreType.TASK */]: 'Task',
6236
+ [4 /* ChoreType.NODE_DIFF */]: 'Changes diffing',
6237
+ [5 /* ChoreType.NODE_PROP */]: 'Updating node property',
6238
+ [6 /* ChoreType.COMPONENT */]: 'Component',
6239
+ [7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */]: 'Signal recompute',
6240
+ [16 /* ChoreType.VISIBLE */]: 'Visible',
6241
+ [32 /* ChoreType.CLEANUP_VISIBLE */]: 'Cleanup visible',
6242
+ [255 /* ChoreType.WAIT_FOR_QUEUE */]: 'Wait for queue',
6243
+ }[type] || 'Unknown: ' + type);
6244
+ }
5799
6245
  function debugChoreTypeToString(type) {
5800
6246
  return ({
5801
6247
  [1 /* ChoreType.QRL_RESOLVE */]: 'QRL_RESOLVE',
@@ -5805,31 +6251,87 @@ function debugChoreTypeToString(type) {
5805
6251
  [5 /* ChoreType.NODE_PROP */]: 'NODE_PROP',
5806
6252
  [6 /* ChoreType.COMPONENT */]: 'COMPONENT',
5807
6253
  [7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */]: 'RECOMPUTE_SIGNAL',
5808
- [16 /* ChoreType.JOURNAL_FLUSH */]: 'JOURNAL_FLUSH',
5809
- [32 /* ChoreType.VISIBLE */]: 'VISIBLE',
5810
- [48 /* ChoreType.CLEANUP_VISIBLE */]: 'CLEANUP_VISIBLE',
5811
- [255 /* ChoreType.WAIT_FOR_ALL */]: 'WAIT_FOR_ALL',
6254
+ [16 /* ChoreType.VISIBLE */]: 'VISIBLE',
6255
+ [32 /* ChoreType.CLEANUP_VISIBLE */]: 'CLEANUP_VISIBLE',
6256
+ [255 /* ChoreType.WAIT_FOR_QUEUE */]: 'WAIT_FOR_QUEUE',
5812
6257
  }[type] || 'UNKNOWN: ' + type);
5813
6258
  }
5814
- function debugChoreToString(chore) {
5815
- const type = debugChoreTypeToString(chore.$type$);
5816
- const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
5817
- const qrlTarget = chore.$target$?.$symbol$;
5818
- return `Chore(${type} ${chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */ ? qrlTarget : host} ${chore.$idx$})`;
5819
- }
5820
- function debugTrace(action, arg, currentChore, queue) {
5821
- const lines = ['===========================\nScheduler: ' + action];
5822
- if (arg && !('$type$' in arg)) {
5823
- lines.push(' arg: ' + String(arg).replaceAll(/\n.*/gim, ''));
5824
- }
5825
- if (queue) {
5826
- queue.forEach((chore) => {
5827
- const active = chore === arg ? '>>>' : ' ';
5828
- lines.push(` ${active} > ` +
5829
- (chore === currentChore ? '[running] ' : '') +
5830
- debugChoreToString(chore));
6259
+ function debugTrace(action, arg, queue, blockedChores) {
6260
+ const lines = [];
6261
+ // Header
6262
+ lines.push(`Scheduler: ${action}`);
6263
+ // Argument section
6264
+ if (arg) {
6265
+ lines.push('');
6266
+ if (arg && '$type$' in arg) {
6267
+ const chore = arg;
6268
+ const type = debugChoreTypeToString(chore.$type$);
6269
+ const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
6270
+ const qrlTarget = chore.$target$?.$symbol$;
6271
+ const targetOrHost = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
6272
+ ? qrlTarget
6273
+ : host;
6274
+ lines.push(`🎯 Current Chore:`);
6275
+ lines.push(` Type: ${type}`);
6276
+ lines.push(` Host: ${targetOrHost}`);
6277
+ // Show execution time if available
6278
+ if (chore.$startTime$ && chore.$endTime$) {
6279
+ const executionTime = chore.$endTime$ - chore.$startTime$;
6280
+ lines.push(` Time: ${executionTime.toFixed(2)}ms`);
6281
+ }
6282
+ else if (chore.$startTime$) {
6283
+ const elapsedTime = performance.now() - chore.$startTime$;
6284
+ lines.push(` Time: ${elapsedTime.toFixed(2)}ms (running)`);
6285
+ }
6286
+ // Show blocked chores for this chore
6287
+ if (chore.$blockedChores$ && chore.$blockedChores$.length > 0) {
6288
+ lines.push(` ⛔ Blocked Chores:`);
6289
+ chore.$blockedChores$.forEach((blockedChore, index) => {
6290
+ const blockedType = debugChoreTypeToString(blockedChore.$type$);
6291
+ const blockedTarget = String(blockedChore.$host$).replaceAll(/\n.*/gim, '');
6292
+ lines.push(` ${index + 1}. ${blockedType} ${blockedTarget} ${blockedChore.$idx$}`);
6293
+ });
6294
+ }
6295
+ }
6296
+ else {
6297
+ lines.push(`📝 Argument: ${String(arg).replaceAll(/\n.*/gim, '')}`);
6298
+ }
6299
+ }
6300
+ // Queue section
6301
+ if (queue && queue.length > 0) {
6302
+ lines.push('');
6303
+ lines.push(`📋 Queue (${queue.length} items):`);
6304
+ queue.forEach((chore, index) => {
6305
+ const isActive = chore === arg;
6306
+ const activeMarker = isActive ? `▶ ` : ' ';
6307
+ const type = debugChoreTypeToString(chore.$type$);
6308
+ const state = chore.$state$ ? `[${ChoreState[chore.$state$]}]` : '';
6309
+ const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
6310
+ const qrlTarget = chore.$target$?.$symbol$;
6311
+ const target = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
6312
+ ? qrlTarget
6313
+ : host;
6314
+ const line = `${activeMarker}${state} ${type} ${target} ${chore.$idx$}`;
6315
+ lines.push(line);
5831
6316
  });
5832
6317
  }
6318
+ // Blocked chores section
6319
+ if (blockedChores && blockedChores.size > 0) {
6320
+ lines.push('');
6321
+ lines.push(`🚫 Blocked Chores (${blockedChores.size} items):`);
6322
+ Array.from(blockedChores).forEach((chore, index) => {
6323
+ const type = debugChoreTypeToString(chore.$type$);
6324
+ const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
6325
+ const qrlTarget = chore.$target$?.$symbol$;
6326
+ const target = chore.$type$ === 1 /* ChoreType.QRL_RESOLVE */ || chore.$type$ === 2 /* ChoreType.RUN_QRL */
6327
+ ? qrlTarget
6328
+ : host;
6329
+ lines.push(` ${index + 1}. ${type} ${target} ${chore.$idx$}`);
6330
+ });
6331
+ }
6332
+ // Footer
6333
+ lines.push('');
6334
+ lines.push('─'.repeat(60));
5833
6335
  // eslint-disable-next-line no-console
5834
6336
  console.log(lines.join('\n') + '\n');
5835
6337
  }
@@ -5847,7 +6349,8 @@ class _SharedContainer {
5847
6349
  $currentUniqueId$ = 0;
5848
6350
  $instanceHash$ = null;
5849
6351
  $buildBase$ = null;
5850
- constructor(scheduleDrain, journalFlush, serverData, locale) {
6352
+ $flushEpoch$ = 0;
6353
+ constructor(journalFlush, serverData, locale) {
5851
6354
  this.$serverData$ = serverData;
5852
6355
  this.$locale$ = locale;
5853
6356
  this.$version$ = version;
@@ -5855,7 +6358,7 @@ class _SharedContainer {
5855
6358
  this.$getObjectById$ = (_id) => {
5856
6359
  throw Error('Not implemented');
5857
6360
  };
5858
- this.$scheduler$ = createScheduler(this, scheduleDrain, journalFlush);
6361
+ this.$scheduler$ = createScheduler(this, journalFlush);
5859
6362
  }
5860
6363
  trackSignalValue(signal, subscriber, property, data) {
5861
6364
  return trackSignalAndAssignHost(signal, subscriber, property, this, data);
@@ -6164,9 +6667,10 @@ function processVNodeData$1(document) {
6164
6667
  const shadowRootContainer = node;
6165
6668
  const shadowRoot = shadowRootContainer?.shadowRoot;
6166
6669
  if (shadowRoot) {
6670
+ const firstShadowRootChild = firstChild(shadowRoot);
6167
6671
  walkContainer(
6168
6672
  // we need to create a new walker for the shadow root
6169
- document.createTreeWalker(shadowRoot, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null, firstChild(shadowRoot), null, '', null);
6673
+ document.createTreeWalker(firstShadowRootChild, 0x1 /* NodeFilter.SHOW_ELEMENT */ | 0x80 /* NodeFilter.SHOW_COMMENT */), null, firstShadowRootChild, null, '', null);
6170
6674
  }
6171
6675
  }
6172
6676
  if ((nodeType & 2 /* NodeType.ELEMENT */) === 2 /* NodeType.ELEMENT */) {
@@ -6242,7 +6746,7 @@ function getDomContainerFromQContainerElement(qContainerElement) {
6242
6746
  /** @internal */
6243
6747
  function _getQContainerElement(element) {
6244
6748
  const qContainerElement = Array.isArray(element)
6245
- ? vnode_getDomParent(element)
6749
+ ? vnode_getDomParent(element, true)
6246
6750
  : element;
6247
6751
  return qContainerElement.closest(QContainerSelector);
6248
6752
  }
@@ -6257,7 +6761,6 @@ class DomContainer extends _SharedContainer {
6257
6761
  rootVNode;
6258
6762
  document;
6259
6763
  $journal$;
6260
- renderDone = null;
6261
6764
  $rawStateData$;
6262
6765
  $storeProxyMap$ = new WeakMap();
6263
6766
  $qFuncs$;
@@ -6267,9 +6770,11 @@ class DomContainer extends _SharedContainer {
6267
6770
  vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
6268
6771
  $stateData$;
6269
6772
  $styleIds$ = null;
6270
- $renderCount$ = 0;
6271
6773
  constructor(element) {
6272
- super(() => this.scheduleRender(), () => vnode_applyJournal(this.$journal$), {}, element.getAttribute(QLocaleAttr));
6774
+ super(() => {
6775
+ this.$flushEpoch$++;
6776
+ vnode_applyJournal(this.$journal$);
6777
+ }, {}, element.getAttribute(QLocaleAttr));
6273
6778
  this.qContainer = element.getAttribute(QContainerAttr);
6274
6779
  if (!this.qContainer) {
6275
6780
  throw qError(25 /* QError.elementWithoutContainer */);
@@ -6311,20 +6816,17 @@ class DomContainer extends _SharedContainer {
6311
6816
  }
6312
6817
  handleError(err, host) {
6313
6818
  if (qDev && host) {
6314
- // Clean vdom
6315
6819
  if (typeof document !== 'undefined') {
6316
6820
  const vHost = host;
6317
- const errorDiv = document.createElement('errored-host');
6318
- if (err && err instanceof Error) {
6319
- errorDiv.props = { error: err };
6320
- }
6321
- errorDiv.setAttribute('q:key', '_error_');
6322
6821
  const journal = [];
6323
- const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
6324
- vnode_getDOMChildNodes(journal, vHost, true).forEach((child) => {
6325
- vnode_insertBefore(journal, vErrorDiv, child, null);
6326
- });
6327
- vnode_insertBefore(journal, vHost, vErrorDiv, null);
6822
+ const vHostParent = vnode_getParent(vHost);
6823
+ const vHostNextSibling = vnode_getNextSibling(vHost);
6824
+ const vErrorDiv = vnode_createErrorDiv(document, vHost, err, journal);
6825
+ // If the host is an element node, we need to insert the error div into its parent.
6826
+ const insertHost = vnode_isElementVNode(vHost) ? vHostParent || vHost : vHost;
6827
+ // If the host is different then we need to insert errored-host in the same position as the host.
6828
+ const insertBefore = insertHost === vHost ? null : vHostNextSibling;
6829
+ vnode_insertBefore(journal, insertHost, vErrorDiv, insertBefore);
6328
6830
  vnode_applyJournal(journal);
6329
6831
  }
6330
6832
  if (err && err instanceof Error) {
@@ -6344,19 +6846,16 @@ class DomContainer extends _SharedContainer {
6344
6846
  }
6345
6847
  setContext(host, context, value) {
6346
6848
  let ctx = this.getHostProp(host, QCtxAttr);
6347
- if (!ctx) {
6849
+ if (ctx == null) {
6348
6850
  this.setHostProp(host, QCtxAttr, (ctx = []));
6349
6851
  }
6350
- mapArray_set(ctx, context.id, value, 0);
6852
+ mapArray_set(ctx, context.id, value, 0, true);
6351
6853
  }
6352
6854
  resolveContext(host, contextId) {
6353
6855
  while (host) {
6354
6856
  const ctx = this.getHostProp(host, QCtxAttr);
6355
- if (ctx) {
6356
- const value = mapArray_get(ctx, contextId.id, 0);
6357
- if (value) {
6358
- return value;
6359
- }
6857
+ if (ctx != null && mapArray_has(ctx, contextId.id, 0)) {
6858
+ return mapArray_get(ctx, contextId.id, 0);
6360
6859
  }
6361
6860
  host = this.getParentHost(host);
6362
6861
  }
@@ -6402,29 +6901,6 @@ class DomContainer extends _SharedContainer {
6402
6901
  }
6403
6902
  return vnode_getProp(vNode, name, getObjectById);
6404
6903
  }
6405
- scheduleRender() {
6406
- this.$renderCount$++;
6407
- this.renderDone ||= getPlatform().nextTick(() => this.processChores());
6408
- return this.renderDone.finally(() => emitEvent('qrender', { instanceHash: this.$instanceHash$, renderCount: this.$renderCount$ }));
6409
- }
6410
- processChores() {
6411
- let renderCount = this.$renderCount$;
6412
- const result = this.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
6413
- if (isPromise(result)) {
6414
- return result.then(async () => {
6415
- while (renderCount !== this.$renderCount$) {
6416
- renderCount = this.$renderCount$;
6417
- await this.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
6418
- }
6419
- this.renderDone = null;
6420
- });
6421
- }
6422
- if (renderCount !== this.$renderCount$) {
6423
- this.processChores();
6424
- return;
6425
- }
6426
- this.renderDone = null;
6427
- }
6428
6904
  ensureProjectionResolved(vNode) {
6429
6905
  if ((vNode[0 /* VNodeProps.flags */] & 16 /* VNodeFlags.Resolved */) === 0) {
6430
6906
  vNode[0 /* VNodeProps.flags */] |= 16 /* VNodeFlags.Resolved */;
@@ -6434,7 +6910,9 @@ class DomContainer extends _SharedContainer {
6434
6910
  if (isSlotProp(prop)) {
6435
6911
  const value = props[i + 1];
6436
6912
  if (typeof value == 'string') {
6437
- props[i + 1] = this.vNodeLocate(value);
6913
+ const projection = this.vNodeLocate(value);
6914
+ props[i + 1] = projection;
6915
+ vnode_getProp(projection, QSlotParent, (id) => this.vNodeLocate(id));
6438
6916
  }
6439
6917
  }
6440
6918
  }
@@ -6555,7 +7033,7 @@ const addQrlToSerializationCtx = (effectSubscriber, container) => {
6555
7033
  }
6556
7034
  };
6557
7035
  const triggerEffects = (container, signal, effects) => {
6558
- const isBrowser = isDomContainer(container);
7036
+ const isBrowser = !isServerPlatform();
6559
7037
  if (effects) {
6560
7038
  const scheduleEffect = (effectSubscription) => {
6561
7039
  const consumer = effectSubscription[0 /* EffectSubscriptionProp.CONSUMER */];
@@ -6565,7 +7043,7 @@ const triggerEffects = (container, signal, effects) => {
6565
7043
  consumer.$flags$ |= 8 /* TaskFlags.DIRTY */;
6566
7044
  let choreType = 3 /* ChoreType.TASK */;
6567
7045
  if (consumer.$flags$ & 1 /* TaskFlags.VISIBLE_TASK */) {
6568
- choreType = 32 /* ChoreType.VISIBLE */;
7046
+ choreType = 16 /* ChoreType.VISIBLE */;
6569
7047
  }
6570
7048
  container.$scheduler$(choreType, consumer);
6571
7049
  }
@@ -6588,22 +7066,22 @@ const triggerEffects = (container, signal, effects) => {
6588
7066
  const props = container.getHostProp(host, ELEMENT_PROPS);
6589
7067
  container.$scheduler$(6 /* ChoreType.COMPONENT */, host, qrl, props);
6590
7068
  }
6591
- else if (isBrowser) {
6592
- if (property === "." /* EffectProperty.VNODE */) {
7069
+ else if (property === "." /* EffectProperty.VNODE */) {
7070
+ if (isBrowser) {
6593
7071
  const host = consumer;
6594
7072
  container.$scheduler$(4 /* ChoreType.NODE_DIFF */, host, host, signal);
6595
7073
  }
6596
- else {
6597
- const host = consumer;
6598
- const effectData = effectSubscription[3 /* EffectSubscriptionProp.DATA */];
6599
- if (effectData instanceof SubscriptionData) {
6600
- const data = effectData.data;
6601
- const payload = {
6602
- ...data,
6603
- $value$: signal,
6604
- };
6605
- container.$scheduler$(5 /* ChoreType.NODE_PROP */, host, property, payload);
6606
- }
7074
+ }
7075
+ else {
7076
+ const host = consumer;
7077
+ const effectData = effectSubscription[3 /* EffectSubscriptionProp.DATA */];
7078
+ if (effectData instanceof SubscriptionData) {
7079
+ const data = effectData.data;
7080
+ const payload = {
7081
+ ...data,
7082
+ $value$: signal,
7083
+ };
7084
+ container.$scheduler$(5 /* ChoreType.NODE_PROP */, host, property, payload);
6607
7085
  }
6608
7086
  }
6609
7087
  };
@@ -6624,10 +7102,10 @@ const getComputedSignalFlags = (serializationStrategy) => {
6624
7102
  // flags |= ComputedSignalFlags.SERIALIZATION_STRATEGY_AUTO;
6625
7103
  // break;
6626
7104
  case 'never':
6627
- flags |= 8 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
7105
+ flags |= 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
6628
7106
  break;
6629
7107
  case 'always':
6630
- flags |= 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
7108
+ flags |= 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
6631
7109
  break;
6632
7110
  }
6633
7111
  return flags;
@@ -7019,6 +7497,9 @@ function vnode_walkVNode(vNode, callback) {
7019
7497
  }
7020
7498
  let vParent = null;
7021
7499
  do {
7500
+ if (callback?.(vCursor, vParent)) {
7501
+ return;
7502
+ }
7022
7503
  const vFirstChild = vnode_getFirstChild(vCursor);
7023
7504
  if (vFirstChild) {
7024
7505
  vCursor = vFirstChild;
@@ -7187,6 +7668,7 @@ const vnode_ensureTextInflated = (journal, vnode) => {
7187
7668
  const flags = textVNode[0 /* VNodeProps.flags */];
7188
7669
  if ((flags & 8 /* VNodeFlags.Inflated */) === 0) {
7189
7670
  const parentNode = vnode_getDomParent(vnode);
7671
+ assertDefined(parentNode, 'Missing parent node.');
7190
7672
  const sharedTextNode = textVNode[4 /* TextVNodeProps.node */];
7191
7673
  const doc = parentNode.ownerDocument;
7192
7674
  // Walk the previous siblings and inflate them.
@@ -7345,6 +7827,18 @@ const indexOfAlphanumeric = (id, length) => {
7345
7827
  }
7346
7828
  return length;
7347
7829
  };
7830
+ const vnode_createErrorDiv = (document, host, err, journal) => {
7831
+ const errorDiv = document.createElement('errored-host');
7832
+ if (err && err instanceof Error) {
7833
+ errorDiv.props = { error: err };
7834
+ }
7835
+ errorDiv.setAttribute('q:key', '_error_');
7836
+ const vErrorDiv = vnode_newElement(errorDiv, 'errored-host');
7837
+ vnode_getDOMChildNodes(journal, host, true).forEach((child) => {
7838
+ vnode_insertBefore(journal, vErrorDiv, child, null);
7839
+ });
7840
+ return vErrorDiv;
7841
+ };
7348
7842
  const parseBoolean = (value) => {
7349
7843
  if (value === 'false') {
7350
7844
  return false;
@@ -7483,7 +7977,7 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
7483
7977
  * unlink the previous or next sibling, we don't know that after "a" node is "b". So we need to
7484
7978
  * find children first (and inflate them).
7485
7979
  */
7486
- const domParentVNode = vnode_getDomParentVNode(parent);
7980
+ const domParentVNode = vnode_getDomParentVNode(parent, false);
7487
7981
  const parentNode = domParentVNode && domParentVNode[6 /* ElementVNodeProps.element */];
7488
7982
  let domChildren = null;
7489
7983
  if (domParentVNode) {
@@ -7532,27 +8026,31 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
7532
8026
  newChildCurrentParent !== parent)) {
7533
8027
  vnode_remove(journal, newChildCurrentParent, newChild, false);
7534
8028
  }
7535
- let adjustedInsertBefore = null;
7536
- if (insertBefore == null) {
7537
- if (vnode_isVirtualVNode(parent)) {
7538
- // If `insertBefore` is null, than we need to insert at the end of the list.
7539
- // Well, not quite. If the parent is a virtual node, our "last node" is not the same
7540
- // as the DOM "last node". So in that case we need to look for the "next node" from
7541
- // our parent.
7542
- adjustedInsertBefore = vnode_getDomSibling(parent, true, false);
8029
+ const parentIsDeleted = parent[0 /* VNodeProps.flags */] & 32 /* VNodeFlags.Deleted */;
8030
+ // if the parent is deleted, then we don't need to insert the new child
8031
+ if (!parentIsDeleted) {
8032
+ let adjustedInsertBefore = null;
8033
+ if (insertBefore == null) {
8034
+ if (vnode_isVirtualVNode(parent)) {
8035
+ // If `insertBefore` is null, than we need to insert at the end of the list.
8036
+ // Well, not quite. If the parent is a virtual node, our "last node" is not the same
8037
+ // as the DOM "last node". So in that case we need to look for the "next node" from
8038
+ // our parent.
8039
+ adjustedInsertBefore = vnode_getDomSibling(parent, true, false);
8040
+ }
8041
+ }
8042
+ else if (vnode_isVirtualVNode(insertBefore)) {
8043
+ // If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
8044
+ adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
8045
+ }
8046
+ else {
8047
+ adjustedInsertBefore = insertBefore;
8048
+ }
8049
+ adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
8050
+ // Here we know the insertBefore node
8051
+ if (domChildren && domChildren.length) {
8052
+ journal.push(5 /* VNodeJournalOpCode.Insert */, parentNode, vnode_getNode(adjustedInsertBefore), ...domChildren);
7543
8053
  }
7544
- }
7545
- else if (vnode_isVirtualVNode(insertBefore)) {
7546
- // If the `insertBefore` is virtual, than we need to descend into the virtual and find e actual
7547
- adjustedInsertBefore = vnode_getDomSibling(insertBefore, true, true);
7548
- }
7549
- else {
7550
- adjustedInsertBefore = insertBefore;
7551
- }
7552
- adjustedInsertBefore && vnode_ensureInflatedIfText(journal, adjustedInsertBefore);
7553
- // Here we know the insertBefore node
7554
- if (domChildren && domChildren.length) {
7555
- journal.push(5 /* VNodeJournalOpCode.Insert */, parentNode, vnode_getNode(adjustedInsertBefore), ...domChildren);
7556
8054
  }
7557
8055
  // link newChild into the previous/next list
7558
8056
  const vNext = insertBefore;
@@ -7574,14 +8072,22 @@ const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
7574
8072
  newChild[2 /* VNodeProps.previousSibling */] = vPrevious;
7575
8073
  newChild[3 /* VNodeProps.nextSibling */] = vNext;
7576
8074
  newChild[1 /* VNodeProps.parent */] = parent;
8075
+ if (parentIsDeleted) {
8076
+ // if the parent is deleted, then the new child is also deleted
8077
+ newChild[0 /* VNodeProps.flags */] |= 32 /* VNodeFlags.Deleted */;
8078
+ }
7577
8079
  };
7578
- const vnode_getDomParent = (vnode) => {
7579
- vnode = vnode_getDomParentVNode(vnode);
8080
+ const vnode_getDomParent = (vnode, includeProjection = true) => {
8081
+ vnode = vnode_getDomParentVNode(vnode, includeProjection);
7580
8082
  return (vnode && vnode[6 /* ElementVNodeProps.element */]);
7581
8083
  };
7582
- const vnode_getDomParentVNode = (vnode) => {
8084
+ const vnode_getDomParentVNode = (vnode, includeProjection = true) => {
7583
8085
  while (vnode && !vnode_isElementVNode(vnode)) {
7584
- vnode = vnode[1 /* VNodeProps.parent */];
8086
+ vnode =
8087
+ vnode[1 /* VNodeProps.parent */] ||
8088
+ (includeProjection
8089
+ ? vnode_getProp(vnode, QSlotParent, (id) => (vnode_isVNode(id) ? id : null))
8090
+ : null);
7585
8091
  }
7586
8092
  return vnode;
7587
8093
  };
@@ -7591,7 +8097,7 @@ const vnode_remove = (journal, vParent, vToRemove, removeDOM) => {
7591
8097
  vnode_ensureTextInflated(journal, vToRemove);
7592
8098
  }
7593
8099
  if (removeDOM) {
7594
- const domParent = vnode_getDomParent(vParent);
8100
+ const domParent = vnode_getDomParent(vParent, false);
7595
8101
  const isInnerHTMLParent = vnode_getAttr(vParent, dangerouslySetInnerHTML);
7596
8102
  if (isInnerHTMLParent) {
7597
8103
  // ignore children, as they are inserted via innerHTML
@@ -8072,6 +8578,26 @@ const vnode_getProps = (vnode) => {
8072
8578
  const vnode_getParent = (vnode) => {
8073
8579
  return vnode[1 /* VNodeProps.parent */] || null;
8074
8580
  };
8581
+ const vnode_isDescendantOf = (vnode, ancestor, rootVNode) => {
8582
+ let parent = vnode_getParentOrProjectionParent(vnode, rootVNode);
8583
+ while (parent) {
8584
+ if (parent === ancestor) {
8585
+ return true;
8586
+ }
8587
+ parent = vnode_getParentOrProjectionParent(parent, rootVNode);
8588
+ }
8589
+ return false;
8590
+ };
8591
+ const vnode_getParentOrProjectionParent = (vnode, rootVNode) => {
8592
+ if (rootVNode) {
8593
+ const parentProjection = vnode_getProp(vnode, QSlotParent, (id) => vnode_locate(rootVNode, id));
8594
+ if (parentProjection) {
8595
+ // This is a projection, so we need to check the parent of the projection
8596
+ return parentProjection;
8597
+ }
8598
+ }
8599
+ return vnode_getParent(vnode);
8600
+ };
8075
8601
  const vnode_getNode = (vnode) => {
8076
8602
  if (vnode === null || vnode_isVirtualVNode(vnode)) {
8077
8603
  return null;
@@ -8431,13 +8957,15 @@ class DeserializationHandler {
8431
8957
  }
8432
8958
  const container = this.$container$;
8433
8959
  let propValue = allocate(container, typeId, value);
8960
+ Reflect.set(target, property, propValue);
8961
+ this.$data$[idx] = undefined;
8962
+ this.$data$[idx + 1] = propValue;
8434
8963
  /** We stored the reference, so now we can inflate, allowing cycles. */
8435
8964
  if (typeId >= 14 /* TypeIds.Error */) {
8436
8965
  propValue = inflate(container, propValue, typeId, value);
8966
+ Reflect.set(target, property, propValue);
8967
+ this.$data$[idx + 1] = propValue;
8437
8968
  }
8438
- Reflect.set(target, property, propValue);
8439
- this.$data$[idx] = undefined;
8440
- this.$data$[idx + 1] = propValue;
8441
8969
  return propValue;
8442
8970
  }
8443
8971
  has(target, property) {
@@ -8616,7 +9144,7 @@ const inflate = (container, target, typeId, data) => {
8616
9144
  */
8617
9145
  // try to download qrl in this tick
8618
9146
  computed.$computeQrl$.resolve();
8619
- container.$scheduler$?.(1 /* ChoreType.QRL_RESOLVE */, null, computed.$computeQrl$);
9147
+ container.$scheduler$(1 /* ChoreType.QRL_RESOLVE */, null, computed.$computeQrl$);
8620
9148
  }
8621
9149
  break;
8622
9150
  }
@@ -9404,8 +9932,8 @@ async function serialize(serializationContext) {
9404
9932
  }
9405
9933
  else if (value instanceof ComputedSignalImpl) {
9406
9934
  let v = value.$untrackedValue$;
9407
- const shouldAlwaysSerialize = value.$flags$ & 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
9408
- const shouldNeverSerialize = value.$flags$ & 8 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
9935
+ const shouldAlwaysSerialize = value.$flags$ & 32 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
9936
+ const shouldNeverSerialize = value.$flags$ & 16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
9409
9937
  const isInvalid = value.$flags$ & 1 /* SignalFlags.INVALID */;
9410
9938
  const isSkippable = fastSkipSerialize(value.$untrackedValue$);
9411
9939
  if (shouldAlwaysSerialize) {
@@ -10747,7 +11275,7 @@ const render = async (parent, jsxNode, opts = {}) => {
10747
11275
  container.$serverData$ = opts.serverData || {};
10748
11276
  const host = container.rootVNode;
10749
11277
  container.$scheduler$(4 /* ChoreType.NODE_DIFF */, host, host, jsxNode);
10750
- await container.$scheduler$(255 /* ChoreType.WAIT_FOR_ALL */);
11278
+ await container.$scheduler$(255 /* ChoreType.WAIT_FOR_QUEUE */).$returnValue$;
10751
11279
  return {
10752
11280
  cleanup: () => {
10753
11281
  cleanup(container, container.rootVNode);
@@ -11585,7 +12113,7 @@ const useVisibleTaskQrl = (qrl, opts) => {
11585
12113
  useRunTask(task, eagerness);
11586
12114
  if (!isServerPlatform()) {
11587
12115
  qrl.resolve(iCtx.$element$);
11588
- iCtx.$container$.$scheduler$(32 /* ChoreType.VISIBLE */, task);
12116
+ iCtx.$container$.$scheduler$(16 /* ChoreType.VISIBLE */, task);
11589
12117
  }
11590
12118
  };
11591
12119
  const useRunTask = (task, eagerness) => {
@@ -11814,7 +12342,7 @@ const PrefetchServiceWorker = (opts) => {
11814
12342
  // the file 'qwik-prefetch-service-worker.js' is not located in /build/
11815
12343
  resolvedOpts.path = baseUrl + resolvedOpts.path;
11816
12344
  }
11817
- let code = PREFETCH_CODE.replace("'_URL_'", JSON.stringify(resolvedOpts.path));
12345
+ let code = PREFETCH_CODE.replace('"_URL_"', JSON.stringify(resolvedOpts.path.split('/').pop()));
11818
12346
  if (!isDev) {
11819
12347
  // consecutive spaces are indentation
11820
12348
  code = code.replaceAll(/\s\s+/gm, '');
@@ -11844,6 +12372,17 @@ const PREFETCH_CODE = /*#__PURE__*/ ((c // Service worker container
11844
12372
  });
11845
12373
  });
11846
12374
  }
12375
+ if ('caches' in window) {
12376
+ caches
12377
+ .keys()
12378
+ .then((names) => {
12379
+ const cacheName = names.find((name) => name.startsWith('QwikBundles'));
12380
+ if (cacheName) {
12381
+ caches.delete(cacheName).catch(console.error);
12382
+ }
12383
+ })
12384
+ .catch(console.error);
12385
+ }
11847
12386
  }).toString();
11848
12387
  /**
11849
12388
  * @deprecated This is no longer needed as the preloading happens automatically in qrl-class. You
@@ -11852,5 +12391,15 @@ const PREFETCH_CODE = /*#__PURE__*/ ((c // Service worker container
11852
12391
  */
11853
12392
  const PrefetchGraph = (_opts = {}) => null;
11854
12393
 
11855
- 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, _deserialize, dumpState as _dumpState, _fnSignal, _getContextContainer, _getContextElement, _getContextEvent, getDomContainer as _getDomContainer, _getQContainerElement, 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, queueQRL as _run, _serializationWeakRef, _serialize, scheduleTask as _task, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttr as _vnode_getAttr, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_getNextSibling as _vnode_getNextSibling, vnode_getPropStartIndex as _vnode_getPropStartIndex, vnode_getProps as _vnode_getProps, 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, createAsyncComputed$, createAsyncComputedSignal as createAsyncComputedQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsx as jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsyncComputed$, useAsyncComputedQrl, 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 };
12394
+ //////////////////////////////////////////////////////////////////////////////////////////
12395
+ // Protect against duplicate imports
12396
+ //////////////////////////////////////////////////////////////////////////////////////////
12397
+ if (globalThis.__qwik) {
12398
+ console.error(`==============================================\n` +
12399
+ `Qwik version ${globalThis.__qwik} already imported while importing ${version}. Verify external vs bundled imports etc. This can lead to issues due to duplicated shared structures.\n` +
12400
+ `==============================================\n`);
12401
+ }
12402
+ globalThis.__qwik = version;
12403
+
12404
+ 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, _deserialize, dumpState as _dumpState, _fnSignal, _getConstProps, _getContextContainer, _getContextElement, _getContextEvent, 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, _serializationWeakRef, _serialize, scheduleTask as _task, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttr as _vnode_getAttr, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_getNextSibling as _vnode_getNextSibling, vnode_getPropStartIndex as _vnode_getPropStartIndex, vnode_getProps as _vnode_getProps, 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, createAsyncComputed$, createAsyncComputedSignal as createAsyncComputedQrl, 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, jsx as jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsyncComputed$, useAsyncComputedQrl, 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 };
11856
12405
  //# sourceMappingURL=core.mjs.map