@qwik.dev/core 2.0.0-alpha.4 → 2.0.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * @qwik.dev/core 2.0.0-alpha.4-dev+374e0d6
3
+ * @qwik.dev/core 2.0.0-alpha.6-dev+d848ba5
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
@@ -149,7 +149,7 @@ const codeToText = (code, ...parts) => {
149
149
  'SsrError(tag): {{0}}', // 29
150
150
  'QRLs can not be resolved because it does not have an attached container. This means that the QRL does not know where it belongs inside the DOM, so it cant dynamically import() from a relative path.', // 30
151
151
  'QRLs can not be dynamically resolved, because it does not have a chunk path', // 31
152
- 'The JSX ref attribute must be a Signal', // 32
152
+ '{{0}}\nThe JSX ref attribute must be a Signal', // 32
153
153
  'Serialization Error: Deserialization of data type {{0}} is not implemented', // 33
154
154
  'Serialization Error: Expected vnode for ref prop, but got {{0}}', // 34
155
155
  'Serialization Error: Cannot allocate data type {{0}}', // 35
@@ -157,12 +157,11 @@ const codeToText = (code, ...parts) => {
157
157
  'Serialization Error: Serialization of data type {{0}} is not implemented', // 37
158
158
  'Serialization Error: Unvisited {{0}}', // 38
159
159
  'Serialization Error: Missing QRL chunk for {{0}}', // 39
160
- 'The value of the textarea must be a string', // 40
160
+ '{{0}}\nThe value of the textarea must be a string found {{1}}', // 40
161
161
  'Unable to find q:container', // 41
162
162
  "Element must have 'q:container' attribute.", // 42
163
163
  'Unknown vnode type {{0}}.', // 43
164
164
  'Materialize error: missing element: {{0}} {{1}} {{2}}', // 44
165
- 'SsrError: {{0}}', // 45
166
165
  'Cannot coerce a Signal, use `.value` instead', // 46
167
166
  'useComputedSignal$ QRL {{0}} {{1}} returned a Promise', // 47
168
167
  'ComputedSignal is read-only', // 48
@@ -234,19 +233,130 @@ var QError;
234
233
  QError[QError["elementWithoutContainer"] = 42] = "elementWithoutContainer";
235
234
  QError[QError["invalidVNodeType"] = 43] = "invalidVNodeType";
236
235
  QError[QError["materializeVNodeDataError"] = 44] = "materializeVNodeDataError";
237
- QError[QError["serverHostMismatch"] = 45] = "serverHostMismatch";
238
- QError[QError["cannotCoerceSignal"] = 46] = "cannotCoerceSignal";
239
- QError[QError["computedNotSync"] = 47] = "computedNotSync";
240
- QError[QError["computedReadOnly"] = 48] = "computedReadOnly";
241
- QError[QError["wrappedReadOnly"] = 49] = "wrappedReadOnly";
242
- QError[QError["promisesNotExpected"] = 50] = "promisesNotExpected";
243
- QError[QError["unsafeAttr"] = 51] = "unsafeAttr";
236
+ QError[QError["cannotCoerceSignal"] = 45] = "cannotCoerceSignal";
237
+ QError[QError["computedNotSync"] = 46] = "computedNotSync";
238
+ QError[QError["computedReadOnly"] = 47] = "computedReadOnly";
239
+ QError[QError["wrappedReadOnly"] = 48] = "wrappedReadOnly";
240
+ QError[QError["promisesNotExpected"] = 49] = "promisesNotExpected";
241
+ QError[QError["unsafeAttr"] = 50] = "unsafeAttr";
244
242
  })(QError || (QError = {}));
245
243
  const qError = (code, errorMessageArgs = []) => {
246
244
  const text = codeToText(code, ...errorMessageArgs);
247
245
  return logErrorAndStop(text, ...errorMessageArgs);
248
246
  };
249
247
 
248
+ /**
249
+ * A friendly name tag for a VirtualVNode.
250
+ *
251
+ * Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
252
+ *
253
+ * The name is only added in development mode and is not included in production builds.
254
+ */
255
+ const DEBUG_TYPE = 'q:type';
256
+ var VirtualType;
257
+ (function (VirtualType) {
258
+ VirtualType["Virtual"] = "V";
259
+ VirtualType["Fragment"] = "F";
260
+ VirtualType["WrappedSignal"] = "S";
261
+ VirtualType["Awaited"] = "A";
262
+ VirtualType["Component"] = "C";
263
+ VirtualType["InlineComponent"] = "I";
264
+ VirtualType["Projection"] = "P";
265
+ })(VirtualType || (VirtualType = {}));
266
+ const START = '\x1b[34m';
267
+ const END = '\x1b[0m';
268
+ const VirtualTypeName = {
269
+ [VirtualType.Virtual]: /* ********* */ START + 'Virtual' + END, //
270
+ [VirtualType.Fragment]: /* ******** */ START + 'Fragment' + END, //
271
+ [VirtualType.WrappedSignal]: /* *** */ START + 'Signal' + END, //
272
+ [VirtualType.Awaited]: /* ********* */ START + 'Awaited' + END, //
273
+ [VirtualType.Component]: /* ******* */ START + 'Component' + END, //
274
+ [VirtualType.InlineComponent]: /* * */ START + 'InlineComponent' + END, //
275
+ [VirtualType.Projection]: /* ****** */ START + 'Projection' + END, //
276
+ };
277
+ var QContainerValue;
278
+ (function (QContainerValue) {
279
+ QContainerValue["PAUSED"] = "paused";
280
+ QContainerValue["RESUMED"] = "resumed";
281
+ // these values below are used in the qwik loader as a plain text for the q:container selector
282
+ // standard dangerouslySetInnerHTML
283
+ QContainerValue["HTML"] = "html";
284
+ // textarea
285
+ QContainerValue["TEXT"] = "text";
286
+ })(QContainerValue || (QContainerValue = {}));
287
+
288
+ /** State factory of the component. */
289
+ const OnRenderProp = 'q:renderFn';
290
+ /** Component style content prefix */
291
+ const ComponentStylesPrefixContent = '⭐️';
292
+ /** `<some-element q:slot="...">` */
293
+ const QSlot = 'q:slot';
294
+ const QSlotParent = ':';
295
+ const QSlotRef = 'q:sref';
296
+ const QSlotS = 'q:s';
297
+ const QStyle = 'q:style';
298
+ const QStyleSelector = 'style[q\\:style]';
299
+ const QStyleSSelector = 'style[q\\:sstyle]';
300
+ const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
301
+ const QScopedStyle = 'q:sstyle';
302
+ const QCtxAttr = 'q:ctx';
303
+ const QSubscribers = 'q:subs';
304
+ const QFuncsPrefix = 'qFuncs_';
305
+ const getQFuncs = (document, hash) => {
306
+ return document[QFuncsPrefix + hash] || [];
307
+ };
308
+ const QBaseAttr = 'q:base';
309
+ const QLocaleAttr = 'q:locale';
310
+ const QManifestHashAttr = 'q:manifest-hash';
311
+ const QInstanceAttr = 'q:instance';
312
+ const QContainerIsland = 'q:container-island';
313
+ const QContainerIslandEnd = '/' + QContainerIsland;
314
+ const QIgnore = 'q:ignore';
315
+ const QIgnoreEnd = '/' + QIgnore;
316
+ const QContainerAttr = 'q:container';
317
+ const QContainerAttrEnd = '/' + QContainerAttr;
318
+ const QTemplate = 'q:template';
319
+ // the same selector should be inside the qwik loader
320
+ // and the same selector should be inside the qwik router spa-shim and spa-init
321
+ const QContainerSelector = '[q\\:container]:not([q\\:container=' +
322
+ QContainerValue.HTML +
323
+ ']):not([q\\:container=' +
324
+ QContainerValue.TEXT +
325
+ '])';
326
+ const HTML_NS = 'http://www.w3.org/1999/xhtml';
327
+ const SVG_NS = 'http://www.w3.org/2000/svg';
328
+ const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
329
+ const ResourceEvent = 'qResource';
330
+ const RenderEvent = 'qRender';
331
+ const TaskEvent = 'qTask';
332
+ const QDefaultSlot = '';
333
+ /**
334
+ * Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
335
+ *
336
+ * As the VNode get materialized the vnode now becomes eligible for mutation. Once the vnode mutates
337
+ * the `VNode` references from the `qwik/json` may become invalid. For this reason, these references
338
+ * need to be eagerly resolved. `VNODE_REF` stores a pointer to "this" vnode. This allows the system
339
+ * to eagerly resolve these pointes as the vnodes are materialized.
340
+ */
341
+ const ELEMENT_ID = 'q:id';
342
+ const ELEMENT_KEY = 'q:key';
343
+ const ELEMENT_PROPS = 'q:props';
344
+ const ELEMENT_SEQ = 'q:seq';
345
+ const ELEMENT_SEQ_IDX = 'q:seqIdx';
346
+ const Q_PREFIX = 'q:';
347
+ /** Non serializable markers - always begins with `:` character */
348
+ const NON_SERIALIZABLE_MARKER_PREFIX = ':';
349
+ const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
350
+ const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
351
+ const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
352
+ // comment nodes
353
+ const FLUSH_COMMENT = 'qkssr-f';
354
+ const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
355
+ const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
356
+ const Q_PROPS_SEPARATOR = ':';
357
+ const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
358
+ const qwikInspectorAttr = 'data-qwik-inspector';
359
+
250
360
  // keep this import from core/build so the cjs build works
