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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * @qwik.dev/core 2.0.0-beta.23-dev+03de42d
3
+ * @qwik.dev/core 2.0.0-beta.25-dev+2677279
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,13 +9,6 @@ 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.23-dev+03de42d";
18
-
19
12
  // same as isDev but separate so we can test
20
13
  const qDev = globalThis.qDev !== false;
21
14
  const qInspector = globalThis.qInspector === true;
@@ -79,6 +72,102 @@ const createAndLogError = (asyncThrow, message, ...optionalParams) => {
79
72
  return err;
80
73
  };
81
74
 
75
+ const ASSERT_DISCLAIMER = 'Internal assert, this is likely caused by a bug in Qwik: ';
76
+ /*@__INLINE__*/
77
+ function assertDefined(value, text, ...parts) {
78
+ if (isDev) {
79
+ if (value != null) {
80
+ return;
81
+ }
82
+ throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
83
+ }
84
+ }
85
+ /*@__INLINE__*/
86
+ function assertEqual(value1, value2, text, ...parts) {
87
+ if (isDev) {
88
+ if (value1 === value2) {
89
+ return;
90
+ }
91
+ throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
92
+ }
93
+ }
94
+ /*@__INLINE__*/
95
+ function assertTrue(value1, text, ...parts) {
96
+ if (isDev) {
97
+ if (value1 === true) {
98
+ return;
99
+ }
100
+ throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
101
+ }
102
+ }
103
+ /*@__INLINE__*/
104
+ function assertFalse(value1, text, ...parts) {
105
+ if (isDev) {
106
+ if (value1 === false) {
107
+ return;
108
+ }
109
+ throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
110
+ }
111
+ }
112
+ /*@__INLINE__*/
113
+ function assertNumber(value1, text, ...parts) {
114
+ if (isDev) {
115
+ if (typeof value1 === 'number') {
116
+ return;
117
+ }
118
+ throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
119
+ }
120
+ }
121
+
122
+ /** @internal */
123
+ const mapApp_findIndx = (array, key, start) => {
124
+ isDev && assertTrue(start % 2 === 0, 'Expecting even number.');
125
+ let bottom = start >> 1;
126
+ let top = (array.length - 2) >> 1;
127
+ while (bottom <= top) {
128
+ const mid = bottom + ((top - bottom) >> 1);
129
+ const midKey = array[mid << 1];
130
+ if (midKey === key) {
131
+ return mid << 1;
132
+ }
133
+ if (midKey < key) {
134
+ bottom = mid + 1;
135
+ }
136
+ else {
137
+ top = mid - 1;
138
+ }
139
+ }
140
+ return (bottom << 1) ^ -1;
141
+ };
142
+ /** @internal */
143
+ const mapArray_set = (array, key, value, start, allowNullValue = false) => {
144
+ const indx = mapApp_findIndx(array, key, start);
145
+ if (indx >= 0) {
146
+ if (value == null && !allowNullValue) {
147
+ array.splice(indx, 2);
148
+ }
149
+ else {
150
+ array[indx + 1] = value;
151
+ }
152
+ }
153
+ else if (value != null || allowNullValue) {
154
+ array.splice(indx ^ -1, 0, key, value);
155
+ }
156
+ };
157
+ /** @internal */
158
+ const mapArray_get = (array, key, start) => {
159
+ const indx = mapApp_findIndx(array, key, start);
160
+ if (indx >= 0) {
161
+ return array[indx + 1];
162
+ }
163
+ else {
164
+ return null;
165
+ }
166
+ };
167
+ const mapArray_has = (array, key, start) => {
168
+ return mapApp_findIndx(array, key, start) >= 0;
169
+ };
170
+
82
171
  /** @private */
