@qwik.dev/core 2.0.0-beta.31 → 2.0.0-beta.34

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.31-dev+906321a
3
+ * @qwik.dev/core 2.0.0-beta.34-dev+8b055bb
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
@@ -189,9 +189,11 @@ const isPrimitiveOrNullUndefined = (v) => {
189
189
  return (typeof v !== 'object' && typeof v !== 'function') || v === null || v === undefined;
190
190
  };
191
191
 
192
+ const baseUrl = 'https://qwikdev-build-v2.qwik-8nx.pages.dev/docs/errors/#q';
192
193
  const codeToText = (code, ...parts) => {
193
194
  if (qDev) {
194
195
  // Keep one error, one line to make it easier to search for the error message.
196
+ // Keep in sync with packages/docs/src/routes/docs/errors/index.mdx
195
197
  const MAP = [
196
198
  'Error while serializing class or style attributes', // 0
197
199
  'Scheduler not found', // 1
@@ -228,6 +230,7 @@ const codeToText = (code, ...parts) => {
228
230
  'Attribute value is unsafe for SSR {{0}}', // 32
229
231
  'SerializerSymbol function returned rejected promise', // 33
230
232
  'Serialization Error: Cannot serialize function: {{0}}', // 34
233
+ 'Cannot read .value of a clientOnly async signal during SSR. Use .loading to check state, or provide an initial value.', // 35
231
234
  ];
232
235
  let text = MAP[code] ?? '';
233
236
  if (parts.length) {
@@ -242,9 +245,7 @@ const codeToText = (code, ...parts) => {
242
245
  return `Code(Q${code}): ${text}`;
243
246
  }
244
247
  else {
245
- // cute little hack to give roughly the correct line number. Update the line number if it shifts.
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}`;
248
+ return `Code(Q${code}) ${baseUrl}${code}`;
248
249
  }
249
250
  };
250
251
  const qError = (code, errorMessageArgs = []) => {
@@ -571,49 +572,52 @@ const addComponentStylePrefix = (styleId) => {
571
572
  * - A `-` (not at the beginning) makes next character uppercase: `dbl-click` => `dblClick`
572
573
  */
573
574
  const EVENT_SUFFIX = '$';
575
+ const DOM_CONTENT_LOADED_EVENT = 'DOMContentLoaded';
574
576
  const isHtmlAttributeAnEventName = (name) => {
575
577
  return (name.charCodeAt(0) === 113 /* q */ &&
576
578
  name.charCodeAt(1) === 45 /* - */ &&
577
- name.charCodeAt(3) === 58 /* : */);
579
+ (name.charCodeAt(3) === 58 /* : */ ||
580
+ (name.charCodeAt(3) === 112 /* p */ && name.charCodeAt(4) === 58)) /* : */);
578
581
  };
579
- function jsxEventToHtmlAttribute(jsxEvent) {
582
+ function jsxEventToHtmlAttribute(jsxEvent, isPassive = false) {
580
583
  if (jsxEvent.endsWith(EVENT_SUFFIX)) {
581
- const [prefix, idx] = getEventScopeDataFromJsxEvent(jsxEvent);
584
+ const [prefix, idx] = getEventScopeDataFromJsxEvent(jsxEvent, isPassive);
582
585
  if (idx !== -1) {
583
- const name = jsxEvent.slice(idx, -1);
584
- return name === 'DOMContentLoaded'
585
- ? // The only DOM event that is not all lowercase
586
- prefix + '-d-o-m-content-loaded'
587
- : createEventName(name.charAt(0) === '-'
588
- ? // marker for case sensitive event name
589
- name.slice(1)
590
- : name.toLowerCase(), prefix);
586
+ return prefix + normalizeJsxEventName(jsxEvent.slice(idx, -1));
591
587
  }
592
588
  }
593
589
  return null; // Return null if not matching expected format
594
590
  }
595
- function createEventName(event, prefix) {
591
+ function createEventName(event, prefix = '') {
596
592
  const eventName = fromCamelToKebabCase(event);
597
593
  return prefix + eventName;
598
594
  }
599
- function getEventScopeDataFromJsxEvent(eventName) {
595
+ function getEventScopeDataFromJsxEvent(eventName, isPassive = false) {
600
596
  let prefix;
601
597
  let idx = -1;
602
598
  // set prefix and idx based on the scope
603
599
  if (eventName.startsWith("on" /* EventNameJSXScope.on */)) {
604
- prefix = "q-e:" /* EventNameHtmlScope.on */;
600
+ prefix = isPassive ? "q-ep:" /* EventNameHtmlScope.onPassive */ : "q-e:" /* EventNameHtmlScope.on */;
605
601
  idx = 2;
606
602
  }
607
603
  else if (eventName.startsWith("window:on" /* EventNameJSXScope.window */)) {
608
- prefix = "q-w:" /* EventNameHtmlScope.window */;
604
+ prefix = isPassive ? "q-wp:" /* EventNameHtmlScope.windowPassive */ : "q-w:" /* EventNameHtmlScope.window */;
609
605
  idx = 9;
610
606
  }
611
607
  else if (eventName.startsWith("document:on" /* EventNameJSXScope.document */)) {
612
- prefix = "q-d:" /* EventNameHtmlScope.document */;
608
+ prefix = isPassive ? "q-dp:" /* EventNameHtmlScope.documentPassive */ : "q-d:" /* EventNameHtmlScope.document */;
613
609
  idx = 11;
614
610
  }
615
611
  return [prefix, idx];
616
612
  }
613
+ const normalizeJsxEventName = (name) => {
614
+ return name === DOM_CONTENT_LOADED_EVENT
615
+ ? '-d-o-m-content-loaded'
616
+ : createEventName(name.charAt(0) === '-'
617
+ ? // marker for case sensitive event name
618
+ name.slice(1)
619
+ : name.toLowerCase());
620
+ };
617
621
  function isPreventDefault(key) {
618
622
  return key.startsWith('preventdefault:');
619
623
  }
@@ -621,11 +625,11 @@ function isPreventDefault(key) {
621
625
  const fromCamelToKebabCase = (text) => {
622
626
  return text.replace(/([A-Z-])/g, (a) => '-' + a.toLowerCase());
623
627
  };
624
- /** E.g. `"q-e:click"` => `['e', 'click']` */
625
- const getEventDataFromHtmlAttribute = (htmlKey) => [
626
- htmlKey.charAt(2),
627
- htmlKey.substring(4),
628
- ];
628
+ /** E.g. `"q-e:click"` => `['e', 'click']`, `"q-ep:click"` => `['ep', 'click']` */
629
+ const getEventDataFromHtmlAttribute = (htmlKey) => {
630
+ const separatorIndex = htmlKey.indexOf(':');
631
+ return [htmlKey.slice(2, separatorIndex), htmlKey.slice(separatorIndex + 1)];
632
+ };
629
633
  /** E.g. `"e:click"`, `"w:load"` */
630
634
  const getScopedEventName = (scope, eventName) => scope + ':' + eventName;
631
635
 
@@ -916,6 +920,9 @@ const createMacroTask = (fn) => {
916
920
  const isBrowser = import.meta.env.TEST ? !isServerPlatform() : !isServer;
917
921
  // Browser-specific setup
918
922
  const doc = isBrowser ? document : undefined;
923
+ const config = {
924
+ $maxIdlePreloads$: 25,
925
+ };
919
926
  // Determine which rel attribute to use based on browser support
920
927
  const rel = isBrowser && doc.createElement('link').relList?.supports?.('modulepreload')
921
928
  ? 'modulePreload'
@@ -983,10 +990,8 @@ function trigger() {
983
990
  const bundle = queue[0];
984
991
  const inverseProbability = bundle.$inverseProbability$;
985
992
  const probability = 1 - inverseProbability;
986
- const allowedPreloads = // While the graph is not available, we limit to 5 preloads
987
- 5;
988
- // When we're 99% sure, everything needs to be queued
989
- if (probability >= 0.99 || preloadCount < allowedPreloads) {
993
+ // We want to preload all the transitive static (1) and dynamic (0.99) dependencies, throttled by the user defined maxIdlePreloads.
994
+ if (probability >= 0.99 || preloadCount < config.$maxIdlePreloads$) {
990
995
  queue.shift();
991
996
  preloadOne(bundle);
992
997
  if (performance.now() >= deadline) {
@@ -1003,13 +1008,12 @@ function trigger() {
1003
1008
  nextTriggerMacroTask();
1004
1009
  }
1005
1010
  }
1006
- const enqueueAdjustment = (bundle, inverseProbability, context, seen) => {
1011
+ const enqueueAdjustment = (bundle, inverseProbability, seen) => {
1007
1012
  // Keep existing work on the stack hot and append new roots behind it.
1008
1013
  adjustmentStack.unshift({
1009
1014
  $bundle$: bundle,
1010
1015
  $inverseProbability$: inverseProbability,
1011
1016
  $seen$: seen,
1012
- $context$: context,
1013
1017
  });
1014
1018
  };
1015
1019
  const processAdjustmentFrame = () => {
@@ -1029,9 +1033,8 @@ const processAdjustmentFrame = () => {
1029
1033
  }
1030
1034
  const probability = 1 - bundle.$inverseProbability$;
1031
1035
  let newInverseProbability;
1032
- if (probability === 1 || (probability >= 0.99 && frame.$context$.$depsCount$ < 100)) {
1033
- frame.$context$.$depsCount$++;
1034
- // we're loaded at max probability, so elevate dynamic imports to 99% sure
1036
+ if (probability === 1 || probability >= 0.99) {
1037
+ // bundle is requested at max probability, so elevate all its transitive static and dynamic deps to 99% sure
1035
1038
  newInverseProbability = Math.min(0.01, 1 - dep.$importProbability$);
1036
1039
  }
1037
1040
  else {
@@ -1047,7 +1050,6 @@ const processAdjustmentFrame = () => {
1047
1050
  $bundle$: depBundle,
1048
1051
  $inverseProbability$: newInverseProbability,
1049
1052
  $seen$: frame.$seen$,
1050
- $context$: frame.$context$,
1051
1053
  });
1052
1054
  return true;
1053
1055
  }
@@ -1124,55 +1126,26 @@ const preloadOne = (bundle) => {
1124
1126
  };
1125
1127
  doc.head.appendChild(link);
1126
1128
  };
1127
- /**
1128
- * Adjust the probability of a bundle based on the probability of its dependent bundles, and queue
1129
- * it if it's likely enough to be preloaded.
1130
- *
1131
- * Note that if the probability is 100%, we treat the dynamic imports as 99% sure, and both will be
1132
- * preloaded without limit.
1133
- *
1134
- * We also limit "organic" probability to 98% so they don't get unlimited preloads.
1135
- */
1136
- const adjustProbabilities = (bundle, newInverseProbability, seen) => {
1137
- enqueueAdjustment(bundle, newInverseProbability, { $depsCount$: 0 }, seen);
1138
- if (shouldYieldInBrowser) {
1139
- nextAdjustmentMacroTask();
1140
- }
1141
- else {
1142
- processPendingAdjustments();
1143
- }
1144
- };
1145
- const handleBundle = (name, inverseProbability, context) => {
1129
+ const handleBundle = (name, inverseProbability) => {
1146
1130
  const bundle = getBundle(name);
1147
- if (bundle && bundle.$inverseProbability$ > inverseProbability) {
1148
- if (context) {
1149
- enqueueAdjustment(bundle, inverseProbability, context);
1150
- }
1151
- else {
1152
- adjustProbabilities(bundle, inverseProbability);
1153
- }
1131
+ if (bundle) {
1132
+ enqueueAdjustment(bundle, inverseProbability);
1154
1133
  }
1155
1134
  };
1156
- const preload = (name, probability) => {
1157
- if (!name?.length) {
1135
+ const preload = (item, probability) => {
1136
+ if (!item?.length) {
1158
1137
  return;
1159
1138
  }
1160
- let inverseProbability = 1 - probability ;
1161
- const context = { $depsCount$: 0 };
1162
- if (Array.isArray(name)) {
1139
+ const inverseProbability = 1 - probability ;
1140
+ if (Array.isArray(item)) {
1163
1141
  // We must process in reverse order to ensure first bundles are handled first
1164
- for (let i = name.length - 1; i >= 0; i--) {
1165
- const item = name[i];
1166
- if (typeof item === 'number') {
1167
- inverseProbability = 1 - item / 10;
1168
- }
1169
- else {
1170
- handleBundle(item, inverseProbability, context);
1171
- }
1142
+ for (let i = item.length - 1; i >= 0; i--) {
1143
+ const bundle = item[i];
1144
+ handleBundle(bundle, inverseProbability);
1172
1145
  }
1173
1146
  }
1174
1147
  else {
1175
- handleBundle(name, inverseProbability, context);
1148
+ handleBundle(item, inverseProbability);
1176
1149
  }
1177
1150
  if (shouldYieldInBrowser) {
1178
1151
  nextAdjustmentMacroTask();
@@ -1215,7 +1188,7 @@ const COMMA = ',';
1215
1188
  *
1216
1189
  * @public
1217
1190
  */
1218
- const version = "2.0.0-beta.31-dev+906321a";
1191
+ const version = "2.0.0-beta.34-dev+8b055bb";
1219
1192
 
1220
1193
  const isNode = (value) => {
1221
1194
  return value && typeof value.nodeType === 'number';
@@ -2033,19 +2006,16 @@ console.log('ASYNC COMPUTED SIGNAL', ...args.map(qwikDebugToString));
2033
2006
  /** Retains job metadata and also serves as the argument for the compute function */
2034
2007
  class AsyncJob {
2035
2008
  $signal$;
2036
- info;
2037
- $infoVersion$;
2038
2009
  /** First holds the compute promise and then the cleanup promise */
2039
2010
  $promise$ = null;
2040
2011
  $cleanupRequested$ = false;
2041
2012
  $canWrite$ = true;
2042
- $track$;
2043
- $cleanups$;
2044
- $abortController$;
2045
2013
  constructor($signal$, info, $infoVersion$) {
2046
2014
  this.$signal$ = $signal$;
2047
- this.info = info;
2048
- this.$infoVersion$ = $infoVersion$;
2015
+ if (info !== undefined) {
2016
+ this.info = info;
2017
+ this.$infoVersion$ = $infoVersion$;
2018
+ }
2049
2019
  }
2050
2020
  get track() {
2051
2021
  return (this.$track$ ||= trackFn(this.$signal$, this.$signal$.$container$));
@@ -2056,7 +2026,7 @@ class AsyncJob {
2056
2026
  /** Backward compatible cache method for resource */
2057
2027
  cache() {
2058
2028
  isDev &&
2059
- console.error('useResource cache() method does not do anything. Use `useAsync$` instead of `useResource$`, use the `interval` option for polling behavior.');
2029
+ console.error('useResource cache() method does not do anything. Use `useAsync$` instead of `useResource$`, use the `expires` option for polling behavior.');
2060
2030
  }
2061
2031
  get previous() {
2062
2032
  const val = this.$signal$.$untrackedValue$;
@@ -2076,48 +2046,55 @@ class AsyncJob {
2076
2046
  * AsyncSignalImpl
2077
2047
  *
2078
2048
  * # ================================
2049
+ *
2050
+ * @internal
2079
2051
  */
2080
2052
  class AsyncSignalImpl extends ComputedSignalImpl {
2081
2053
  $untrackedLoading$ = false;
2082
2054
  $untrackedError$ = undefined;
2083
- $loadingEffects$ = undefined;
2084
- $errorEffects$ = undefined;
2085
2055
  $current$ = null;
2086
- // TODO only create the array if concurrency > 1
2087
- $jobs$ = [];
2088
- $concurrency$ = 1;
2089
- $interval$ = 0;
2090
- $timeoutMs$;
2091
- $info$ = undefined;
2092
- $infoVersion$ = 0;
2093
2056
  [_EFFECT_BACK_REF] = undefined;
2094
2057
  constructor(container, fn, flags = 1 /* SignalFlags.INVALID */ |
2095
2058
  16 /* SerializationSignalFlags.SERIALIZATION_STRATEGY_ALWAYS */, options) {
2096
2059
  super(container, fn, flags);
2097
- const interval = options?.interval;
2098
- const concurrency = options?.concurrency ?? 1;
2099
- const initial = options?.initial;
2100
- const timeout = options?.timeout;
2101
- const eagerCleanup = options?.eagerCleanup;
2102
- const clientOnly = options?.clientOnly;
2060
+ if (!options) {
2061
+ return;
2062
+ }
2103
2063
  // Handle initial value - eagerly evaluate if function, set $untrackedValue$ and $promiseValue$
2104
2064
  // Do NOT call setValue() which would clear the INVALID flag and prevent async computation
2065
+ const initial = options.initial;
2105
2066
  if (initial !== undefined) {
2106
2067
  const initialValue = typeof initial === 'function' ? initial() : initial;
2107
2068
  this.$untrackedValue$ = initialValue;
2108
2069
  }
2109
- this.$concurrency$ = concurrency;
2070
+ const concurrency = options.concurrency;
2071
+ if (concurrency !== undefined && concurrency >= 0 && concurrency !== 1) {
2072
+ this.$concurrency$ = concurrency;
2073
+ this.$jobs$ = [];
2074
+ }
2075
+ const timeout = options.timeout;
2110
2076
  if (timeout) {
2111
2077
  this.$timeoutMs$ = timeout;
2112
2078
  }
2113
- if (eagerCleanup) {
2079
+ if (options.eagerCleanup) {
2114
2080
  this.$flags$ |= 32 /* AsyncSignalFlags.EAGER_CLEANUP */;
2115
2081
  }
2116
- if (clientOnly) {
2082
+ if (options.clientOnly) {
2117
2083
  this.$flags$ |= 64 /* AsyncSignalFlags.CLIENT_ONLY */;
2118
2084
  }
2119
- if (interval) {
2120
- this.interval = interval;
2085
+ if (options.allowStale === false) {
2086
+ if (isDev && initial !== undefined) {
2087
+ throw new Error('allowStale: false and initial cannot be used together. ' +
2088
+ 'allowStale: false clears the value on invalidation, which conflicts with providing an initial value.');
2089
+ }
2090
+ this.$flags$ |= 128 /* AsyncSignalFlags.CLEAR_ON_INVALIDATE */;
2091
+ }
2092
+ const expires = options.expires ?? (options.interval ? Math.abs(options.interval) : undefined);
2093
+ if (expires) {
2094
+ this.expires = expires;
2095
+ }
2096
+ if (options.poll === false || (options.interval !== undefined && options.interval < 0)) {
2097
+ this.$flags$ |= 256 /* AsyncSignalFlags.NO_POLL */;
2121
2098
  }
2122
2099
  }
2123
2100
  get untrackedValue() {
@@ -2137,9 +2114,7 @@ class AsyncSignalImpl extends ComputedSignalImpl {
2137
2114
  if ((import.meta.env.TEST ? isServerPlatform() : isServer) &&
2138
2115
  this.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */ &&
2139
2116
  this.$untrackedValue$ === NEEDS_COMPUTATION) {
2140
- throw new Error(isDev
2141
- ? 'During SSR, cannot read .value from clientOnly async signal without an initial value. Use .loading or provide an initial value.'
2142
- : 'Cannot read .value from clientOnly');
2117
+ throw qError(35 /* QError.asyncClientOnlyValueDuringSSR */);
2143
2118
  }
2144
2119
  return this.$untrackedValue$;
2145
2120
  }
@@ -2166,8 +2141,13 @@ class AsyncSignalImpl extends ComputedSignalImpl {
2166
2141
  this.untrackedError = undefined;
2167
2142
  this.$info$ = undefined;
2168
2143
  // Prevent pending computations from overwriting this value
2169
- for (let i = 0; i < this.$jobs$.length; i++) {
2170
- this.$jobs$[i].$canWrite$ = false;
2144
+ if (this.$jobs$) {
2145
+ for (let i = 0; i < this.$jobs$.length; i++) {
2146
+ this.$jobs$[i].$canWrite$ = false;
2147
+ }
2148
+ }
2149
+ else if (this.$current$) {
2150
+ this.$current$.$canWrite$ = false;
2171
2151
  }
2172
2152
  this.$clearNextPoll$();
2173
2153
  super.value = value;
@@ -2235,28 +2215,64 @@ class AsyncSignalImpl extends ComputedSignalImpl {
2235
2215
  get untrackedError() {
2236
2216
  return this.$untrackedError$;
2237
2217
  }
2238
- get interval() {
2239
- return this.$interval$;
2218
+ get expires() {
2219
+ return this.$expires$ || 0;
2240
2220
  }
2241
- set interval(value) {
2221
+ set expires(value) {
2242
2222
  this.$clearNextPoll$();
2243
- this.$interval$ = value;
2244
- if (this.$interval$ !== 0 && this.$hasSubscribers$()) {
2223
+ this.$expires$ = value;
2224
+ if (this.$expires$ && this.$hasSubscribers$()) {
2245
2225
  this.$scheduleNextPoll$();
2246
2226
  }
2247
2227
  }
2228
+ get poll() {
2229
+ return !(this.$flags$ & 256 /* AsyncSignalFlags.NO_POLL */);
2230
+ }
2231
+ set poll(value) {
2232
+ if (value) {
2233
+ this.$flags$ &= -257 /* AsyncSignalFlags.NO_POLL */;
2234
+ }
2235
+ else {
2236
+ this.$flags$ |= 256 /* AsyncSignalFlags.NO_POLL */;
2237
+ }
2238
+ // Reschedule since poll behavior changed
2239
+ if (this.$expires$ && this.$hasSubscribers$()) {
2240
+ this.$clearNextPoll$();
2241
+ this.$scheduleNextPoll$();
2242
+ }
2243
+ }
2244
+ /** @deprecated Use `expires` and `poll` instead. */
2245
+ get interval() {
2246
+ const expires = this.$expires$ || 0;
2247
+ return this.$flags$ & 256 /* AsyncSignalFlags.NO_POLL */ ? -expires : expires;
2248
+ }
2249
+ set interval(value) {
2250
+ if (value < 0) {
2251
+ this.$flags$ |= 256 /* AsyncSignalFlags.NO_POLL */;
2252
+ }
2253
+ else {
2254
+ this.$flags$ &= -257 /* AsyncSignalFlags.NO_POLL */;
2255
+ }
2256
+ this.expires = Math.abs(value);
2257
+ }
2248
2258
  /** Invalidates the signal, causing it to re-compute its value. */
2249
2259
  async invalidate(info) {
2250
- this.$flags$ |= 1 /* SignalFlags.INVALID */;
2251
- this.$clearNextPoll$();
2252
2260
  if (arguments.length > 0) {
2253
2261
  this.$info$ = info;
2254
- this.$infoVersion$++;
2262
+ this.$infoVersion$ = this.$infoVersion$ === undefined ? 1 : this.$infoVersion$ + 1;
2255
2263
  }
2256
- if (this.$effects$?.size || this.$loadingEffects$?.size || this.$errorEffects$?.size) {
2264
+ this.$setInvalid$(true, this.$flags$ & 128 /* AsyncSignalFlags.CLEAR_ON_INVALIDATE */);
2265
+ }
2266
+ $setInvalid$(allowRecalc, mustClear) {
2267
+ this.$flags$ |= 1 /* SignalFlags.INVALID */;
2268
+ this.$clearNextPoll$();
2269
+ if (mustClear) {
2270
+ this.$untrackedValue$ = NEEDS_COMPUTATION;
2271
+ }
2272
+ if (allowRecalc &&
2273
+ (this.$effects$?.size || this.$loadingEffects$?.size || this.$errorEffects$?.size)) {
2257
2274
  // compute in next microtask
2258
- await true;
2259
- this.$computeIfNeeded$();
2275
+ Promise.resolve().then(() => this.$computeIfNeeded$());
2260
2276
  }
2261
2277
  }
2262
2278
  /** Abort the current computation and run cleanups if needed. */
@@ -2301,63 +2317,92 @@ class AsyncSignalImpl extends ComputedSignalImpl {
2301
2317
  return;
2302
2318
  }
2303
2319
  this.$clearNextPoll$();
2304
- if (this.$current$) {
2305
- this.$requestCleanups$(this.$current$);
2320
+ // Clear flag here to make sure the cleanups don't start another compute
2321
+ this.$flags$ &= -2 /* SignalFlags.INVALID */;
2322
+ const current = this.$current$;
2323
+ if (current) {
2324
+ this.$requestCleanups$(current);
2306
2325
  }
2307
- const limit = this.$concurrency$ === 0 ? Number.POSITIVE_INFINITY : this.$concurrency$;
2308
- if (this.$jobs$.length >= limit) {
2326
+ const limit = this.$concurrency$ === 0 ? Number.POSITIVE_INFINITY : (this.$concurrency$ ?? 1);
2327
+ // We only have $jobs$[] when concurrency != 1
2328
+ if (this.$jobs$ ? this.$jobs$.length >= limit : current?.$promise$) {
2309
2329
  // We requested cleanups for all the previous jobs, once one finishes it will be removed from the jobs array and trigger computeIfNeeded
2330
+ // Restore invalid state
2331
+ this.$flags$ |= 1 /* SignalFlags.INVALID */;
2310
2332
  return;
2311
2333
  }
2312
- this.$flags$ &= -2 /* SignalFlags.INVALID */;
2313
2334
  // We put the actual computation in a separate method so we can easily retain the promise
2314
2335
  const infoVersion = this.$infoVersion$;
2315
2336
  const running = new AsyncJob(this, this.$info$, infoVersion);
2316
2337
  this.$current$ = running;
2317
- this.$jobs$.push(running);
2338
+ if (this.$jobs$) {
2339
+ this.$jobs$.push(running);
2340
+ }
2318
2341
  running.$promise$ = this.$runComputation$(running);
2319
2342
  }
2320
2343
  async $runComputation$(running) {
2321
2344
  const isCurrent = () => running === this.$current$;
2322
- this.untrackedLoading = true;
2323
- const fn = this.$computeQrl$.resolved || (await this.$computeQrl$.resolve());
2345
+ let fn = this.$computeQrl$.resolved;
2346
+ if (!fn) {
2347
+ // QRL resolution is async — we have to publish loading=true before awaiting so
2348
+ // subscribers know the value isn't ready yet.
2349
+ this.untrackedLoading = true;
2350
+ fn = await this.$computeQrl$.resolve();
2351
+ if (running.$abortController$?.signal.aborted) {
2352
+ running.$promise$ = null;
2353
+ return;
2354
+ }
2355
+ }
2324
2356
  try {
2325
2357
  if (this.$timeoutMs$) {
2326
2358
  this.$computationTimeoutId$ = setTimeout(() => {
2327
- running.$abortController$?.abort();
2328
- const error = new Error(`timeout`);
2329
- if (isCurrent()) {
2330
- this.untrackedError = error;
2331
- running.$canWrite$ = false;
2332
- }
2359
+ const error = new Error(`timeout ${this.$timeoutMs$}ms`);
2360
+ this.$setError$(running, error);
2361
+ running.$abortController$?.abort(error);
2333
2362
  }, this.$timeoutMs$);
2334
2363
  }
2335
- // Try to stay sync if possible
2364
+ // Try to stay sync if possible. Only publish loading=true to subscribers when
2365
+ // the compute is actually asynchronous — a synchronous resolve (e.g. pre-loaded
2366
+ // values injected via _injectAsyncSignalValue) should never transition through a
2367
+ // visible loading state, which on SSR would fire the loading-effect subscribers
2368
+ // (tasks) while the value is still "loading" from their perspective.
2336
2369
  const valuePromise = retryOnPromise(fn.bind(null, running));
2337
- const value = isPromise(valuePromise) ? await valuePromise : valuePromise;
2370
+ let value;
2371
+ if (isPromise(valuePromise)) {
2372
+ this.untrackedLoading = true;
2373
+ value = await valuePromise;
2374
+ }
2375
+ else {
2376
+ value = valuePromise;
2377
+ }
2338
2378
  running.$promise$ = null;
2339
2379
  if (running.$canWrite$) {
2340
- const index = this.$jobs$.indexOf(running);
2341
- if (index !== -1) {
2342
- for (let i = 0; i < index; i++) {
2343
- this.$jobs$[i].$canWrite$ = false;
2380
+ const jobs = this.$jobs$;
2381
+ if (jobs) {
2382
+ let doDisable = false;
2383
+ for (let i = jobs.length - 1; i >= 0; i--) {
2384
+ if (jobs[i] === running) {
2385
+ doDisable = true;
2386
+ }
2387
+ else if (doDisable) {
2388
+ jobs[i].$canWrite$ = false;
2389
+ }
2344
2390
  }
2345
2391
  }
2346
2392
  DEBUG && log('Promise resolved', value);
2347
2393
  // we leave error as-is until result
2348
2394
  // Note that these assignments run setters
2349
2395
  this.untrackedError = undefined;
2350
- // Use super.value instead of this.value to avoid the AsyncSignalImpl setter
2351
- // which clears INVALID and disables all jobs. INVALID must persist so that
2352
- // line 442 can detect dependency changes during computation and re-run.
2396
+ /**
2397
+ * Use super.value instead of this.value to persist invalid state, so that invalidation
2398
+ * during computation recomputes
2399
+ */
2353
2400
  super.value = value;
2354
2401
  }
2355
2402
  }
2356
2403
  catch (err) {
2357
2404
  running.$promise$ = null;
2358
- if (isCurrent()) {
2359
- this.untrackedError = err;
2360
- }
2405
+ this.$setError$(running, err);
2361
2406
  }
2362
2407
  if (isCurrent()) {
2363
2408
  clearTimeout(this.$computationTimeoutId$);
@@ -2374,14 +2419,37 @@ class AsyncSignalImpl extends ComputedSignalImpl {
2374
2419
  }
2375
2420
  }
2376
2421
  }
2422
+ /**
2423
+ * Sets the error from the given job. We only accept errors from the current job and we ignore
2424
+ * AbortErrors.
2425
+ */
2426
+ $setError$(job, error) {
2427
+ if (job !== this.$current$ || !job.$canWrite$) {
2428
+ return;
2429
+ }
2430
+ job.$canWrite$ = false;
2431
+ if (error instanceof Error && error.name === 'AbortError') {
2432
+ // AbortError from AbortSignal is a cancellation, not an actual error
2433
+ return;
2434
+ }
2435
+ this.untrackedError = error;
2436
+ // Job failures should be rare and require retrying
2437
+ this.untrackedValue = NEEDS_COMPUTATION;
2438
+ }
2377
2439
  /** Called after SSR/unmount */
2378
2440
  async $destroy$() {
2379
2441
  this.$clearNextPoll$();
2380
2442
  clearTimeout(this.$computationTimeoutId$);
2381
- if (this.$current$) {
2382
- await this.$requestCleanups$(this.$current$);
2443
+ const current = this.$current$;
2444
+ if (current) {
2445
+ this.$requestCleanups$(current);
2446
+ }
2447
+ if (this.$jobs$) {
2448
+ await Promise.all(this.$jobs$.map((job) => job.$promise$));
2449
+ }
2450
+ else {
2451
+ await current?.$promise$;
2383
2452
  }
2384
- await Promise.all(this.$jobs$.map((job) => job.$promise$));
2385
2453
  }
2386
2454
  $clearNextPoll$() {
2387
2455
  if (this.$pollTimeoutId$ !== undefined) {
@@ -2390,66 +2458,76 @@ class AsyncSignalImpl extends ComputedSignalImpl {
2390
2458
  }
2391
2459
  }
2392
2460
  $scheduleNextPoll$() {
2393
- if (!(import.meta.env.TEST ? !isServerPlatform() : isBrowser$1) || this.$interval$ === 0) {
2461
+ if ((import.meta.env.TEST ? isServerPlatform() : isServer) || !this.$expires$) {
2394
2462
  return;
2395
2463
  }
2396
2464
  this.$clearNextPoll$();
2397
- if (this.$interval$ < 0) {
2398
- this.$pollTimeoutId$ = setTimeout(() => {
2399
- this.$pollTimeoutId$ = undefined;
2400
- this.$flags$ |= 1 /* SignalFlags.INVALID */;
2401
- }, -this.$interval$);
2402
- }
2403
- else {
2404
- this.$pollTimeoutId$ = setTimeout(this.invalidate.bind(this), this.$interval$);
2405
- }
2465
+ const allowRecalc = !(this.$flags$ & 256 /* AsyncSignalFlags.NO_POLL */);
2466
+ // Even when clear on invalidate, we don't clear if we're merely re-running due to polling
2467
+ // We expect to get the new value soon, so we can avoid showing a loading state
2468
+ const mustClear = this.$flags$ & 128 /* AsyncSignalFlags.CLEAR_ON_INVALIDATE */ && !allowRecalc;
2469
+ this.$pollTimeoutId$ = setTimeout(() => this.$setInvalid$(allowRecalc, mustClear), this.$expires$);
2406
2470
  this.$pollTimeoutId$?.unref?.();
2407
2471
  }
2408
2472
  $hasSubscribers$() {
2409
2473
  return !!(this.$effects$?.size || this.$loadingEffects$?.size || this.$errorEffects$?.size);
2410
2474
  }
2411
- async $requestCleanups$(job, reason) {
2475
+ $requestCleanups$(job, reason) {
2412
2476
  if (job.$cleanupRequested$) {
2413
- return job.$promise$;
2477
+ return;
2414
2478
  }
2415
2479
  job.$cleanupRequested$ = true;
2416
2480
  job.$abortController$?.abort(reason);
2417
- job.$promise$ = Promise.resolve(job.$promise$).then(() => (job.$promise$ = this.$runCleanups$(job)));
2481
+ job.$promise$ = maybeThen(job.$promise$, () => this.$runCleanups$(job));
2418
2482
  }
2419
2483
  /** Clean up and trigger signal compute once complete */
2420
- async $runCleanups$(job) {
2484
+ $runCleanups$(job) {
2421
2485
  const cleanups = job.$cleanups$;
2422
- if (cleanups?.length) {
2423
- const onError = (err) => {
2424
- const handleError = this.$container$?.handleError;
2425
- if (handleError) {
2426
- handleError(err, null);
2427
- }
2428
- else {
2429
- console.error('Error in async signal cleanup', err);
2486
+ const onError = (err) => {
2487
+ const handleError = this.$container$?.handleError;
2488
+ if (handleError) {
2489
+ handleError(err, null);
2490
+ }
2491
+ else {
2492
+ console.error('Error in async signal cleanup', err);
2493
+ }
2494
+ };
2495
+ const onDone = () => {
2496
+ job.$promise$ = null;
2497
+ if (cleanups) {
2498
+ cleanups.length = 0;
2499
+ }
2500
+ // Now trigger compute
2501
+ const jobs = this.$jobs$;
2502
+ if (jobs) {
2503
+ const idx = jobs.indexOf(job);
2504
+ if (idx !== -1) {
2505
+ jobs.splice(idx, 1);
2430
2506
  }
2431
- };
2507
+ }
2508
+ this.$computeIfNeeded$();
2509
+ };
2510
+ let promiseChain = undefined;
2511
+ if (cleanups) {
2432
2512
  // Keep this sync-ish so sync functions run immediately.
2433
- await Promise.all(cleanups.map((fn) => {
2513
+ for (let i = 0; i < cleanups.length; i++) {
2434
2514
  try {
2435
- const result = fn();
2515
+ const result = cleanups[i]();
2436
2516
  if (isPromise(result)) {
2437
- return result.catch(onError);
2517
+ promiseChain = (promiseChain ? promiseChain.then(() => result) : result).catch(onError);
2438
2518
  }
2439
2519
  }
2440
2520
  catch (err) {
2441
2521
  onError(err);
2442
2522
  }
2443
- }));
2444
- cleanups.length = 0;
2523
+ }
2445
2524
  }
2446
- // Now trigger compute
2447
- const jobs = this.$jobs$;
2448
- const idx = jobs.indexOf(job);
2449
- if (idx !== -1) {
2450
- jobs.splice(idx, 1);
2525
+ if (promiseChain) {
2526
+ return promiseChain.then(onDone);
2527
+ }
2528
+ else {
2529
+ onDone();
2451
2530
  }
2452
- this.$computeIfNeeded$();
2453
2531
  }
2454
2532
  }
2455
2533
 
@@ -3108,7 +3186,69 @@ const isJSXNode = (n) => {
3108
3186
 
3109
3187
  const BIND_VALUE = 'bind:value';
3110
3188
  const BIND_CHECKED = 'bind:checked';
3189
+ const PASSIVE = 'passive:';
3190
+ const PREVENT_DEFAULT = 'preventdefault:';
3111
3191
  const _hasOwnProperty$1 = Object.prototype.hasOwnProperty;
3192
+ const removePassiveMarkers = (props, passiveKeys, preventDefaultKeys, passiveEvents, canMutate = false) => {
3193
+ let mutableProps = props;
3194
+ let copied = canMutate;
3195
+ if (passiveKeys.length > 0) {
3196
+ if (!copied) {
3197
+ mutableProps = { ...mutableProps };
3198
+ copied = true;
3199
+ }
3200
+ for (let i = 0; i < passiveKeys.length; i++) {
3201
+ const k = passiveKeys[i];
3202
+ delete mutableProps[k];
3203
+ }
3204
+ }
3205
+ if (preventDefaultKeys.length > 0) {
3206
+ for (let i = 0; i < preventDefaultKeys.length; i++) {
3207
+ const k = preventDefaultKeys[i];
3208
+ if (passiveEvents.has(normalizeJsxEventName(k.slice(PREVENT_DEFAULT.length)))) {
3209
+ if (!copied) {
3210
+ mutableProps = { ...mutableProps };
3211
+ copied = true;
3212
+ }
3213
+ delete mutableProps[k];
3214
+ }
3215
+ }
3216
+ }
3217
+ return mutableProps;
3218
+ };
3219
+ const getPassiveEventKey = (key) => {
3220
+ if (key.startsWith('on') && key.endsWith('$')) {
3221
+ return normalizeJsxEventName(key.slice(2, -1));
3222
+ }
3223
+ if (key.startsWith('window:on') && key.endsWith('$')) {
3224
+ return normalizeJsxEventName(key.slice(9, -1));
3225
+ }
3226
+ if (key.startsWith('document:on') && key.endsWith('$')) {
3227
+ return normalizeJsxEventName(key.slice(11, -1));
3228
+ }
3229
+ return null;
3230
+ };
3231
+ const convertJsxEventProps = (props, eventKeys, keyOrder, passiveEvents, canMutate = false) => {
3232
+ let mutableProps = props;
3233
+ let copied = canMutate;
3234
+ for (let i = 0; i < eventKeys.length; i++) {
3235
+ const k = eventKeys[i];
3236
+ const passiveEventKey = getPassiveEventKey(k);
3237
+ const attr = jsxEventToHtmlAttribute(k, passiveEvents.has(passiveEventKey));
3238
+ if (attr) {
3239
+ if (!copied) {
3240
+ mutableProps = { ...mutableProps };
3241
+ copied = true;
3242
+ }
3243
+ const attrIndex = keyOrder.get(attr);
3244
+ if (attrIndex === undefined || attrIndex < keyOrder.get(k)) {
3245
+ mutableProps[attr] = mutableProps[k];
3246
+ }
3247
+ delete mutableProps[k];
3248
+ }
3249
+ }
3250
+ return mutableProps;
3251
+ };
3112
3252
  /**
3113
3253
  * Create a JSXNode with the properties fully split into variable and constant parts, and children
3114
3254
  * separated out. Furthermore, the varProps must be a sorted object, that is, the keys must be
@@ -3154,20 +3294,28 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
3154
3294
  let bindCheckedSignal = null;
3155
3295
  // Apply transformations for native HTML elements only
3156
3296
  if (typeof type === 'string') {
3157
- // Transform event names (onClick$ -> q-e:click)
3297
+ const passiveEvents = new Set();
3298
+ const constEventKeys = [];
3299
+ const varEventKeys = [];
3300
+ const constPassiveKeys = [];
3301
+ const varPassiveKeys = [];
3302
+ const constPreventDefaultKeys = [];
3303
+ const varPreventDefaultKeys = [];
3304
+ const constKeyOrder = new Map();
3305
+ const varKeyOrder = new Map();
3158
3306
  if (constProps) {
3159
- const processedKeys = new Set();
3307
+ let index = 0;
3160
3308
  for (const k in constProps) {
3161
- const attr = jsxEventToHtmlAttribute(k);
3162
- if (attr) {
3163
- if (!constPropsCopied) {
3164
- constProps = { ...constProps };
3165
- constPropsCopied = true;
3166
- }
3167
- if (!_hasOwnProperty$1.call(constProps, attr) || processedKeys.has(attr)) {
3168
- constProps[attr] = constProps[k];
3169
- }
3170
- delete constProps[k];
3309
+ constKeyOrder.set(k, index++);
3310
+ if (k.startsWith(PASSIVE)) {
3311
+ constPassiveKeys.push(k);
3312
+ passiveEvents.add(normalizeJsxEventName(k.slice(PASSIVE.length)));
3313
+ }
3314
+ else if (k.startsWith(PREVENT_DEFAULT)) {
3315
+ constPreventDefaultKeys.push(k);
3316
+ }
3317
+ else if (getPassiveEventKey(k) !== null) {
3318
+ constEventKeys.push(k);
3171
3319
  }
3172
3320
  else if (k === BIND_CHECKED) {
3173
3321
  // Set flag, will process after walk
@@ -3177,24 +3325,21 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
3177
3325
  // Set flag, will process after walk
3178
3326
  bindValueSignal = constProps[k];
3179
3327
  }
3180
- processedKeys.add(k);
3181
3328
  }
3182
3329
  }
3183
3330
  if (varProps) {
3184
- const processedKeys = new Set();
3331
+ let index = 0;
3185
3332
  for (const k in varProps) {
3186
- const attr = jsxEventToHtmlAttribute(k);
3187
- if (attr) {
3188
- if (!varPropsCopied) {
3189
- varProps = { ...varProps };
3190
- varPropsCopied = true;
3191
- }
3192
- // Transform event name in place
3193
- if (!_hasOwnProperty$1.call(varProps, attr) || processedKeys.has(attr)) {
3194
- varProps[attr] = varProps[k];
3195
- }
3196
- delete varProps[k];
3197
- toSort = true;
3333
+ varKeyOrder.set(k, index++);
3334
+ if (k.startsWith(PASSIVE)) {
3335
+ varPassiveKeys.push(k);
3336
+ passiveEvents.add(normalizeJsxEventName(k.slice(PASSIVE.length)));
3337
+ }
3338
+ else if (k.startsWith(PREVENT_DEFAULT)) {
3339
+ varPreventDefaultKeys.push(k);
3340
+ }
3341
+ else if (getPassiveEventKey(k) !== null) {
3342
+ varEventKeys.push(k);
3198
3343
  }
3199
3344
  else if (k === BIND_CHECKED) {
3200
3345
  // Set flag, will process after walk
@@ -3204,9 +3349,23 @@ const _jsxSplit = (type, varProps, constProps, children, flags, key, dev) => {
3204
3349
  // Set flag, will process after walk
3205
3350
  bindValueSignal = varProps[k];
3206
3351
  }
3207
- processedKeys.add(k);
3208
3352
  }
3209
3353
  }
3354
+ if (constProps) {
3355
+ const originalConstProps = constProps;
3356
+ constProps = removePassiveMarkers(constProps, constPassiveKeys, constPreventDefaultKeys, passiveEvents, constPropsCopied);
3357
+ constPropsCopied = constPropsCopied || constProps !== originalConstProps;
3358
+ constProps = convertJsxEventProps(constProps, constEventKeys, constKeyOrder, passiveEvents, constPropsCopied);
3359
+ constPropsCopied = constPropsCopied || constProps !== originalConstProps;
3360
+ }
3361
+ if (varProps) {
3362
+ const originalVarProps = varProps;
3363
+ varProps = removePassiveMarkers(varProps, varPassiveKeys, varPreventDefaultKeys, passiveEvents, varPropsCopied);
3364
+ varPropsCopied = varPropsCopied || varProps !== originalVarProps;
3365
+ varProps = convertJsxEventProps(varProps, varEventKeys, varKeyOrder, passiveEvents, varPropsCopied);
3366
+ varPropsCopied = varPropsCopied || varProps !== originalVarProps;
3367
+ toSort = toSort || varEventKeys.length > 0;
3368
+ }
3210
3369
  // Handle bind:* - only in varProps, bind:* should be moved to varProps
3211
3370
  if (bindCheckedSignal || bindValueSignal) {
3212
3371
  if (!varPropsCopied) {
@@ -3518,11 +3677,13 @@ function addUseOnEvents(jsx, useOnEvents) {
3518
3677
  }
3519
3678
  else {
3520
3679
  if (isDev) {
3680
+ const sourceLocation = getUseOnSourceLocation(useOnEvents[key].qrls);
3521
3681
  logWarn('You are trying to add an event "' +
3522
3682
  key +
3523
3683
  '" using `useOn` hook, ' +
3524
3684
  'but a node to which you can add an event is not found. ' +
3525
- 'Please make sure that the component has a valid element node. ');
3685
+ 'Please make sure that the component outputs a DOM element.' +
3686
+ (sourceLocation ? ` Offending \`useOn\`: ${sourceLocation}.` : ''));
3526
3687
  }
3527
3688
  continue;
3528
3689
  }