251
361
  const createPlatform = () => {
252
362
  return {
@@ -307,7 +417,7 @@ const createPlatform = () => {
307
417
  */
308
418
  const toUrl = (doc, containerEl, url) => {
309
419
  const baseURI = doc.baseURI;
310
- const base = new URL(containerEl.getAttribute('q:base') ?? baseURI, baseURI);
420
+ const base = new URL(containerEl.getAttribute(QBaseAttr) ?? baseURI, baseURI);
311
421
  return new URL(url, base);
312
422
  };
313
423
  let _platform = /*#__PURE__ */ createPlatform();
@@ -399,15 +509,24 @@ const delay = (timeout) => {
399
509
  setTimeout(resolve, timeout);
400
510
  });
401
511
  };
512
+ // Retries a function that throws a promise.
402
513
  function retryOnPromise(fn, retryCount = 0) {
403
- try {
404
- return fn();
405
- }
406
- catch (e) {
514
+ const retryOrThrow = (e) => {
407
515
  if (isPromise(e) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
408
516
  return e.then(retryOnPromise.bind(null, fn, retryCount++));
409
517
  }
410
518
  throw e;
519
+ };
520
+ try {
521
+ const result = fn();
522
+ if (isPromise(result)) {
523
+ // not awaited promise is not caught by try/catch block
524
+ return result.catch((e) => retryOrThrow(e));
525
+ }
526
+ return result;
527
+ }
528
+ catch (e) {
529
+ return retryOrThrow(e);
411
530
  }
412
531
  }
413
532
 
@@ -450,118 +569,6 @@ var VNodeDataFlag;
450
569
  VNodeDataFlag[VNodeDataFlag["SERIALIZE"] = 16] = "SERIALIZE";
451
570
  })(VNodeDataFlag || (VNodeDataFlag = {}));
452
571
 
453
- /**
454
- * A friendly name tag for a VirtualVNode.
455
- *
456
- * Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
457
- *
458
- * The name is only added in development mode and is not included in production builds.
459
- */
460
- const DEBUG_TYPE = 'q:type';
461
- var VirtualType;
462
- (function (VirtualType) {
463
- VirtualType["Virtual"] = "V";
464
- VirtualType["Fragment"] = "F";
465
- VirtualType["WrappedSignal"] = "S";
466
- VirtualType["Awaited"] = "A";
467
- VirtualType["Component"] = "C";
468
- VirtualType["InlineComponent"] = "I";
469
- VirtualType["Projection"] = "P";
470
- })(VirtualType || (VirtualType = {}));
471
- const START = '\x1b[34m';
472
- const END = '\x1b[0m';
473
- const VirtualTypeName = {
474
- [VirtualType.Virtual]: /* ********* */ START + 'Virtual' + END, //
475
- [VirtualType.Fragment]: /* ******** */ START + 'Fragment' + END, //
476
- [VirtualType.WrappedSignal]: /* *** */ START + 'Signal' + END, //
477
- [VirtualType.Awaited]: /* ********* */ START + 'Awaited' + END, //
478
- [VirtualType.Component]: /* ******* */ START + 'Component' + END, //
479
- [VirtualType.InlineComponent]: /* * */ START + 'InlineComponent' + END, //
480
- [VirtualType.Projection]: /* ****** */ START + 'Projection' + END, //
481
- };
482
- var QContainerValue;
483
- (function (QContainerValue) {
484
- QContainerValue["PAUSED"] = "paused";
485
- QContainerValue["RESUMED"] = "resumed";
486
- // these values below are used in the qwik loader as a plain text for the q:container selector
487
- // standard dangerouslySetInnerHTML
488
- QContainerValue["HTML"] = "html";
489
- // textarea
490
- QContainerValue["TEXT"] = "text";
491
- })(QContainerValue || (QContainerValue = {}));
492
-
493
- /** State factory of the component. */
494
- const OnRenderProp = 'q:renderFn';
495
- /** Component style content prefix */
496
- const ComponentStylesPrefixContent = '⭐️';
497
- /** `<some-element q:slot="...">` */
498
- const QSlot = 'q:slot';
499
- const QSlotParent = ':';
500
- const QSlotRef = 'q:sref';
501
- const QSlotS = 'q:s';
502
- const QStyle = 'q:style';
503
- const QStyleSelector = 'style[q\\:style]';
504
- const QStyleSSelector = 'style[q\\:sstyle]';
505
- const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
506
- const QScopedStyle = 'q:sstyle';
507
- const QCtxAttr = 'q:ctx';
508
- const QSubscribers = 'q:subs';
509
- const QFuncsPrefix = 'qFuncs_';
510
- const getQFuncs = (document, hash) => {
511
- return document[QFuncsPrefix + hash] || [];
512
- };
513
- const QBaseAttr = 'q:base';
514
- const QLocaleAttr = 'q:locale';
515
- const QManifestHashAttr = 'q:manifest-hash';
516
- const QInstanceAttr = 'q:instance';
517
- const QContainerIsland = 'q:container-island';
518
- const QContainerIslandEnd = '/' + QContainerIsland;
519
- const QIgnore = 'q:ignore';
520
- const QIgnoreEnd = '/' + QIgnore;
521
- const QContainerAttr = 'q:container';
522
- const QContainerAttrEnd = '/' + QContainerAttr;
523
- const QTemplate = 'q:template';
524
- // the same selector should be inside the qwik loader
525
- // and the same selector should be inside the qwik router spa-shim and spa-init
526
- const QContainerSelector = '[q\\:container]:not([q\\:container=' +
527
- QContainerValue.HTML +
528
- ']):not([q\\:container=' +
529
- QContainerValue.TEXT +
530
- '])';
531
- const HTML_NS = 'http://www.w3.org/1999/xhtml';
532
- const SVG_NS = 'http://www.w3.org/2000/svg';
533
- const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
534
- const ResourceEvent = 'qResource';
535
- const RenderEvent = 'qRender';
536
- const TaskEvent = 'qTask';
537
- const QDefaultSlot = '';
538
- /**
539
- * Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
540
- *
541
- * As the VNode get materialized the vnode now becomes eligible for mutation. Once the vnode mutates
542
- * the `VNode` references from the `qwik/json` may become invalid. For this reason, these references
543
- * need to be eagerly resolved. `VNODE_REF` stores a pointer to "this" vnode. This allows the system
544
- * to eagerly resolve these pointes as the vnodes are materialized.
545
- */
546
- const ELEMENT_ID = 'q:id';
547
- const ELEMENT_KEY = 'q:key';
548
- const ELEMENT_PROPS = 'q:props';
549
- const ELEMENT_SEQ = 'q:seq';
550
- const ELEMENT_SEQ_IDX = 'q:seqIdx';
551
- const Q_PREFIX = 'q:';
552
- /** Non serializable markers - always begins with `:` character */
553
- const NON_SERIALIZABLE_MARKER_PREFIX = ':';
554
- const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
555
- const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
556
- const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
557
- // comment nodes
558
- const FLUSH_COMMENT = 'qkssr-f';
559
- const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
560
- const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
561
- const Q_PROPS_SEPARATOR = ':';
562
- const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
563
- const qwikInspectorAttr = 'data-qwik-inspector';
564
-
565
572
  let _locale = undefined;
