@qwik.dev/core 2.0.0-beta.3 → 2.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * @qwik.dev/core 2.0.0-beta.3-dev+aa098fc
3
+ * @qwik.dev/core 2.0.0-beta.4-dev+9849dcf
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
@@ -74,6 +74,24 @@
74
74
  return err;
75
75
  };
76
76
 
77
+ /** @private */
78
+ const isSerializableObject = (v) => {
79
+ const proto = Object.getPrototypeOf(v);
80
+ return proto === Object.prototype || proto === Array.prototype || proto === null;
81
+ };
82
+ const isObject = (v) => {
83
+ return typeof v === 'object' && v !== null;
84
+ };
85
+ const isArray = (v) => {
86
+ return Array.isArray(v);
87
+ };
88
+ const isString = (v) => {
89
+ return typeof v === 'string';
90
+ };
91
+ const isFunction = (v) => {
92
+ return typeof v === 'function';
93
+ };
94
+
77
95
  const codeToText = (code, ...parts) => {
78
96
  if (qDev) {
79
97
  // Keep one error, one line to make it easier to search for the error message.
@@ -118,7 +136,7 @@
118
136
  if (parts.length) {
119
137
  text = text.replaceAll(/{{(\d+)}}/g, (_, index) => {
120
138
  let v = parts[index];
121
- if (v && typeof v === 'object' && v.constructor === Object) {
139
+ if (v && isObject(v) && v.constructor === Object) {
122
140
  v = JSON.stringify(v).slice(0, 50);
123
141
  }
124
142
  return v;
@@ -379,7 +397,7 @@
379
397
  setTimeout(resolve, timeout);
380
398
  });
381
399
  };
382
- // Retries a function that throws a promise.
400
+ /** Retries a function that throws a promise. */
383
401
  function retryOnPromise(fn, retryCount = 0) {
384
402
  const retryOrThrow = (e) => {
385
403
  if (isPromise(e) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
@@ -404,24 +422,6 @@
404
422
  }
405
423
  }
406
424
 
407
- /** @private */
408
- const isSerializableObject = (v) => {
409
- const proto = Object.getPrototypeOf(v);
410
- return proto === Object.prototype || proto === Array.prototype || proto === null;
411
- };
412
- const isObject = (v) => {
413
- return !!v && typeof v === 'object';
414
- };
415
- const isArray = (v) => {
416
- return Array.isArray(v);
417
- };
418
- const isString = (v) => {
419
- return typeof v === 'string';
420
- };
421
- const isFunction = (v) => {
422
- return typeof v === 'function';
423
- };
424
-
425
425
  const ASSERT_DISCLAIMER = 'Internal assert, this is likely caused by a bug in Qwik: ';
426
426
  function assertDefined(value, text, ...parts) {
427
427
  if (qDev) {
@@ -641,7 +641,7 @@
641
641
  this.$funcStr$ = fnStr;
642
642
  this.$flags$ = flags;
643
643
  }
644
- $invalidate$() {
644
+ invalidate() {
645
645
  this.$flags$ |= 1 /* SignalFlags.INVALID */;
646
646
  this.$forceRunEffects$ = false;
647
647
  this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
@@ -651,9 +651,8 @@
651
651
  * remained the same object.
652
652
  */
653
653
  force() {
654
- this.$flags$ |= 1 /* SignalFlags.INVALID */;
655
- this.$forceRunEffects$ = false;
656
- triggerEffects(this.$container$, this, this.$effects$);
654
+ this.$forceRunEffects$ = true;
655
+ this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, this.$hostElement$, this, this.$effects$);
657
656
  }
658
657
  get untrackedValue() {
659
658
  const didChange = this.$computeIfNeeded$();
@@ -711,7 +710,6 @@
711
710
  }
712
711
 
713
712
  let _context;
714
- /** @public */
715
713
  const tryGetInvokeContext = () => {
716
714
  if (!_context) {
717
715
  const context = typeof document !== 'undefined' && document && document.__q_context__;
@@ -732,6 +730,7 @@
732
730
  }
733
731
  return ctx;
734
732
  };
733
+ /** @internal */
735
734
  const useInvokeContext = () => {
736
735
  const ctx = tryGetInvokeContext();
737
736
  if (!ctx || ctx.$event$ !== RenderEvent) {
@@ -777,7 +776,7 @@
777
776
  // TODO how about putting url and locale (and event/custom?) in to a "static" object
778
777
  const newInvokeContext = (locale, hostElement, element, event, url) => {
779
778
  // ServerRequestEvent has .locale, but it's not always defined.
780
- const $locale$ = locale || (typeof event === 'object' && event && 'locale' in event ? event.locale : undefined);
779
+ const $locale$ = locale || (event && isObject(event) && 'locale' in event ? event.locale : undefined);
781
780
  const ctx = {
782
781
  $url$: url,
783
782
  $i$: 0,
@@ -857,6 +856,13 @@
857
856
  }
858
857
  };
859
858
  /** @internal */
859
+ const _getContextContainer = () => {
860
+ const iCtx = tryGetInvokeContext();
861
+ if (iCtx) {
862
+ return iCtx.$container$;
863
+ }
864
+ };
865
+ /** @internal */
860
866
  const _jsxBranch = (input) => {
861
867
  return input;
862
868
  };
@@ -1230,7 +1236,7 @@
1230
1236
  *
1231
1237
  * @public
1232
1238
  */
1233
- const version = "2.0.0-beta.3-dev+aa098fc";
1239
+ const version = "2.0.0-beta.4-dev+9849dcf";
1234
1240
 
1235
1241
  /** @internal */
1236
1242
  const EMPTY_ARRAY = [];
@@ -1395,6 +1401,8 @@
1395
1401
  const _VAR_PROPS = Symbol('VAR');
1396
1402
  /** @internal @deprecated v1 compat */
1397
1403
  const _IMMUTABLE = Symbol('IMMUTABLE');
1404
+ /** @internal */
1405
+ const _UNINITIALIZED = Symbol('UNINITIALIZED');
1398
1406
 
1399
1407
  // <docs markdown="../../readme.md#implicit$FirstArg">
1400
1408
  // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
@@ -1464,14 +1472,15 @@
1464
1472
  constructor(container, fn,
1465
1473
  // We need a separate flag to know when the computation needs running because
1466
1474
  // we need the old value to know if effects need running after computation
1467
- flags = 1 /* SignalFlags.INVALID */) {
1475
+ flags = 1 /* SignalFlags.INVALID */ |
1476
+ 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */) {
1468
1477
  // The value is used for comparison when signals trigger, which can only happen
1469
1478
  // when it was calculated before. Therefore we can pass whatever we like.
1470
1479
  super(container, NEEDS_COMPUTATION);
1471
1480
  this.$computeQrl$ = fn;
1472
1481
  this.$flags$ = flags;
1473
1482
  }
1474
- $invalidate$() {
1483
+ invalidate() {
1475
1484
  this.$flags$ |= 1 /* SignalFlags.INVALID */;
1476
1485
  this.$forceRunEffects$ = false;
1477
1486
  this.$container$?.$scheduler$(7 /* ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS */, null, this, this.$effects$);
@@ -1541,7 +1550,7 @@
1541
1550
  */
1542
1551
  class SerializerSignalImpl extends ComputedSignalImpl {
1543
1552
  constructor(container, argQrl) {
1544
- super(container, argQrl);
1553
+ super(container, argQrl, 1 /* SignalFlags.INVALID */ | 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */);
1545
1554
  }
1546
1555
  $didInitialize$ = false;
1547
1556
  $computeIfNeeded$() {
@@ -1557,7 +1566,7 @@
1557
1566
  const update = arg.update;
1558
1567
  const currentValue = this.$untrackedValue$ === NEEDS_COMPUTATION ? initial : this.$untrackedValue$;
1559
1568
  const untrackedValue = trackSignal(() => this.$didInitialize$
1560
- ? update?.(currentValue)
1569
+ ? update?.(currentValue) || currentValue
1561
1570
  : deserialize(currentValue), this, "." /* EffectProperty.VNODE */, this.$container$);
1562
1571
  const didChange = (this.$didInitialize$ && untrackedValue !== 'undefined') ||
1563
1572
  untrackedValue !== this.$untrackedValue$;
@@ -1646,8 +1655,7 @@
1646
1655
  }
1647
1656
  const flags = this.$flags$;
1648
1657
  if (flags & 1 /* StoreFlags.RECURSIVE */ &&
1649
- typeof value === 'object' &&
1650
- value !== null &&
1658
+ isObject(value) &&
1651
1659
  !Object.isFrozen(value) &&
1652
1660
  !isStore(value) &&
1653
1661
  !Object.isFrozen(target)) {
@@ -1825,7 +1833,7 @@
1825
1833
  $loadingEffects$ = null;
1826
1834
  $errorEffects$ = null;
1827
1835
  $destroy$;
1828
- $promiseValue$ = null;
1836
+ $promiseValue$ = NEEDS_COMPUTATION;
1829
1837
  [_EFFECT_BACK_REF] = null;
1830
1838
  constructor(container, fn, flags = 1 /* SignalFlags.INVALID */) {
1831
1839
  super(container, fn, flags);
@@ -1859,6 +1867,10 @@
1859
1867
  get untrackedError() {
1860
1868
  return this.$untrackedError$;
1861
1869
  }
1870
+ invalidate() {
1871
+ super.invalidate();
1872
+ this.$promiseValue$ = NEEDS_COMPUTATION;
1873
+ }
1862
1874
  $computeIfNeeded$() {
1863
1875
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1864
1876
  return false;
@@ -1866,11 +1878,12 @@
1866
1878
  const computeQrl = this.$computeQrl$;
1867
1879
  throwIfQRLNotResolved(computeQrl);
1868
1880
  const [cleanup] = cleanupFn(this, (err) => this.$container$?.handleError(err, null));
1869
- const untrackedValue = this.$promiseValue$ ??
1870
- computeQrl.getFn()({
1881
+ const untrackedValue = this.$promiseValue$ === NEEDS_COMPUTATION
1882
+ ? computeQrl.getFn()({
1871
1883
  track: trackFn(this, this.$container$),
1872
1884
  cleanup,
1873
- });
1885
+ })
1886
+ : this.$promiseValue$;
1874
1887
  if (isPromise(untrackedValue)) {
1875
1888
  this.untrackedLoading = true;
1876
1889
  this.untrackedError = null;
@@ -1881,11 +1894,12 @@
1881
1894
  this.untrackedError = null;
1882
1895
  })
1883
1896
  .catch((err) => {
1897
+ this.$promiseValue$ = err;
1884
1898
  this.untrackedLoading = false;
1885
1899
  this.untrackedError = err;
1886
1900
  });
1887
1901
  }
1888
- this.$promiseValue$ = null;
1902
+ this.$promiseValue$ = NEEDS_COMPUTATION;
1889
1903
  this.$flags$ &= -2 /* SignalFlags.INVALID */;
1890
1904
  const didChange = untrackedValue !== this.$untrackedValue$;
1891
1905
  if (didChange) {
@@ -1900,13 +1914,15 @@
1900
1914
  return new SignalImpl(null, value);
1901
1915
  };
1902
1916
  /** @internal */
1903
- const createComputedSignal = (qrl) => {
1904
- throwIfQRLNotResolved(qrl);
1905
- return new ComputedSignalImpl(null, qrl);
1917
+ const createComputedSignal = (qrl, options) => {
1918
+ return new ComputedSignalImpl(options?.container || null, qrl, getComputedSignalFlags(options?.serializationStrategy || 'always'));
1919
+ };
1920
+ /** @internal */
1921
+ const createAsyncComputedSignal = (qrl, options) => {
1922
+ return new AsyncComputedSignalImpl(options?.container || null, qrl, getComputedSignalFlags(options?.serializationStrategy || 'never'));
1906
1923
  };
1907
1924
  /** @internal */
1908
1925
  const createSerializerSignal = (arg) => {
1909
- throwIfQRLNotResolved(arg);
1910
1926
  return new SerializerSignalImpl(null, arg);
1911
1927
  };
1912
1928
 
@@ -1925,11 +1941,22 @@
1925
1941
  * The QRL must be a function which returns the value of the signal. The function must not have side
1926
1942
  * effects, and it must be synchronous.
1927
1943
  *
1928
- * If you need the function to be async, use `useSignal` and `useTask$` instead.
1944
+ * If you need the function to be async, use `useAsyncComputed$` instead.
1929
1945
  *
1930
1946
  * @public
1931
1947
  */
1932
1948
  const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedSignal);
1949
+ /**
1950
+ * Create an async computed signal which is calculated from the given QRL. A computed signal is a
1951
+ * signal which is calculated from other signals or async operation. When the signals change, the
1952
+ * computed signal is recalculated.
1953
+ *
1954
+ * The QRL must be a function which returns the value of the signal. The function must not have side
1955
+ * effects, and it can be async.
1956
+ *
1957
+ * @public
1958
+ */
1959
+ const createAsyncComputed$ = /*#__PURE__*/ implicit$FirstArg(createAsyncComputedSignal);
1933
1960
  /**
1934
1961
  * Create a signal that holds a custom serializable value. See {@link useSerializer$} for more
1935
1962
  * details.
@@ -1989,17 +2016,6 @@
1989
2016
  // the object is not reactive, so we can just return the value
1990
2017
  return obj[prop];
1991
2018
  };
1992
- /** @internal */
1993
- const _wrapStore = (obj, prop) => {
1994
- const target = getStoreTarget(obj);
1995
- const value = target[prop];
1996
- if (isSignal(value)) {
1997
- return value;
1998
- }
1999
- else {
2000
- return new WrappedSignalImpl(null, getProp, [obj, prop], null, 1 /* SignalFlags.INVALID */);
2001
- }
2002
- };
2003
2019
  /** @internal @deprecated v1 compat */
2004
2020
  const _wrapSignal = (obj, prop) => {
2005
2021
  const r = _wrapProp(obj, prop);
@@ -2434,9 +2450,12 @@
2434
2450
  return jsx;
2435
2451
  }, (err) => {
2436
2452
  if (isPromise(err) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
2437
- return err.then(() => executeComponentWithPromiseExceptionRetry(retryCount++));
2453
+ return err.then(() => executeComponentWithPromiseExceptionRetry(++retryCount));
2438
2454
  }
2439
2455
  else {
2456
+ if (retryCount >= MAX_RETRY_ON_PROMISE_COUNT) {
2457
+ throw new Error(`Max retry count of component execution reached`);
2458
+ }
2440
2459
  throw err;
2441
2460
  }
2442
2461
  });
@@ -4999,10 +5018,12 @@
4999
5018
  return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
5000
5019
  }
5001
5020
  else if (isSignal(resource)) {
5002
- return Promise.resolve(resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
5021
+ const value = retryOnPromise(() => resource.value);
5022
+ const promise = isPromise(value) ? value : Promise.resolve(value);
5023
+ return promise.then(useBindInvokeContext(props.onResolved));
5003
5024
  }
5004
5025
  else {
5005
- return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
5026
+ return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved));
5006
5027
  }
5007
5028
  }
5008
5029
  const _createResourceReturn = (opts) => {
@@ -5533,7 +5554,7 @@
5533
5554
  if (target instanceof ComputedSignalImpl || target instanceof WrappedSignalImpl) {
5534
5555
  const forceRunEffects = target.$forceRunEffects$;
5535
5556
  target.$forceRunEffects$ = false;
5536
- if (!effects?.size) {
5557
+ if (!effects?.size && !forceRunEffects) {
5537
5558
  break;
5538
5559
  }
5539
5560
  // needed for computed signals and throwing QRLs
@@ -6477,7 +6498,7 @@
6477
6498
  container.$scheduler$(1 /* ChoreType.QRL_RESOLVE */, null, consumer.$computeQrl$);
6478
6499
  }
6479
6500
  }
6480
- consumer.$invalidate$();
6501
+ consumer.invalidate();
6481
6502
  }
6482
6503
  else if (property === ":" /* EffectProperty.COMPONENT */) {
6483
6504
  const host = consumer;
@@ -6512,7 +6533,23 @@
6512
6533
  };
6513
6534
  /** @internal */
6514
6535
  const isSerializerObj = (obj) => {
6515
- return (typeof obj === 'object' && obj !== null && typeof obj[SerializerSymbol] === 'function');
6536
+ return isObject(obj) && typeof obj[SerializerSymbol] === 'function';
6537
+ };
6538
+ const getComputedSignalFlags = (serializationStrategy) => {
6539
+ let flags = 1 /* SignalFlags.INVALID */;
6540
+ switch (serializationStrategy) {
6541
+ // TODO: implement this in the future
6542
+ // case 'auto':
6543
+ // flags |= ComputedSignalFlags.SERIALIZATION_STRATEGY_AUTO;
6544
+ // break;
6545
+ case 'never':
6546
+ flags |= 8 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
6547
+ break;
6548
+ case 'always':
6549
+ flags |= 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
6550
+ break;
6551
+ }
6552
+ return flags;
6516
6553
  };
6517
6554
 
6518
6555
  const stringifyPath = [];
@@ -8252,7 +8289,7 @@
8252
8289
  /** There's [documentation](./serialization.md) */
8253
8290
  const deserializedProxyMap = new WeakMap();
8254
8291
  const isDeserializerProxy = (value) => {
8255
- return typeof value === 'object' && value !== null && SERIALIZER_PROXY_UNWRAP in value;
8292
+ return isObject(value) && SERIALIZER_PROXY_UNWRAP in value;
8256
8293
  };
8257
8294
  const SERIALIZER_PROXY_UNWRAP = Symbol('UNWRAP');
8258
8295
  /** Call this on the serialized root state */
@@ -8460,9 +8497,7 @@
8460
8497
  if (hasValue) {
8461
8498
  asyncComputed.$untrackedValue$ = d[6];
8462
8499
  }
8463
- else {
8464
- asyncComputed.$flags$ |= 1 /* SignalFlags.INVALID */;
8465
- }
8500
+ asyncComputed.$flags$ |= 1 /* SignalFlags.INVALID */;
8466
8501
  break;
8467
8502
  }
8468
8503
  // Inflating a SerializerSignal is the same as inflating a ComputedSignal
@@ -8562,7 +8597,7 @@
8562
8597
  propsProxy[_VAR_PROPS] = data === 0 ? {} : data[0];
8563
8598
  propsProxy[_CONST_PROPS] = data[1];
8564
8599
  break;
8565
- case 35 /* TypeIds.EffectData */: {
8600
+ case 35 /* TypeIds.SubscriptionData */: {
8566
8601
  const effectData = target;
8567
8602
  effectData.data.$scopedStyleIdPrefix$ = data[0];
8568
8603
  effectData.data.$isConst$ = data[1];
@@ -8583,6 +8618,7 @@
8583
8618
  EMPTY_OBJ,
8584
8619
  NEEDS_COMPUTATION,
8585
8620
  STORE_ALL_PROPS,
8621
+ _UNINITIALIZED,
8586
8622
  Slot,
8587
8623
  Fragment,
8588
8624
  NaN,
@@ -8602,6 +8638,7 @@
8602
8638
  'EMPTY_OBJ',
8603
8639
  'NEEDS_COMPUTATION',
8604
8640
  'STORE_ALL_PROPS',
8641
+ '_UNINITIALIZED',
8605
8642
  'Slot',
8606
8643
  'Fragment',
8607
8644
  'NaN',
@@ -8623,7 +8660,13 @@
8623
8660
  if (!container.$forwardRefs$) {
8624
8661
  throw qError(18 /* QError.serializeErrorCannotAllocate */, ['forward ref']);
8625
8662
  }
8626
- return container.$getObjectById$(container.$forwardRefs$[value]);
8663
+ const rootRef = container.$forwardRefs$[value];
8664
+ if (rootRef === -1) {
8665
+ return _UNINITIALIZED;
8666
+ }
8667
+ else {
8668
+ return container.$getObjectById$(rootRef);
8669
+ }
8627
8670
  case 2 /* TypeIds.ForwardRefs */:
8628
8671
  return value;
8629
8672
  case 3 /* TypeIds.Constant */:
@@ -8718,7 +8761,7 @@
8718
8761
  else {
8719
8762
  throw qError(17 /* QError.serializeErrorExpectedVNode */, [typeof vNode]);
8720
8763
  }
8721
- case 35 /* TypeIds.EffectData */:
8764
+ case 35 /* TypeIds.SubscriptionData */:
8722
8765
  return new SubscriptionData({});
8723
8766
  default:
8724
8767
  throw qError(18 /* QError.serializeErrorCannotAllocate */, [typeId]);
@@ -8780,7 +8823,7 @@
8780
8823
  };
8781
8824
  }
8782
8825
  const seenObjsMap = new Map();
8783
- const rootsPathMap = new Map();
8826
+ const objectPathStringCache = new Map();
8784
8827
  const syncFnMap = new Map();
8785
8828
  const syncFns = [];
8786
8829
  const roots = [];
@@ -8789,7 +8832,7 @@
8789
8832
  return seenObjsMap.set(obj, { $parent$: parent, $index$: index, $rootIndex$: -1 });
8790
8833
  };
8791
8834
  const $addRootPath$ = (obj) => {
8792
- const rootPath = rootsPathMap.get(obj);
8835
+ const rootPath = objectPathStringCache.get(obj);
8793
8836
  if (rootPath) {
8794
8837
  return rootPath;
8795
8838
  }
@@ -8808,7 +8851,7 @@
8808
8851
  current = seenObjsMap.get(current.$parent$);
8809
8852
  }
8810
8853
  const pathStr = path.length > 1 ? path.join(' ') : path.length ? path[0] : seen.$index$;
8811
- rootsPathMap.set(obj, pathStr);
8854
+ objectPathStringCache.set(obj, pathStr);
8812
8855
  return pathStr;
8813
8856
  };
8814
8857
  const $addRoot$ = (obj, parent = null) => {
@@ -8875,7 +8918,7 @@
8875
8918
  $storeProxyMap$: storeProxyMap,
8876
8919
  $getProp$: getProp,
8877
8920
  $setProp$: setProp,
8878
- $pathMap$: rootsPathMap,
8921
+ $objectPathStringCache$: objectPathStringCache,
8879
8922
  };
8880
8923
  };
8881
8924
  function $discoverRoots$(serializationContext, obj, parent, index) {
@@ -8899,7 +8942,8 @@
8899
8942
  for (let i = 1; i < value.length; i += 2) {
8900
8943
  const keyValue = value[i - 1];
8901
8944
  const attrValue = value[i];
8902
- if (typeof attrValue === 'string' ||
8945
+ if (attrValue == null ||
8946
+ typeof attrValue === 'string' ||
8903
8947
  // skip empty props
8904
8948
  (keyValue === ELEMENT_PROPS &&
8905
8949
  Object.keys(attrValue).length === 0)) {
@@ -8924,6 +8968,14 @@
8924
8968
  this.$qrl$ = $qrl$;
8925
8969
  }
8926
8970
  }
8971
+ class SerializationWeakRef {
8972
+ $obj$;
8973
+ constructor($obj$) {
8974
+ this.$obj$ = $obj$;
8975
+ }
8976
+ }
8977
+ /** @internal */
8978
+ const _serializationWeakRef = (obj) => new SerializationWeakRef(obj);
8927
8979
  /**
8928
8980
  * Format:
8929
8981
  *
@@ -8934,12 +8986,14 @@
8934
8986
  * - Therefore root indexes need to be doubled to get the actual index.
8935
8987
  */
8936
8988
  async function serialize(serializationContext) {
8937
- const { $writer$, $isSsrNode$, $isDomRef$, $storeProxyMap$, $addRoot$, $pathMap$, $wasSeen$ } = serializationContext;
8989
+ const { $writer$, $isSsrNode$, $isDomRef$, $storeProxyMap$, $addRoot$, $objectPathStringCache$, $wasSeen$, } = serializationContext;
8938
8990
  let depth = 0;
8991
+ let rootIdx = 0;
8939
8992
  const forwardRefs = [];
8940
8993
  let forwardRefsId = 0;
8941
8994
  const promises = new Set();
8942
8995
  const preloadQrls = new Set();
8996
+ const s11nWeakRefs = new Map();
8943
8997
  let parent = null;
8944
8998
  const isRootObject = () => depth === 0;
8945
8999
  const outputArray = (value, writeFn) => {
@@ -8984,19 +9038,41 @@
8984
9038
  };
8985
9039
  const addPreloadQrl = (qrl) => {
8986
9040
  preloadQrls.add(qrl);
8987
- serializationContext.$addRoot$(qrl, null);
9041
+ serializationContext.$addRoot$(qrl);
8988
9042
  };
8989
- const outputRootRef = (value, rootDepth = 0) => {
9043
+ const outputAsRootRef = (value, rootDepth = 0) => {
8990
9044
  const seen = $wasSeen$(value);
8991
- const rootRefPath = $pathMap$.get(value);
9045
+ const rootRefPath = $objectPathStringCache$.get(value);
9046
+ // Objects are the only way to create circular dependencies.
9047
+ // So the first thing to to is to see if we have a circular dependency.
9048
+ // (NOTE: For root objects we need to serialize them regardless if we have seen
9049
+ // them before, otherwise the root object reference will point to itself.)
9050
+ // Also note that depth will be 1 for objects in root
8992
9051
  if (rootDepth === depth && seen && seen.$parent$ !== null && rootRefPath) {
8993
9052
  output(0 /* TypeIds.RootRef */, rootRefPath);
8994
9053
  return true;
8995
9054
  }
8996
9055
  else if (depth > rootDepth && seen && seen.$rootIndex$ !== -1) {
9056
+ // We have seen this object before, so we can serialize it as a reference.
9057
+ // Otherwise serialize as normal
8997
9058
  output(0 /* TypeIds.RootRef */, seen.$rootIndex$);
8998
9059
  return true;
8999
9060
  }
9061
+ else if (s11nWeakRefs.has(value)) {
9062
+ const forwardRefId = s11nWeakRefs.get(value);
9063
+ // We see the object again, we must now make it a root and update the forward ref
9064
+ if (rootDepth === depth) {
9065
+ // It's already a root
9066
+ forwardRefs[forwardRefId] = rootIdx;
9067
+ }
9068
+ else {
9069
+ // ref
9070
+ const rootRef = $addRoot$(value);
9071
+ output(0 /* TypeIds.RootRef */, rootRef);
9072
+ forwardRefs[forwardRefId] = rootRef;
9073
+ return true;
9074
+ }
9075
+ }
9000
9076
  return false;
9001
9077
  };
9002
9078
  const writeValue = (value) => {
@@ -9011,13 +9087,13 @@
9011
9087
  }
9012
9088
  else if (typeof value === 'function') {
9013
9089
  if (value === Slot) {
9014
- output(3 /* TypeIds.Constant */, 9 /* Constants.Slot */);
9090
+ output(3 /* TypeIds.Constant */, 10 /* Constants.Slot */);
9015
9091
  }
9016
9092
  else if (value === Fragment) {
9017
- output(3 /* TypeIds.Constant */, 10 /* Constants.Fragment */);
9093
+ output(3 /* TypeIds.Constant */, 11 /* Constants.Fragment */);
9018
9094
  }
9019
9095
  else if (isQrl(value)) {
9020
- if (!outputRootRef(value)) {
9096
+ if (!outputAsRootRef(value)) {
9021
9097
  const qrl = qrlToString(serializationContext, value);
9022
9098
  const type = preloadQrls.has(value) ? 21 /* TypeIds.PreloadQRL */ : 20 /* TypeIds.QRL */;
9023
9099
  if (isRootObject()) {
@@ -9040,19 +9116,19 @@
9040
9116
  }
9041
9117
  else if (typeof value === 'number') {
9042
9118
  if (Number.isNaN(value)) {
9043
- output(3 /* TypeIds.Constant */, 11 /* Constants.NaN */);
9119
+ output(3 /* TypeIds.Constant */, 12 /* Constants.NaN */);
9044
9120
  }
9045
9121
  else if (!Number.isFinite(value)) {
9046
- output(3 /* TypeIds.Constant */, value < 0 ? 13 /* Constants.NegativeInfinity */ : 12 /* Constants.PositiveInfinity */);
9122
+ output(3 /* TypeIds.Constant */, value < 0 ? 14 /* Constants.NegativeInfinity */ : 13 /* Constants.PositiveInfinity */);
9047
9123
  }
9048
9124
  else if (value === Number.MAX_SAFE_INTEGER) {
9049
- output(3 /* TypeIds.Constant */, 14 /* Constants.MaxSafeInt */);
9125
+ output(3 /* TypeIds.Constant */, 15 /* Constants.MaxSafeInt */);
9050
9126
  }
9051
9127
  else if (value === Number.MAX_SAFE_INTEGER - 1) {
9052
- output(3 /* TypeIds.Constant */, 15 /* Constants.AlmostMaxSafeInt */);
9128
+ output(3 /* TypeIds.Constant */, 16 /* Constants.AlmostMaxSafeInt */);
9053
9129
  }
9054
9130
  else if (value === Number.MIN_SAFE_INTEGER) {
9055
- output(3 /* TypeIds.Constant */, 16 /* Constants.MinSafeInt */);
9131
+ output(3 /* TypeIds.Constant */, 17 /* Constants.MinSafeInt */);
9056
9132
  }
9057
9133
  else {
9058
9134
  output(4 /* TypeIds.Number */, value);
@@ -9082,7 +9158,7 @@
9082
9158
  output(3 /* TypeIds.Constant */, 4 /* Constants.EmptyString */);
9083
9159
  }
9084
9160
  else {
9085
- if (!outputRootRef(value)) {
9161
+ if (!outputAsRootRef(value)) {
9086
9162
  output(5 /* TypeIds.String */, value);
9087
9163
  }
9088
9164
  }
@@ -9096,6 +9172,9 @@
9096
9172
  else if (value === STORE_ALL_PROPS) {
9097
9173
  output(3 /* TypeIds.Constant */, 8 /* Constants.STORE_ALL_PROPS */);
9098
9174
  }
9175
+ else if (value === _UNINITIALIZED) {
9176
+ output(3 /* TypeIds.Constant */, 9 /* Constants.UNINITIALIZED */);
9177
+ }
9099
9178
  else {
9100
9179
  throw qError(20 /* QError.serializeErrorUnknownType */, [typeof value]);
9101
9180
  }
@@ -9105,14 +9184,11 @@
9105
9184
  * The object writer outputs an array object (without type prefix) and this increases the depth
9106
9185
  * for the objects within (depth 1).
9107
9186
  */
9108
- // Objects are the only way to create circular dependencies.
9109
- // So the first thing to to is to see if we have a circular dependency.
9110
- // (NOTE: For root objects we need to serialize them regardless if we have seen
9111
- // them before, otherwise the root object reference will point to itself.)
9112
- // Also note that depth will be 1 for objects in root
9113
- if (outputRootRef(value, 1)) {
9187
+ if (outputAsRootRef(value, 1)) {
9114
9188
  return;
9115
9189
  }
9190
+ // handle custom serializers
9191
+ // add to the seen map
9116
9192
  if (isPropsProxy(value)) {
9117
9193
  const varProps = value[_VAR_PROPS];
9118
9194
  const constProps = value[_CONST_PROPS];
@@ -9124,7 +9200,7 @@
9124
9200
  output(34 /* TypeIds.PropsProxy */, out);
9125
9201
  }
9126
9202
  else if (value instanceof SubscriptionData) {
9127
- output(35 /* TypeIds.EffectData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
9203
+ output(35 /* TypeIds.SubscriptionData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
9128
9204
  }
9129
9205
  else if (isStore(value)) {
9130
9206
  if (isResource(value)) {
@@ -9200,14 +9276,6 @@
9200
9276
  output(1 /* TypeIds.ForwardRef */, forwardRefId);
9201
9277
  return;
9202
9278
  }
9203
- /**
9204
- * Special case: when a Signal value is an SSRNode, it always needs to be a DOM ref instead.
9205
- * It can never be meant to become a vNode, because vNodes are internal only.
9206
- */
9207
- const v = value instanceof ComputedSignalImpl &&
9208
- (value.$flags$ & 1 /* SignalFlags.INVALID */ || fastSkipSerialize(value.$untrackedValue$))
9209
- ? NEEDS_COMPUTATION
9210
- : value.$untrackedValue$;
9211
9279
  if (value instanceof WrappedSignalImpl) {
9212
9280
  output(26 /* TypeIds.WrappedSignal */, [
9213
9281
  ...serializeWrappingFn(serializationContext, value),
@@ -9217,35 +9285,34 @@
9217
9285
  ...(value.$effects$ || []),
9218
9286
  ]);
9219
9287
  }
9220
- else if (value instanceof AsyncComputedSignalImpl) {
9221
- addPreloadQrl(value.$computeQrl$);
9222
- const out = [
9223
- value.$computeQrl$,
9224
- value.$effects$,
9225
- value.$loadingEffects$,
9226
- value.$errorEffects$,
9227
- value.$untrackedLoading$,
9228
- value.$untrackedError$,
9229
- ];
9230
- if (v !== NEEDS_COMPUTATION) {
9231
- out.push(v);
9232
- }
9233
- output(28 /* TypeIds.AsyncComputedSignal */, out);
9234
- }
9235
9288
  else if (value instanceof ComputedSignalImpl) {
9289
+ let v = value.$untrackedValue$;
9290
+ const shouldAlwaysSerialize = value.$flags$ & 16 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */;
9291
+ const shouldNeverSerialize = value.$flags$ & 8 /* ComputedSignalFlags.SERIALIZATION_STRATEGY_NEVER */;
9292
+ const isInvalid = value.$flags$ & 1 /* SignalFlags.INVALID */;
9293
+ const isSkippable = fastSkipSerialize(value.$untrackedValue$);
9294
+ if (shouldAlwaysSerialize) {
9295
+ v = value.$untrackedValue$;
9296
+ }
9297
+ else if (shouldNeverSerialize) {
9298
+ v = NEEDS_COMPUTATION;
9299
+ }
9300
+ else if (isInvalid || isSkippable) {
9301
+ v = NEEDS_COMPUTATION;
9302
+ }
9236
9303
  addPreloadQrl(value.$computeQrl$);
9237
- const out = [
9238
- value.$computeQrl$,
9239
- // TODO check if we can use domVRef for effects
9240
- value.$effects$,
9241
- ];
9304
+ const out = [value.$computeQrl$, value.$effects$];
9305
+ const isAsync = value instanceof AsyncComputedSignalImpl;
9306
+ if (isAsync) {
9307
+ out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedLoading$, value.$untrackedError$);
9308
+ }
9242
9309
  if (v !== NEEDS_COMPUTATION) {
9243
9310
  out.push(v);
9244
9311
  }
9245
- output(27 /* TypeIds.ComputedSignal */, out);
9312
+ output(isAsync ? 28 /* TypeIds.AsyncComputedSignal */ : 27 /* TypeIds.ComputedSignal */, out);
9246
9313
  }
9247
9314
  else {
9248
- output(25 /* TypeIds.Signal */, [v, ...(value.$effects$ || [])]);
9315
+ output(25 /* TypeIds.Signal */, [value.$untrackedValue$, ...(value.$effects$ || [])]);
9249
9316
  }
9250
9317
  }
9251
9318
  else if (value instanceof URL) {
@@ -9380,6 +9447,12 @@
9380
9447
  const out = btoa(buf).replace(/=+$/, '');
9381
9448
  output(19 /* TypeIds.Uint8Array */, out);
9382
9449
  }
9450
+ else if (value instanceof SerializationWeakRef) {
9451
+ const forwardRefId = forwardRefsId++;
9452
+ s11nWeakRefs.set(value.$obj$, forwardRefId);
9453
+ forwardRefs[forwardRefId] = -1;
9454
+ output(1 /* TypeIds.ForwardRef */, forwardRefId);
9455
+ }
9383
9456
  else if (vnode_isVNode(value)) {
9384
9457
  output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
9385
9458
  }
@@ -9403,21 +9476,20 @@
9403
9476
  }
9404
9477
  const outputRoots = async () => {
9405
9478
  $writer$.write('[');
9406
- let lastRootsLength = 0;
9407
9479
  let rootsLength = serializationContext.$roots$.length;
9408
- while (lastRootsLength < rootsLength || promises.size) {
9409
- if (lastRootsLength !== 0) {
9480
+ while (rootIdx < rootsLength || promises.size) {
9481
+ if (rootIdx !== 0) {
9410
9482
  $writer$.write(',');
9411
9483
  }
9412
9484
  let separator = false;
9413
- for (let i = lastRootsLength; i < rootsLength; i++) {
9485
+ for (; rootIdx < rootsLength; rootIdx++) {
9414
9486
  if (separator) {
9415
9487
  $writer$.write(',');
9416
9488
  }
9417
9489
  else {
9418
9490
  separator = true;
9419
9491
  }
9420
- writeValue(serializationContext.$roots$[i]);
9492
+ writeValue(serializationContext.$roots$[rootIdx]);
9421
9493
  }
9422
9494
  if (promises.size) {
9423
9495
  try {
@@ -9427,7 +9499,6 @@
9427
9499
  // ignore rejections, they will be serialized as rejected promises
9428
9500
  }
9429
9501
  }
9430
- lastRootsLength = rootsLength;
9431
9502
  rootsLength = serializationContext.$roots$.length;
9432
9503
  }
9433
9504
  if (forwardRefs.length) {
@@ -9733,7 +9804,7 @@
9733
9804
  return (
9734
9805
  // THINK: Not sure if we need to keep track of functions (QRLs) Let's skip them for now.
9735
9806
  // and see if we have a test case which requires them.
9736
- (typeof obj === 'object' && obj !== null) ||
9807
+ isObject(obj) ||
9737
9808
  /**
9738
9809
  * We track all strings greater than 1 character, because those take at least 6 bytes to encode
9739
9810
  * and even with 999 root objects it saves one byte per reference. Tracking more objects makes
@@ -9761,9 +9832,7 @@
9761
9832
  return '__brand' in value && value.__brand === 'resource';
9762
9833
  }
9763
9834
  const frameworkType = (obj) => {
9764
- return ((typeof obj === 'object' &&
9765
- obj !== null &&
9766
- (obj instanceof SignalImpl || obj instanceof Task || isJSXNode(obj))) ||
9835
+ return ((isObject(obj) && (obj instanceof SignalImpl || obj instanceof Task || isJSXNode(obj))) ||
9767
9836
  isQrl(obj));
9768
9837
  };
9769
9838
  const canSerialize = (value, seen = new WeakSet()) => {
@@ -9849,6 +9918,9 @@
9849
9918
  return true;
9850
9919
  }
9851
9920
  }
9921
+ else if (value === _UNINITIALIZED) {
9922
+ return true;
9923
+ }
9852
9924
  return false;
9853
9925
  };
9854
9926
  const QRL_RUNTIME_CHUNK = 'mock-chunk';
@@ -9888,12 +9960,12 @@
9888
9960
  'FormData',
9889
9961
  'JSXNode',
9890
9962
  'PropsProxy',
9891
- 'EffectData',
9963
+ 'SubscriptionData',
9892
9964
  ];
9893
9965
  const circularProofJson = (obj, indent) => {
9894
9966
  const seen = new WeakSet();
9895
- return JSON.stringify(obj, (key, value) => {
9896
- if (typeof value === 'object' && value !== null) {
9967
+ return JSON.stringify(obj, (_, value) => {
9968
+ if (isObject(value)) {
9897
9969
  if (seen.has(value)) {
9898
9970
  return `[Circular ${value.constructor.name}]`;
9899
9971
  }
@@ -9930,7 +10002,7 @@
9930
10002
  let value = state[++i];
9931
10003
  if (key === undefined) {
9932
10004
  hasRaw = true;
9933
- out.push(`${RED}[raw${typeof value === 'object' && value ? ` ${value.constructor.name}` : ''}]${RESET} ${printRaw(value, `${prefix} `)}`);
10005
+ out.push(`${RED}[raw${isObject(value) ? ` ${value.constructor.name}` : ''}]${RESET} ${printRaw(value, `${prefix} `)}`);
9934
10006
  }
9935
10007
  else {
9936
10008
  if (key === 3 /* TypeIds.Constant */) {
@@ -10044,7 +10116,6 @@
10044
10116
  return value;
10045
10117
  };
10046
10118
  const noSerializeSet = /*#__PURE__*/ new WeakSet();
10047
- const weakSerializeSet = /*#__PURE__*/ new WeakSet();
10048
10119
  const shouldSerialize = (obj) => {
10049
10120
  if (isObject(obj) || isFunction(obj)) {
10050
10121
  return !noSerializeSet.has(obj);
@@ -10053,7 +10124,7 @@
10053
10124
  };
10054
10125
  const fastSkipSerialize = (obj) => {
10055
10126
  return (obj &&
10056
- (typeof obj === 'object' || typeof obj === 'function') &&
10127
+ (isObject(obj) || typeof obj === 'function') &&
10057
10128
  (NoSerializeSymbol in obj || noSerializeSet.has(obj)));
10058
10129
  };
10059
10130
  // <docs markdown="../../readme.md#noSerialize">
@@ -10078,16 +10149,11 @@
10078
10149
  // </docs>
10079
10150
  const noSerialize = (input) => {
10080
10151
  // only add supported values to the noSerializeSet, prevent console errors
10081
- if ((typeof input === 'object' && input !== null) || typeof input === 'function') {
10152
+ if ((isObject(input) && input !== null) || typeof input === 'function') {
10082
10153
  noSerializeSet.add(input);
10083
10154
  }
10084
10155
  return input;
10085
10156
  };
10086
- /** @internal */
10087
- const _weakSerialize = (input) => {
10088
- weakSerializeSet.add(input);
10089
- return input;
10090
- };
10091
10157
  /**
10092
10158
  * If an object has this property, it will not be serialized. Use this on prototypes to avoid having
10093
10159
  * to call `noSerialize()` on every object.
@@ -11291,13 +11357,13 @@
11291
11357
  return set(value);
11292
11358
  };
11293
11359
 
11294
- const useComputedCommon = (qrl, Class) => {
11360
+ const useComputedCommon = (qrl, createFn, options) => {
11295
11361
  const { val, set } = useSequentialScope();
11296
11362
  if (val) {
11297
11363
  return val;
11298
11364
  }
11299
11365
  assertQrl(qrl);
11300
- const signal = new Class(null, qrl);
11366
+ const signal = createFn(qrl, options);
11301
11367
  set(signal);
11302
11368
  // Note that we first save the signal
11303
11369
  // and then we throw to load the qrl
@@ -11306,8 +11372,8 @@
11306
11372
  return signal;
11307
11373
  };
11308
11374
  /** @internal */
11309
- const useComputedQrl = (qrl) => {
11310
- return useComputedCommon(qrl, ComputedSignalImpl);
11375
+ const useComputedQrl = (qrl, options) => {
11376
+ return useComputedCommon(qrl, createComputedSignal, options);
11311
11377
  };
11312
11378
  /**
11313
11379
  * Creates a computed signal which is calculated from the given function. A computed signal is a
@@ -11322,7 +11388,7 @@
11322
11388
  const useComputed$ = implicit$FirstArg(useComputedQrl);
11323
11389
 
11324
11390
  /** @internal */
11325
- const useSerializerQrl = (qrl) => useComputedCommon(qrl, SerializerSignalImpl);
11391
+ const useSerializerQrl = (qrl) => useComputedCommon(qrl, createSerializerSignal);
11326
11392
  /**
11327
11393
  * Creates a signal which holds a custom serializable value. It requires that the value implements
11328
11394
  * the `CustomSerializable` type, which means having a function under the `[SerializeSymbol]`
@@ -11577,8 +11643,8 @@
11577
11643
  const useVisibleTask$ = /*#__PURE__*/ implicit$FirstArg(useVisibleTaskQrl);
11578
11644
 
11579
11645
  /** @internal */
11580
- const useAsyncComputedQrl = (qrl) => {
11581
- return useComputedCommon(qrl, AsyncComputedSignalImpl);
11646
+ const useAsyncComputedQrl = (qrl, options) => {
11647
+ return useComputedCommon(qrl, createAsyncComputedSignal, options);
11582
11648
  };
11583
11649
  /**
11584
11650
  * Creates a computed signal which is calculated from the given function. A computed signal is a
@@ -11702,10 +11768,12 @@
11702
11768
  exports._IMMUTABLE = _IMMUTABLE;
11703
11769
  exports._SharedContainer = _SharedContainer;
11704
11770
  exports._SubscriptionData = SubscriptionData;
11771
+ exports._UNINITIALIZED = _UNINITIALIZED;
11705
11772
  exports._VAR_PROPS = _VAR_PROPS;
11706
11773
  exports._deserialize = _deserialize;
11707
11774
  exports._dumpState = dumpState;
11708
11775
  exports._fnSignal = _fnSignal;
11776
+ exports._getContextContainer = _getContextContainer;
11709
11777
  exports._getContextElement = _getContextElement;
11710
11778
  exports._getContextEvent = _getContextEvent;
11711
11779
  exports._getDomContainer = getDomContainer;
@@ -11725,18 +11793,20 @@
11725
11793
  exports._regSymbol = _regSymbol;
11726
11794
  exports._restProps = _restProps;
11727
11795
  exports._run = queueQRL;
11796
+ exports._serializationWeakRef = _serializationWeakRef;
11728
11797
  exports._serialize = _serialize;
11729
11798
  exports._task = scheduleTask;
11799
+ exports._useInvokeContext = useInvokeContext;
11730
11800
  exports._verifySerializable = verifySerializable;
11731
11801
  exports._vnode_toString = vnode_toString;
11732
11802
  exports._waitUntilRendered = _waitUntilRendered;
11733
11803
  exports._walkJSX = _walkJSX;
11734
- exports._weakSerialize = _weakSerialize;
11735
11804
  exports._wrapProp = _wrapProp;
11736
11805
  exports._wrapSignal = _wrapSignal;
11737
- exports._wrapStore = _wrapStore;
11738
11806
  exports.component$ = component$;
11739
11807
  exports.componentQrl = componentQrl;
11808
+ exports.createAsyncComputed$ = createAsyncComputed$;
11809
+ exports.createAsyncComputedQrl = createAsyncComputedSignal;
11740
11810
  exports.createComputed$ = createComputed$;
11741
11811
  exports.createComputedQrl = createComputedSignal;
11742
11812
  exports.createContextId = createContextId;