@@ -3531,11 +3692,12 @@ function addUseOnEvents(jsx, useOnEvents) {
3531
3692
  if (targetElement.type === 'script' && key === qVisibleEvent) {
3532
3693
  eventKey = 'q-d:qinit';
3533
3694
  if (isDev) {
3534
- logWarn('You are trying to add an event "' +
3535
- key +
3536
- '" using the `useVisibleTask$` hook with the "intersection-observer" strategy, ' +
3537
- 'but a node to which you can add an event is not found. ' +
3538
- 'Using "document-ready" or "document-idle" instead.');
3695
+ const sourceLocation = getUseOnSourceLocation(useOnEvents[key].qrls);
3696
+ logWarn(`You are trying to add the event "${key}" ` +
3697
+ 'using the `useVisibleTask$` hook with the "intersection-observer" strategy, ' +
3698
+ 'but this only works when the component outputs a DOM element. Falling back to ' +
3699
+ '"document-ready" instead.' +
3700
+ (sourceLocation ? ` Offending \`useVisibleTask$\`: ${sourceLocation}.` : ''));
3539
3701
  }
3540
3702
  }
3541
3703
  addUseOnEvent(targetElement, eventKey, useOnEvents[key]);
@@ -3545,6 +3707,21 @@ function addUseOnEvents(jsx, useOnEvents) {
3545
3707
  return jsxResult;
3546
3708
  });