566
573
  /**
567
574
  * Retrieve the current locale.
@@ -1135,7 +1142,6 @@ class StoreHandler {
1135
1142
  }
1136
1143
  /** In the case of oldValue and value are the same, the effects are not triggered. */
1137
1144
  set(target, prop, value) {
1138
- target = unwrapDeserializerProxy(target);
1139
1145
  if (typeof prop === 'symbol') {
1140
1146
  target[prop] = value;
1141
1147
  return true;
@@ -1204,6 +1210,8 @@ function addEffect(target, prop, store, effectSubscriber) {
1204
1210
  // to unsubscribe from. So we need to store the reference from the effect back
1205
1211
  // to this signal.
1206
1212
  ensureContains(effectSubscriber, target);
1213
+ // We need to add the subscriber to the effect so that we can clean it up later
1214
+ ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], target, store.$container$);
1207
1215
  }
1208
1216
  function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
1209
1217
  target[prop] = value;
@@ -1274,32 +1282,40 @@ function clearVNodeEffectDependencies(container, value) {
1274
1282
  }
1275
1283
  for (let i = effects.length - 1; i >= 0; i--) {
1276
1284
  const subscriber = effects[i];
1277
- const subscriptionRemoved = clearEffects(subscriber, value);
1278
- if (subscriptionRemoved) {
1279
- effects.splice(i, 1);
1280
- }
1285
+ clearEffects(subscriber, value, effects, i, container);
1286
+ }
1287
+ if (effects.length === 0) {
1288
+ vnode_setProp(value, QSubscribers, null);
1281
1289
  }
1282
1290
  }