83
172
  const isSerializableObject = (v) => {
84
173
  const proto = Object.getPrototypeOf(v);
@@ -134,7 +223,7 @@ const codeToText = (code, ...parts) => {
134
223
  'Materialize error: missing element: {{0}} {{1}} {{2}}', // 27
135
224
  'Cannot coerce a Signal, use `.value` instead', // 28
136
225
  'useComputed$ QRL {{0}} {{1}} cannot return a Promise', // 29
137
- 'ComputedSignal is read-only', // 30
226
+ '===\nQwik version {{0}} already imported while importing {{1}}.\nThis can lead to issues due to duplicated shared structures.\nVerify that the Qwik libraries you\'re using are in "resolve.noExternal[]" and in "optimizeDeps.exclude".\n===\n', // 30
138
227
  'WrappedSignal is read-only', // 31
139
228
  'Attribute value is unsafe for SSR {{0}}', // 32
140
229
  'SerializerSymbol function returned rejected promise', // 33
@@ -154,7 +243,8 @@ const codeToText = (code, ...parts) => {
154
243
  }
155
244
  else {
156
245
  // cute little hack to give roughly the correct line number. Update the line number if it shifts.
157
- return `Code(Q${code}) https://github.com/QwikDev/qwik/blob/main/packages/qwik/src/core/error/error.ts#L${8 + code}`;
246
+ // TODO change the URL after merging into main
247
+ return `Code(Q${code}) https://github.com/QwikDev/qwik/blob/build/v2/packages/qwik/src/core/shared/error/error.ts#${parts.join()}L${9 + code}`;
158
248
  }
159
249
  };
160
250
  const qError = (code, errorMessageArgs = []) => {
@@ -186,6 +276,112 @@ const getSymbolHash = (symbolName) => {
186
276
  return symbolName;
187
277
  };
188
278
 
279
+ /**
280
+ * A friendly name tag for a VirtualVNode.
281
+ *
282
+ * Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
283
+ *
284
+ * The name is only added in development mode and is not included in production builds.
285
+ */
286
+ const DEBUG_TYPE = 'q:type';
287
+ const VirtualTypeName = {
288
+ ["V" /* VirtualType.Virtual */]: /* ********* */ 'Virtual', //
289
+ ["F" /* VirtualType.Fragment */]: /* ******** */ 'Fragment', //
290
+ ["S" /* VirtualType.WrappedSignal */]: /* *** */ 'Signal', //
291
+ ["A" /* VirtualType.Awaited */]: /* ********* */ 'Awaited', //
292
+ ["C" /* VirtualType.Component */]: /* ******* */ 'Component', //
293
+ ["I" /* VirtualType.InlineComponent */]: /* * */ 'InlineComponent', //
294
+ ["P" /* VirtualType.Projection */]: /* ****** */ 'Projection', //
295
+ };
296
+
297
+ /**
298
+ * @file
299
+ *
300
+ * VNodeData is additional information which allows the `vnode` to recover virtual VNode information
301
+ * from the HTML.
302
+ */
303
+ /**
304
+ * VNodeDataSeparator contains information about splitting up the VNodeData and attaching it to the
305
+ * HTML.
306
+ */
307
+ const VNodeDataSeparator = {
308
+ REFERENCE: /* ******** */ 126, // `~` is a reference to the node. Save it.
309
+ ADVANCE_1: /* ********* */ 33, // `!` is vNodeData separator skipping 0. (ie next vNode)
310
+ ADVANCE_8192: /* ****** */ 46, // `.` is vNodeData separator skipping 4096.
311
+ };
312
+ /**
313
+ * VNodeDataChar contains information about the VNodeData used for encoding props.
314
+ *
315
+ * Available character ranges: 59 - 64, 91 - 94, 96, 123 - 126
316
+ */
317
+ const VNodeDataChar = {
318
+ OPEN: /* ************** */ 123, // `{` is the start of the VNodeData for a virtual element.
319
+ CLOSE: /* ************* */ 125, // `}` is the end of the VNodeData for a virtual element.
320
+ SCOPED_STYLE: /* ******* */ 59, // `;` - `q:sstyle` - Style attribute.
321
+ RENDER_FN: /* ********** */ 60, // `<` - `q:renderFn' - Component QRL render function (body)
322
+ ID: /* ***************** */ 61, // `=` - `q:id` - ID of the element.
323
+ PROPS: /* ************** */ 62, // `>` - `q:props' - Component Props
324
+ SLOT_PARENT: /* ******** */ 63, // `?` - `q:sparent` - Slot parent.
325
+ KEY: /* **************** */ 64, // `@` - `q:key` - Element key.
326
+ SEQ: /* **************** */ 91, // `[` - `q:seq' - Seq value from `useSequentialScope()`
327
+ CONTEXT: /* ************ */ 93, // `]` - `q:ctx' - Component context/props
328
+ SEQ_IDX: /* ************ */ 94, // `^` - `q:seqIdx' - Sequential scope id
329
+ BACK_REFS: /* ********** */ 96, // '`' - `q:brefs' - Effect dependencies/subscriptions
330
+ SEPARATOR: /* ********* */ 124, // `|` - Separator char to encode any key/value pairs.
331
+ SLOT: /* ************** */ 126};
332
+
333
+ function escapeHTML(html) {
334
+ let escapedHTML = '';
335
+ const length = html.length;
336
+ let idx = 0;
337
+ let lastIdx = idx;
338
+ for (; idx < length; idx++) {
339
+ // We get the charCode NOT string. String would allocate memory.
340
+ const ch = html.charCodeAt(idx);
341
+ // Every time we concat a string we allocate memory. We want to minimize that.
342
+ if (ch === 60 /* < */) {
343
+ escapedHTML += html.substring(lastIdx, idx) + '&lt;';
344
+ }
345
+ else if (ch === 62 /* > */) {
346
+ escapedHTML += html.substring(lastIdx, idx) + '&gt;';
347
+ }
348
+ else if (ch === 38 /* & */) {
349
+ escapedHTML += html.substring(lastIdx, idx) + '&amp;';
350
+ }
351
+ else if (ch === 34 /* " */) {
352
+ escapedHTML += html.substring(lastIdx, idx) + '&quot;';
353
+ }
354
+ else if (ch === 39 /* ' */) {
355
+ escapedHTML += html.substring(lastIdx, idx) + '&#39;';
356
+ }
357
+ else {
358
+ continue;
359
+ }
360
+ lastIdx = idx + 1;
361
+ }
362
+ if (lastIdx === 0) {
363
+ // This is most common case, just return previous string no memory allocation.
364
+ return html;
365
+ }
366
+ else {
367
+ // Add the tail of replacement.
368
+ return escapedHTML + html.substring(lastIdx);
369
+ }
370
+ }
371
+ function decodeVNodeDataString(str) {
372
+ let result = '';
373
+ for (let i = 0; i < str.length; i++) {
374
+ if (str.charAt(i) === '\\' && i + 1 < str.length) {
375
+ result += str.charAt(i + 1);
376
+ i++;
377
+ }
378
+ else {
379
+ result += str.charAt(i);
380
+ }
381
+ }
382
+ return result;
383
+ }
384
+
189
385
  /** State factory of the component. */
190
386
  const OnRenderProp = 'q:renderFn';
191
387
  /** Component style content prefix */
@@ -254,127 +450,15 @@ const NON_SERIALIZABLE_MARKER_PREFIX = ':';
254
450
  const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
255
451
  const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
256
452
  const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
257
- // comment nodes
258
- const FLUSH_COMMENT = 'qkssr-f';
259
- const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
260
- const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
261
453
  const Q_PROPS_SEPARATOR = ':';
262
454
  const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
263
455
  const qwikInspectorAttr = 'data-qwik-inspector';
264
456
  const debugStyleScopeIdPrefixAttr = '__scopedStyleIdPrefix__';
265
457
 
266
- // keep this import from core/build so the cjs build works
267
- const createPlatform = () => {
268
- return {
269
- isServer,
270
- importSymbol(containerEl, url, symbolName) {
271
- if (isServer) {
272
- const hash = getSymbolHash(symbolName);
273
- const regSym = globalThis.__qwik_reg_symbols?.get(hash);
274
- if (regSym) {
275
- return regSym;
276
- }
277
- }
278
- if (!url) {
279
- throw qError(14 /* QError.qrlMissingChunk */, [symbolName]);
280
- }
281
- if (!containerEl) {
282
- throw qError(13 /* QError.qrlMissingContainer */, [url, symbolName]);
283
- }
284
- const urlDoc = toUrl(containerEl.ownerDocument, containerEl, url).toString();
285
- const urlCopy = new URL(urlDoc);
286
- urlCopy.hash = '';
287
- const importURL = urlCopy.href;
288
- return import(/* @vite-ignore */ importURL).then((mod) => {
289
- return mod[symbolName];
290
- });
291
- },
292
- raf: (fn) => {
293
- return new Promise((resolve) => {
294
- requestAnimationFrame(() => {
295
- resolve(fn());
296
- });
297
- });
298
- },
299
- chunkForSymbol(symbolName, chunk) {
300
- return [symbolName, chunk ?? '_'];
301
- },
302
- };
303
- };
304
- /**
305
- * Convert relative base URI and relative URL into a fully qualified URL.
306
- *
307
- * @param base -`QRL`s are relative, and therefore they need a base for resolution.
308
- *
309
- * - `Element` use `base.ownerDocument.baseURI`
310
- * - `Document` use `base.baseURI`
311
- * - `string` use `base` as is
312
- * - `QConfig` use `base.baseURI`
313
- *
314
- * @param url - Relative URL
315
- * @returns Fully qualified URL.
316
- */
317
- const toUrl = (doc, containerEl, url) => {
318
- const baseURI = doc.baseURI;
319
- const base = new URL(containerEl.getAttribute(QBaseAttr) ?? baseURI, baseURI);
320
- return new URL(url, base);
321
- };
322
- let _platform = /*#__PURE__ */ createPlatform();
323
- // <docs markdown="./readme.md#setPlatform">
324
- // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
325
- // (edit ./readme.md#setPlatform instead and run `pnpm docs.sync`)
326
- /**
327
- * Sets the `CorePlatform`.
328
- *
329
- * This is useful to override the platform in tests to change the behavior of,
330
- * `requestAnimationFrame`, and import resolution.
331
- *
332
- * @param doc - The document of the application for which the platform is needed.
333
- * @param platform - The platform to use.
334
- * @public
335
- */
336
- // </docs>
337
- const setPlatform = (plt) => (_platform = plt);
338
- // <docs markdown="./readme.md#getPlatform">
339
- // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
340
- // (edit ./readme.md#getPlatform instead and run `pnpm docs.sync`)
341
- /**
342
- * Retrieve the `CorePlatform`.
343
- *
344
- * The `CorePlatform` is also responsible for retrieving the Manifest, that contains mappings from
345
- * symbols to javascript import chunks. For this reason, `CorePlatform` can't be global, but is
346
- * specific to the application currently running. On server it is possible that many different
347
- * applications are running in a single server instance, and for this reason the `CorePlatform` is
348
- * associated with the application document.
349
- *
350
- * @param docOrNode - The document (or node) of the application for which the platform is needed.
351
- * @public
352
- */
353
- // </docs>
354
- const getPlatform = () => {
355
- return _platform;
356
- };
357
- const isServerPlatform = () => {
358
- if (qDynamicPlatform) {
359
- return _platform.isServer;
360
- }
361
- return false;
362
- };
363
-
364
- const isNode = (value) => {
365
- return value && typeof value.nodeType === 'number';
366
- };
367
- const isDocument = (value) => {
368
- return value.nodeType === 9;
369
- };
370
- const isElement$1 = (value) => {
371
- return value.nodeType === 1;
372
- };
373
-
374
- const MAX_RETRY_ON_PROMISE_COUNT = 100;
375
- const isPromise = (value) => {
376
- // not using "value instanceof Promise" to have zone.js support
377
- return !!value && typeof value == 'object' && typeof value.then === 'function';
458
+ const MAX_RETRY_ON_PROMISE_COUNT = 100;
459
+ const isPromise = (value) => {
460
+ // not using "value instanceof Promise" to have zone.js support
461
+ return !!value && typeof value == 'object' && typeof value.then === 'function';
378
462
  };
379
463
  const safeCall = (call, thenFn, rejectFn) => {
380
464
  try {
@@ -455,101 +539,583 @@ function retryOnPromise(fn, onError = justThrow) {
455
539
  return ok ? result.catch(retry) : retry(result);
456
540
  }
457
541
 
458
- const ASSERT_DISCLAIMER = 'Internal assert, this is likely caused by a bug in Qwik: ';
459
- function assertDefined(value, text, ...parts) {
460
- if (qDev) {
461
- if (value != null) {
462
- return;
463
- }
464
- throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
465
- }
466
- }
467
- function assertEqual(value1, value2, text, ...parts) {
468
- if (qDev) {
469
- if (value1 === value2) {
470
- return;
471
- }
472
- throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
473
- }
542
+ const styleContent = (styleId) => {
543
+ return ComponentStylesPrefixContent + styleId;
544
+ };
545
+ function isClassAttr(key) {
546
+ return key === 'class';
474
547
  }
475
- function assertTrue(value1, text, ...parts) {
476
- if (qDev) {
477
- if (value1 === true) {
478
- return;
479
- }
480
- throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
481
- }
548
+ function convertScopedStyleIdsToArray(scopedStyleIds) {
549
+ return scopedStyleIds?.split(' ') ?? null;
482
550
  }
483
- function assertFalse(value1, text, ...parts) {
484
- if (qDev) {
485
- if (value1 === false) {
486
- return;
487
- }
488
- throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
489
- }
551
+ function convertStyleIdsToString(scopedStyleIds) {
552
+ return Array.from(scopedStyleIds).join(' ');
490
553
  }
491
- function assertNumber(value1, text, ...parts) {
492
- if (qDev) {
493
- if (typeof value1 === 'number') {
494
- return;
495
- }
496
- throwErrorAndStop(ASSERT_DISCLAIMER + text, ...parts);
554
+ const addComponentStylePrefix = (styleId) => {
555
+ if (styleId) {
556
+ let idx = 0;
557
+ do {
558
+ styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
559
+ } while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
497
560
  }
498
- }
561
+ return styleId || null;
562
+ };
499
563
 
500
564
  /**
501
- * A friendly name tag for a VirtualVNode.
565
+ * Think of `-` as an escape character which makes the next character uppercase. `--` is just `-`.
502
566
  *
503
- * Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
567
+ * Rules for JSX property event names starting with `on`:
504
568
  *
505
- * The name is only added in development mode and is not included in production builds.
569
+ * - Are case insensitive: `onClick$` is same `onclick$`
570
+ * - A `--` is `-`: `dbl--click` => `dbl-click`
571
+ * - Become case sensitive if prefixed by `-`: `-Click` is `Click`
572
+ * - A `-` (not at the beginning) makes next character uppercase: `dbl-click` => `dblClick`
506
573
  */
507
- const DEBUG_TYPE = 'q:type';
508
- const VirtualTypeName = {
509
- ["V" /* VirtualType.Virtual */]: /* ********* */ 'Virtual', //
510
- ["F" /* VirtualType.Fragment */]: /* ******** */ 'Fragment', //
511
- ["S" /* VirtualType.WrappedSignal */]: /* *** */ 'Signal', //
512
- ["A" /* VirtualType.Awaited */]: /* ********* */ 'Awaited', //
513
- ["C" /* VirtualType.Component */]: /* ******* */ 'Component', //
514
- ["I" /* VirtualType.InlineComponent */]: /* * */ 'InlineComponent', //
515
- ["P" /* VirtualType.Projection */]: /* ****** */ 'Projection', //
574
+ const EVENT_SUFFIX = '$';
575
+ const isHtmlAttributeAnEventName = (name) => {
576
+ return (name.charCodeAt(0) === 113 /* q */ &&
577
+ name.charCodeAt(1) === 45 /* - */ &&
578
+ name.charCodeAt(3) === 58 /* : */);
579
+ };
580
+ function jsxEventToHtmlAttribute(jsxEvent) {
581
+ if (jsxEvent.endsWith(EVENT_SUFFIX)) {
582
+ const [prefix, idx] = getEventScopeDataFromJsxEvent(jsxEvent);
583
+ if (idx !== -1) {
584
+ const name = jsxEvent.slice(idx, -1);
585
+ return name === 'DOMContentLoaded'
586
+ ? // The only DOM event that is not all lowercase
587
+ prefix + '-d-o-m-content-loaded'
588
+ : createEventName(name.charAt(0) === '-'
589
+ ? // marker for case sensitive event name
590
+ name.slice(1)
591
+ : name.toLowerCase(), prefix);
592
+ }
593
+ }
594
+ return null; // Return null if not matching expected format
595
+ }
596
+ function createEventName(event, prefix) {
597
+ const eventName = fromCamelToKebabCase(event);
598
+ return prefix + eventName;
599
+ }
600
+ function getEventScopeDataFromJsxEvent(eventName) {
601
+ let prefix;
602
+ let idx = -1;
603
+ // set prefix and idx based on the scope
604
+ if (eventName.startsWith("on" /* EventNameJSXScope.on */)) {
605
+ prefix = "q-e:" /* EventNameHtmlScope.on */;
606
+ idx = 2;
607
+ }
608
+ else if (eventName.startsWith("window:on" /* EventNameJSXScope.window */)) {
609
+ prefix = "q-w:" /* EventNameHtmlScope.window */;
610
+ idx = 9;
611
+ }
612
+ else if (eventName.startsWith("document:on" /* EventNameJSXScope.document */)) {
613
+ prefix = "q-d:" /* EventNameHtmlScope.document */;
614
+ idx = 11;
615
+ }
616
+ return [prefix, idx];
617
+ }
618
+ function isPreventDefault(key) {
619
+ return key.startsWith('preventdefault:');
620
+ }
621
+ /** Converts a camelCase string to kebab-case. This is used for event names. */
622
+ const fromCamelToKebabCase = (text) => {
623
+ return text.replace(/([A-Z-])/g, (a) => '-' + a.toLowerCase());
516
624
  };
625
+ /** E.g. `"q-e:click"` => `['e', 'click']` */
626
+ const getEventDataFromHtmlAttribute = (htmlKey) => [
627
+ htmlKey.charAt(2),
628
+ htmlKey.substring(4),
629
+ ];
630
+ /** E.g. `"e:click"`, `"w:load"` */
631
+ const getScopedEventName = (scope, eventName) => scope + ':' + eventName;
517
632
 
518
- /**
519
- * @file
520
- *
521
- * VNodeData is additional information which allows the `vnode` to recover virtual VNode information
522
- * from the HTML.
523
- */
524
- /**
525
- * VNodeDataSeparator contains information about splitting up the VNodeData and attaching it to the
526
- * HTML.
527
- */
528
- const VNodeDataSeparator = {
529
- REFERENCE: /* ******** */ 126, // `~` is a reference to the node. Save it.
530
- ADVANCE_1: /* ********* */ 33, // `!` is vNodeData separator skipping 0. (ie next vNode)
531
- ADVANCE_8192: /* ****** */ 46, // `.` is vNodeData separator skipping 4096.
633
+ /** CSS properties which accept numbers but are not in units of "px". */
634
+ const unitlessNumbers = new Set([
635
+ 'animationIterationCount',
636
+ 'aspectRatio',
637
+ 'borderImageOutset',
638
+ 'borderImageSlice',
639
+ 'borderImageWidth',
640
+ 'boxFlex',
641
+ 'boxFlexGroup',
642
+ 'boxOrdinalGroup',
643
+ 'columnCount',
644
+ 'columns',
645
+ 'flex',
646
+ 'flexGrow',
647
+ 'flexShrink',
648
+ 'gridArea',
649
+ 'gridRow',
650
+ 'gridRowEnd',
651
+ 'gridRowStart',
652
+ 'gridColumn',
653
+ 'gridColumnEnd',
654
+ 'gridColumnStart',
655
+ 'fontWeight',
656
+ 'lineClamp',
657
+ 'lineHeight',
658
+ 'opacity',
659
+ 'order',
660
+ 'orphans',
661
+ 'scale',
662
+ 'tabSize',
663
+ 'widows',
664
+ 'zIndex',
665
+ 'zoom',
666
+ 'MozAnimationIterationCount', // Known Prefixed Properties
667
+ 'MozBoxFlex', // TODO: Remove these since they shouldn't be used in modern code
668
+ 'msFlex',
669
+ 'msFlexPositive',
670
+ 'WebkitAnimationIterationCount',
671
+ 'WebkitBoxFlex',
672
+ 'WebkitBoxOrdinalGroup',
673
+ 'WebkitColumnCount',
674
+ 'WebkitColumns',
675
+ 'WebkitFlex',
676
+ 'WebkitFlexGrow',
677
+ 'WebkitFlexShrink',
678
+ 'WebkitLineClamp',
679
+ ]);
680
+ const isUnitlessNumber = (name) => {
681
+ return unitlessNumbers.has(name);
682
+ };
683
+
684
+ const hashCode = (text, hash = 0) => {
685
+ for (let i = 0; i < text.length; i++) {
686
+ const chr = text.charCodeAt(i);
687
+ hash = (hash << 5) - hash + chr;
688
+ hash |= 0; // Convert to 32bit integer
689
+ }
690
+ return Number(Math.abs(hash)).toString(36);
691
+ };
692
+
693
+ const serializeClass = (obj) => {
694
+ if (!obj) {
695
+ return '';
696
+ }
697
+ if (isString(obj)) {
698
+ return obj.trim();
699
+ }
700
+ const classes = [];
701
+ if (isArray(obj)) {
702
+ for (const o of obj) {
703
+ const classList = serializeClass(o);
704
+ if (classList) {
705
+ classes.push(classList);
706
+ }
707
+ }
708
+ }
709
+ else {
710
+ for (const [key, value] of Object.entries(obj)) {
711
+ if (value) {
712
+ classes.push(key.trim());
713
+ }
714
+ }
715
+ }
716
+ return classes.join(' ');
717
+ };
718
+ // Unlike fromCamelToKebabCase, this leaves `-` so that `background-color` stays `background-color`
719
+ const fromCamelToKebabCaseWithDash = (text) => {
720
+ return text.replace(/([A-Z])/g, '-$1').toLowerCase();
721
+ };
722
+ const stringifyStyle = (obj) => {
723
+ if (obj == null) {
724
+ return '';
725
+ }
726
+ if (typeof obj == 'object') {
727
+ if (isArray(obj)) {
728
+ throw qError(0 /* QError.stringifyClassOrStyle */, [obj, 'style']);
729
+ }
730
+ else {
731
+ const chunks = [];
732
+ for (const key in obj) {
733
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
734
+ const value = obj[key];
735
+ if (value != null && typeof value !== 'function') {
736
+ if (key.startsWith('--')) {
737
+ chunks.push(key + ':' + value);
738
+ }
739
+ else {
740
+ chunks.push(fromCamelToKebabCaseWithDash(key) + ':' + setValueForStyle(key, value));
741
+ }
742
+ }
743
+ }
744
+ }
745
+ return chunks.join(';');
746
+ }
747
+ }
748
+ return String(obj);
749
+ };
750
+ const serializeBooleanOrNumberAttribute = (value) => {
751
+ return value != null ? String(value) : null;
752
+ };
753
+ function serializeAttribute(key, value, styleScopedId) {
754
+ if (isClassAttr(key)) {
755
+ const serializedClass = serializeClass(value);
756
+ value = styleScopedId
757
+ ? styleScopedId + (serializedClass.length ? ' ' + serializedClass : serializedClass)
758
+ : serializedClass;
759
+ }
760
+ else if (key === 'style') {
761
+ value = stringifyStyle(value);
762
+ }
763
+ else if (isEnumeratedBooleanAttribute(key) || typeof value === 'number') {
764
+ // aria attrs, tabindex etc.
765
+ value = serializeBooleanOrNumberAttribute(value);
766
+ }
767
+ else if (value === false || value == null) {
768
+ value = null;
769
+ }
770
+ else if (value === true && isPreventDefault(key)) {
771
+ value = '';
772
+ }
773
+ return value;
774
+ }
775
+ function isEnumeratedBooleanAttribute(key) {
776
+ return isAriaAttribute(key) || ['spellcheck', 'draggable', 'contenteditable'].includes(key);
777
+ }
778
+ const setValueForStyle = (styleName, value) => {
779
+ if (typeof value === 'number' && value !== 0 && !isUnitlessNumber(styleName)) {
780
+ return value + 'px';
781
+ }
782
+ return value;
783
+ };
784
+ function isAriaAttribute(prop) {
785
+ return prop.startsWith('aria-');
786
+ }
787
+ const styleKey = (qStyles, index) => {
788
+ assertQrl(qStyles);
789
+ return `${hashCode(qStyles.$hash$)}-${index}`;
790
+ };
791
+
792
+ // Browser-specific setup
793
+ const doc = isBrowser ? document : undefined;
794
+ // Determine which rel attribute to use based on browser support
795
+ const rel = isBrowser && doc.createElement('link').relList.supports('modulepreload')
796
+ ? 'modulePreload'
797
+ : 'preload';
798
+ const isJSRegex = /\.[mc]?js$/;
799
+
800
+ const BundleImportState_None = 0;
801
+ const BundleImportState_Preload = 2;
802
+ const BundleImportState_Alias = 3;
803
+ const BundleImportState_Loaded = 4;
804
+
805
+ let base;
806
+ const makeBundle = (name, deps) => {
807
+ return {
808
+ $name$: name,
809
+ $state$: isJSRegex.test(name) ? BundleImportState_None : BundleImportState_Alias,
810
+ $deps$: deps,
811
+ $inverseProbability$: 1,
812
+ $createdTs$: Date.now(),
813
+ $waitedMs$: 0,
814
+ $loadedMs$: 0,
815
+ };
816
+ };
817
+ const getBundle = (name) => {
818
+ let bundle = bundles.get(name);
819
+ if (!bundle) {
820
+ let deps;
821
+ bundle = makeBundle(name, deps);
822
+ bundles.set(name, bundle);
823
+ }
824
+ return bundle;
825
+ };
826
+
827
+ const bundles = new Map();
828
+ let preloadCount = 0;
829
+ const queue = [];
830
+ /**
831
+ * This is called when a bundle is queued, or finished loading.
832
+ *
833
+ * Because Chrome doesn't treat new modulepreloads as higher priority, we only make
834
+ * maxSimultaneousPreloads links available at a time, so that when a new high priority bundle comes
835
+ * in, it is soon preloaded.
836
+ *
837
+ * We make sure to first preload the high priority items.
838
+ */
839
+ const trigger = () => {
840
+ if (!queue.length) {
841
+ return;
842
+ }
843
+ while (queue.length) {
844
+ const bundle = queue[0];
845
+ const inverseProbability = bundle.$inverseProbability$;
846
+ const probability = 1 - inverseProbability;
847
+ const allowedPreloads = // While the graph is not available, we limit to 5 preloads
848
+ 5;
849
+ // When we're 99% sure, everything needs to be queued
850
+ if (probability >= 0.99 || preloadCount < allowedPreloads) {
851
+ queue.shift();
852
+ preloadOne(bundle);
853
+ }
854
+ else {
855
+ break;
856
+ }
857
+ }
858
+ };
859
+ const preloadOne = (bundle) => {
860
+ if (bundle.$state$ >= BundleImportState_Preload) {
861
+ return;
862
+ }
863
+ preloadCount++;
864
+ const start = Date.now();
865
+ bundle.$waitedMs$ = start - bundle.$createdTs$;
866
+ bundle.$state$ = BundleImportState_Preload;
867
+ const link = doc.createElement('link');
868
+ // Only bundles with state none are js bundles
869
+ link.href = new URL(`${base}${bundle.$name$}`, doc.baseURI).toString();
870
+ link.rel = rel;
871
+ // Needed when rel is 'preload'
872
+ link.as = 'script';
873
+ // Handle completion of the preload
874
+ link.onload = link.onerror = () => {
875
+ preloadCount--;
876
+ const end = Date.now();
877
+ bundle.$loadedMs$ = end - start;
878
+ bundle.$state$ = BundleImportState_Loaded;
879
+ // Keep the <head> clean
880
+ link.remove();
881
+ // More bundles may be ready to preload
882
+ trigger();
883
+ };
884
+ doc.head.appendChild(link);
885
+ };
886
+ /**
887
+ * Adjust the probability of a bundle based on the probability of its dependent bundles, and queue
888
+ * it if it's likely enough to be preloaded.
889
+ *
890
+ * Note that if the probability is 100%, we treat the dynamic imports as 99% sure, and both will be
891
+ * preloaded without limit.
892
+ *
893
+ * We also limit "organic" probability to 98% so they don't get unlimited preloads.
894
+ */
895
+ const adjustProbabilities = (bundle, newInverseProbability, seen) => {
896
+ if (seen?.has(bundle)) {
897
+ return;
898
+ }
899
+ const previousInverseProbability = bundle.$inverseProbability$;
900
+ bundle.$inverseProbability$ = newInverseProbability;
901
+ // Don't propagate tiny changes
902
+ if (previousInverseProbability - bundle.$inverseProbability$ < 0.01) {
903
+ return;
904
+ }
905
+ if (bundle.$deps$) {
906
+ seen ||= new Set();
907
+ seen.add(bundle);
908
+ const probability = 1 - bundle.$inverseProbability$;
909
+ for (const dep of bundle.$deps$) {
910
+ const depBundle = getBundle(dep.$name$);
911
+ if (depBundle.$inverseProbability$ === 0) {
912
+ // it's already at max probability
913
+ continue;
914
+ }
915
+ /**
916
+ * The chance that a dep won't be loaded is 1-(the chance that the dep will be loaded)*(the
917
+ * chance that the current bundle will be loaded).
918
+ *
919
+ * We can multiply this chance together with all other bundle adjustments to get the chance
920
+ * that a dep will be loaded given all the chances of the other bundles.
921
+ *
922
+ * But when we're very likely to load the current bundle, make the dynamic imports very likely
923
+ * too.
924
+ */
925
+ let newInverseProbability;
926
+ if (probability === 1 || (probability >= 0.99 && depsCount < 100)) {
927
+ depsCount++;
928
+ // we're loaded at max probability, so elevate dynamic imports to 99% sure
929
+ newInverseProbability = Math.min(0.01, 1 - dep.$importProbability$);
930
+ }
931
+ else {
932
+ const newInverseImportProbability = 1 - dep.$importProbability$ * probability;
933
+ /** We need to undo the previous adjustment */
934
+ const prevAdjust = dep.$factor$;
935
+ const factor = newInverseImportProbability / prevAdjust;
936
+ // limit organic probability to 98%
937
+ newInverseProbability = Math.max(0.02, depBundle.$inverseProbability$ * factor);
938
+ dep.$factor$ = factor;
939
+ }
940
+ adjustProbabilities(depBundle, newInverseProbability, seen);
941
+ }
942
+ }
943
+ };
944
+ const handleBundle = (name, inverseProbability) => {
945
+ const bundle = getBundle(name);
946
+ if (bundle && bundle.$inverseProbability$ > inverseProbability) {
947
+ adjustProbabilities(bundle, inverseProbability);
948
+ }
949
+ };
950
+ let depsCount;
951
+ const preload = (name, probability) => {
952
+ if (!name?.length) {
953
+ return;
954
+ }
955
+ depsCount = 0;
956
+ let inverseProbability = 1 - probability ;
957
+ if (Array.isArray(name)) {
958
+ // We must process in reverse order to ensure first bundles are handled first
959
+ for (let i = name.length - 1; i >= 0; i--) {
960
+ const item = name[i];
961
+ if (typeof item === 'number') {
962
+ inverseProbability = 1 - item / 10;
963
+ }
964
+ else {
965
+ handleBundle(item, inverseProbability);
966
+ }
967
+ }
968
+ }
969
+ else {
970
+ handleBundle(name, inverseProbability);
971
+ }
972
+ if (isBrowser) {
973
+ trigger();
974
+ }
975
+ };
976
+ if (isBrowser) {
977
+ // Get early hints from qwikloader
978
+ document.addEventListener('qsymbol', (ev) => {
979
+ const { symbol, href } = ev.detail;
980
+ // the qrl class doesn't emit href, we don't need to preload
981
+ if (href) {
982
+ const hash = symbol.slice(symbol.lastIndexOf('_') + 1);
983
+ preload(hash, 1);
984
+ }
985
+ });
986
+ }
987
+
988
+ const isObjectEmpty = (obj) => {
989
+ for (const key in obj) {
990
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
991
+ return false;
992
+ }
993
+ }
994
+ return true;
995
+ };
996
+
997
+ // Pre-allocated common strings to reduce allocation overhead
998
+ const CLOSE_TAG = '</';
999
+ const ESCAPED_CLOSE_TAG = '<\\/';
1000
+ const QUOTE = '"';
1001
+ const BRACKET_OPEN = '[';
1002
+ const BRACKET_CLOSE = ']';
1003
+ const COMMA = ',';
1004
+
1005
+ /**
1006
+ * QWIK_VERSION
1007
+ *
1008
+ * @public
1009
+ */
1010
+ const version = "2.0.0-beta.25-dev+2677279";
1011
+
1012
+ // keep this import from core/build so the cjs build works
1013
+ const createPlatform = () => {
1014
+ return {
1015
+ isServer,
1016
+ importSymbol(containerEl, url, symbolName) {
1017
+ if (isServer) {
1018
+ const hash = getSymbolHash(symbolName);
1019
+ const regSym = globalThis.__qwik_reg_symbols?.get(hash);
1020
+ if (regSym) {
1021
+ return regSym;
1022
+ }
1023
+ }
1024
+ if (!url) {
1025
+ throw qError(14 /* QError.qrlMissingChunk */, [symbolName]);
1026
+ }
1027
+ if (!containerEl) {
1028
+ throw qError(13 /* QError.qrlMissingContainer */, [url, symbolName]);
1029
+ }
1030
+ const urlDoc = toUrl(containerEl.ownerDocument, containerEl, url).toString();
1031
+ const urlCopy = new URL(urlDoc);
1032
+ urlCopy.hash = '';
1033
+ const importURL = urlCopy.href;
1034
+ return import(/* @vite-ignore */ importURL).then((mod) => {
1035
+ return mod[symbolName];
1036
+ });
1037
+ },
1038
+ raf: (fn) => {
1039
+ return new Promise((resolve) => {
1040
+ requestAnimationFrame(() => {
1041
+ resolve(fn());
1042
+ });
1043
+ });
1044
+ },
1045
+ chunkForSymbol(symbolName, chunk) {
1046
+ return [symbolName, chunk ?? '_'];
1047
+ },
1048
+ };
1049
+ };
1050
+ /**
1051
+ * Convert relative base URI and relative URL into a fully qualified URL.
1052
+ *
1053
+ * @param base -`QRL`s are relative, and therefore they need a base for resolution.
1054
+ *
1055
+ * - `Element` use `base.ownerDocument.baseURI`
1056
+ * - `Document` use `base.baseURI`
1057
+ * - `string` use `base` as is
1058
+ * - `QConfig` use `base.baseURI`
1059
+ *
1060
+ * @param url - Relative URL
1061
+ * @returns Fully qualified URL.
1062
+ */
1063
+ const toUrl = (doc, containerEl, url) => {
1064
+ const baseURI = doc.baseURI;
1065
+ const base = new URL(containerEl.getAttribute(QBaseAttr) ?? baseURI, baseURI);
1066
+ return new URL(url, base);
1067
+ };
1068
+ let _platform = /*#__PURE__ */ createPlatform();
1069
+ // <docs markdown="./readme.md#setPlatform">
1070
+ // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
1071
+ // (edit ./readme.md#setPlatform instead and run `pnpm docs.sync`)
1072
+ /**
1073
+ * Sets the `CorePlatform`.
1074
+ *
1075
+ * This is useful to override the platform in tests to change the behavior of,
1076
+ * `requestAnimationFrame`, and import resolution.
1077
+ *
1078
+ * @param doc - The document of the application for which the platform is needed.
1079
+ * @param platform - The platform to use.
1080
+ * @public
1081
+ */
1082
+ // </docs>
1083
+ const setPlatform = (plt) => (_platform = plt);
1084
+ // <docs markdown="./readme.md#getPlatform">
1085
+ // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
1086
+ // (edit ./readme.md#getPlatform instead and run `pnpm docs.sync`)
1087
+ /**
1088
+ * Retrieve the `CorePlatform`.
1089
+ *
1090
+ * The `CorePlatform` is also responsible for retrieving the Manifest, that contains mappings from
1091
+ * symbols to javascript import chunks. For this reason, `CorePlatform` can't be global, but is
1092
+ * specific to the application currently running. On server it is possible that many different
1093
+ * applications are running in a single server instance, and for this reason the `CorePlatform` is
1094
+ * associated with the application document.
1095
+ *
1096
+ * @param docOrNode - The document (or node) of the application for which the platform is needed.
1097
+ * @public
1098
+ */
1099
+ // </docs>
1100
+ const getPlatform = () => {
1101
+ return _platform;
1102
+ };
1103
+ const isServerPlatform = () => {
1104
+ if (qDynamicPlatform) {
1105
+ return _platform.isServer;
1106
+ }
1107
+ return false;
1108
+ };
1109
+
1110
+ const isNode = (value) => {
1111
+ return value && typeof value.nodeType === 'number';
1112
+ };
1113
+ const isDocument = (value) => {
1114
+ return value.nodeType === 9;
1115
+ };
1116
+ const isElement$1 = (value) => {
1117
+ return value.nodeType === 1;
532
1118
  };
533
- /**
534
- * VNodeDataChar contains information about the VNodeData used for encoding props.
535
- *
536
- * Available character ranges: 59 - 64, 91 - 94, 96, 123 - 126
537
- */
538
- const VNodeDataChar = {
539
- OPEN: /* ************** */ 123, // `{` is the start of the VNodeData for a virtual element.
540
- CLOSE: /* ************* */ 125, // `}` is the end of the VNodeData for a virtual element.
541
- SCOPED_STYLE: /* ******* */ 59, // `;` - `q:sstyle` - Style attribute.
542
- RENDER_FN: /* ********** */ 60, // `<` - `q:renderFn' - Component QRL render function (body)
543
- ID: /* ***************** */ 61, // `=` - `q:id` - ID of the element.
544
- PROPS: /* ************** */ 62, // `>` - `q:props' - Component Props
545
- SLOT_PARENT: /* ******** */ 63, // `?` - `q:sparent` - Slot parent.
546
- KEY: /* **************** */ 64, // `@` - `q:key` - Element key.
547
- SEQ: /* **************** */ 91, // `[` - `q:seq' - Seq value from `useSequentialScope()`
548
- CONTEXT: /* ************ */ 93, // `]` - `q:ctx' - Component context/props
549
- SEQ_IDX: /* ************ */ 94, // `^` - `q:seqIdx' - Sequential scope id
550
- BACK_REFS: /* ********** */ 96, // '`' - `q:brefs' - Effect dependencies/subscriptions
551
- SEPARATOR: /* ********* */ 124, // `|` - Separator char to encode any key/value pairs.
552
- SLOT: /* ************** */ 126};
553
1119
 
554
1120
  const isForeignObjectElement = (elementName) => {
555
1121
  return isDev ? elementName.toLowerCase() === 'foreignobject' : elementName === 'foreignObject';
@@ -773,75 +1339,6 @@ const mergeMaps = (map1, map2) => {
773
1339
  return map1;
774
1340
  };
775
1341
 
776
- /**
777
- * Think of `-` as an escape character which makes the next character uppercase. `--` is just `-`.
778
- *
779
- * Rules for JSX property event names starting with `on`:
780
- *
781
- * - Are case insensitive: `onClick$` is same `onclick$`
782
- * - A `--` is `-`: `dbl--click` => `dbl-click`
783
- * - Become case sensitive if prefixed by `-`: `-Click` is `Click`
784
- * - A `-` (not at the beginning) makes next character uppercase: `dbl-click` => `dblClick`
785
- */
786
- const EVENT_SUFFIX = '$';
787
- const isHtmlAttributeAnEventName = (name) => {
788
- return (name.charCodeAt(0) === 113 /* q */ &&
789
- name.charCodeAt(1) === 45 /* - */ &&
790
- name.charCodeAt(3) === 58 /* : */);
791
- };
792
- function jsxEventToHtmlAttribute(jsxEvent) {
793
- if (jsxEvent.endsWith(EVENT_SUFFIX)) {
794
- const [prefix, idx] = getEventScopeDataFromJsxEvent(jsxEvent);
795
- if (idx !== -1) {
796
- const name = jsxEvent.slice(idx, -1);
797
- return name === 'DOMContentLoaded'
798
- ? // The only DOM event that is not all lowercase
799
- prefix + '-d-o-m-content-loaded'
800
- : createEventName(name.charAt(0) === '-'
801
- ? // marker for case sensitive event name
802
- name.slice(1)
803
- : name.toLowerCase(), prefix);
804
- }
805
- }
806
- return null; // Return null if not matching expected format
807
- }
808
- function createEventName(event, prefix) {
809
- const eventName = fromCamelToKebabCase(event);
810
- return prefix + eventName;
811
- }
812
- function getEventScopeDataFromJsxEvent(eventName) {
813
- let prefix;
814
- let idx = -1;
815
- // set prefix and idx based on the scope
816
- if (eventName.startsWith("on" /* EventNameJSXScope.on */)) {
817
- prefix = "q-e:" /* EventNameHtmlScope.on */;
818
- idx = 2;
819
- }
820
- else if (eventName.startsWith("window:on" /* EventNameJSXScope.window */)) {
821
- prefix = "q-w:" /* EventNameHtmlScope.window */;
822
- idx = 9;
823
- }
824
- else if (eventName.startsWith("document:on" /* EventNameJSXScope.document */)) {
825
- prefix = "q-d:" /* EventNameHtmlScope.document */;
826
- idx = 11;
827
- }
828
- return [prefix, idx];
829
- }
830
- function isPreventDefault(key) {
831
- return key.startsWith('preventdefault:');
832
- }
833
- /** Converts a camelCase string to kebab-case. This is used for event names. */
834
- const fromCamelToKebabCase = (text) => {
835
- return text.replace(/([A-Z-])/g, (a) => '-' + a.toLowerCase());
836
- };
837
- /** E.g. `"q-e:click"` => `['e', 'click']` */
838
- const getEventDataFromHtmlAttribute = (htmlKey) => [
839
- htmlKey.charAt(2),
840
- htmlKey.substring(4),
841
- ];
842
- /** E.g. `"e:click"`, `"w:load"` */
843
- const getScopedEventName = (scope, eventName) => scope + ':' + eventName;
844
-
845
1342
  /** @internal */
846
1343
  const _EFFECT_BACK_REF = Symbol('backRef');
847
1344
  /** Class for back reference to the EffectSubscription */
@@ -1092,16 +1589,20 @@ class SignalImpl {
1092
1589
  this.$untrackedValue$ = value;
1093
1590
  }
1094
1591
  /**
1095
- * Use this to force running subscribers, for example when the calculated value has mutated but
1592
+ * Use this to trigger running subscribers, for example when the calculated value has mutated but
1096
1593
  * remained the same object
1097
1594
  */
1595
+ trigger() {
1596
+ scheduleEffects(this.$container$, this, this.$effects$);
1597
+ }
1598
+ /** @deprecated Use `trigger()` instead */
1098
1599
  force() {
1099
1600
  scheduleEffects(this.$container$, this, this.$effects$);
1100
1601
  }
1602
+ // We need this to be getter/setter so subclasses can override them
1101
1603
  get untrackedValue() {
1102
1604
  return this.$untrackedValue$;
1103
1605
  }
1104
- // TODO: should we disallow setting the value directly?
1105
1606
  set untrackedValue(value) {
1106
1607
  this.$untrackedValue$ = value;
1107
1608
  }
@@ -1205,6 +1706,7 @@ const _UNINITIALIZED = Symbol('UNINITIALIZED');
1205
1706
 
1206
1707
  /** @internal */
1207
1708
  const EMPTY_ARRAY = [];
1709
+ /** @internal */
1208
1710
  const EMPTY_OBJ = {};
1209
1711
  Object.freeze(EMPTY_ARRAY);
1210
1712
  Object.freeze(EMPTY_OBJ);
@@ -1616,6 +2118,9 @@ class ComputedSignalImpl extends SignalImpl {
1616
2118
  isDev && assertFalse(this.$untrackedValue$ === NEEDS_COMPUTATION, 'Invalid state');
1617
2119
  return this.$untrackedValue$;
1618
2120
  }
2121
+ set untrackedValue(value) {
2122
+ this.$untrackedValue$ = value;
2123
+ }
1619
2124
  $computeIfNeeded$() {
1620
2125
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1621
2126
  return;
@@ -1711,18 +2216,17 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1711
2216
  $jobs$ = [];
1712
2217
  $concurrency$ = 1;
1713
2218
  $interval$ = 0;
1714
- $pollTimeoutId$ = undefined;
1715
2219
  $timeoutMs$;
1716
- $computationTimeoutId$;
1717
2220
  [_EFFECT_BACK_REF] = undefined;
1718
2221
  constructor(container, fn, flags = 1 /* SignalFlags.INVALID */ |
1719
2222
  16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */, options) {
1720
2223
  super(container, fn, flags);
1721
- const interval = options?.interval || 0;
2224
+ const interval = options?.interval;
1722
2225
  const concurrency = options?.concurrency ?? 1;
1723
2226
  const initial = options?.initial;
1724
2227
  const timeout = options?.timeout;
1725
2228
  const eagerCleanup = options?.eagerCleanup;
2229
+ const clientOnly = options?.clientOnly;
1726
2230
  // Handle initial value - eagerly evaluate if function, set $untrackedValue$ and $promiseValue$
1727
2231
  // Do NOT call setValue() which would clear the INVALID flag and prevent async computation
1728
2232
  if (initial !== undefined) {
@@ -1730,11 +2234,42 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1730
2234
  this.$untrackedValue$ = initialValue;
1731
2235
  }
1732
2236
  this.$concurrency$ = concurrency;
1733
- this.$timeoutMs$ = timeout;
2237
+ if (timeout) {
2238
+ this.$timeoutMs$ = timeout;
2239
+ }
1734
2240
  if (eagerCleanup) {
1735
2241
  this.$flags$ |= 32 /* AsyncSignalFlags.EAGER_CLEANUP */;
1736
2242
  }
1737
- this.interval = interval;
2243
+ if (clientOnly) {
2244
+ this.$flags$ |= 64 /* AsyncSignalFlags.CLIENT_ONLY */;
2245
+ }
2246
+ if (interval) {
2247
+ this.interval = interval;
2248
+ }
2249
+ }
2250
+ get untrackedValue() {
2251
+ this.$computeIfNeeded$();
2252
+ if (this.$current$?.$promise$) {
2253
+ if (this.$untrackedValue$ === NEEDS_COMPUTATION ||
2254
+ (import.meta.env.TEST ? isServerPlatform() : isServer)) {
2255
+ throw this.$current$?.$promise$;
2256
+ }
2257
+ return this.$untrackedValue$;
2258
+ }
2259
+ if (this.$untrackedError$) {
2260
+ throw this.$untrackedError$;
2261
+ }
2262
+ // For clientOnly signals without initial value during SSR, throw if trying to read value
2263
+ // During SSR, clientOnly signals are skipped, so there's no computed value available
2264
+ if ((import.meta.env.TEST ? isServerPlatform() : isServer) &&
2265
+ this.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */ &&
2266
+ this.$untrackedValue$ === NEEDS_COMPUTATION) {
2267
+ throw new Error('During SSR, cannot read .value from clientOnly async signal without an initial value. Use .loading or provide an initial value.');
2268
+ }
2269
+ return this.$untrackedValue$;
2270
+ }
2271
+ set untrackedValue(value) {
2272
+ this.$untrackedValue$ = value;
1738
2273
  }
1739
2274
  /**
1740
2275
  * Loading is true if the signal is still waiting for the promise to resolve, false if the promise
@@ -1827,6 +2362,14 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1827
2362
  if (!(this.$flags$ & 1 /* SignalFlags.INVALID */)) {
1828
2363
  return;
1829
2364
  }
2365
+ // Skip computation on SSR for clientOnly signals
2366
+ if ((import.meta.env.TEST ? isServerPlatform() : isServer) &&
2367
+ this.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
2368
+ // We must pretend to load, and register as a listener for the captures
2369
+ this.$untrackedLoading$ = true;
2370
+ this.$container$?.serializationCtx.$eagerResume$.add(this);
2371
+ return;
2372
+ }
1830
2373
  this.$clearNextPoll$();
1831
2374
  if (this.$current$) {
1832
2375
  this.$requestCleanups$(this.$current$);
@@ -1901,20 +2444,6 @@ class AsyncSignalImpl extends ComputedSignalImpl {
1901
2444
  }
1902
2445
  await Promise.all(this.$jobs$.map((job) => job.$promise$));
1903
2446
  }
1904
- get untrackedValue() {
1905
- this.$computeIfNeeded$();
1906
- if (this.$current$?.$promise$) {
1907
- if (this.$untrackedValue$ === NEEDS_COMPUTATION ||
1908
- (import.meta.env.TEST ? isServerPlatform() : isServer)) {
1909
- throw this.$current$?.$promise$;
1910
- }
1911
- return this.$untrackedValue$;
1912
- }
1913
- if (this.$untrackedError$) {
1914
- throw this.$untrackedError$;
1915
- }
1916
- return this.$untrackedValue$;
1917
- }
1918
2447
  $clearNextPoll$() {
1919
2448
  if (this.$pollTimeoutId$ !== undefined) {
1920
2449
  clearTimeout(this.$pollTimeoutId$);
@@ -2198,6 +2727,8 @@ class WrappedSignalImpl extends SignalImpl {
2198
2727
  $funcStr$;
2199
2728
  $flags$;
2200
2729
  $hostElement$ = undefined;
2730
+ // important: don't use implemnets BackRef here
2731
+ // it causes v8 optimizations eager bailouts, because of not consistent class shape
2201
2732
  [_EFFECT_BACK_REF] = undefined;
2202
2733
  constructor(container, fn, args, fnStr,
2203
2734
  // We need a separate flag to know when the computation needs running because
@@ -2393,17 +2924,16 @@ function _chk(_, element) {
2393
2924
  */
2394
2925
  function _res(_, element) {
2395
2926
  maybeScopeFromQL(this, element);
2396
- // Captures are deserialized, signals are now resumed
2397
- }
2398
-
2399
- const isObjectEmpty = (obj) => {
2400
- for (const key in obj) {
2401
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
2402
- return false;
2927
+ // Captures are deserialized, now trigger computation on AsyncSignals
2928
+ if (_captures) {
2929
+ for (const capture of _captures) {
2930
+ if (capture instanceof AsyncSignalImpl && capture.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
2931
+ capture.$computeIfNeeded$();
2932
+ }
2933
+ // note that polling async signals will automatically schedule themselves so no action needed
2403
2934
  }
2404
2935
  }
2405
- return true;
2406
- };
2936
+ }
2407
2937
 
2408
2938
  const _hasOwnProperty$2 = Object.prototype.hasOwnProperty;
2409
2939
  // TODO store props as the arrays the vnodes also use?
@@ -2462,6 +2992,9 @@ const isJSXNode = (n) => {
2462
2992
  _hasOwnProperty$2.call(n, 'key') &&
2463
2993
  _hasOwnProperty$2.call(n, 'props') &&
2464
2994
  _hasOwnProperty$2.call(n, 'type')) {
2995
+ if (isPropsProxy(n)) {
2996
+ return false;
2997
+ }
2465
2998
  logWarn(`Duplicate implementations of "JSXNode" found`);
2466
2999
  return true;
2467
3000
  }
@@ -2535,6 +3068,14 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
2535
3068
  }
2536
3069
  delete constProps[k];
2537
3070
  }
3071
+ else if (k === BIND_CHECKED) {
3072
+ // Set flag, will process after walk
3073
+ bindCheckedSignal = constProps[k];
3074
+ }
3075
+ else if (k === BIND_VALUE) {
3076
+ // Set flag, will process after walk
3077
+ bindValueSignal = constProps[k];
3078
+ }
2538
3079
  processedKeys.add(k);
2539
3080
  }
2540
3081
  }
@@ -2564,44 +3105,65 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
2564
3105
  }
2565
3106
  processedKeys.add(k);
2566
3107
  }
2567
- // Handle bind:* - only in varProps, bind:* should be moved to varProps
2568
- if (bindCheckedSignal || bindValueSignal) {
2569
- if (!varPropsCopied) {
2570
- varProps = { ...varProps };
2571
- varPropsCopied = true;
2572
- }
2573
- if (bindCheckedSignal) {
3108
+ }
3109
+ // Handle bind:* - only in varProps, bind:* should be moved to varProps
3110
+ if (bindCheckedSignal || bindValueSignal) {
3111
+ if (!varPropsCopied) {
3112
+ varProps = { ...varProps };
3113
+ varPropsCopied = true;
3114
+ }
3115
+ varProps ||= {};
3116
+ if (bindCheckedSignal) {
3117
+ // Delete from both varProps and constProps if present
3118
+ if (varProps && _hasOwnProperty$1.call(varProps, BIND_CHECKED)) {
2574
3119
  delete varProps[BIND_CHECKED];
2575
- varProps.checked = bindCheckedSignal;
2576
- const handler = createQRL(null, '_chk', _chk, null, [bindCheckedSignal]);
2577
- // Move q-e:input from constProps if it exists
2578
- if (constProps && _hasOwnProperty$1.call(constProps, 'q-e:input')) {
2579
- if (!constPropsCopied) {
2580
- constProps = { ...constProps };
2581
- constPropsCopied = true;
2582
- }
2583
- const existingHandler = constProps['q-e:input'];
2584
- delete constProps['q-e:input'];
2585
- toSort = mergeHandlers(varProps, 'q-e:input', existingHandler) || toSort;
3120
+ }
3121
+ if (constProps && _hasOwnProperty$1.call(constProps, BIND_CHECKED)) {
3122
+ if (!constPropsCopied) {
3123
+ constProps = { ...constProps };
3124
+ constPropsCopied = true;
3125
+ }
3126
+ delete constProps[BIND_CHECKED];
3127
+ }
3128
+ varProps.checked = bindCheckedSignal;
3129
+ const handler = createQRL(null, '_chk', _chk, null, [bindCheckedSignal]);
3130
+ // Move q-e:input from constProps if it exists
3131
+ if (constProps && _hasOwnProperty$1.call(constProps, 'q-e:input')) {
3132
+ if (!constPropsCopied) {
3133
+ constProps = { ...constProps };
3134
+ constPropsCopied = true;
2586
3135
  }
2587
- toSort = mergeHandlers(varProps, 'q-e:input', handler) || toSort;
3136
+ const existingHandler = constProps['q-e:input'];
3137
+ delete constProps['q-e:input'];
3138
+ toSort = mergeHandlers(varProps, 'q-e:input', existingHandler) || toSort;
2588
3139
  }
2589
- else if (bindValueSignal) {
3140
+ toSort = mergeHandlers(varProps, 'q-e:input', handler) || toSort;
3141
+ }
3142
+ else if (bindValueSignal) {
3143
+ // Delete from both varProps and constProps if present
3144
+ if (varProps && _hasOwnProperty$1.call(varProps, BIND_VALUE)) {
2590
3145
  delete varProps[BIND_VALUE];
2591
- varProps.value = bindValueSignal;
2592
- const handler = createQRL(null, '_val', _val, null, [bindValueSignal]);
2593
- // Move q-e:input from constProps if it exists
2594
- if (constProps && _hasOwnProperty$1.call(constProps, 'q-e:input')) {
2595
- if (!constPropsCopied) {
2596
- constProps = { ...constProps };
2597
- constPropsCopied = true;
2598
- }
2599
- const existingHandler = constProps['q-e:input'];
2600
- delete constProps['q-e:input'];
2601
- toSort = mergeHandlers(varProps, 'q-e:input', existingHandler) || toSort;
3146
+ }
3147
+ if (constProps && _hasOwnProperty$1.call(constProps, BIND_VALUE)) {
3148
+ if (!constPropsCopied) {
3149
+ constProps = { ...constProps };
3150
+ constPropsCopied = true;
3151
+ }
3152
+ delete constProps[BIND_VALUE];
3153
+ }
3154
+ varProps.value = bindValueSignal;
3155
+ const handler = createQRL(null, '_val', _val, null, [bindValueSignal]);
3156
+ // Move q-e:input from constProps if it exists
3157
+ if (constProps && _hasOwnProperty$1.call(constProps, 'q-e:input')) {
3158
+ if (!constPropsCopied) {
3159
+ constProps = { ...constProps };
3160
+ constPropsCopied = true;
2602
3161
  }
2603
- toSort = mergeHandlers(varProps, 'q-e:input', handler) || toSort;
3162
+ const existingHandler = constProps['q-e:input'];
3163
+ delete constProps['q-e:input'];
3164
+ toSort = mergeHandlers(varProps, 'q-e:input', existingHandler) || toSort;
2604
3165
  }
3166
+ toSort = mergeHandlers(varProps, 'q-e:input', handler) || toSort;
2605
3167
  }
2606
3168
  }
2607
3169
  // Transform className -> class
@@ -2914,7 +3476,6 @@ function addUseOnEvent(jsxElement, key, value) {
2914
3476
  props[key] = undefined;
2915
3477
  }
2916
3478
  }
2917
- const getValue = (o) => o.value;
2918
3479
  /**
2919
3480
  * Finds the first element node in the JSX output.
2920
3481
  *
@@ -2938,7 +3499,7 @@ function findFirstElementNode(jsx) {
2938
3499
  return maybeThen(jsx, (jsx) => findFirstElementNode(jsx));
2939
3500
  }
2940
3501
  else if (isSignal(jsx)) {
2941
- return findFirstElementNode(untrack(getValue, jsx));
3502
+ return findFirstElementNode(jsx.untrackedValue);
2942
3503
  }
2943
3504
  }
2944
3505
  return null;
@@ -3007,11 +3568,7 @@ const SSRRaw = () => null;
3007
3568
  const SSRComment = () => null;
3008
3569
  /** @public */
3009
3570
  const SSRStreamBlock = (props) => {
3010
- return [
3011
- jsx(SSRComment, { data: STREAM_BLOCK_START_COMMENT }),
3012
- props.children,
3013
- jsx(SSRComment, { data: STREAM_BLOCK_END_COMMENT }),
3014
- ];
3571
+ return props.children;
3015
3572
  };
3016
3573
  /** @public */
3017
3574
  const SSRStream = (props, key) => jsx(RenderOnce, { children: jsx(InternalSSRStream, props) }, key);
@@ -3023,78 +3580,26 @@ const fastSetAttribute = (target, name, value) => {
3023
3580
  _setAttribute = target.setAttribute;
3024
3581
  }
3025
3582
  _setAttribute.call(target, name, value);
3026
- };
3027
- let _setAttributeNS = null;
3028
- const fastSetAttributeNS = (target, namespace, name, value) => {
3029
- if (!_setAttributeNS) {
3030
- _setAttributeNS = target.setAttributeNS;
3031
- }
3032
- _setAttributeNS.call(target, namespace, name, value);
3033
- };
3034
- function directSetAttribute(element, attrName, attrValue, isSvg) {
3035
- if (attrValue != null) {
3036
- if (isSvg) {
3037
- // only svg elements can have namespace attributes
3038
- const namespace = getAttributeNamespace(attrName);
3039
- if (namespace) {
3040
- fastSetAttributeNS(element, namespace, attrName, attrValue);
3041
- return;
3042
- }
3043
- }
3044
- fastSetAttribute(element, attrName, attrValue);
3045
- }
3046
- }
3047
-
3048
- function escapeHTML(html) {
3049
- let escapedHTML = '';
3050
- const length = html.length;
3051
- let idx = 0;
3052
- let lastIdx = idx;
3053
- for (; idx < length; idx++) {
3054
- // We get the charCode NOT string. String would allocate memory.
3055
- const ch = html.charCodeAt(idx);
3056
- // Every time we concat a string we allocate memory. We want to minimize that.
3057
- if (ch === 60 /* < */) {
3058
- escapedHTML += html.substring(lastIdx, idx) + '&lt;';
3059
- }
3060
- else if (ch === 62 /* > */) {
3061
- escapedHTML += html.substring(lastIdx, idx) + '&gt;';
3062
- }
3063
- else if (ch === 38 /* & */) {
3064
- escapedHTML += html.substring(lastIdx, idx) + '&amp;';
3065
- }
3066
- else if (ch === 34 /* " */) {
3067
- escapedHTML += html.substring(lastIdx, idx) + '&quot;';
3068
- }
3069
- else if (ch === 39 /* ' */) {
3070
- escapedHTML += html.substring(lastIdx, idx) + '&#39;';
3071
- }
3072
- else {
3073
- continue;
3074
- }
3075
- lastIdx = idx + 1;
3076
- }
3077
- if (lastIdx === 0) {
3078
- // This is most common case, just return previous string no memory allocation.
3079
- return html;
3080
- }
3081
- else {
3082
- // Add the tail of replacement.
3083
- return escapedHTML + html.substring(lastIdx);
3084
- }
3085
- }
3086
- function decodeVNodeDataString(str) {
3087
- let result = '';
3088
- for (let i = 0; i < str.length; i++) {
3089
- if (str.charAt(i) === '\\' && i + 1 < str.length) {
3090
- result += str.charAt(i + 1);
3091
- i++;
3092
- }
3093
- else {
3094
- result += str.charAt(i);
3583
+ };
3584
+ let _setAttributeNS = null;
3585
+ const fastSetAttributeNS = (target, namespace, name, value) => {
3586
+ if (!_setAttributeNS) {
3587
+ _setAttributeNS = target.setAttributeNS;
3588
+ }
3589
+ _setAttributeNS.call(target, namespace, name, value);
3590
+ };
3591
+ function directSetAttribute(element, attrName, attrValue, isSvg) {
3592
+ if (attrValue != null) {
3593
+ if (isSvg) {
3594
+ // only svg elements can have namespace attributes
3595
+ const namespace = getAttributeNamespace(attrName);
3596
+ if (namespace) {
3597
+ fastSetAttributeNS(element, namespace, attrName, attrValue);
3598
+ return;
3599
+ }
3095
3600
  }
3601
+ fastSetAttribute(element, attrName, attrValue);
3096
3602
  }
3097
- return result;
3098
3603
  }
3099
3604
 
3100
3605
  function getFileLocationFromJsx(jsxDev) {
@@ -3133,187 +3638,6 @@ const _restProps = (props, omit = [], target = {}) => {
3133
3638
  return createPropsProxy(new JSXNodeImpl(null, varPropsTarget, constPropsTarget, null, null));
3134
3639
  };
3135
3640
 
3136
- const styleContent = (styleId) => {
3137
- return ComponentStylesPrefixContent + styleId;
3138
- };
3139
- function isClassAttr(key) {
3140
- return key === 'class';
3141
- }
3142
- function convertScopedStyleIdsToArray(scopedStyleIds) {
3143
- return scopedStyleIds?.split(' ') ?? null;
3144
- }
3145
- function convertStyleIdsToString(scopedStyleIds) {
3146
- return Array.from(scopedStyleIds).join(' ');
3147
- }
3148
- const addComponentStylePrefix = (styleId) => {
3149
- if (styleId) {
3150
- let idx = 0;
3151
- do {
3152
- styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
3153
- } while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
3154
- }
3155
- return styleId || null;
3156
- };
3157
-
3158
- /** CSS properties which accept numbers but are not in units of "px". */
3159
- const unitlessNumbers = new Set([
3160
- 'animationIterationCount',
3161
- 'aspectRatio',
3162
- 'borderImageOutset',
3163
- 'borderImageSlice',
3164
- 'borderImageWidth',
3165
- 'boxFlex',
3166
- 'boxFlexGroup',
3167
- 'boxOrdinalGroup',
3168
- 'columnCount',
3169
- 'columns',
3170
- 'flex',
3171
- 'flexGrow',
3172
- 'flexShrink',
3173
- 'gridArea',
3174
- 'gridRow',
3175
- 'gridRowEnd',
3176
- 'gridRowStart',
3177
- 'gridColumn',
3178
- 'gridColumnEnd',
3179
- 'gridColumnStart',
3180
- 'fontWeight',
3181
- 'lineClamp',
3182
- 'lineHeight',
3183
- 'opacity',
3184
- 'order',
3185
- 'orphans',
3186
- 'scale',
3187
- 'tabSize',
3188
- 'widows',
3189
- 'zIndex',
3190
- 'zoom',
3191
- 'MozAnimationIterationCount', // Known Prefixed Properties
3192
- 'MozBoxFlex', // TODO: Remove these since they shouldn't be used in modern code
3193
- 'msFlex',
3194
- 'msFlexPositive',
3195
- 'WebkitAnimationIterationCount',
3196
- 'WebkitBoxFlex',
3197
- 'WebkitBoxOrdinalGroup',
3198
- 'WebkitColumnCount',
3199
- 'WebkitColumns',
3200
- 'WebkitFlex',
3201
- 'WebkitFlexGrow',
3202
- 'WebkitFlexShrink',
3203
- 'WebkitLineClamp',
3204
- ]);
3205
- const isUnitlessNumber = (name) => {
3206
- return unitlessNumbers.has(name);
3207
- };
3208
-
3209
- const hashCode = (text, hash = 0) => {
3210
- for (let i = 0; i < text.length; i++) {
3211
- const chr = text.charCodeAt(i);
3212
- hash = (hash << 5) - hash + chr;
3213
- hash |= 0; // Convert to 32bit integer
3214
- }
3215
- return Number(Math.abs(hash)).toString(36);
3216
- };
3217
-
3218
- const serializeClass = (obj) => {
3219
- if (!obj) {
3220
- return '';
3221
- }
3222
- if (isString(obj)) {
3223
- return obj.trim();
3224
- }
3225
- const classes = [];
3226
- if (isArray(obj)) {
3227
- for (const o of obj) {
3228
- const classList = serializeClass(o);
3229
- if (classList) {
3230
- classes.push(classList);
3231
- }
3232
- }
3233
- }
3234
- else {
3235
- for (const [key, value] of Object.entries(obj)) {
3236
- if (value) {
3237
- classes.push(key.trim());
3238
- }
3239
- }
3240
- }
3241
- return classes.join(' ');
3242
- };
3243
- // Unlike fromCamelToKebabCase, this leaves `-` so that `background-color` stays `background-color`
3244
- const fromCamelToKebabCaseWithDash = (text) => {
3245
- return text.replace(/([A-Z])/g, '-$1').toLowerCase();
3246
- };
3247
- const stringifyStyle = (obj) => {
3248
- if (obj == null) {
3249
- return '';
3250
- }
3251
- if (typeof obj == 'object') {
3252
- if (isArray(obj)) {
3253
- throw qError(0 /* QError.stringifyClassOrStyle */, [obj, 'style']);
3254
- }
3255
- else {
3256
- const chunks = [];
3257
- for (const key in obj) {
3258
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
3259
- const value = obj[key];
3260
- if (value != null && typeof value !== 'function') {
3261
- if (key.startsWith('--')) {
3262
- chunks.push(key + ':' + value);
3263
- }
3264
- else {
3265
- chunks.push(fromCamelToKebabCaseWithDash(key) + ':' + setValueForStyle(key, value));
3266
- }
3267
- }
3268
- }
3269
- }
3270
- return chunks.join(';');
3271
- }
3272
- }
3273
- return String(obj);
3274
- };
3275
- const serializeBooleanOrNumberAttribute = (value) => {
3276
- return value != null ? String(value) : null;
3277
- };
3278
- function serializeAttribute(key, value, styleScopedId) {
3279
- if (isClassAttr(key)) {
3280
- const serializedClass = serializeClass(value);
3281
- value = styleScopedId
3282
- ? styleScopedId + (serializedClass.length ? ' ' + serializedClass : serializedClass)
3283
- : serializedClass;
3284
- }
3285
- else if (key === 'style') {
3286
- value = stringifyStyle(value);
3287
- }
3288
- else if (isEnumeratedBooleanAttribute(key) || typeof value === 'number') {
3289
- // aria attrs, tabindex etc.
3290
- value = serializeBooleanOrNumberAttribute(value);
3291
- }
3292
- else if (value === false || value == null) {
3293
- value = null;
3294
- }
3295
- else if (value === true && isPreventDefault(key)) {
3296
- value = '';
3297
- }
3298
- return value;
3299
- }
3300
- function isEnumeratedBooleanAttribute(key) {
3301
- return isAriaAttribute(key) || ['spellcheck', 'draggable', 'contenteditable'].includes(key);
3302
- }
3303
- const setValueForStyle = (styleName, value) => {
3304
- if (typeof value === 'number' && value !== 0 && !isUnitlessNumber(styleName)) {
3305
- return value + 'px';
3306
- }
3307
- return value;
3308
- };
3309
- function isAriaAttribute(prop) {
3310
- return prop.startsWith('aria-');
3311
- }
3312
- const styleKey = (qStyles, index) => {
3313
- assertQrl(qStyles);
3314
- return `${hashCode(qStyles.$hash$)}-${index}`;
3315
- };
3316
-
3317
3641
  class DeleteOperation {
3318
3642
  target;
3319
3643
  constructor(target) {
@@ -3329,7 +3653,6 @@ class RemoveAllChildrenOperation {
3329
3653
  class SetTextOperation {
3330
3654
  target;
3331
3655
  text;
3332
- operationType = 16 /* VNodeOperationType.SetText */;
3333
3656
  constructor(target, text) {
3334
3657
  this.target = target;
3335
3658
  this.text = text;
@@ -3418,6 +3741,10 @@ function runEventHandlerQRL(handler, event, element, ctx = newInvokeContextFromD
3418
3741
  * @internal
3419
3742
  */
3420
3743
  function _run(event, element) {
3744
+ if (!element.isConnected) {
3745
+ // ignore events on disconnected elements, this can happen when the event is triggered while the element is being removed
3746
+ return;
3747
+ }
3421
3748
  const ctx = newInvokeContextFromDOM(event, element);
3422
3749
  if (typeof this === 'string') {
3423
3750
  setCaptures(deserializeCaptures(ctx.$container$, this));
@@ -3427,55 +3754,6 @@ function _run(event, element) {
3427
3754
  return runEventHandlerQRL(qrlToRun, event, element, ctx);
3428
3755
  }
3429
3756
 
3430
- /** @internal */
3431
- const mapApp_findIndx = (array, key, start) => {
3432
- isDev && assertTrue(start % 2 === 0, 'Expecting even number.');
3433
- let bottom = start >> 1;
3434
- let top = (array.length - 2) >> 1;
3435
- while (bottom <= top) {
3436
- const mid = bottom + ((top - bottom) >> 1);
3437
- const midKey = array[mid << 1];
3438
- if (midKey === key) {
3439
- return mid << 1;
3440
- }
3441
- if (midKey < key) {
3442
- bottom = mid + 1;
3443
- }
3444
- else {
3445
- top = mid - 1;
3446
- }
3447
- }
3448
- return (bottom << 1) ^ -1;
3449
- };
3450
- /** @internal */
3451
- const mapArray_set = (array, key, value, start, allowNullValue = false) => {
3452
- const indx = mapApp_findIndx(array, key, start);
3453
- if (indx >= 0) {
3454
- if (value == null && !allowNullValue) {
3455
- array.splice(indx, 2);
3456
- }
3457
- else {
3458
- array[indx + 1] = value;
3459
- }
3460
- }
3461
- else if (value != null || allowNullValue) {
3462
- array.splice(indx ^ -1, 0, key, value);
3463
- }
3464
- };
3465
- /** @internal */
3466
- const mapArray_get = (array, key, start) => {
3467
- const indx = mapApp_findIndx(array, key, start);
3468
- if (indx >= 0) {
3469
- return array[indx + 1];
3470
- }
3471
- else {
3472
- return null;
3473
- }
3474
- };
3475
- const mapArray_has = (array, key, start) => {
3476
- return mapApp_findIndx(array, key, start) >= 0;
3477
- };
3478
-
3479
3757
  /**
3480
3758
  * Helper to get the next sibling of a VNode. Extracted to module scope to help V8 inline it
3481
3759
  * reliably.
@@ -3565,7 +3843,7 @@ function diff(diffContext, jsxNode, vStartNode) {
3565
3843
  if (isJSXNode(diffContext.jsxValue)) {
3566
3844
  const type = diffContext.jsxValue.type;
3567
3845
  if (typeof type === 'string') {
3568
- expectNoMoreTextNodes(diffContext);
3846
+ expectNoTextNode(diffContext);
3569
3847
  expectElement(diffContext, diffContext.jsxValue, type);
3570
3848
  const hasDangerousInnerHTML = (diffContext.jsxValue.constProps &&
3571
3849
  _hasOwnProperty.call(diffContext.jsxValue.constProps, dangerouslySetInnerHTML)) ||
@@ -3579,12 +3857,12 @@ function diff(diffContext, jsxNode, vStartNode) {
3579
3857
  }
3580
3858
  else if (typeof type === 'function') {
3581
3859
  if (type === Fragment) {
3582
- expectNoMoreTextNodes(diffContext);
3860
+ expectNoTextNode(diffContext);
3583
3861
  expectVirtual(diffContext, "F" /* VirtualType.Fragment */, diffContext.jsxValue.key);
3584
3862
  descend(diffContext, diffContext.jsxValue.children, true);
3585
3863
  }
3586
3864
  else if (type === Slot) {
3587
- expectNoMoreTextNodes(diffContext);
3865
+ expectNoTextNode(diffContext);
3588
3866
  if (!expectSlot(diffContext)) {
3589
3867
  // nothing to project, so try to render the Slot default content.
3590
3868
  descend(diffContext, diffContext.jsxValue.children, true);
@@ -3605,7 +3883,7 @@ function diff(diffContext, jsxNode, vStartNode) {
3605
3883
  }
3606
3884
  else {
3607
3885
  // Must be a component
3608
- expectNoMoreTextNodes(diffContext);
3886
+ expectNoTextNode(diffContext);
3609
3887
  expectComponent(diffContext, type);
3610
3888
  }
3611
3889
  }
@@ -3790,11 +4068,10 @@ function descendContentToProject(diffContext, children, host) {
3790
4068
  const props = host.props;
3791
4069
  if (props) {
3792
4070
  // we need to create empty projections for all the slots to remove unused slots content
3793
- for (const prop of Object.keys(props)) {
4071
+ for (const prop in props) {
3794
4072
  if (isSlotProp(prop)) {
3795
4073
  const slotName = prop;
3796
- projections.push(slotName);
3797
- projections.push(createProjectionJSXNode(slotName));
4074
+ mapArray_set(projections, slotName, createProjectionJSXNode(slotName), 0);
3798
4075
  }
3799
4076
  }
3800
4077
  }
@@ -3976,9 +4253,8 @@ function expectNoMore(diffContext) {
3976
4253
  }
3977
4254
  }
3978
4255
  }
3979
- function expectNoMoreTextNodes(diffContext) {
3980
- while (diffContext.vCurrent !== null && vnode_isTextVNode(diffContext.vCurrent)) {
3981
- cleanup(diffContext.container, diffContext.journal, diffContext.vCurrent, diffContext.cursor);
4256
+ function expectNoTextNode(diffContext) {
4257
+ if (diffContext.vCurrent !== null && vnode_isTextVNode(diffContext.vCurrent)) {
3982
4258
  const toRemove = diffContext.vCurrent;
3983
4259
  diffContext.vCurrent = peekNextSibling(diffContext.vCurrent);
3984
4260
  vnode_remove(diffContext.journal, diffContext.vParent, toRemove, true);
@@ -4077,7 +4353,9 @@ function registerEventHandlers(key, value, element, vnode, diffContext) {
4077
4353
  handlers.push(runEventHandlerQRL.bind(null, item));
4078
4354
  }
4079
4355
  }
4080
- (element._qDispatch ||= {})[scopedKebabName] = handlers;
4356
+ if (handlers.length > 0) {
4357
+ (element._qDispatch ||= {})[scopedKebabName] = handlers;
4358
+ }
4081
4359
  }
4082
4360
  else if (value) {
4083
4361
  (element._qDispatch ||= {})[scopedKebabName] = [
@@ -4491,7 +4769,7 @@ function expectComponent(diffContext, component) {
4491
4769
  (vnode_isVirtualVNode(componentHost)
4492
4770
  ? vnode_getProp(componentHost, OnRenderProp, null) === null
4493
4771
  : true)) {
4494
- componentHost = componentHost.parent;
4772
+ componentHost = componentHost.parent || vnode_getProjectionParentComponent(componentHost);
4495
4773
  }
4496
4774
  const jsxOutput = executeComponent(diffContext.container, host, (componentHost || diffContext.container.rootVNode), component, jsxNode.props);
4497
4775
  diffContext.asyncQueue.push(jsxOutput, host);
@@ -5402,6 +5680,13 @@ function walkCursor(cursor, options) {
5402
5680
  if (currentVNode.dirty & 64 /* ChoreBits.CLEANUP */) {
5403
5681
  executeCleanup(currentVNode, container);
5404
5682
  }
5683
+ else if (currentVNode.dirty & 32 /* ChoreBits.CHILDREN */) {
5684
+ const next = tryDescendDirtyChildren(container, cursorData, currentVNode, cursor);
5685
+ if (next !== null) {
5686
+ currentVNode = next;
5687
+ continue;
5688
+ }
5689
+ }
5405
5690
  // Clear dirty bits and move to next node
5406
5691
  currentVNode.dirty &= -128 /* ChoreBits.DIRTY_MASK */;
5407
5692
  setCursorPosition(container, cursorData, getNextVNode(currentVNode, cursor));
@@ -5426,17 +5711,9 @@ function walkCursor(cursor, options) {
5426
5711
  result = executeCompute(currentVNode, container);
5427
5712
  }
5428
5713
  else if (currentVNode.dirty & 32 /* ChoreBits.CHILDREN */) {
5429
- const dirtyChildren = currentVNode.dirtyChildren;
5430
- if (!dirtyChildren || dirtyChildren.length === 0) {
5431
- // No dirty children
5432
- currentVNode.dirty &= ~32 /* ChoreBits.CHILDREN */;
5433
- }
5434
- else {
5435
- partitionDirtyChildren(dirtyChildren, currentVNode);
5436
- currentVNode.nextDirtyChildIndex = 0;
5437
- // descend
5438
- currentVNode = getNextVNode(dirtyChildren[0], cursor);
5439
- setCursorPosition(container, cursorData, currentVNode);
5714
+ const next = tryDescendDirtyChildren(container, cursorData, currentVNode, cursor);
5715
+ if (next !== null) {
5716
+ currentVNode = next;
5440
5717
  continue;
5441
5718
  }
5442
5719
  }
@@ -5493,6 +5770,22 @@ function finishWalk(container, cursor, cursorData, isServer) {
5493
5770
  function resolveCursor(container) {
5494
5771
  container.$checkPendingCount$();
5495
5772
  }
5773
+ /**
5774
+ * If the vNode has dirty children, partitions them, sets cursor to first dirty child, and returns
5775
+ * that child. Otherwise clears CHILDREN bit and returns null.
5776
+ */
5777
+ function tryDescendDirtyChildren(container, cursorData, currentVNode, cursor) {
5778
+ const dirtyChildren = currentVNode.dirtyChildren;
5779
+ if (!dirtyChildren || dirtyChildren.length === 0) {
5780
+ currentVNode.dirty &= -33 /* ChoreBits.CHILDREN */;
5781
+ return null;
5782
+ }
5783
+ partitionDirtyChildren(dirtyChildren, currentVNode);
5784
+ currentVNode.nextDirtyChildIndex = 0;
5785
+ const next = getNextVNode(dirtyChildren[0], cursor);
5786
+ setCursorPosition(container, cursorData, next);
5787
+ return next;
5788
+ }
5496
5789
  /**
5497
5790
  * Partitions dirtyChildren array so non-projections come first, projections last. Uses in-place
5498
5791
  * swapping to avoid allocations.
@@ -7359,6 +7652,15 @@ function materializeFromVNodeData(vParent, vData, element, child) {
7359
7652
  vnode_ensureElementKeyInflated(elementVNode);
7360
7653
  addVNode(elementVNode);
7361
7654
  child = fastNextSibling(child);
7655
+ while (
7656
+ // skip only elements, not text nodes
7657
+ isElement(child) &&
7658
+ shouldSkipElement(child)) {
7659
+ child = fastNextSibling(child);
7660
+ if (!child && value > 0) {
7661
+ throw qError(27 /* QError.materializeVNodeDataError */, [vData, peek(), nextToConsumeIdx]);
7662
+ }
7663
+ }
7362
7664
  }
7363
7665
  // collect the elements;
7364
7666
  }
@@ -8481,18 +8783,26 @@ const _fnSignal = (fn, args, fnStr) => {
8481
8783
  * - Odd values are numbers, strings (JSON stringified with `</` escaping) or arrays (same format).
8482
8784
  * - Therefore root indexes need to be doubled to get the actual index.
8483
8785
  */
8484
- async function serialize(serializationContext) {
8485
- const { $writer$, $isSsrNode$, $isDomRef$, $storeProxyMap$, $addRoot$, $promoteToRoot$, getSeenRef, $markSeen$, } = serializationContext;
8486
- let rootIdx = 0;
8487
- const forwardRefs = [];
8488
- let forwardRefsId = 0;
8489
- const promises = new Set();
8490
- const s11nWeakRefs = new Map();
8491
- let parent;
8492
- const qrlMap = new Map();
8786
+ class Serializer {
8787
+ $serializationContext$;
8788
+ rootIdx = 0;
8789
+ forwardRefs = [];
8790
+ forwardRefsId = 0;
8791
+ promises = new Set();
8792
+ s11nWeakRefs = new Map();
8793
+ parent;
8794
+ qrlMap = new Map();
8795
+ $writer$;
8796
+ constructor($serializationContext$) {
8797
+ this.$serializationContext$ = $serializationContext$;
8798
+ this.$writer$ = $serializationContext$.$writer$;
8799
+ }
8800
+ async serialize() {
8801
+ await this.outputRoots();
8802
+ }
8493
8803
  /** Helper to output an array */
8494
- const outputArray = (value, keepUndefined, writeFn) => {
8495
- $writer$.write('[');
8804
+ outputArray(value, keepUndefined, writeFn) {
8805
+ this.$writer$.write(BRACKET_OPEN);
8496
8806
  let separator = false;
8497
8807
  let length;
8498
8808
  if (keepUndefined) {
@@ -8507,41 +8817,52 @@ async function serialize(serializationContext) {
8507
8817
  }
8508
8818
  for (let i = 0; i < length; i++) {
8509
8819
  if (separator) {
8510
- $writer$.write(',');
8820
+ this.$writer$.write(COMMA);
8511
8821
  }
8512
8822
  else {
8513
8823
  separator = true;
8514
8824
  }
8515
8825
  writeFn(value[i], i);
8516
8826
  }
8517
- $writer$.write(']');
8518
- };
8827
+ this.$writer$.write(BRACKET_CLOSE);
8828
+ }
8829
+ /** Whether a string needs JSON escaping (quote, backslash, or control chars). */
8830
+ stringNeedsJsonEscape$(str) {
8831
+ for (let i = 0; i < str.length; i++) {
8832
+ const c = str.charCodeAt(i);
8833
+ if (c < 32 || c === 34 || c === 92) {
8834
+ return true;
8835
+ }
8836
+ }
8837
+ return false;
8838
+ }
8519
8839
  /** Output a type,value pair. If the value is an array, it calls writeValue on each item. */
8520
- const output = (type, value, keepUndefined) => {
8521
- $writer$.write(`${type},`);
8840
+ output(type, value, keepUndefined) {
8522
8841
  if (typeof value === 'number') {
8523
- $writer$.write(value.toString());
8842
+ this.$writer$.write(type + COMMA + value);
8524
8843
  }
8525
8844
  else if (typeof value === 'string') {
8526
- const s = JSON.stringify(value);
8845
+ const s = this.stringNeedsJsonEscape$(value) ? JSON.stringify(value) : QUOTE + value + QUOTE;
8846
+ this.$writer$.write(type + COMMA);
8527
8847
  let angleBracketIdx = -1;
8528
8848
  let lastIdx = 0;
8529
- while ((angleBracketIdx = s.indexOf('</', lastIdx)) !== -1) {
8530
- $writer$.write(s.slice(lastIdx, angleBracketIdx));
8531
- $writer$.write('<\\/');
8849
+ while ((angleBracketIdx = s.indexOf(CLOSE_TAG, lastIdx)) !== -1) {
8850
+ this.$writer$.write(s.slice(lastIdx, angleBracketIdx));
8851
+ this.$writer$.write(ESCAPED_CLOSE_TAG);
8532
8852
  lastIdx = angleBracketIdx + 2;
8533
8853
  }
8534
- $writer$.write(lastIdx === 0 ? s : s.slice(lastIdx));
8854
+ this.$writer$.write(lastIdx === 0 ? s : s.slice(lastIdx));
8535
8855
  }
8536
8856
  else {
8537
- outputArray(value, !!keepUndefined, (valueItem, idx) => {
8538
- writeValue(valueItem, idx);
8857
+ this.$writer$.write(type + COMMA);
8858
+ this.outputArray(value, !!keepUndefined, (valueItem, idx) => {
8859
+ this.writeValue(valueItem, idx);
8539
8860
  });
8540
8861
  }
8541
- };
8542
- const getSeenRefOrOutput = (value, index, keepWeak) => {
8543
- let seen = getSeenRef(value);
8544
- const forwardRefIdx = !keepWeak && s11nWeakRefs.get(value);
8862
+ }
8863
+ getSeenRefOrOutput(value, index, keepWeak) {
8864
+ let seen = this.$serializationContext$.getSeenRef(value);
8865
+ const forwardRefIdx = !keepWeak && this.s11nWeakRefs.get(value);
8545
8866
  if (!seen) {
8546
8867
  if (keepWeak) {
8547
8868
  // we're testing a weakref, so don't mark it as seen yet
@@ -8550,136 +8871,136 @@ async function serialize(serializationContext) {
8550
8871
  // Maybe it's a weakref and that should count as seen
8551
8872
  if (typeof forwardRefIdx === 'number') {
8552
8873
  // Yes, no longer a weakref
8553
- seen = $addRoot$(value, true);
8874
+ seen = this.$serializationContext$.$addRoot$(value, true);
8554
8875
  }
8555
8876
  else {
8556
- return $markSeen$(value, parent, index);
8877
+ return this.$serializationContext$.$markSeen$(value, this.parent, index);
8557
8878
  }
8558
8879
  }
8559
8880
  // Now that we saw it a second time, make sure it's a root
8560
8881
  if (seen.$parent$) {
8561
8882
  // Note, this means it was output before so we always need a backref
8562
8883
  // Special case: we're a root so instead of adding a backref, we replace ourself
8563
- if (!parent) {
8564
- $promoteToRoot$(seen, index);
8565
- value = serializationContext.$roots$[index];
8884
+ if (!this.parent) {
8885
+ this.$serializationContext$.$promoteToRoot$(seen, index);
8886
+ value = this.$serializationContext$.$roots$[index];
8566
8887
  }
8567
8888
  else {
8568
- $promoteToRoot$(seen);
8889
+ this.$serializationContext$.$promoteToRoot$(seen);
8569
8890
  }
8570
8891
  }
8571
8892
  // Check if there was a weakref to us
8572
8893
  if (typeof forwardRefIdx === 'number') {
8573
- forwardRefs[forwardRefIdx] = seen.$index$;
8574
- s11nWeakRefs.delete(value);
8894
+ this.forwardRefs[forwardRefIdx] = seen.$index$;
8895
+ this.s11nWeakRefs.delete(value);
8575
8896
  }
8576
8897
  // Now we know it's a root and we should output a RootRef
8577
8898
  const rootIdx = value instanceof SerializationBackRef ? value.$path$ : seen.$index$;
8578
8899
  // But make sure we do output ourselves
8579
- if (!parent && rootIdx === index) {
8900
+ if (!this.parent && rootIdx === index) {
8580
8901
  return seen;
8581
8902
  }
8582
- output(1 /* TypeIds.RootRef */, rootIdx);
8583
- };
8903
+ this.output(1 /* TypeIds.RootRef */, rootIdx);
8904
+ }
8584
8905
  // First check for scalars, then do objects with seen checks
8585
8906
  // Make sure to only get the SeenRef once, it's expensive
8586
- const writeValue = (value, index) => {
8907
+ writeValue(value, index) {
8587
8908
  if (fastSkipSerialize(value)) {
8588
- output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
8909
+ this.output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
8589
8910
  }
8590
8911
  else {
8591
8912
  switch (typeof value) {
8592
8913
  case 'undefined':
8593
- output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
8914
+ this.output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
8594
8915
  break;
8595
8916
  case 'boolean':
8596
- output(3 /* TypeIds.Constant */, value ? 2 /* Constants.True */ : 3 /* Constants.False */);
8917
+ this.output(3 /* TypeIds.Constant */, value ? 2 /* Constants.True */ : 3 /* Constants.False */);
8597
8918
  break;
8598
8919
  case 'number':
8599
8920
  if (Number.isNaN(value)) {
8600
- output(3 /* TypeIds.Constant */, 12 /* Constants.NaN */);
8921
+ this.output(3 /* TypeIds.Constant */, 12 /* Constants.NaN */);
8601
8922
  }
8602
8923
  else if (!Number.isFinite(value)) {
8603
- output(3 /* TypeIds.Constant */, value < 0 ? 14 /* Constants.NegativeInfinity */ : 13 /* Constants.PositiveInfinity */);
8924
+ this.output(3 /* TypeIds.Constant */, value < 0 ? 14 /* Constants.NegativeInfinity */ : 13 /* Constants.PositiveInfinity */);
8604
8925
  }
8605
8926
  else if (value === Number.MAX_SAFE_INTEGER) {
8606
- output(3 /* TypeIds.Constant */, 15 /* Constants.MaxSafeInt */);
8927
+ this.output(3 /* TypeIds.Constant */, 15 /* Constants.MaxSafeInt */);
8607
8928
  }
8608
8929
  else if (value === Number.MAX_SAFE_INTEGER - 1) {
8609
- output(3 /* TypeIds.Constant */, 16 /* Constants.AlmostMaxSafeInt */);
8930
+ this.output(3 /* TypeIds.Constant */, 16 /* Constants.AlmostMaxSafeInt */);
8610
8931
  }
8611
8932
  else if (value === Number.MIN_SAFE_INTEGER) {
8612
- output(3 /* TypeIds.Constant */, 17 /* Constants.MinSafeInt */);
8933
+ this.output(3 /* TypeIds.Constant */, 17 /* Constants.MinSafeInt */);
8613
8934
  }
8614
8935
  else {
8615
- output(0 /* TypeIds.Plain */, value);
8936
+ this.output(0 /* TypeIds.Plain */, value);
8616
8937
  }
8617
8938
  break;
8618
8939
  case 'string':
8619
8940
  if (value.length === 0) {
8620
- output(3 /* TypeIds.Constant */, 4 /* Constants.EmptyString */);
8941
+ this.output(3 /* TypeIds.Constant */, 4 /* Constants.EmptyString */);
8621
8942
  }
8622
8943
  else {
8623
8944
  // If the string is short, we output directly
8624
8945
  // Very short strings add overhead to tracking
8625
- if (value.length < 4 || getSeenRefOrOutput(value, index)) {
8626
- output(0 /* TypeIds.Plain */, value);
8946
+ if (value.length < 4 || this.getSeenRefOrOutput(value, index)) {
8947
+ this.output(0 /* TypeIds.Plain */, value);
8627
8948
  }
8628
8949
  }
8629
8950
  break;
8630
8951
  case 'bigint':
8631
- if ((value < 10000 && value > -1e3) || getSeenRefOrOutput(value, index)) {
8632
- output(12 /* TypeIds.BigInt */, value.toString());
8952
+ if ((value < 10000 && value > -1e3) || this.getSeenRefOrOutput(value, index)) {
8953
+ this.output(12 /* TypeIds.BigInt */, value.toString());
8633
8954
  }
8634
8955
  break;
8635
8956
  case 'symbol':
8636
8957
  if (value === NEEDS_COMPUTATION) {
8637
- output(3 /* TypeIds.Constant */, 7 /* Constants.NEEDS_COMPUTATION */);
8958
+ this.output(3 /* TypeIds.Constant */, 7 /* Constants.NEEDS_COMPUTATION */);
8638
8959
  }
8639
8960
  else if (value === STORE_ALL_PROPS) {
8640
- output(3 /* TypeIds.Constant */, 8 /* Constants.STORE_ALL_PROPS */);
8961
+ this.output(3 /* TypeIds.Constant */, 8 /* Constants.STORE_ALL_PROPS */);
8641
8962
  }
8642
8963
  else if (value === _UNINITIALIZED) {
8643
- output(3 /* TypeIds.Constant */, 9 /* Constants.UNINITIALIZED */);
8964
+ this.output(3 /* TypeIds.Constant */, 9 /* Constants.UNINITIALIZED */);
8644
8965
  }
8645
8966
  break;
8646
8967
  case 'function':
8647
8968
  if (value === Slot) {
8648
- output(3 /* TypeIds.Constant */, 10 /* Constants.Slot */);
8969
+ this.output(3 /* TypeIds.Constant */, 10 /* Constants.Slot */);
8649
8970
  }
8650
8971
  else if (value === Fragment) {
8651
- output(3 /* TypeIds.Constant */, 11 /* Constants.Fragment */);
8972
+ this.output(3 /* TypeIds.Constant */, 11 /* Constants.Fragment */);
8652
8973
  }
8653
8974
  else if (isQrl(value)) {
8654
- if (getSeenRefOrOutput(value, index)) {
8655
- const [chunk, symbol, captures] = qrlToString(serializationContext, value, true);
8975
+ if (this.getSeenRefOrOutput(value, index)) {
8976
+ const [chunk, symbol, captures] = qrlToString(this.$serializationContext$, value, true);
8656
8977
  let data;
8657
8978
  if (chunk !== '') {
8658
8979
  // not a sync QRL, replace all parts with string references
8659
- data = `${$addRoot$(chunk)}#${$addRoot$(symbol)}${captures ? '#' + captures : ''}`;
8980
+ data = `${this.$serializationContext$.$addRoot$(chunk)}#${this.$serializationContext$.$addRoot$(symbol)}${captures ? '#' + captures : ''}`;
8660
8981
  // Since we map QRLs to strings, we need to keep track of this secondary mapping
8661
- const existing = qrlMap.get(data);
8982
+ const existing = this.qrlMap.get(data);
8662
8983
  if (existing) {
8663
8984
  // We encountered the same QRL again, make it a root
8664
- const ref = $addRoot$(existing);
8665
- output(1 /* TypeIds.RootRef */, ref);
8985
+ const ref = this.$serializationContext$.$addRoot$(existing);
8986
+ this.output(1 /* TypeIds.RootRef */, ref);
8666
8987
  return;
8667
8988
  }
8668
8989
  else {
8669
- qrlMap.set(data, value);
8990
+ this.qrlMap.set(data, value);
8670
8991
  }
8671
8992
  }
8672
8993
  else {
8673
8994
  // sync QRL
8674
8995
  data = Number(symbol);
8675
8996
  }
8676
- output(9 /* TypeIds.QRL */, data);
8997
+ this.output(9 /* TypeIds.QRL */, data);
8677
8998
  }
8678
8999
  }
8679
9000
  else if (isQwikComponent(value)) {
8680
9001
  const [qrl] = value[SERIALIZABLE_STATE];
8681
- serializationContext.$renderSymbols$.add(qrl.$symbol$);
8682
- output(21 /* TypeIds.Component */, [qrl]);
9002
+ this.$serializationContext$.$renderSymbols$.add(qrl.$symbol$);
9003
+ this.output(21 /* TypeIds.Component */, [qrl]);
8683
9004
  }
8684
9005
  else {
8685
9006
  throw qError(34 /* QError.serializeErrorCannotSerializeFunction */, [value.toString()]);
@@ -8687,25 +9008,25 @@ async function serialize(serializationContext) {
8687
9008
  break;
8688
9009
  case 'object':
8689
9010
  if (value === EMPTY_ARRAY) {
8690
- output(3 /* TypeIds.Constant */, 5 /* Constants.EMPTY_ARRAY */);
9011
+ this.output(3 /* TypeIds.Constant */, 5 /* Constants.EMPTY_ARRAY */);
8691
9012
  }
8692
9013
  else if (value === EMPTY_OBJ) {
8693
- output(3 /* TypeIds.Constant */, 6 /* Constants.EMPTY_OBJ */);
9014
+ this.output(3 /* TypeIds.Constant */, 6 /* Constants.EMPTY_OBJ */);
8694
9015
  }
8695
9016
  else if (value === null) {
8696
- output(3 /* TypeIds.Constant */, 1 /* Constants.Null */);
9017
+ this.output(3 /* TypeIds.Constant */, 1 /* Constants.Null */);
8697
9018
  }
8698
9019
  else if (value instanceof SerializationBackRef) {
8699
- output(1 /* TypeIds.RootRef */, value.$path$);
9020
+ this.output(1 /* TypeIds.RootRef */, value.$path$);
8700
9021
  }
8701
9022
  else {
8702
- const newSeenRef = getSeenRefOrOutput(value, index);
9023
+ const newSeenRef = this.getSeenRefOrOutput(value, index);
8703
9024
  if (newSeenRef) {
8704
- const oldParent = parent;
8705
- parent = newSeenRef;
9025
+ const oldParent = this.parent;
9026
+ this.parent = newSeenRef;
8706
9027
  // separate function for readability
8707
- writeObjectValue(value);
8708
- parent = oldParent;
9028
+ this.writeObjectValue(value);
9029
+ this.parent = oldParent;
8709
9030
  }
8710
9031
  }
8711
9032
  break;
@@ -8713,11 +9034,11 @@ async function serialize(serializationContext) {
8713
9034
  throw qError(20 /* QError.serializeErrorUnknownType */, [typeof value]);
8714
9035
  }
8715
9036
  }
8716
- };
8717
- const writeObjectValue = (value) => {
9037
+ }
9038
+ writeObjectValue(value) {
8718
9039
  if (isPropsProxy(value)) {
8719
9040
  const owner = value[_OWNER];
8720
- output(30 /* TypeIds.PropsProxy */, [
9041
+ this.output(30 /* TypeIds.PropsProxy */, [
8721
9042
  _serializationWeakRef(owner),
8722
9043
  owner.varProps,
8723
9044
  owner.constProps,
@@ -8725,15 +9046,13 @@ async function serialize(serializationContext) {
8725
9046
  ]);
8726
9047
  }
8727
9048
  else if (value instanceof SubscriptionData) {
8728
- output(31 /* TypeIds.SubscriptionData */, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
9049
+ this.output(31 /* TypeIds.SubscriptionData */, [
9050
+ value.data.$scopedStyleIdPrefix$,
9051
+ value.data.$isConst$,
9052
+ ]);
8729
9053
  }
8730
9054
  else if (value instanceof EffectSubscription) {
8731
- output(32 /* TypeIds.EffectSubscription */, [
8732
- value.consumer,
8733
- value.property,
8734
- value.backRef,
8735
- value.data,
8736
- ]);
9055
+ this.output(32 /* TypeIds.EffectSubscription */, [value.consumer, value.property, value.data]);
8737
9056
  }
8738
9057
  else if (isStore(value)) {
8739
9058
  const storeHandler = getStoreHandler(value);
@@ -8744,7 +9063,7 @@ async function serialize(serializationContext) {
8744
9063
  const innerStores = [];
8745
9064
  for (const prop in storeTarget) {
8746
9065
  const propValue = storeTarget[prop];
8747
- const innerStore = $storeProxyMap$.get(propValue);
9066
+ const innerStore = this.$serializationContext$.$storeProxyMap$.get(propValue);
8748
9067
  if (innerStore) {
8749
9068
  innerStores.push(innerStore);
8750
9069
  }
@@ -8753,26 +9072,26 @@ async function serialize(serializationContext) {
8753
9072
  while (out[out.length - 1] === undefined) {
8754
9073
  out.pop();
8755
9074
  }
8756
- output(27 /* TypeIds.Store */, out);
9075
+ this.output(27 /* TypeIds.Store */, out);
8757
9076
  }
8758
9077
  else if (isSerializerObj(value)) {
8759
9078
  const result = value[SerializerSymbol](value);
8760
9079
  if (isPromise(result)) {
8761
- const forwardRef = resolvePromise(result, $addRoot$, (resolved, resolvedValue) => {
9080
+ const forwardRef = this.resolvePromise(result, (resolved, resolvedValue) => {
8762
9081
  return new PromiseResult(26 /* TypeIds.SerializerSignal */, resolved, resolvedValue, undefined, undefined);
8763
9082
  });
8764
- output(2 /* TypeIds.ForwardRef */, forwardRef);
9083
+ this.output(2 /* TypeIds.ForwardRef */, forwardRef);
8765
9084
  }
8766
9085
  else {
8767
9086
  // We replace ourselves with this value
8768
- const index = parent.$index$;
8769
- parent = parent.$parent$;
8770
- writeValue(result, index);
9087
+ const index = this.parent.$index$;
9088
+ this.parent = this.parent.$parent$;
9089
+ this.writeValue(result, index);
8771
9090
  }
8772
9091
  }
8773
9092
  else if (isObjectLiteral(value)) {
8774
9093
  if (Array.isArray(value)) {
8775
- output(4 /* TypeIds.Array */, value);
9094
+ this.output(4 /* TypeIds.Array */, value);
8776
9095
  }
8777
9096
  else {
8778
9097
  const out = [];
@@ -8784,36 +9103,30 @@ async function serialize(serializationContext) {
8784
9103
  }
8785
9104
  }
8786
9105
  }
8787
- output(5 /* TypeIds.Object */, out.length ? out : 0);
9106
+ this.output(5 /* TypeIds.Object */, out.length ? out : 0);
8788
9107
  }
8789
9108
  }
8790
- else if ($isDomRef$(value)) {
9109
+ else if (this.$serializationContext$.$isDomRef$(value)) {
8791
9110
  value.$ssrNode$.vnodeData[0] |= 16 /* VNodeDataFlag.SERIALIZE */;
8792
- output(11 /* TypeIds.RefVNode */, value.$ssrNode$.id);
9111
+ this.output(11 /* TypeIds.RefVNode */, value.$ssrNode$.id);
8793
9112
  }
8794
9113
  else if (value instanceof SignalImpl) {
8795
9114
  if (value instanceof SerializerSignalImpl) {
8796
9115
  const maybeValue = getCustomSerializerPromise(value, value.$untrackedValue$);
8797
9116
  if (isPromise(maybeValue)) {
8798
- const forwardRefId = resolvePromise(maybeValue, $addRoot$, (resolved, resolvedValue) => {
9117
+ const forwardRefId = this.resolvePromise(maybeValue, (resolved, resolvedValue) => {
8799
9118
  return new PromiseResult(26 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
8800
9119
  });
8801
- output(2 /* TypeIds.ForwardRef */, forwardRefId);
9120
+ this.output(2 /* TypeIds.ForwardRef */, forwardRefId);
8802
9121
  }
8803
9122
  else {
8804
- output(26 /* TypeIds.SerializerSignal */, [
8805
- value.$computeQrl$,
8806
- filterEffectBackRefs(value[_EFFECT_BACK_REF]),
8807
- value.$effects$,
8808
- maybeValue,
8809
- ]);
9123
+ this.output(26 /* TypeIds.SerializerSignal */, [value.$computeQrl$, value.$effects$, maybeValue]);
8810
9124
  }
8811
9125
  return;
8812
9126
  }
8813
9127
  if (value instanceof WrappedSignalImpl) {
8814
- output(23 /* TypeIds.WrappedSignal */, [
8815
- ...serializeWrappingFn(serializationContext, value),
8816
- filterEffectBackRefs(value[_EFFECT_BACK_REF]),
9128
+ this.output(23 /* TypeIds.WrappedSignal */, [
9129
+ ...serializeWrappingFn(this.$serializationContext$, value),
8817
9130
  value.$flags$,
8818
9131
  value.$hostElement$,
8819
9132
  ...(value.$effects$ || []),
@@ -8829,7 +9142,9 @@ async function serialize(serializationContext) {
8829
9142
  const interval = isAsync && value.$interval$ > 0 ? value.$interval$ : undefined;
8830
9143
  const concurrency = isAsync && value.$concurrency$ !== 1 ? value.$concurrency$ : undefined;
8831
9144
  const timeout = isAsync && value.$timeoutMs$ !== 0 ? value.$timeoutMs$ : undefined;
8832
- const eagerCleanup = isAsync && value.$flags$ & 32 /* AsyncSignalFlags.EAGER_CLEANUP */ ? true : undefined;
9145
+ // Send the flags but remove the serialization bits and default to 0 when undefined
9146
+ const asyncFlags = (isAsync && value.$flags$ & -25 /* SerializationSignalFlags.SERIALIZATION_ALL_STRATEGIES */) ||
9147
+ undefined;
8833
9148
  if (isInvalid || isSkippable) {
8834
9149
  v = NEEDS_COMPUTATION;
8835
9150
  }
@@ -8839,14 +9154,11 @@ async function serialize(serializationContext) {
8839
9154
  else if (shouldNeverSerialize) {
8840
9155
  v = NEEDS_COMPUTATION;
8841
9156
  }
8842
- const out = [
8843
- value.$computeQrl$,
8844
- filterEffectBackRefs(value[_EFFECT_BACK_REF]),
8845
- value.$effects$,
8846
- ];
9157
+ const out = [value.$computeQrl$, value.$effects$];
8847
9158
  if (isAsync) {
8848
9159
  // After SSR, the signal is never loading, so no need to send it
8849
9160
  out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedError$);
9161
+ out.push(asyncFlags || undefined);
8850
9162
  }
8851
9163
  let keepUndefined = false;
8852
9164
  if (v !== NEEDS_COMPUTATION ||
@@ -8867,9 +9179,8 @@ async function serialize(serializationContext) {
8867
9179
  out.push(interval);
8868
9180
  out.push(concurrency);
8869
9181
  out.push(timeout);
8870
- out.push(eagerCleanup);
8871
9182
  }
8872
- output(isAsync ? 25 /* TypeIds.AsyncSignal */ : 24 /* TypeIds.ComputedSignal */, out, keepUndefined);
9183
+ this.output(isAsync ? 25 /* TypeIds.AsyncSignal */ : 24 /* TypeIds.ComputedSignal */, out, keepUndefined);
8873
9184
  }
8874
9185
  else {
8875
9186
  const v = value.$untrackedValue$;
@@ -8878,17 +9189,17 @@ async function serialize(serializationContext) {
8878
9189
  if (value.$effects$) {
8879
9190
  out.push(...value.$effects$);
8880
9191
  }
8881
- output(22 /* TypeIds.Signal */, out, keepUndefined);
9192
+ this.output(22 /* TypeIds.Signal */, out, keepUndefined);
8882
9193
  }
8883
9194
  }
8884
9195
  else if (value instanceof URL) {
8885
- output(6 /* TypeIds.URL */, value.href);
9196
+ this.output(6 /* TypeIds.URL */, value.href);
8886
9197
  }
8887
9198
  else if (value instanceof Date) {
8888
- output(7 /* TypeIds.Date */, Number.isNaN(value.valueOf()) ? '' : value.valueOf());
9199
+ this.output(7 /* TypeIds.Date */, Number.isNaN(value.valueOf()) ? '' : value.valueOf());
8889
9200
  }
8890
9201
  else if (value instanceof RegExp) {
8891
- output(8 /* TypeIds.Regex */, value.toString());
9202
+ this.output(8 /* TypeIds.Regex */, value.toString());
8892
9203
  }
8893
9204
  else if (value instanceof Error) {
8894
9205
  const out = [value.message];
@@ -8898,29 +9209,32 @@ async function serialize(serializationContext) {
8898
9209
  if (isDev) {
8899
9210
  out.push('stack', value.stack);
8900
9211
  }
8901
- output(15 /* TypeIds.Error */, out);
9212
+ this.output(15 /* TypeIds.Error */, out);
8902
9213
  }
8903
- else if ($isSsrNode$(value)) {
8904
- const rootIndex = $addRoot$(value);
8905
- serializationContext.$setProp$(value, ELEMENT_ID, String(rootIndex));
9214
+ else if (this.$serializationContext$.$isSsrNode$(value)) {
9215
+ const rootIndex = this.$serializationContext$.$addRoot$(value);
9216
+ this.$serializationContext$.$setProp$(value, ELEMENT_ID, String(rootIndex));
8906
9217
  // we need to output before the vnode overwrites its values
8907
- output(10 /* TypeIds.VNode */, value.id);
9218
+ this.output(10 /* TypeIds.VNode */, value.id);
8908
9219
  const vNodeData = value.vnodeData;
8909
9220
  if (vNodeData) {
8910
- discoverValuesForVNodeData(vNodeData, (vNodeDataValue) => $addRoot$(vNodeDataValue));
9221
+ discoverValuesForVNodeData(vNodeData, (vNodeDataValue) => this.$serializationContext$.$addRoot$(vNodeDataValue));
8911
9222
  vNodeData[0] |= 16 /* VNodeDataFlag.SERIALIZE */;
8912
9223
  }
8913
9224
  if (value.children) {
8914
9225
  // can be static, but we need to save vnode data structure + discover the back refs
8915
- for (const child of value.children) {
9226
+ const childrenLength = value.children.length;
9227
+ for (let i = 0; i < childrenLength; i++) {
9228
+ const child = value.children[i];
8916
9229
  const childVNodeData = child.vnodeData;
8917
9230
  if (childVNodeData) {
8918
9231
  // add all back refs to the roots
8919
- for (const value of childVNodeData) {
9232
+ for (let i = 0; i < childVNodeData.length; i++) {
9233
+ const value = childVNodeData[i];
8920
9234
  if (isSsrAttrs(value)) {
8921
- const backRefKeyIndex = value.findIndex((v) => v === QBackRefs);
8922
- if (backRefKeyIndex !== -1) {
8923
- $addRoot$(value[backRefKeyIndex + 1]);
9235
+ const backRefs = tryGetBackRefs(value);
9236
+ if (backRefs) {
9237
+ this.$serializationContext$.$addRoot$(backRefs);
8924
9238
  }
8925
9239
  }
8926
9240
  }
@@ -8932,28 +9246,25 @@ async function serialize(serializationContext) {
8932
9246
  else if (typeof FormData !== 'undefined' && value instanceof FormData) {
8933
9247
  // FormData is generally used only once so don't bother with references
8934
9248
  const array = [];
8935
- value.forEach((value, key) => {
8936
- if (typeof value === 'string') {
8937
- array.push(key, value);
8938
- }
8939
- else {
8940
- array.push(key, value.name);
9249
+ for (const [k, v] of value.entries()) {
9250
+ if (typeof v === 'string') {
9251
+ array.push(k, v);
8941
9252
  }
8942
- });
8943
- output(28 /* TypeIds.FormData */, array);
9253
+ }
9254
+ this.output(28 /* TypeIds.FormData */, array);
8944
9255
  }
8945
9256
  else if (value instanceof URLSearchParams) {
8946
- output(13 /* TypeIds.URLSearchParams */, value.toString());
9257
+ this.output(13 /* TypeIds.URLSearchParams */, value.toString());
8947
9258
  }
8948
9259
  else if (value instanceof Set) {
8949
- output(17 /* TypeIds.Set */, [...value.values()]);
9260
+ this.output(17 /* TypeIds.Set */, [...value.values()]);
8950
9261
  }
8951
9262
  else if (value instanceof Map) {
8952
9263
  const combined = [];
8953
9264
  for (const [k, v] of value.entries()) {
8954
9265
  combined.push(k, v);
8955
9266
  }
8956
- output(18 /* TypeIds.Map */, combined);
9267
+ this.output(18 /* TypeIds.Map */, combined);
8957
9268
  }
8958
9269
  else if (isJSXNode(value)) {
8959
9270
  const out = [
@@ -8967,38 +9278,31 @@ async function serialize(serializationContext) {
8967
9278
  while (out[out.length - 1] === undefined) {
8968
9279
  out.pop();
8969
9280
  }
8970
- output(29 /* TypeIds.JSXNode */, out);
9281
+ this.output(29 /* TypeIds.JSXNode */, out);
8971
9282
  }
8972
9283
  else if (value instanceof Task) {
8973
- const out = [
8974
- value.$qrl$,
8975
- value.$flags$,
8976
- value.$index$,
8977
- value.$el$,
8978
- value[_EFFECT_BACK_REF],
8979
- value.$state$,
8980
- ];
9284
+ const out = [value.$qrl$, value.$flags$, value.$index$, value.$el$, value.$state$];
8981
9285
  while (out[out.length - 1] === undefined) {
8982
9286
  out.pop();
8983
9287
  }
8984
- output(20 /* TypeIds.Task */, out);
9288
+ this.output(20 /* TypeIds.Task */, out);
8985
9289
  }
8986
9290
  else if (isPromise(value)) {
8987
- const forwardRefId = resolvePromise(value, $addRoot$, (resolved, resolvedValue) => {
9291
+ const forwardRefId = this.resolvePromise(value, (resolved, resolvedValue) => {
8988
9292
  return new PromiseResult(16 /* TypeIds.Promise */, resolved, resolvedValue);
8989
9293
  });
8990
- output(2 /* TypeIds.ForwardRef */, forwardRefId);
9294
+ this.output(2 /* TypeIds.ForwardRef */, forwardRefId);
8991
9295
  }
8992
9296
  else if (value instanceof PromiseResult) {
8993
9297
  if (value.$type$ === 26 /* TypeIds.SerializerSignal */) {
8994
9298
  if (value.$qrl$) {
8995
- output(26 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
9299
+ this.output(26 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
8996
9300
  }
8997
9301
  else if (value.$resolved$) {
8998
9302
  // We replace ourselves with this value
8999
- const index = parent.$index$;
9000
- parent = parent.$parent$;
9001
- writeValue(value.$value$, index);
9303
+ const index = this.parent.$index$;
9304
+ this.parent = this.parent.$parent$;
9305
+ this.writeValue(value.$value$, index);
9002
9306
  }
9003
9307
  else {
9004
9308
  console.error(value.$value$);
@@ -9006,95 +9310,97 @@ async function serialize(serializationContext) {
9006
9310
  }
9007
9311
  }
9008
9312
  else {
9009
- output(16 /* TypeIds.Promise */, [value.$resolved$, value.$value$]);
9313
+ this.output(16 /* TypeIds.Promise */, [value.$resolved$, value.$value$]);
9010
9314
  }
9011
9315
  }
9012
9316
  else if (value instanceof Uint8Array) {
9013
9317
  let buf = '';
9014
- for (const c of value) {
9015
- buf += String.fromCharCode(c);
9318
+ const length = value.length;
9319
+ for (let i = 0; i < length; i++) {
9320
+ buf += String.fromCharCode(value[i]);
9016
9321
  }
9017
9322
  const out = btoa(buf).replace(/=+$/, '');
9018
- output(19 /* TypeIds.Uint8Array */, out);
9323
+ this.output(19 /* TypeIds.Uint8Array */, out);
9019
9324
  }
9020
9325
  else if (value instanceof SerializationWeakRef) {
9021
9326
  const obj = value.$obj$;
9022
9327
  // This will return a fake SeenRef if it's not been seen before
9023
- if (getSeenRefOrOutput(obj, parent.$index$, true)) {
9024
- let forwardRefId = s11nWeakRefs.get(obj);
9328
+ if (this.getSeenRefOrOutput(obj, this.parent.$index$, true)) {
9329
+ let forwardRefId = this.s11nWeakRefs.get(obj);
9025
9330
  if (forwardRefId === undefined) {
9026
- forwardRefId = forwardRefsId++;
9027
- s11nWeakRefs.set(obj, forwardRefId);
9028
- forwardRefs[forwardRefId] = -1;
9331
+ forwardRefId = this.forwardRefsId++;
9332
+ this.s11nWeakRefs.set(obj, forwardRefId);
9333
+ this.forwardRefs[forwardRefId] = -1;
9029
9334
  }
9030
- output(2 /* TypeIds.ForwardRef */, forwardRefId);
9335
+ this.output(2 /* TypeIds.ForwardRef */, forwardRefId);
9031
9336
  }
9032
9337
  }
9033
9338
  else if (vnode_isVNode(value)) {
9034
- output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
9339
+ this.output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
9035
9340
  }
9036
9341
  else {
9037
9342
  throw qError(20 /* QError.serializeErrorUnknownType */, [typeof value]);
9038
9343
  }
9039
- };
9040
- function resolvePromise(promise, $addRoot$, classCreator) {
9041
- const forwardRefId = forwardRefsId++;
9344
+ }
9345
+ resolvePromise(promise, classCreator) {
9346
+ const forwardRefId = this.forwardRefsId++;
9042
9347
  promise
9043
9348
  .then((resolvedValue) => {
9044
- promises.delete(promise);
9045
- forwardRefs[forwardRefId] = $addRoot$(classCreator(true, resolvedValue));
9349
+ this.promises.delete(promise);
9350
+ this.forwardRefs[forwardRefId] = this.$serializationContext$.$addRoot$(classCreator(true, resolvedValue));
9046
9351
  })
9047
9352
  .catch((err) => {
9048
- promises.delete(promise);
9049
- forwardRefs[forwardRefId] = $addRoot$(classCreator(false, err));
9353
+ this.promises.delete(promise);
9354
+ this.forwardRefs[forwardRefId] = this.$serializationContext$.$addRoot$(classCreator(false, err));
9050
9355
  });
9051
- promises.add(promise);
9356
+ this.promises.add(promise);
9052
9357
  return forwardRefId;
9053
9358
  }
9054
- const outputRoots = async () => {
9055
- $writer$.write('[');
9056
- const { $roots$ } = serializationContext;
9057
- while (rootIdx < $roots$.length || promises.size) {
9058
- if (rootIdx !== 0) {
9059
- $writer$.write(',');
9359
+ async outputRoots() {
9360
+ this.$writer$.write(BRACKET_OPEN);
9361
+ const { $roots$ } = this.$serializationContext$;
9362
+ while (this.rootIdx < $roots$.length || this.promises.size) {
9363
+ if (this.rootIdx !== 0) {
9364
+ this.$writer$.write(COMMA);
9060
9365
  }
9061
9366
  let separator = false;
9062
- for (; rootIdx < $roots$.length; rootIdx++) {
9367
+ for (; this.rootIdx < $roots$.length; this.rootIdx++) {
9063
9368
  if (separator) {
9064
- $writer$.write(',');
9369
+ this.$writer$.write(COMMA);
9065
9370
  }
9066
9371
  else {
9067
9372
  separator = true;
9068
9373
  }
9069
- writeValue($roots$[rootIdx], rootIdx);
9374
+ this.writeValue($roots$[this.rootIdx], this.rootIdx);
9070
9375
  }
9071
- if (promises.size) {
9376
+ if (this.promises.size) {
9072
9377
  try {
9073
- await Promise.race(promises);
9378
+ await Promise.race(this.promises);
9074
9379
  }
9075
9380
  catch {
9076
9381
  // ignore rejections, they will be serialized as rejected promises
9077
9382
  }
9078
9383
  }
9079
9384
  }
9080
- if (forwardRefs.length) {
9081
- let lastIdx = forwardRefs.length - 1;
9082
- while (lastIdx >= 0 && forwardRefs[lastIdx] === -1) {
9385
+ if (this.forwardRefs.length) {
9386
+ let lastIdx = this.forwardRefs.length - 1;
9387
+ while (lastIdx >= 0 && this.forwardRefs[lastIdx] === -1) {
9083
9388
  lastIdx--;
9084
9389
  }
9085
9390
  if (lastIdx >= 0) {
9086
- $writer$.write(',');
9087
- $writer$.write(14 /* TypeIds.ForwardRefs */ + ',');
9088
- const out = lastIdx === forwardRefs.length - 1 ? forwardRefs : forwardRefs.slice(0, lastIdx + 1);
9391
+ this.$writer$.write(COMMA);
9392
+ this.$writer$.write(14 /* TypeIds.ForwardRefs */ + COMMA);
9393
+ const out = lastIdx === this.forwardRefs.length - 1
9394
+ ? this.forwardRefs
9395
+ : this.forwardRefs.slice(0, lastIdx + 1);
9089
9396
  // We could also implement RLE of -1 values
9090
- outputArray(out, true, (value) => {
9091
- $writer$.write(String(value));
9397
+ this.outputArray(out, true, (value) => {
9398
+ this.$writer$.write(String(value));
9092
9399
  });
9093
9400
  }
9094
9401
  }
9095
- $writer$.write(']');
9096
- };
9097
- await outputRoots();
9402
+ this.$writer$.write(BRACKET_CLOSE);
9403
+ }
9098
9404
  }
9099
9405
  class PromiseResult {
9100
9406
  $type$;
@@ -9132,16 +9438,15 @@ function getCustomSerializerPromise(signal, value) {
9132
9438
  });
9133
9439
  }
9134
9440
  const discoverValuesForVNodeData = (vnodeData, callback) => {
9135
- for (const value of vnodeData) {
9441
+ const length = vnodeData.length;
9442
+ for (let i = 0; i < length; i++) {
9443
+ const value = vnodeData[i];
9136
9444
  if (isSsrAttrs(value)) {
9137
- for (let i = 1; i < value.length; i += 2) {
9138
- const keyValue = value[i - 1];
9139
- const attrValue = value[i];
9445
+ for (const key in value) {
9446
+ const attrValue = value[key];
9140
9447
  if (attrValue == null ||
9141
9448
  typeof attrValue === 'string' ||
9142
- // skip empty props
9143
- (keyValue === ELEMENT_PROPS &&
9144
- Object.keys(attrValue).length === 0)) {
9449
+ (key === ELEMENT_PROPS && isObjectEmpty(attrValue))) {
9145
9450
  continue;
9146
9451
  }
9147
9452
  callback(attrValue);
@@ -9149,7 +9454,7 @@ const discoverValuesForVNodeData = (vnodeData, callback) => {
9149
9454
  }
9150
9455
  }
9151
9456
  };
9152
- const isSsrAttrs = (value) => Array.isArray(value) && value.length > 0;
9457
+ const isSsrAttrs = (value) => typeof value === 'object' && value !== null && !isObjectEmpty(value);
9153
9458
  /**
9154
9459
  * When serializing the object we need check if it is URL, RegExp, Map, Set, etc. This is time
9155
9460
  * consuming. So if we could know that this is a basic object literal we could skip the check, and
@@ -9175,17 +9480,10 @@ function serializeWrappingFn(serializationContext, value) {
9175
9480
  const syncFnId = serializationContext.$addSyncFn$(value.$funcStr$, value.$args$.length, value.$func$);
9176
9481
  return [syncFnId, value.$args$];
9177
9482
  }
9178
- function filterEffectBackRefs(effectBackRef) {
9179
- let effectBackRefToSerialize = undefined;
9180
- if (effectBackRef) {
9181
- for (const [effectProp, effect] of effectBackRef) {
9182
- if (effect.backRef) {
9183
- effectBackRefToSerialize ||= new Map();
9184
- effectBackRefToSerialize.set(effectProp, effect);
9185
- }
9186
- }
9187
- }
9188
- return effectBackRefToSerialize;
9483
+ function tryGetBackRefs(props) {
9484
+ return Object.prototype.hasOwnProperty.call(props, QBackRefs)
9485
+ ? props[QBackRefs]
9486
+ : undefined;
9189
9487
  }
9190
9488
  class SerializationWeakRef {
9191
9489
  $obj$;
@@ -9209,39 +9507,56 @@ class SerializationBackRef {
9209
9507
  this.$path$ = $path$;
9210
9508
  }
9211
9509
  }
9212
- const createSerializationContext = (
9213
- /**
9214
- * Node constructor, for instanceof checks.
9215
- *
9216
- * A node constructor can be null. For example on the client we can't serialize DOM nodes as
9217
- * server will not know what to do with them.
9218
- */
9219
- NodeConstructor,
9220
- /** DomRef constructor, for instanceof checks. */
9221
- DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, writer) => {
9222
- if (!writer) {
9223
- const buffer = [];
9224
- writer = {
9225
- write: (text) => buffer.push(text),
9226
- toString: () => buffer.join(''),
9227
- };
9228
- }
9229
- const seenObjsMap = new Map();
9230
- const syncFnMap = new Map();
9231
- const syncFns = [];
9232
- const roots = [];
9233
- const eagerResume = new Set();
9234
- const getSeenRef = (obj) => seenObjsMap.get(obj);
9235
- const $markSeen$ = (obj, parent, index) => {
9510
+ class SerializationContextImpl {
9511
+ NodeConstructor;
9512
+ DomRefConstructor;
9513
+ $symbolToChunkResolver$;
9514
+ $setProp$;
9515
+ $storeProxyMap$;
9516
+ $writer$;
9517
+ $seenObjsMap$ = new Map();
9518
+ $syncFnMap$ = new Map();
9519
+ $syncFns$ = [];
9520
+ $roots$ = [];
9521
+ $eagerResume$ = new Set();
9522
+ $eventQrls$ = new Set();
9523
+ $eventNames$ = new Set();
9524
+ $renderSymbols$ = new Set();
9525
+ $serializer$;
9526
+ constructor(
9527
+ /**
9528
+ * Node constructor, for instanceof checks.
9529
+ *
9530
+ * A node constructor can be null. For example on the client we can't serialize DOM nodes as
9531
+ * server will not know what to do with them.
9532
+ */
9533
+ NodeConstructor,
9534
+ /** DomRef constructor, for instanceof checks. */
9535
+ DomRefConstructor, $symbolToChunkResolver$, $setProp$, $storeProxyMap$, $writer$) {
9536
+ this.NodeConstructor = NodeConstructor;
9537
+ this.DomRefConstructor = DomRefConstructor;
9538
+ this.$symbolToChunkResolver$ = $symbolToChunkResolver$;
9539
+ this.$setProp$ = $setProp$;
9540
+ this.$storeProxyMap$ = $storeProxyMap$;
9541
+ this.$writer$ = $writer$;
9542
+ this.$serializer$ = new Serializer(this);
9543
+ }
9544
+ async $serialize$() {
9545
+ return await this.$serializer$.serialize();
9546
+ }
9547
+ getSeenRef(obj) {
9548
+ return this.$seenObjsMap$.get(obj);
9549
+ }
9550
+ $markSeen$(obj, parent, index) {
9236
9551
  const ref = { $index$: index, $parent$: parent };
9237
- seenObjsMap.set(obj, ref);
9552
+ this.$seenObjsMap$.set(obj, ref);
9238
9553
  return ref;
9239
- };
9554
+ }
9240
9555
  /**
9241
9556
  * Returns a path string representing the path from roots through all parents to the object.
9242
9557
  * Format: "3 2 0" where each number is the index within its parent, from root to leaf.
9243
9558
  */
9244
- const $getObjectPath$ = (ref) => {
9559
+ $getObjectPath$(ref) {
9245
9560
  // Traverse up through parent references to build a path
9246
9561
  const path = [];
9247
9562
  while (ref.$parent$) {
@@ -9251,88 +9566,89 @@ DomRefConstructor, symbolToChunkResolver, getProp, setProp, storeProxyMap, write
9251
9566
  // Now we are at root, but it could be a backref
9252
9567
  path.unshift(ref.$index$);
9253
9568
  return path.join(' ');
9254
- };
9255
- const $promoteToRoot$ = (ref, index) => {
9256
- const path = $getObjectPath$(ref);
9569
+ }
9570
+ $promoteToRoot$(ref, index) {
9571
+ const path = this.$getObjectPath$(ref);
9257
9572
  if (index === undefined) {
9258
- index = roots.length;
9573
+ index = this.$roots$.length;
9259
9574
  }
9260
- roots[index] = new SerializationBackRef(path);
9575
+ this.$roots$[index] = new SerializationBackRef(path);
9261
9576
  ref.$parent$ = null;
9262
9577
  ref.$index$ = index;
9263
- };
9264
- const $addRoot$ = ((obj, returnRef) => {
9265
- let seen = seenObjsMap.get(obj);
9578
+ }
9579
+ $addRoot$(obj, returnRef = false) {
9580
+ let seen = this.$seenObjsMap$.get(obj);
9266
9581
  let index;
9267
9582
  if (!seen) {
9268
- index = roots.length;
9583
+ index = this.$roots$.length;
9269
9584
  seen = {
9270
9585
  $index$: index,
9271
9586
  // TODO benchmark with and without $parent$
9272
9587
  // $parent$: undefined
9273
9588
  };
9274
- seenObjsMap.set(obj, seen);
9275
- roots.push(obj);
9589
+ this.$seenObjsMap$.set(obj, seen);
9590
+ this.$roots$.push(obj);
9276
9591
  }
9277
9592
  else {
9278
9593
  if (seen.$parent$) {
9279
- $promoteToRoot$(seen);
9594
+ this.$promoteToRoot$(seen);
9280
9595
  }
9281
9596
  index = seen.$index$;
9282
9597
  }
9283
9598
  return returnRef ? seen : index;
9284
- });
9285
- const isSsrNode = (NodeConstructor ? (obj) => obj instanceof NodeConstructor : (() => false));
9286
- isDomRef = (DomRefConstructor ? (obj) => obj instanceof DomRefConstructor : (() => false));
9287
- return {
9288
- async $serialize$() {
9289
- return await serialize(this);
9290
- },
9291
- $isSsrNode$: isSsrNode,
9292
- $isDomRef$: isDomRef,
9293
- $symbolToChunkResolver$: symbolToChunkResolver,
9294
- getSeenRef,
9295
- $roots$: roots,
9296
- $markSeen$,
9297
- $hasRootId$: (obj) => {
9298
- const id = seenObjsMap.get(obj);
9299
- return id && (id.$parent$ ? undefined : id.$index$);
9300
- },
9301
- $promoteToRoot$,
9302
- $addRoot$,
9303
- $syncFns$: syncFns,
9304
- $addSyncFn$: (funcStr, argCount, fn) => {
9305
- const isFullFn = funcStr == null;
9599
+ }
9600
+ $isSsrNode$(obj) {
9601
+ return this.NodeConstructor ? obj instanceof this.NodeConstructor : false;
9602
+ }
9603
+ $isDomRef$(obj) {
9604
+ return this.DomRefConstructor ? obj instanceof this.DomRefConstructor : false;
9605
+ }
9606
+ $hasRootId$(obj) {
9607
+ const id = this.$seenObjsMap$.get(obj);
9608
+ return id && (id.$parent$ ? undefined : id.$index$);
9609
+ }
9610
+ $addSyncFn$(funcStr, argCount, fn) {
9611
+ const isFullFn = funcStr == null;
9612
+ if (isFullFn) {
9613
+ funcStr = fn.serialized || fn.toString();
9614
+ }
9615
+ let id = this.$syncFnMap$.get(funcStr);
9616
+ if (id === undefined) {
9617
+ id = this.$syncFns$.length;
9618
+ this.$syncFnMap$.set(funcStr, id);
9306
9619
  if (isFullFn) {
9307
- funcStr = fn.serialized || fn.toString();
9620
+ this.$syncFns$.push(funcStr);
9308
9621
  }
9309
- let id = syncFnMap.get(funcStr);
9310
- if (id === undefined) {
9311
- id = syncFns.length;
9312
- syncFnMap.set(funcStr, id);
9313
- if (isFullFn) {
9314
- syncFns.push(funcStr);
9315
- }
9316
- else {
9317
- let code = '(';
9318
- for (let i = 0; i < argCount; i++) {
9319
- code += (i == 0 ? 'p' : ',p') + i;
9320
- }
9321
- syncFns.push((code += ')=>' + funcStr));
9622
+ else {
9623
+ let code = '(';
9624
+ for (let i = 0; i < argCount; i++) {
9625
+ code += (i == 0 ? 'p' : ',p') + i;
9322
9626
  }
9627
+ this.$syncFns$.push((code += ')=>' + funcStr));
9323
9628
  }
9324
- return id;
9325
- },
9326
- $writer$: writer,
9327
- $eventQrls$: new Set(),
9328
- $eventNames$: new Set(),
9329
- $renderSymbols$: new Set(),
9330
- $storeProxyMap$: storeProxyMap,
9331
- $eagerResume$: eagerResume,
9332
- $resources$: new Set(),
9333
- $getProp$: getProp,
9334
- $setProp$: setProp,
9335
- };
9629
+ }
9630
+ return id;
9631
+ }
9632
+ }
9633
+ const createSerializationContext = (
9634
+ /**
9635
+ * Node constructor, for instanceof checks.
9636
+ *
9637
+ * A node constructor can be null. For example on the client we can't serialize DOM nodes as
9638
+ * server will not know what to do with them.
9639
+ */
9640
+ NodeConstructor,
9641
+ /** DomRef constructor, for instanceof checks. */
9642
+ DomRefConstructor, symbolToChunkResolver, setProp, storeProxyMap, writer) => {
9643
+ if (!writer) {
9644
+ const buffer = [];
9645
+ writer = {
9646
+ write: (text) => buffer.push(text),
9647
+ toString: () => buffer.join(''),
9648
+ };
9649
+ }
9650
+ isDomRef = (DomRefConstructor ? (obj) => obj instanceof DomRefConstructor : (() => false));
9651
+ return new SerializationContextImpl(NodeConstructor, DomRefConstructor, symbolToChunkResolver, setProp, storeProxyMap, writer);
9336
9652
  };
9337
9653
 
9338
9654
  /** @internal */
@@ -9363,7 +9679,7 @@ class _SharedContainer {
9363
9679
  return trackSignalAndAssignHost(signal, subscriber, property, this, data);
9364
9680
  }
9365
9681
  serializationCtxFactory(NodeConstructor, DomRefConstructor, symbolToChunkResolver, writer) {
9366
- return createSerializationContext(NodeConstructor, DomRefConstructor, symbolToChunkResolver, this.getHostProp.bind(this), this.setHostProp.bind(this), this.$storeProxyMap$, writer);
9682
+ return createSerializationContext(NodeConstructor, DomRefConstructor, symbolToChunkResolver, this.setHostProp.bind(this), this.$storeProxyMap$, writer);
9367
9683
  }
9368
9684
  $checkPendingCount$() {
9369
9685
  if (this.$pendingCount$ === 0) {
@@ -9396,16 +9712,14 @@ const applyQwikComponentBody = (ssr, jsx, component) => {
9396
9712
  return executeComponent(ssr, host, host, componentQrl, srcProps);
9397
9713
  };
9398
9714
 
9399
- class ParentComponentData {
9400
- $scopedStyle$;
9401
- $componentFrame$;
9402
- constructor($scopedStyle$, $componentFrame$) {
9403
- this.$scopedStyle$ = $scopedStyle$;
9404
- this.$componentFrame$ = $componentFrame$;
9405
- }
9406
- }
9407
9715
  class MaybeAsyncSignal {
9408
9716
  }
9717
+ function setParentOptions(mutable, styleScoped, parentComponentFrame) {
9718
+ return () => {
9719
+ mutable.currentStyleScoped = styleScoped;
9720
+ mutable.parentComponentFrame = parentComponentFrame;
9721
+ };
9722
+ }
9409
9723
  /** @internal */
9410
9724
  async function _walkJSX(ssr, value, options) {
9411
9725
  const stack = [value];
@@ -9413,32 +9727,22 @@ async function _walkJSX(ssr, value, options) {
9413
9727
  const drain = async () => {
9414
9728
  while (stack.length) {
9415
9729
  const value = stack.pop();
9416
- if (value instanceof ParentComponentData) {
9417
- options.currentStyleScoped = value.$scopedStyle$;
9418
- options.parentComponentFrame = value.$componentFrame$;
9419
- continue;
9420
- }
9421
- else if (value === MaybeAsyncSignal) {
9422
- // It could be an async signal, but it is not resolved yet, we need to wait for it.
9423
- // We could do that in the processJSXNode,
9424
- // but it will mean that we need to await it there, and it will return a promise.
9425
- // We probably want to avoid creating a promise for all jsx nodes.
9730
+ // Reference equality first (no prototype walk), then typeof
9731
+ if (value === MaybeAsyncSignal) {
9426
9732
  const trackFn = stack.pop();
9427
9733
  await retryOnPromise(() => stack.push(trackFn()));
9428
9734
  continue;
9429
9735
  }
9430
- else if (typeof value === 'function') {
9736
+ if (typeof value === 'function') {
9431
9737
  if (value === Promise) {
9432
9738
  stack.push(await stack.pop());
9433
- continue;
9434
9739
  }
9435
- await value.apply(ssr);
9740
+ else {
9741
+ await value.apply(ssr);
9742
+ }
9436
9743
  continue;
9437
9744
  }
9438
- processJSXNode(ssr, enqueue, value, {
9439
- styleScoped: options.currentStyleScoped,
9440
- parentComponentFrame: options.parentComponentFrame,
9441
- });
9745
+ processJSXNode(ssr, enqueue, value, options);
9442
9746
  }
9443
9747
  };
9444
9748
  await drain();
@@ -9465,7 +9769,7 @@ function processJSXNode(ssr, enqueue, value, options) {
9465
9769
  }
9466
9770
  else if (isSignal(value)) {
9467
9771
  maybeAddPollingAsyncSignalToEagerResume(ssr.serializationCtx, value);
9468
- ssr.openFragment(isDev ? [DEBUG_TYPE, "S" /* VirtualType.WrappedSignal */] : EMPTY_ARRAY);
9772
+ ssr.openFragment(isDev ? { [DEBUG_TYPE]: "S" /* VirtualType.WrappedSignal */ } : EMPTY_OBJ);
9469
9773
  const signalNode = ssr.getOrCreateLastNode();
9470
9774
  const unwrappedSignal = value instanceof WrappedSignalImpl ? value.$unwrapIfSignal$() : value;
9471
9775
  enqueue(ssr.closeFragment);
@@ -9473,20 +9777,20 @@ function processJSXNode(ssr, enqueue, value, options) {
9473
9777
  enqueue(MaybeAsyncSignal);
9474
9778
  }
9475
9779
  else if (isPromise(value)) {
9476
- ssr.openFragment(isDev ? [DEBUG_TYPE, "A" /* VirtualType.Awaited */] : EMPTY_ARRAY);
9780
+ ssr.openFragment(isDev ? { [DEBUG_TYPE]: "A" /* VirtualType.Awaited */ } : EMPTY_OBJ);
9477
9781
  enqueue(ssr.closeFragment);
9478
9782
  enqueue(value);
9479
9783
  enqueue(Promise);
9480
- enqueue(() => ssr.commentNode(FLUSH_COMMENT));
9784
+ enqueue(() => ssr.streamHandler.flush());
9481
9785
  }
9482
9786
  else if (isAsyncGenerator(value)) {
9483
9787
  enqueue(async () => {
9484
9788
  for await (const chunk of value) {
9485
9789
  await _walkJSX(ssr, chunk, {
9486
- currentStyleScoped: options.styleScoped,
9790
+ currentStyleScoped: options.currentStyleScoped,
9487
9791
  parentComponentFrame: options.parentComponentFrame,
9488
9792
  });
9489
- ssr.commentNode(FLUSH_COMMENT);
9793
+ ssr.streamHandler.flush();
9490
9794
  }
9491
9795
  });
9492
9796
  }
@@ -9495,7 +9799,7 @@ function processJSXNode(ssr, enqueue, value, options) {
9495
9799
  const type = jsx.type;
9496
9800
  // Below, JSXChildren allows functions and regexes, but we assume the dev only uses those as appropriate.
9497
9801
  if (typeof type === 'string') {
9498
- appendClassIfScopedStyleExists(jsx, options.styleScoped);
9802
+ appendClassIfScopedStyleExists(jsx, options.currentStyleScoped);
9499
9803
  let qwikInspectorAttrValue = null;
9500
9804
  if (isDev && jsx.dev && jsx.type !== 'head') {
9501
9805
  qwikInspectorAttrValue = getFileLocationFromJsx(jsx.dev);
@@ -9503,14 +9807,7 @@ function processJSXNode(ssr, enqueue, value, options) {
9503
9807
  appendQwikInspectorAttribute(jsx, qwikInspectorAttrValue);
9504
9808
  }
9505
9809
  }
9506
- const innerHTML = ssr.openElement(type, jsx.key, toSsrAttrs(jsx.varProps, {
9507
- serializationCtx: ssr.serializationCtx,
9508
- styleScopedId: options.styleScoped,
9509
- toSort: jsx.toSort,
9510
- }), toSsrAttrs(jsx.constProps, {
9511
- serializationCtx: ssr.serializationCtx,
9512
- styleScopedId: options.styleScoped,
9513
- }), qwikInspectorAttrValue);
9810
+ const innerHTML = ssr.openElement(type, jsx.key, jsx.varProps, jsx.constProps, options.currentStyleScoped, qwikInspectorAttrValue);
9514
9811
  if (innerHTML) {
9515
9812
  ssr.htmlNode(innerHTML);
9516
9813
  }
@@ -9533,9 +9830,9 @@ function processJSXNode(ssr, enqueue, value, options) {
9533
9830
  }
9534
9831
  else if (isFunction(type)) {
9535
9832
  if (type === Fragment) {
9536
- let attrs = jsx.key != null ? [ELEMENT_KEY, jsx.key] : EMPTY_ARRAY;
9833
+ const attrs = jsx.key != null ? { [ELEMENT_KEY]: jsx.key } : {};
9537
9834
  if (isDev) {
9538
- attrs = [DEBUG_TYPE, "F" /* VirtualType.Fragment */, ...attrs]; // Add debug info.
9835
+ attrs[DEBUG_TYPE] = "F" /* VirtualType.Fragment */; // Add debug info.
9539
9836
  }
9540
9837
  ssr.openFragment(attrs);
9541
9838
  enqueue(ssr.closeFragment);
@@ -9547,14 +9844,16 @@ function processJSXNode(ssr, enqueue, value, options) {
9547
9844
  const componentFrame = options.parentComponentFrame;
9548
9845
  if (componentFrame) {
9549
9846
  const compId = componentFrame.componentNode.id || '';
9550
- const projectionAttrs = isDev ? [DEBUG_TYPE, "P" /* VirtualType.Projection */] : [];
9551
- projectionAttrs.push(QSlotParent, compId);
9847
+ const projectionAttrs = isDev
9848
+ ? { [DEBUG_TYPE]: "P" /* VirtualType.Projection */ }
9849
+ : {};
9850
+ projectionAttrs[QSlotParent] = compId;
9552
9851
  ssr.openProjection(projectionAttrs);
9553
9852
  const host = componentFrame.componentNode;
9554
9853
  const node = ssr.getOrCreateLastNode();
9555
9854
  const slotName = getSlotName(host, jsx, ssr);
9556
- projectionAttrs.push(QSlot, slotName);
9557
- enqueue(new ParentComponentData(options.styleScoped, options.parentComponentFrame));
9855
+ projectionAttrs[QSlot] = slotName;
9856
+ enqueue(setParentOptions(options, options.currentStyleScoped, options.parentComponentFrame));
9558
9857
  enqueue(ssr.closeProjection);
9559
9858
  const slotDefaultChildren = jsx.children || null;
9560
9859
  const slotChildren = componentFrame.consumeChildrenForSlot(node, slotName) || slotDefaultChildren;
@@ -9562,11 +9861,15 @@ function processJSXNode(ssr, enqueue, value, options) {
9562
9861
  ssr.addUnclaimedProjection(componentFrame, QDefaultSlot, slotDefaultChildren);
9563
9862
  }
9564
9863
  enqueue(slotChildren);
9565
- enqueue(new ParentComponentData(componentFrame.projectionScopedStyle, componentFrame.projectionComponentFrame));
9864
+ enqueue(setParentOptions(options, componentFrame.projectionScopedStyle, componentFrame.projectionComponentFrame));
9566
9865
  }
9567
9866
  else {
9568
9867
  // Even thought we are not projecting we still need to leave a marker for the slot.
9569
- ssr.openFragment(isDev ? [DEBUG_TYPE, "P" /* VirtualType.Projection */] : EMPTY_ARRAY);
9868
+ let projectionAttrs = EMPTY_OBJ;
9869
+ if (isDev) {
9870
+ projectionAttrs = { [DEBUG_TYPE]: "P" /* VirtualType.Projection */ };
9871
+ }
9872
+ ssr.openFragment(projectionAttrs);
9570
9873
  ssr.closeFragment();
9571
9874
  }
9572
9875
  }
@@ -9574,17 +9877,17 @@ function processJSXNode(ssr, enqueue, value, options) {
9574
9877
  ssr.commentNode(directGetPropsProxyProp(jsx, 'data') || '');
9575
9878
  }
9576
9879
  else if (type === SSRStream) {
9577
- ssr.commentNode(FLUSH_COMMENT);
9880
+ ssr.streamHandler.flush();
9578
9881
  const generator = jsx.children;
9579
9882
  let value;
9580
9883
  if (isFunction(generator)) {
9581
9884
  value = generator({
9582
9885
  async write(chunk) {
9583
9886
  await _walkJSX(ssr, chunk, {
9584
- currentStyleScoped: options.styleScoped,
9887
+ currentStyleScoped: options.currentStyleScoped,
9585
9888
  parentComponentFrame: options.parentComponentFrame,
9586
9889
  });
9587
- ssr.commentNode(FLUSH_COMMENT);
9890
+ ssr.streamHandler.flush();
9588
9891
  },
9589
9892
  });
9590
9893
  }
@@ -9597,14 +9900,23 @@ function processJSXNode(ssr, enqueue, value, options) {
9597
9900
  else if (type === SSRRaw) {
9598
9901
  ssr.htmlNode(directGetPropsProxyProp(jsx, 'data'));
9599
9902
  }
9903
+ else if (type === SSRStreamBlock) {
9904
+ ssr.streamHandler.streamBlockStart();
9905
+ enqueue(() => ssr.streamHandler.streamBlockEnd());
9906
+ enqueue(jsx.children);
9907
+ }
9600
9908
  else if (isQwikComponent(type)) {
9601
- // prod: use new instance of an array for props, we always modify props for a component
9602
- ssr.openComponent(isDev ? [DEBUG_TYPE, "C" /* VirtualType.Component */] : []);
9909
+ // prod: use new instance of an object for props, we always modify props for a component
9910
+ const componentAttrs = {};
9911
+ if (isDev) {
9912
+ componentAttrs[DEBUG_TYPE] = "C" /* VirtualType.Component */;
9913
+ }
9914
+ ssr.openComponent(componentAttrs);
9603
9915
  const host = ssr.getOrCreateLastNode();
9604
9916
  const componentFrame = ssr.getParentComponentFrame();
9605
- componentFrame.distributeChildrenIntoSlots(jsx.children, options.styleScoped, options.parentComponentFrame);
9917
+ componentFrame.distributeChildrenIntoSlots(jsx.children, options.currentStyleScoped, options.parentComponentFrame);
9606
9918
  const jsxOutput = applyQwikComponentBody(ssr, jsx, type);
9607
- enqueue(new ParentComponentData(options.styleScoped, options.parentComponentFrame));
9919
+ enqueue(setParentOptions(options, options.currentStyleScoped, options.parentComponentFrame));
9608
9920
  enqueue(ssr.closeComponent);
9609
9921
  if (isPromise(jsxOutput)) {
9610
9922
  // Defer reading QScopedStyle until after the promise resolves
@@ -9612,22 +9924,23 @@ function processJSXNode(ssr, enqueue, value, options) {
9612
9924
  const resolvedOutput = await jsxOutput;
9613
9925
  const compStyleComponentId = addComponentStylePrefix(host.getProp(QScopedStyle));
9614
9926
  enqueue(resolvedOutput);
9615
- enqueue(new ParentComponentData(compStyleComponentId, componentFrame));
9927
+ enqueue(setParentOptions(options, compStyleComponentId, componentFrame));
9616
9928
  });
9617
9929
  }
9618
9930
  else {
9619
9931
  enqueue(jsxOutput);
9620
9932
  const compStyleComponentId = addComponentStylePrefix(host.getProp(QScopedStyle));
9621
- enqueue(new ParentComponentData(compStyleComponentId, componentFrame));
9933
+ enqueue(setParentOptions(options, compStyleComponentId, componentFrame));
9622
9934
  }
9623
9935
  }
9624
9936
  else {
9625
- const inlineComponentProps = [ELEMENT_KEY, jsx.key];
9626
- ssr.openFragment(isDev
9627
- ? [DEBUG_TYPE, "I" /* VirtualType.InlineComponent */, ...inlineComponentProps]
9628
- : inlineComponentProps);
9937
+ const inlineComponentProps = { [ELEMENT_KEY]: jsx.key };
9938
+ if (isDev) {
9939
+ inlineComponentProps[DEBUG_TYPE] = "I" /* VirtualType.InlineComponent */;
9940
+ }
9941
+ ssr.openFragment(inlineComponentProps);
9629
9942
  enqueue(ssr.closeFragment);
9630
- const component = ssr.getComponentFrame(0);
9943
+ const component = ssr.getParentComponentFrame();
9631
9944
  const jsxOutput = applyInlineComponent(ssr, component && component.componentNode, type, jsx);
9632
9945
  enqueue(jsxOutput);
9633
9946
  isPromise(jsxOutput) && enqueue(Promise);
@@ -9636,112 +9949,6 @@ function processJSXNode(ssr, enqueue, value, options) {
9636
9949
  }
9637
9950
  }
9638
9951
  }
9639
- function toSsrAttrs(record, options) {
9640
- if (record == null) {
9641
- return null;
9642
- }
9643
- const ssrAttrs = [];
9644
- const handleProp = (key, value) => {
9645
- if (value == null) {
9646
- return;
9647
- }
9648
- if (isHtmlAttributeAnEventName(key)) {
9649
- const eventValue = setEvent(options.serializationCtx, key, value);
9650
- if (eventValue) {
9651
- ssrAttrs.push(key, eventValue);
9652
- }
9653
- return;
9654
- }
9655
- if (isSignal(value)) {
9656
- maybeAddPollingAsyncSignalToEagerResume(options.serializationCtx, value);
9657
- // write signal as is. We will track this signal inside `writeAttrs`
9658
- if (isClassAttr(key)) {
9659
- // additionally append styleScopedId for class attr
9660
- ssrAttrs.push(key, [value, options.styleScopedId]);
9661
- }
9662
- else {
9663
- ssrAttrs.push(key, value);
9664
- }
9665
- return;
9666
- }
9667
- if (isPreventDefault(key)) {
9668
- addPreventDefaultEventToSerializationContext(options.serializationCtx, key);
9669
- }
9670
- else if (key === ITERATION_ITEM_SINGLE || key === ITERATION_ITEM_MULTI) {
9671
- value = options.serializationCtx.$addRoot$(value);
9672
- }
9673
- value = serializeAttribute(key, value, options.styleScopedId);
9674
- ssrAttrs.push(key, value);
9675
- };
9676
- if (options.toSort) {
9677
- const keys = Object.keys(record).sort();
9678
- for (const key of keys) {
9679
- handleProp(key, record[key]);
9680
- }
9681
- }
9682
- else {
9683
- for (const key in record) {
9684
- handleProp(key, record[key]);
9685
- }
9686
- }
9687
- return ssrAttrs;
9688
- }
9689
- function setEvent(serializationCtx, key, rawValue) {
9690
- let value = null;
9691
- const qrls = rawValue;
9692
- const appendToValue = (valueToAppend) => {
9693
- value = (value == null ? '' : value + '|') + valueToAppend;
9694
- };
9695
- const getQrlString = (qrl) => {
9696
- /**
9697
- * If there are captures we need to schedule so everything is executed in the right order + qrls
9698
- * are resolved.
9699
- *
9700
- * For internal qrls (starting with `_`) we assume that they do the right thing.
9701
- */
9702
- if (!qrl.$symbol$.startsWith('_') && qrl.$captures$?.length) {
9703
- qrl = createQRL(null, '_run', _run, null, [qrl]);
9704
- }
9705
- return qrlToString(serializationCtx, qrl);
9706
- };
9707
- if (Array.isArray(qrls)) {
9708
- for (let i = 0; i <= qrls.length; i++) {
9709
- const qrl = qrls[i];
9710
- if (isQrl(qrl)) {
9711
- appendToValue(getQrlString(qrl));
9712
- addQwikEventToSerializationContext(serializationCtx, key, qrl);
9713
- }
9714
- else if (qrl != null) {
9715
- // nested arrays etc.
9716
- const nestedValue = setEvent(serializationCtx, key, qrl);
9717
- if (nestedValue) {
9718
- appendToValue(nestedValue);
9719
- }
9720
- }
9721
- }
9722
- }
9723
- else if (isQrl(qrls)) {
9724
- value = getQrlString(qrls);
9725
- addQwikEventToSerializationContext(serializationCtx, key, qrls);
9726
- }
9727
- return value;
9728
- }
9729
- function addQwikEventToSerializationContext(serializationCtx, key, qrl) {
9730
- const data = getEventDataFromHtmlAttribute(key);
9731
- if (data) {
9732
- const [scope, eventName] = data;
9733
- const scopedEvent = getScopedEventName(scope, eventName);
9734
- serializationCtx.$eventNames$.add(scopedEvent);
9735
- serializationCtx.$eventQrls$.add(qrl);
9736
- }
9737
- }
9738
- function addPreventDefaultEventToSerializationContext(serializationCtx, key) {
9739
- // skip the `preventdefault`, leave the ':'
9740
- const eventName = 'e' + key.substring(14);
9741
- if (eventName) {
9742
- serializationCtx.$eventNames$.add(eventName);
9743
- }
9744
- }
9745
9952
  function maybeAddPollingAsyncSignalToEagerResume(serializationCtx, signal) {
9746
9953
  // Unwrap if it's a WrappedSignalImpl
9747
9954
  const unwrappedSignal = signal instanceof WrappedSignalImpl ? signal.$unwrapIfSignal$() : signal;
@@ -9912,6 +10119,57 @@ const isResourceReturn = (obj) => {
9912
10119
  return obj && obj.__brand === 'resource';
9913
10120
  };
9914
10121
 
10122
+ /** @internal */
10123
+ function setEvent(serializationCtx, key, rawValue, isLoopElement) {
10124
+ let value = null;
10125
+ const qrls = rawValue;
10126
+ const appendToValue = (valueToAppend) => {
10127
+ value = (value == null ? '' : value + '|') + valueToAppend;
10128
+ };
10129
+ const getQrlString = (qrl) => {
10130
+ /**
10131
+ * If there are captures we need to schedule so everything is executed in the right order + qrls
10132
+ * are resolved.
10133
+ *
10134
+ * For internal qrls (starting with `_`) we assume that they do the right thing.
10135
+ */
10136
+ if (!qrl.$symbol$.startsWith('_') && (qrl.$captures$?.length || isLoopElement)) {
10137
+ qrl = createQRL(null, '_run', _run, null, [qrl]);
10138
+ }
10139
+ return qrlToString(serializationCtx, qrl);
10140
+ };
10141
+ if (Array.isArray(qrls)) {
10142
+ for (let i = 0; i < qrls.length; i++) {
10143
+ const qrl = qrls[i];
10144
+ if (isQrl(qrl)) {
10145
+ appendToValue(getQrlString(qrl));
10146
+ addQwikEventToSerializationContext(serializationCtx, key, qrl);
10147
+ }
10148
+ else if (qrl != null) {
10149
+ // nested arrays etc.
10150
+ const nestedValue = setEvent(serializationCtx, key, qrl, isLoopElement);
10151
+ if (nestedValue) {
10152
+ appendToValue(nestedValue);
10153
+ }
10154
+ }
10155
+ }
10156
+ }
10157
+ else if (isQrl(qrls)) {
10158
+ value = getQrlString(qrls);
10159
+ addQwikEventToSerializationContext(serializationCtx, key, qrls);
10160
+ }
10161
+ return value;
10162
+ }
10163
+ function addQwikEventToSerializationContext(serializationCtx, key, qrl) {
10164
+ const data = getEventDataFromHtmlAttribute(key);
10165
+ if (data) {
10166
+ const [scope, eventName] = data;
10167
+ const scopedEvent = getScopedEventName(scope, eventName);
10168
+ serializationCtx.$eventNames$.add(scopedEvent);
10169
+ serializationCtx.$eventQrls$.add(qrl);
10170
+ }
10171
+ }
10172
+
9915
10173
  let loading = Promise.resolve();
9916
10174
  const inflate = (container, target, typeId, data) => {
9917
10175
  if (typeId === 0 /* TypeIds.Plain */) {
@@ -9945,8 +10203,7 @@ const inflate = (container, target, typeId, data) => {
9945
10203
  task.$flags$ = v[1];
9946
10204
  task.$index$ = v[2];
9947
10205
  task.$el$ = v[3];
9948
- task[_EFFECT_BACK_REF] = v[4];
9949
- task.$state$ = v[5];
10206
+ task.$state$ = v[4];
9950
10207
  break;
9951
10208
  case 21 /* TypeIds.Component */:
9952
10209
  target[SERIALIZABLE_STATE][0] = data[0];
@@ -9967,6 +10224,7 @@ const inflate = (container, target, typeId, data) => {
9967
10224
  const storeHandler = getStoreHandler(target);
9968
10225
  storeHandler.$flags$ = flags;
9969
10226
  storeHandler.$effects$ = effects;
10227
+ restoreEffectBackRefForEffectsMap(storeHandler.$effects$, store);
9970
10228
  break;
9971
10229
  }
9972
10230
  case 22 /* TypeIds.Signal */: {
@@ -9974,6 +10232,7 @@ const inflate = (container, target, typeId, data) => {
9974
10232
  const d = data;
9975
10233
  signal.$untrackedValue$ = d[0];
9976
10234
  signal.$effects$ = new Set(d.slice(1));
10235
+ restoreEffectBackRefForEffects(signal.$effects$, signal);
9977
10236
  break;
9978
10237
  }
9979
10238
  case 23 /* TypeIds.WrappedSignal */: {
@@ -9981,39 +10240,43 @@ const inflate = (container, target, typeId, data) => {
9981
10240
  const d = data;
9982
10241
  signal.$func$ = container.getSyncFn(d[0]);
9983
10242
  signal.$args$ = d[1];
9984
- signal[_EFFECT_BACK_REF] = d[2];
9985
10243
  signal.$untrackedValue$ = NEEDS_COMPUTATION;
9986
- signal.$flags$ = d[3];
10244
+ signal.$flags$ = d[2];
9987
10245
  signal.$flags$ |= 1 /* SignalFlags.INVALID */;
9988
- signal.$hostElement$ = d[4];
9989
- signal.$effects$ = new Set(d.slice(5));
10246
+ signal.$hostElement$ = d[3];
10247
+ signal.$effects$ = new Set(d.slice(4));
9990
10248
  inflateWrappedSignalValue(signal);
10249
+ restoreEffectBackRefForEffects(signal.$effects$, signal);
9991
10250
  break;
9992
10251
  }
9993
10252
  case 25 /* TypeIds.AsyncSignal */: {
9994
10253
  const asyncSignal = target;
9995
10254
  const d = data;
9996
10255
  asyncSignal.$computeQrl$ = d[0];
9997
- asyncSignal[_EFFECT_BACK_REF] = d[1];
9998
- asyncSignal.$effects$ = new Set(d[2]);
9999
- asyncSignal.$loadingEffects$ = new Set(d[3]);
10000
- asyncSignal.$errorEffects$ = new Set(d[4]);
10001
- asyncSignal.$untrackedError$ = d[5];
10256
+ asyncSignal.$effects$ = new Set(d[1]);
10257
+ asyncSignal.$loadingEffects$ = new Set(d[2]);
10258
+ asyncSignal.$errorEffects$ = new Set(d[3]);
10259
+ asyncSignal.$untrackedError$ = d[4];
10260
+ asyncSignal.$flags$ = d[5] ?? 0;
10261
+ if (asyncSignal.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
10262
+ // If it's client only, it was serialized because it pretended to be loading
10263
+ asyncSignal.$untrackedLoading$ = true;
10264
+ }
10002
10265
  const hasValue = d.length > 6;
10003
10266
  if (hasValue) {
10004
10267
  asyncSignal.$untrackedValue$ = d[6];
10005
10268
  }
10006
- if (asyncSignal.$untrackedValue$ !== NEEDS_COMPUTATION) {
10007
- // If we have a value after SSR, it will always be mean the signal was not invalid
10008
- asyncSignal.$flags$ &= -2 /* SignalFlags.INVALID */;
10269
+ // can happen when never serialize etc
10270
+ if (asyncSignal.$untrackedValue$ === NEEDS_COMPUTATION) {
10271
+ asyncSignal.$flags$ |= 1 /* SignalFlags.INVALID */;
10009
10272
  }
10010
10273
  // Note, we use the setter so that it schedules polling if needed
10011
- asyncSignal.interval = d[7] ?? 0;
10012
- asyncSignal.$concurrency$ = d[8] ?? 1;
10013
- asyncSignal.$timeoutMs$ = d[9] ?? 0;
10014
- if (d[10]) {
10015
- asyncSignal.$flags$ |= 32 /* AsyncSignalFlags.EAGER_CLEANUP */;
10016
- }
10274
+ asyncSignal.interval = (d[7] ?? 0);
10275
+ asyncSignal.$concurrency$ = (d[8] ?? 1);
10276
+ asyncSignal.$timeoutMs$ = (d[9] ?? 0);
10277
+ restoreEffectBackRefForEffects(asyncSignal.$effects$, asyncSignal);
10278
+ restoreEffectBackRefForEffects(asyncSignal.$loadingEffects$, asyncSignal);
10279
+ restoreEffectBackRefForEffects(asyncSignal.$errorEffects$, asyncSignal);
10017
10280
  break;
10018
10281
  }
10019
10282
  // Inflating a SerializerSignal is the same as inflating a ComputedSignal
@@ -10031,19 +10294,19 @@ const inflate = (container, target, typeId, data) => {
10031
10294
  // ignore preload errors
10032
10295
  });
10033
10296
  loading = loading.finally(() => p);
10034
- computed[_EFFECT_BACK_REF] = d[1];
10035
- if (d[2]) {
10036
- computed.$effects$ = new Set(d[2]);
10297
+ if (d[1]) {
10298
+ computed.$effects$ = new Set(d[1]);
10037
10299
  }
10038
- const hasValue = d.length > 3;
10300
+ const hasValue = d.length > 2;
10039
10301
  if (hasValue) {
10040
- computed.$untrackedValue$ = d[3];
10302
+ computed.$untrackedValue$ = d[2];
10041
10303
  }
10042
10304
  if (typeId !== 26 /* TypeIds.SerializerSignal */ && computed.$untrackedValue$ !== NEEDS_COMPUTATION) {
10043
10305
  // If we have a value after SSR, it will always be mean the signal was not invalid
10044
10306
  // The serialized signal is always left invalid so it can recreate the custom object
10045
10307
  computed.$flags$ &= -2 /* SignalFlags.INVALID */;
10046
10308
  }
10309
+ restoreEffectBackRefForEffects(computed.$effects$, computed);
10047
10310
  break;
10048
10311
  }
10049
10312
  case 15 /* TypeIds.Error */: {
@@ -10118,7 +10381,9 @@ const inflate = (container, target, typeId, data) => {
10118
10381
  owner._proxy = propsProxy;
10119
10382
  }
10120
10383
  propsProxy[_OWNER] = owner;
10121
- propsProxy[_PROPS_HANDLER].$effects$ = d[3];
10384
+ const propsHandler = propsProxy[_PROPS_HANDLER];
10385
+ propsHandler.$effects$ = d[3];
10386
+ restoreEffectBackRefForEffectsMap(propsHandler.$effects$, propsProxy);
10122
10387
  break;
10123
10388
  case 31 /* TypeIds.SubscriptionData */: {
10124
10389
  const effectData = target;
@@ -10131,14 +10396,15 @@ const inflate = (container, target, typeId, data) => {
10131
10396
  const d = data;
10132
10397
  effectSub.consumer = d[0];
10133
10398
  effectSub.property = d[1];
10134
- effectSub.backRef = d[2];
10135
- effectSub.data = d[3];
10399
+ effectSub.data = d[2];
10400
+ restoreEffectBackRefForConsumer(effectSub);
10136
10401
  break;
10137
10402
  }
10138
10403
  default:
10139
10404
  throw qError(16 /* QError.serializeErrorNotImplemented */, [typeId]);
10140
10405
  }
10141
- }; /**
10406
+ };
10407
+ /**
10142
10408
  * Restores an array eagerly. If you need it lazily, use `deserializeData(container, TypeIds.Array,
10143
10409
  * array)` instead
10144
10410
  */
@@ -10189,6 +10455,31 @@ function inflateWrappedSignalValue(signal) {
10189
10455
  }
10190
10456
  }
10191
10457
  }
10458
+ function restoreEffectBackRefForConsumer(effect) {
10459
+ const isServerSide = import.meta.env.TEST ? isServerPlatform() : isServer;
10460
+ const consumerBackRef = effect.consumer;
10461
+ if (isServerSide && !consumerBackRef) {
10462
+ // on browser, we don't serialize for example VNodes, so then on server side we don't have consumer
10463
+ return;
10464
+ }
10465
+ consumerBackRef[_EFFECT_BACK_REF] ||= new Map();
10466
+ consumerBackRef[_EFFECT_BACK_REF].set(effect.property, effect);
10467
+ }
10468
+ function restoreEffectBackRefForEffects(effects, consumer) {
10469
+ if (effects) {
10470
+ for (const effect of effects) {
10471
+ effect.backRef ||= new Set();
10472
+ effect.backRef.add(consumer);
10473
+ }
10474
+ }
10475
+ }
10476
+ function restoreEffectBackRefForEffectsMap(effectsMap, consumer) {
10477
+ if (effectsMap) {
10478
+ for (const [, effects] of effectsMap) {
10479
+ restoreEffectBackRefForEffects(effects, consumer);
10480
+ }
10481
+ }
10482
+ }
10192
10483
 
10193
10484
  /** Arrays/Objects are special-cased so their identifiers is a single digit. */
10194
10485
  const needsInflation = (typeId) => typeId >= 15 /* TypeIds.Error */ || typeId === 4 /* TypeIds.Array */ || typeId === 5 /* TypeIds.Object */;
@@ -10356,7 +10647,6 @@ function processVNodeData(document) {
10356
10647
  // Process all of the `qwik/vnode` script tags by attaching them to the corresponding containers.
10357
10648
  const attachVnodeDataAndRefs = (element) => {
10358
10649
  Array.from(element.querySelectorAll('script[type="qwik/vnode"]')).forEach((script) => {
10359
- script.setAttribute('type', 'x-qwik/vnode');
10360
10650
  const qContainerElement = script.closest('[q\\:container]');
10361
10651
  qContainerElement.qVnodeData = script.textContent;
10362
10652
  qContainerElement.qVNodeRefs = new Map();
@@ -10673,9 +10963,14 @@ class DomContainer extends _SharedContainer {
10673
10963
  $hoistStyles$() {
10674
10964
  const document = this.element.ownerDocument;
10675
10965
  const head = document.head;
10676
- const styles = document.querySelectorAll(QStylesAllSelector);
10677
- for (let i = 0; i < styles.length; i++) {
10678
- head.appendChild(styles[i]);
10966
+ const styles = document.body.querySelectorAll(QStylesAllSelector);
10967
+ const styleTagCount = styles.length;
10968
+ if (styleTagCount) {
10969
+ const fragment = document.createDocumentFragment();
10970
+ for (let i = 0; i < styleTagCount; i++) {
10971
+ fragment.appendChild(styles[i]);
10972
+ }
10973
+ head.appendChild(fragment);
10679
10974
  }
10680
10975
  }
10681
10976
  $setRawState$(id, vParent) {
@@ -11649,7 +11944,7 @@ function preprocessState(data, container) {
11649
11944
  * @internal
11650
11945
  */
11651
11946
  async function _serialize(data) {
11652
- const serializationContext = createSerializationContext(null, null, () => '', () => '', () => { }, new WeakMap());
11947
+ const serializationContext = createSerializationContext(null, null, () => '', () => { }, new WeakMap());
11653
11948
  serializationContext.$addRoot$(data);
11654
11949
  await serializationContext.$serialize$();
11655
11950
  return serializationContext.$writer$.toString();
@@ -11786,7 +12081,7 @@ const shouldSerialize = (obj) => {
11786
12081
  const fastSkipSerialize = (obj) => {
11787
12082
  return (!!obj &&
11788
12083
  (isObject(obj) || typeof obj === 'function') &&
11789
- (NoSerializeSymbol in obj || noSerializeSet.has(obj)));
12084
+ (noSerializeSet.has(obj) || NoSerializeSymbol in obj));
11790
12085
  };
11791
12086
  // <docs markdown="../../readme.md#noSerialize">
11792
12087
  // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
@@ -12037,12 +12332,9 @@ const createQRL = (chunk, symbol, symbolRef, symbolFn, captures) => {
12037
12332
  return symbolRef;
12038
12333
  }));
12039
12334
  }
12040
- if (isBrowser && symbol) {
12041
- /**
12042
- * Preloading the symbol instead of the chunk allows us to get probabilities for the bundle
12043
- * based on its contents.
12044
- */
12045
- p(symbol, 0.8);
12335
+ if (isBrowser && chunk) {
12336
+ /** Preloading the chunk when we create the QRL. */
12337
+ p(chunk, 0.8);
12046
12338
  }
12047
12339
  return qrl;
12048
12340
  };
@@ -12672,12 +12964,12 @@ const a = 97; // `a`.charCodeAt(0);
12672
12964
  const z = 122; // `z`.charCodeAt(0);
12673
12965
  const OPEN_BRACE = 123; // `{`.charCodeAt(0);
12674
12966
  const CLOSE_BRACE = 125; // `}`.charCodeAt(0);
12675
- const STRINGS_COMMENTS = /*__PURE__*/ (() => [
12967
+ const STRINGS_COMMENTS = /*@__PURE__*/ (() => [
12676
12968
  [ANY, SINGLE_QUOTE, stringSingle],
12677
12969
  [ANY, DOUBLE_QUOTE, stringDouble],
12678
12970
  [ANY, FORWARD_SLASH, commentMultiline, '*'],
12679
12971
  ])();
12680
- const STATE_MACHINE = /*__PURE__*/ (() => [
12972
+ const STATE_MACHINE = /*@__PURE__*/ (() => [
12681
12973
  [
12682
12974
  /// rule
12683
12975
  [ANY, STAR, starSelector],
@@ -13105,6 +13397,7 @@ const useConstant = (value, ...args) => {
13105
13397
  if (val != null) {
13106
13398
  return val;
13107
13399
  }
13400
+ // We don't want to create a subscription since we only run this once
13108
13401
  // Note: We are not using `invoke` here because we don't want to clear the context
13109
13402
  value = isFunction(value) && !isQwikComponent(value) ? untrack(value, ...args) : value;
13110
13403
  return set(value);
@@ -13488,11 +13781,7 @@ const PrefetchGraph = (_opts = {}) => null;
13488
13781
  // Protect against duplicate imports
13489
13782
  //////////////////////////////////////////////////////////////////////////////////////////
13490
13783
  if (globalThis.__qwik) {
13491
- console.error(`==============================================\n` +
13492
- `Qwik version ${globalThis.__qwik} already imported while importing ${version}.\n` +
13493
- `This can lead to issues due to duplicated shared structures.\n` +
13494
- `Verify that the Qwik libraries you're using are in "resolve.noExternal[]" and in "optimizeDeps.exclude".\n` +
13495
- `==============================================\n`);
13784
+ qError(30 /* QError.duplicateQwik */, [globalThis.__qwik, version]);
13496
13785
  }
13497
13786
  globalThis.__qwik = version;
13498
13787
  if (import.meta.hot) {
@@ -13501,5 +13790,5 @@ if (import.meta.hot) {
13501
13790
  });
13502
13791
  }
13503
13792
 
13504
- export { $, Fragment, NoSerializeSymbol, PrefetchGraph, PrefetchServiceWorker, RenderOnce, Resource, SSRComment, SSRRaw, SSRStream, SSRStreamBlock, SerializerSymbol, SkipRender, Slot, _CONST_PROPS, DomContainer as _DomContainer, _EFFECT_BACK_REF, EMPTY_ARRAY as _EMPTY_ARRAY, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _captures, _chk, createQRL as _createQRL, _deserialize, _dumpState, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, qrlToString as _qrlToString, _regSymbol, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, scheduleTask as _task, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsync$, createAsyncSignal as createAsyncQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsync$, useAsyncQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
13793
+ 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, EMPTY_OBJ as _EMPTY_OBJ, _IMMUTABLE, _SharedContainer, SubscriptionData as _SubscriptionData, _UNINITIALIZED, _VAR_PROPS, _captures, _chk, createQRL as _createQRL, _deserialize, _dumpState, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, isJSXNode as _isJSXNode, isStore as _isStore, isStringifiable as _isStringifiable, isTask as _isTask, _jsxBranch, _jsxC, _jsxQ, _jsxS, _jsxSorted, _jsxSplit, mapApp_findIndx as _mapApp_findIndx, mapArray_get as _mapArray_get, mapArray_set as _mapArray_set, _noopQrl, _noopQrlDEV, preprocessState as _preprocessState, _qrlSync, qrlToString as _qrlToString, _regSymbol, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, setEvent as _setEvent, scheduleTask as _task, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getFirstChild as _vnode_getFirstChild, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_toString as _vnode_toString, _waitUntilRendered, _walkJSX, _wrapProp, _wrapSignal, component$, componentQrl, createAsync$, createAsyncSignal as createAsyncQrl, createComputed$, createComputedSignal as createComputedQrl, createContextId, h as createElement, createSerializer$, createSerializerSignal as createSerializerQrl, createSignal, event$, eventQrl, forceStoreEffects, getDomContainer, getLocale, getPlatform, h, implicit$FirstArg, inlinedQrl, inlinedQrlDEV, isSignal, jsx, jsxDEV, jsxs, noSerialize, qrl, qrlDEV, render, setPlatform, sync$, untrack, unwrapStore, useAsync$, useAsyncQrl, useComputed$, useComputedQrl, useConstant, useContext, useContextProvider, useErrorBoundary, useId, useLexicalScope, useOn, useOnDocument, useOnWindow, useResource$, useResourceQrl, useSerializer$, useSerializerQrl, useServerData, useSignal, useStore, useStyles$, useStylesQrl, useStylesScoped$, useStylesScopedQrl, useTask$, useTaskQrl, useVisibleTask$, useVisibleTaskQrl, version, withLocale };
13505
13794
  //# sourceMappingURL=core.mjs.map