3547
3709
  }
3710
+ function getUseOnSourceLocation(eventQrls) {
3711
+ for (let i = 0; i < eventQrls.length; i++) {
3712
+ const eventQrl = eventQrls[i];
3713
+ const task = eventQrl?.getCaptured()?.[0];
3714
+ if (isTask(task)) {
3715
+ const dev = task.$qrl$.dev;
3716
+ if (dev?.file) {
3717
+ return typeof dev.lo === 'number' && typeof dev.hi === 'number'
3718
+ ? `${dev.file}:${dev.lo}-${dev.hi}`
3719
+ : dev.file;
3720
+ }
3721
+ }
3722
+ }
3723
+ return null;
3724
+ }
3548
3725
  /**
3549
3726
  * Adds an event to the JSX element.
3550
3727
  *
@@ -3556,14 +3733,15 @@ function addUseOnEvent(jsxElement, key, value) {
3556
3733
  // These handlers are always there, so they go in constProps
3557
3734
  const props = (jsxElement.constProps ||= {});
3558
3735
  const propValue = props[key];
3736
+ const qrls = value.qrls;
3559
3737
  if (propValue == null) {
3560
- props[key] = value;
3738
+ props[key] = qrls;
3561
3739
  }
3562
3740
  else if (Array.isArray(propValue)) {
3563
- propValue.push(...value);
3741
+ propValue.push(...qrls);
3564
3742
  }
3565
3743
  else {
3566
- props[key] = [propValue, ...value];
3744
+ props[key] = [propValue, ...qrls];
3567
3745
  }
3568
3746
  const varProp = jsxElement.varProps[key];
3569
3747
  if (varProp) {
@@ -3572,10 +3750,28 @@ function addUseOnEvent(jsxElement, key, value) {
3572
3750
  propValue.push(...props[key]);
3573
3751
  }
3574
3752
  else {
3575
- jsxElement.varProps[key] = [propValue, ...value];
3753
+ jsxElement.varProps[key] = [propValue, ...qrls];
3576
3754
  }
3577
3755
  props[key] = undefined;
3578
3756
  }
3757
+ const capture = value.capture;
3758
+ const preventdefault = value.preventdefault;
3759
+ const stoppropagation = value.stoppropagation;
3760
+ if (!capture && !preventdefault && !stoppropagation) {
3761
+ return;
3762
+ }
3763
+ const [, eventName] = getEventDataFromHtmlAttribute(key);
3764
+ capture && addUseOnModifier(jsxElement, eventName, 'capture');
3765
+ preventdefault && addUseOnModifier(jsxElement, eventName, 'preventdefault');
3766
+ stoppropagation && addUseOnModifier(jsxElement, eventName, 'stoppropagation');
3767
+ }
3768
+ function addUseOnModifier(jsxElement, eventName, modifier) {
3769
+ const key = `${modifier}:${eventName}`;
3770
+ const varProps = jsxElement.varProps;
3771
+ if (varProps === EMPTY_OBJ) {
3772
+ jsxElement.varProps = {};
3773
+ }
3774
+ jsxElement.varProps[key] = true;
3579
3775
  }
3580
3776
  /**
3581
3777
  * Finds the first element node in the JSX output.
@@ -6080,13 +6276,18 @@ function scheduleYield() {
6080
6276
  *
6081
6277
  * @param options - Walk options (time budget, etc.)
6082
6278
  */