1283
- function clearSubscriberEffectDependencies(value) {
1291
+ function clearSubscriberEffectDependencies(container, value) {
1284
1292
  if (value.$effectDependencies$) {
1285
1293
  for (let i = value.$effectDependencies$.length - 1; i >= 0; i--) {
1286
1294
  const subscriber = value.$effectDependencies$[i];
1287
- const subscriptionRemoved = clearEffects(subscriber, value);
1288
- if (subscriptionRemoved) {
1289
- value.$effectDependencies$.splice(i, 1);
1290
- }
1295
+ clearEffects(subscriber, value, value.$effectDependencies$, i, container);
1296
+ }
1297
+ if (value.$effectDependencies$.length === 0) {
1298
+ value.$effectDependencies$ = null;
1291
1299
  }
1292
1300
  }
1293
1301
  }
1294
- function clearEffects(subscriber, value) {
1295
- if (!isSignal(subscriber)) {
1296
- return false;
1302
+ function clearEffects(subscriber, value, effectArray, indexToRemove, container) {
1303
+ let subscriptionRemoved = false;
1304
+ const seenSet = new Set();
1305
+ if (subscriber instanceof WrappedSignal) {
1306
+ subscriptionRemoved = clearSignalEffects(subscriber, value, seenSet);
1297
1307
  }
1298
- const effectSubscriptions = subscriber.$effects$;
1299
- const hostElement = subscriber.$hostElement$;
1300
- if (hostElement && hostElement === value) {
1301
- subscriber.$hostElement$ = null;
1308
+ else if (container.$storeProxyMap$.has(subscriber)) {
1309
+ const store = container.$storeProxyMap$.get(subscriber);
1310
+ const handler = getStoreHandler(store);
1311
+ subscriptionRemoved = clearStoreEffects(handler, value);
1302
1312
  }
1313
+ if (subscriptionRemoved) {
1314
+ effectArray.splice(indexToRemove, 1);
1315
+ }
1316
+ }
1317
+ function clearSignalEffects(subscriber, value, seenSet) {
1318
+ const effectSubscriptions = subscriber.$effects$;
1303
1319
  let subscriptionRemoved = false;
1304
1320
  if (effectSubscriptions) {
1305
1321
  for (let i = effectSubscriptions.length - 1; i >= 0; i--) {
@@ -1310,15 +1326,84 @@ function clearEffects(subscriber, value) {
1310
1326
  }
1311
1327
  }
1312
1328
  }
1313
- // clear the effects of the arguments
1314
- const args = subscriber.$args$;
1315
- if (args) {
1316
- for (let i = args.length - 1; i >= 0; i--) {
1317
- clearEffects(args[i], subscriber);
1329
+ if (subscriber instanceof WrappedSignal) {
1330
+ const hostElement = subscriber.$hostElement$;
1331
+ if (hostElement && hostElement === value) {
1332
+ subscriber.$hostElement$ = null;
1333
+ }
1334
+ // clear the effects of the arguments
1335
+ const args = subscriber.$args$;
1336
+ if (args) {
1337
+ clearArgsEffects(args, subscriber, seenSet);
1318
1338
  }
1319
1339
  }
1320
1340
  return subscriptionRemoved;
1321
1341
  }
1342
+ function clearStoreEffects(storeHandler, value) {
1343
+ const effectSubscriptions = storeHandler.$effects$;
1344
+ if (!effectSubscriptions) {
1345
+ return false;
1346
+ }
1347
+ let subscriptionRemoved = false;
1348
+ for (const key in effectSubscriptions) {
1349
+ const effects = effectSubscriptions[key];
1350
+ for (let i = effects.length - 1; i >= 0; i--) {
1351
+ const effect = effects[i];
1352
+ if (effect[EffectSubscriptionsProp.EFFECT] === value) {
1353
+ effects.splice(i, 1);
1354
+ subscriptionRemoved = true;
1355
+ }
1356
+ }
1357
+ if (effects.length === 0) {
1358
+ delete effectSubscriptions[key];
1359
+ }
1360
+ }
1361
+ return subscriptionRemoved;
1362
+ }
1363
+ function clearArgsEffects(args, subscriber, seenSet) {
1364
+ for (let i = args.length - 1; i >= 0; i--) {
1365
+ const arg = args[i];
1366
+ clearArgEffect(arg, subscriber, seenSet);
1367
+ }
1368
+ }
1369
+ function clearArgEffect(arg, subscriber, seenSet) {
1370
+ if (seenSet.has(arg)) {
1371
+ return;
1372
+ }
1373
+ seenSet.add(arg);
1374
+ if (isSignal(arg)) {
1375
+ clearSignalEffects(arg, subscriber, seenSet);
1376
+ }
1377
+ else if (typeof arg === 'object' && arg !== null) {
1378
+ if (isStore(arg)) {
1379
+ clearStoreEffects(getStoreHandler(arg), subscriber);
1380
+ }
1381
+ else if (isPropsProxy(arg)) {
1382
+ // Separate check for props proxy, because props proxy getter could call signal getter.
1383
+ // To avoid that we need to get the constProps and varProps directly
1384
+ // from the props proxy object and loop over them.
1385
+ const constProps = arg[_CONST_PROPS];
1386
+ const varProps = arg[_VAR_PROPS];
1387
+ if (constProps) {
1388
+ for (const key in constProps) {
1389
+ clearArgEffect(constProps[key], subscriber, seenSet);
1390
+ }
1391
+ }
1392
+ for (const key in varProps) {
1393
+ clearArgEffect(varProps[key], subscriber, seenSet);
1394
+ }
1395
+ }
1396
+ else {
1397
+ for (const key in arg) {
1398
+ clearArgEffect(arg[key], subscriber, seenSet);
1399
+ }
1400
+ }
1401
+ }
1402
+ else if (Array.isArray(arg)) {
1403
+ clearArgsEffects(arg, subscriber, seenSet);
1404
+ }
1405
+ else ;
1406
+ }
1322
1407
 
1323
1408
  /** @internal */
1324
1409
  const useResourceQrl = (qrl, opts) => {
@@ -1405,14 +1490,17 @@ function getResourceValueAsPromise(props) {
1405
1490
  // create a subscription for the resource._state changes
1406
1491
  const state = resource._state;
1407
1492
  if (state === 'pending' && props.onPending) {
1408
- return Promise.resolve(props.onPending());
1493
+ return Promise.resolve().then(useBindInvokeContext(props.onPending));
1409
1494
  }
1410
1495
  else if (state === 'rejected' && props.onRejected) {
1411
- return Promise.resolve(resource._error).then(props.onRejected);
1496
+ return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
1412
1497
  }
1413
1498
  else {
1414
- // resolved, pending without onPending prop or rejected with onRejected prop
1415
- return Promise.resolve(untrack(() => resource._resolved)).then(props.onResolved);
1499
+ const resolvedValue = untrack(() => resource._resolved);
1500
+ if (resolvedValue !== undefined) {
1501
+ // resolved, pending without onPending prop or rejected without onRejected prop
1502
+ return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
1503
+ }
1416
1504
  }
1417
1505
  }
1418
1506
  return resource.value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
@@ -1453,7 +1541,7 @@ const runResource = (task, container, host) => {
1453
1541
  cleanupTask(task);
1454
1542
  const iCtx = newInvokeContext(container.$locale$, host, undefined, ResourceEvent);
1455
1543
  iCtx.$container$ = container;
1456
- const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(task));
1544
+ const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(container, task));
1457
1545
  const resource = task.$state$;
1458
1546
  assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
1459
1547
  const track = (obj, prop) => {
@@ -2254,6 +2342,17 @@ function escapeHTML(html) {
2254
2342
  }
2255
2343
  }
2256
2344
 
2345
+ function getFileLocationFromJsx(jsxDev) {
2346
+ if (!jsxDev) {
2347
+ return null;
2348
+ }
2349
+ const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
2350
+ if (sanitizedFileName) {
2351
+ return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
2352
+ }
2353
+ return null;
2354
+ }
2355
+
2257
2356
  const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2258
2357
  let journal = container.$journal$;
2259
2358
  /**
@@ -2697,7 +2796,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2697
2796
  *
2698
2797
  * @returns {boolean}
2699
2798
  */
2700
- function createNewElement(jsx, elementName) {
2799
+ function createNewElement(jsx, elementName, currentFile) {
2701
2800
  const element = createElementWithNamespace(elementName);
2702
2801
  const { constProps } = jsx;
2703
2802
  let needsQDispatchEventPatch = false;
@@ -2728,6 +2827,9 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2728
2827
  value(element);
2729
2828
  continue;
2730
2829
  }
2830
+ else {
2831
+ throw qError(QError.invalidRefValue, [currentFile]);
2832
+ }
2731
2833
  }
2732
2834
  if (isSignal(value)) {
2733
2835
  const signalData = new EffectPropData({
@@ -2742,13 +2844,13 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2742
2844
  continue;
2743
2845
  }
2744
2846
  if (elementName === 'textarea' && key === 'value') {
2745
- if (typeof value !== 'string') {
2847
+ if (value && typeof value !== 'string') {
2746
2848
  if (isDev) {
2747
- throw qError(QError.wrongTextareaValue);
2849
+ throw qError(QError.wrongTextareaValue, [currentFile, value]);
2748
2850
  }
2749
2851
  continue;
2750
2852
  }
2751
- element.value = escapeHTML(value);
2853
+ element.value = escapeHTML(value || '');
2752
2854
  continue;
2753
2855
  }
2754
2856
  value = serializeAttribute(key, value, scopedStyleIdPrefix);
@@ -2782,6 +2884,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2782
2884
  const isSameElementName = vCurrent && vnode_isElementVNode(vCurrent) && elementName === vnode_getElementName(vCurrent);
2783
2885
  const jsxKey = jsx.key;
2784
2886
  let needsQDispatchEventPatch = false;
2887
+ const currentFile = getFileLocationFromJsx(jsx.dev);
2785
2888
  if (!isSameElementName || jsxKey !== getKey(vCurrent)) {
2786
2889
  // So we have a key and it does not match the current node.
2787
2890
  // We need to do a forward search to find it.
@@ -2794,14 +2897,21 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2794
2897
  else {
2795
2898
  // Existing keyed node
2796
2899
  vnode_insertBefore(journal, vParent, vNewNode, vCurrent);
2900
+ // We are here, so jsx is different from the vCurrent, so now we want to point to the moved node.
2901
+ vCurrent = vNewNode;
2902
+ // We need to clean up the vNewNode, because we don't want to skip advance to next sibling (see `advance` function).
2903
+ vNewNode = null;
2904
+ // We need also to go back to the previous sibling, because we assigned previous sibling to the vCurrent.
2905
+ if (vSiblings !== null) {
2906
+ vSiblingsIdx -= SiblingsArray.Size;
2907
+ }
2797
2908
  }
2798
2909
  }
2799
2910
  // reconcile attributes
2800
2911
  const jsxAttrs = [];
2801
2912
  const props = jsx.varProps;
2802
2913
  for (const key in props) {
2803
- let value = props[key];
2804
- value = serializeAttribute(key, value, scopedStyleIdPrefix);
2914
+ const value = props[key];
2805
2915
  if (value != null) {
2806
2916
  mapArray_set(jsxAttrs, key, value, 0);
2807
2917
  }
@@ -2810,7 +2920,8 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2810
2920
  mapArray_set(jsxAttrs, ELEMENT_KEY, jsxKey, 0);
2811
2921
  }
2812
2922
  const vNode = (vNewNode || vCurrent);
2813
- needsQDispatchEventPatch = setBulkProps(vNode, jsxAttrs) || needsQDispatchEventPatch;
2923
+ needsQDispatchEventPatch =
2924
+ setBulkProps(vNode, jsxAttrs, currentFile) || needsQDispatchEventPatch;
2814
2925
  if (needsQDispatchEventPatch) {
2815
2926
  // Event handler needs to be patched onto the element.
2816
2927
  const element = vnode_getNode(vNode);
@@ -2835,7 +2946,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2835
2946
  }
2836
2947
  }
2837
2948
  /** @param tag Returns true if `qDispatchEvent` needs patching */
2838
- function setBulkProps(vnode, srcAttrs) {
2949
+ function setBulkProps(vnode, srcAttrs, currentFile) {
2839
2950
  vnode_ensureElementInflated(vnode);
2840
2951
  const dstAttrs = vnode;
2841
2952
  let srcIdx = 0;
@@ -2860,11 +2971,18 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2860
2971
  value(element);
2861
2972
  return;
2862
2973
  }
2974
+ else {
2975
+ throw qError(QError.invalidRefValue, [currentFile]);
2976
+ }
2863
2977
  }
2864
2978
  if (isSignal(value)) {
2865
- value = untrack(() => value.value);
2979
+ const signalData = new EffectPropData({
2980
+ $scopedStyleIdPrefix$: scopedStyleIdPrefix,
2981
+ $isConst$: false,
2982
+ });
2983
+ value = trackSignalAndAssignHost(value, vnode, key, container, signalData);
2866
2984
  }
2867
- vnode_setAttr(journal, vnode, key, value);
2985
+ vnode_setAttr(journal, vnode, key, serializeAttribute(key, value, scopedStyleIdPrefix));
2868
2986
  if (value === null) {
2869
2987
  // if we set `null` than attribute was removed and we need to shorten the dstLength
2870
2988
  dstLength = dstAttrs.length;
@@ -2920,6 +3038,10 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
2920
3038
  }
2921
3039
  srcIdx++;
2922
3040
  srcKey = srcIdx < srcLength ? srcAttrs[srcIdx++] : null;
3041
+ // we need to increment dstIdx too, because we added destination key and value to the VNode
3042
+ // and dstAttrs is a reference to the VNode
3043
+ dstIdx++;
3044
+ dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
2923
3045
  }
2924
3046
  else if (srcKey == dstKey) {
2925
3047
  const srcValue = srcAttrs[srcIdx++];
@@ -3037,7 +3159,7 @@ const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
3037
3159
  vNewNode = retrieveChildWithKey(null, jsxKey);
3038
3160
  if (vNewNode != null) {
3039
3161
  // We found it, move it up.
3040
- vnode_insertBefore(journal, vParent, (vNewNode = vnode_newVirtual()), vCurrent && getInsertBefore());
3162
+ vnode_insertBefore(journal, vParent, vNewNode, vCurrent && getInsertBefore());
3041
3163
  return;
3042
3164
  }
3043
3165
  }
@@ -3279,7 +3401,7 @@ function cleanup(container, vNode) {
3279
3401
  const obj = seq[i];
3280
3402
  if (isTask(obj)) {
3281
3403
  const task = obj;
3282
- clearSubscriberEffectDependencies(task);
3404
+ clearSubscriberEffectDependencies(container, task);
3283
3405
  if (task.$flags$ & TaskFlags.VISIBLE_TASK) {
3284
3406
  container.$scheduler$(ChoreType.CLEANUP_VISIBLE, task);
3285
3407
  }
@@ -3480,6 +3602,108 @@ const createComputedQrl = createComputedSignal;
3480
3602
  */
3481
3603
  const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedQrl);
3482
3604
 
3605
+ /// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
3606
+ const aVNodePath = [];
3607
+ const bVNodePath = [];
3608
+ /**
3609
+ * Compare two VNodes and determine their document position relative to each other.
3610
+ *
3611
+ * @param a VNode to compare
3612
+ * @param b VNode to compare
3613
+ * @param rootVNode - Root VNode of a container
3614
+ * @returns -1 if `a` is before `b`, 0 if `a` is the same as `b`, 1 if `a` is after `b`.
3615
+ */
3616
+ const vnode_documentPosition = (a, b, rootVNode) => {
3617
+ if (a === b) {
3618
+ return 0;
3619
+ }
3620
+ let aDepth = -1;
3621
+ let bDepth = -1;
3622
+ while (a) {
3623
+ const vNode = (aVNodePath[++aDepth] = a);
3624
+ a = (vNode[VNodeProps.parent] ||
3625
+ (rootVNode && vnode_getProp(a, QSlotParent, (id) => vnode_locate(rootVNode, id))));
3626
+ }
3627
+ while (b) {
3628
+ const vNode = (bVNodePath[++bDepth] = b);
3629
+ b = (vNode[VNodeProps.parent] ||
3630
+ (rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))));
3631
+ }
3632
+ while (aDepth >= 0 && bDepth >= 0) {
3633
+ a = aVNodePath[aDepth];
3634
+ b = bVNodePath[bDepth];
3635
+ if (a === b) {
3636
+ // if the nodes are the same, we need to check the next level.
3637
+ aDepth--;
3638
+ bDepth--;
3639
+ }
3640
+ else {
3641
+ // We found a difference so we need to scan nodes at this level.
3642
+ let cursor = b;
3643
+ do {
3644
+ cursor = vnode_getNextSibling(cursor);
3645
+ if (cursor === a) {
3646
+ return 1;
3647
+ }
3648
+ } while (cursor);
3649
+ cursor = b;
3650
+ do {
3651
+ cursor = vnode_getPreviousSibling(cursor);
3652
+ if (cursor === a) {
3653
+ return -1;
3654
+ }
3655
+ } while (cursor);
3656
+ if (rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))) {
3657
+ // The "b" node is a projection, so we need to set it after "a" node,
3658
+ // because the "a" node could be a context provider.
3659
+ return -1;
3660
+ }
3661
+ // The node is not in the list of siblings, that means it must be disconnected.
3662
+ return 1;
3663
+ }
3664
+ }
3665
+ return aDepth < bDepth ? -1 : 1;
3666
+ };
3667
+ /// These global variables are used to avoid creating new arrays for each call to `ssrNodeDocumentPosition`.
3668
+ const aSsrNodePath = [];
3669
+ const bSsrNodePath = [];
3670
+ /**
3671
+ * Compare two SSR nodes and determine their document position relative to each other. Compares only
3672
+ * position between parent and child.
3673
+ *
3674
+ * @param a SSR node to compare
3675
+ * @param b SSR node to compare
3676
+ * @returns -1 if `a` is before `b`, 0 if `a` is the same as `b`, 1 if `a` is after `b`.
3677
+ */
3678
+ const ssrNodeDocumentPosition = (a, b) => {
3679
+ if (a === b) {
3680
+ return 0;
3681
+ }
3682
+ let aDepth = -1;
3683
+ let bDepth = -1;
3684
+ while (a) {
3685
+ const ssrNode = (aSsrNodePath[++aDepth] = a);
3686
+ a = ssrNode.currentComponentNode;
3687
+ }
3688
+ while (b) {
3689
+ const ssrNode = (bSsrNodePath[++bDepth] = b);
3690
+ b = ssrNode.currentComponentNode;
3691
+ }
3692
+ while (aDepth >= 0 && bDepth >= 0) {
3693
+ a = aSsrNodePath[aDepth];
3694
+ b = bSsrNodePath[bDepth];
3695
+ if (a === b) {
3696
+ // if the nodes are the same, we need to check the next level.
3697
+ aDepth--;
3698
+ bDepth--;
3699
+ }
3700
+ else {
3701
+ return 1;
3702
+ }
3703
+ }
3704
+ return aDepth < bDepth ? -1 : 1;
3705
+ };
3706
+
3483
3707
  /**
3484
3708
  * Scheduler is responsible for running application code in predictable order.
3485
3709
  *
@@ -3612,7 +3836,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3612
3836
  $executed$: false,
3613
3837
  };
3614
3838
  chore.$promise$ = new Promise((resolve) => (chore.$resolve$ = resolve));
3615
- chore = sortedInsert(choreQueue, chore);
3839
+ chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
3616
3840
  if (!journalFlushScheduled && runLater) {
3617
3841
  // If we are not currently draining, we need to schedule a drain.
3618
3842
  journalFlushScheduled = true;
@@ -3623,7 +3847,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3623
3847
  return chore.$promise$;
3624
3848
  }
3625
3849
  else {
3626
- return drainUpTo(chore);
3850
+ return drainUpTo(chore, container.rootVNode || null);
3627
3851
  }
3628
3852
  }
3629
3853
  /**
@@ -3631,7 +3855,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3631
3855
  *
3632
3856
  * @param runUptoChore
3633
3857
  */
3634
- function drainUpTo(runUptoChore) {
3858
+ function drainUpTo(runUptoChore, rootVNode) {
3635
3859
  // If it already ran, it's not in the queue
3636
3860
  if (runUptoChore.$executed$) {
3637
3861
  return runUptoChore.$returnValue$;
@@ -3642,7 +3866,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3642
3866
  }
3643
3867
  while (choreQueue.length) {
3644
3868
  const nextChore = choreQueue.shift();
3645
- const order = choreComparator(nextChore, runUptoChore, false);
3869
+ const order = choreComparator(nextChore, runUptoChore, rootVNode);
3646
3870
  if (order === null) {
3647
3871
  continue;
3648
3872
  }
@@ -3658,7 +3882,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3658
3882
  }
3659
3883
  const returnValue = executeChore(nextChore);
3660
3884
  if (isPromise(returnValue)) {
3661
- const promise = returnValue.then(() => drainUpTo(runUptoChore));
3885
+ const promise = returnValue.then(() => drainUpTo(runUptoChore, rootVNode));
3662
3886
  return promise;
3663
3887
  }
3664
3888
  }
@@ -3679,7 +3903,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3679
3903
  returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
3680
3904
  if (chore.$type$ === ChoreType.COMPONENT) {
3681
3905
  const styleScopedId = container.getHostProp(host, QScopedStyle);
3682
- return vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId));
3906
+ return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
3683
3907
  }
3684
3908
  else {
3685
3909
  return jsx;
@@ -3710,7 +3934,7 @@ const createScheduler = (container, scheduleDrain, journalFlush) => {
3710
3934
  if (isSignal(jsx)) {
3711
3935
  jsx = jsx.value;
3712
3936
  }
3713
- returnValue = vnode_diff(container, jsx, parentVirtualNode, null);
3937
+ returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
3714
3938
  break;
3715
3939
  case ChoreType.NODE_PROP:
3716
3940
  const virtualNode = chore.$host$;
@@ -3779,7 +4003,15 @@ function vNodeAlreadyDeleted(chore) {
3779
4003
  vnode_isVNode(chore.$host$) &&
3780
4004
  chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
3781
4005
  }
3782
- function choreComparator(a, b, shouldThrowOnHostMismatch) {
4006
+ /**
4007
+ * Compares two chores to determine their execution order in the scheduler's queue.
4008
+ *
4009
+ * @param a - The first chore to compare
4010
+ * @param b - The second chore to compare
4011
+ * @returns A number indicating the relative order of the chores. A negative number means `a` runs
4012
+ * before `b`.
4013
+ */
4014
+ function choreComparator(a, b, rootVNode) {
3783
4015
  const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
3784
4016
  if (macroTypeDiff !== 0) {
3785
4017
  return macroTypeDiff;
@@ -3792,7 +4024,7 @@ function choreComparator(a, b, shouldThrowOnHostMismatch) {
3792
4024
  if (aHost !== bHost && aHost !== null && bHost !== null) {
3793
4025
  if (vnode_isVNode(aHost) && vnode_isVNode(bHost)) {
3794
4026
  // we are running on the client.
3795
- const hostDiff = vnode_documentPosition(aHost, bHost);
4027
+ const hostDiff = vnode_documentPosition(aHost, bHost, rootVNode);
3796
4028
  if (hostDiff !== 0) {
3797
4029
  return hostDiff;
3798
4030
  }
@@ -3806,11 +4038,11 @@ function choreComparator(a, b, shouldThrowOnHostMismatch) {
3806
4038
  You are attempting to change a state that has already been streamed to the client.
3807
4039
  This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
3808
4040
  Problematic Node: ${aHost.toString()}`;
3809
- if (shouldThrowOnHostMismatch) {
3810
- throw qError(QError.serverHostMismatch, [errorMessage]);
3811
- }
3812
4041
  logWarn(errorMessage);
3813
- return null;
4042
+ const hostDiff = ssrNodeDocumentPosition(aHost, bHost);
4043
+ if (hostDiff !== 0) {
4044
+ return hostDiff;
4045
+ }
3814
4046
  }
3815
4047
  }
3816
4048
  const microTypeDiff = (a.$type$ & ChoreType.MICRO) - (b.$type$ & ChoreType.MICRO);
@@ -3833,7 +4065,7 @@ function choreComparator(a, b, shouldThrowOnHostMismatch) {
3833
4065
  }
3834
4066
  return 0;
3835
4067
  }
3836
- function sortedFindIndex(sortedArray, value) {
4068
+ function sortedFindIndex(sortedArray, value, rootVNode) {
3837
4069
  /// We need to ensure that the `queue` is sorted by priority.
3838
4070
  /// 1. Find a place where to insert into.
3839
4071
  let bottom = 0;
@@ -3841,7 +4073,7 @@ function sortedFindIndex(sortedArray, value) {
3841
4073
  while (bottom < top) {
3842
4074
  const middle = bottom + ((top - bottom) >> 1);
3843
4075
  const midChore = sortedArray[middle];
3844
- const comp = choreComparator(value, midChore, true);
4076
+ const comp = choreComparator(value, midChore, rootVNode);
3845
4077
  if (comp < 0) {
3846
4078
  top = middle;
3847
4079
  }
@@ -3855,10 +4087,10 @@ function sortedFindIndex(sortedArray, value) {
3855
4087
  }
3856
4088
  return ~bottom;
3857
4089
  }
3858
- function sortedInsert(sortedArray, value) {
4090
+ function sortedInsert(sortedArray, value, rootVNode) {
3859
4091
  /// We need to ensure that the `queue` is sorted by priority.
3860
4092
  /// 1. Find a place where to insert into.
3861
- const idx = sortedFindIndex(sortedArray, value);
4093
+ const idx = sortedFindIndex(sortedArray, value, rootVNode);
3862
4094
  if (idx < 0) {
3863
4095
  /// 2. Insert the chore into the queue.
3864
4096
  sortedArray.splice(~idx, 0, value);
@@ -3936,7 +4168,7 @@ const runTask = (task, container, host) => {
3936
4168
  cleanupTask(task);
3937
4169
  const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
3938
4170
  iCtx.$container$ = container;
3939
- const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(task));
4171
+ const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(container, task));
3940
4172
  const track = (obj, prop) => {
3941
4173
  const ctx = newInvokeContext();
3942
4174
  ctx.$effectSubscriber$ = [task, EffectProperty.COMPONENT];
@@ -4568,7 +4800,7 @@ function processJSXNode(ssr, enqueue, value, options) {
4568
4800
  appendClassIfScopedStyleExists(jsx, options.styleScoped);
4569
4801
  let qwikInspectorAttrValue = null;
4570
4802
  if (isDev && jsx.dev && jsx.type !== 'head') {
4571
- qwikInspectorAttrValue = getQwikInspectorAttributeValue(jsx.dev);
4803
+ qwikInspectorAttrValue = getFileLocationFromJsx(jsx.dev);
4572
4804
  if (qInspector) {
4573
4805
  appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue);
4574
4806
  }
@@ -4842,13 +5074,6 @@ function getSlotName(host, jsx, ssr) {
4842
5074
  }
4843
5075
  return directGetPropsProxyProp(jsx, 'name') || QDefaultSlot;
4844
5076
  }
4845
- function getQwikInspectorAttributeValue(jsxDev) {
4846
- const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
4847
- if (sanitizedFileName) {
4848
- return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
4849
- }
4850
- return null;
4851
- }
4852
5077
  function appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue) {
4853
5078
  if (qwikInspectorAttrValue && (!jsx.constProps || !(qwikInspectorAttr in jsx.constProps))) {
4854
5079
  (jsx.constProps ||= {})[qwikInspectorAttr] = qwikInspectorAttrValue;
@@ -4870,7 +5095,7 @@ function appendClassIfScopedStyleExists(jsx, styleScoped) {
4870
5095
  *
4871
5096
  * @public
4872
5097
  */
4873
- const version = "2.0.0-alpha.4-dev+374e0d6";
5098
+ const version = "2.0.0-alpha.6-dev+d848ba5";
4874
5099
 
4875
5100
  /** @internal */
4876
5101
  class _SharedContainer {
@@ -6761,7 +6986,7 @@ const vnode_getNode = (vnode) => {
6761
6986
  assertTrue(vnode_isTextVNode(vnode), 'Expecting Text Node.');
6762
6987
  return vnode[TextVNodeProps.node];
6763
6988
  };
6764
- function vnode_toString(depth = 10, offset = '', materialize = false, siblings = false) {
6989
+ function vnode_toString(depth = 20, offset = '', materialize = false, siblings = false) {
6765
6990
  let vnode = this;
6766
6991
  if (depth === 0) {
6767
6992
  return '...';
@@ -6978,51 +7203,6 @@ const vnode_getType = (vnode) => {
6978
7203
  throw qError(QError.invalidVNodeType, [type]);
6979
7204
  };
6980
7205
  const isElement = (node) => node && typeof node == 'object' && fastNodeType(node) === /** Node.ELEMENT_NODE* */ 1;
6981
- /// These global variables are used to avoid creating new arrays for each call to `vnode_getPathToClosestDomNode`.
6982
- const aPath = [];
6983
- const bPath = [];
6984
- const vnode_documentPosition = (a, b) => {
6985
- if (a === b) {
6986
- return 0;
6987
- }
6988
- let aDepth = -1;
6989
- let bDepth = -1;
6990
- while (a) {
6991
- a = (aPath[++aDepth] = a)[VNodeProps.parent];
6992
- }
6993
- while (b) {
6994
- b = (bPath[++bDepth] = b)[VNodeProps.parent];
6995
- }
6996
- while (aDepth >= 0 && bDepth >= 0) {
6997
- a = aPath[aDepth];
6998
- b = bPath[bDepth];
6999
- if (a === b) {
7000
- // if the nodes are the same, we need to check the next level.
7001
- aDepth--;
7002
- bDepth--;
7003
- }
7004
- else {
7005
- // We found a difference so we need to scan nodes at this level.
7006
- let cursor = b;
7007
- do {
7008
- cursor = vnode_getNextSibling(cursor);
7009
- if (cursor === a) {
7010
- return 1;
7011
- }
7012
- } while (cursor);
7013
- cursor = b;
7014
- do {
7015
- cursor = vnode_getPreviousSibling(cursor);
7016
- if (cursor === a) {
7017
- return -1;
7018
- }
7019
- } while (cursor);
7020
- // The node is not in the list of siblings, that means it must be disconnected.
7021
- return 1;
7022
- }
7023
- }
7024
- return aDepth < bDepth ? -1 : 1;
7025
- };
7026
7206
  /**
7027
7207
  * Use this method to find the parent component for projection.
7028
7208
  *
@@ -7049,11 +7229,7 @@ const vnode_getProjectionParentComponent = (vHost, rootVNode) => {
7049
7229
  while (projectionDepth--) {
7050
7230
  while (vHost &&
7051
7231
  (vnode_isVirtualVNode(vHost) ? vnode_getProp(vHost, OnRenderProp, null) === null : true)) {
7052
- const qSlotParentProp = vnode_getProp(vHost, QSlotParent, null);
7053
- const qSlotParent = qSlotParentProp &&
7054
- (typeof qSlotParentProp === 'string'
7055
- ? vnode_locate(rootVNode, qSlotParentProp)
7056
- : qSlotParentProp);
7232
+ const qSlotParent = vnode_getProp(vHost, QSlotParent, (id) => vnode_locate(rootVNode, id));
7057
7233
  const vProjectionParent = vnode_isVirtualVNode(vHost) && qSlotParent;
7058
7234
  if (vProjectionParent) {
7059
7235
  // We found a projection, so we need to go up one more level.
@@ -7962,14 +8138,14 @@ class DomContainer extends _SharedContainer {
7962
8138
  if (vnode_getProp(vNode, OnRenderProp, null) !== null) {
7963
8139
  return vNode;
7964
8140
  }
7965
- // If virtual node, than it could be a slot so we need to read its parent.
7966
- const parent = vnode_getProp(vNode, QSlotParent, this.$vnodeLocate$);
7967
- if (parent) {
7968
- vNode = parent;
7969
- continue;
7970
- }
8141
+ vNode =
8142
+ vnode_getParent(vNode) ||
8143
+ // If virtual node, than it could be a slot so we need to read its parent.
8144
+ vnode_getProp(vNode, QSlotParent, this.$vnodeLocate$);
8145
+ }
8146
+ else {
8147
+ vNode = vnode_getParent(vNode);
7971
8148
  }
7972
- vNode = vnode_getParent(vNode);
7973
8149
  }
7974
8150
  return null;
7975
8151
  }
@@ -8069,12 +8245,6 @@ class DomContainer extends _SharedContainer {
8069
8245
 
8070
8246
  /** There's [documentation](./serialization.md) */
8071
8247
  const deserializedProxyMap = new WeakMap();
8072
- const unwrapDeserializerProxy = (value) => {
8073
- const unwrapped = typeof value === 'object' &&
8074
- value !== null &&
8075
- value[SERIALIZER_PROXY_UNWRAP];
8076
- return unwrapped ? unwrapped : value;
8077
- };
8078
8248
  const isDeserializerProxy = (value) => {
8079
8249
  return typeof value === 'object' && value !== null && SERIALIZER_PROXY_UNWRAP in value;
8080
8250
  };
@@ -8127,14 +8297,14 @@ class DeserializationHandler {
8127
8297
  return value;
8128
8298
  }
8129
8299
  const container = this.$container$;
8130
- const propValue = allocate(container, typeId, value);
8131
- Reflect.set(target, property, propValue);
8132
- this.$data$[idx] = undefined;
8133
- this.$data$[idx + 1] = propValue;
8300
+ let propValue = allocate(container, typeId, value);
8134
8301
  /** We stored the reference, so now we can inflate, allowing cycles. */
8135
8302
  if (typeId >= TypeIds.Error) {
8136
- inflate(container, propValue, typeId, value);
8303
+ propValue = inflate(container, propValue, typeId, value);
8137
8304
  }
8305
+ Reflect.set(target, property, propValue);
8306
+ this.$data$[idx] = undefined;
8307
+ this.$data$[idx + 1] = propValue;
8138
8308
  return propValue;
8139
8309
  }
8140
8310
  has(target, property) {
@@ -8173,7 +8343,7 @@ const resolvers = new WeakMap();
8173
8343
  const inflate = (container, target, typeId, data) => {
8174
8344
  if (typeId === undefined) {
8175
8345
  // Already processed
8176
- return;
8346
+ return target;
8177
8347
  }
8178
8348
  // restore the complex data, except for plain objects
8179
8349
  if (typeId !== TypeIds.Object && Array.isArray(data)) {
@@ -8245,16 +8415,13 @@ const inflate = (container, target, typeId, data) => {
8245
8415
  case TypeIds.Store:
8246
8416
  case TypeIds.StoreArray: {
8247
8417
  const [value, flags, effects, storeEffect] = data;
8248
- const handler = getStoreHandler(target);
8249
- handler.$flags$ = flags;
8250
- // First assign so it sets up the deep stores
8251
- Object.assign(getStoreTarget(target), value);
8252
- // Afterwards restore the effects so they don't get triggered
8418
+ const store = getOrCreateStore(value, flags, container);
8419
+ const storeHandler = getStoreHandler(store);
8253
8420
  if (storeEffect) {
8254
8421
  effects[STORE_ARRAY_PROP] = storeEffect;
8255
8422
  }
8256
- handler.$effects$ = effects;
8257
- container.$storeProxyMap$.set(value, target);
8423
+ storeHandler.$effects$ = effects;
8424
+ target = store;
8258
8425
  break;
8259
8426
  }
8260
8427
  case TypeIds.Signal: {
@@ -8381,6 +8548,7 @@ const inflate = (container, target, typeId, data) => {
8381
8548
  default:
8382
8549
  throw qError(QError.serializeErrorNotImplemented, [typeId]);
8383
8550
  }
8551
+ return target;
8384
8552
  };
8385
8553
  const _constants = [
8386
8554
  undefined,
@@ -8446,9 +8614,9 @@ const allocate = (container, typeId, value) => {
8446
8614
  case TypeIds.ComputedSignal:
8447
8615
  return new ComputedSignal(container, null);
8448
8616
  case TypeIds.Store:
8449
- return createStore(container, {}, 0);
8450
8617
  case TypeIds.StoreArray:
8451
- return createStore(container, [], 0);
8618
+ // ignore allocate, we need to assign target while creating store
8619
+ return null;
8452
8620
  case TypeIds.URLSearchParams:
8453
8621
  return new URLSearchParams(value);
8454
8622
  case TypeIds.FormData:
@@ -9310,15 +9478,15 @@ function _deserialize(rawStateData, element) {
9310
9478
  }
9311
9479
  return output;
9312
9480
  }
9313
- function deserializeData(container, typeId, propValue) {
9481
+ function deserializeData(container, typeId, value) {
9314
9482
  if (typeId === undefined) {
9315
- return propValue;
9483
+ return value;
9316
9484
  }
9317
- const value = allocate(container, typeId, propValue);
9485
+ let propValue = allocate(container, typeId, value);
9318
9486
  if (typeId >= TypeIds.Error) {
9319
- inflate(container, value, typeId, propValue);
9487
+ propValue = inflate(container, propValue, typeId, value);
9320
9488
  }
9321
- return value;
9489
+ return propValue;
9322
9490
  }
9323
9491
  function getObjectById(id, stateData) {
9324
9492
  if (typeof id === 'string') {