6083
- function processCursorQueue(options = {
6084
- timeBudget: 1000 / 60, // 60fps
6085
- }) {
6279
+ function processCursorQueue() {
6086
6280
  isNextTickScheduled = false;
6281
+ const startTime = performance.now();
6282
+ const yieldTime = startTime + 15; // 16 ms = 60 FPS, use 15 to yield slightly before next frame
6087
6283
  let cursor = null;
6088
6284
  while ((cursor = getHighestPriorityCursor())) {
6089
- walkCursor(cursor, options);
6285
+ if (walkCursor(cursor, yieldTime)) {
6286
+ // Cursor overran time budget, yield to browser
6287
+ // Note that each tick we process at least one thing
6288
+ scheduleYield();
6289
+ return;
6290
+ }
6090
6291
  }
6091
6292
  }
6092
6293
  /**
@@ -6105,13 +6306,12 @@ function processCursorQueue(options = {
6105
6306
  * Note that there is only one walker for all containers in the app with the same Qwik version.
6106
6307
  *
6107
6308
  * @param cursor - The cursor to walk
6108
- * @param options - Walk options (time budget, etc.)
6109
- * @returns Walk result indicating completion status
6309
+ * @param until - Time budget (timestamp to yield by)
6310
+ * @returns `true` if the walk was paused due to time budget (do not process more cursors in this
6311
+ * tick)
6110
6312
  */
6111
- function walkCursor(cursor, options) {
6112
- const { timeBudget } = options;
6313
+ function walkCursor(cursor, until) {
6113
6314
  const isRunningOnServer = import.meta.env.TEST ? isServerPlatform() : isServer;
6114
- const startTime = performance.now();
6115
6315
  const cursorData = getCursorData(cursor);
6116
6316
  // Check if cursor is blocked by a promise
6117
6317
  const blockingPromise = cursorData.promise;
@@ -6212,13 +6412,8 @@ function walkCursor(cursor, options) {
6212
6412
  return;
6213
6413
  }
6214
6414
  // Check time budget (only for DOM, not SSR)
6215
- if (isBrowser$1) {
6216
- const elapsed = performance.now() - startTime;
6217
- if (elapsed >= timeBudget) {
6218
- // Schedule continuation as macrotask to actually yield to browser
6219
- scheduleYield();
6220
- return;
6221
- }
6415
+ if (performance.now() >= until) {
6416
+ return true;
6222
6417
  }
6223
6418
  }
6224
6419
  isDev &&
@@ -6835,6 +7030,7 @@ const vnode_newText = (textNode, textContent) => {
6835
7030
  isDev && assertFalse(vnode_isVirtualVNode(vnode), 'Incorrect format of TextVNode.');
6836
7031
  return vnode;
6837
7032
  };
7033
+ /** @internal */
6838
7034
  const vnode_newVirtual = () => {
6839
7035
  const vnode = new VirtualVNode(null, 2 /* VNodeFlags.Virtual */ | (-1 << 12 /* VNodeFlagsIndex.shift */), // Flags
6840
7036
  null, null, null, null, null, null);
@@ -6847,6 +7043,7 @@ const vnode_newVirtual = () => {
6847
7043
  const vnode_isVNode = (vNode) => {
6848
7044
  return vNode instanceof VNode;
6849
7045
  };
7046
+ /** @internal */
6850
7047
  const vnode_isElementVNode = (vNode) => {
6851
7048
  return (vNode.flags & 1 /* VNodeFlags.Element */) === 1 /* VNodeFlags.Element */;
6852
7049
  };
@@ -6905,6 +7102,7 @@ const vnode_getNodeTypeName = (vNode) => {
6905
7102
  }
6906
7103
  return '<unknown>';
6907
7104
  };
7105
+ /** @internal */
6908
7106
  const vnode_getProp = (vNode, key, getObject) => {
6909
7107
  if (vnode_isElementVNode(vNode) || vnode_isVirtualVNode(vNode)) {
6910
7108
  const value = vNode.props?.[key] ?? null;
@@ -6917,6 +7115,7 @@ const vnode_getProp = (vNode, key, getObject) => {
6917
7115
  }
6918
7116
  return null;
6919
7117
  };
7118
+ /** @internal */
6920
7119
  const vnode_setProp = (vNode, key, value) => {
6921
7120
  if (value == null && vNode.props) {
6922
7121
  delete vNode.props[key];
@@ -7308,6 +7507,7 @@ const vnode_getChildWithIdx = (vNode, childIdx) => {
7308
7507
  return child;
7309
7508
  };
7310
7509
  const vNodeStack = [];
7510
+ /** @internal */
7311
7511
  const vnode_getVNodeForChildNode = (vNode, childElement) => {
7312
7512
  ensureElementVNode(vNode);
7313
7513
  let child = vnode_getFirstChild(vNode);
@@ -7621,6 +7821,7 @@ const vnode_inflateProjectionTrailingText = (journal, projection) => {
7621
7821
  vnode_ensureTextInflated(journal, last);
7622
7822
  }
7623
7823
  };
7824
+ /** @internal */
7624
7825
  const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
7625
7826
  if (vnode_isElementOrTextVNode(newChild)) {
7626
7827
  vnode_insertElementBefore(journal, parent, newChild, insertBefore);
@@ -7644,6 +7845,7 @@ const vnode_getDomParentVNode = (vnode, includeProjection) => {
7644
7845
  }
7645
7846
  return vnode;
7646
7847
  };
7848
+ /** @internal */
7647
7849
  const vnode_remove = (journal, vParent, vToRemove, removeDOM) => {
7648
7850
  isDev && assertEqual(vParent, vToRemove.parent, 'Parent mismatch.');
7649
7851
  if (vnode_isTextVNode(vToRemove)) {
@@ -7712,6 +7914,7 @@ const vnode_truncate = (journal, vParent, vDelete, removeDOM = true) => {
7712
7914
  vParent.lastChild = vPrevious;
7713
7915
  };
7714
7916
  //////////////////////////////////////////////////////////////////////////////////////////////////////
7917
+ /** @internal */
7715
7918
  const vnode_getElementName = (vnode) => {
7716
7919
  const elementVNode = ensureElementVNode(vnode);
7717
7920
  let elementName = elementVNode.elementName;
@@ -9115,6 +9318,95 @@ function getEffects(target, prop, storeEffects) {
9115
9318
  return effectsToTrigger;
9116
9319
  }
9117
9320
 
9321
+ /** Used to represent an undefined value that must be serialized */
9322
+ const explicitUndefined = Symbol('undefined');
9323
+ // Used for allocate, make sure they are in sync with Constants
9324
+ const _constants = [
9325
+ undefined,
9326
+ null,
9327
+ true,
9328
+ false,
9329
+ '',
9330
+ EMPTY_ARRAY,
9331
+ EMPTY_OBJ,
9332
+ NEEDS_COMPUTATION,
9333
+ STORE_ALL_PROPS,
9334
+ _UNINITIALIZED,
9335
+ Slot,
9336
+ Fragment,
9337
+ NaN,
9338
+ Infinity,
9339
+ -Infinity,
9340
+ Number.MAX_SAFE_INTEGER,
9341
+ Number.MAX_SAFE_INTEGER - 1,
9342
+ Number.MIN_SAFE_INTEGER,
9343
+ ];
9344
+ // Used for dumpState, make sure they are in sync with Constants
9345
+ const _constantNames = [
9346
+ 'undefined',
9347
+ 'null',
9348
+ 'true',
9349
+ 'false',
9350
+ "''",
9351
+ 'EMPTY_ARRAY',
9352
+ 'EMPTY_OBJ',
9353
+ 'NEEDS_COMPUTATION',
9354
+ 'STORE_ALL_PROPS',
9355
+ '_UNINITIALIZED',
9356
+ 'Slot',
9357
+ 'Fragment',
9358
+ 'NaN',
9359
+ 'Infinity',
9360
+ '-Infinity',
9361
+ 'MAX_SAFE_INTEGER',
9362
+ 'MAX_SAFE_INTEGER-1',
9363
+ 'MIN_SAFE_INTEGER',
9364
+ ];
9365
+ // Used for dumpState, make sure they are in sync with TypeIds
9366
+ const _typeIdNames = [
9367
+ 'Plain',
9368
+ 'RootRef',
9369
+ 'ForwardRef',
9370
+ 'Constant',
9371
+ 'Array',
9372
+ 'Object',
9373
+ 'URL',
9374
+ 'Date',
9375
+ 'Regex',
9376
+ 'QRL',
9377
+ 'VNode',
9378
+ 'RefVNode',
9379
+ 'BigInt',
9380
+ 'URLSearchParams',
9381
+ 'ForwardRefs',
9382
+ 'TemporalDuration',
9383
+ 'TemporalInstant',
9384
+ 'TemporalPlainDate',
9385
+ 'TemporalPlainDateTime',
9386
+ 'TemporalPlainMonthDay',
9387
+ 'TemporalPlainTime',
9388
+ 'TemporalPlainYearMonth',
9389
+ 'TemporalZonedDateTime',
9390
+ 'Error',
9391
+ 'Promise',
9392
+ 'Set',
9393
+ 'Map',
9394
+ 'Uint8Array',
9395
+ 'Task',
9396
+ 'Component',
9397
+ 'Signal',
9398
+ 'WrappedSignal',
9399
+ 'ComputedSignal',
9400
+ 'AsyncSignal',
9401
+ 'SerializerSignal',
9402
+ 'Store',
9403
+ 'FormData',
9404
+ 'JSXNode',
9405
+ 'PropsProxy',
9406
+ 'SubscriptionData',
9407
+ 'EffectSubscription',
9408
+ ];
9409
+
9118
9410
  function qrlToString(serializationContext, qrl, raw) {
9119
9411
  let symbol = qrl.$symbol$;
9120
9412
  let chunk = qrl.$chunk$;
@@ -9211,6 +9503,8 @@ class Serializer {
9211
9503
  $parent$;
9212
9504
  $qrlMap$ = new Map();
9213
9505
  $writer$;
9506
+ /** We need to determine this at runtime because polyfills may not be loaded a module load time */
9507
+ $hasTemporal$ = typeof Temporal !== 'undefined';
9214
9508
  constructor($serializationContext$) {
9215
9509
  this.$serializationContext$ = $serializationContext$;
9216
9510
  this.$writer$ = $serializationContext$.$writer$;
@@ -9254,6 +9548,29 @@ class Serializer {
9254
9548
  }
9255
9549
  return false;
9256
9550
  }
9551
+ maybeNumericObjectKey$(key) {
9552
+ if (key.length === 0 || key.length >= 8) {
9553
+ return key;
9554
+ }
9555
+ let i = 0;
9556
+ if (key.charCodeAt(0) === 45) {
9557
+ if (key.length === 1) {
9558
+ return key;
9559
+ }
9560
+ i = 1;
9561
+ }
9562
+ const first = key.charCodeAt(i);
9563
+ if (first < 49 || first > 57) {
9564
+ return key;
9565
+ }
9566
+ for (i++; i < key.length; i++) {
9567
+ const c = key.charCodeAt(i);
9568
+ if (c < 48 || c > 57) {
9569
+ return key;
9570
+ }
9571
+ }
9572
+ return Number(key);
9573
+ }
9257
9574
  /** Output a type,value pair. If the value is an array, it calls writeValue on each item. */
9258
9575
  output(type, value, keepUndefined) {
9259
9576
  if (typeof value === 'number') {
@@ -9381,6 +9698,9 @@ class Serializer {
9381
9698
  else if (value === _UNINITIALIZED) {
9382
9699
  this.output(3 /* TypeIds.Constant */, 9 /* Constants.UNINITIALIZED */);
9383
9700
  }
9701
+ else if (value === explicitUndefined) {
9702
+ this.output(3 /* TypeIds.Constant */, 0 /* Constants.Undefined */);
9703
+ }
9384
9704
  break;
9385
9705
  case 'function':
9386
9706
  if (value === Slot) {
@@ -9418,7 +9738,7 @@ class Serializer {
9418
9738
  else if (isQwikComponent(value)) {
9419
9739
  const [qrl] = value[SERIALIZABLE_STATE];
9420
9740
  this.$serializationContext$.$renderSymbols$.add(qrl.$symbol$);
9421
- this.output(21 /* TypeIds.Component */, [qrl]);
9741
+ this.output(29 /* TypeIds.Component */, [qrl]);
9422
9742
  }
9423
9743
  else {
9424
9744
  throw qError(34 /* QError.serializeErrorCannotSerializeFunction */, [value.toString()]);
@@ -9456,7 +9776,7 @@ class Serializer {
9456
9776
  writeObjectValue(value) {
9457
9777
  if (isPropsProxy(value)) {
9458
9778
  const owner = value[_OWNER];
9459
- this.output(30 /* TypeIds.PropsProxy */, [
9779
+ this.output(38 /* TypeIds.PropsProxy */, [
9460
9780
  _serializationWeakRef(owner),
9461
9781
  owner.varProps,
9462
9782
  owner.constProps,
@@ -9464,13 +9784,15 @@ class Serializer {
9464
9784
  ]);
9465
9785
  }
9466
9786
  else if (value instanceof SubscriptionData) {
9467
- this.output(31 /* TypeIds.SubscriptionData */, [
9787
+ // TODO make everything optional or use two types
9788
+ this.output(39 /* TypeIds.SubscriptionData */, [
9468
9789
  value.data.$scopedStyleIdPrefix$,
9469
9790
  value.data.$isConst$,
9470
9791
  ]);
9471
9792
  }
9472
9793
  else if (value instanceof EffectSubscription) {
9473
- this.output(32 /* TypeIds.EffectSubscription */, [value.consumer, value.property, value.data]);
9794
+ // TODO no data if [null, true]
9795
+ this.output(40 /* TypeIds.EffectSubscription */, [value.consumer, value.property, value.data]);
9474
9796
  }
9475
9797
  else if (isStore(value)) {
9476
9798
  const storeHandler = getStoreHandler(value);
@@ -9490,13 +9812,13 @@ class Serializer {
9490
9812
  while (out[out.length - 1] === undefined) {
9491
9813
  out.pop();
9492
9814
  }
9493
- this.output(27 /* TypeIds.Store */, out);
9815
+ this.output(35 /* TypeIds.Store */, out);
9494
9816
  }
9495
9817
  else if (isSerializerObj(value)) {
9496
9818
  const result = value[SerializerSymbol](value);
9497
9819
  if (isPromise(result)) {
9498
9820
  const forwardRef = this.resolvePromise(result, (resolved, resolvedValue) => {
9499
- return new PromiseResult(26 /* TypeIds.SerializerSignal */, resolved, resolvedValue, undefined, undefined);
9821
+ return new PromiseResult(34 /* TypeIds.SerializerSignal */, resolved, resolvedValue, undefined, undefined);
9500
9822
  });
9501
9823
  this.output(2 /* TypeIds.ForwardRef */, forwardRef);
9502
9824
  }
@@ -9517,7 +9839,7 @@ class Serializer {
9517
9839
  if (Object.prototype.hasOwnProperty.call(value, key)) {
9518
9840
  const subVal = value[key];
9519
9841
  if (!fastSkipSerialize(subVal)) {
9520
- out.push(key, subVal);
9842
+ out.push(this.maybeNumericObjectKey$(key), subVal);
9521
9843
  }
9522
9844
  }
9523
9845
  }
@@ -9533,17 +9855,17 @@ class Serializer {
9533
9855
  const maybeValue = getCustomSerializerPromise(value, value.$untrackedValue$);
9534
9856
  if (isPromise(maybeValue)) {
9535
9857
  const forwardRefId = this.resolvePromise(maybeValue, (resolved, resolvedValue) => {
9536
- return new PromiseResult(26 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
9858
+ return new PromiseResult(34 /* TypeIds.SerializerSignal */, resolved, resolvedValue, value.$effects$, value.$computeQrl$);
9537
9859
  });
9538
9860
  this.output(2 /* TypeIds.ForwardRef */, forwardRefId);
9539
9861
  }
9540
9862
  else {
9541
- this.output(26 /* TypeIds.SerializerSignal */, [value.$computeQrl$, value.$effects$, maybeValue]);
9863
+ this.output(34 /* TypeIds.SerializerSignal */, [value.$computeQrl$, value.$effects$, maybeValue]);
9542
9864
  }
9543
9865
  return;
9544
9866
  }
9545
9867
  if (value instanceof WrappedSignalImpl) {
9546
- this.output(23 /* TypeIds.WrappedSignal */, [
9868
+ this.output(31 /* TypeIds.WrappedSignal */, [
9547
9869
  ...serializeWrappingFn(this.$serializationContext$, value),
9548
9870
  value.$flags$,
9549
9871
  value.$hostElement$,
@@ -9557,7 +9879,7 @@ class Serializer {
9557
9879
  const isInvalid = value.$flags$ & 1 /* SignalFlags.INVALID */;
9558
9880
  const isSkippable = fastSkipSerialize(value.$untrackedValue$);
9559
9881
  const isAsync = value instanceof AsyncSignalImpl;
9560
- const interval = isAsync && value.$interval$ !== 0 ? value.$interval$ : undefined;
9882
+ const expires = isAsync && value.$expires$ !== 0 ? value.$expires$ : undefined;
9561
9883
  const concurrency = isAsync && value.$concurrency$ !== 1 ? value.$concurrency$ : undefined;
9562
9884
  const timeout = isAsync && value.$timeoutMs$ !== 0 ? value.$timeoutMs$ : undefined;
9563
9885
  // Send the flags but remove the serialization bits and default to 0 when undefined
@@ -9578,36 +9900,31 @@ class Serializer {
9578
9900
  out.push(value.$loadingEffects$, value.$errorEffects$, value.$untrackedError$);
9579
9901
  out.push(asyncFlags || undefined);
9580
9902
  }
9581
- let keepUndefined = false;
9582
9903
  if (v !== NEEDS_COMPUTATION ||
9583
- interval !== undefined ||
9904
+ expires !== undefined ||
9584
9905
  concurrency !== undefined ||
9585
9906
  timeout !== undefined) {
9586
- out.push(v);
9587
- if (v === undefined) {
9588
- /**
9589
- * If value is undefined, we need to keep it in the output. If we don't do that, later
9590
- * during resuming, the value will be set to symbol(invalid) with flag invalid, and
9591
- * thats is incorrect.
9592
- */
9593
- keepUndefined = true;
9594
- }
9907
+ /**
9908
+ * If value is undefined, we need to keep it in the output. If we don't do that, later
9909
+ * during resuming, the value will be set to symbol(invalid) with flag invalid, and thats
9910
+ * is incorrect.
9911
+ */
9912
+ out.push(v === undefined ? explicitUndefined : v);
9595
9913
  }
9596
9914
  if (isAsync) {
9597
- out.push(interval);
9915
+ out.push(expires);
9598
9916
  out.push(concurrency);
9599
9917
  out.push(timeout);
9600
9918
  }
9601
- this.output(isAsync ? 25 /* TypeIds.AsyncSignal */ : 24 /* TypeIds.ComputedSignal */, out, keepUndefined);
9919
+ this.output(isAsync ? 33 /* TypeIds.AsyncSignal */ : 32 /* TypeIds.ComputedSignal */, out);
9602
9920
  }
9603
9921
  else {
9604
9922
  const v = value.$untrackedValue$;
9605
- const keepUndefined = v === undefined;
9606
- const out = [v];
9923
+ const out = [v === undefined ? explicitUndefined : v];
9607
9924
  if (value.$effects$) {
9608
9925
  out.push(...value.$effects$);
9609
9926
  }
9610
- this.output(22 /* TypeIds.Signal */, out, keepUndefined);
9927
+ this.output(30 /* TypeIds.Signal */, out);
9611
9928
  }
9612
9929
  }
9613
9930
  else if (value instanceof URL) {
@@ -9616,6 +9933,30 @@ class Serializer {
9616
9933
  else if (value instanceof Date) {
9617
9934
  this.output(7 /* TypeIds.Date */, Number.isNaN(value.valueOf()) ? '' : value.valueOf());
9618
9935
  }
9936
+ else if (this.$hasTemporal$ && value instanceof Temporal.Duration) {
9937
+ this.output(15 /* TypeIds.TemporalDuration */, value.toJSON());
9938
+ }
9939
+ else if (this.$hasTemporal$ && value instanceof Temporal.Instant) {
9940
+ this.output(16 /* TypeIds.TemporalInstant */, value.toJSON());
9941
+ }
9942
+ else if (this.$hasTemporal$ && value instanceof Temporal.PlainDate) {
9943
+ this.output(17 /* TypeIds.TemporalPlainDate */, value.toJSON());
9944
+ }
9945
+ else if (this.$hasTemporal$ && value instanceof Temporal.PlainDateTime) {
9946
+ this.output(18 /* TypeIds.TemporalPlainDateTime */, value.toJSON());
9947
+ }
9948
+ else if (this.$hasTemporal$ && value instanceof Temporal.PlainMonthDay) {
9949
+ this.output(19 /* TypeIds.TemporalPlainMonthDay */, value.toJSON());
9950
+ }
9951
+ else if (this.$hasTemporal$ && value instanceof Temporal.PlainTime) {
9952
+ this.output(20 /* TypeIds.TemporalPlainTime */, value.toJSON());
9953
+ }
9954
+ else if (this.$hasTemporal$ && value instanceof Temporal.PlainYearMonth) {
9955
+ this.output(21 /* TypeIds.TemporalPlainYearMonth */, value.toJSON());
9956
+ }
9957
+ else if (this.$hasTemporal$ && value instanceof Temporal.ZonedDateTime) {
9958
+ this.output(22 /* TypeIds.TemporalZonedDateTime */, value.toJSON());
9959
+ }
9619
9960
  else if (value instanceof RegExp) {
9620
9961
  this.output(8 /* TypeIds.Regex */, value.toString());
9621
9962
  }
@@ -9627,7 +9968,7 @@ class Serializer {
9627
9968
  if (isDev) {
9628
9969
  out.push('stack', value.stack);
9629
9970
  }
9630
- this.output(15 /* TypeIds.Error */, out);
9971
+ this.output(23 /* TypeIds.Error */, out);
9631
9972
  }
9632
9973
  else if (this.$serializationContext$.$isSsrNode$(value)) {
9633
9974
  const rootIndex = this.$serializationContext$.$addRoot$(value);
@@ -9659,20 +10000,20 @@ class Serializer {
9659
10000
  array.push(k, v);
9660
10001
  }
9661
10002
  }
9662
- this.output(28 /* TypeIds.FormData */, array);
10003
+ this.output(36 /* TypeIds.FormData */, array);
9663
10004
  }
9664
10005
  else if (value instanceof URLSearchParams) {
9665
10006
  this.output(13 /* TypeIds.URLSearchParams */, value.toString());
9666
10007
  }
9667
10008
  else if (value instanceof Set) {
9668
- this.output(17 /* TypeIds.Set */, [...value.values()]);
10009
+ this.output(25 /* TypeIds.Set */, [...value.values()]);
9669
10010
  }
9670
10011
  else if (value instanceof Map) {
9671
10012
  const combined = [];
9672
10013
  for (const [k, v] of value.entries()) {
9673
10014
  combined.push(k, v);
9674
10015
  }
9675
- this.output(18 /* TypeIds.Map */, combined);
10016
+ this.output(26 /* TypeIds.Map */, combined);
9676
10017
  }
9677
10018
  else if (isJSXNode(value)) {
9678
10019
  const out = [
@@ -9686,25 +10027,25 @@ class Serializer {
9686
10027
  while (out[out.length - 1] === undefined) {
9687
10028
  out.pop();
9688
10029
  }
9689
- this.output(29 /* TypeIds.JSXNode */, out);
10030
+ this.output(37 /* TypeIds.JSXNode */, out);
9690
10031
  }
9691
10032
  else if (value instanceof Task) {
9692
10033
  const out = [value.$qrl$, value.$flags$, value.$index$, value.$el$, value.$state$];
9693
10034
  while (out[out.length - 1] === undefined) {
9694
10035
  out.pop();
9695
10036
  }
9696
- this.output(20 /* TypeIds.Task */, out);
10037
+ this.output(28 /* TypeIds.Task */, out);
9697
10038
  }
9698
10039
  else if (isPromise(value)) {
9699
10040
  const forwardRefId = this.resolvePromise(value, (resolved, resolvedValue) => {
9700
- return new PromiseResult(16 /* TypeIds.Promise */, resolved, resolvedValue);
10041
+ return new PromiseResult(24 /* TypeIds.Promise */, resolved, resolvedValue);
9701
10042
  });
9702
10043
  this.output(2 /* TypeIds.ForwardRef */, forwardRefId);
9703
10044
  }
9704
10045
  else if (value instanceof PromiseResult) {
9705
- if (value.$type$ === 26 /* TypeIds.SerializerSignal */) {
10046
+ if (value.$type$ === 34 /* TypeIds.SerializerSignal */) {
9706
10047
  if (value.$qrl$) {
9707
- this.output(26 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
10048
+ this.output(34 /* TypeIds.SerializerSignal */, [value.$qrl$, value.$effects$, value.$value$]);
9708
10049
  }
9709
10050
  else if (value.$resolved$) {
9710
10051
  // We replace ourselves with this value
@@ -9718,7 +10059,7 @@ class Serializer {
9718
10059
  }
9719
10060
  }
9720
10061
  else {
9721
- this.output(16 /* TypeIds.Promise */, [value.$resolved$, value.$value$]);
10062
+ this.output(24 /* TypeIds.Promise */, [value.$resolved$, value.$value$]);
9722
10063
  }
9723
10064
  }
9724
10065
  else if (value instanceof Uint8Array) {
@@ -9728,7 +10069,7 @@ class Serializer {
9728
10069
  buf += String.fromCharCode(value[i]);
9729
10070
  }
9730
10071
  const out = btoa(buf).replace(/=+$/, '');
9731
- this.output(19 /* TypeIds.Uint8Array */, out);
10072
+ this.output(27 /* TypeIds.Uint8Array */, out);
9732
10073
  }
9733
10074
  else if (value instanceof SerializationWeakRef) {
9734
10075
  const obj = value.$obj$;
@@ -10046,7 +10387,9 @@ DomRefConstructor, symbolToChunkResolver, setProp, storeProxyMap, writer) => {
10046
10387
  if (!writer) {
10047
10388
  const buffer = [];
10048
10389
  writer = {
10049
- write: (text) => buffer.push(text),
10390
+ write: (text) => {
10391
+ buffer.push(text);
10392
+ },
10050
10393
  toString: () => buffer.join(''),
10051
10394
  };
10052
10395
  }
@@ -10056,6 +10399,7 @@ DomRefConstructor, symbolToChunkResolver, setProp, storeProxyMap, writer) => {
10056
10399
 
10057
10400
  const getKeyVal = (value, key) => value[key];
10058
10401
  const canSerialize = (value, seen = new WeakSet()) => {
10402
+ const hasTemporal = typeof Temporal !== 'undefined';
10059
10403
  if (value == null ||
10060
10404
  typeof value === 'string' ||
10061
10405
  typeof value === 'number' ||
@@ -10118,6 +10462,30 @@ const canSerialize = (value, seen = new WeakSet()) => {
10118
10462
  else if (value instanceof Date) {
10119
10463
  return true;
10120
10464
  }
10465
+ else if (hasTemporal && value instanceof Temporal.Duration) {
10466
+ return true;
10467
+ }
10468
+ else if (hasTemporal && value instanceof Temporal.Instant) {
10469
+ return true;
10470
+ }
10471
+ else if (hasTemporal && value instanceof Temporal.PlainDate) {
10472
+ return true;
10473
+ }
10474
+ else if (hasTemporal && value instanceof Temporal.PlainDateTime) {
10475
+ return true;
10476
+ }
10477
+ else if (hasTemporal && value instanceof Temporal.PlainMonthDay) {
10478
+ return true;
10479
+ }
10480
+ else if (hasTemporal && value instanceof Temporal.PlainTime) {
10481
+ return true;
10482
+ }
10483
+ else if (hasTemporal && value instanceof Temporal.PlainYearMonth) {
10484
+ return true;
10485
+ }
10486
+ else if (hasTemporal && value instanceof Temporal.ZonedDateTime) {
10487
+ return true;
10488
+ }
10121
10489
  else if (value instanceof RegExp) {
10122
10490
  return true;
10123
10491
  }
@@ -10154,85 +10522,6 @@ const canSerialize = (value, seen = new WeakSet()) => {
10154
10522
  return false;
10155
10523
  };
10156
10524
 
10157
- // Used for allocate, make sure they are in sync with Constants
10158
- const _constants = [
10159
- undefined,
10160
- null,
10161
- true,
10162
- false,
10163
- '',
10164
- EMPTY_ARRAY,
10165
- EMPTY_OBJ,
10166
- NEEDS_COMPUTATION,
10167
- STORE_ALL_PROPS,
10168
- _UNINITIALIZED,
10169
- Slot,
10170
- Fragment,
10171
- NaN,
10172
- Infinity,
10173
- -Infinity,
10174
- Number.MAX_SAFE_INTEGER,
10175
- Number.MAX_SAFE_INTEGER - 1,
10176
- Number.MIN_SAFE_INTEGER,
10177
- ];
10178
- // Used for dumpState, make sure they are in sync with Constants
10179
- const _constantNames = [
10180
- 'undefined',
10181
- 'null',
10182
- 'true',
10183
- 'false',
10184
- "''",
10185
- 'EMPTY_ARRAY',
10186
- 'EMPTY_OBJ',
10187
- 'NEEDS_COMPUTATION',
10188
- 'STORE_ALL_PROPS',
10189
- '_UNINITIALIZED',
10190
- 'Slot',
10191
- 'Fragment',
10192
- 'NaN',
10193
- 'Infinity',
10194
- '-Infinity',
10195
- 'MAX_SAFE_INTEGER',
10196
- 'MAX_SAFE_INTEGER-1',
10197
- 'MIN_SAFE_INTEGER',
10198
- ];
10199
- // Used for dumpState, make sure they are in sync with TypeIds
10200
- const _typeIdNames = [
10201
- 'Plain',
10202
- 'RootRef',
10203
- 'ForwardRef',
10204
- 'Constant',
10205
- 'Array',
10206
- 'Object',
10207
- 'URL',
10208
- 'Date',
10209
- 'Regex',
10210
- 'QRL',
10211
- 'VNode',
10212
- 'RefVNode',
10213
- 'BigInt',
10214
- 'URLSearchParams',
10215
- 'ForwardRefs',
10216
- 'Error',
10217
- 'Promise',
10218
- 'Set',
10219
- 'Map',
10220
- 'Uint8Array',
10221
- 'Task',
10222
- 'Component',
10223
- 'Signal',
10224
- 'WrappedSignal',
10225
- 'ComputedSignal',
10226
- 'AsyncSignal',
10227
- 'SerializerSignal',
10228
- 'Store',
10229
- 'FormData',
10230
- 'JSXNode',
10231
- 'PropsProxy',
10232
- 'SubscriptionData',
10233
- 'EffectSubscription',
10234
- ];
10235
-
10236
10525
  const circularProofJson = (obj, indent) => {
10237
10526
  const seen = new WeakSet();
10238
10527
  return JSON.stringify(obj, (_, value) => {
@@ -10445,30 +10734,46 @@ const allocate = (container, typeId, value) => {
10445
10734
  }
10446
10735
  return qrl;
10447
10736
  }
10448
- case 20 /* TypeIds.Task */:
10737
+ case 28 /* TypeIds.Task */:
10449
10738
  return new Task(-1, -1, null, null, null, null);
10450
10739
  case 6 /* TypeIds.URL */:
10451
10740
  return new URL(value);
10452
10741
  case 7 /* TypeIds.Date */:
10453
10742
  return new Date(value);
10743
+ case 15 /* TypeIds.TemporalDuration */:
10744
+ return Temporal.Duration.from(value);
10745
+ case 16 /* TypeIds.TemporalInstant */:
10746
+ return Temporal.Instant.from(value);
10747
+ case 17 /* TypeIds.TemporalPlainDate */:
10748
+ return Temporal.PlainDate.from(value);
10749
+ case 18 /* TypeIds.TemporalPlainDateTime */:
10750
+ return Temporal.PlainDateTime.from(value);
10751
+ case 19 /* TypeIds.TemporalPlainMonthDay */:
10752
+ return Temporal.PlainMonthDay.from(value);
10753
+ case 20 /* TypeIds.TemporalPlainTime */:
10754
+ return Temporal.PlainTime.from(value);
10755
+ case 21 /* TypeIds.TemporalPlainYearMonth */:
10756
+ return Temporal.PlainYearMonth.from(value);
10757
+ case 22 /* TypeIds.TemporalZonedDateTime */:
10758
+ return Temporal.ZonedDateTime.from(value);
10454
10759
  case 8 /* TypeIds.Regex */:
10455
10760
  const idx = value.lastIndexOf('/');
10456
10761
  return new RegExp(value.slice(1, idx), value.slice(idx + 1));
10457
- case 15 /* TypeIds.Error */:
10762
+ case 23 /* TypeIds.Error */:
10458
10763
  return new Error();
10459
- case 21 /* TypeIds.Component */:
10764
+ case 29 /* TypeIds.Component */:
10460
10765
  return componentQrl(null);
10461
- case 22 /* TypeIds.Signal */:
10766
+ case 30 /* TypeIds.Signal */:
10462
10767
  return new SignalImpl(container, 0);
10463
- case 23 /* TypeIds.WrappedSignal */:
10768
+ case 31 /* TypeIds.WrappedSignal */:
10464
10769
  return new WrappedSignalImpl(container, null, null, null);
10465
- case 24 /* TypeIds.ComputedSignal */:
10770
+ case 32 /* TypeIds.ComputedSignal */:
10466
10771
  return new ComputedSignalImpl(container, null);
10467
- case 25 /* TypeIds.AsyncSignal */:
10468
- return new AsyncSignalImpl(container, null, undefined, { interval: 0 });
10469
- case 26 /* TypeIds.SerializerSignal */:
10772
+ case 33 /* TypeIds.AsyncSignal */:
10773
+ return new AsyncSignalImpl(container, null, undefined, {});
10774
+ case 34 /* TypeIds.SerializerSignal */:
10470
10775
  return new SerializerSignalImpl(container, null);
10471
- case 27 /* TypeIds.Store */: {
10776
+ case 35 /* TypeIds.Store */: {
10472
10777
  const data = value;
10473
10778
  // We need to allocate the store first, before we inflate its data, because the data can
10474
10779
  // reference the store itself (circular)
@@ -10487,17 +10792,17 @@ const allocate = (container, typeId, value) => {
10487
10792
  }
10488
10793
  case 13 /* TypeIds.URLSearchParams */:
10489
10794
  return new URLSearchParams(value);
10490
- case 28 /* TypeIds.FormData */:
10795
+ case 36 /* TypeIds.FormData */:
10491
10796
  return new FormData();
10492
- case 29 /* TypeIds.JSXNode */:
10797
+ case 37 /* TypeIds.JSXNode */:
10493
10798
  return new JSXNodeImpl(null, null, null, null, 0, null);
10494
10799
  case 12 /* TypeIds.BigInt */:
10495
10800
  return BigInt(value);
10496
- case 17 /* TypeIds.Set */:
10801
+ case 25 /* TypeIds.Set */:
10497
10802
  return new Set();
10498
- case 18 /* TypeIds.Map */:
10803
+ case 26 /* TypeIds.Map */:
10499
10804
  return new Map();
10500
- case 16 /* TypeIds.Promise */:
10805
+ case 24 /* TypeIds.Promise */:
10501
10806
  let resolve;
10502
10807
  let reject;
10503
10808
  const promise = new Promise((res, rej) => {
@@ -10508,13 +10813,13 @@ const allocate = (container, typeId, value) => {
10508
10813
  // Don't leave unhandled promise rejections
10509
10814
  promise.catch(() => { });
10510
10815
  return promise;
10511
- case 19 /* TypeIds.Uint8Array */:
10816
+ case 27 /* TypeIds.Uint8Array */:
10512
10817
  const encodedLength = value.length;
10513
10818
  const blocks = encodedLength >>> 2;
10514
10819
  const rest = encodedLength & 3;
10515
10820
  const decodedLength = blocks * 3 + (rest ? rest - 1 : 0);
10516
10821
  return new Uint8Array(decodedLength);
10517
- case 30 /* TypeIds.PropsProxy */:
10822
+ case 38 /* TypeIds.PropsProxy */:
10518
10823
  return createPropsProxy(null);
10519
10824
  case 10 /* TypeIds.VNode */:
10520
10825
  return retrieveVNodeOrDocument(container, value);
@@ -10552,9 +10857,9 @@ const allocate = (container, typeId, value) => {
10552
10857
  else {
10553
10858
  throw qError(17 /* QError.serializeErrorExpectedVNode */, [typeof vNode]);
10554
10859
  }
10555
- case 31 /* TypeIds.SubscriptionData */:
10860
+ case 39 /* TypeIds.SubscriptionData */:
10556
10861
  return new SubscriptionData({});
10557
- case 32 /* TypeIds.EffectSubscription */:
10862
+ case 40 /* TypeIds.EffectSubscription */:
10558
10863
  return new EffectSubscription(null, null, null, null);
10559
10864
  default:
10560
10865
  throw qError(18 /* QError.serializeErrorCannotAllocate */, [typeId]);
@@ -10737,23 +11042,31 @@ async function _walkJSX(ssr, value, options) {
10737
11042
  const enqueue = (value) => stack.push(value);
10738
11043
  const drain = async () => {
10739
11044
  while (stack.length) {
10740
- const value = stack.pop();
10741
- // Reference equality first (no prototype walk), then typeof
10742
- if (value === MaybeAsyncSignal) {
10743
- const trackFn = stack.pop();
10744
- await retryOnPromise(() => stack.push(trackFn()));
10745
- continue;
10746
- }
10747
- if (typeof value === 'function') {
10748
- if (value === Promise) {
10749
- stack.push(await stack.pop());
11045
+ try {
11046
+ const value = stack.pop();
11047
+ // Reference equality first (no prototype walk), then typeof
11048
+ if (value === MaybeAsyncSignal) {
11049
+ const trackFn = stack.pop();
11050
+ await retryOnPromise(() => stack.push(trackFn()));
11051
+ continue;
10750
11052
  }
10751
- else {
10752
- await value.apply(ssr);
11053
+ if (typeof value === 'function') {
11054
+ if (value === Promise) {
11055
+ stack.push(await stack.pop());
11056
+ }
11057
+ else {
11058
+ await value.apply(ssr);
11059
+ }
11060
+ continue;
11061
+ }
11062
+ processJSXNode(ssr, enqueue, value, options);
11063
+ }
11064
+ finally {
11065
+ const pendingFlush = ssr.streamHandler.waitForPendingFlush();
11066
+ if (isPromise(pendingFlush)) {
11067
+ await pendingFlush;
10753
11068
  }
10754
- continue;
10755
11069
  }
10756
- processJSXNode(ssr, enqueue, value, options);
10757
11070
  }
10758
11071
  };
10759
11072
  await drain();
@@ -10801,7 +11114,7 @@ function processJSXNode(ssr, enqueue, value, options) {
10801
11114
  currentStyleScoped: options.currentStyleScoped,
10802
11115
  parentComponentFrame: options.parentComponentFrame,
10803
11116
  });
10804
- ssr.streamHandler.flush();
11117
+ await ssr.streamHandler.flush();
10805
11118
  }
10806
11119
  });
10807
11120
  }
@@ -10898,7 +11211,7 @@ function processJSXNode(ssr, enqueue, value, options) {
10898
11211
  currentStyleScoped: options.currentStyleScoped,
10899
11212
  parentComponentFrame: options.parentComponentFrame,
10900
11213
  });
10901
- ssr.streamHandler.flush();
11214
+ await ssr.streamHandler.flush();
10902
11215
  },
10903
11216
  });
10904
11217
  }
@@ -10964,10 +11277,11 @@ function maybeAddPollingAsyncSignalToEagerResume(serializationCtx, signal) {
10964
11277
  // Unwrap if it's a WrappedSignalImpl
10965
11278
  const unwrappedSignal = signal instanceof WrappedSignalImpl ? signal.$unwrapIfSignal$() : signal;
10966
11279
  if (unwrappedSignal instanceof AsyncSignalImpl) {
10967
- const interval = unwrappedSignal.$interval$;
11280
+ const expires = unwrappedSignal.$expires$;
10968
11281
  // Don't check for $effects$ here - effects are added later during tracking.
10969
11282
  // The AsyncSignal's polling mechanism will check for effects before scheduling.
10970
- if (interval > 0) {
11283
+ // Only eager-resume for polling signals, not stale-only ones.
11284
+ if (expires && !(unwrappedSignal.$flags$ & 256 /* AsyncSignalFlags.NO_POLL */)) {
10971
11285
  serializationCtx.$addRoot$(unwrappedSignal);
10972
11286
  serializationCtx.$eagerResume$.add(unwrappedSignal);
10973
11287
  }
@@ -11195,8 +11509,8 @@ function addQwikEventToSerializationContext(serializationCtx, key, qrl) {
11195
11509
  * @see `useOn`, `useOnWindow`, `useOnDocument`.
11196
11510
  */
11197
11511
  // </docs>
11198
- const useOn = (event, eventQrl) => {
11199
- _useOn("q-e:" /* EventNameHtmlScope.on */, event, eventQrl);
11512
+ const useOn = (event, eventQrl, options) => {
11513
+ _useOn(options?.passive ? "q-ep:" /* EventNameHtmlScope.onPassive */ : "q-e:" /* EventNameHtmlScope.on */, event, eventQrl, options);
11200
11514
  };
11201
11515
  // <docs markdown="../readme.md#useOnDocument">
11202
11516
  // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
@@ -11229,8 +11543,8 @@ const useOn = (event, eventQrl) => {
11229
11543
  * ```
11230
11544
  */
11231
11545
  // </docs>
11232
- const useOnDocument = (event, eventQrl) => {
11233
- _useOn("q-d:" /* EventNameHtmlScope.document */, event, eventQrl);
11546
+ const useOnDocument = (event, eventQrl, options) => {
11547
+ _useOn(options?.passive ? "q-dp:" /* EventNameHtmlScope.documentPassive */ : "q-d:" /* EventNameHtmlScope.document */, event, eventQrl, options);
11234
11548
  };
11235
11549
  // <docs markdown="../readme.md#useOnWindow">
11236
11550
  // !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
@@ -11264,10 +11578,10 @@ const useOnDocument = (event, eventQrl) => {
11264
11578
  * ```
11265
11579
  */
11266
11580
  // </docs>
11267
- const useOnWindow = (event, eventQrl) => {
11268
- _useOn("q-w:" /* EventNameHtmlScope.window */, event, eventQrl);
11581
+ const useOnWindow = (event, eventQrl, options) => {
11582
+ _useOn(options?.passive ? "q-wp:" /* EventNameHtmlScope.windowPassive */ : "q-w:" /* EventNameHtmlScope.window */, event, eventQrl, options);
11269
11583
  };
11270
- const _useOn = (prefix, eventName, eventQrl) => {
11584
+ const _useOn = (prefix, eventName, eventQrl, options) => {
11271
11585
  const { isAdded, addEvent } = useOnEventsSequentialScope();
11272
11586
  if (isAdded) {
11273
11587
  return;
@@ -11276,11 +11590,11 @@ const _useOn = (prefix, eventName, eventQrl) => {
11276
11590
  if (Array.isArray(eventName)) {
11277
11591
  for (let i = 0; i < eventName.length; i++) {
11278
11592
  const event = eventName[i];
11279
- addEvent(prefix + fromCamelToKebabCase(event), eventQrl);
11593
+ addEvent(prefix + fromCamelToKebabCase(event), eventQrl, options);
11280
11594
  }
11281
11595
  }
11282
11596
  else {
11283
- addEvent(prefix + fromCamelToKebabCase(eventName), eventQrl);
11597
+ addEvent(prefix + fromCamelToKebabCase(eventName), eventQrl, options);
11284
11598
  }
11285
11599
  }
11286
11600
  };
@@ -11317,13 +11631,27 @@ const useOnEventsSequentialScope = () => {
11317
11631
  while (addedFlags.length <= seqIdx) {
11318
11632
  addedFlags.push(false);
11319
11633
  }
11320
- const addEvent = (eventName, eventQrl) => {
11634
+ const addEvent = (eventName, eventQrl, options) => {
11321
11635
  addedFlags[seqIdx] = true;
11322
- let events = onMap[eventName];
11323
- if (!events) {
11324
- onMap[eventName] = events = [];
11636
+ let event = onMap[eventName];
11637
+ if (!event) {
11638
+ onMap[eventName] = event = {
11639
+ qrls: [],
11640
+ capture: false,
11641
+ preventdefault: false,
11642
+ stoppropagation: false,
11643
+ };
11644
+ }
11645
+ event.qrls.push(eventQrl);
11646
+ if (options?.capture) {
11647
+ event.capture = true;
11648
+ }
11649
+ if (options?.preventdefault) {
11650
+ event.preventdefault = true;
11651
+ }
11652
+ if (options?.stoppropagation) {
11653
+ event.stoppropagation = true;
11325
11654
  }
11326
- events.push(eventQrl);
11327
11655
  };
11328
11656
  return {
11329
11657
  isAdded: addedFlags[seqIdx],
@@ -11451,6 +11779,9 @@ const dangerousObjectKeys = new Set([
11451
11779
  'then',
11452
11780
  ]);
11453
11781
  const isSafeObjectKV = (key, value) => {
11782
+ if (typeof key === 'number') {
11783
+ return true;
11784
+ }
11454
11785
  return (typeof key === 'string' &&
11455
11786
  key !== '__proto__' &&
11456
11787
  (typeof value !== 'function' || !dangerousObjectKeys.has(key)));
@@ -11483,7 +11814,7 @@ const inflate = (container, target, typeId, data) => {
11483
11814
  target[key] = value;
11484
11815
  }
11485
11816
  break;
11486
- case 20 /* TypeIds.Task */:
11817
+ case 28 /* TypeIds.Task */:
11487
11818
  const task = target;
11488
11819
  const v = data;
11489
11820
  task.$qrl$ = v[0];
@@ -11492,10 +11823,10 @@ const inflate = (container, target, typeId, data) => {
11492
11823
  task.$el$ = v[3];
11493
11824
  task.$state$ = v[4];
11494
11825
  break;
11495
- case 21 /* TypeIds.Component */:
11826
+ case 29 /* TypeIds.Component */:
11496
11827
  target[SERIALIZABLE_STATE][0] = data[0];
11497
11828
  break;
11498
- case 27 /* TypeIds.Store */: {
11829
+ case 35 /* TypeIds.Store */: {
11499
11830
  // Inflate the store target
11500
11831
  const store = unwrapStore(target);
11501
11832
  const storeTarget = pendingStoreTargets.get(store);
@@ -11514,7 +11845,7 @@ const inflate = (container, target, typeId, data) => {
11514
11845
  restoreEffectBackRefForEffectsMap(storeHandler.$effects$, store);
11515
11846
  break;
11516
11847
  }
11517
- case 22 /* TypeIds.Signal */: {
11848
+ case 30 /* TypeIds.Signal */: {
11518
11849
  const signal = target;
11519
11850
  const d = data;
11520
11851
  signal.$untrackedValue$ = d[0];
@@ -11522,7 +11853,7 @@ const inflate = (container, target, typeId, data) => {
11522
11853
  restoreEffectBackRefForEffects(signal.$effects$, signal);
11523
11854
  break;
11524
11855
  }
11525
- case 23 /* TypeIds.WrappedSignal */: {
11856
+ case 31 /* TypeIds.WrappedSignal */: {
11526
11857
  const signal = target;
11527
11858
  const d = data;
11528
11859
  signal.$func$ = container.getSyncFn(d[0]);
@@ -11536,14 +11867,22 @@ const inflate = (container, target, typeId, data) => {
11536
11867
  restoreEffectBackRefForEffects(signal.$effects$, signal);
11537
11868
  break;
11538
11869
  }
11539
- case 25 /* TypeIds.AsyncSignal */: {
11870
+ case 33 /* TypeIds.AsyncSignal */: {
11540
11871
  const asyncSignal = target;
11541
11872
  const d = data;
11542
11873
  asyncSignal.$computeQrl$ = d[0];
11543
- asyncSignal.$effects$ = new Set(d[1]);
11544
- asyncSignal.$loadingEffects$ = new Set(d[2]);
11545
- asyncSignal.$errorEffects$ = new Set(d[3]);
11546
- asyncSignal.$untrackedError$ = d[4];
11874
+ if (d[1]) {
11875
+ asyncSignal.$effects$ = new Set(d[1]);
11876
+ }
11877
+ if (d[2]) {
11878
+ asyncSignal.$loadingEffects$ = new Set(d[2]);
11879
+ }
11880
+ if (d[3]) {
11881
+ asyncSignal.$errorEffects$ = new Set(d[3]);
11882
+ }
11883
+ if (d[4]) {
11884
+ asyncSignal.$untrackedError$ = d[4];
11885
+ }
11547
11886
  asyncSignal.$flags$ = d[5] ?? 0;
11548
11887
  if (asyncSignal.$flags$ & 64 /* AsyncSignalFlags.CLIENT_ONLY */) {
11549
11888
  // If it's client only, it was serialized because it pretended to be loading
@@ -11557,9 +11896,16 @@ const inflate = (container, target, typeId, data) => {
11557
11896
  if (asyncSignal.$untrackedValue$ === NEEDS_COMPUTATION) {
11558
11897
  asyncSignal.$flags$ |= 1 /* SignalFlags.INVALID */;
11559
11898
  }
11560
- // Note, we use the setter so that it schedules polling if needed
11561
- asyncSignal.interval = (d[7] ?? 0);
11562
- asyncSignal.$concurrency$ = (d[8] ?? 1);
11899
+ // Handle old format (negative = no poll) and new format (always positive, flag in d[5])
11900
+ const rawExpires = (d[7] ?? 0);
11901
+ asyncSignal.expires = Math.abs(rawExpires);
11902
+ if (rawExpires < 0) {
11903
+ asyncSignal.$flags$ |= 256 /* AsyncSignalFlags.NO_POLL */;
11904
+ }
11905
+ if (d[8] !== undefined && d[8] !== 1) {
11906
+ asyncSignal.$concurrency$ = (d[8] ?? 1);
11907
+ asyncSignal.$jobs$ = [];
11908
+ }
11563
11909
  asyncSignal.$timeoutMs$ = (d[9] ?? 0);
11564
11910
  restoreEffectBackRefForEffects(asyncSignal.$effects$, asyncSignal);
11565
11911
  restoreEffectBackRefForEffects(asyncSignal.$loadingEffects$, asyncSignal);
@@ -11567,8 +11913,8 @@ const inflate = (container, target, typeId, data) => {
11567
11913
  break;
11568
11914
  }
11569
11915
  // Inflating a SerializerSignal is the same as inflating a ComputedSignal
11570
- case 26 /* TypeIds.SerializerSignal */:
11571
- case 24 /* TypeIds.ComputedSignal */: {
11916
+ case 34 /* TypeIds.SerializerSignal */:
11917
+ case 32 /* TypeIds.ComputedSignal */: {
11572
11918
  const computed = target;
11573
11919
  const d = data;
11574
11920
  computed.$computeQrl$ = d[0];
@@ -11588,7 +11934,7 @@ const inflate = (container, target, typeId, data) => {
11588
11934
  if (hasValue) {
11589
11935
  computed.$untrackedValue$ = d[2];
11590
11936
  }
11591
- if (typeId !== 26 /* TypeIds.SerializerSignal */ && computed.$untrackedValue$ !== NEEDS_COMPUTATION) {
11937
+ if (typeId !== 34 /* TypeIds.SerializerSignal */ && computed.$untrackedValue$ !== NEEDS_COMPUTATION) {
11592
11938
  // If we have a value after SSR, it will always be mean the signal was not invalid
11593
11939
  // The serialized signal is always left invalid so it can recreate the custom object
11594
11940
  computed.$flags$ &= -2 /* SignalFlags.INVALID */;
@@ -11596,7 +11942,7 @@ const inflate = (container, target, typeId, data) => {
11596
11942
  restoreEffectBackRefForEffects(computed.$effects$, computed);
11597
11943
  break;
11598
11944
  }
11599
- case 15 /* TypeIds.Error */: {
11945
+ case 23 /* TypeIds.Error */: {
11600
11946
  const d = data;
11601
11947
  target.message = d[0];
11602
11948
  for (let i = 1; i < d.length; i += 2) {
@@ -11604,7 +11950,7 @@ const inflate = (container, target, typeId, data) => {
11604
11950
  }
11605
11951
  break;
11606
11952
  }
11607
- case 28 /* TypeIds.FormData */: {
11953
+ case 36 /* TypeIds.FormData */: {
11608
11954
  const formData = target;
11609
11955
  const d = data;
11610
11956
  for (let i = 0; i < d.length; i++) {
@@ -11612,7 +11958,7 @@ const inflate = (container, target, typeId, data) => {
11612
11958
  }
11613
11959
  break;
11614
11960
  }
11615
- case 29 /* TypeIds.JSXNode */: {
11961
+ case 37 /* TypeIds.JSXNode */: {
11616
11962
  const jsx = target;
11617
11963
  const [type, key, varProps, constProps, children, toSort] = data;
11618
11964
  jsx.type = type;
@@ -11623,7 +11969,7 @@ const inflate = (container, target, typeId, data) => {
11623
11969
  jsx.toSort = !!toSort;
11624
11970
  break;
11625
11971
  }
11626
- case 17 /* TypeIds.Set */: {
11972
+ case 25 /* TypeIds.Set */: {
11627
11973
  const set = target;
11628
11974
  const d = data;
11629
11975
  for (let i = 0; i < d.length; i++) {
@@ -11631,7 +11977,7 @@ const inflate = (container, target, typeId, data) => {
11631
11977
  }
11632
11978
  break;
11633
11979
  }
11634
- case 18 /* TypeIds.Map */: {
11980
+ case 26 /* TypeIds.Map */: {
11635
11981
  const map = target;
11636
11982
  const d = data;
11637
11983
  for (let i = 0; i < d.length; i++) {
@@ -11639,7 +11985,7 @@ const inflate = (container, target, typeId, data) => {
11639
11985
  }
11640
11986
  break;
11641
11987
  }
11642
- case 16 /* TypeIds.Promise */: {
11988
+ case 24 /* TypeIds.Promise */: {
11643
11989
  const promise = target;
11644
11990
  const [resolved, result] = data;
11645
11991
  const [resolve, reject] = resolvers.get(promise);
@@ -11651,7 +11997,7 @@ const inflate = (container, target, typeId, data) => {
11651
11997
  }
11652
11998
  break;
11653
11999
  }
11654
- case 19 /* TypeIds.Uint8Array */:
12000
+ case 27 /* TypeIds.Uint8Array */:
11655
12001
  const bytes = target;
11656
12002
  const buf = atob(data);
11657
12003
  let i = 0;
@@ -11660,7 +12006,7 @@ const inflate = (container, target, typeId, data) => {
11660
12006
  bytes[i++] = s.charCodeAt(0);
11661
12007
  }
11662
12008
  break;
11663
- case 30 /* TypeIds.PropsProxy */:
12009
+ case 38 /* TypeIds.PropsProxy */:
11664
12010
  const propsProxy = target;
11665
12011
  const d = data;
11666
12012
  let owner = d[0];
@@ -11673,13 +12019,13 @@ const inflate = (container, target, typeId, data) => {
11673
12019
  propsHandler.$effects$ = d[3];
11674
12020
  restoreEffectBackRefForEffectsMap(propsHandler.$effects$, propsProxy);
11675
12021
  break;
11676
- case 31 /* TypeIds.SubscriptionData */: {
12022
+ case 39 /* TypeIds.SubscriptionData */: {
11677
12023
  const effectData = target;
11678
12024
  effectData.data.$scopedStyleIdPrefix$ = data[0];
11679
12025
  effectData.data.$isConst$ = data[1];
11680
12026
  break;
11681
12027
  }
11682
- case 32 /* TypeIds.EffectSubscription */: {
12028
+ case 40 /* TypeIds.EffectSubscription */: {
11683
12029
  const effectSub = target;
11684
12030
  const d = data;
11685
12031
  effectSub.consumer = d[0];
@@ -11770,7 +12116,7 @@ function restoreEffectBackRefForEffectsMap(effectsMap, consumer) {
11770
12116
  }
11771
12117
 
11772
12118
  /** Arrays/Objects are special-cased so their identifiers is a single digit. */
11773
- const needsInflation = (typeId) => typeId >= 15 /* TypeIds.Error */ || typeId === 4 /* TypeIds.Array */ || typeId === 5 /* TypeIds.Object */;
12119
+ const needsInflation = (typeId) => typeId >= 23 /* TypeIds.Error */ || typeId === 4 /* TypeIds.Array */ || typeId === 5 /* TypeIds.Object */;
11774
12120
  const deserializedProxyMap = new WeakMap();
11775
12121
  const isDeserializerProxy = (value) => {
11776
12122
  return isObject(value) && SERIALIZER_PROXY_UNWRAP in value;
@@ -11934,6 +12280,14 @@ const _verifySerializable = (value, seen, ctx, preMessage) => {
11934
12280
  if (canSerialize(unwrapped)) {
11935
12281
  return value;
11936
12282
  }
12283
+ // Framework-internal branded values (e.g. route loaders/actions, validators)
12284
+ // are callables or objects that stamp __brand / __brand__ to opt out of the
12285
+ // serializer walking their internals. Honor that for both objects and
12286
+ // functions — loader/action refs are functions with __brand = 'server_loader'
12287
+ // / 'server_action' and should not be rejected as unserializable.
12288
+ if (unwrapped.__brand || unwrapped.__brand__) {
12289
+ return value;
12290
+ }
11937
12291
  const typeObj = typeof unwrapped;
11938
12292
  switch (typeObj) {
11939
12293
  case 'object':
@@ -11963,10 +12317,6 @@ const _verifySerializable = (value, seen, ctx, preMessage) => {
11963
12317
  if (unwrapped instanceof VNode) {
11964
12318
  return value;
11965
12319
  }
11966
- // We have .__brand and .__brand__
11967
- if (unwrapped.__brand || unwrapped.__brand__) {
11968
- return value;
11969
- }
11970
12320
  if (isSerializableObject(unwrapped)) {
11971
12321
  for (const [key, item] of Object.entries(unwrapped)) {
11972
12322
  _verifySerializable(item, seen, ctx + '.' + key);
@@ -13308,13 +13658,15 @@ class QRLClass {
13308
13658
  $container$;
13309
13659
  constructor($lazy$, $captures$, container) {
13310
13660
  this.$lazy$ = $lazy$;
13661
+ if (qDev) {
13662
+ initQrlClassDev($lazy$, $captures$, this);
13663
+ }
13311
13664
  if ($captures$) {
13312
13665
  this.$captures$ = $captures$;
13313
13666
  if (typeof $captures$ === 'string') {
13314
13667
  // We cannot rely on the container of the lazy ref, it may be missing or different
13315
13668
  this.$container$ = container;
13316
13669
  }
13317
- qDev && initQrlClassDev($lazy$, $captures$, this);
13318
13670
  }
13319
13671
  // If it is plain value with deserialized or missing captures, resolve it immediately
13320
13672
  // Otherwise we keep using the async path so we can wait for qrls to load
@@ -14930,5 +15282,5 @@ if (import.meta.hot) {
14930
15282
  });
14931
15283
  }
14932
15284
 
14933
- export { $, Each, 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, _addProjection, _captures, _chk, createQRL as _createQRL, _deserialize, _dumpState, eachCmp as _eaC, eachCmpTask as _eaT, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, _hmr, 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, _removeProjection, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, setEvent as _setEvent, _setProjectionTarget, scheduleTask as _task, _updateProjectionProps, _useHmr, _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 };
15285
+ export { $, Each, 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, _addProjection, _captures, _chk, createQRL as _createQRL, _deserialize, _dumpState, eachCmp as _eaC, eachCmpTask as _eaT, _executeSsrChores, _fnSignal, _getConstProps, _getContextContainer, _getContextEvent, _getContextHostElement, getDomContainer as _getDomContainer, _getQContainerElement, _getVarProps, _hasStoreEffects, _hmr, 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, _removeProjection, _res, _resolveContextWithoutSequentialScope, _restProps, _rsc, _run, _serialize, setEvent as _setEvent, _setProjectionTarget, scheduleTask as _task, _updateProjectionProps, _useHmr, _val, verifySerializable as _verifySerializable, vnode_ensureElementInflated as _vnode_ensureElementInflated, vnode_getAttrKeys as _vnode_getAttrKeys, vnode_getElementName as _vnode_getElementName, vnode_getFirstChild as _vnode_getFirstChild, vnode_getProp as _vnode_getProp, vnode_getVNodeForChildNode as _vnode_getVNodeForChildNode, vnode_insertBefore as _vnode_insertBefore, vnode_isElementVNode as _vnode_isElementVNode, vnode_isMaterialized as _vnode_isMaterialized, vnode_isTextVNode as _vnode_isTextVNode, vnode_isVirtualVNode as _vnode_isVirtualVNode, vnode_newVirtual as _vnode_newVirtual, vnode_remove as _vnode_remove, vnode_setProp as _vnode_setProp, 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 };
14934
15286
  //# sourceMappingURL=core.mjs.map