@qwik.dev/core 2.0.0-alpha.5 → 2.0.0-alpha.7
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/bindings/qwik.darwin-arm64.node +0 -0
- package/bindings/qwik.darwin-x64.node +0 -0
- package/bindings/qwik.linux-x64-gnu.node +0 -0
- package/bindings/qwik.win32-x64-msvc.node +0 -0
- package/bindings/qwik_wasm_bg.wasm +0 -0
- package/dist/build/package.json +1 -1
- package/dist/cli.cjs +65 -63
- package/dist/core-internal.d.ts +78 -77
- package/dist/core.cjs +1770 -1517
- package/dist/core.cjs.map +1 -1
- package/dist/core.min.mjs +1 -1
- package/dist/core.mjs +1768 -1517
- package/dist/core.mjs.map +1 -1
- package/dist/core.prod.cjs +985 -848
- package/dist/core.prod.mjs +1210 -1032
- package/dist/insights/index.qwik.cjs +3658 -160
- package/dist/insights/index.qwik.mjs +3658 -160
- package/dist/loader/index.cjs +2 -2
- package/dist/loader/index.mjs +2 -2
- package/dist/loader/package.json +1 -1
- package/dist/optimizer.cjs +230 -5691
- package/dist/optimizer.mjs +192 -5992
- package/dist/prefetch/package.json +1 -1
- package/dist/qwikloader.debug.js +12 -15
- package/dist/qwikloader.js +2 -2
- package/dist/server.cjs +754 -7067
- package/dist/server.mjs +771 -7062
- package/dist/starters/adapters/fastify/src/plugins/fastify-qwik.ts +2 -0
- package/dist/starters/features/cypress/package.json +1 -1
- package/dist/starters/features/drizzle/drizzle/schema.ts +6 -18
- package/dist/starters/features/drizzle/drizzle.config.ts +5 -4
- package/dist/starters/features/drizzle/package.json +14 -11
- package/dist/starters/features/pandacss/package.json +1 -1
- package/dist/starters/features/partytown/package.json +1 -1
- package/dist/starters/features/postcss/package.json +1 -1
- package/dist/starters/features/prisma/package.json +1 -1
- package/dist/starters/features/react/package.json +1 -1
- package/dist/starters/features/storybook/package.json +1 -1
- package/dist/starters/features/styled-vanilla-extract/package.json +2 -1
- package/dist/starters/features/tailwind/package.json +15 -9
- package/dist/starters/features/tailwind/src/global.css +1 -7
- package/dist/starters/features/turso/package.json +1 -1
- package/dist/starters/features/turso/src/utils/turso.ts +1 -1
- package/dist/starters/features/vitest/package.json +1 -1
- package/dist/testing/index.cjs +1445 -1252
- package/dist/testing/index.mjs +1455 -1256
- package/dist/testing/package.json +1 -1
- package/handlers.mjs +9 -0
- package/package.json +7 -5
- package/public.d.ts +2 -0
- package/dist/starters/features/tailwind/.vscode/settings.json +0 -3
- package/dist/starters/features/tailwind/postcss.config.cjs +0 -6
- package/dist/starters/features/tailwind/tailwind.config.js +0 -8
package/dist/core.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* @qwik.dev/core 2.0.0-alpha.
|
|
3
|
+
* @qwik.dev/core 2.0.0-alpha.7-dev+a26598a
|
|
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
|
|
@@ -121,8 +121,8 @@
|
|
|
121
121
|
// Keep one error, one line to make it easier to search for the error message.
|
|
122
122
|
const MAP = [
|
|
123
123
|
'Error while serializing class or style attributes', // 0
|
|
124
|
-
'', // 1
|
|
125
|
-
'', // 2
|
|
124
|
+
'Scheduler not found', // 1
|
|
125
|
+
'track() received object, without prop to track', // 2
|
|
126
126
|
'Only primitive and object literals can be serialized. {{0}}', // 3
|
|
127
127
|
'', // 4 unused
|
|
128
128
|
'You can render over a existing q:container. Skipping render().', // 5
|
|
@@ -165,13 +165,11 @@
|
|
|
165
165
|
"Element must have 'q:container' attribute.", // 42
|
|
166
166
|
'Unknown vnode type {{0}}.', // 43
|
|
167
167
|
'Materialize error: missing element: {{0}} {{1}} {{2}}', // 44
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'
|
|
171
|
-
'
|
|
172
|
-
'
|
|
173
|
-
'SsrError: Promises not expected here.', // 50
|
|
174
|
-
'Attribute value is unsafe for SSR', // 51
|
|
168
|
+
'Cannot coerce a Signal, use `.value` instead', // 45
|
|
169
|
+
'useComputedSignal$ QRL {{0}} {{1}} returned a Promise', // 46
|
|
170
|
+
'ComputedSignal is read-only', // 47
|
|
171
|
+
'WrappedSignal is read-only', // 48
|
|
172
|
+
'Attribute value is unsafe for SSR', // 49
|
|
175
173
|
];
|
|
176
174
|
let text = MAP[code] ?? '';
|
|
177
175
|
if (parts.length) {
|
|
@@ -193,8 +191,8 @@
|
|
|
193
191
|
var QError;
|
|
194
192
|
(function (QError) {
|
|
195
193
|
QError[QError["stringifyClassOrStyle"] = 0] = "stringifyClassOrStyle";
|
|
196
|
-
QError[QError["
|
|
197
|
-
QError[QError["
|
|
194
|
+
QError[QError["schedulerNotFound"] = 1] = "schedulerNotFound";
|
|
195
|
+
QError[QError["trackObjectWithoutProp"] = 2] = "trackObjectWithoutProp";
|
|
198
196
|
QError[QError["verifySerializable"] = 3] = "verifySerializable";
|
|
199
197
|
QError[QError["UNUSED_4"] = 4] = "UNUSED_4";
|
|
200
198
|
QError[QError["cannotRenderOverExistingContainer"] = 5] = "cannotRenderOverExistingContainer";
|
|
@@ -237,19 +235,153 @@
|
|
|
237
235
|
QError[QError["elementWithoutContainer"] = 42] = "elementWithoutContainer";
|
|
238
236
|
QError[QError["invalidVNodeType"] = 43] = "invalidVNodeType";
|
|
239
237
|
QError[QError["materializeVNodeDataError"] = 44] = "materializeVNodeDataError";
|
|
240
|
-
QError[QError["
|
|
241
|
-
QError[QError["
|
|
242
|
-
QError[QError["
|
|
243
|
-
QError[QError["
|
|
244
|
-
QError[QError["
|
|
245
|
-
QError[QError["promisesNotExpected"] = 50] = "promisesNotExpected";
|
|
246
|
-
QError[QError["unsafeAttr"] = 51] = "unsafeAttr";
|
|
238
|
+
QError[QError["cannotCoerceSignal"] = 45] = "cannotCoerceSignal";
|
|
239
|
+
QError[QError["computedNotSync"] = 46] = "computedNotSync";
|
|
240
|
+
QError[QError["computedReadOnly"] = 47] = "computedReadOnly";
|
|
241
|
+
QError[QError["wrappedReadOnly"] = 48] = "wrappedReadOnly";
|
|
242
|
+
QError[QError["unsafeAttr"] = 49] = "unsafeAttr";
|
|
247
243
|
})(QError || (QError = {}));
|
|
248
244
|
const qError = (code, errorMessageArgs = []) => {
|
|
249
245
|
const text = codeToText(code, ...errorMessageArgs);
|
|
250
246
|
return logErrorAndStop(text, ...errorMessageArgs);
|
|
251
247
|
};
|
|
252
248
|
|
|
249
|
+
/** QRL related utilities that you can import without importing all of Qwik. */
|
|
250
|
+
const SYNC_QRL = '<sync>';
|
|
251
|
+
/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
|
|
252
|
+
const isSyncQrl = (value) => {
|
|
253
|
+
return isQrl$1(value) && value.$symbol$ == SYNC_QRL;
|
|
254
|
+
};
|
|
255
|
+
const isQrl$1 = (value) => {
|
|
256
|
+
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
257
|
+
};
|
|
258
|
+
function assertQrl(qrl) {
|
|
259
|
+
if (build.isDev) {
|
|
260
|
+
if (!isQrl$1(qrl)) {
|
|
261
|
+
throw new Error('Not a QRL');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const getSymbolHash = (symbolName) => {
|
|
266
|
+
const index = symbolName.lastIndexOf('_');
|
|
267
|
+
if (index > -1) {
|
|
268
|
+
return symbolName.slice(index + 1);
|
|
269
|
+
}
|
|
270
|
+
return symbolName;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* A friendly name tag for a VirtualVNode.
|
|
275
|
+
*
|
|
276
|
+
* Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
|
|
277
|
+
*
|
|
278
|
+
* The name is only added in development mode and is not included in production builds.
|
|
279
|
+
*/
|
|
280
|
+
const DEBUG_TYPE = 'q:type';
|
|
281
|
+
var VirtualType;
|
|
282
|
+
(function (VirtualType) {
|
|
283
|
+
VirtualType["Virtual"] = "V";
|
|
284
|
+
VirtualType["Fragment"] = "F";
|
|
285
|
+
VirtualType["WrappedSignal"] = "S";
|
|
286
|
+
VirtualType["Awaited"] = "A";
|
|
287
|
+
VirtualType["Component"] = "C";
|
|
288
|
+
VirtualType["InlineComponent"] = "I";
|
|
289
|
+
VirtualType["Projection"] = "P";
|
|
290
|
+
})(VirtualType || (VirtualType = {}));
|
|
291
|
+
const START = '\x1b[34m';
|
|
292
|
+
const END = '\x1b[0m';
|
|
293
|
+
const VirtualTypeName = {
|
|
294
|
+
[VirtualType.Virtual]: /* ********* */ START + 'Virtual' + END, //
|
|
295
|
+
[VirtualType.Fragment]: /* ******** */ START + 'Fragment' + END, //
|
|
296
|
+
[VirtualType.WrappedSignal]: /* *** */ START + 'Signal' + END, //
|
|
297
|
+
[VirtualType.Awaited]: /* ********* */ START + 'Awaited' + END, //
|
|
298
|
+
[VirtualType.Component]: /* ******* */ START + 'Component' + END, //
|
|
299
|
+
[VirtualType.InlineComponent]: /* * */ START + 'InlineComponent' + END, //
|
|
300
|
+
[VirtualType.Projection]: /* ****** */ START + 'Projection' + END, //
|
|
301
|
+
};
|
|
302
|
+
var QContainerValue;
|
|
303
|
+
(function (QContainerValue) {
|
|
304
|
+
QContainerValue["PAUSED"] = "paused";
|
|
305
|
+
QContainerValue["RESUMED"] = "resumed";
|
|
306
|
+
// these values below are used in the qwik loader as a plain text for the q:container selector
|
|
307
|
+
// standard dangerouslySetInnerHTML
|
|
308
|
+
QContainerValue["HTML"] = "html";
|
|
309
|
+
// textarea
|
|
310
|
+
QContainerValue["TEXT"] = "text";
|
|
311
|
+
})(QContainerValue || (QContainerValue = {}));
|
|
312
|
+
|
|
313
|
+
/** State factory of the component. */
|
|
314
|
+
const OnRenderProp = 'q:renderFn';
|
|
315
|
+
/** Component style content prefix */
|
|
316
|
+
const ComponentStylesPrefixContent = '⚡️';
|
|
317
|
+
/** `<some-element q:slot="...">` */
|
|
318
|
+
const QSlot = 'q:slot';
|
|
319
|
+
const QSlotParent = ':';
|
|
320
|
+
const QSlotRef = 'q:sref';
|
|
321
|
+
const QSlotS = 'q:s';
|
|
322
|
+
const QStyle = 'q:style';
|
|
323
|
+
const QStyleSelector = 'style[q\\:style]';
|
|
324
|
+
const QStyleSSelector = 'style[q\\:sstyle]';
|
|
325
|
+
const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
|
|
326
|
+
const QScopedStyle = 'q:sstyle';
|
|
327
|
+
const QCtxAttr = 'q:ctx';
|
|
328
|
+
const QBackRefs = 'q:brefs';
|
|
329
|
+
const QFuncsPrefix = 'qFuncs_';
|
|
330
|
+
const getQFuncs = (document, hash) => {
|
|
331
|
+
return document[QFuncsPrefix + hash] || [];
|
|
332
|
+
};
|
|
333
|
+
const QBaseAttr = 'q:base';
|
|
334
|
+
const QLocaleAttr = 'q:locale';
|
|
335
|
+
const QManifestHashAttr = 'q:manifest-hash';
|
|
336
|
+
const QInstanceAttr = 'q:instance';
|
|
337
|
+
const QContainerIsland = 'q:container-island';
|
|
338
|
+
const QContainerIslandEnd = '/' + QContainerIsland;
|
|
339
|
+
const QIgnore = 'q:ignore';
|
|
340
|
+
const QIgnoreEnd = '/' + QIgnore;
|
|
341
|
+
const QContainerAttr = 'q:container';
|
|
342
|
+
const QContainerAttrEnd = '/' + QContainerAttr;
|
|
343
|
+
const QTemplate = 'q:template';
|
|
344
|
+
// the same selector should be inside the qwik loader
|
|
345
|
+
// and the same selector should be inside the qwik router spa-shim and spa-init
|
|
346
|
+
const QContainerSelector = '[q\\:container]:not([q\\:container=' +
|
|
347
|
+
QContainerValue.HTML +
|
|
348
|
+
']):not([q\\:container=' +
|
|
349
|
+
QContainerValue.TEXT +
|
|
350
|
+
'])';
|
|
351
|
+
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
352
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
353
|
+
const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
|
|
354
|
+
const ResourceEvent = 'qResource';
|
|
355
|
+
const RenderEvent = 'qRender';
|
|
356
|
+
const TaskEvent = 'qTask';
|
|
357
|
+
const QDefaultSlot = '';
|
|
358
|
+
/**
|
|
359
|
+
* Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
|
|
360
|
+
*
|
|
361
|
+
* As the VNode get materialized the vnode now becomes eligible for mutation. Once the vnode mutates
|
|
362
|
+
* the `VNode` references from the `qwik/json` may become invalid. For this reason, these references
|
|
363
|
+
* need to be eagerly resolved. `VNODE_REF` stores a pointer to "this" vnode. This allows the system
|
|
364
|
+
* to eagerly resolve these pointes as the vnodes are materialized.
|
|
365
|
+
*/
|
|
366
|
+
const ELEMENT_ID = 'q:id';
|
|
367
|
+
const ELEMENT_KEY = 'q:key';
|
|
368
|
+
const ELEMENT_PROPS = 'q:props';
|
|
369
|
+
const ELEMENT_SEQ = 'q:seq';
|
|
370
|
+
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
371
|
+
const Q_PREFIX = 'q:';
|
|
372
|
+
/** Non serializable markers - always begins with `:` character */
|
|
373
|
+
const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
374
|
+
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
375
|
+
const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
|
|
376
|
+
const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
|
|
377
|
+
// comment nodes
|
|
378
|
+
const FLUSH_COMMENT = 'qkssr-f';
|
|
379
|
+
const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
|
|
380
|
+
const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
|
|
381
|
+
const Q_PROPS_SEPARATOR = ':';
|
|
382
|
+
const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
|
|
383
|
+
const qwikInspectorAttr = 'data-qwik-inspector';
|
|
384
|
+
|
|
253
385
|
// keep this import from core/build so the cjs build works
|
|
254
386
|
const createPlatform = () => {
|
|
255
387
|
return {
|
|
@@ -310,7 +442,7 @@
|
|
|
310
442
|
*/
|
|
311
443
|
const toUrl = (doc, containerEl, url) => {
|
|
312
444
|
const baseURI = doc.baseURI;
|
|
313
|
-
const base = new URL(containerEl.getAttribute(
|
|
445
|
+
const base = new URL(containerEl.getAttribute(QBaseAttr) ?? baseURI, baseURI);
|
|
314
446
|
return new URL(url, base);
|
|
315
447
|
};
|
|
316
448
|
let _platform = /*#__PURE__ */ createPlatform();
|
|
@@ -389,11 +521,6 @@
|
|
|
389
521
|
? valueOrPromise.then(thenFn, shouldNotError)
|
|
390
522
|
: thenFn(valueOrPromise);
|
|
391
523
|
};
|
|
392
|
-
const maybeThenPassError = (valueOrPromise, thenFn) => {
|
|
393
|
-
return isPromise(valueOrPromise)
|
|
394
|
-
? valueOrPromise.then(thenFn)
|
|
395
|
-
: thenFn(valueOrPromise);
|
|
396
|
-
};
|
|
397
524
|
const shouldNotError = (reason) => {
|
|
398
525
|
throwErrorAndStop(reason);
|
|
399
526
|
};
|
|
@@ -402,15 +529,24 @@
|
|
|
402
529
|
setTimeout(resolve, timeout);
|
|
403
530
|
});
|
|
404
531
|
};
|
|
532
|
+
// Retries a function that throws a promise.
|
|
405
533
|
function retryOnPromise(fn, retryCount = 0) {
|
|
406
|
-
|
|
407
|
-
return fn();
|
|
408
|
-
}
|
|
409
|
-
catch (e) {
|
|
534
|
+
const retryOrThrow = (e) => {
|
|
410
535
|
if (isPromise(e) && retryCount < MAX_RETRY_ON_PROMISE_COUNT) {
|
|
411
536
|
return e.then(retryOnPromise.bind(null, fn, retryCount++));
|
|
412
537
|
}
|
|
413
538
|
throw e;
|
|
539
|
+
};
|
|
540
|
+
try {
|
|
541
|
+
const result = fn();
|
|
542
|
+
if (isPromise(result)) {
|
|
543
|
+
// not awaited promise is not caught by try/catch block
|
|
544
|
+
return result.catch((e) => retryOrThrow(e));
|
|
545
|
+
}
|
|
546
|
+
return result;
|
|
547
|
+
}
|
|
548
|
+
catch (e) {
|
|
549
|
+
return retryOrThrow(e);
|
|
414
550
|
}
|
|
415
551
|
}
|
|
416
552
|
|
|
@@ -453,118 +589,6 @@
|
|
|
453
589
|
VNodeDataFlag[VNodeDataFlag["SERIALIZE"] = 16] = "SERIALIZE";
|
|
454
590
|
})(VNodeDataFlag || (VNodeDataFlag = {}));
|
|
455
591
|
|
|
456
|
-
/**
|
|
457
|
-
* A friendly name tag for a VirtualVNode.
|
|
458
|
-
*
|
|
459
|
-
* Theses are used to give a name to a VirtualVNode. This is useful for debugging and testing.
|
|
460
|
-
*
|
|
461
|
-
* The name is only added in development mode and is not included in production builds.
|
|
462
|
-
*/
|
|
463
|
-
const DEBUG_TYPE = 'q:type';
|
|
464
|
-
var VirtualType;
|
|
465
|
-
(function (VirtualType) {
|
|
466
|
-
VirtualType["Virtual"] = "V";
|
|
467
|
-
VirtualType["Fragment"] = "F";
|
|
468
|
-
VirtualType["WrappedSignal"] = "S";
|
|
469
|
-
VirtualType["Awaited"] = "A";
|
|
470
|
-
VirtualType["Component"] = "C";
|
|
471
|
-
VirtualType["InlineComponent"] = "I";
|
|
472
|
-
VirtualType["Projection"] = "P";
|
|
473
|
-
})(VirtualType || (VirtualType = {}));
|
|
474
|
-
const START = '\x1b[34m';
|
|
475
|
-
const END = '\x1b[0m';
|
|
476
|
-
const VirtualTypeName = {
|
|
477
|
-
[VirtualType.Virtual]: /* ********* */ START + 'Virtual' + END, //
|
|
478
|
-
[VirtualType.Fragment]: /* ******** */ START + 'Fragment' + END, //
|
|
479
|
-
[VirtualType.WrappedSignal]: /* *** */ START + 'Signal' + END, //
|
|
480
|
-
[VirtualType.Awaited]: /* ********* */ START + 'Awaited' + END, //
|
|
481
|
-
[VirtualType.Component]: /* ******* */ START + 'Component' + END, //
|
|
482
|
-
[VirtualType.InlineComponent]: /* * */ START + 'InlineComponent' + END, //
|
|
483
|
-
[VirtualType.Projection]: /* ****** */ START + 'Projection' + END, //
|
|
484
|
-
};
|
|
485
|
-
var QContainerValue;
|
|
486
|
-
(function (QContainerValue) {
|
|
487
|
-
QContainerValue["PAUSED"] = "paused";
|
|
488
|
-
QContainerValue["RESUMED"] = "resumed";
|
|
489
|
-
// these values below are used in the qwik loader as a plain text for the q:container selector
|
|
490
|
-
// standard dangerouslySetInnerHTML
|
|
491
|
-
QContainerValue["HTML"] = "html";
|
|
492
|
-
// textarea
|
|
493
|
-
QContainerValue["TEXT"] = "text";
|
|
494
|
-
})(QContainerValue || (QContainerValue = {}));
|
|
495
|
-
|
|
496
|
-
/** State factory of the component. */
|
|
497
|
-
const OnRenderProp = 'q:renderFn';
|
|
498
|
-
/** Component style content prefix */
|
|
499
|
-
const ComponentStylesPrefixContent = '⭐️';
|
|
500
|
-
/** `<some-element q:slot="...">` */
|
|
501
|
-
const QSlot = 'q:slot';
|
|
502
|
-
const QSlotParent = ':';
|
|
503
|
-
const QSlotRef = 'q:sref';
|
|
504
|
-
const QSlotS = 'q:s';
|
|
505
|
-
const QStyle = 'q:style';
|
|
506
|
-
const QStyleSelector = 'style[q\\:style]';
|
|
507
|
-
const QStyleSSelector = 'style[q\\:sstyle]';
|
|
508
|
-
const QStylesAllSelector = QStyleSelector + ',' + QStyleSSelector;
|
|
509
|
-
const QScopedStyle = 'q:sstyle';
|
|
510
|
-
const QCtxAttr = 'q:ctx';
|
|
511
|
-
const QSubscribers = 'q:subs';
|
|
512
|
-
const QFuncsPrefix = 'qFuncs_';
|
|
513
|
-
const getQFuncs = (document, hash) => {
|
|
514
|
-
return document[QFuncsPrefix + hash] || [];
|
|
515
|
-
};
|
|
516
|
-
const QBaseAttr = 'q:base';
|
|
517
|
-
const QLocaleAttr = 'q:locale';
|
|
518
|
-
const QManifestHashAttr = 'q:manifest-hash';
|
|
519
|
-
const QInstanceAttr = 'q:instance';
|
|
520
|
-
const QContainerIsland = 'q:container-island';
|
|
521
|
-
const QContainerIslandEnd = '/' + QContainerIsland;
|
|
522
|
-
const QIgnore = 'q:ignore';
|
|
523
|
-
const QIgnoreEnd = '/' + QIgnore;
|
|
524
|
-
const QContainerAttr = 'q:container';
|
|
525
|
-
const QContainerAttrEnd = '/' + QContainerAttr;
|
|
526
|
-
const QTemplate = 'q:template';
|
|
527
|
-
// the same selector should be inside the qwik loader
|
|
528
|
-
// and the same selector should be inside the qwik router spa-shim and spa-init
|
|
529
|
-
const QContainerSelector = '[q\\:container]:not([q\\:container=' +
|
|
530
|
-
QContainerValue.HTML +
|
|
531
|
-
']):not([q\\:container=' +
|
|
532
|
-
QContainerValue.TEXT +
|
|
533
|
-
'])';
|
|
534
|
-
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
535
|
-
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
536
|
-
const MATH_NS = 'http://www.w3.org/1998/Math/MathML';
|
|
537
|
-
const ResourceEvent = 'qResource';
|
|
538
|
-
const RenderEvent = 'qRender';
|
|
539
|
-
const TaskEvent = 'qTask';
|
|
540
|
-
const QDefaultSlot = '';
|
|
541
|
-
/**
|
|
542
|
-
* Attribute to mark that this VNode has a pointer to itself from the `qwik/json` state.
|
|
543
|
-
*
|
|
544
|
-
* As the VNode get materialized the vnode now becomes eligible for mutation. Once the vnode mutates
|
|
545
|
-
* the `VNode` references from the `qwik/json` may become invalid. For this reason, these references
|
|
546
|
-
* need to be eagerly resolved. `VNODE_REF` stores a pointer to "this" vnode. This allows the system
|
|
547
|
-
* to eagerly resolve these pointes as the vnodes are materialized.
|
|
548
|
-
*/
|
|
549
|
-
const ELEMENT_ID = 'q:id';
|
|
550
|
-
const ELEMENT_KEY = 'q:key';
|
|
551
|
-
const ELEMENT_PROPS = 'q:props';
|
|
552
|
-
const ELEMENT_SEQ = 'q:seq';
|
|
553
|
-
const ELEMENT_SEQ_IDX = 'q:seqIdx';
|
|
554
|
-
const Q_PREFIX = 'q:';
|
|
555
|
-
/** Non serializable markers - always begins with `:` character */
|
|
556
|
-
const NON_SERIALIZABLE_MARKER_PREFIX = ':';
|
|
557
|
-
const USE_ON_LOCAL = NON_SERIALIZABLE_MARKER_PREFIX + 'on';
|
|
558
|
-
const USE_ON_LOCAL_SEQ_IDX = NON_SERIALIZABLE_MARKER_PREFIX + 'onIdx';
|
|
559
|
-
const USE_ON_LOCAL_FLAGS = NON_SERIALIZABLE_MARKER_PREFIX + 'onFlags';
|
|
560
|
-
// comment nodes
|
|
561
|
-
const FLUSH_COMMENT = 'qkssr-f';
|
|
562
|
-
const STREAM_BLOCK_START_COMMENT = 'qkssr-pu';
|
|
563
|
-
const STREAM_BLOCK_END_COMMENT = 'qkssr-po';
|
|
564
|
-
const Q_PROPS_SEPARATOR = ':';
|
|
565
|
-
const dangerouslySetInnerHTML = 'dangerouslySetInnerHTML';
|
|
566
|
-
const qwikInspectorAttr = 'data-qwik-inspector';
|
|
567
|
-
|
|
568
592
|
let _locale = undefined;
|
|
569
593
|
/**
|
|
570
594
|
* Retrieve the current locale.
|
|
@@ -614,7 +638,7 @@
|
|
|
614
638
|
_locale = locale;
|
|
615
639
|
}
|
|
616
640
|
|
|
617
|
-
const isQrl
|
|
641
|
+
const isQrl = (value) => {
|
|
618
642
|
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
619
643
|
};
|
|
620
644
|
|
|
@@ -686,21 +710,21 @@
|
|
|
686
710
|
// Emit event
|
|
687
711
|
announcedQRL.add(symbol);
|
|
688
712
|
emitEvent('qprefetch', {
|
|
689
|
-
symbols: [
|
|
713
|
+
symbols: [symbol],
|
|
690
714
|
bundles: chunk && [chunk],
|
|
691
715
|
});
|
|
692
716
|
}
|
|
693
717
|
// Unwrap subscribers
|
|
694
|
-
return createQRL(chunk, symbol, null, symbolFn, null, lexicalScopeCapture
|
|
718
|
+
return createQRL(chunk, symbol, null, symbolFn, null, lexicalScopeCapture);
|
|
695
719
|
};
|
|
696
720
|
/** @internal */
|
|
697
721
|
const inlinedQrl = (symbol, symbolName, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
698
722
|
// Unwrap subscribers
|
|
699
|
-
return createQRL(null, symbolName, symbol, null, null, lexicalScopeCapture
|
|
723
|
+
return createQRL(null, symbolName, symbol, null, null, lexicalScopeCapture);
|
|
700
724
|
};
|
|
701
725
|
/** @internal */
|
|
702
726
|
const _noopQrl = (symbolName, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
703
|
-
return createQRL(null, symbolName, null, null, null, lexicalScopeCapture
|
|
727
|
+
return createQRL(null, symbolName, null, null, null, lexicalScopeCapture);
|
|
704
728
|
};
|
|
705
729
|
/** @internal */
|
|
706
730
|
const _noopQrlDEV = (symbolName, opts, lexicalScopeCapture = EMPTY_ARRAY) => {
|
|
@@ -729,6 +753,80 @@
|
|
|
729
753
|
return symbol;
|
|
730
754
|
};
|
|
731
755
|
|
|
756
|
+
var ChoreType;
|
|
757
|
+
(function (ChoreType) {
|
|
758
|
+
/// MASKS defining three levels of sorting
|
|
759
|
+
ChoreType[ChoreType["MACRO"] = 240] = "MACRO";
|
|
760
|
+
/* order of elements (not encoded here) */
|
|
761
|
+
ChoreType[ChoreType["MICRO"] = 15] = "MICRO";
|
|
762
|
+
/** Ensure that the QRL promise is resolved before processing next chores in the queue */
|
|
763
|
+
ChoreType[ChoreType["QRL_RESOLVE"] = 1] = "QRL_RESOLVE";
|
|
764
|
+
ChoreType[ChoreType["RUN_QRL"] = 2] = "RUN_QRL";
|
|
765
|
+
ChoreType[ChoreType["TASK"] = 3] = "TASK";
|
|
766
|
+
ChoreType[ChoreType["NODE_DIFF"] = 4] = "NODE_DIFF";
|
|
767
|
+
ChoreType[ChoreType["NODE_PROP"] = 5] = "NODE_PROP";
|
|
768
|
+
ChoreType[ChoreType["COMPONENT"] = 6] = "COMPONENT";
|
|
769
|
+
ChoreType[ChoreType["RECOMPUTE_AND_SCHEDULE_EFFECTS"] = 7] = "RECOMPUTE_AND_SCHEDULE_EFFECTS";
|
|
770
|
+
// Next macro level
|
|
771
|
+
ChoreType[ChoreType["JOURNAL_FLUSH"] = 16] = "JOURNAL_FLUSH";
|
|
772
|
+
// Next macro level
|
|
773
|
+
ChoreType[ChoreType["VISIBLE"] = 32] = "VISIBLE";
|
|
774
|
+
// Next macro level
|
|
775
|
+
ChoreType[ChoreType["CLEANUP_VISIBLE"] = 48] = "CLEANUP_VISIBLE";
|
|
776
|
+
// Next macro level
|
|
777
|
+
ChoreType[ChoreType["WAIT_FOR_ALL"] = 255] = "WAIT_FOR_ALL";
|
|
778
|
+
})(ChoreType || (ChoreType = {}));
|
|
779
|
+
|
|
780
|
+
// <docs markdown="../readme.md#useLexicalScope">
|
|
781
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
782
|
+
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
783
|
+
/**
|
|
784
|
+
* Used by the Qwik Optimizer to restore the lexically scoped variables.
|
|
785
|
+
*
|
|
786
|
+
* This method should not be present in the application source code.
|
|
787
|
+
*
|
|
788
|
+
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
|
|
789
|
+
* (before any `await` statements.)
|
|
790
|
+
*
|
|
791
|
+
* @internal
|
|
792
|
+
*/
|
|
793
|
+
// </docs>
|
|
794
|
+
const useLexicalScope = () => {
|
|
795
|
+
const context = getInvokeContext();
|
|
796
|
+
let qrl = context.$qrl$;
|
|
797
|
+
if (!qrl) {
|
|
798
|
+
const el = context.$element$;
|
|
799
|
+
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
|
|
800
|
+
const containerElement = _getQContainerElement(el);
|
|
801
|
+
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
|
|
802
|
+
const container = getDomContainer(containerElement);
|
|
803
|
+
qrl = container.parseQRL(decodeURIComponent(String(context.$url$)));
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
assertQrl(qrl);
|
|
807
|
+
assertDefined(qrl.$captureRef$, 'invoke: qrl $captureRef$ must be defined inside useLexicalScope()', qrl);
|
|
808
|
+
}
|
|
809
|
+
return qrl.$captureRef$;
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* This is called by qwik-loader to schedule a QRL. It has to be synchronous.
|
|
814
|
+
*
|
|
815
|
+
* @internal
|
|
816
|
+
*/
|
|
817
|
+
const queueQRL = (...args) => {
|
|
818
|
+
// This will already check container
|
|
819
|
+
const [runQrl] = useLexicalScope();
|
|
820
|
+
const context = getInvokeContext();
|
|
821
|
+
const hostElement = context.$hostElement$;
|
|
822
|
+
const container = getDomContainer(hostElement);
|
|
823
|
+
const scheduler = container.$scheduler$;
|
|
824
|
+
if (!scheduler) {
|
|
825
|
+
throw qError(QError.schedulerNotFound);
|
|
826
|
+
}
|
|
827
|
+
return scheduler(ChoreType.RUN_QRL, hostElement, runQrl, args);
|
|
828
|
+
};
|
|
829
|
+
|
|
732
830
|
/**
|
|
733
831
|
* Allows to project the children of the current component. <Slot/> can only be used within the
|
|
734
832
|
* context of a component defined with `component$`.
|
|
@@ -853,6 +951,47 @@
|
|
|
853
951
|
return key.startsWith('preventdefault:');
|
|
854
952
|
}
|
|
855
953
|
|
|
954
|
+
function getFileLocationFromJsx(jsxDev) {
|
|
955
|
+
if (!jsxDev) {
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
959
|
+
if (sanitizedFileName) {
|
|
960
|
+
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
961
|
+
}
|
|
962
|
+
return null;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const styleContent = (styleId) => {
|
|
966
|
+
return ComponentStylesPrefixContent + styleId;
|
|
967
|
+
};
|
|
968
|
+
function hasClassAttr(props) {
|
|
969
|
+
for (const key in props) {
|
|
970
|
+
if (Object.prototype.hasOwnProperty.call(props, key) && isClassAttr(key)) {
|
|
971
|
+
return true;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return false;
|
|
975
|
+
}
|
|
976
|
+
function isClassAttr(key) {
|
|
977
|
+
return key === 'class' || key === 'className';
|
|
978
|
+
}
|
|
979
|
+
function convertScopedStyleIdsToArray(scopedStyleIds) {
|
|
980
|
+
return scopedStyleIds?.split(' ') ?? null;
|
|
981
|
+
}
|
|
982
|
+
function convertStyleIdsToString(scopedStyleIds) {
|
|
983
|
+
return Array.from(scopedStyleIds).join(' ');
|
|
984
|
+
}
|
|
985
|
+
const addComponentStylePrefix = (styleId) => {
|
|
986
|
+
if (styleId) {
|
|
987
|
+
let idx = 0;
|
|
988
|
+
do {
|
|
989
|
+
styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
|
|
990
|
+
} while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
|
|
991
|
+
}
|
|
992
|
+
return styleId || null;
|
|
993
|
+
};
|
|
994
|
+
|
|
856
995
|
/** CSS properties which accept numbers but are not in units of "px". */
|
|
857
996
|
const unitlessNumbers = new Set([
|
|
858
997
|
'animationIterationCount',
|
|
@@ -1011,36 +1150,6 @@
|
|
|
1011
1150
|
assertQrl(qStyles);
|
|
1012
1151
|
return `${hashCode(qStyles.$hash$)}-${index}`;
|
|
1013
1152
|
};
|
|
1014
|
-
const styleContent = (styleId) => {
|
|
1015
|
-
return ComponentStylesPrefixContent + styleId;
|
|
1016
|
-
};
|
|
1017
|
-
|
|
1018
|
-
function hasClassAttr(props) {
|
|
1019
|
-
for (const key in props) {
|
|
1020
|
-
if (Object.prototype.hasOwnProperty.call(props, key) && isClassAttr(key)) {
|
|
1021
|
-
return true;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
return false;
|
|
1025
|
-
}
|
|
1026
|
-
function isClassAttr(key) {
|
|
1027
|
-
return key === 'class' || key === 'className';
|
|
1028
|
-
}
|
|
1029
|
-
function convertScopedStyleIdsToArray(scopedStyleIds) {
|
|
1030
|
-
return scopedStyleIds?.split(' ') ?? null;
|
|
1031
|
-
}
|
|
1032
|
-
function convertStyleIdsToString(scopedStyleIds) {
|
|
1033
|
-
return Array.from(scopedStyleIds).join(' ');
|
|
1034
|
-
}
|
|
1035
|
-
const addComponentStylePrefix = (styleId) => {
|
|
1036
|
-
if (styleId) {
|
|
1037
|
-
let idx = 0;
|
|
1038
|
-
do {
|
|
1039
|
-
styleId = styleId.substring(0, idx) + styleContent(styleId.substring(idx));
|
|
1040
|
-
} while ((idx = styleId.indexOf(' ', idx) + 1) !== 0);
|
|
1041
|
-
}
|
|
1042
|
-
return styleId || null;
|
|
1043
|
-
};
|
|
1044
1153
|
|
|
1045
1154
|
const STORE_TARGET = Symbol('store.target');
|
|
1046
1155
|
const STORE_HANDLER = Symbol('store.handler');
|
|
@@ -1185,8 +1294,12 @@
|
|
|
1185
1294
|
return Reflect.ownKeys(target);
|
|
1186
1295
|
}
|
|
1187
1296
|
getOwnPropertyDescriptor(target, prop) {
|
|
1297
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
1188
1298
|
if (Array.isArray(target) || typeof prop === 'symbol') {
|
|
1189
|
-
return
|
|
1299
|
+
return descriptor;
|
|
1300
|
+
}
|
|
1301
|
+
if (descriptor && !descriptor.configurable) {
|
|
1302
|
+
return descriptor;
|
|
1190
1303
|
}
|
|
1191
1304
|
return {
|
|
1192
1305
|
enumerable: true,
|
|
@@ -1194,39 +1307,185 @@
|
|
|
1194
1307
|
};
|
|
1195
1308
|
}
|
|
1196
1309
|
}
|
|
1197
|
-
function addEffect(target, prop, store,
|
|
1198
|
-
const effectsMap = (store.$effects$ ||=
|
|
1199
|
-
|
|
1200
|
-
|
|
1310
|
+
function addEffect(target, prop, store, effectSubscription) {
|
|
1311
|
+
const effectsMap = (store.$effects$ ||= new Map());
|
|
1312
|
+
let effects = effectsMap.get(prop);
|
|
1313
|
+
if (!effects) {
|
|
1314
|
+
effects = new Set();
|
|
1315
|
+
effectsMap.set(prop, effects);
|
|
1316
|
+
}
|
|
1201
1317
|
// Let's make sure that we have a reference to this effect.
|
|
1202
1318
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
1203
1319
|
// changes we know who to notify.
|
|
1204
|
-
|
|
1320
|
+
ensureContainsSubscription(effects, effectSubscription);
|
|
1205
1321
|
// But when effect is scheduled in needs to be able to know which signals
|
|
1206
1322
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
1207
1323
|
// to this signal.
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], target, store.$container$);
|
|
1324
|
+
ensureContainsBackRef(effectSubscription, target);
|
|
1325
|
+
addQrlToSerializationCtx(effectSubscription, store.$container$);
|
|
1211
1326
|
}
|
|
1212
1327
|
function setNewValueAndTriggerEffects(prop, value, target, currentStore) {
|
|
1213
1328
|
target[prop] = value;
|
|
1214
1329
|
triggerEffects(currentStore.$container$, currentStore, getEffects(target, prop, currentStore.$effects$));
|
|
1215
1330
|
}
|
|
1216
1331
|
function getEffects(target, prop, storeEffects) {
|
|
1217
|
-
let effectsToTrigger
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1332
|
+
let effectsToTrigger;
|
|
1333
|
+
if (storeEffects) {
|
|
1334
|
+
if (Array.isArray(target)) {
|
|
1335
|
+
for (const effects of storeEffects.values()) {
|
|
1336
|
+
effectsToTrigger ||= new Set();
|
|
1337
|
+
for (const effect of effects) {
|
|
1338
|
+
effectsToTrigger.add(effect);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
else {
|
|
1343
|
+
effectsToTrigger = storeEffects.get(prop);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
const storeArrayValue = storeEffects?.get(STORE_ARRAY_PROP);
|
|
1223
1347
|
if (storeArrayValue) {
|
|
1224
|
-
effectsToTrigger ||=
|
|
1225
|
-
|
|
1348
|
+
effectsToTrigger ||= new Set();
|
|
1349
|
+
for (const effect of storeArrayValue) {
|
|
1350
|
+
effectsToTrigger.add(effect);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
return effectsToTrigger || null;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1357
|
+
* Special value used to mark that a given signal needs to be computed. This is essentially a
|
|
1358
|
+
* "marked as dirty" flag.
|
|
1359
|
+
*/
|
|
1360
|
+
const NEEDS_COMPUTATION = Symbol('invalid');
|
|
1361
|
+
/** @internal */
|
|
1362
|
+
const _EFFECT_BACK_REF = Symbol('backRef');
|
|
1363
|
+
|
|
1364
|
+
/** Class for back reference to the EffectSubscription */
|
|
1365
|
+
class BackRef {
|
|
1366
|
+
[_EFFECT_BACK_REF] = null;
|
|
1367
|
+
}
|
|
1368
|
+
function clearAllEffects(container, consumer) {
|
|
1369
|
+
if (vnode_isVNode(consumer) && vnode_isElementVNode(consumer)) {
|
|
1370
|
+
ensureMaterialized(consumer);
|
|
1371
|
+
}
|
|
1372
|
+
const effects = consumer[_EFFECT_BACK_REF];
|
|
1373
|
+
if (!effects) {
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
for (const [, effect] of effects) {
|
|
1377
|
+
const backRefs = effect[EffectSubscriptionProp.BACK_REF];
|
|
1378
|
+
if (!backRefs) {
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
for (const producer of backRefs) {
|
|
1382
|
+
if (producer instanceof Signal) {
|
|
1383
|
+
clearSignal(container, producer, effect);
|
|
1384
|
+
}
|
|
1385
|
+
else if (container.$storeProxyMap$.has(producer)) {
|
|
1386
|
+
const target = container.$storeProxyMap$.get(producer);
|
|
1387
|
+
const storeHandler = getStoreHandler(target);
|
|
1388
|
+
clearStore(storeHandler, effect);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
function clearSignal(container, producer, effect) {
|
|
1394
|
+
const effects = producer.$effects$;
|
|
1395
|
+
if (effects) {
|
|
1396
|
+
effects.delete(effect);
|
|
1397
|
+
}
|
|
1398
|
+
if (producer instanceof WrappedSignal) {
|
|
1399
|
+
producer.$hostElement$ = null;
|
|
1400
|
+
clearAllEffects(container, producer);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
function clearStore(producer, effect) {
|
|
1404
|
+
const effects = producer?.$effects$;
|
|
1405
|
+
if (effects) {
|
|
1406
|
+
for (const propEffects of effects.values()) {
|
|
1407
|
+
propEffects.delete(effect);
|
|
1408
|
+
}
|
|
1226
1409
|
}
|
|
1227
|
-
return effectsToTrigger;
|
|
1228
1410
|
}
|
|
1229
1411
|
|
|
1412
|
+
// <docs markdown="../../readme.md#implicit$FirstArg">
|
|
1413
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
1414
|
+
// (edit ../../readme.md#implicit$FirstArg instead and run `pnpm docs.sync`)
|
|
1415
|
+
/**
|
|
1416
|
+
* Create a `____$(...)` convenience method from `___(...)`.
|
|
1417
|
+
*
|
|
1418
|
+
* It is very common for functions to take a lazy-loadable resource as a first argument. For this
|
|
1419
|
+
* reason, the Qwik Optimizer automatically extracts the first argument from any function which ends
|
|
1420
|
+
* in `$`.
|
|
1421
|
+
*
|
|
1422
|
+
* This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
|
|
1423
|
+
* The former is just a shorthand for the latter.
|
|
1424
|
+
*
|
|
1425
|
+
* For example, these function calls are equivalent:
|
|
1426
|
+
*
|
|
1427
|
+
* - `component$(() => {...})` is same as `component($(() => {...}))`
|
|
1428
|
+
*
|
|
1429
|
+
* ```tsx
|
|
1430
|
+
* export function myApi(callback: QRL<() => void>): void {
|
|
1431
|
+
* // ...
|
|
1432
|
+
* }
|
|
1433
|
+
*
|
|
1434
|
+
* export const myApi$ = implicit$FirstArg(myApi);
|
|
1435
|
+
* // type of myApi$: (callback: () => void): void
|
|
1436
|
+
*
|
|
1437
|
+
* // can be used as:
|
|
1438
|
+
* myApi$(() => console.log('callback'));
|
|
1439
|
+
*
|
|
1440
|
+
* // will be transpiled to:
|
|
1441
|
+
* // FILE: <current file>
|
|
1442
|
+
* myApi(qrl('./chunk-abc.js', 'callback'));
|
|
1443
|
+
*
|
|
1444
|
+
* // FILE: chunk-abc.js
|
|
1445
|
+
* export const callback = () => console.log('callback');
|
|
1446
|
+
* ```
|
|
1447
|
+
*
|
|
1448
|
+
* @param fn - A function that should have its first argument automatically `$`.
|
|
1449
|
+
* @public
|
|
1450
|
+
*/
|
|
1451
|
+
// </docs>
|
|
1452
|
+
const implicit$FirstArg = (fn) => {
|
|
1453
|
+
return function (first, ...rest) {
|
|
1454
|
+
return fn.call(null, dollar(first), ...rest);
|
|
1455
|
+
};
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
const createSignal$1 = (value) => {
|
|
1459
|
+
return new Signal(null, value);
|
|
1460
|
+
};
|
|
1461
|
+
const createComputedSignal = (qrl) => {
|
|
1462
|
+
throwIfQRLNotResolved(qrl);
|
|
1463
|
+
return new ComputedSignal(null, qrl);
|
|
1464
|
+
};
|
|
1465
|
+
|
|
1466
|
+
/**
|
|
1467
|
+
* Creates a Signal with the given value. If no value is given, the signal is created with
|
|
1468
|
+
* `undefined`.
|
|
1469
|
+
*
|
|
1470
|
+
* @public
|
|
1471
|
+
*/
|
|
1472
|
+
const createSignal = createSignal$1;
|
|
1473
|
+
/** @internal */
|
|
1474
|
+
const createComputedQrl = createComputedSignal;
|
|
1475
|
+
/**
|
|
1476
|
+
* Create a computed signal which is calculated from the given QRL. A computed signal is a signal
|
|
1477
|
+
* which is calculated from other signals. When the signals change, the computed signal is
|
|
1478
|
+
* recalculated.
|
|
1479
|
+
*
|
|
1480
|
+
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
1481
|
+
* effects, and it mus be synchronous.
|
|
1482
|
+
*
|
|
1483
|
+
* If you need the function to be async, use `useSignal` and `useTask$` instead.
|
|
1484
|
+
*
|
|
1485
|
+
* @public
|
|
1486
|
+
*/
|
|
1487
|
+
const createComputed$ = /*#__PURE__*/ implicit$FirstArg(createComputedQrl);
|
|
1488
|
+
|
|
1230
1489
|
/**
|
|
1231
1490
|
* @internal
|
|
1232
1491
|
* The storage provider for hooks. Each invocation increases index i. Data is stored in an array.
|
|
@@ -1262,272 +1521,66 @@
|
|
|
1262
1521
|
};
|
|
1263
1522
|
};
|
|
1264
1523
|
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
return value instanceof Subscriber || value instanceof WrappedSignal;
|
|
1270
|
-
}
|
|
1271
|
-
function clearVNodeEffectDependencies(container, value) {
|
|
1272
|
-
if (vnode_isElementVNode(value)) {
|
|
1273
|
-
ensureMaterialized(value);
|
|
1274
|
-
}
|
|
1275
|
-
const effects = vnode_getProp(value, QSubscribers, container.$getObjectById$);
|
|
1276
|
-
if (!effects) {
|
|
1277
|
-
return;
|
|
1278
|
-
}
|
|
1279
|
-
for (let i = effects.length - 1; i >= 0; i--) {
|
|
1280
|
-
const subscriber = effects[i];
|
|
1281
|
-
clearEffects(subscriber, value, effects, i, container);
|
|
1282
|
-
}
|
|
1283
|
-
if (effects.length === 0) {
|
|
1284
|
-
vnode_setProp(value, QSubscribers, null);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
function clearSubscriberEffectDependencies(container, value) {
|
|
1288
|
-
if (value.$effectDependencies$) {
|
|
1289
|
-
for (let i = value.$effectDependencies$.length - 1; i >= 0; i--) {
|
|
1290
|
-
const subscriber = value.$effectDependencies$[i];
|
|
1291
|
-
clearEffects(subscriber, value, value.$effectDependencies$, i, container);
|
|
1524
|
+
function getSubscriber(effect, prop, data) {
|
|
1525
|
+
if (!effect[_EFFECT_BACK_REF]) {
|
|
1526
|
+
if (build.isServer && isSsrNode(effect)) {
|
|
1527
|
+
effect.setProp(QBackRefs, new Map());
|
|
1292
1528
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1529
|
+
else {
|
|
1530
|
+
effect[_EFFECT_BACK_REF] = new Map();
|
|
1295
1531
|
}
|
|
1296
1532
|
}
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
subscriptionRemoved = clearSignalEffects(subscriber, value, seenSet);
|
|
1303
|
-
}
|
|
1304
|
-
else if (container.$storeProxyMap$.has(subscriber)) {
|
|
1305
|
-
const store = container.$storeProxyMap$.get(subscriber);
|
|
1306
|
-
const handler = getStoreHandler(store);
|
|
1307
|
-
subscriptionRemoved = clearStoreEffects(handler, value);
|
|
1533
|
+
const subMap = effect[_EFFECT_BACK_REF];
|
|
1534
|
+
let sub = subMap.get(prop);
|
|
1535
|
+
if (!sub) {
|
|
1536
|
+
sub = [effect, prop];
|
|
1537
|
+
subMap.set(prop, sub);
|
|
1308
1538
|
}
|
|
1309
|
-
if (
|
|
1310
|
-
|
|
1539
|
+
if (data) {
|
|
1540
|
+
sub[EffectSubscriptionProp.DATA] = data;
|
|
1311
1541
|
}
|
|
1542
|
+
return sub;
|
|
1312
1543
|
}
|
|
1313
|
-
function
|
|
1314
|
-
|
|
1315
|
-
let subscriptionRemoved = false;
|
|
1316
|
-
if (effectSubscriptions) {
|
|
1317
|
-
for (let i = effectSubscriptions.length - 1; i >= 0; i--) {
|
|
1318
|
-
const effect = effectSubscriptions[i];
|
|
1319
|
-
if (effect[EffectSubscriptionsProp.EFFECT] === value) {
|
|
1320
|
-
effectSubscriptions.splice(i, 1);
|
|
1321
|
-
subscriptionRemoved = true;
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
if (subscriber instanceof WrappedSignal) {
|
|
1326
|
-
const hostElement = subscriber.$hostElement$;
|
|
1327
|
-
if (hostElement && hostElement === value) {
|
|
1328
|
-
subscriber.$hostElement$ = null;
|
|
1329
|
-
}
|
|
1330
|
-
// clear the effects of the arguments
|
|
1331
|
-
const args = subscriber.$args$;
|
|
1332
|
-
if (args) {
|
|
1333
|
-
clearArgsEffects(args, subscriber, seenSet);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
return subscriptionRemoved;
|
|
1337
|
-
}
|
|
1338
|
-
function clearStoreEffects(storeHandler, value) {
|
|
1339
|
-
const effectSubscriptions = storeHandler.$effects$;
|
|
1340
|
-
if (!effectSubscriptions) {
|
|
1341
|
-
return false;
|
|
1342
|
-
}
|
|
1343
|
-
let subscriptionRemoved = false;
|
|
1344
|
-
for (const key in effectSubscriptions) {
|
|
1345
|
-
const effects = effectSubscriptions[key];
|
|
1346
|
-
for (let i = effects.length - 1; i >= 0; i--) {
|
|
1347
|
-
const effect = effects[i];
|
|
1348
|
-
if (effect[EffectSubscriptionsProp.EFFECT] === value) {
|
|
1349
|
-
effects.splice(i, 1);
|
|
1350
|
-
subscriptionRemoved = true;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
if (effects.length === 0) {
|
|
1354
|
-
delete effectSubscriptions[key];
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
return subscriptionRemoved;
|
|
1358
|
-
}
|
|
1359
|
-
function clearArgsEffects(args, subscriber, seenSet) {
|
|
1360
|
-
for (let i = args.length - 1; i >= 0; i--) {
|
|
1361
|
-
const arg = args[i];
|
|
1362
|
-
clearArgEffect(arg, subscriber, seenSet);
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
function clearArgEffect(arg, subscriber, seenSet) {
|
|
1366
|
-
if (seenSet.has(arg)) {
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
seenSet.add(arg);
|
|
1370
|
-
if (isSignal(arg)) {
|
|
1371
|
-
clearSignalEffects(arg, subscriber, seenSet);
|
|
1372
|
-
}
|
|
1373
|
-
else if (typeof arg === 'object' && arg !== null) {
|
|
1374
|
-
if (isStore(arg)) {
|
|
1375
|
-
clearStoreEffects(getStoreHandler(arg), subscriber);
|
|
1376
|
-
}
|
|
1377
|
-
else {
|
|
1378
|
-
for (const key in arg) {
|
|
1379
|
-
clearArgEffect(arg[key], subscriber, seenSet);
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
else if (Array.isArray(arg)) {
|
|
1384
|
-
clearArgsEffects(arg, subscriber, seenSet);
|
|
1385
|
-
}
|
|
1386
|
-
else ;
|
|
1544
|
+
function isSsrNode(value) {
|
|
1545
|
+
return '__brand__' in value && 'currentComponentNode' in value;
|
|
1387
1546
|
}
|
|
1388
1547
|
|
|
1548
|
+
var TaskFlags;
|
|
1549
|
+
(function (TaskFlags) {
|
|
1550
|
+
TaskFlags[TaskFlags["VISIBLE_TASK"] = 1] = "VISIBLE_TASK";
|
|
1551
|
+
TaskFlags[TaskFlags["TASK"] = 2] = "TASK";
|
|
1552
|
+
TaskFlags[TaskFlags["RESOURCE"] = 4] = "RESOURCE";
|
|
1553
|
+
TaskFlags[TaskFlags["DIRTY"] = 8] = "DIRTY";
|
|
1554
|
+
})(TaskFlags || (TaskFlags = {}));
|
|
1389
1555
|
/** @internal */
|
|
1390
|
-
const
|
|
1391
|
-
const { val, set,
|
|
1392
|
-
if (val
|
|
1393
|
-
return
|
|
1556
|
+
const useTaskQrl = (qrl) => {
|
|
1557
|
+
const { val, set, iCtx, i } = useSequentialScope();
|
|
1558
|
+
if (val) {
|
|
1559
|
+
return;
|
|
1394
1560
|
}
|
|
1395
1561
|
assertQrl(qrl);
|
|
1562
|
+
set(1);
|
|
1563
|
+
const task = new Task(TaskFlags.DIRTY | TaskFlags.TASK, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
1564
|
+
// In V2 we add the task to the sequential scope. We need to do this
|
|
1565
|
+
// in order to be able to retrieve it later when the parent element is
|
|
1566
|
+
// deleted and we need to be able to release the task subscriptions.
|
|
1567
|
+
set(task);
|
|
1396
1568
|
const container = iCtx.$container$;
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
set(resource);
|
|
1402
|
-
return resource;
|
|
1403
|
-
};
|
|
1404
|
-
// <docs markdown="../readme.md#useResource">
|
|
1405
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
1406
|
-
// (edit ../readme.md#useResource instead and run `pnpm docs.sync`)
|
|
1407
|
-
/**
|
|
1408
|
-
* This method works like an async memoized function that runs whenever some tracked value changes
|
|
1409
|
-
* and returns some data.
|
|
1410
|
-
*
|
|
1411
|
-
* `useResource` however returns immediate a `ResourceReturn` object that contains the data and a
|
|
1412
|
-
* state that indicates if the data is available or not.
|
|
1413
|
-
*
|
|
1414
|
-
* The status can be one of the following:
|
|
1415
|
-
*
|
|
1416
|
-
* - `pending` - the data is not yet available.
|
|
1417
|
-
* - `resolved` - the data is available.
|
|
1418
|
-
* - `rejected` - the data is not available due to an error or timeout.
|
|
1419
|
-
*
|
|
1420
|
-
* Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
|
|
1421
|
-
* re-throw it (or a new Error), the resource status will never be `rejected`.
|
|
1422
|
-
*
|
|
1423
|
-
* ### Example
|
|
1424
|
-
*
|
|
1425
|
-
* Example showing how `useResource` to perform a fetch to request the weather, whenever the input
|
|
1426
|
-
* city name changes.
|
|
1427
|
-
*
|
|
1428
|
-
* ```tsx
|
|
1429
|
-
* const Cmp = component$(() => {
|
|
1430
|
-
* const cityS = useSignal('');
|
|
1431
|
-
*
|
|
1432
|
-
* const weatherResource = useResource$(async ({ track, cleanup }) => {
|
|
1433
|
-
* const cityName = track(cityS);
|
|
1434
|
-
* const abortController = new AbortController();
|
|
1435
|
-
* cleanup(() => abortController.abort('cleanup'));
|
|
1436
|
-
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
1437
|
-
* signal: abortController.signal,
|
|
1438
|
-
* });
|
|
1439
|
-
* const data = await res.json();
|
|
1440
|
-
* return data as { temp: number };
|
|
1441
|
-
* });
|
|
1442
|
-
*
|
|
1443
|
-
* return (
|
|
1444
|
-
* <div>
|
|
1445
|
-
* <input name="city" bind:value={cityS} />
|
|
1446
|
-
* <Resource
|
|
1447
|
-
* value={weatherResource}
|
|
1448
|
-
* onResolved={(weather) => {
|
|
1449
|
-
* return <div>Temperature: {weather.temp}</div>;
|
|
1450
|
-
* }}
|
|
1451
|
-
* />
|
|
1452
|
-
* </div>
|
|
1453
|
-
* );
|
|
1454
|
-
* });
|
|
1455
|
-
* ```
|
|
1456
|
-
*
|
|
1457
|
-
* @public
|
|
1458
|
-
* @see Resource
|
|
1459
|
-
* @see ResourceReturn
|
|
1460
|
-
*/
|
|
1461
|
-
// </docs>
|
|
1462
|
-
const Resource = (props) => {
|
|
1463
|
-
// Resource path
|
|
1464
|
-
return _jsxSorted(Fragment, null, null, getResourceValueAsPromise(props), 0, null);
|
|
1465
|
-
};
|
|
1466
|
-
function getResourceValueAsPromise(props) {
|
|
1467
|
-
const resource = props.value;
|
|
1468
|
-
if (isResourceReturn(resource)) {
|
|
1469
|
-
const isBrowser = !isServerPlatform();
|
|
1470
|
-
if (isBrowser) {
|
|
1471
|
-
// create a subscription for the resource._state changes
|
|
1472
|
-
const state = resource._state;
|
|
1473
|
-
if (state === 'pending' && props.onPending) {
|
|
1474
|
-
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
1475
|
-
}
|
|
1476
|
-
else if (state === 'rejected' && props.onRejected) {
|
|
1477
|
-
return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
|
|
1478
|
-
}
|
|
1479
|
-
else {
|
|
1480
|
-
const resolvedValue = untrack(() => resource._resolved);
|
|
1481
|
-
if (resolvedValue !== undefined) {
|
|
1482
|
-
// resolved, pending without onPending prop or rejected without onRejected prop
|
|
1483
|
-
return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
|
|
1484
|
-
}
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
return resource.value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1488
|
-
}
|
|
1489
|
-
else if (isPromise(resource)) {
|
|
1490
|
-
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1491
|
-
}
|
|
1492
|
-
else if (isSignal(resource)) {
|
|
1493
|
-
return Promise.resolve(resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1569
|
+
const promise = container.$scheduler$(ChoreType.TASK, task);
|
|
1570
|
+
if (isPromise(promise)) {
|
|
1571
|
+
// TODO: should we handle this differently?
|
|
1572
|
+
promise.catch(() => { });
|
|
1494
1573
|
}
|
|
1495
|
-
else {
|
|
1496
|
-
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
const _createResourceReturn = (opts) => {
|
|
1500
|
-
const resource = {
|
|
1501
|
-
__brand: 'resource',
|
|
1502
|
-
value: undefined,
|
|
1503
|
-
loading: isServerPlatform() ? false : true,
|
|
1504
|
-
_resolved: undefined,
|
|
1505
|
-
_error: undefined,
|
|
1506
|
-
_state: 'pending',
|
|
1507
|
-
_timeout: opts?.timeout ?? -1,
|
|
1508
|
-
_cache: 0,
|
|
1509
|
-
};
|
|
1510
|
-
return resource;
|
|
1511
1574
|
};
|
|
1512
|
-
const
|
|
1513
|
-
const result = _createResourceReturn(opts);
|
|
1514
|
-
result.value = initialPromise;
|
|
1515
|
-
return createStore(container, result, StoreFlags.RECURSIVE);
|
|
1516
|
-
};
|
|
1517
|
-
const isResourceReturn = (obj) => {
|
|
1518
|
-
return isObject(obj) && (getStoreTarget(obj) || obj).__brand === 'resource';
|
|
1519
|
-
};
|
|
1520
|
-
const runResource = (task, container, host) => {
|
|
1575
|
+
const runTask = (task, container, host) => {
|
|
1521
1576
|
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
1522
1577
|
cleanupTask(task);
|
|
1523
|
-
const iCtx = newInvokeContext(container.$locale$, host, undefined,
|
|
1578
|
+
const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
|
|
1524
1579
|
iCtx.$container$ = container;
|
|
1525
|
-
const taskFn = task.$qrl$.getFn(iCtx, () =>
|
|
1526
|
-
const resource = task.$state$;
|
|
1527
|
-
assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
|
|
1580
|
+
const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
|
|
1528
1581
|
const track = (obj, prop) => {
|
|
1529
1582
|
const ctx = newInvokeContext();
|
|
1530
|
-
ctx.$effectSubscriber$ =
|
|
1583
|
+
ctx.$effectSubscriber$ = getSubscriber(task, EffectProperty.COMPONENT);
|
|
1531
1584
|
ctx.$container$ = container;
|
|
1532
1585
|
return invoke(ctx, () => {
|
|
1533
1586
|
if (isFunction(obj)) {
|
|
@@ -1540,115 +1593,85 @@
|
|
|
1540
1593
|
return obj.value;
|
|
1541
1594
|
}
|
|
1542
1595
|
else {
|
|
1543
|
-
|
|
1596
|
+
throw qError(QError.trackObjectWithoutProp);
|
|
1544
1597
|
}
|
|
1545
1598
|
});
|
|
1546
1599
|
};
|
|
1547
1600
|
const handleError = (reason) => container.handleError(reason, host);
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
if (typeof fn === 'function') {
|
|
1565
|
-
cleanups.push(fn);
|
|
1566
|
-
}
|
|
1567
|
-
},
|
|
1568
|
-
cache(policy) {
|
|
1569
|
-
let milliseconds = 0;
|
|
1570
|
-
if (policy === 'immutable') {
|
|
1571
|
-
milliseconds = Infinity;
|
|
1572
|
-
}
|
|
1573
|
-
else {
|
|
1574
|
-
milliseconds = policy;
|
|
1575
|
-
}
|
|
1576
|
-
resource._cache = milliseconds;
|
|
1577
|
-
},
|
|
1578
|
-
previous: resourceTarget._resolved,
|
|
1579
|
-
};
|
|
1580
|
-
let resolve;
|
|
1581
|
-
let reject;
|
|
1582
|
-
let done = false;
|
|
1583
|
-
const setState = (resolved, value) => {
|
|
1584
|
-
if (!done) {
|
|
1585
|
-
done = true;
|
|
1586
|
-
if (resolved) {
|
|
1587
|
-
done = true;
|
|
1588
|
-
resource.loading = false;
|
|
1589
|
-
resource._state = 'resolved';
|
|
1590
|
-
resource._resolved = value;
|
|
1591
|
-
resource._error = undefined;
|
|
1592
|
-
resolve(value);
|
|
1593
|
-
}
|
|
1594
|
-
else {
|
|
1595
|
-
done = true;
|
|
1596
|
-
resource.loading = false;
|
|
1597
|
-
resource._state = 'rejected';
|
|
1598
|
-
resource._error = value;
|
|
1599
|
-
reject(value);
|
|
1601
|
+
let cleanupFns = null;
|
|
1602
|
+
const cleanup = (fn) => {
|
|
1603
|
+
if (typeof fn == 'function') {
|
|
1604
|
+
if (!cleanupFns) {
|
|
1605
|
+
cleanupFns = [];
|
|
1606
|
+
task.$destroy$ = noSerialize(() => {
|
|
1607
|
+
task.$destroy$ = null;
|
|
1608
|
+
cleanupFns.forEach((fn) => {
|
|
1609
|
+
try {
|
|
1610
|
+
fn();
|
|
1611
|
+
}
|
|
1612
|
+
catch (err) {
|
|
1613
|
+
handleError(err);
|
|
1614
|
+
}
|
|
1615
|
+
});
|
|
1616
|
+
});
|
|
1600
1617
|
}
|
|
1601
|
-
|
|
1618
|
+
cleanupFns.push(fn);
|
|
1602
1619
|
}
|
|
1603
|
-
return false;
|
|
1604
1620
|
};
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
*/
|
|
1609
|
-
cleanups.push(() => {
|
|
1610
|
-
if (untrack(() => resource.loading) === true) {
|
|
1611
|
-
const value = untrack(() => resource._resolved);
|
|
1612
|
-
setState(true, value);
|
|
1613
|
-
}
|
|
1614
|
-
});
|
|
1615
|
-
// Execute mutation inside empty invocation
|
|
1616
|
-
invoke(iCtx, () => {
|
|
1617
|
-
// console.log('RESOURCE.pending: ');
|
|
1618
|
-
resource._state = 'pending';
|
|
1619
|
-
resource.loading = !isServerPlatform();
|
|
1620
|
-
const promise = (resource.value = new Promise((r, re) => {
|
|
1621
|
-
resolve = r;
|
|
1622
|
-
reject = re;
|
|
1623
|
-
}));
|
|
1624
|
-
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
1625
|
-
});
|
|
1626
|
-
const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
|
|
1627
|
-
setState(true, value);
|
|
1628
|
-
}, (err) => {
|
|
1621
|
+
const taskApi = { track, cleanup };
|
|
1622
|
+
const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
1623
|
+
// If a Promise is thrown, that means we need to re-run the task.
|
|
1629
1624
|
if (isPromise(err)) {
|
|
1630
|
-
return err.then(() =>
|
|
1625
|
+
return err.then(() => runTask(task, container, host));
|
|
1631
1626
|
}
|
|
1632
1627
|
else {
|
|
1633
|
-
|
|
1628
|
+
throw err;
|
|
1634
1629
|
}
|
|
1635
1630
|
});
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1631
|
+
return result;
|
|
1632
|
+
};
|
|
1633
|
+
const cleanupTask = (task) => {
|
|
1634
|
+
const destroy = task.$destroy$;
|
|
1635
|
+
if (destroy) {
|
|
1636
|
+
task.$destroy$ = null;
|
|
1637
|
+
try {
|
|
1638
|
+
destroy();
|
|
1639
|
+
}
|
|
1640
|
+
catch (err) {
|
|
1641
|
+
logError(err);
|
|
1642
|
+
}
|
|
1646
1643
|
}
|
|
1647
|
-
return promise;
|
|
1648
1644
|
};
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1645
|
+
class Task extends BackRef {
|
|
1646
|
+
$flags$;
|
|
1647
|
+
$index$;
|
|
1648
|
+
$el$;
|
|
1649
|
+
$qrl$;
|
|
1650
|
+
$state$;
|
|
1651
|
+
$destroy$;
|
|
1652
|
+
constructor($flags$, $index$, $el$, $qrl$, $state$, $destroy$) {
|
|
1653
|
+
super();
|
|
1654
|
+
this.$flags$ = $flags$;
|
|
1655
|
+
this.$index$ = $index$;
|
|
1656
|
+
this.$el$ = $el$;
|
|
1657
|
+
this.$qrl$ = $qrl$;
|
|
1658
|
+
this.$state$ = $state$;
|
|
1659
|
+
this.$destroy$ = $destroy$;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
const isTask = (value) => {
|
|
1663
|
+
return value instanceof Task;
|
|
1664
|
+
};
|
|
1665
|
+
/**
|
|
1666
|
+
* Used internally as a qrl event handler to schedule a task.
|
|
1667
|
+
*
|
|
1668
|
+
* @internal
|
|
1669
|
+
*/
|
|
1670
|
+
const scheduleTask = (_event, element) => {
|
|
1671
|
+
const [task] = useLexicalScope();
|
|
1672
|
+
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
|
|
1673
|
+
const container = getDomContainer(element);
|
|
1674
|
+
container.$scheduler$(type, task);
|
|
1652
1675
|
};
|
|
1653
1676
|
|
|
1654
1677
|
/** @file Public types for the client deserialization */
|
|
@@ -1726,22 +1749,67 @@
|
|
|
1726
1749
|
VirtualVNodeProps[VirtualVNodeProps["PROPS_OFFSET"] = 6] = "PROPS_OFFSET";
|
|
1727
1750
|
})(VirtualVNodeProps || (VirtualVNodeProps = {}));
|
|
1728
1751
|
|
|
1729
|
-
const
|
|
1752
|
+
const mapApp_findIndx = (elementVNode, key, start) => {
|
|
1753
|
+
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
1754
|
+
let bottom = start >> 1;
|
|
1755
|
+
let top = (elementVNode.length - 2) >> 1;
|
|
1756
|
+
while (bottom <= top) {
|
|
1757
|
+
const mid = bottom + ((top - bottom) >> 1);
|
|
1758
|
+
const midKey = elementVNode[mid << 1];
|
|
1759
|
+
if (midKey === key) {
|
|
1760
|
+
return mid << 1;
|
|
1761
|
+
}
|
|
1762
|
+
if (midKey < key) {
|
|
1763
|
+
bottom = mid + 1;
|
|
1764
|
+
}
|
|
1765
|
+
else {
|
|
1766
|
+
top = mid - 1;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
return (bottom << 1) ^ -1;
|
|
1770
|
+
};
|
|
1771
|
+
const mapArray_set = (elementVNode, key, value, start) => {
|
|
1772
|
+
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
1773
|
+
if (indx >= 0) {
|
|
1774
|
+
if (value == null) {
|
|
1775
|
+
elementVNode.splice(indx, 2);
|
|
1776
|
+
}
|
|
1777
|
+
else {
|
|
1778
|
+
elementVNode[indx + 1] = value;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
else if (value != null) {
|
|
1782
|
+
elementVNode.splice(indx ^ -1, 0, key, value);
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
const mapArray_get = (elementVNode, key, start) => {
|
|
1786
|
+
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
1787
|
+
if (indx >= 0) {
|
|
1788
|
+
return elementVNode[indx + 1];
|
|
1789
|
+
}
|
|
1790
|
+
else {
|
|
1791
|
+
return null;
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
|
|
1795
|
+
const isForeignObjectElement = (elementName) => {
|
|
1796
|
+
return build.isDev ? elementName.toLowerCase() === 'foreignobject' : elementName === 'foreignObject';
|
|
1797
|
+
};
|
|
1730
1798
|
const isSvgElement = (elementName) => elementName === 'svg' || isForeignObjectElement(elementName);
|
|
1731
1799
|
const isMathElement = (elementName) => elementName === 'math';
|
|
1732
1800
|
const vnode_isDefaultNamespace = (vnode) => {
|
|
1733
1801
|
const flags = vnode[VNodeProps.flags];
|
|
1734
1802
|
return (flags & VNodeFlags.NAMESPACE_MASK) === 0;
|
|
1735
1803
|
};
|
|
1736
|
-
const vnode_getElementNamespaceFlags = (
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1804
|
+
const vnode_getElementNamespaceFlags = (element) => {
|
|
1805
|
+
const namespace = fastNamespaceURI(element);
|
|
1806
|
+
switch (namespace) {
|
|
1807
|
+
case SVG_NS:
|
|
1808
|
+
return VNodeFlags.NS_svg;
|
|
1809
|
+
case MATH_NS:
|
|
1810
|
+
return VNodeFlags.NS_math;
|
|
1811
|
+
default:
|
|
1812
|
+
return VNodeFlags.NS_html;
|
|
1745
1813
|
}
|
|
1746
1814
|
};
|
|
1747
1815
|
function vnode_getDomChildrenWithCorrectNamespacesToInsert(journal, domParentVNode, newChild) {
|
|
@@ -2095,19 +2163,21 @@
|
|
|
2095
2163
|
* @returns
|
|
2096
2164
|
*/
|
|
2097
2165
|
const executeComponent = (container, renderHost, subscriptionHost, componentQRL, props) => {
|
|
2098
|
-
const iCtx = newInvokeContext(container.$locale$, subscriptionHost, undefined, RenderEvent);
|
|
2099
|
-
|
|
2100
|
-
|
|
2166
|
+
const iCtx = newInvokeContext(container.$locale$, subscriptionHost || undefined, undefined, RenderEvent);
|
|
2167
|
+
if (subscriptionHost) {
|
|
2168
|
+
iCtx.$effectSubscriber$ = getSubscriber(subscriptionHost, EffectProperty.COMPONENT);
|
|
2169
|
+
iCtx.$container$ = container;
|
|
2170
|
+
}
|
|
2101
2171
|
let componentFn;
|
|
2102
2172
|
container.ensureProjectionResolved(renderHost);
|
|
2103
2173
|
let isInlineComponent = false;
|
|
2104
2174
|
if (componentQRL === null) {
|
|
2105
|
-
componentQRL =
|
|
2175
|
+
componentQRL = container.getHostProp(renderHost, OnRenderProp);
|
|
2106
2176
|
assertDefined(componentQRL, 'No Component found at this location');
|
|
2107
2177
|
}
|
|
2108
|
-
if (isQrl(componentQRL)) {
|
|
2178
|
+
if (isQrl$1(componentQRL)) {
|
|
2109
2179
|
props = props || container.getHostProp(renderHost, ELEMENT_PROPS) || EMPTY_OBJ;
|
|
2110
|
-
if (props
|
|
2180
|
+
if (props.children) {
|
|
2111
2181
|
delete props.children;
|
|
2112
2182
|
}
|
|
2113
2183
|
componentFn = componentQRL.getFn(iCtx);
|
|
@@ -2125,18 +2195,16 @@
|
|
|
2125
2195
|
if (!isInlineComponent) {
|
|
2126
2196
|
container.setHostProp(renderHost, ELEMENT_SEQ_IDX, null);
|
|
2127
2197
|
container.setHostProp(renderHost, USE_ON_LOCAL_SEQ_IDX, null);
|
|
2128
|
-
|
|
2129
|
-
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2130
|
-
}
|
|
2198
|
+
container.setHostProp(renderHost, ELEMENT_PROPS, props);
|
|
2131
2199
|
}
|
|
2132
2200
|
if (vnode_isVNode(renderHost)) {
|
|
2133
|
-
|
|
2201
|
+
clearAllEffects(container, renderHost);
|
|
2134
2202
|
}
|
|
2135
2203
|
return componentFn(props);
|
|
2136
2204
|
}, (jsx) => {
|
|
2137
2205
|
const useOnEvents = container.getHostProp(renderHost, USE_ON_LOCAL);
|
|
2138
2206
|
if (useOnEvents) {
|
|
2139
|
-
return
|
|
2207
|
+
return addUseOnEvents(jsx, useOnEvents);
|
|
2140
2208
|
}
|
|
2141
2209
|
return jsx;
|
|
2142
2210
|
}, (err) => {
|
|
@@ -2162,6 +2230,7 @@
|
|
|
2162
2230
|
*/
|
|
2163
2231
|
function addUseOnEvents(jsx, useOnEvents) {
|
|
2164
2232
|
const jsxElement = findFirstStringJSX(jsx);
|
|
2233
|
+
let jsxResult = jsx;
|
|
2165
2234
|
return maybeThen(jsxElement, (jsxElement) => {
|
|
2166
2235
|
let isInvisibleComponent = false;
|
|
2167
2236
|
if (!jsxElement) {
|
|
@@ -2180,13 +2249,15 @@
|
|
|
2180
2249
|
if (Object.prototype.hasOwnProperty.call(useOnEvents, key)) {
|
|
2181
2250
|
if (isInvisibleComponent) {
|
|
2182
2251
|
if (key === 'onQvisible$') {
|
|
2183
|
-
jsxElement = addScriptNodeForInvisibleComponents(
|
|
2252
|
+
const [jsxElement, jsx] = addScriptNodeForInvisibleComponents(jsxResult);
|
|
2253
|
+
jsxResult = jsx;
|
|
2184
2254
|
if (jsxElement) {
|
|
2185
2255
|
addUseOnEvent(jsxElement, 'document:onQinit$', useOnEvents[key]);
|
|
2186
2256
|
}
|
|
2187
2257
|
}
|
|
2188
2258
|
else if (key.startsWith('document:') || key.startsWith('window:')) {
|
|
2189
|
-
jsxElement = addScriptNodeForInvisibleComponents(
|
|
2259
|
+
const [jsxElement, jsx] = addScriptNodeForInvisibleComponents(jsxResult);
|
|
2260
|
+
jsxResult = jsx;
|
|
2190
2261
|
if (jsxElement) {
|
|
2191
2262
|
addUseOnEvent(jsxElement, key, useOnEvents[key]);
|
|
2192
2263
|
}
|
|
@@ -2204,7 +2275,7 @@
|
|
|
2204
2275
|
}
|
|
2205
2276
|
}
|
|
2206
2277
|
}
|
|
2207
|
-
return
|
|
2278
|
+
return jsxResult;
|
|
2208
2279
|
});
|
|
2209
2280
|
}
|
|
2210
2281
|
function addUseOnEvent(jsxElement, key, value) {
|
|
@@ -2250,6 +2321,9 @@
|
|
|
2250
2321
|
type: 'placeholder',
|
|
2251
2322
|
hidden: '',
|
|
2252
2323
|
}, null, 3);
|
|
2324
|
+
if (jsx.type === Slot) {
|
|
2325
|
+
return [jsxElement, _jsxSorted(Fragment, null, null, [jsx, jsxElement], 0, null)];
|
|
2326
|
+
}
|
|
2253
2327
|
if (jsx.children == null) {
|
|
2254
2328
|
jsx.children = jsxElement;
|
|
2255
2329
|
}
|
|
@@ -2259,15 +2333,23 @@
|
|
|
2259
2333
|
else {
|
|
2260
2334
|
jsx.children = [jsx.children, jsxElement];
|
|
2261
2335
|
}
|
|
2262
|
-
return jsxElement;
|
|
2336
|
+
return [jsxElement, jsx];
|
|
2263
2337
|
}
|
|
2264
2338
|
else if (Array.isArray(jsx) && jsx.length) {
|
|
2265
2339
|
// get first element
|
|
2266
|
-
|
|
2340
|
+
const [jsxElement, _] = addScriptNodeForInvisibleComponents(jsx[0]);
|
|
2341
|
+
return [jsxElement, jsx];
|
|
2267
2342
|
}
|
|
2268
|
-
return null;
|
|
2343
|
+
return [null, null];
|
|
2269
2344
|
}
|
|
2270
2345
|
|
|
2346
|
+
/** @internal */
|
|
2347
|
+
const _CONST_PROPS = Symbol('CONST');
|
|
2348
|
+
/** @internal */
|
|
2349
|
+
const _VAR_PROPS = Symbol('VAR');
|
|
2350
|
+
/** @internal @deprecated v1 compat */
|
|
2351
|
+
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
2352
|
+
|
|
2271
2353
|
function isSlotProp(prop) {
|
|
2272
2354
|
return !prop.startsWith('q:') && !prop.startsWith(NON_SERIALIZABLE_MARKER_PREFIX);
|
|
2273
2355
|
}
|
|
@@ -2276,12 +2358,24 @@
|
|
|
2276
2358
|
}
|
|
2277
2359
|
/** @internal */
|
|
2278
2360
|
const _restProps = (props, omit, target = {}) => {
|
|
2279
|
-
|
|
2361
|
+
let constPropsTarget = null;
|
|
2362
|
+
const constProps = props[_CONST_PROPS];
|
|
2363
|
+
if (constProps) {
|
|
2364
|
+
for (const key in constProps) {
|
|
2365
|
+
if (!omit.includes(key)) {
|
|
2366
|
+
constPropsTarget ||= {};
|
|
2367
|
+
constPropsTarget[key] = constProps[key];
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
const varPropsTarget = target;
|
|
2372
|
+
const varProps = props[_VAR_PROPS];
|
|
2373
|
+
for (const key in varProps) {
|
|
2280
2374
|
if (!omit.includes(key)) {
|
|
2281
|
-
|
|
2375
|
+
varPropsTarget[key] = varProps[key];
|
|
2282
2376
|
}
|
|
2283
2377
|
}
|
|
2284
|
-
return
|
|
2378
|
+
return createPropsProxy(varPropsTarget, constPropsTarget);
|
|
2285
2379
|
};
|
|
2286
2380
|
|
|
2287
2381
|
function escapeHTML(html) {
|
|
@@ -2323,17 +2417,6 @@
|
|
|
2323
2417
|
}
|
|
2324
2418
|
}
|
|
2325
2419
|
|
|
2326
|
-
function getFileLocationFromJsx(jsxDev) {
|
|
2327
|
-
if (!jsxDev) {
|
|
2328
|
-
return null;
|
|
2329
|
-
}
|
|
2330
|
-
const sanitizedFileName = jsxDev.fileName?.replace(/\\/g, '/');
|
|
2331
|
-
if (sanitizedFileName) {
|
|
2332
|
-
return `${sanitizedFileName}:${jsxDev.lineNumber}:${jsxDev.columnNumber}`;
|
|
2333
|
-
}
|
|
2334
|
-
return null;
|
|
2335
|
-
}
|
|
2336
|
-
|
|
2337
2420
|
const vnode_diff = (container, jsxNode, vStartNode, scopedStyleIdPrefix) => {
|
|
2338
2421
|
let journal = container.$journal$;
|
|
2339
2422
|
/**
|
|
@@ -2352,9 +2435,9 @@
|
|
|
2352
2435
|
/// (Node can be null, if we are at the end of the list.)
|
|
2353
2436
|
let vCurrent = null;
|
|
2354
2437
|
/// When we insert new node we start it here so that we can descend into it.
|
|
2355
|
-
/// NOTE: it can't be stored in `vCurrent` because `
|
|
2438
|
+
/// NOTE: it can't be stored in `vCurrent` because `vNewNode` is in journal
|
|
2356
2439
|
/// and is not connected to the tree.
|
|
2357
|
-
let vNewNode = null;
|
|
2440
|
+
let vNewNode = null;
|
|
2358
2441
|
/// When elements have keys they can be consumed out of order and therefore we can't use nextSibling.
|
|
2359
2442
|
/// In such a case this array will contain the elements after the current location.
|
|
2360
2443
|
/// The array even indices will contains keys and odd indices the vNode.
|
|
@@ -2407,7 +2490,7 @@
|
|
|
2407
2490
|
}
|
|
2408
2491
|
else if (isSignal(jsxValue)) {
|
|
2409
2492
|
if (vCurrent) {
|
|
2410
|
-
|
|
2493
|
+
clearAllEffects(container, vCurrent);
|
|
2411
2494
|
}
|
|
2412
2495
|
expectVirtual(VirtualType.WrappedSignal, null);
|
|
2413
2496
|
descend(trackSignalAndAssignHost(jsxValue, (vNewNode || vCurrent), EffectProperty.VNODE, container), true);
|
|
@@ -2622,9 +2705,10 @@
|
|
|
2622
2705
|
};
|
|
2623
2706
|
const projections = [];
|
|
2624
2707
|
if (host) {
|
|
2708
|
+
const props = vnode_getProps(host);
|
|
2625
2709
|
// we need to create empty projections for all the slots to remove unused slots content
|
|
2626
|
-
for (let i =
|
|
2627
|
-
const prop =
|
|
2710
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
2711
|
+
const prop = props[i];
|
|
2628
2712
|
if (isSlotProp(prop)) {
|
|
2629
2713
|
const slotName = prop;
|
|
2630
2714
|
projections.push(slotName);
|
|
@@ -2792,10 +2876,19 @@
|
|
|
2792
2876
|
// But we need to mark them so that they don't get pulled into the diff.
|
|
2793
2877
|
const eventName = getEventNameFromJsxProp(key);
|
|
2794
2878
|
const scope = getEventNameScopeFromJsxProp(key);
|
|
2795
|
-
vnode_setProp(vNewNode, HANDLER_PREFIX + ':' + scope + ':' + eventName, value);
|
|
2796
2879
|
if (eventName) {
|
|
2880
|
+
vnode_setProp(vNewNode, HANDLER_PREFIX + ':' + scope + ':' + eventName, value);
|
|
2797
2881
|
registerQwikLoaderEvent(eventName);
|
|
2798
2882
|
}
|
|
2883
|
+
if (scope) {
|
|
2884
|
+
// add an event attr with empty value for qwikloader element selector.
|
|
2885
|
+
// We don't need value here. For ssr this value is a QRL,
|
|
2886
|
+
// but for CSR value should be just empty
|
|
2887
|
+
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
2888
|
+
if (htmlEvent) {
|
|
2889
|
+
vnode_setAttr(journal, vNewNode, htmlEvent, '');
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2799
2892
|
needsQDispatchEventPatch = true;
|
|
2800
2893
|
continue;
|
|
2801
2894
|
}
|
|
@@ -2808,12 +2901,15 @@
|
|
|
2808
2901
|
value(element);
|
|
2809
2902
|
continue;
|
|
2810
2903
|
}
|
|
2904
|
+
else if (value == null) {
|
|
2905
|
+
continue;
|
|
2906
|
+
}
|
|
2811
2907
|
else {
|
|
2812
2908
|
throw qError(QError.invalidRefValue, [currentFile]);
|
|
2813
2909
|
}
|
|
2814
2910
|
}
|
|
2815
2911
|
if (isSignal(value)) {
|
|
2816
|
-
const signalData = new
|
|
2912
|
+
const signalData = new SubscriptionData({
|
|
2817
2913
|
$scopedStyleIdPrefix$: scopedStyleIdPrefix,
|
|
2818
2914
|
$isConst$: true,
|
|
2819
2915
|
});
|
|
@@ -2917,7 +3013,7 @@
|
|
|
2917
3013
|
let returnValue = false;
|
|
2918
3014
|
qrls.flat(2).forEach((qrl) => {
|
|
2919
3015
|
if (qrl) {
|
|
2920
|
-
const value = qrl
|
|
3016
|
+
const value = container.$scheduler$(ChoreType.RUN_QRL, vNode, qrl, [event, element]);
|
|
2921
3017
|
returnValue = returnValue || value === true;
|
|
2922
3018
|
}
|
|
2923
3019
|
});
|
|
@@ -2929,10 +3025,10 @@
|
|
|
2929
3025
|
/** @param tag Returns true if `qDispatchEvent` needs patching */
|
|
2930
3026
|
function setBulkProps(vnode, srcAttrs, currentFile) {
|
|
2931
3027
|
vnode_ensureElementInflated(vnode);
|
|
2932
|
-
const dstAttrs = vnode;
|
|
3028
|
+
const dstAttrs = vnode_getProps(vnode);
|
|
2933
3029
|
let srcIdx = 0;
|
|
2934
3030
|
const srcLength = srcAttrs.length;
|
|
2935
|
-
let dstIdx =
|
|
3031
|
+
let dstIdx = 0;
|
|
2936
3032
|
let dstLength = dstAttrs.length;
|
|
2937
3033
|
let srcKey = srcIdx < srcLength ? srcAttrs[srcIdx++] : null;
|
|
2938
3034
|
let dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
|
|
@@ -2952,12 +3048,15 @@
|
|
|
2952
3048
|
value(element);
|
|
2953
3049
|
return;
|
|
2954
3050
|
}
|
|
3051
|
+
else if (value == null) {
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
2955
3054
|
else {
|
|
2956
3055
|
throw qError(QError.invalidRefValue, [currentFile]);
|
|
2957
3056
|
}
|
|
2958
3057
|
}
|
|
2959
3058
|
if (isSignal(value)) {
|
|
2960
|
-
const signalData = new
|
|
3059
|
+
const signalData = new SubscriptionData({
|
|
2961
3060
|
$scopedStyleIdPrefix$: scopedStyleIdPrefix,
|
|
2962
3061
|
$isConst$: false,
|
|
2963
3062
|
});
|
|
@@ -2971,21 +3070,21 @@
|
|
|
2971
3070
|
};
|
|
2972
3071
|
const recordJsxEvent = (key, value) => {
|
|
2973
3072
|
const eventName = getEventNameFromJsxProp(key);
|
|
3073
|
+
const scope = getEventNameScopeFromJsxProp(key);
|
|
2974
3074
|
if (eventName) {
|
|
2975
|
-
const scope = getEventNameScopeFromJsxProp(key);
|
|
2976
3075
|
record(':' + scope + ':' + eventName, value);
|
|
2977
|
-
|
|
2978
|
-
// add an event attr with empty value for qwikloader element selector.
|
|
2979
|
-
// We don't need value here. For ssr this value is a QRL,
|
|
2980
|
-
// but for CSR value should be just empty
|
|
2981
|
-
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
2982
|
-
if (htmlEvent) {
|
|
2983
|
-
record(htmlEvent, '');
|
|
2984
|
-
}
|
|
2985
|
-
// register an event for qwik loader
|
|
2986
|
-
if (eventName) {
|
|
3076
|
+
// register an event for qwik loader
|
|
2987
3077
|
registerQwikLoaderEvent(eventName);
|
|
2988
3078
|
}
|
|
3079
|
+
if (scope) {
|
|
3080
|
+
// add an event attr with empty value for qwikloader element selector.
|
|
3081
|
+
// We don't need value here. For ssr this value is a QRL,
|
|
3082
|
+
// but for CSR value should be just empty
|
|
3083
|
+
const htmlEvent = convertEventNameFromJsxPropToHtmlAttr(key);
|
|
3084
|
+
if (htmlEvent) {
|
|
3085
|
+
record(htmlEvent, '');
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
2989
3088
|
};
|
|
2990
3089
|
while (srcKey !== null || dstKey !== null) {
|
|
2991
3090
|
if (dstKey?.startsWith(HANDLER_PREFIX) || dstKey?.startsWith(Q_PREFIX)) {
|
|
@@ -3181,10 +3280,6 @@
|
|
|
3181
3280
|
else if (!hashesAreEqual) {
|
|
3182
3281
|
insertNewComponent(host, componentQRL, jsxProps);
|
|
3183
3282
|
if (vNewNode) {
|
|
3184
|
-
if (host) {
|
|
3185
|
-
// TODO(varixo): not sure why we need to copy flags here.
|
|
3186
|
-
vNewNode[VNodeProps.flags] = host[VNodeProps.flags];
|
|
3187
|
-
}
|
|
3188
3283
|
host = vNewNode;
|
|
3189
3284
|
shouldRender = true;
|
|
3190
3285
|
}
|
|
@@ -3237,7 +3332,7 @@
|
|
|
3237
3332
|
}
|
|
3238
3333
|
function insertNewComponent(host, componentQRL, jsxProps) {
|
|
3239
3334
|
if (host) {
|
|
3240
|
-
|
|
3335
|
+
clearAllEffects(container, host);
|
|
3241
3336
|
}
|
|
3242
3337
|
vnode_insertBefore(journal, vParent, (vNewNode = vnode_newVirtual()), vCurrent && getInsertBefore());
|
|
3243
3338
|
const jsxNode = jsxValue;
|
|
@@ -3325,8 +3420,8 @@
|
|
|
3325
3420
|
if (!src || !dst) {
|
|
3326
3421
|
return true;
|
|
3327
3422
|
}
|
|
3328
|
-
let srcKeys = removePropsKeys(Object.keys(src), ['children',
|
|
3329
|
-
let dstKeys = removePropsKeys(Object.keys(dst), ['children',
|
|
3423
|
+
let srcKeys = removePropsKeys(Object.keys(src), ['children', QBackRefs]);
|
|
3424
|
+
let dstKeys = removePropsKeys(Object.keys(dst), ['children', QBackRefs]);
|
|
3330
3425
|
if (srcKeys.length !== dstKeys.length) {
|
|
3331
3426
|
return true;
|
|
3332
3427
|
}
|
|
@@ -3372,7 +3467,7 @@
|
|
|
3372
3467
|
do {
|
|
3373
3468
|
const type = vCursor[VNodeProps.flags];
|
|
3374
3469
|
if (type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) {
|
|
3375
|
-
|
|
3470
|
+
clearAllEffects(container, vCursor);
|
|
3376
3471
|
markVNodeAsDeleted(vCursor);
|
|
3377
3472
|
// Only elements and virtual nodes need to be traversed for children
|
|
3378
3473
|
if (type & VNodeFlags.Virtual) {
|
|
@@ -3382,7 +3477,7 @@
|
|
|
3382
3477
|
const obj = seq[i];
|
|
3383
3478
|
if (isTask(obj)) {
|
|
3384
3479
|
const task = obj;
|
|
3385
|
-
|
|
3480
|
+
clearAllEffects(container, task);
|
|
3386
3481
|
if (task.$flags$ & TaskFlags.VISIBLE_TASK) {
|
|
3387
3482
|
container.$scheduler$(ChoreType.CLEANUP_VISIBLE, task);
|
|
3388
3483
|
}
|
|
@@ -3397,8 +3492,8 @@
|
|
|
3397
3492
|
vnode_getProp(vCursor, OnRenderProp, null) !== null;
|
|
3398
3493
|
if (isComponent) {
|
|
3399
3494
|
// SPECIAL CASE: If we are a component, we need to descend into the projected content and release the content.
|
|
3400
|
-
const attrs = vCursor;
|
|
3401
|
-
for (let i =
|
|
3495
|
+
const attrs = vnode_getProps(vCursor);
|
|
3496
|
+
for (let i = 0; i < attrs.length; i = i + 2) {
|
|
3402
3497
|
const key = attrs[i];
|
|
3403
3498
|
if (!isParentSlotProp(key) && isSlotProp(key)) {
|
|
3404
3499
|
const value = attrs[i + 1];
|
|
@@ -3458,130 +3553,420 @@
|
|
|
3458
3553
|
// We are back where we started, we are done.
|
|
3459
3554
|
return;
|
|
3460
3555
|
}
|
|
3461
|
-
const vNextParentSibling = vnode_getNextSibling(vParent);
|
|
3462
|
-
if (vNextParentSibling) {
|
|
3463
|
-
vCursor = vNextParentSibling;
|
|
3464
|
-
break;
|
|
3556
|
+
const vNextParentSibling = vnode_getNextSibling(vParent);
|
|
3557
|
+
if (vNextParentSibling) {
|
|
3558
|
+
vCursor = vNextParentSibling;
|
|
3559
|
+
break;
|
|
3560
|
+
}
|
|
3561
|
+
vParent = vnode_getParent(vParent);
|
|
3562
|
+
}
|
|
3563
|
+
if (vParent == null) {
|
|
3564
|
+
// We are done.
|
|
3565
|
+
return;
|
|
3566
|
+
}
|
|
3567
|
+
} while (true);
|
|
3568
|
+
}
|
|
3569
|
+
function cleanupStaleUnclaimedProjection(journal, projection) {
|
|
3570
|
+
// we are removing a node where the projection would go after slot render.
|
|
3571
|
+
// This is not needed, so we need to cleanup still unclaimed projection
|
|
3572
|
+
const projectionParent = vnode_getParent(projection);
|
|
3573
|
+
if (projectionParent) {
|
|
3574
|
+
const projectionParentType = projectionParent[VNodeProps.flags];
|
|
3575
|
+
if (projectionParentType & VNodeFlags.Element &&
|
|
3576
|
+
vnode_getElementName(projectionParent) === QTemplate) {
|
|
3577
|
+
// if parent is the q:template element then projection is still unclaimed - remove it
|
|
3578
|
+
vnode_remove(journal, projectionParent, projection, true);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
function markVNodeAsDeleted(vCursor) {
|
|
3583
|
+
/**
|
|
3584
|
+
* Marks vCursor as deleted. We need to do this to prevent chores from running after the vnode is
|
|
3585
|
+
* removed. (for example signal subscriptions)
|
|
3586
|
+
*/
|
|
3587
|
+
vCursor[VNodeProps.flags] |= VNodeFlags.Deleted;
|
|
3588
|
+
}
|
|
3589
|
+
/**
|
|
3590
|
+
* This marks the property as immutable. It is needed for the QRLs so that QwikLoader can get a hold
|
|
3591
|
+
* of them. This character must be `:` so that the `vnode_getAttr` can ignore them.
|
|
3592
|
+
*/
|
|
3593
|
+
const HANDLER_PREFIX = ':';
|
|
3594
|
+
let count = 0;
|
|
3595
|
+
var SiblingsArray;
|
|
3596
|
+
(function (SiblingsArray) {
|
|
3597
|
+
SiblingsArray[SiblingsArray["Name"] = 0] = "Name";
|
|
3598
|
+
SiblingsArray[SiblingsArray["Key"] = 1] = "Key";
|
|
3599
|
+
SiblingsArray[SiblingsArray["VNode"] = 2] = "VNode";
|
|
3600
|
+
SiblingsArray[SiblingsArray["Size"] = 3] = "Size";
|
|
3601
|
+
SiblingsArray[SiblingsArray["NextVNode"] = 5] = "NextVNode";
|
|
3602
|
+
})(SiblingsArray || (SiblingsArray = {}));
|
|
3603
|
+
|
|
3604
|
+
/** @internal */
|
|
3605
|
+
const useResourceQrl = (qrl, opts) => {
|
|
3606
|
+
const { val, set, i, iCtx } = useSequentialScope();
|
|
3607
|
+
if (val != null) {
|
|
3608
|
+
return val;
|
|
3609
|
+
}
|
|
3610
|
+
assertQrl(qrl);
|
|
3611
|
+
const container = iCtx.$container$;
|
|
3612
|
+
const resource = createResourceReturn(container, opts);
|
|
3613
|
+
const el = iCtx.$hostElement$;
|
|
3614
|
+
const task = new Task(TaskFlags.DIRTY | TaskFlags.RESOURCE, i, el, qrl, resource, null);
|
|
3615
|
+
container.$scheduler$(ChoreType.TASK, task);
|
|
3616
|
+
set(resource);
|
|
3617
|
+
return resource;
|
|
3618
|
+
};
|
|
3619
|
+
// <docs markdown="../readme.md#useResource">
|
|
3620
|
+
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3621
|
+
// (edit ../readme.md#useResource instead and run `pnpm docs.sync`)
|
|
3622
|
+
/**
|
|
3623
|
+
* This method works like an async memoized function that runs whenever some tracked value changes
|
|
3624
|
+
* and returns some data.
|
|
3625
|
+
*
|
|
3626
|
+
* `useResource` however returns immediate a `ResourceReturn` object that contains the data and a
|
|
3627
|
+
* state that indicates if the data is available or not.
|
|
3628
|
+
*
|
|
3629
|
+
* The status can be one of the following:
|
|
3630
|
+
*
|
|
3631
|
+
* - `pending` - the data is not yet available.
|
|
3632
|
+
* - `resolved` - the data is available.
|
|
3633
|
+
* - `rejected` - the data is not available due to an error or timeout.
|
|
3634
|
+
*
|
|
3635
|
+
* Be careful when using a `try/catch` statement in `useResource$`. If you catch the error and don't
|
|
3636
|
+
* re-throw it (or a new Error), the resource status will never be `rejected`.
|
|
3637
|
+
*
|
|
3638
|
+
* ### Example
|
|
3639
|
+
*
|
|
3640
|
+
* Example showing how `useResource` to perform a fetch to request the weather, whenever the input
|
|
3641
|
+
* city name changes.
|
|
3642
|
+
*
|
|
3643
|
+
* ```tsx
|
|
3644
|
+
* const Cmp = component$(() => {
|
|
3645
|
+
* const cityS = useSignal('');
|
|
3646
|
+
*
|
|
3647
|
+
* const weatherResource = useResource$(async ({ track, cleanup }) => {
|
|
3648
|
+
* const cityName = track(cityS);
|
|
3649
|
+
* const abortController = new AbortController();
|
|
3650
|
+
* cleanup(() => abortController.abort('cleanup'));
|
|
3651
|
+
* const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
|
|
3652
|
+
* signal: abortController.signal,
|
|
3653
|
+
* });
|
|
3654
|
+
* const data = await res.json();
|
|
3655
|
+
* return data as { temp: number };
|
|
3656
|
+
* });
|
|
3657
|
+
*
|
|
3658
|
+
* return (
|
|
3659
|
+
* <div>
|
|
3660
|
+
* <input name="city" bind:value={cityS} />
|
|
3661
|
+
* <Resource
|
|
3662
|
+
* value={weatherResource}
|
|
3663
|
+
* onResolved={(weather) => {
|
|
3664
|
+
* return <div>Temperature: {weather.temp}</div>;
|
|
3665
|
+
* }}
|
|
3666
|
+
* />
|
|
3667
|
+
* </div>
|
|
3668
|
+
* );
|
|
3669
|
+
* });
|
|
3670
|
+
* ```
|
|
3671
|
+
*
|
|
3672
|
+
* @public
|
|
3673
|
+
* @see Resource
|
|
3674
|
+
* @see ResourceReturn
|
|
3675
|
+
*/
|
|
3676
|
+
// </docs>
|
|
3677
|
+
const Resource = (props) => {
|
|
3678
|
+
// Resource path
|
|
3679
|
+
return _jsxSorted(Fragment, null, null, getResourceValueAsPromise(props), 0, null);
|
|
3680
|
+
};
|
|
3681
|
+
function getResourceValueAsPromise(props) {
|
|
3682
|
+
const resource = props.value;
|
|
3683
|
+
if (isResourceReturn(resource) && resource.value) {
|
|
3684
|
+
const isBrowser = !isServerPlatform();
|
|
3685
|
+
if (isBrowser) {
|
|
3686
|
+
// create a subscription for the resource._state changes
|
|
3687
|
+
const state = resource._state;
|
|
3688
|
+
if (state === 'pending' && props.onPending) {
|
|
3689
|
+
return Promise.resolve().then(useBindInvokeContext(props.onPending));
|
|
3690
|
+
}
|
|
3691
|
+
else if (state === 'rejected' && props.onRejected) {
|
|
3692
|
+
return Promise.resolve(resource._error).then(useBindInvokeContext(props.onRejected));
|
|
3693
|
+
}
|
|
3694
|
+
else {
|
|
3695
|
+
const resolvedValue = untrack(() => resource._resolved);
|
|
3696
|
+
if (resolvedValue !== undefined) {
|
|
3697
|
+
// resolved, pending without onPending prop or rejected without onRejected prop
|
|
3698
|
+
return Promise.resolve(resolvedValue).then(useBindInvokeContext(props.onResolved));
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
return resource.value.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3703
|
+
}
|
|
3704
|
+
else if (isPromise(resource)) {
|
|
3705
|
+
return resource.then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3706
|
+
}
|
|
3707
|
+
else if (isSignal(resource)) {
|
|
3708
|
+
return Promise.resolve(resource.value).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3709
|
+
}
|
|
3710
|
+
else {
|
|
3711
|
+
return Promise.resolve(resource).then(useBindInvokeContext(props.onResolved), useBindInvokeContext(props.onRejected));
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
const _createResourceReturn = (opts) => {
|
|
3715
|
+
const resource = {
|
|
3716
|
+
__brand: 'resource',
|
|
3717
|
+
value: undefined,
|
|
3718
|
+
loading: isServerPlatform() ? false : true,
|
|
3719
|
+
_resolved: undefined,
|
|
3720
|
+
_error: undefined,
|
|
3721
|
+
_state: 'pending',
|
|
3722
|
+
_timeout: opts?.timeout ?? -1,
|
|
3723
|
+
_cache: 0,
|
|
3724
|
+
};
|
|
3725
|
+
return resource;
|
|
3726
|
+
};
|
|
3727
|
+
const createResourceReturn = (container, opts, initialPromise) => {
|
|
3728
|
+
const result = _createResourceReturn(opts);
|
|
3729
|
+
result.value = initialPromise;
|
|
3730
|
+
return createStore(container, result, StoreFlags.RECURSIVE);
|
|
3731
|
+
};
|
|
3732
|
+
const isResourceReturn = (obj) => {
|
|
3733
|
+
return isObject(obj) && (getStoreTarget(obj) || obj).__brand === 'resource';
|
|
3734
|
+
};
|
|
3735
|
+
const runResource = (task, container, host) => {
|
|
3736
|
+
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
3737
|
+
cleanupTask(task);
|
|
3738
|
+
const iCtx = newInvokeContext(container.$locale$, host, undefined, ResourceEvent);
|
|
3739
|
+
iCtx.$container$ = container;
|
|
3740
|
+
const taskFn = task.$qrl$.getFn(iCtx, () => clearAllEffects(container, task));
|
|
3741
|
+
const resource = task.$state$;
|
|
3742
|
+
assertDefined(resource, 'useResource: when running a resource, "task.resource" must be a defined.', task);
|
|
3743
|
+
const track = (obj, prop) => {
|
|
3744
|
+
const ctx = newInvokeContext();
|
|
3745
|
+
ctx.$effectSubscriber$ = getSubscriber(task, EffectProperty.COMPONENT);
|
|
3746
|
+
ctx.$container$ = container;
|
|
3747
|
+
return invoke(ctx, () => {
|
|
3748
|
+
if (isFunction(obj)) {
|
|
3749
|
+
return obj();
|
|
3750
|
+
}
|
|
3751
|
+
if (prop) {
|
|
3752
|
+
return obj[prop];
|
|
3753
|
+
}
|
|
3754
|
+
else if (isSignal(obj)) {
|
|
3755
|
+
return obj.value;
|
|
3756
|
+
}
|
|
3757
|
+
else {
|
|
3758
|
+
return obj;
|
|
3759
|
+
}
|
|
3760
|
+
});
|
|
3761
|
+
};
|
|
3762
|
+
const handleError = (reason) => container.handleError(reason, host);
|
|
3763
|
+
const cleanups = [];
|
|
3764
|
+
task.$destroy$ = noSerialize(() => {
|
|
3765
|
+
cleanups.forEach((fn) => {
|
|
3766
|
+
try {
|
|
3767
|
+
fn();
|
|
3768
|
+
}
|
|
3769
|
+
catch (err) {
|
|
3770
|
+
handleError(err);
|
|
3771
|
+
}
|
|
3772
|
+
});
|
|
3773
|
+
done = true;
|
|
3774
|
+
});
|
|
3775
|
+
const resourceTarget = unwrapStore(resource);
|
|
3776
|
+
const opts = {
|
|
3777
|
+
track,
|
|
3778
|
+
cleanup(fn) {
|
|
3779
|
+
if (typeof fn === 'function') {
|
|
3780
|
+
cleanups.push(fn);
|
|
3781
|
+
}
|
|
3782
|
+
},
|
|
3783
|
+
cache(policy) {
|
|
3784
|
+
let milliseconds = 0;
|
|
3785
|
+
if (policy === 'immutable') {
|
|
3786
|
+
milliseconds = Infinity;
|
|
3787
|
+
}
|
|
3788
|
+
else {
|
|
3789
|
+
milliseconds = policy;
|
|
3790
|
+
}
|
|
3791
|
+
resource._cache = milliseconds;
|
|
3792
|
+
},
|
|
3793
|
+
previous: resourceTarget._resolved,
|
|
3794
|
+
};
|
|
3795
|
+
let resolve;
|
|
3796
|
+
let reject;
|
|
3797
|
+
let done = false;
|
|
3798
|
+
const setState = (resolved, value) => {
|
|
3799
|
+
if (!done) {
|
|
3800
|
+
done = true;
|
|
3801
|
+
if (resolved) {
|
|
3802
|
+
done = true;
|
|
3803
|
+
resource.loading = false;
|
|
3804
|
+
resource._state = 'resolved';
|
|
3805
|
+
resource._resolved = value;
|
|
3806
|
+
resource._error = undefined;
|
|
3807
|
+
resolve(value);
|
|
3808
|
+
}
|
|
3809
|
+
else {
|
|
3810
|
+
done = true;
|
|
3811
|
+
resource.loading = false;
|
|
3812
|
+
resource._state = 'rejected';
|
|
3813
|
+
resource._error = value;
|
|
3814
|
+
reject(value);
|
|
3465
3815
|
}
|
|
3466
|
-
|
|
3816
|
+
return true;
|
|
3467
3817
|
}
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3818
|
+
return false;
|
|
3819
|
+
};
|
|
3820
|
+
/**
|
|
3821
|
+
* Add cleanup to resolve the resource if we are trying to run the same resource again while the
|
|
3822
|
+
* previous one is not resolved yet. The next `runResource` run will call this cleanup
|
|
3823
|
+
*/
|
|
3824
|
+
cleanups.push(() => {
|
|
3825
|
+
if (untrack(() => resource.loading) === true) {
|
|
3826
|
+
const value = untrack(() => resource._resolved);
|
|
3827
|
+
setState(true, value);
|
|
3471
3828
|
}
|
|
3472
|
-
}
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3829
|
+
});
|
|
3830
|
+
// Execute mutation inside empty invocation
|
|
3831
|
+
invoke(iCtx, () => {
|
|
3832
|
+
// console.log('RESOURCE.pending: ');
|
|
3833
|
+
resource._state = 'pending';
|
|
3834
|
+
resource.loading = !isServerPlatform();
|
|
3835
|
+
const promise = (resource.value = new Promise((r, re) => {
|
|
3836
|
+
resolve = r;
|
|
3837
|
+
reject = re;
|
|
3838
|
+
}));
|
|
3839
|
+
promise.catch(ignoreErrorToPreventNodeFromCrashing);
|
|
3840
|
+
});
|
|
3841
|
+
const promise = safeCall(() => Promise.resolve(taskFn(opts)), (value) => {
|
|
3842
|
+
setState(true, value);
|
|
3843
|
+
}, (err) => {
|
|
3844
|
+
if (isPromise(err)) {
|
|
3845
|
+
return err.then(() => runResource(task, container, host));
|
|
3484
3846
|
}
|
|
3847
|
+
else {
|
|
3848
|
+
setState(false, err);
|
|
3849
|
+
}
|
|
3850
|
+
});
|
|
3851
|
+
const timeout = resourceTarget._timeout;
|
|
3852
|
+
if (timeout > 0) {
|
|
3853
|
+
return Promise.race([
|
|
3854
|
+
promise,
|
|
3855
|
+
delay(timeout).then(() => {
|
|
3856
|
+
if (setState(false, new Error('timeout'))) {
|
|
3857
|
+
cleanupTask(task);
|
|
3858
|
+
}
|
|
3859
|
+
}),
|
|
3860
|
+
]);
|
|
3485
3861
|
}
|
|
3486
|
-
|
|
3487
|
-
function markVNodeAsDeleted(vCursor) {
|
|
3488
|
-
/**
|
|
3489
|
-
* Marks vCursor as deleted. We need to do this to prevent chores from running after the vnode is
|
|
3490
|
-
* removed. (for example signal subscriptions)
|
|
3491
|
-
*/
|
|
3492
|
-
vCursor[VNodeProps.flags] |= VNodeFlags.Deleted;
|
|
3493
|
-
}
|
|
3494
|
-
/**
|
|
3495
|
-
* This marks the property as immutable. It is needed for the QRLs so that QwikLoader can get a hold
|
|
3496
|
-
* of them. This character must be `:` so that the `vnode_getAttr` can ignore them.
|
|
3497
|
-
*/
|
|
3498
|
-
const HANDLER_PREFIX = ':';
|
|
3499
|
-
let count = 0;
|
|
3500
|
-
var SiblingsArray;
|
|
3501
|
-
(function (SiblingsArray) {
|
|
3502
|
-
SiblingsArray[SiblingsArray["Name"] = 0] = "Name";
|
|
3503
|
-
SiblingsArray[SiblingsArray["Key"] = 1] = "Key";
|
|
3504
|
-
SiblingsArray[SiblingsArray["VNode"] = 2] = "VNode";
|
|
3505
|
-
SiblingsArray[SiblingsArray["Size"] = 3] = "Size";
|
|
3506
|
-
SiblingsArray[SiblingsArray["NextVNode"] = 5] = "NextVNode";
|
|
3507
|
-
})(SiblingsArray || (SiblingsArray = {}));
|
|
3508
|
-
|
|
3509
|
-
// <docs markdown="../../readme.md#implicit$FirstArg">
|
|
3510
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3511
|
-
// (edit ../../readme.md#implicit$FirstArg instead and run `pnpm docs.sync`)
|
|
3512
|
-
/**
|
|
3513
|
-
* Create a `____$(...)` convenience method from `___(...)`.
|
|
3514
|
-
*
|
|
3515
|
-
* It is very common for functions to take a lazy-loadable resource as a first argument. For this
|
|
3516
|
-
* reason, the Qwik Optimizer automatically extracts the first argument from any function which ends
|
|
3517
|
-
* in `$`.
|
|
3518
|
-
*
|
|
3519
|
-
* This means that `foo$(arg0)` and `foo($(arg0))` are equivalent with respect to Qwik Optimizer.
|
|
3520
|
-
* The former is just a shorthand for the latter.
|
|
3521
|
-
*
|
|
3522
|
-
* For example, these function calls are equivalent:
|
|
3523
|
-
*
|
|
3524
|
-
* - `component$(() => {...})` is same as `component($(() => {...}))`
|
|
3525
|
-
*
|
|
3526
|
-
* ```tsx
|
|
3527
|
-
* export function myApi(callback: QRL<() => void>): void {
|
|
3528
|
-
* // ...
|
|
3529
|
-
* }
|
|
3530
|
-
*
|
|
3531
|
-
* export const myApi$ = implicit$FirstArg(myApi);
|
|
3532
|
-
* // type of myApi$: (callback: () => void): void
|
|
3533
|
-
*
|
|
3534
|
-
* // can be used as:
|
|
3535
|
-
* myApi$(() => console.log('callback'));
|
|
3536
|
-
*
|
|
3537
|
-
* // will be transpiled to:
|
|
3538
|
-
* // FILE: <current file>
|
|
3539
|
-
* myApi(qrl('./chunk-abc.js', 'callback'));
|
|
3540
|
-
*
|
|
3541
|
-
* // FILE: chunk-abc.js
|
|
3542
|
-
* export const callback = () => console.log('callback');
|
|
3543
|
-
* ```
|
|
3544
|
-
*
|
|
3545
|
-
* @param fn - A function that should have its first argument automatically `$`.
|
|
3546
|
-
* @public
|
|
3547
|
-
*/
|
|
3548
|
-
// </docs>
|
|
3549
|
-
const implicit$FirstArg = (fn) => {
|
|
3550
|
-
return function (first, ...rest) {
|
|
3551
|
-
return fn.call(null, dollar(first), ...rest);
|
|
3552
|
-
};
|
|
3553
|
-
};
|
|
3554
|
-
|
|
3555
|
-
const createSignal$1 = (value) => {
|
|
3556
|
-
return new Signal(null, value);
|
|
3862
|
+
return promise;
|
|
3557
3863
|
};
|
|
3558
|
-
const
|
|
3559
|
-
|
|
3560
|
-
|
|
3864
|
+
const ignoreErrorToPreventNodeFromCrashing = (err) => {
|
|
3865
|
+
// ignore error to prevent node from crashing
|
|
3866
|
+
// node will crash in promise is rejected and no one is listening to the rejection.
|
|
3561
3867
|
};
|
|
3562
3868
|
|
|
3869
|
+
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
3870
|
+
const aVNodePath = [];
|
|
3871
|
+
const bVNodePath = [];
|
|
3563
3872
|
/**
|
|
3564
|
-
*
|
|
3565
|
-
* `undefined`.
|
|
3873
|
+
* Compare two VNodes and determine their document position relative to each other.
|
|
3566
3874
|
*
|
|
3567
|
-
* @
|
|
3875
|
+
* @param a VNode to compare
|
|
3876
|
+
* @param b VNode to compare
|
|
3877
|
+
* @param rootVNode - Root VNode of a container
|
|
3878
|
+
* @returns -1 if `a` is before `b`, 0 if `a` is the same as `b`, 1 if `a` is after `b`.
|
|
3568
3879
|
*/
|
|
3569
|
-
const
|
|
3570
|
-
|
|
3571
|
-
|
|
3880
|
+
const vnode_documentPosition = (a, b, rootVNode) => {
|
|
3881
|
+
if (a === b) {
|
|
3882
|
+
return 0;
|
|
3883
|
+
}
|
|
3884
|
+
let aDepth = -1;
|
|
3885
|
+
let bDepth = -1;
|
|
3886
|
+
while (a) {
|
|
3887
|
+
const vNode = (aVNodePath[++aDepth] = a);
|
|
3888
|
+
a = (vNode[VNodeProps.parent] ||
|
|
3889
|
+
(rootVNode && vnode_getProp(a, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
3890
|
+
}
|
|
3891
|
+
while (b) {
|
|
3892
|
+
const vNode = (bVNodePath[++bDepth] = b);
|
|
3893
|
+
b = (vNode[VNodeProps.parent] ||
|
|
3894
|
+
(rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
3895
|
+
}
|
|
3896
|
+
while (aDepth >= 0 && bDepth >= 0) {
|
|
3897
|
+
a = aVNodePath[aDepth];
|
|
3898
|
+
b = bVNodePath[bDepth];
|
|
3899
|
+
if (a === b) {
|
|
3900
|
+
// if the nodes are the same, we need to check the next level.
|
|
3901
|
+
aDepth--;
|
|
3902
|
+
bDepth--;
|
|
3903
|
+
}
|
|
3904
|
+
else {
|
|
3905
|
+
// We found a difference so we need to scan nodes at this level.
|
|
3906
|
+
let cursor = b;
|
|
3907
|
+
do {
|
|
3908
|
+
cursor = vnode_getNextSibling(cursor);
|
|
3909
|
+
if (cursor === a) {
|
|
3910
|
+
return 1;
|
|
3911
|
+
}
|
|
3912
|
+
} while (cursor);
|
|
3913
|
+
cursor = b;
|
|
3914
|
+
do {
|
|
3915
|
+
cursor = vnode_getPreviousSibling(cursor);
|
|
3916
|
+
if (cursor === a) {
|
|
3917
|
+
return -1;
|
|
3918
|
+
}
|
|
3919
|
+
} while (cursor);
|
|
3920
|
+
if (rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))) {
|
|
3921
|
+
// The "b" node is a projection, so we need to set it after "a" node,
|
|
3922
|
+
// because the "a" node could be a context provider.
|
|
3923
|
+
return -1;
|
|
3924
|
+
}
|
|
3925
|
+
// The node is not in the list of siblings, that means it must be disconnected.
|
|
3926
|
+
return 1;
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
return aDepth < bDepth ? -1 : 1;
|
|
3930
|
+
};
|
|
3931
|
+
/// These global variables are used to avoid creating new arrays for each call to `ssrNodeDocumentPosition`.
|
|
3932
|
+
const aSsrNodePath = [];
|
|
3933
|
+
const bSsrNodePath = [];
|
|
3572
3934
|
/**
|
|
3573
|
-
*
|
|
3574
|
-
*
|
|
3575
|
-
* recalculated.
|
|
3576
|
-
*
|
|
3577
|
-
* The QRL must be a function which returns the value of the signal. The function must not have side
|
|
3578
|
-
* effects, and it mus be synchronous.
|
|
3935
|
+
* Compare two SSR nodes and determine their document position relative to each other. Compares only
|
|
3936
|
+
* position between parent and child.
|
|
3579
3937
|
*
|
|
3580
|
-
*
|
|
3581
|
-
*
|
|
3582
|
-
* @
|
|
3938
|
+
* @param a SSR node to compare
|
|
3939
|
+
* @param b SSR node to compare
|
|
3940
|
+
* @returns -1 if `a` is before `b`, 0 if `a` is the same as `b`, 1 if `a` is after `b`.
|
|
3583
3941
|
*/
|
|
3584
|
-
const
|
|
3942
|
+
const ssrNodeDocumentPosition = (a, b) => {
|
|
3943
|
+
if (a === b) {
|
|
3944
|
+
return 0;
|
|
3945
|
+
}
|
|
3946
|
+
let aDepth = -1;
|
|
3947
|
+
let bDepth = -1;
|
|
3948
|
+
while (a) {
|
|
3949
|
+
const ssrNode = (aSsrNodePath[++aDepth] = a);
|
|
3950
|
+
a = ssrNode.currentComponentNode;
|
|
3951
|
+
}
|
|
3952
|
+
while (b) {
|
|
3953
|
+
const ssrNode = (bSsrNodePath[++bDepth] = b);
|
|
3954
|
+
b = ssrNode.currentComponentNode;
|
|
3955
|
+
}
|
|
3956
|
+
while (aDepth >= 0 && bDepth >= 0) {
|
|
3957
|
+
a = aSsrNodePath[aDepth];
|
|
3958
|
+
b = bSsrNodePath[bDepth];
|
|
3959
|
+
if (a === b) {
|
|
3960
|
+
// if the nodes are the same, we need to check the next level.
|
|
3961
|
+
aDepth--;
|
|
3962
|
+
bDepth--;
|
|
3963
|
+
}
|
|
3964
|
+
else {
|
|
3965
|
+
return 1;
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
return aDepth < bDepth ? -1 : 1;
|
|
3969
|
+
};
|
|
3585
3970
|
|
|
3586
3971
|
/**
|
|
3587
3972
|
* Scheduler is responsible for running application code in predictable order.
|
|
@@ -3664,38 +4049,29 @@
|
|
|
3664
4049
|
* - Visible Tasks are sorted afterJournalFlush, than depth first on component and finally in
|
|
3665
4050
|
* declaration order within component.
|
|
3666
4051
|
*/
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
ChoreType[ChoreType["MICRO"] = 15] = "MICRO";
|
|
3673
|
-
/** Ensure tha the QRL promise is resolved before processing next chores in the queue */
|
|
3674
|
-
ChoreType[ChoreType["QRL_RESOLVE"] = 1] = "QRL_RESOLVE";
|
|
3675
|
-
ChoreType[ChoreType["RESOURCE"] = 2] = "RESOURCE";
|
|
3676
|
-
ChoreType[ChoreType["TASK"] = 3] = "TASK";
|
|
3677
|
-
ChoreType[ChoreType["NODE_DIFF"] = 4] = "NODE_DIFF";
|
|
3678
|
-
ChoreType[ChoreType["NODE_PROP"] = 5] = "NODE_PROP";
|
|
3679
|
-
ChoreType[ChoreType["COMPONENT_SSR"] = 6] = "COMPONENT_SSR";
|
|
3680
|
-
ChoreType[ChoreType["COMPONENT"] = 7] = "COMPONENT";
|
|
3681
|
-
ChoreType[ChoreType["RECOMPUTE_AND_SCHEDULE_EFFECTS"] = 8] = "RECOMPUTE_AND_SCHEDULE_EFFECTS";
|
|
3682
|
-
ChoreType[ChoreType["JOURNAL_FLUSH"] = 16] = "JOURNAL_FLUSH";
|
|
3683
|
-
ChoreType[ChoreType["VISIBLE"] = 32] = "VISIBLE";
|
|
3684
|
-
ChoreType[ChoreType["CLEANUP_VISIBLE"] = 48] = "CLEANUP_VISIBLE";
|
|
3685
|
-
ChoreType[ChoreType["WAIT_FOR_ALL"] = 255] = "WAIT_FOR_ALL";
|
|
3686
|
-
})(ChoreType || (ChoreType = {}));
|
|
4052
|
+
// Turn this on to get debug output of what the scheduler is doing.
|
|
4053
|
+
const DEBUG$1 = false;
|
|
4054
|
+
const getPromise = (chore) => (chore.$promise$ ||= new Promise((resolve) => {
|
|
4055
|
+
chore.$resolve$ = resolve;
|
|
4056
|
+
}));
|
|
3687
4057
|
const createScheduler = (container, scheduleDrain, journalFlush) => {
|
|
3688
4058
|
const choreQueue = [];
|
|
4059
|
+
const qrlRuns = [];
|
|
3689
4060
|
let currentChore = null;
|
|
3690
|
-
let
|
|
4061
|
+
let drainScheduled = false;
|
|
3691
4062
|
return schedule;
|
|
3692
4063
|
///// IMPLEMENTATION /////
|
|
3693
4064
|
function schedule(type, hostOrTask = null, targetOrQrl = null, payload = null) {
|
|
3694
|
-
const
|
|
3695
|
-
const
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
4065
|
+
const isServer = !isDomContainer(container);
|
|
4066
|
+
const isComponentSsr = isServer && type === ChoreType.COMPONENT;
|
|
4067
|
+
const runLater = type !== ChoreType.WAIT_FOR_ALL && !isComponentSsr && type !== ChoreType.RUN_QRL;
|
|
4068
|
+
const isTask = type === ChoreType.TASK || type === ChoreType.VISIBLE || type === ChoreType.CLEANUP_VISIBLE;
|
|
4069
|
+
const isClientOnly = type === ChoreType.JOURNAL_FLUSH ||
|
|
4070
|
+
type === ChoreType.NODE_DIFF ||
|
|
4071
|
+
type === ChoreType.NODE_PROP;
|
|
4072
|
+
if (isServer && isClientOnly) {
|
|
4073
|
+
return;
|
|
4074
|
+
}
|
|
3699
4075
|
if (isTask) {
|
|
3700
4076
|
hostOrTask.$flags$ |= TaskFlags.DIRTY;
|
|
3701
4077
|
}
|
|
@@ -3714,184 +4090,234 @@
|
|
|
3714
4090
|
$returnValue$: null,
|
|
3715
4091
|
$executed$: false,
|
|
3716
4092
|
};
|
|
3717
|
-
chore.$promise$ = new Promise((resolve) => (chore.$resolve$ = resolve));
|
|
3718
4093
|
chore = sortedInsert(choreQueue, chore, container.rootVNode || null);
|
|
3719
|
-
if (!
|
|
4094
|
+
if (!drainScheduled && runLater) {
|
|
3720
4095
|
// If we are not currently draining, we need to schedule a drain.
|
|
3721
|
-
|
|
4096
|
+
drainScheduled = true;
|
|
3722
4097
|
schedule(ChoreType.JOURNAL_FLUSH);
|
|
3723
|
-
|
|
4098
|
+
// Catch here to avoid unhandled promise rejection
|
|
4099
|
+
scheduleDrain()?.catch?.(() => { });
|
|
3724
4100
|
}
|
|
4101
|
+
// TODO figure out what to do with chore errors
|
|
3725
4102
|
if (runLater) {
|
|
3726
|
-
return chore
|
|
4103
|
+
return getPromise(chore);
|
|
3727
4104
|
}
|
|
3728
4105
|
else {
|
|
3729
|
-
return drainUpTo(chore,
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
/**
|
|
3733
|
-
* Execute all of the chores up to and including the given chore.
|
|
3734
|
-
*
|
|
3735
|
-
* @param runUptoChore
|
|
3736
|
-
*/
|
|
3737
|
-
function drainUpTo(runUptoChore, rootVNode) {
|
|
3738
|
-
// If it already ran, it's not in the queue
|
|
3739
|
-
if (runUptoChore.$executed$) {
|
|
3740
|
-
return runUptoChore.$returnValue$;
|
|
3741
|
-
}
|
|
3742
|
-
if (currentChore) {
|
|
3743
|
-
// Already running chore, which means we're waiting for async completion
|
|
3744
|
-
return runUptoChore.$promise$;
|
|
4106
|
+
return drainUpTo(chore, isServer);
|
|
3745
4107
|
}
|
|
4108
|
+
}
|
|
4109
|
+
/** Execute all of the chores up to and including the given chore. */
|
|
4110
|
+
function drainUpTo(runUptoChore, isServer) {
|
|
4111
|
+
let maxRetries = 5000;
|
|
3746
4112
|
while (choreQueue.length) {
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
if (order === null) {
|
|
3750
|
-
continue;
|
|
4113
|
+
if (maxRetries-- < 0) {
|
|
4114
|
+
throw new Error('drainUpTo: max retries reached');
|
|
3751
4115
|
}
|
|
3752
|
-
if (
|
|
3753
|
-
//
|
|
3754
|
-
|
|
4116
|
+
if (currentChore) {
|
|
4117
|
+
// Already running chore, which means we're waiting for async completion
|
|
4118
|
+
return getPromise(currentChore)
|
|
4119
|
+
.then(() => drainUpTo(runUptoChore, isServer))
|
|
4120
|
+
.catch((e) => {
|
|
4121
|
+
container.handleError(e, currentChore?.$host$);
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
4124
|
+
const nextChore = choreQueue[0];
|
|
4125
|
+
if (nextChore.$executed$) {
|
|
4126
|
+
choreQueue.shift();
|
|
4127
|
+
if (nextChore === runUptoChore) {
|
|
4128
|
+
break;
|
|
4129
|
+
}
|
|
4130
|
+
continue;
|
|
3755
4131
|
}
|
|
3756
|
-
|
|
3757
|
-
if (isDeletedVNode &&
|
|
4132
|
+
if (vNodeAlreadyDeleted(nextChore) &&
|
|
3758
4133
|
// we need to process cleanup tasks for deleted nodes
|
|
3759
4134
|
nextChore.$type$ !== ChoreType.CLEANUP_VISIBLE) {
|
|
4135
|
+
choreQueue.shift();
|
|
3760
4136
|
continue;
|
|
3761
4137
|
}
|
|
3762
|
-
|
|
3763
|
-
if (isPromise(returnValue)) {
|
|
3764
|
-
const promise = returnValue.then(() => drainUpTo(runUptoChore, rootVNode));
|
|
3765
|
-
return promise;
|
|
3766
|
-
}
|
|
4138
|
+
executeChore(nextChore, isServer);
|
|
3767
4139
|
}
|
|
3768
4140
|
return runUptoChore.$returnValue$;
|
|
3769
4141
|
}
|
|
3770
|
-
function executeChore(chore) {
|
|
4142
|
+
function executeChore(chore, isServer) {
|
|
3771
4143
|
const host = chore.$host$;
|
|
3772
4144
|
assertEqual(currentChore, null, 'Chore already running.');
|
|
3773
4145
|
currentChore = chore;
|
|
3774
4146
|
let returnValue = null;
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
3783
|
-
if (chore.$type$ === ChoreType.COMPONENT) {
|
|
3784
|
-
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
3785
|
-
return vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId));
|
|
4147
|
+
try {
|
|
4148
|
+
switch (chore.$type$) {
|
|
4149
|
+
case ChoreType.WAIT_FOR_ALL:
|
|
4150
|
+
{
|
|
4151
|
+
if (isServer) {
|
|
4152
|
+
drainScheduled = false;
|
|
4153
|
+
}
|
|
3786
4154
|
}
|
|
3787
|
-
|
|
3788
|
-
|
|
4155
|
+
break;
|
|
4156
|
+
case ChoreType.JOURNAL_FLUSH:
|
|
4157
|
+
{
|
|
4158
|
+
returnValue = journalFlush();
|
|
4159
|
+
drainScheduled = false;
|
|
4160
|
+
}
|
|
4161
|
+
break;
|
|
4162
|
+
case ChoreType.COMPONENT:
|
|
4163
|
+
{
|
|
4164
|
+
returnValue = safeCall(() => executeComponent(container, host, host, chore.$target$, chore.$payload$), (jsx) => {
|
|
4165
|
+
if (isServer) {
|
|
4166
|
+
return jsx;
|
|
4167
|
+
}
|
|
4168
|
+
else {
|
|
4169
|
+
const styleScopedId = container.getHostProp(host, QScopedStyle);
|
|
4170
|
+
return retryOnPromise(() => vnode_diff(container, jsx, host, addComponentStylePrefix(styleScopedId)));
|
|
4171
|
+
}
|
|
4172
|
+
}, (err) => container.handleError(err, host));
|
|
4173
|
+
}
|
|
4174
|
+
break;
|
|
4175
|
+
case ChoreType.RUN_QRL:
|
|
4176
|
+
{
|
|
4177
|
+
const fn = chore.$target$.getFn();
|
|
4178
|
+
const result = retryOnPromise(() => fn(...chore.$payload$));
|
|
4179
|
+
if (isPromise(result)) {
|
|
4180
|
+
const handled = result
|
|
4181
|
+
.finally(() => {
|
|
4182
|
+
qrlRuns.splice(qrlRuns.indexOf(handled), 1);
|
|
4183
|
+
})
|
|
4184
|
+
.catch((error) => {
|
|
4185
|
+
container.handleError(error, chore.$host$);
|
|
4186
|
+
});
|
|
4187
|
+
// Don't wait for the promise to resolve
|
|
4188
|
+
// TODO come up with a better solution, we also want concurrent signal handling with tasks but serial tasks
|
|
4189
|
+
qrlRuns.push(handled);
|
|
4190
|
+
DEBUG$1 &&
|
|
4191
|
+
debugTrace('execute.DONE (but still running)', chore, currentChore, choreQueue);
|
|
4192
|
+
chore.$returnValue$ = handled;
|
|
4193
|
+
chore.$resolve$?.(handled);
|
|
4194
|
+
currentChore = null;
|
|
4195
|
+
chore.$executed$ = true;
|
|
4196
|
+
// early out so we don't call after()
|
|
4197
|
+
return;
|
|
4198
|
+
}
|
|
4199
|
+
returnValue = null;
|
|
4200
|
+
}
|
|
4201
|
+
break;
|
|
4202
|
+
case ChoreType.TASK:
|
|
4203
|
+
case ChoreType.VISIBLE:
|
|
4204
|
+
{
|
|
4205
|
+
const payload = chore.$payload$;
|
|
4206
|
+
if (payload.$flags$ & TaskFlags.RESOURCE) {
|
|
4207
|
+
const result = runResource(payload, container, host);
|
|
4208
|
+
// Don't await the return value of the resource, because async resources should not be awaited.
|
|
4209
|
+
// The reason for this is that we should be able to update for example a node with loading
|
|
4210
|
+
// text. If we await the resource, the loading text will not be displayed until the resource
|
|
4211
|
+
// is loaded.
|
|
4212
|
+
// Awaiting on the client also causes a deadlock.
|
|
4213
|
+
// In any case, the resource will never throw.
|
|
4214
|
+
returnValue = isServer ? result : null;
|
|
4215
|
+
}
|
|
4216
|
+
else {
|
|
4217
|
+
returnValue = runTask(payload, container, host);
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
break;
|
|
4221
|
+
case ChoreType.CLEANUP_VISIBLE:
|
|
4222
|
+
{
|
|
4223
|
+
const task = chore.$payload$;
|
|
4224
|
+
cleanupTask(task);
|
|
4225
|
+
}
|
|
4226
|
+
break;
|
|
4227
|
+
case ChoreType.NODE_DIFF:
|
|
4228
|
+
{
|
|
4229
|
+
const parentVirtualNode = chore.$target$;
|
|
4230
|
+
let jsx = chore.$payload$;
|
|
4231
|
+
if (isSignal(jsx)) {
|
|
4232
|
+
jsx = jsx.value;
|
|
4233
|
+
}
|
|
4234
|
+
returnValue = retryOnPromise(() => vnode_diff(container, jsx, parentVirtualNode, null));
|
|
4235
|
+
}
|
|
4236
|
+
break;
|
|
4237
|
+
case ChoreType.NODE_PROP:
|
|
4238
|
+
{
|
|
4239
|
+
const virtualNode = chore.$host$;
|
|
4240
|
+
const payload = chore.$payload$;
|
|
4241
|
+
let value = payload.$value$;
|
|
4242
|
+
if (isSignal(value)) {
|
|
4243
|
+
value = value.value;
|
|
4244
|
+
}
|
|
4245
|
+
const isConst = payload.$isConst$;
|
|
4246
|
+
const journal = container.$journal$;
|
|
4247
|
+
const property = chore.$idx$;
|
|
4248
|
+
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
4249
|
+
if (isConst) {
|
|
4250
|
+
const element = virtualNode[ElementVNodeProps.element];
|
|
4251
|
+
journal.push(VNodeJournalOpCode.SetAttribute, element, property, serializedValue);
|
|
4252
|
+
}
|
|
4253
|
+
else {
|
|
4254
|
+
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
break;
|
|
4258
|
+
case ChoreType.QRL_RESOLVE: {
|
|
4259
|
+
{
|
|
4260
|
+
const target = chore.$target$;
|
|
4261
|
+
returnValue = !target.resolved ? target.resolve() : null;
|
|
3789
4262
|
}
|
|
3790
|
-
}, (err) => container.handleError(err, host));
|
|
3791
|
-
break;
|
|
3792
|
-
case ChoreType.RESOURCE:
|
|
3793
|
-
// Don't await the return value of the resource, because async resources should not be awaited.
|
|
3794
|
-
// The reason for this is that we should be able to update for example a node with loading
|
|
3795
|
-
// text. If we await the resource, the loading text will not be displayed until the resource
|
|
3796
|
-
// is loaded.
|
|
3797
|
-
const result = runResource(chore.$payload$, container, host);
|
|
3798
|
-
returnValue = isDomContainer(container) ? null : result;
|
|
3799
|
-
break;
|
|
3800
|
-
case ChoreType.TASK:
|
|
3801
|
-
returnValue = runTask(chore.$payload$, container, host);
|
|
3802
|
-
break;
|
|
3803
|
-
case ChoreType.VISIBLE:
|
|
3804
|
-
returnValue = runTask(chore.$payload$, container, host);
|
|
3805
|
-
break;
|
|
3806
|
-
case ChoreType.CLEANUP_VISIBLE:
|
|
3807
|
-
const task = chore.$payload$;
|
|
3808
|
-
cleanupTask(task);
|
|
3809
|
-
break;
|
|
3810
|
-
case ChoreType.NODE_DIFF:
|
|
3811
|
-
const parentVirtualNode = chore.$target$;
|
|
3812
|
-
let jsx = chore.$payload$;
|
|
3813
|
-
if (isSignal(jsx)) {
|
|
3814
|
-
jsx = jsx.value;
|
|
3815
|
-
}
|
|
3816
|
-
returnValue = vnode_diff(container, jsx, parentVirtualNode, null);
|
|
3817
|
-
break;
|
|
3818
|
-
case ChoreType.NODE_PROP:
|
|
3819
|
-
const virtualNode = chore.$host$;
|
|
3820
|
-
const payload = chore.$payload$;
|
|
3821
|
-
let value = payload.$value$;
|
|
3822
|
-
if (isSignal(value)) {
|
|
3823
|
-
value = value.value;
|
|
3824
|
-
}
|
|
3825
|
-
const isConst = payload.$isConst$;
|
|
3826
|
-
const journal = container.$journal$;
|
|
3827
|
-
const property = chore.$idx$;
|
|
3828
|
-
const serializedValue = serializeAttribute(property, value, payload.$scopedStyleIdPrefix$);
|
|
3829
|
-
if (isConst) {
|
|
3830
|
-
const element = virtualNode[ElementVNodeProps.element];
|
|
3831
|
-
journal.push(VNodeJournalOpCode.SetAttribute, element, property, serializedValue);
|
|
3832
|
-
}
|
|
3833
|
-
else {
|
|
3834
|
-
vnode_setAttr(journal, virtualNode, property, serializedValue);
|
|
3835
|
-
}
|
|
3836
|
-
break;
|
|
3837
|
-
case ChoreType.QRL_RESOLVE: {
|
|
3838
|
-
const target = chore.$target$;
|
|
3839
|
-
returnValue = !target.resolved ? target.resolve() : null;
|
|
3840
|
-
break;
|
|
3841
|
-
}
|
|
3842
|
-
case ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS: {
|
|
3843
|
-
const target = chore.$target$;
|
|
3844
|
-
const forceRunEffects = target.$forceRunEffects$;
|
|
3845
|
-
target.$forceRunEffects$ = false;
|
|
3846
|
-
if (!target.$effects$?.length) {
|
|
3847
4263
|
break;
|
|
3848
4264
|
}
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
4265
|
+
case ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS: {
|
|
4266
|
+
{
|
|
4267
|
+
const target = chore.$target$;
|
|
4268
|
+
const forceRunEffects = target.$forceRunEffects$;
|
|
4269
|
+
target.$forceRunEffects$ = false;
|
|
4270
|
+
if (!target.$effects$?.size) {
|
|
4271
|
+
break;
|
|
4272
|
+
}
|
|
4273
|
+
returnValue = retryOnPromise(() => {
|
|
4274
|
+
if (target.$computeIfNeeded$() || forceRunEffects) {
|
|
4275
|
+
triggerEffects(container, target, target.$effects$);
|
|
4276
|
+
}
|
|
4277
|
+
});
|
|
3852
4278
|
}
|
|
3853
|
-
|
|
3854
|
-
|
|
4279
|
+
break;
|
|
4280
|
+
}
|
|
3855
4281
|
}
|
|
3856
4282
|
}
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
}
|
|
4283
|
+
catch (e) {
|
|
4284
|
+
returnValue = Promise.reject(e);
|
|
4285
|
+
}
|
|
4286
|
+
const after = (value, error) => {
|
|
3862
4287
|
currentChore = null;
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
function vNodeAlreadyDeleted(chore) {
|
|
3881
|
-
return !!(chore.$host$ &&
|
|
3882
|
-
vnode_isVNode(chore.$host$) &&
|
|
3883
|
-
chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
|
|
3884
|
-
}
|
|
3885
|
-
function choreComparator(a, b, rootVNode, shouldThrowOnHostMismatch) {
|
|
3886
|
-
const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
|
|
3887
|
-
if (macroTypeDiff !== 0) {
|
|
3888
|
-
return macroTypeDiff;
|
|
4288
|
+
chore.$executed$ = true;
|
|
4289
|
+
if (error) {
|
|
4290
|
+
container.handleError(error, host);
|
|
4291
|
+
}
|
|
4292
|
+
else {
|
|
4293
|
+
chore.$returnValue$ = value;
|
|
4294
|
+
chore.$resolve$?.(value);
|
|
4295
|
+
}
|
|
4296
|
+
};
|
|
4297
|
+
if (isPromise(returnValue)) {
|
|
4298
|
+
chore.$promise$ = returnValue.then(after, (error) => after(undefined, error));
|
|
4299
|
+
chore.$resolve$?.(chore.$promise$);
|
|
4300
|
+
chore.$resolve$ = undefined;
|
|
4301
|
+
}
|
|
4302
|
+
else {
|
|
4303
|
+
after(returnValue);
|
|
4304
|
+
}
|
|
3889
4305
|
}
|
|
3890
|
-
|
|
3891
|
-
|
|
4306
|
+
/**
|
|
4307
|
+
* Compares two chores to determine their execution order in the scheduler's queue.
|
|
4308
|
+
*
|
|
4309
|
+
* @param a - The first chore to compare
|
|
4310
|
+
* @param b - The second chore to compare
|
|
4311
|
+
* @returns A number indicating the relative order of the chores. A negative number means `a` runs
|
|
4312
|
+
* before `b`.
|
|
4313
|
+
*/
|
|
4314
|
+
function choreComparator(a, b, rootVNode) {
|
|
4315
|
+
const macroTypeDiff = (a.$type$ & ChoreType.MACRO) - (b.$type$ & ChoreType.MACRO);
|
|
4316
|
+
if (macroTypeDiff !== 0) {
|
|
4317
|
+
return macroTypeDiff;
|
|
4318
|
+
}
|
|
3892
4319
|
const aHost = a.$host$;
|
|
3893
4320
|
const bHost = b.$host$;
|
|
3894
|
-
// QRL_RESOLVE does not have a host.
|
|
3895
4321
|
if (aHost !== bHost && aHost !== null && bHost !== null) {
|
|
3896
4322
|
if (vnode_isVNode(aHost) && vnode_isVNode(bHost)) {
|
|
3897
4323
|
// we are running on the client.
|
|
@@ -3901,6 +4327,8 @@
|
|
|
3901
4327
|
}
|
|
3902
4328
|
}
|
|
3903
4329
|
else {
|
|
4330
|
+
assertFalse(vnode_isVNode(aHost), 'expected aHost to be SSRNode but it is a VNode');
|
|
4331
|
+
assertFalse(vnode_isVNode(bHost), 'expected bHost to be SSRNode but it is a VNode');
|
|
3904
4332
|
// we are running on the server.
|
|
3905
4333
|
// On server we can't schedule task for a different host!
|
|
3906
4334
|
// Server is SSR, and therefore scheduling for anything but the current host
|
|
@@ -3909,258 +4337,125 @@
|
|
|
3909
4337
|
You are attempting to change a state that has already been streamed to the client.
|
|
3910
4338
|
This can lead to inconsistencies between Server-Side Rendering (SSR) and Client-Side Rendering (CSR).
|
|
3911
4339
|
Problematic Node: ${aHost.toString()}`;
|
|
3912
|
-
if (shouldThrowOnHostMismatch) {
|
|
3913
|
-
throw qError(QError.serverHostMismatch, [errorMessage]);
|
|
3914
|
-
}
|
|
3915
4340
|
logWarn(errorMessage);
|
|
3916
|
-
|
|
4341
|
+
const hostDiff = ssrNodeDocumentPosition(aHost, bHost);
|
|
4342
|
+
if (hostDiff !== 0) {
|
|
4343
|
+
return hostDiff;
|
|
4344
|
+
}
|
|
3917
4345
|
}
|
|
3918
4346
|
}
|
|
3919
4347
|
const microTypeDiff = (a.$type$ & ChoreType.MICRO) - (b.$type$ & ChoreType.MICRO);
|
|
3920
4348
|
if (microTypeDiff !== 0) {
|
|
3921
4349
|
return microTypeDiff;
|
|
3922
4350
|
}
|
|
4351
|
+
// types are the same
|
|
3923
4352
|
const idxDiff = toNumber(a.$idx$) - toNumber(b.$idx$);
|
|
3924
4353
|
if (idxDiff !== 0) {
|
|
3925
4354
|
return idxDiff;
|
|
3926
4355
|
}
|
|
3927
|
-
// If the host is the same, we need to compare the target.
|
|
3928
|
-
if (a.$target$ !== b.$target$
|
|
3929
|
-
((a.$type$ === ChoreType.QRL_RESOLVE && b.$type$ === ChoreType.QRL_RESOLVE) ||
|
|
3930
|
-
(a.$type$ === ChoreType.NODE_PROP && b.$type$ === ChoreType.NODE_PROP) ||
|
|
3931
|
-
(a.$type$ === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS &&
|
|
3932
|
-
b.$type$ === ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS))) {
|
|
4356
|
+
// If the host is the same (or missing), and the type is the same, we need to compare the target.
|
|
4357
|
+
if (a.$target$ !== b.$target$ || a.$payload$ !== b.$payload$) {
|
|
3933
4358
|
// 1 means that we are going to process chores as FIFO
|
|
3934
4359
|
return 1;
|
|
3935
4360
|
}
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
function sortedFindIndex(sortedArray, value, rootVNode) {
|
|
3940
|
-
/// We need to ensure that the `queue` is sorted by priority.
|
|
3941
|
-
/// 1. Find a place where to insert into.
|
|
3942
|
-
let bottom = 0;
|
|
3943
|
-
let top = sortedArray.length;
|
|
3944
|
-
while (bottom < top) {
|
|
3945
|
-
const middle = bottom + ((top - bottom) >> 1);
|
|
3946
|
-
const midChore = sortedArray[middle];
|
|
3947
|
-
const comp = choreComparator(value, midChore, rootVNode, true);
|
|
3948
|
-
if (comp < 0) {
|
|
3949
|
-
top = middle;
|
|
3950
|
-
}
|
|
3951
|
-
else if (comp > 0) {
|
|
3952
|
-
bottom = middle + 1;
|
|
3953
|
-
}
|
|
3954
|
-
else {
|
|
3955
|
-
// We already have the host in the queue.
|
|
3956
|
-
return middle;
|
|
4361
|
+
// If the chore is the same as the current chore, we will run it again
|
|
4362
|
+
if (b === currentChore) {
|
|
4363
|
+
return 1;
|
|
3957
4364
|
}
|
|
4365
|
+
// The chores are the same and will run only once
|
|
4366
|
+
return 0;
|
|
3958
4367
|
}
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
}
|
|
3974
|
-
|
|
3975
|
-
// <docs markdown="../readme.md#useLexicalScope">
|
|
3976
|
-
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
3977
|
-
// (edit ../readme.md#useLexicalScope instead and run `pnpm docs.sync`)
|
|
3978
|
-
/**
|
|
3979
|
-
* Used by the Qwik Optimizer to restore the lexically scoped variables.
|
|
3980
|
-
*
|
|
3981
|
-
* This method should not be present in the application source code.
|
|
3982
|
-
*
|
|
3983
|
-
* NOTE: `useLexicalScope` method can only be used in the synchronous portion of the callback
|
|
3984
|
-
* (before any `await` statements.)
|
|
3985
|
-
*
|
|
3986
|
-
* @internal
|
|
3987
|
-
*/
|
|
3988
|
-
// </docs>
|
|
3989
|
-
const useLexicalScope = () => {
|
|
3990
|
-
const context = getInvokeContext();
|
|
3991
|
-
let qrl = context.$qrl$;
|
|
3992
|
-
if (!qrl) {
|
|
3993
|
-
const el = context.$element$;
|
|
3994
|
-
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
|
|
3995
|
-
const containerElement = _getQContainerElement(el);
|
|
3996
|
-
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
|
|
3997
|
-
const container = getDomContainer(containerElement);
|
|
3998
|
-
qrl = container.parseQRL(decodeURIComponent(String(context.$url$)));
|
|
3999
|
-
}
|
|
4000
|
-
else {
|
|
4001
|
-
assertQrl(qrl);
|
|
4002
|
-
assertDefined(qrl.$captureRef$, 'invoke: qrl $captureRef$ must be defined inside useLexicalScope()', qrl);
|
|
4003
|
-
}
|
|
4004
|
-
return qrl.$captureRef$;
|
|
4005
|
-
};
|
|
4006
|
-
|
|
4007
|
-
var TaskFlags;
|
|
4008
|
-
(function (TaskFlags) {
|
|
4009
|
-
TaskFlags[TaskFlags["VISIBLE_TASK"] = 1] = "VISIBLE_TASK";
|
|
4010
|
-
TaskFlags[TaskFlags["TASK"] = 2] = "TASK";
|
|
4011
|
-
TaskFlags[TaskFlags["RESOURCE"] = 4] = "RESOURCE";
|
|
4012
|
-
TaskFlags[TaskFlags["DIRTY"] = 8] = "DIRTY";
|
|
4013
|
-
})(TaskFlags || (TaskFlags = {}));
|
|
4014
|
-
/** @internal */
|
|
4015
|
-
const useTaskQrl = (qrl, opts) => {
|
|
4016
|
-
const { val, set, iCtx, i } = useSequentialScope();
|
|
4017
|
-
if (val) {
|
|
4018
|
-
return;
|
|
4019
|
-
}
|
|
4020
|
-
assertQrl(qrl);
|
|
4021
|
-
set(1);
|
|
4022
|
-
const host = iCtx.$hostElement$;
|
|
4023
|
-
const task = new Task(TaskFlags.DIRTY | TaskFlags.TASK, i, iCtx.$hostElement$, qrl, undefined, null);
|
|
4024
|
-
// In V2 we add the task to the sequential scope. We need to do this
|
|
4025
|
-
// in order to be able to retrieve it later when the parent element is
|
|
4026
|
-
// deleted and we need to be able to release the task subscriptions.
|
|
4027
|
-
set(task);
|
|
4028
|
-
const result = runTask(task, iCtx.$container$, host);
|
|
4029
|
-
if (isPromise(result)) {
|
|
4030
|
-
throw result;
|
|
4031
|
-
}
|
|
4032
|
-
qrl.$resolveLazy$(iCtx.$element$);
|
|
4033
|
-
if (isServerPlatform()) {
|
|
4034
|
-
useRunTask(task, opts?.eagerness);
|
|
4035
|
-
}
|
|
4036
|
-
};
|
|
4037
|
-
const runTask = (task, container, host) => {
|
|
4038
|
-
task.$flags$ &= ~TaskFlags.DIRTY;
|
|
4039
|
-
cleanupTask(task);
|
|
4040
|
-
const iCtx = newInvokeContext(container.$locale$, host, undefined, TaskEvent);
|
|
4041
|
-
iCtx.$container$ = container;
|
|
4042
|
-
const taskFn = task.$qrl$.getFn(iCtx, () => clearSubscriberEffectDependencies(container, task));
|
|
4043
|
-
const track = (obj, prop) => {
|
|
4044
|
-
const ctx = newInvokeContext();
|
|
4045
|
-
ctx.$effectSubscriber$ = [task, EffectProperty.COMPONENT];
|
|
4046
|
-
ctx.$container$ = container;
|
|
4047
|
-
return invoke(ctx, () => {
|
|
4048
|
-
if (isFunction(obj)) {
|
|
4049
|
-
return obj();
|
|
4050
|
-
}
|
|
4051
|
-
if (prop) {
|
|
4052
|
-
return obj[prop];
|
|
4053
|
-
}
|
|
4054
|
-
else if (isSignal(obj)) {
|
|
4055
|
-
return obj.value;
|
|
4368
|
+
function sortedFindIndex(sortedArray, value, rootVNode) {
|
|
4369
|
+
/// We need to ensure that the `queue` is sorted by priority.
|
|
4370
|
+
/// 1. Find a place where to insert into.
|
|
4371
|
+
let bottom = 0;
|
|
4372
|
+
let top = sortedArray.length;
|
|
4373
|
+
while (bottom < top) {
|
|
4374
|
+
const middle = bottom + ((top - bottom) >> 1);
|
|
4375
|
+
const midChore = sortedArray[middle];
|
|
4376
|
+
const comp = choreComparator(value, midChore, rootVNode);
|
|
4377
|
+
if (comp < 0) {
|
|
4378
|
+
top = middle;
|
|
4379
|
+
}
|
|
4380
|
+
else if (comp > 0) {
|
|
4381
|
+
bottom = middle + 1;
|
|
4056
4382
|
}
|
|
4057
4383
|
else {
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
});
|
|
4061
|
-
};
|
|
4062
|
-
const handleError = (reason) => container.handleError(reason, host);
|
|
4063
|
-
let cleanupFns = null;
|
|
4064
|
-
const cleanup = (fn) => {
|
|
4065
|
-
if (typeof fn == 'function') {
|
|
4066
|
-
if (!cleanupFns) {
|
|
4067
|
-
cleanupFns = [];
|
|
4068
|
-
task.$destroy$ = noSerialize(() => {
|
|
4069
|
-
task.$destroy$ = null;
|
|
4070
|
-
cleanupFns.forEach((fn) => {
|
|
4071
|
-
try {
|
|
4072
|
-
fn();
|
|
4073
|
-
}
|
|
4074
|
-
catch (err) {
|
|
4075
|
-
handleError(err);
|
|
4076
|
-
}
|
|
4077
|
-
});
|
|
4078
|
-
});
|
|
4384
|
+
// We already have the host in the queue.
|
|
4385
|
+
return middle;
|
|
4079
4386
|
}
|
|
4080
|
-
cleanupFns.push(fn);
|
|
4081
|
-
}
|
|
4082
|
-
};
|
|
4083
|
-
const taskApi = { track, cleanup };
|
|
4084
|
-
const result = safeCall(() => taskFn(taskApi), cleanup, (err) => {
|
|
4085
|
-
if (isPromise(err)) {
|
|
4086
|
-
return err.then(() => runTask(task, container, host));
|
|
4087
|
-
}
|
|
4088
|
-
else {
|
|
4089
|
-
return handleError(err);
|
|
4090
4387
|
}
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4388
|
+
return ~bottom;
|
|
4389
|
+
}
|
|
4390
|
+
function sortedInsert(sortedArray, value, rootVNode) {
|
|
4391
|
+
/// We need to ensure that the `queue` is sorted by priority.
|
|
4392
|
+
/// 1. Find a place where to insert into.
|
|
4393
|
+
const idx = sortedFindIndex(sortedArray, value, rootVNode);
|
|
4394
|
+
if (idx < 0) {
|
|
4395
|
+
/// 2. Insert the chore into the queue.
|
|
4396
|
+
sortedArray.splice(~idx, 0, value);
|
|
4397
|
+
return value;
|
|
4100
4398
|
}
|
|
4101
|
-
|
|
4102
|
-
|
|
4399
|
+
const existing = sortedArray[idx];
|
|
4400
|
+
/**
|
|
4401
|
+
* When a derived signal is updated we need to run vnode_diff. However the signal can update
|
|
4402
|
+
* multiple times during component execution. For this reason it is necessary for us to update
|
|
4403
|
+
* the chore with the latest result of the signal.
|
|
4404
|
+
*/
|
|
4405
|
+
if (existing.$type$ === ChoreType.NODE_DIFF) {
|
|
4406
|
+
existing.$payload$ = value.$payload$;
|
|
4103
4407
|
}
|
|
4408
|
+
if (existing.$executed$) {
|
|
4409
|
+
existing.$executed$ = false;
|
|
4410
|
+
}
|
|
4411
|
+
return existing;
|
|
4104
4412
|
}
|
|
4105
4413
|
};
|
|
4106
|
-
const
|
|
4107
|
-
|
|
4108
|
-
useOn('qvisible', getTaskHandlerQrl(task));
|
|
4109
|
-
}
|
|
4110
|
-
else if (eagerness === 'load' || eagerness === 'document-ready') {
|
|
4111
|
-
useOnDocument('qinit', getTaskHandlerQrl(task));
|
|
4112
|
-
}
|
|
4113
|
-
else if (eagerness === 'idle' || eagerness === 'document-idle') {
|
|
4114
|
-
useOnDocument('qidle', getTaskHandlerQrl(task));
|
|
4115
|
-
}
|
|
4116
|
-
};
|
|
4117
|
-
const getTaskHandlerQrl = (task) => {
|
|
4118
|
-
const taskQrl = task.$qrl$;
|
|
4119
|
-
const taskHandler = createQRL(taskQrl.$chunk$, '_hW', _hW, null, null, [task], taskQrl.$symbol$);
|
|
4120
|
-
// Needed for chunk lookup in dev mode
|
|
4121
|
-
if (taskQrl.dev) {
|
|
4122
|
-
taskHandler.dev = taskQrl.dev;
|
|
4123
|
-
}
|
|
4124
|
-
return taskHandler;
|
|
4125
|
-
};
|
|
4126
|
-
class Task extends Subscriber {
|
|
4127
|
-
$flags$;
|
|
4128
|
-
$index$;
|
|
4129
|
-
$el$;
|
|
4130
|
-
$qrl$;
|
|
4131
|
-
$state$;
|
|
4132
|
-
$destroy$;
|
|
4133
|
-
constructor($flags$, $index$, $el$, $qrl$, $state$, $destroy$) {
|
|
4134
|
-
super();
|
|
4135
|
-
this.$flags$ = $flags$;
|
|
4136
|
-
this.$index$ = $index$;
|
|
4137
|
-
this.$el$ = $el$;
|
|
4138
|
-
this.$qrl$ = $qrl$;
|
|
4139
|
-
this.$state$ = $state$;
|
|
4140
|
-
this.$destroy$ = $destroy$;
|
|
4141
|
-
}
|
|
4142
|
-
}
|
|
4143
|
-
const isTask = (value) => {
|
|
4144
|
-
return value instanceof Task;
|
|
4145
|
-
};
|
|
4146
|
-
/**
|
|
4147
|
-
* Low-level API used by the Optimizer to process `useTask$()` API. This method is not intended to
|
|
4148
|
-
* be used by developers.
|
|
4149
|
-
*
|
|
4150
|
-
* @internal
|
|
4151
|
-
*/
|
|
4152
|
-
const _hW = () => {
|
|
4153
|
-
const [task] = useLexicalScope();
|
|
4154
|
-
const container = getDomContainer(task.$el$);
|
|
4155
|
-
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
|
|
4156
|
-
container.$scheduler$(type, task);
|
|
4414
|
+
const toNumber = (value) => {
|
|
4415
|
+
return typeof value === 'number' ? value : -1;
|
|
4157
4416
|
};
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4417
|
+
function vNodeAlreadyDeleted(chore) {
|
|
4418
|
+
return !!(chore.$host$ &&
|
|
4419
|
+
vnode_isVNode(chore.$host$) &&
|
|
4420
|
+
chore.$host$[VNodeProps.flags] & VNodeFlags.Deleted);
|
|
4421
|
+
}
|
|
4422
|
+
function debugChoreTypeToString(type) {
|
|
4423
|
+
return ({
|
|
4424
|
+
[ChoreType.QRL_RESOLVE]: 'QRL_RESOLVE',
|
|
4425
|
+
[ChoreType.RUN_QRL]: 'RUN_QRL',
|
|
4426
|
+
[ChoreType.TASK]: 'TASK',
|
|
4427
|
+
[ChoreType.NODE_DIFF]: 'NODE_DIFF',
|
|
4428
|
+
[ChoreType.NODE_PROP]: 'NODE_PROP',
|
|
4429
|
+
[ChoreType.COMPONENT]: 'COMPONENT',
|
|
4430
|
+
[ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS]: 'RECOMPUTE_SIGNAL',
|
|
4431
|
+
[ChoreType.JOURNAL_FLUSH]: 'JOURNAL_FLUSH',
|
|
4432
|
+
[ChoreType.VISIBLE]: 'VISIBLE',
|
|
4433
|
+
[ChoreType.CLEANUP_VISIBLE]: 'CLEANUP_VISIBLE',
|
|
4434
|
+
[ChoreType.WAIT_FOR_ALL]: 'WAIT_FOR_ALL',
|
|
4435
|
+
}[type] || 'UNKNOWN: ' + type);
|
|
4436
|
+
}
|
|
4437
|
+
function debugChoreToString(chore) {
|
|
4438
|
+
const type = debugChoreTypeToString(chore.$type$);
|
|
4439
|
+
const host = String(chore.$host$).replaceAll(/\n.*/gim, '');
|
|
4440
|
+
const qrlTarget = chore.$target$?.$symbol$;
|
|
4441
|
+
return `Chore(${type} ${chore.$type$ === ChoreType.QRL_RESOLVE || chore.$type$ === ChoreType.RUN_QRL ? qrlTarget : host} ${chore.$idx$})`;
|
|
4442
|
+
}
|
|
4443
|
+
function debugTrace(action, arg, currentChore, queue) {
|
|
4444
|
+
const lines = ['===========================\nScheduler: ' + action];
|
|
4445
|
+
if (arg && !('$type$' in arg)) {
|
|
4446
|
+
lines.push(' arg: ' + String(arg).replaceAll(/\n.*/gim, ''));
|
|
4447
|
+
}
|
|
4448
|
+
if (queue) {
|
|
4449
|
+
queue.forEach((chore) => {
|
|
4450
|
+
const active = chore === arg ? '>>>' : ' ';
|
|
4451
|
+
lines.push(` ${active} > ` +
|
|
4452
|
+
(chore === currentChore ? '[running] ' : '') +
|
|
4453
|
+
debugChoreToString(chore));
|
|
4454
|
+
});
|
|
4455
|
+
}
|
|
4456
|
+
// eslint-disable-next-line no-console
|
|
4457
|
+
console.log(lines.join('\n') + '\n');
|
|
4458
|
+
}
|
|
4164
4459
|
|
|
4165
4460
|
/**
|
|
4166
4461
|
* @file
|
|
@@ -4194,18 +4489,19 @@
|
|
|
4194
4489
|
return value instanceof Signal;
|
|
4195
4490
|
};
|
|
4196
4491
|
/** @internal */
|
|
4197
|
-
class
|
|
4492
|
+
class SubscriptionData {
|
|
4198
4493
|
data;
|
|
4199
4494
|
constructor(data) {
|
|
4200
4495
|
this.data = data;
|
|
4201
4496
|
}
|
|
4202
4497
|
}
|
|
4203
|
-
var
|
|
4204
|
-
(function (
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4498
|
+
var EffectSubscriptionProp;
|
|
4499
|
+
(function (EffectSubscriptionProp) {
|
|
4500
|
+
EffectSubscriptionProp[EffectSubscriptionProp["CONSUMER"] = 0] = "CONSUMER";
|
|
4501
|
+
EffectSubscriptionProp[EffectSubscriptionProp["PROPERTY"] = 1] = "PROPERTY";
|
|
4502
|
+
EffectSubscriptionProp[EffectSubscriptionProp["BACK_REF"] = 2] = "BACK_REF";
|
|
4503
|
+
EffectSubscriptionProp[EffectSubscriptionProp["DATA"] = 3] = "DATA";
|
|
4504
|
+
})(EffectSubscriptionProp || (EffectSubscriptionProp = {}));
|
|
4209
4505
|
var EffectProperty;
|
|
4210
4506
|
(function (EffectProperty) {
|
|
4211
4507
|
EffectProperty["COMPONENT"] = ":";
|
|
@@ -4242,19 +4538,16 @@
|
|
|
4242
4538
|
}
|
|
4243
4539
|
const effectSubscriber = ctx.$effectSubscriber$;
|
|
4244
4540
|
if (effectSubscriber) {
|
|
4245
|
-
const effects = (this.$effects$ ||=
|
|
4541
|
+
const effects = (this.$effects$ ||= new Set());
|
|
4246
4542
|
// Let's make sure that we have a reference to this effect.
|
|
4247
4543
|
// Adding reference is essentially adding a subscription, so if the signal
|
|
4248
4544
|
// changes we know who to notify.
|
|
4249
|
-
|
|
4545
|
+
ensureContainsSubscription(effects, effectSubscriber);
|
|
4250
4546
|
// But when effect is scheduled in needs to be able to know which signals
|
|
4251
4547
|
// to unsubscribe from. So we need to store the reference from the effect back
|
|
4252
4548
|
// to this signal.
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
// We need to add the subscriber to the effect so that we can clean it up later
|
|
4256
|
-
ensureEffectContainsSubscriber(effectSubscriber[EffectSubscriptionsProp.EFFECT], this, this.$container$);
|
|
4257
|
-
}
|
|
4549
|
+
ensureContainsBackRef(effectSubscriber, this);
|
|
4550
|
+
addQrlToSerializationCtx(effectSubscriber, this.$container$);
|
|
4258
4551
|
}
|
|
4259
4552
|
}
|
|
4260
4553
|
return this.untrackedValue;
|
|
@@ -4273,122 +4566,97 @@
|
|
|
4273
4566
|
}
|
|
4274
4567
|
toString() {
|
|
4275
4568
|
return (`[${this.constructor.name}${this.$invalid$ ? ' INVALID' : ''} ${String(this.$untrackedValue$)}]` +
|
|
4276
|
-
(this.$effects
|
|
4569
|
+
(Array.from(this.$effects$ || [])
|
|
4570
|
+
.map((e) => '\n -> ' + pad(qwikDebugToString(e[0]), ' '))
|
|
4571
|
+
.join('\n') || ''));
|
|
4277
4572
|
}
|
|
4278
4573
|
toJSON() {
|
|
4279
4574
|
return { value: this.$untrackedValue$ };
|
|
4280
4575
|
}
|
|
4281
4576
|
}
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
const isMissing = array.indexOf(value) === -1;
|
|
4285
|
-
if (isMissing) {
|
|
4286
|
-
array.push(value);
|
|
4287
|
-
}
|
|
4288
|
-
};
|
|
4289
|
-
const ensureContainsEffect = (array, effectSubscriptions) => {
|
|
4290
|
-
for (let i = 0; i < array.length; i++) {
|
|
4291
|
-
const existingEffect = array[i];
|
|
4292
|
-
if (existingEffect[0] === effectSubscriptions[0] &&
|
|
4293
|
-
existingEffect[1] === effectSubscriptions[1]) {
|
|
4294
|
-
return;
|
|
4295
|
-
}
|
|
4296
|
-
}
|
|
4297
|
-
array.push(effectSubscriptions);
|
|
4577
|
+
const ensureContainsSubscription = (array, effectSubscription) => {
|
|
4578
|
+
array.add(effectSubscription);
|
|
4298
4579
|
};
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4580
|
+
/** Ensure the item is in back refs set */
|
|
4581
|
+
const ensureContainsBackRef = (array, value) => {
|
|
4582
|
+
array[EffectSubscriptionProp.BACK_REF] ||= new Set();
|
|
4583
|
+
array[EffectSubscriptionProp.BACK_REF].add(value);
|
|
4584
|
+
};
|
|
4585
|
+
const addQrlToSerializationCtx = (effectSubscriber, container) => {
|
|
4586
|
+
if (!!container && !isDomContainer(container)) {
|
|
4587
|
+
const effect = effectSubscriber[EffectSubscriptionProp.CONSUMER];
|
|
4588
|
+
const property = effectSubscriber[EffectSubscriptionProp.PROPERTY];
|
|
4589
|
+
let qrl = null;
|
|
4590
|
+
if (isTask(effect)) {
|
|
4591
|
+
qrl = effect.$qrl$;
|
|
4304
4592
|
}
|
|
4305
|
-
effect
|
|
4306
|
-
|
|
4307
|
-
else if (vnode_isVNode(effect) && !vnode_isTextVNode(effect)) {
|
|
4308
|
-
let subscribers = vnode_getProp(effect, QSubscribers, container ? container.$getObjectById$ : null);
|
|
4309
|
-
subscribers ||= [];
|
|
4310
|
-
if (subscriberExistInSubscribers(subscribers, subscriber)) {
|
|
4311
|
-
return;
|
|
4593
|
+
else if (effect instanceof ComputedSignal) {
|
|
4594
|
+
qrl = effect.$computeQrl$;
|
|
4312
4595
|
}
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
}
|
|
4316
|
-
else if (isSSRNode(effect)) {
|
|
4317
|
-
let subscribers = effect.getProp(QSubscribers);
|
|
4318
|
-
subscribers ||= [];
|
|
4319
|
-
if (subscriberExistInSubscribers(subscribers, subscriber)) {
|
|
4320
|
-
return;
|
|
4596
|
+
else if (property === EffectProperty.COMPONENT) {
|
|
4597
|
+
qrl = container.getHostProp(effect, OnRenderProp);
|
|
4321
4598
|
}
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
}
|
|
4325
|
-
};
|
|
4326
|
-
const isSSRNode = (effect) => {
|
|
4327
|
-
return 'setProp' in effect && 'getProp' in effect && 'removeProp' in effect && 'id' in effect;
|
|
4328
|
-
};
|
|
4329
|
-
const subscriberExistInSubscribers = (subscribers, subscriber) => {
|
|
4330
|
-
for (let i = 0; i < subscribers.length; i++) {
|
|
4331
|
-
if (subscribers[i] === subscriber) {
|
|
4332
|
-
return true;
|
|
4599
|
+
if (qrl) {
|
|
4600
|
+
container.serializationCtx.$eventQrls$.add(qrl);
|
|
4333
4601
|
}
|
|
4334
4602
|
}
|
|
4335
|
-
return false;
|
|
4336
4603
|
};
|
|
4337
4604
|
const triggerEffects = (container, signal, effects) => {
|
|
4605
|
+
const isBrowser = isDomContainer(container);
|
|
4338
4606
|
if (effects) {
|
|
4339
|
-
const scheduleEffect = (
|
|
4340
|
-
const
|
|
4341
|
-
const property =
|
|
4607
|
+
const scheduleEffect = (effectSubscription) => {
|
|
4608
|
+
const consumer = effectSubscription[EffectSubscriptionProp.CONSUMER];
|
|
4609
|
+
const property = effectSubscription[EffectSubscriptionProp.PROPERTY];
|
|
4342
4610
|
assertDefined(container, 'Container must be defined.');
|
|
4343
|
-
if (isTask(
|
|
4344
|
-
|
|
4611
|
+
if (isTask(consumer)) {
|
|
4612
|
+
consumer.$flags$ |= TaskFlags.DIRTY;
|
|
4345
4613
|
let choreType = ChoreType.TASK;
|
|
4346
|
-
if (
|
|
4614
|
+
if (consumer.$flags$ & TaskFlags.VISIBLE_TASK) {
|
|
4347
4615
|
choreType = ChoreType.VISIBLE;
|
|
4348
4616
|
}
|
|
4349
|
-
|
|
4350
|
-
choreType = ChoreType.RESOURCE;
|
|
4351
|
-
}
|
|
4352
|
-
container.$scheduler$(choreType, effect);
|
|
4617
|
+
container.$scheduler$(choreType, consumer);
|
|
4353
4618
|
}
|
|
4354
|
-
else if (
|
|
4619
|
+
else if (consumer instanceof Signal) {
|
|
4355
4620
|
// we don't schedule ComputedSignal/DerivedSignal directly, instead we invalidate it and
|
|
4356
4621
|
// and schedule the signals effects (recursively)
|
|
4357
|
-
if (
|
|
4622
|
+
if (consumer instanceof ComputedSignal) {
|
|
4358
4623
|
// Ensure that the computed signal's QRL is resolved.
|
|
4359
4624
|
// If not resolved schedule it to be resolved.
|
|
4360
|
-
if (!
|
|
4361
|
-
container.$scheduler$(ChoreType.QRL_RESOLVE, null,
|
|
4625
|
+
if (!consumer.$computeQrl$.resolved) {
|
|
4626
|
+
container.$scheduler$(ChoreType.QRL_RESOLVE, null, consumer.$computeQrl$);
|
|
4362
4627
|
}
|
|
4363
4628
|
}
|
|
4364
|
-
|
|
4629
|
+
consumer.$invalidate$();
|
|
4365
4630
|
}
|
|
4366
4631
|
else if (property === EffectProperty.COMPONENT) {
|
|
4367
|
-
const host =
|
|
4632
|
+
const host = consumer;
|
|
4368
4633
|
const qrl = container.getHostProp(host, OnRenderProp);
|
|
4369
4634
|
assertDefined(qrl, 'Component must have QRL');
|
|
4370
4635
|
const props = container.getHostProp(host, ELEMENT_PROPS);
|
|
4371
4636
|
container.$scheduler$(ChoreType.COMPONENT, host, qrl, props);
|
|
4372
4637
|
}
|
|
4373
|
-
else if (
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4638
|
+
else if (isBrowser) {
|
|
4639
|
+
if (property === EffectProperty.VNODE) {
|
|
4640
|
+
const host = consumer;
|
|
4641
|
+
container.$scheduler$(ChoreType.NODE_DIFF, host, host, signal);
|
|
4642
|
+
}
|
|
4643
|
+
else {
|
|
4644
|
+
const host = consumer;
|
|
4645
|
+
const effectData = effectSubscription[EffectSubscriptionProp.DATA];
|
|
4646
|
+
if (effectData instanceof SubscriptionData) {
|
|
4647
|
+
const data = effectData.data;
|
|
4648
|
+
const payload = {
|
|
4649
|
+
...data,
|
|
4650
|
+
$value$: signal,
|
|
4651
|
+
};
|
|
4652
|
+
container.$scheduler$(ChoreType.NODE_PROP, host, property, payload);
|
|
4653
|
+
}
|
|
4388
4654
|
}
|
|
4389
4655
|
}
|
|
4390
4656
|
};
|
|
4391
|
-
effects
|
|
4657
|
+
for (const effect of effects) {
|
|
4658
|
+
scheduleEffect(effect);
|
|
4659
|
+
}
|
|
4392
4660
|
}
|
|
4393
4661
|
};
|
|
4394
4662
|
/**
|
|
@@ -4446,7 +4714,7 @@
|
|
|
4446
4714
|
throwIfQRLNotResolved(computeQrl);
|
|
4447
4715
|
const ctx = tryGetInvokeContext();
|
|
4448
4716
|
const previousEffectSubscription = ctx?.$effectSubscriber$;
|
|
4449
|
-
ctx && (ctx.$effectSubscriber$ =
|
|
4717
|
+
ctx && (ctx.$effectSubscriber$ = getSubscriber(this, EffectProperty.VNODE));
|
|
4450
4718
|
try {
|
|
4451
4719
|
const untrackedValue = computeQrl.getFn(ctx)();
|
|
4452
4720
|
if (isPromise(untrackedValue)) {
|
|
@@ -4484,9 +4752,9 @@
|
|
|
4484
4752
|
// We need a separate flag to know when the computation needs running because
|
|
4485
4753
|
// we need the old value to know if effects need running after computation
|
|
4486
4754
|
$invalid$ = true;
|
|
4487
|
-
$effectDependencies$ = null;
|
|
4488
4755
|
$hostElement$ = null;
|
|
4489
4756
|
$forceRunEffects$ = false;
|
|
4757
|
+
[_EFFECT_BACK_REF] = null;
|
|
4490
4758
|
constructor(container, fn, args, fnStr) {
|
|
4491
4759
|
super(container, NEEDS_COMPUTATION);
|
|
4492
4760
|
this.$args$ = args;
|
|
@@ -4554,7 +4822,7 @@
|
|
|
4554
4822
|
if (jsx.key !== null) {
|
|
4555
4823
|
host.setProp(ELEMENT_KEY, jsx.key);
|
|
4556
4824
|
}
|
|
4557
|
-
return scheduler(ChoreType.
|
|
4825
|
+
return scheduler(ChoreType.COMPONENT, host, componentQrl, srcProps);
|
|
4558
4826
|
};
|
|
4559
4827
|
|
|
4560
4828
|
class ParentComponentData {
|
|
@@ -4566,21 +4834,10 @@
|
|
|
4566
4834
|
}
|
|
4567
4835
|
}
|
|
4568
4836
|
/** @internal */
|
|
4569
|
-
function _walkJSX(ssr, value, options) {
|
|
4837
|
+
async function _walkJSX(ssr, value, options) {
|
|
4570
4838
|
const stack = [value];
|
|
4571
|
-
let resolveDrain;
|
|
4572
|
-
let rejectDrain;
|
|
4573
|
-
const drained = options.allowPromises &&
|
|
4574
|
-
new Promise((res, rej) => {
|
|
4575
|
-
resolveDrain = res;
|
|
4576
|
-
rejectDrain = rej;
|
|
4577
|
-
});
|
|
4578
4839
|
const enqueue = (value) => stack.push(value);
|
|
4579
|
-
const
|
|
4580
|
-
stack.push(value);
|
|
4581
|
-
drain();
|
|
4582
|
-
};
|
|
4583
|
-
const drain = () => {
|
|
4840
|
+
const drain = async () => {
|
|
4584
4841
|
while (stack.length) {
|
|
4585
4842
|
const value = stack.pop();
|
|
4586
4843
|
if (value instanceof ParentComponentData) {
|
|
@@ -4590,20 +4847,10 @@
|
|
|
4590
4847
|
}
|
|
4591
4848
|
else if (typeof value === 'function') {
|
|
4592
4849
|
if (value === Promise) {
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
}
|
|
4596
|
-
stack.pop().then(resolveValue, rejectDrain);
|
|
4597
|
-
return;
|
|
4598
|
-
}
|
|
4599
|
-
const waitOn = value.apply(ssr);
|
|
4600
|
-
if (waitOn) {
|
|
4601
|
-
if (!options.allowPromises) {
|
|
4602
|
-
throw qError(QError.promisesNotExpected);
|
|
4603
|
-
}
|
|
4604
|
-
waitOn.then(drain, rejectDrain);
|
|
4605
|
-
return;
|
|
4850
|
+
stack.push(await stack.pop());
|
|
4851
|
+
continue;
|
|
4606
4852
|
}
|
|
4853
|
+
await value.apply(ssr);
|
|
4607
4854
|
continue;
|
|
4608
4855
|
}
|
|
4609
4856
|
processJSXNode(ssr, enqueue, value, {
|
|
@@ -4611,12 +4858,8 @@
|
|
|
4611
4858
|
parentComponentFrame: options.parentComponentFrame,
|
|
4612
4859
|
});
|
|
4613
4860
|
}
|
|
4614
|
-
if (stack.length === 0 && options.allowPromises) {
|
|
4615
|
-
resolveDrain();
|
|
4616
|
-
}
|
|
4617
4861
|
};
|
|
4618
|
-
drain();
|
|
4619
|
-
return drained;
|
|
4862
|
+
await drain();
|
|
4620
4863
|
}
|
|
4621
4864
|
function processJSXNode(ssr, enqueue, value, options) {
|
|
4622
4865
|
// console.log('processJSXNode', value);
|
|
@@ -4655,7 +4898,6 @@
|
|
|
4655
4898
|
enqueue(async () => {
|
|
4656
4899
|
for await (const chunk of value) {
|
|
4657
4900
|
await _walkJSX(ssr, chunk, {
|
|
4658
|
-
allowPromises: true,
|
|
4659
4901
|
currentStyleScoped: options.styleScoped,
|
|
4660
4902
|
parentComponentFrame: options.parentComponentFrame,
|
|
4661
4903
|
});
|
|
@@ -4742,7 +4984,6 @@
|
|
|
4742
4984
|
value = generator({
|
|
4743
4985
|
async write(chunk) {
|
|
4744
4986
|
await _walkJSX(ssr, chunk, {
|
|
4745
|
-
allowPromises: true,
|
|
4746
4987
|
currentStyleScoped: options.styleScoped,
|
|
4747
4988
|
parentComponentFrame: options.parentComponentFrame,
|
|
4748
4989
|
});
|
|
@@ -4899,11 +5140,23 @@
|
|
|
4899
5140
|
const appendToValue = (valueToAppend) => {
|
|
4900
5141
|
value = (value == null ? '' : value + '\n') + valueToAppend;
|
|
4901
5142
|
};
|
|
5143
|
+
const getQrlString = (qrl) => {
|
|
5144
|
+
/**
|
|
5145
|
+
* If there are captures we need to schedule so everything is executed in the right order + qrls
|
|
5146
|
+
* are resolved.
|
|
5147
|
+
*
|
|
5148
|
+
* For internal qrls (starting with `_`) we assume that they do the right thing.
|
|
5149
|
+
*/
|
|
5150
|
+
if (!qrl.$symbol$.startsWith('_') && (qrl.$captureRef$ || qrl.$capture$)) {
|
|
5151
|
+
qrl = createQRL(null, '_run', queueQRL, null, null, [qrl]);
|
|
5152
|
+
}
|
|
5153
|
+
return qrlToString(serializationCtx, qrl);
|
|
5154
|
+
};
|
|
4902
5155
|
if (Array.isArray(qrls)) {
|
|
4903
5156
|
for (let i = 0; i <= qrls.length; i++) {
|
|
4904
5157
|
const qrl = qrls[i];
|
|
4905
|
-
if (isQrl(qrl)) {
|
|
4906
|
-
appendToValue(
|
|
5158
|
+
if (isQrl$1(qrl)) {
|
|
5159
|
+
appendToValue(getQrlString(qrl));
|
|
4907
5160
|
addQwikEventToSerializationContext(serializationCtx, key, qrl);
|
|
4908
5161
|
}
|
|
4909
5162
|
else if (qrl != null) {
|
|
@@ -4915,8 +5168,8 @@
|
|
|
4915
5168
|
}
|
|
4916
5169
|
}
|
|
4917
5170
|
}
|
|
4918
|
-
else if (isQrl(qrls)) {
|
|
4919
|
-
value =
|
|
5171
|
+
else if (isQrl$1(qrls)) {
|
|
5172
|
+
value = getQrlString(qrls);
|
|
4920
5173
|
addQwikEventToSerializationContext(serializationCtx, key, qrls);
|
|
4921
5174
|
}
|
|
4922
5175
|
return value;
|
|
@@ -4966,7 +5219,7 @@
|
|
|
4966
5219
|
*
|
|
4967
5220
|
* @public
|
|
4968
5221
|
*/
|
|
4969
|
-
const version = "2.0.0-alpha.
|
|
5222
|
+
const version = "2.0.0-alpha.7-dev+a26598a";
|
|
4970
5223
|
|
|
4971
5224
|
/** @internal */
|
|
4972
5225
|
class _SharedContainer {
|
|
@@ -4998,13 +5251,6 @@
|
|
|
4998
5251
|
}
|
|
4999
5252
|
}
|
|
5000
5253
|
|
|
5001
|
-
/** @internal */
|
|
5002
|
-
const _CONST_PROPS = Symbol('CONST');
|
|
5003
|
-
/** @internal */
|
|
5004
|
-
const _VAR_PROPS = Symbol('VAR');
|
|
5005
|
-
/** @internal @deprecated v1 compat */
|
|
5006
|
-
const _IMMUTABLE = Symbol('IMMUTABLE');
|
|
5007
|
-
|
|
5008
5254
|
// Keep these properties named like this so they're the same as from wrapSignal
|
|
5009
5255
|
const getValueProp = (p0) => p0.value;
|
|
5010
5256
|
const getProp = (p0, p1) => p0[p1];
|
|
@@ -5416,7 +5662,7 @@
|
|
|
5416
5662
|
else if (isTask(value)) {
|
|
5417
5663
|
return `Task(${qwikDebugToString(value.$qrl$)})`;
|
|
5418
5664
|
}
|
|
5419
|
-
else if (isQrl
|
|
5665
|
+
else if (isQrl(value)) {
|
|
5420
5666
|
return `Qrl(${value.$symbol$})`;
|
|
5421
5667
|
}
|
|
5422
5668
|
else if (typeof value === 'object' || typeof value === 'function') {
|
|
@@ -5570,14 +5816,21 @@
|
|
|
5570
5816
|
CONTEXT_CHAR: /* **** */ ']',
|
|
5571
5817
|
SEQ_IDX: /* ************ */ 94, // `^` - `q:seqIdx' - Sequential scope id
|
|
5572
5818
|
SEQ_IDX_CHAR: /* **** */ '^',
|
|
5573
|
-
|
|
5574
|
-
|
|
5819
|
+
BACK_REFS: /* ********** */ 96, // '`' - `q:brefs' - Effect dependencies/subscriptions
|
|
5820
|
+
BACK_REFS_CHAR: /* ** */ '`',
|
|
5575
5821
|
SEPARATOR: /* ********* */ 124, // `|` - Separator char to encode any key/value pairs.
|
|
5576
5822
|
SEPARATOR_CHAR: /* ** */ '|',
|
|
5577
5823
|
SLOT: /* ************** */ 126, // `~` - `q:slot' - Slot name
|
|
5578
5824
|
SLOT_CHAR: /* ******* */ '~',
|
|
5579
5825
|
};
|
|
5580
5826
|
|
|
5827
|
+
const mergeMaps = (map1, map2) => {
|
|
5828
|
+
for (const [k, v] of map2) {
|
|
5829
|
+
map1.set(k, v);
|
|
5830
|
+
}
|
|
5831
|
+
return map1;
|
|
5832
|
+
};
|
|
5833
|
+
|
|
5581
5834
|
/**
|
|
5582
5835
|
* @file
|
|
5583
5836
|
*
|
|
@@ -5833,6 +6086,7 @@
|
|
|
5833
6086
|
elementVNode[VNodeProps.flags] ^= VNodeFlags.Inflated;
|
|
5834
6087
|
const element = elementVNode[ElementVNodeProps.element];
|
|
5835
6088
|
const attributes = element.attributes;
|
|
6089
|
+
const props = vnode_getProps(elementVNode);
|
|
5836
6090
|
for (let idx = 0; idx < attributes.length; idx++) {
|
|
5837
6091
|
const attr = attributes[idx];
|
|
5838
6092
|
const key = attr.name;
|
|
@@ -5843,15 +6097,15 @@
|
|
|
5843
6097
|
}
|
|
5844
6098
|
else if (key.startsWith(QContainerAttr)) {
|
|
5845
6099
|
if (attr.value === QContainerValue.HTML) {
|
|
5846
|
-
mapArray_set(
|
|
6100
|
+
mapArray_set(props, dangerouslySetInnerHTML, element.innerHTML, 0);
|
|
5847
6101
|
}
|
|
5848
6102
|
else if (attr.value === QContainerValue.TEXT && 'value' in element) {
|
|
5849
|
-
mapArray_set(
|
|
6103
|
+
mapArray_set(props, 'value', element.value, 0);
|
|
5850
6104
|
}
|
|
5851
6105
|
}
|
|
5852
6106
|
else if (!key.startsWith('on:')) {
|
|
5853
6107
|
const value = attr.value;
|
|
5854
|
-
mapArray_set(
|
|
6108
|
+
mapArray_set(props, key, value, 0);
|
|
5855
6109
|
}
|
|
5856
6110
|
}
|
|
5857
6111
|
}
|
|
@@ -6287,54 +6541,16 @@
|
|
|
6287
6541
|
journal.length = 0;
|
|
6288
6542
|
};
|
|
6289
6543
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
6290
|
-
const mapApp_findIndx = (elementVNode, key, start) => {
|
|
6291
|
-
assertTrue(start % 2 === 0, 'Expecting even number.');
|
|
6292
|
-
let bottom = start >> 1;
|
|
6293
|
-
let top = (elementVNode.length - 2) >> 1;
|
|
6294
|
-
while (bottom <= top) {
|
|
6295
|
-
const mid = bottom + ((top - bottom) >> 1);
|
|
6296
|
-
const midKey = elementVNode[mid << 1];
|
|
6297
|
-
if (midKey === key) {
|
|
6298
|
-
return mid << 1;
|
|
6299
|
-
}
|
|
6300
|
-
if (midKey < key) {
|
|
6301
|
-
bottom = mid + 1;
|
|
6302
|
-
}
|
|
6303
|
-
else {
|
|
6304
|
-
top = mid - 1;
|
|
6305
|
-
}
|
|
6306
|
-
}
|
|
6307
|
-
return (bottom << 1) ^ -1;
|
|
6308
|
-
};
|
|
6309
|
-
const mapArray_set = (elementVNode, key, value, start) => {
|
|
6310
|
-
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
6311
|
-
if (indx >= 0) {
|
|
6312
|
-
if (value == null) {
|
|
6313
|
-
elementVNode.splice(indx, 2);
|
|
6314
|
-
}
|
|
6315
|
-
else {
|
|
6316
|
-
elementVNode[indx + 1] = value;
|
|
6317
|
-
}
|
|
6318
|
-
}
|
|
6319
|
-
else if (value != null) {
|
|
6320
|
-
elementVNode.splice(indx ^ -1, 0, key, value);
|
|
6321
|
-
}
|
|
6322
|
-
};
|
|
6323
|
-
const mapArray_get = (elementVNode, key, start) => {
|
|
6324
|
-
const indx = mapApp_findIndx(elementVNode, key, start);
|
|
6325
|
-
if (indx >= 0) {
|
|
6326
|
-
return elementVNode[indx + 1];
|
|
6327
|
-
}
|
|
6328
|
-
else {
|
|
6329
|
-
return null;
|
|
6330
|
-
}
|
|
6331
|
-
};
|
|
6332
|
-
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
6333
6544
|
const vnode_insertBefore = (journal, parent, newChild, insertBefore) => {
|
|
6334
6545
|
ensureElementOrVirtualVNode(parent);
|
|
6335
6546
|
if (vnode_isElementVNode(parent)) {
|
|
6336
6547
|
ensureMaterialized(parent);
|
|
6337
6548
|
}
|
|
6549
|
+
if (newChild === insertBefore) {
|
|
6550
|
+
// invalid insertBefore. We can't insert before self reference
|
|
6551
|
+
// prevent infinity loop and putting self reference to next sibling
|
|
6552
|
+
insertBefore = null;
|
|
6553
|
+
}
|
|
6338
6554
|
let adjustedInsertBefore = null;
|
|
6339
6555
|
if (insertBefore == null) {
|
|
6340
6556
|
if (vnode_isVirtualVNode(parent)) {
|
|
@@ -6458,9 +6674,10 @@
|
|
|
6458
6674
|
const elementVNode = ensureElementVNode(vnode);
|
|
6459
6675
|
let elementName = elementVNode[ElementVNodeProps.elementName];
|
|
6460
6676
|
if (elementName === undefined) {
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
elementVNode[
|
|
6677
|
+
const element = elementVNode[ElementVNodeProps.element];
|
|
6678
|
+
const nodeName = build.isDev ? fastNodeName(element).toLowerCase() : fastNodeName(element);
|
|
6679
|
+
elementName = elementVNode[ElementVNodeProps.elementName] = nodeName;
|
|
6680
|
+
elementVNode[VNodeProps.flags] |= vnode_getElementNamespaceFlags(element);
|
|
6464
6681
|
}
|
|
6465
6682
|
return elementName;
|
|
6466
6683
|
};
|
|
@@ -6642,6 +6859,20 @@
|
|
|
6642
6859
|
}
|
|
6643
6860
|
return node;
|
|
6644
6861
|
};
|
|
6862
|
+
let _fastNamespaceURI = null;
|
|
6863
|
+
const fastNamespaceURI = (element) => {
|
|
6864
|
+
if (!_fastNamespaceURI) {
|
|
6865
|
+
_fastNamespaceURI = fastGetter(element, 'namespaceURI');
|
|
6866
|
+
}
|
|
6867
|
+
return _fastNamespaceURI.call(element);
|
|
6868
|
+
};
|
|
6869
|
+
let _fastNodeName = null;
|
|
6870
|
+
const fastNodeName = (element) => {
|
|
6871
|
+
if (!_fastNodeName) {
|
|
6872
|
+
_fastNodeName = fastGetter(element, 'nodeName');
|
|
6873
|
+
}
|
|
6874
|
+
return _fastNodeName.call(element);
|
|
6875
|
+
};
|
|
6645
6876
|
const fastGetter = (prototype, name) => {
|
|
6646
6877
|
let getter;
|
|
6647
6878
|
while (prototype && !(getter = Object.getOwnPropertyDescriptor(prototype, name)?.get)) {
|
|
@@ -6708,8 +6939,11 @@
|
|
|
6708
6939
|
container.$setRawState$(parseInt(id), vParent);
|
|
6709
6940
|
build.isDev && vnode_setAttr(null, vParent, ELEMENT_ID, id);
|
|
6710
6941
|
}
|
|
6711
|
-
else if (peek() === VNodeDataChar.
|
|
6712
|
-
|
|
6942
|
+
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
6943
|
+
if (!container) {
|
|
6944
|
+
container = getDomContainer(vParent[ElementVNodeProps.element]);
|
|
6945
|
+
}
|
|
6946
|
+
setEffectBackRefFromVNodeData(vParent, consumeValue(), container);
|
|
6713
6947
|
}
|
|
6714
6948
|
else {
|
|
6715
6949
|
// prevent infinity loop if there are some characters outside the range
|
|
@@ -6719,6 +6953,18 @@
|
|
|
6719
6953
|
}
|
|
6720
6954
|
return vFirstChild;
|
|
6721
6955
|
};
|
|
6956
|
+
function setEffectBackRefFromVNodeData(vParent, value, container) {
|
|
6957
|
+
const deserializedSubMap = container.$getObjectById$(value);
|
|
6958
|
+
if (!vParent[_EFFECT_BACK_REF]) {
|
|
6959
|
+
Object.defineProperty(vParent, _EFFECT_BACK_REF, {
|
|
6960
|
+
value: deserializedSubMap,
|
|
6961
|
+
});
|
|
6962
|
+
}
|
|
6963
|
+
else {
|
|
6964
|
+
const subMap = vParent[_EFFECT_BACK_REF];
|
|
6965
|
+
mergeMaps(subMap, deserializedSubMap);
|
|
6966
|
+
}
|
|
6967
|
+
}
|
|
6722
6968
|
const processVNodeData$1 = (vData, callback) => {
|
|
6723
6969
|
let nextToConsumeIdx = 0;
|
|
6724
6970
|
let ch = 0;
|
|
@@ -6763,8 +7009,9 @@
|
|
|
6763
7009
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6764
7010
|
vnode_ensureElementInflated(vnode);
|
|
6765
7011
|
const keys = [];
|
|
6766
|
-
|
|
6767
|
-
|
|
7012
|
+
const props = vnode_getProps(vnode);
|
|
7013
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
7014
|
+
const key = props[i];
|
|
6768
7015
|
if (!key.startsWith(Q_PROPS_SEPARATOR)) {
|
|
6769
7016
|
keys.push(key);
|
|
6770
7017
|
}
|
|
@@ -6777,22 +7024,23 @@
|
|
|
6777
7024
|
const type = vnode[VNodeProps.flags];
|
|
6778
7025
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6779
7026
|
vnode_ensureElementInflated(vnode);
|
|
6780
|
-
const
|
|
7027
|
+
const props = vnode_getProps(vnode);
|
|
7028
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6781
7029
|
if (idx >= 0) {
|
|
6782
|
-
if (
|
|
7030
|
+
if (props[idx + 1] != value && (type & VNodeFlags.Element) !== 0) {
|
|
6783
7031
|
// Values are different, update DOM
|
|
6784
7032
|
const element = vnode[ElementVNodeProps.element];
|
|
6785
7033
|
journal && journal.push(VNodeJournalOpCode.SetAttribute, element, key, value);
|
|
6786
7034
|
}
|
|
6787
7035
|
if (value == null) {
|
|
6788
|
-
|
|
7036
|
+
props.splice(idx, 2);
|
|
6789
7037
|
}
|
|
6790
7038
|
else {
|
|
6791
|
-
|
|
7039
|
+
props[idx + 1] = value;
|
|
6792
7040
|
}
|
|
6793
7041
|
}
|
|
6794
7042
|
else if (value != null) {
|
|
6795
|
-
|
|
7043
|
+
props.splice(idx ^ -1, 0, key, value);
|
|
6796
7044
|
if ((type & VNodeFlags.Element) !== 0) {
|
|
6797
7045
|
// New value, update DOM
|
|
6798
7046
|
const element = vnode[ElementVNodeProps.element];
|
|
@@ -6805,7 +7053,8 @@
|
|
|
6805
7053
|
const type = vnode[VNodeProps.flags];
|
|
6806
7054
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6807
7055
|
vnode_ensureElementInflated(vnode);
|
|
6808
|
-
|
|
7056
|
+
const props = vnode_getProps(vnode);
|
|
7057
|
+
return mapArray_get(props, key, 0);
|
|
6809
7058
|
}
|
|
6810
7059
|
return null;
|
|
6811
7060
|
};
|
|
@@ -6813,11 +7062,12 @@
|
|
|
6813
7062
|
const type = vnode[VNodeProps.flags];
|
|
6814
7063
|
if ((type & VNodeFlags.ELEMENT_OR_VIRTUAL_MASK) !== 0) {
|
|
6815
7064
|
type & VNodeFlags.Element && vnode_ensureElementInflated(vnode);
|
|
6816
|
-
const
|
|
7065
|
+
const props = vnode_getProps(vnode);
|
|
7066
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6817
7067
|
if (idx >= 0) {
|
|
6818
|
-
let value =
|
|
7068
|
+
let value = props[idx + 1];
|
|
6819
7069
|
if (typeof value === 'string' && getObject) {
|
|
6820
|
-
|
|
7070
|
+
props[idx + 1] = value = getObject(value);
|
|
6821
7071
|
}
|
|
6822
7072
|
return value;
|
|
6823
7073
|
}
|
|
@@ -6826,12 +7076,13 @@
|
|
|
6826
7076
|
};
|
|
6827
7077
|
const vnode_setProp = (vnode, key, value) => {
|
|
6828
7078
|
ensureElementOrVirtualVNode(vnode);
|
|
6829
|
-
const
|
|
7079
|
+
const props = vnode_getProps(vnode);
|
|
7080
|
+
const idx = mapApp_findIndx(props, key, 0);
|
|
6830
7081
|
if (idx >= 0) {
|
|
6831
|
-
|
|
7082
|
+
props[idx + 1] = value;
|
|
6832
7083
|
}
|
|
6833
7084
|
else if (value != null) {
|
|
6834
|
-
|
|
7085
|
+
props.splice(idx ^ -1, 0, key, value);
|
|
6835
7086
|
}
|
|
6836
7087
|
};
|
|
6837
7088
|
const vnode_getPropStartIndex = (vnode) => {
|
|
@@ -6844,6 +7095,9 @@
|
|
|
6844
7095
|
}
|
|
6845
7096
|
throw qError(QError.invalidVNodeType, [type]);
|
|
6846
7097
|
};
|
|
7098
|
+
const vnode_getProps = (vnode) => {
|
|
7099
|
+
return vnode[vnode_getPropStartIndex(vnode)];
|
|
7100
|
+
};
|
|
6847
7101
|
const vnode_getParent = (vnode) => {
|
|
6848
7102
|
return vnode[VNodeProps.parent] || null;
|
|
6849
7103
|
};
|
|
@@ -7007,8 +7261,11 @@
|
|
|
7007
7261
|
else if (peek() === VNodeDataChar.SEQ_IDX) {
|
|
7008
7262
|
vnode_setAttr(null, vParent, ELEMENT_SEQ_IDX, consumeValue());
|
|
7009
7263
|
}
|
|
7010
|
-
else if (peek() === VNodeDataChar.
|
|
7011
|
-
|
|
7264
|
+
else if (peek() === VNodeDataChar.BACK_REFS) {
|
|
7265
|
+
if (!container) {
|
|
7266
|
+
container = getDomContainer(element);
|
|
7267
|
+
}
|
|
7268
|
+
setEffectBackRefFromVNodeData(vParent, consumeValue(), container);
|
|
7012
7269
|
}
|
|
7013
7270
|
else if (peek() === VNodeDataChar.CONTEXT) {
|
|
7014
7271
|
vnode_setAttr(null, vParent, QCtxAttr, consumeValue());
|
|
@@ -7074,60 +7331,6 @@
|
|
|
7074
7331
|
throw qError(QError.invalidVNodeType, [type]);
|
|
7075
7332
|
};
|
|
7076
7333
|
const isElement = (node) => node && typeof node == 'object' && fastNodeType(node) === /** Node.ELEMENT_NODE* */ 1;
|
|
7077
|
-
/// These global variables are used to avoid creating new arrays for each call to `vnode_documentPosition`.
|
|
7078
|
-
const aPath = [];
|
|
7079
|
-
const bPath = [];
|
|
7080
|
-
const vnode_documentPosition = (a, b, rootVNode) => {
|
|
7081
|
-
if (a === b) {
|
|
7082
|
-
return 0;
|
|
7083
|
-
}
|
|
7084
|
-
let aDepth = -1;
|
|
7085
|
-
let bDepth = -1;
|
|
7086
|
-
while (a) {
|
|
7087
|
-
const vNode = (aPath[++aDepth] = a);
|
|
7088
|
-
a = (vNode[VNodeProps.parent] ||
|
|
7089
|
-
(rootVNode && vnode_getProp(a, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
7090
|
-
}
|
|
7091
|
-
while (b) {
|
|
7092
|
-
const vNode = (bPath[++bDepth] = b);
|
|
7093
|
-
b = (vNode[VNodeProps.parent] ||
|
|
7094
|
-
(rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))));
|
|
7095
|
-
}
|
|
7096
|
-
while (aDepth >= 0 && bDepth >= 0) {
|
|
7097
|
-
a = aPath[aDepth];
|
|
7098
|
-
b = bPath[bDepth];
|
|
7099
|
-
if (a === b) {
|
|
7100
|
-
// if the nodes are the same, we need to check the next level.
|
|
7101
|
-
aDepth--;
|
|
7102
|
-
bDepth--;
|
|
7103
|
-
}
|
|
7104
|
-
else {
|
|
7105
|
-
// We found a difference so we need to scan nodes at this level.
|
|
7106
|
-
let cursor = b;
|
|
7107
|
-
do {
|
|
7108
|
-
cursor = vnode_getNextSibling(cursor);
|
|
7109
|
-
if (cursor === a) {
|
|
7110
|
-
return 1;
|
|
7111
|
-
}
|
|
7112
|
-
} while (cursor);
|
|
7113
|
-
cursor = b;
|
|
7114
|
-
do {
|
|
7115
|
-
cursor = vnode_getPreviousSibling(cursor);
|
|
7116
|
-
if (cursor === a) {
|
|
7117
|
-
return -1;
|
|
7118
|
-
}
|
|
7119
|
-
} while (cursor);
|
|
7120
|
-
if (rootVNode && vnode_getProp(b, QSlotParent, (id) => vnode_locate(rootVNode, id))) {
|
|
7121
|
-
// The "b" node is a projection, so we need to set it after "a" node,
|
|
7122
|
-
// because the "a" node could be a context provider.
|
|
7123
|
-
return -1;
|
|
7124
|
-
}
|
|
7125
|
-
// The node is not in the list of siblings, that means it must be disconnected.
|
|
7126
|
-
return 1;
|
|
7127
|
-
}
|
|
7128
|
-
}
|
|
7129
|
-
return aDepth < bDepth ? -1 : 1;
|
|
7130
|
-
};
|
|
7131
7334
|
/**
|
|
7132
7335
|
* Use this method to find the parent component for projection.
|
|
7133
7336
|
*
|
|
@@ -7170,23 +7373,20 @@
|
|
|
7170
7373
|
};
|
|
7171
7374
|
const VNodeArray = class VNode extends Array {
|
|
7172
7375
|
static createElement(flags, parent, previousSibling, nextSibling, firstChild, lastChild, element, elementName) {
|
|
7173
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7174
|
-
vnode.push(firstChild, lastChild, element, elementName);
|
|
7376
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, firstChild, lastChild, element, elementName, []);
|
|
7175
7377
|
return vnode;
|
|
7176
7378
|
}
|
|
7177
7379
|
static createText(flags, parent, previousSibling, nextSibling, textNode, text) {
|
|
7178
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7179
|
-
vnode.push(textNode, text);
|
|
7380
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, textNode, text);
|
|
7180
7381
|
return vnode;
|
|
7181
7382
|
}
|
|
7182
7383
|
static createVirtual(flags, parent, previousSibling, nextSibling, firstChild, lastChild) {
|
|
7183
|
-
const vnode = new VNode(flags, parent, previousSibling, nextSibling);
|
|
7184
|
-
vnode.push(firstChild, lastChild);
|
|
7384
|
+
const vnode = new VNode(flags, parent, previousSibling, nextSibling, firstChild, lastChild, []);
|
|
7185
7385
|
return vnode;
|
|
7186
7386
|
}
|
|
7187
|
-
constructor(flags, parent, previousSibling, nextSibling) {
|
|
7188
|
-
|
|
7189
|
-
|
|
7387
|
+
constructor(flags, parent, previousSibling, nextSibling, ...rest) {
|
|
7388
|
+
// @ts-expect-error
|
|
7389
|
+
super(flags, parent, previousSibling, nextSibling, ...rest);
|
|
7190
7390
|
if (build.isDev) {
|
|
7191
7391
|
this.toString = vnode_toString;
|
|
7192
7392
|
}
|
|
@@ -7251,10 +7451,12 @@
|
|
|
7251
7451
|
return returnValue;
|
|
7252
7452
|
}
|
|
7253
7453
|
const newInvokeContextFromTuple = ([element, event, url]) => {
|
|
7254
|
-
const
|
|
7454
|
+
const domContainer = getDomContainer(element);
|
|
7455
|
+
const container = domContainer.element;
|
|
7456
|
+
const vNode = container ? vnode_locate(domContainer.rootVNode, element) : undefined;
|
|
7255
7457
|
const locale = container?.getAttribute(QLocaleAttr) || undefined;
|
|
7256
7458
|
locale && setLocale(locale);
|
|
7257
|
-
return newInvokeContext(locale,
|
|
7459
|
+
return newInvokeContext(locale, vNode, element, event, url);
|
|
7258
7460
|
};
|
|
7259
7461
|
// TODO how about putting url and locale (and event/custom?) in to a "static" object
|
|
7260
7462
|
const newInvokeContext = (locale, hostElement, element, event, url) => {
|
|
@@ -7289,16 +7491,14 @@
|
|
|
7289
7491
|
* @param property `true` - subscriber is component `false` - subscriber is VNode `string` -
|
|
7290
7492
|
* subscriber is property
|
|
7291
7493
|
* @param container
|
|
7494
|
+
* @param data - Additional subscription data
|
|
7292
7495
|
* @returns
|
|
7293
7496
|
*/
|
|
7294
7497
|
const trackSignal = (fn, subscriber, property, container, data) => {
|
|
7295
7498
|
const previousSubscriber = trackInvocation.$effectSubscriber$;
|
|
7296
7499
|
const previousContainer = trackInvocation.$container$;
|
|
7297
7500
|
try {
|
|
7298
|
-
trackInvocation.$effectSubscriber$ =
|
|
7299
|
-
if (data) {
|
|
7300
|
-
trackInvocation.$effectSubscriber$.push(data);
|
|
7301
|
-
}
|
|
7501
|
+
trackInvocation.$effectSubscriber$ = getSubscriber(subscriber, property, data);
|
|
7302
7502
|
trackInvocation.$container$ = container;
|
|
7303
7503
|
return invoke(trackInvocation, fn);
|
|
7304
7504
|
}
|
|
@@ -7319,8 +7519,16 @@
|
|
|
7319
7519
|
if (iCtx) {
|
|
7320
7520
|
const hostElement = iCtx.$hostElement$;
|
|
7321
7521
|
let element = null;
|
|
7322
|
-
if (
|
|
7323
|
-
|
|
7522
|
+
if (hostElement != null) {
|
|
7523
|
+
if (vnode_isVNode(hostElement)) {
|
|
7524
|
+
if (vnode_isElementVNode(hostElement)) {
|
|
7525
|
+
element = vnode_getNode(hostElement);
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7528
|
+
else {
|
|
7529
|
+
// isSSRnode
|
|
7530
|
+
element = hostElement;
|
|
7531
|
+
}
|
|
7324
7532
|
}
|
|
7325
7533
|
return element ?? iCtx.$qrl$?.$setContainer$(undefined);
|
|
7326
7534
|
}
|
|
@@ -7956,9 +8164,9 @@
|
|
|
7956
8164
|
$storeProxyMap$ = new WeakMap();
|
|
7957
8165
|
$qFuncs$;
|
|
7958
8166
|
$instanceHash$;
|
|
7959
|
-
|
|
8167
|
+
vNodeLocate = (id) => vnode_locate(this.rootVNode, id);
|
|
8168
|
+
$stateData$;
|
|
7960
8169
|
$styleIds$ = null;
|
|
7961
|
-
$vnodeLocate$ = (id) => vnode_locate(this.rootVNode, id);
|
|
7962
8170
|
$renderCount$ = 0;
|
|
7963
8171
|
constructor(element) {
|
|
7964
8172
|
super(() => this.scheduleRender(), () => vnode_applyJournal(this.$journal$), {}, element.getAttribute('q:locale'));
|
|
@@ -7984,29 +8192,29 @@
|
|
|
7984
8192
|
this.rootVNode = vnode_newUnMaterializedElement(this.element);
|
|
7985
8193
|
// These are here to initialize all properties at once for single class transition
|
|
7986
8194
|
this.$rawStateData$ = null;
|
|
7987
|
-
this
|
|
8195
|
+
this.$stateData$ = null;
|
|
7988
8196
|
const document = this.element.ownerDocument;
|
|
7989
8197
|
if (!document.qVNodeData) {
|
|
7990
8198
|
processVNodeData(document);
|
|
7991
8199
|
}
|
|
7992
8200
|
this.$rawStateData$ = [];
|
|
7993
|
-
this
|
|
8201
|
+
this.$stateData$ = [];
|
|
7994
8202
|
const qwikStates = element.querySelectorAll('script[type="qwik/state"]');
|
|
7995
8203
|
if (qwikStates.length !== 0) {
|
|
7996
8204
|
const lastState = qwikStates[qwikStates.length - 1];
|
|
7997
8205
|
this.$rawStateData$ = JSON.parse(lastState.textContent);
|
|
7998
|
-
this
|
|
8206
|
+
this.$stateData$ = wrapDeserializerProxy(this, this.$rawStateData$);
|
|
7999
8207
|
}
|
|
8000
8208
|
this.$qFuncs$ = getQFuncs(document, this.$instanceHash$) || EMPTY_ARRAY;
|
|
8001
8209
|
}
|
|
8002
8210
|
$setRawState$(id, vParent) {
|
|
8003
|
-
this
|
|
8211
|
+
this.$stateData$[id] = vParent;
|
|
8004
8212
|
}
|
|
8005
8213
|
parseQRL(qrl) {
|
|
8006
8214
|
return inflateQRL(this, parseQRL(qrl));
|
|
8007
8215
|
}
|
|
8008
8216
|
handleError(err, host) {
|
|
8009
|
-
if (qDev) {
|
|
8217
|
+
if (qDev && host) {
|
|
8010
8218
|
// Clean vdom
|
|
8011
8219
|
if (typeof document !== 'undefined') {
|
|
8012
8220
|
const vHost = host;
|
|
@@ -8030,7 +8238,7 @@
|
|
|
8030
8238
|
throw err;
|
|
8031
8239
|
}
|
|
8032
8240
|
}
|
|
8033
|
-
const errorStore = this.resolveContext(host, ERROR_CONTEXT);
|
|
8241
|
+
const errorStore = host && this.resolveContext(host, ERROR_CONTEXT);
|
|
8034
8242
|
if (!errorStore) {
|
|
8035
8243
|
throw err;
|
|
8036
8244
|
}
|
|
@@ -8066,7 +8274,7 @@
|
|
|
8066
8274
|
vNode =
|
|
8067
8275
|
vnode_getParent(vNode) ||
|
|
8068
8276
|
// If virtual node, than it could be a slot so we need to read its parent.
|
|
8069
|
-
vnode_getProp(vNode, QSlotParent, this
|
|
8277
|
+
vnode_getProp(vNode, QSlotParent, this.vNodeLocate);
|
|
8070
8278
|
}
|
|
8071
8279
|
else {
|
|
8072
8280
|
vNode = vnode_getParent(vNode);
|
|
@@ -8086,7 +8294,7 @@
|
|
|
8086
8294
|
case ELEMENT_PROPS:
|
|
8087
8295
|
case OnRenderProp:
|
|
8088
8296
|
case QCtxAttr:
|
|
8089
|
-
case
|
|
8297
|
+
case QBackRefs:
|
|
8090
8298
|
getObjectById = this.$getObjectById$;
|
|
8091
8299
|
break;
|
|
8092
8300
|
case ELEMENT_SEQ_IDX:
|
|
@@ -8099,7 +8307,7 @@
|
|
|
8099
8307
|
scheduleRender() {
|
|
8100
8308
|
this.$renderCount$++;
|
|
8101
8309
|
this.renderDone ||= getPlatform().nextTick(() => this.processChores());
|
|
8102
|
-
return this.renderDone;
|
|
8310
|
+
return this.renderDone.finally(() => emitEvent('qrender', { instanceHash: this.$instanceHash$, renderCount: this.$renderCount$ }));
|
|
8103
8311
|
}
|
|
8104
8312
|
processChores() {
|
|
8105
8313
|
let renderCount = this.$renderCount$;
|
|
@@ -8122,12 +8330,13 @@
|
|
|
8122
8330
|
ensureProjectionResolved(vNode) {
|
|
8123
8331
|
if ((vNode[VNodeProps.flags] & VNodeFlags.Resolved) === 0) {
|
|
8124
8332
|
vNode[VNodeProps.flags] |= VNodeFlags.Resolved;
|
|
8125
|
-
|
|
8126
|
-
|
|
8333
|
+
const props = vnode_getProps(vNode);
|
|
8334
|
+
for (let i = 0; i < props.length; i = i + 2) {
|
|
8335
|
+
const prop = props[i];
|
|
8127
8336
|
if (isSlotProp(prop)) {
|
|
8128
|
-
const value =
|
|
8337
|
+
const value = props[i + 1];
|
|
8129
8338
|
if (typeof value == 'string') {
|
|
8130
|
-
|
|
8339
|
+
props[i + 1] = this.vNodeLocate(value);
|
|
8131
8340
|
}
|
|
8132
8341
|
}
|
|
8133
8342
|
}
|
|
@@ -8138,7 +8347,7 @@
|
|
|
8138
8347
|
id = parseFloat(id);
|
|
8139
8348
|
}
|
|
8140
8349
|
assertTrue(id < this.$rawStateData$.length / 2, `Invalid reference: ${id} >= ${this.$rawStateData$.length / 2}`);
|
|
8141
|
-
return this
|
|
8350
|
+
return this.$stateData$[id];
|
|
8142
8351
|
};
|
|
8143
8352
|
getSyncFn(id) {
|
|
8144
8353
|
const fn = this.$qFuncs$[id];
|
|
@@ -8210,8 +8419,7 @@
|
|
|
8210
8419
|
? parseInt(property, 10)
|
|
8211
8420
|
: NaN;
|
|
8212
8421
|
if (Number.isNaN(i) || i < 0 || i >= this.$length$) {
|
|
8213
|
-
|
|
8214
|
-
return out;
|
|
8422
|
+
return Reflect.get(target, property, receiver);
|
|
8215
8423
|
}
|
|
8216
8424
|
// The serialized data is an array with 2 values for each item
|
|
8217
8425
|
const idx = i * 2;
|
|
@@ -8277,6 +8485,7 @@
|
|
|
8277
8485
|
switch (typeId) {
|
|
8278
8486
|
case TypeIds.Object:
|
|
8279
8487
|
// We use getters for making complex values lazy
|
|
8488
|
+
// TODO scan the data for computeQRLs and schedule resolve chores
|
|
8280
8489
|
for (let i = 0; i < data.length; i += 4) {
|
|
8281
8490
|
const key = deserializeData(container, data[i], data[i + 1]);
|
|
8282
8491
|
const valType = data[i + 2];
|
|
@@ -8316,7 +8525,7 @@
|
|
|
8316
8525
|
task.$flags$ = v[1];
|
|
8317
8526
|
task.$index$ = v[2];
|
|
8318
8527
|
task.$el$ = v[3];
|
|
8319
|
-
task
|
|
8528
|
+
task[_EFFECT_BACK_REF] = v[4];
|
|
8320
8529
|
task.$state$ = v[5];
|
|
8321
8530
|
break;
|
|
8322
8531
|
case TypeIds.Resource:
|
|
@@ -8339,12 +8548,9 @@
|
|
|
8339
8548
|
break;
|
|
8340
8549
|
case TypeIds.Store:
|
|
8341
8550
|
case TypeIds.StoreArray: {
|
|
8342
|
-
const [value, flags, effects
|
|
8551
|
+
const [value, flags, effects] = data;
|
|
8343
8552
|
const store = getOrCreateStore(value, flags, container);
|
|
8344
8553
|
const storeHandler = getStoreHandler(store);
|
|
8345
|
-
if (storeEffect) {
|
|
8346
|
-
effects[STORE_ARRAY_PROP] = storeEffect;
|
|
8347
|
-
}
|
|
8348
8554
|
storeHandler.$effects$ = effects;
|
|
8349
8555
|
target = store;
|
|
8350
8556
|
break;
|
|
@@ -8353,7 +8559,7 @@
|
|
|
8353
8559
|
const signal = target;
|
|
8354
8560
|
const d = data;
|
|
8355
8561
|
signal.$untrackedValue$ = d[0];
|
|
8356
|
-
signal.$effects$ = d.slice(1);
|
|
8562
|
+
signal.$effects$ = new Set(d.slice(1));
|
|
8357
8563
|
break;
|
|
8358
8564
|
}
|
|
8359
8565
|
case TypeIds.WrappedSignal: {
|
|
@@ -8361,10 +8567,10 @@
|
|
|
8361
8567
|
const d = data;
|
|
8362
8568
|
signal.$func$ = container.getSyncFn(d[0]);
|
|
8363
8569
|
signal.$args$ = d[1];
|
|
8364
|
-
signal
|
|
8570
|
+
signal[_EFFECT_BACK_REF] = d[2];
|
|
8365
8571
|
signal.$untrackedValue$ = d[3];
|
|
8366
8572
|
signal.$hostElement$ = d[4];
|
|
8367
|
-
signal.$effects$ = d.slice(5);
|
|
8573
|
+
signal.$effects$ = new Set(d.slice(5));
|
|
8368
8574
|
break;
|
|
8369
8575
|
}
|
|
8370
8576
|
case TypeIds.ComputedSignal: {
|
|
@@ -8484,6 +8690,7 @@
|
|
|
8484
8690
|
EMPTY_ARRAY,
|
|
8485
8691
|
EMPTY_OBJ,
|
|
8486
8692
|
NEEDS_COMPUTATION,
|
|
8693
|
+
STORE_ARRAY_PROP,
|
|
8487
8694
|
Slot,
|
|
8488
8695
|
Fragment,
|
|
8489
8696
|
NaN,
|
|
@@ -8564,6 +8771,8 @@
|
|
|
8564
8771
|
reject = rej;
|
|
8565
8772
|
});
|
|
8566
8773
|
resolvers.set(promise, [resolve, reject]);
|
|
8774
|
+
// Don't leave unhandled promise rejections
|
|
8775
|
+
promise.catch(() => { });
|
|
8567
8776
|
return promise;
|
|
8568
8777
|
case TypeIds.Uint8Array:
|
|
8569
8778
|
const encodedLength = value.length;
|
|
@@ -8573,12 +8782,9 @@
|
|
|
8573
8782
|
return new Uint8Array(decodedLength);
|
|
8574
8783
|
case TypeIds.PropsProxy:
|
|
8575
8784
|
return createPropsProxy(null, null);
|
|
8576
|
-
case TypeIds.RefVNode:
|
|
8577
8785
|
case TypeIds.VNode:
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
return vnodeOrDocument;
|
|
8581
|
-
}
|
|
8786
|
+
return retrieveVNodeOrDocument(container, value);
|
|
8787
|
+
case TypeIds.RefVNode:
|
|
8582
8788
|
const vNode = retrieveVNodeOrDocument(container, value);
|
|
8583
8789
|
if (vnode_isVNode(vNode)) {
|
|
8584
8790
|
return vnode_getNode(vNode);
|
|
@@ -8587,7 +8793,7 @@
|
|
|
8587
8793
|
throw qError(QError.serializeErrorExpectedVNode, [typeof vNode]);
|
|
8588
8794
|
}
|
|
8589
8795
|
case TypeIds.EffectData:
|
|
8590
|
-
return new
|
|
8796
|
+
return new SubscriptionData({});
|
|
8591
8797
|
default:
|
|
8592
8798
|
throw qError(QError.serializeErrorCannotAllocate, [typeId]);
|
|
8593
8799
|
}
|
|
@@ -8619,7 +8825,7 @@
|
|
|
8619
8825
|
assertDefined(backChannel, 'Missing QRL_RUNTIME_CHUNK');
|
|
8620
8826
|
qrlRef = backChannel.get(symbol);
|
|
8621
8827
|
}
|
|
8622
|
-
return createQRL(chunk, symbol, qrlRef, null, captureIds, null
|
|
8828
|
+
return createQRL(chunk, symbol, qrlRef, null, captureIds, null);
|
|
8623
8829
|
}
|
|
8624
8830
|
function inflateQRL(container, qrl) {
|
|
8625
8831
|
const captureIds = qrl.$capture$;
|
|
@@ -8737,7 +8943,7 @@
|
|
|
8737
8943
|
/** Visit an object, adding anything that will be serialized as to scan */
|
|
8738
8944
|
const visit = (obj) => {
|
|
8739
8945
|
if (typeof obj === 'function') {
|
|
8740
|
-
if (isQrl(obj)) {
|
|
8946
|
+
if (isQrl$1(obj)) {
|
|
8741
8947
|
if (obj.$captureRef$) {
|
|
8742
8948
|
discoveredValues.push(...obj.$captureRef$);
|
|
8743
8949
|
}
|
|
@@ -8756,6 +8962,7 @@
|
|
|
8756
8962
|
obj instanceof RegExp ||
|
|
8757
8963
|
obj instanceof Uint8Array ||
|
|
8758
8964
|
obj instanceof URLSearchParams ||
|
|
8965
|
+
vnode_isVNode(obj) ||
|
|
8759
8966
|
(typeof FormData !== 'undefined' && obj instanceof FormData) ||
|
|
8760
8967
|
// Ignore the no serialize objects
|
|
8761
8968
|
fastSkipSerialize(obj)) ;
|
|
@@ -8765,8 +8972,7 @@
|
|
|
8765
8972
|
else if (isStore(obj)) {
|
|
8766
8973
|
const target = getStoreTarget(obj);
|
|
8767
8974
|
const effects = getStoreHandler(obj).$effects$;
|
|
8768
|
-
|
|
8769
|
-
discoveredValues.push(target, effects, storeEffect);
|
|
8975
|
+
discoveredValues.push(target, effects);
|
|
8770
8976
|
for (const prop in target) {
|
|
8771
8977
|
const propValue = target[prop];
|
|
8772
8978
|
if (storeProxyMap.has(propValue)) {
|
|
@@ -8800,9 +9006,7 @@
|
|
|
8800
9006
|
}
|
|
8801
9007
|
// WrappedSignal uses syncQrl which has no captured refs
|
|
8802
9008
|
if (obj instanceof WrappedSignal) {
|
|
8803
|
-
|
|
8804
|
-
discoveredValues.push(...obj.$effectDependencies$);
|
|
8805
|
-
}
|
|
9009
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8806
9010
|
if (obj.$args$) {
|
|
8807
9011
|
discoveredValues.push(...obj.$args$);
|
|
8808
9012
|
}
|
|
@@ -8815,7 +9019,8 @@
|
|
|
8815
9019
|
}
|
|
8816
9020
|
}
|
|
8817
9021
|
else if (obj instanceof Task) {
|
|
8818
|
-
discoveredValues.push(obj.$el$, obj.$qrl$, obj.$state
|
|
9022
|
+
discoveredValues.push(obj.$el$, obj.$qrl$, obj.$state$);
|
|
9023
|
+
discoverEffectBackRefs(obj[_EFFECT_BACK_REF], discoveredValues);
|
|
8819
9024
|
}
|
|
8820
9025
|
else if (isSsrNode(obj)) {
|
|
8821
9026
|
discoverValuesForVNodeData(obj.vnodeData, discoveredValues);
|
|
@@ -8834,7 +9039,7 @@
|
|
|
8834
9039
|
else if (Array.isArray(obj)) {
|
|
8835
9040
|
discoveredValues.push(...obj);
|
|
8836
9041
|
}
|
|
8837
|
-
else if (isQrl(obj)) {
|
|
9042
|
+
else if (isQrl$1(obj)) {
|
|
8838
9043
|
obj.$captureRef$ && obj.$captureRef$.length && discoveredValues.push(...obj.$captureRef$);
|
|
8839
9044
|
}
|
|
8840
9045
|
else if (isPropsProxy(obj)) {
|
|
@@ -8850,7 +9055,7 @@
|
|
|
8850
9055
|
});
|
|
8851
9056
|
promises.push(obj);
|
|
8852
9057
|
}
|
|
8853
|
-
else if (obj instanceof
|
|
9058
|
+
else if (obj instanceof SubscriptionData) {
|
|
8854
9059
|
discoveredValues.push(obj.data);
|
|
8855
9060
|
}
|
|
8856
9061
|
else if (isObjectLiteral(obj)) {
|
|
@@ -8895,15 +9100,31 @@
|
|
|
8895
9100
|
for (const value of vnodeData) {
|
|
8896
9101
|
if (isSsrAttrs(value)) {
|
|
8897
9102
|
for (let i = 1; i < value.length; i += 2) {
|
|
8898
|
-
|
|
9103
|
+
const attrValue = value[i];
|
|
9104
|
+
if (typeof attrValue === 'string') {
|
|
8899
9105
|
continue;
|
|
8900
9106
|
}
|
|
8901
|
-
const attrValue = value[i];
|
|
8902
9107
|
discoveredValues.push(attrValue);
|
|
8903
9108
|
}
|
|
8904
9109
|
}
|
|
8905
9110
|
}
|
|
8906
9111
|
};
|
|
9112
|
+
const discoverEffectBackRefs = (effectsBackRefs, discoveredValues) => {
|
|
9113
|
+
if (effectsBackRefs) {
|
|
9114
|
+
// We need serialize effect subscriptions with back refs
|
|
9115
|
+
let hasBackRefs = false;
|
|
9116
|
+
for (const [, effect] of effectsBackRefs) {
|
|
9117
|
+
const backRefs = effect[EffectSubscriptionProp.BACK_REF];
|
|
9118
|
+
if (backRefs) {
|
|
9119
|
+
hasBackRefs = true;
|
|
9120
|
+
break;
|
|
9121
|
+
}
|
|
9122
|
+
}
|
|
9123
|
+
if (hasBackRefs) {
|
|
9124
|
+
discoveredValues.push(effectsBackRefs);
|
|
9125
|
+
}
|
|
9126
|
+
}
|
|
9127
|
+
};
|
|
8907
9128
|
const promiseResults = new WeakMap();
|
|
8908
9129
|
/**
|
|
8909
9130
|
* Format:
|
|
@@ -8975,7 +9196,7 @@
|
|
|
8975
9196
|
else if (value === Fragment) {
|
|
8976
9197
|
output(TypeIds.Constant, Constants.Fragment);
|
|
8977
9198
|
}
|
|
8978
|
-
else if (isQrl(value)) {
|
|
9199
|
+
else if (isQrl$1(value)) {
|
|
8979
9200
|
const qrl = qrlToString(serializationContext, value);
|
|
8980
9201
|
const id = serializationContext.$addRoot$(qrl);
|
|
8981
9202
|
output(TypeIds.QRL, id);
|
|
@@ -9050,6 +9271,9 @@
|
|
|
9050
9271
|
else if (value === NEEDS_COMPUTATION) {
|
|
9051
9272
|
output(TypeIds.Constant, Constants.NEEDS_COMPUTATION);
|
|
9052
9273
|
}
|
|
9274
|
+
else if (value === STORE_ARRAY_PROP) {
|
|
9275
|
+
output(TypeIds.Constant, Constants.STORE_ARRAY_PROP);
|
|
9276
|
+
}
|
|
9053
9277
|
else {
|
|
9054
9278
|
throw qError(QError.serializeErrorUnknownType, [typeof value]);
|
|
9055
9279
|
}
|
|
@@ -9086,7 +9310,7 @@
|
|
|
9086
9310
|
: 0;
|
|
9087
9311
|
output(TypeIds.PropsProxy, out);
|
|
9088
9312
|
}
|
|
9089
|
-
else if (value instanceof
|
|
9313
|
+
else if (value instanceof SubscriptionData) {
|
|
9090
9314
|
output(TypeIds.EffectData, [value.data.$scopedStyleIdPrefix$, value.data.$isConst$]);
|
|
9091
9315
|
}
|
|
9092
9316
|
else if (isStore(value)) {
|
|
@@ -9097,6 +9321,7 @@
|
|
|
9097
9321
|
if (!res) {
|
|
9098
9322
|
throw qError(QError.serializeErrorUnvisited, ['resource']);
|
|
9099
9323
|
}
|
|
9324
|
+
// TODO the effects include the resourcereturn which has duplicate data
|
|
9100
9325
|
output(TypeIds.Resource, [...res, getStoreHandler(value).$effects$]);
|
|
9101
9326
|
}
|
|
9102
9327
|
else {
|
|
@@ -9104,7 +9329,6 @@
|
|
|
9104
9329
|
const storeTarget = getStoreTarget(value);
|
|
9105
9330
|
const flags = storeHandler.$flags$;
|
|
9106
9331
|
const effects = storeHandler.$effects$;
|
|
9107
|
-
const storeEffect = effects?.[STORE_ARRAY_PROP] ?? null;
|
|
9108
9332
|
const innerStores = [];
|
|
9109
9333
|
for (const prop in storeTarget) {
|
|
9110
9334
|
const propValue = storeTarget[prop];
|
|
@@ -9114,7 +9338,7 @@
|
|
|
9114
9338
|
serializationContext.$addRoot$(innerStore);
|
|
9115
9339
|
}
|
|
9116
9340
|
}
|
|
9117
|
-
const out = [storeTarget, flags, effects,
|
|
9341
|
+
const out = [storeTarget, flags, effects, ...innerStores];
|
|
9118
9342
|
while (out[out.length - 1] == null) {
|
|
9119
9343
|
out.pop();
|
|
9120
9344
|
}
|
|
@@ -9153,7 +9377,7 @@
|
|
|
9153
9377
|
if (value instanceof WrappedSignal) {
|
|
9154
9378
|
output(TypeIds.WrappedSignal, [
|
|
9155
9379
|
...serializeWrappingFn(serializationContext, value),
|
|
9156
|
-
value
|
|
9380
|
+
filterEffectBackRefs(value[_EFFECT_BACK_REF]),
|
|
9157
9381
|
v,
|
|
9158
9382
|
value.$hostElement$,
|
|
9159
9383
|
...(value.$effects$ || []),
|
|
@@ -9260,7 +9484,7 @@
|
|
|
9260
9484
|
value.$flags$,
|
|
9261
9485
|
value.$index$,
|
|
9262
9486
|
value.$el$,
|
|
9263
|
-
value
|
|
9487
|
+
value[_EFFECT_BACK_REF],
|
|
9264
9488
|
value.$state$,
|
|
9265
9489
|
];
|
|
9266
9490
|
while (out[out.length - 1] == null) {
|
|
@@ -9283,12 +9507,27 @@
|
|
|
9283
9507
|
const out = btoa(buf).replace(/=+$/, '');
|
|
9284
9508
|
output(TypeIds.Uint8Array, out);
|
|
9285
9509
|
}
|
|
9510
|
+
else if (vnode_isVNode(value)) {
|
|
9511
|
+
output(TypeIds.Constant, Constants.Undefined);
|
|
9512
|
+
}
|
|
9286
9513
|
else {
|
|
9287
9514
|
throw qError(QError.serializeErrorUnknownType, [typeof value]);
|
|
9288
9515
|
}
|
|
9289
9516
|
};
|
|
9290
9517
|
writeValue(serializationContext.$roots$, -1);
|
|
9291
9518
|
}
|
|
9519
|
+
function filterEffectBackRefs(effectBackRef) {
|
|
9520
|
+
let effectBackRefToSerialize = null;
|
|
9521
|
+
if (effectBackRef) {
|
|
9522
|
+
for (const [effectProp, effect] of effectBackRef) {
|
|
9523
|
+
if (effect[EffectSubscriptionProp.BACK_REF]) {
|
|
9524
|
+
effectBackRefToSerialize ||= new Map();
|
|
9525
|
+
effectBackRefToSerialize.set(effectProp, effect);
|
|
9526
|
+
}
|
|
9527
|
+
}
|
|
9528
|
+
}
|
|
9529
|
+
return effectBackRefToSerialize;
|
|
9530
|
+
}
|
|
9292
9531
|
function serializeWrappingFn(serializationContext, value) {
|
|
9293
9532
|
// if value is an object then we need to wrap this in ()
|
|
9294
9533
|
if (value.$funcStr$ && value.$funcStr$[0] === '{') {
|
|
@@ -9301,15 +9540,12 @@
|
|
|
9301
9540
|
function qrlToString(serializationContext, value) {
|
|
9302
9541
|
let symbol = value.$symbol$;
|
|
9303
9542
|
let chunk = value.$chunk$;
|
|
9304
|
-
const refSymbol = value.$refSymbol$ ?? symbol;
|
|
9305
9543
|
const platform = getPlatform();
|
|
9306
9544
|
if (platform) {
|
|
9307
|
-
const result = platform.chunkForSymbol(
|
|
9545
|
+
const result = platform.chunkForSymbol(symbol, chunk, value.dev?.file);
|
|
9308
9546
|
if (result) {
|
|
9309
9547
|
chunk = result[1];
|
|
9310
|
-
|
|
9311
|
-
symbol = result[0];
|
|
9312
|
-
}
|
|
9548
|
+
symbol = result[0];
|
|
9313
9549
|
}
|
|
9314
9550
|
}
|
|
9315
9551
|
const isSync = isSyncQrl(value);
|
|
@@ -9486,9 +9722,9 @@
|
|
|
9486
9722
|
return ((typeof obj === 'object' &&
|
|
9487
9723
|
obj !== null &&
|
|
9488
9724
|
(obj instanceof Signal || obj instanceof Task || isJSXNode(obj))) ||
|
|
9489
|
-
isQrl(obj));
|
|
9725
|
+
isQrl$1(obj));
|
|
9490
9726
|
};
|
|
9491
|
-
const canSerialize = (value) => {
|
|
9727
|
+
const canSerialize = (value, seen = new WeakSet()) => {
|
|
9492
9728
|
if (value == null ||
|
|
9493
9729
|
typeof value === 'string' ||
|
|
9494
9730
|
typeof value === 'number' ||
|
|
@@ -9497,6 +9733,10 @@
|
|
|
9497
9733
|
return true;
|
|
9498
9734
|
}
|
|
9499
9735
|
else if (typeof value === 'object') {
|
|
9736
|
+
if (seen.has(value)) {
|
|
9737
|
+
return true;
|
|
9738
|
+
}
|
|
9739
|
+
seen.add(value);
|
|
9500
9740
|
const proto = Object.getPrototypeOf(value);
|
|
9501
9741
|
if (isStore(value)) {
|
|
9502
9742
|
value = getStoreTarget(value);
|
|
@@ -9505,7 +9745,7 @@
|
|
|
9505
9745
|
for (const key in value) {
|
|
9506
9746
|
// if the value is a props proxy, then sometimes we could create a component-level subscription,
|
|
9507
9747
|
// so we should call untrack here to avoid tracking the value
|
|
9508
|
-
if (!canSerialize(untrack(() => value[key]))) {
|
|
9748
|
+
if (!canSerialize(untrack(() => value[key]), seen)) {
|
|
9509
9749
|
return false;
|
|
9510
9750
|
}
|
|
9511
9751
|
}
|
|
@@ -9513,7 +9753,7 @@
|
|
|
9513
9753
|
}
|
|
9514
9754
|
else if (proto == Array.prototype) {
|
|
9515
9755
|
for (let i = 0; i < value.length; i++) {
|
|
9516
|
-
if (!canSerialize(value[i])) {
|
|
9756
|
+
if (!canSerialize(value[i], seen)) {
|
|
9517
9757
|
return false;
|
|
9518
9758
|
}
|
|
9519
9759
|
}
|
|
@@ -9563,7 +9803,7 @@
|
|
|
9563
9803
|
}
|
|
9564
9804
|
}
|
|
9565
9805
|
else if (typeof value === 'function') {
|
|
9566
|
-
if (isQrl(value) || isQwikComponent(value)) {
|
|
9806
|
+
if (isQrl$1(value) || isQwikComponent(value)) {
|
|
9567
9807
|
return true;
|
|
9568
9808
|
}
|
|
9569
9809
|
}
|
|
@@ -9616,20 +9856,21 @@
|
|
|
9616
9856
|
Constants[Constants["EMPTY_ARRAY"] = 5] = "EMPTY_ARRAY";
|
|
9617
9857
|
Constants[Constants["EMPTY_OBJ"] = 6] = "EMPTY_OBJ";
|
|
9618
9858
|
Constants[Constants["NEEDS_COMPUTATION"] = 7] = "NEEDS_COMPUTATION";
|
|
9619
|
-
Constants[Constants["
|
|
9620
|
-
Constants[Constants["
|
|
9621
|
-
Constants[Constants["
|
|
9622
|
-
Constants[Constants["
|
|
9623
|
-
Constants[Constants["
|
|
9624
|
-
Constants[Constants["
|
|
9859
|
+
Constants[Constants["STORE_ARRAY_PROP"] = 8] = "STORE_ARRAY_PROP";
|
|
9860
|
+
Constants[Constants["Slot"] = 9] = "Slot";
|
|
9861
|
+
Constants[Constants["Fragment"] = 10] = "Fragment";
|
|
9862
|
+
Constants[Constants["NaN"] = 11] = "NaN";
|
|
9863
|
+
Constants[Constants["PositiveInfinity"] = 12] = "PositiveInfinity";
|
|
9864
|
+
Constants[Constants["NegativeInfinity"] = 13] = "NegativeInfinity";
|
|
9865
|
+
Constants[Constants["MaxSafeInt"] = 14] = "MaxSafeInt";
|
|
9625
9866
|
// used for close fragment
|
|
9626
|
-
Constants[Constants["AlmostMaxSafeInt"] =
|
|
9627
|
-
Constants[Constants["MinSafeInt"] =
|
|
9867
|
+
Constants[Constants["AlmostMaxSafeInt"] = 15] = "AlmostMaxSafeInt";
|
|
9868
|
+
Constants[Constants["MinSafeInt"] = 16] = "MinSafeInt";
|
|
9628
9869
|
})(Constants || (Constants = {}));
|
|
9629
9870
|
|
|
9630
9871
|
/** @internal */
|
|
9631
9872
|
const verifySerializable = (value, preMessage) => {
|
|
9632
|
-
const seen = new
|
|
9873
|
+
const seen = new WeakSet();
|
|
9633
9874
|
return _verifySerializable(value, seen, '_', preMessage);
|
|
9634
9875
|
};
|
|
9635
9876
|
const _verifySerializable = (value, seen, ctx, preMessage) => {
|
|
@@ -9638,10 +9879,12 @@
|
|
|
9638
9879
|
return value;
|
|
9639
9880
|
}
|
|
9640
9881
|
if (shouldSerialize(unwrapped)) {
|
|
9641
|
-
if (
|
|
9642
|
-
|
|
9882
|
+
if (typeof unwrapped === 'object') {
|
|
9883
|
+
if (seen.has(unwrapped)) {
|
|
9884
|
+
return value;
|
|
9885
|
+
}
|
|
9886
|
+
seen.add(unwrapped);
|
|
9643
9887
|
}
|
|
9644
|
-
seen.add(unwrapped);
|
|
9645
9888
|
if (isSignal(unwrapped)) {
|
|
9646
9889
|
return value;
|
|
9647
9890
|
}
|
|
@@ -9745,16 +9988,7 @@
|
|
|
9745
9988
|
return input;
|
|
9746
9989
|
};
|
|
9747
9990
|
|
|
9748
|
-
const
|
|
9749
|
-
return typeof value === 'function' && typeof value.getSymbol === 'function';
|
|
9750
|
-
};
|
|
9751
|
-
// Make sure this value is same as value in `platform.ts`
|
|
9752
|
-
const SYNC_QRL = '<sync>';
|
|
9753
|
-
/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
|
|
9754
|
-
const isSyncQrl = (value) => {
|
|
9755
|
-
return isQrl(value) && value.$symbol$ == SYNC_QRL;
|
|
9756
|
-
};
|
|
9757
|
-
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef, refSymbol) => {
|
|
9991
|
+
const createQRL = (chunk, symbol, symbolRef, symbolFn, capture, captureRef) => {
|
|
9758
9992
|
if (qDev && qSerialize) {
|
|
9759
9993
|
if (captureRef) {
|
|
9760
9994
|
for (const item of captureRef) {
|
|
@@ -9776,9 +10010,14 @@
|
|
|
9776
10010
|
};
|
|
9777
10011
|
function bindFnToContext(currentCtx, beforeFn) {
|
|
9778
10012
|
// Note that we bind the current `this`
|
|
9779
|
-
|
|
9780
|
-
if (!
|
|
9781
|
-
|
|
10013
|
+
const bound = (...args) => {
|
|
10014
|
+
if (!qrl.resolved) {
|
|
10015
|
+
return qrl.resolve().then((fn) => {
|
|
10016
|
+
if (!isFunction(fn)) {
|
|
10017
|
+
throw qError(QError.qrlIsNotFunction);
|
|
10018
|
+
}
|
|
10019
|
+
return bound(...args);
|
|
10020
|
+
});
|
|
9782
10021
|
}
|
|
9783
10022
|
if (beforeFn && beforeFn() === false) {
|
|
9784
10023
|
return;
|
|
@@ -9791,13 +10030,14 @@
|
|
|
9791
10030
|
context.$qrl$ = qrl;
|
|
9792
10031
|
context.$event$ ||= this;
|
|
9793
10032
|
try {
|
|
9794
|
-
return invoke.call(this, context,
|
|
10033
|
+
return invoke.call(this, context, symbolRef, ...args);
|
|
9795
10034
|
}
|
|
9796
10035
|
finally {
|
|
9797
10036
|
context.$qrl$ = prevQrl;
|
|
9798
10037
|
context.$event$ = prevEvent;
|
|
9799
10038
|
}
|
|
9800
|
-
}
|
|
10039
|
+
};
|
|
10040
|
+
return bound;
|
|
9801
10041
|
}
|
|
9802
10042
|
const resolveLazy = (containerEl) => {
|
|
9803
10043
|
return symbolRef !== null ? symbolRef : resolve(containerEl);
|
|
@@ -9809,8 +10049,20 @@
|
|
|
9809
10049
|
}
|
|
9810
10050
|
return function (...args) {
|
|
9811
10051
|
let context = tryGetInvokeContext();
|
|
10052
|
+
// use the given qrl if it is the right one
|
|
9812
10053
|
if (context) {
|
|
9813
|
-
|
|
10054
|
+
// TODO check if this is necessary in production
|
|
10055
|
+
if (context.$qrl$?.$symbol$ === qrl.$symbol$) {
|
|
10056
|
+
return fn.apply(this, args);
|
|
10057
|
+
}
|
|
10058
|
+
const prevQrl = context.$qrl$;
|
|
10059
|
+
context.$qrl$ = qrl;
|
|
10060
|
+
try {
|
|
10061
|
+
return fn.apply(this, args);
|
|
10062
|
+
}
|
|
10063
|
+
finally {
|
|
10064
|
+
context.$qrl$ = prevQrl;
|
|
10065
|
+
}
|
|
9814
10066
|
}
|
|
9815
10067
|
context = newInvokeContext();
|
|
9816
10068
|
context.$qrl$ = qrl;
|
|
@@ -9838,11 +10090,11 @@
|
|
|
9838
10090
|
const start = now();
|
|
9839
10091
|
const ctx = tryGetInvokeContext();
|
|
9840
10092
|
if (symbolFn !== null) {
|
|
9841
|
-
symbolRef = symbolFn().then((module) => (qrl.resolved = symbolRef =
|
|
10093
|
+
symbolRef = symbolFn().then((module) => (qrl.resolved = wrapFn((symbolRef = module[symbol]))));
|
|
9842
10094
|
}
|
|
9843
10095
|
else {
|
|
9844
10096
|
const imported = getPlatform().importSymbol(_containerEl, chunk, symbol);
|
|
9845
|
-
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = symbolRef =
|
|
10097
|
+
symbolRef = maybeThen(imported, (ref) => (qrl.resolved = wrapFn((symbolRef = ref))));
|
|
9846
10098
|
}
|
|
9847
10099
|
if (typeof symbolRef === 'object' && isPromise(symbolRef)) {
|
|
9848
10100
|
symbolRef.then(() => emitUsedSymbol(symbol, ctx?.$element$, start), (err) => {
|
|
@@ -9865,10 +10117,9 @@
|
|
|
9865
10117
|
return invoke;
|
|
9866
10118
|
}
|
|
9867
10119
|
};
|
|
9868
|
-
const
|
|
9869
|
-
const hash = getSymbolHash(resolvedSymbol);
|
|
10120
|
+
const hash = getSymbolHash(symbol);
|
|
9870
10121
|
Object.assign(qrl, {
|
|
9871
|
-
getSymbol: () =>
|
|
10122
|
+
getSymbol: () => symbol,
|
|
9872
10123
|
getHash: () => hash,
|
|
9873
10124
|
getCaptured: () => captureRef,
|
|
9874
10125
|
resolve,
|
|
@@ -9876,7 +10127,6 @@
|
|
|
9876
10127
|
$setContainer$: setContainer,
|
|
9877
10128
|
$chunk$: chunk,
|
|
9878
10129
|
$symbol$: symbol,
|
|
9879
|
-
$refSymbol$: refSymbol,
|
|
9880
10130
|
$hash$: hash,
|
|
9881
10131
|
getFn: bindFnToContext,
|
|
9882
10132
|
$capture$: capture,
|
|
@@ -9885,8 +10135,8 @@
|
|
|
9885
10135
|
resolved: undefined,
|
|
9886
10136
|
});
|
|
9887
10137
|
if (symbolRef) {
|
|
9888
|
-
//
|
|
9889
|
-
symbolRef = maybeThen(symbolRef, (resolved) => (qrl.resolved = symbolRef =
|
|
10138
|
+
// Unwrap any promises
|
|
10139
|
+
symbolRef = maybeThen(symbolRef, (resolved) => (qrl.resolved = wrapFn((symbolRef = resolved))));
|
|
9890
10140
|
}
|
|
9891
10141
|
if (build.isDev) {
|
|
9892
10142
|
Object.defineProperty(qrl, '_devOnlySymbolRef', {
|
|
@@ -9900,20 +10150,6 @@
|
|
|
9900
10150
|
}
|
|
9901
10151
|
return qrl;
|
|
9902
10152
|
};
|
|
9903
|
-
const getSymbolHash = (symbolName) => {
|
|
9904
|
-
const index = symbolName.lastIndexOf('_');
|
|
9905
|
-
if (index > -1) {
|
|
9906
|
-
return symbolName.slice(index + 1);
|
|
9907
|
-
}
|
|
9908
|
-
return symbolName;
|
|
9909
|
-
};
|
|
9910
|
-
function assertQrl(qrl) {
|
|
9911
|
-
if (qDev) {
|
|
9912
|
-
if (!isQrl(qrl)) {
|
|
9913
|
-
throw new Error('Not a QRL');
|
|
9914
|
-
}
|
|
9915
|
-
}
|
|
9916
|
-
}
|
|
9917
10153
|
const EMITTED = /*#__PURE__*/ new Set();
|
|
9918
10154
|
const emitUsedSymbol = (symbol, element, reqTime) => {
|
|
9919
10155
|
if (!EMITTED.has(symbol)) {
|
|
@@ -10026,7 +10262,7 @@
|
|
|
10026
10262
|
if (!qRuntimeQrl && qDev) {
|
|
10027
10263
|
throw new Error('Optimizer should replace all usages of $() with some special syntax. If you need to create a QRL manually, use inlinedQrl() instead.');
|
|
10028
10264
|
}
|
|
10029
|
-
return createQRL(null, 's' + runtimeSymbolId++, expression, null, null, null
|
|
10265
|
+
return createQRL(null, 's' + runtimeSymbolId++, expression, null, null, null);
|
|
10030
10266
|
};
|
|
10031
10267
|
/** @private Use To avoid optimizer replacement */
|
|
10032
10268
|
const dollar = $;
|
|
@@ -10052,7 +10288,7 @@
|
|
|
10052
10288
|
// eslint-disable-next-line no-new-func
|
|
10053
10289
|
fn = new Function('return ' + fn.toString())();
|
|
10054
10290
|
}
|
|
10055
|
-
return createQRL('', SYNC_QRL, fn, null, null, null
|
|
10291
|
+
return createQRL('', SYNC_QRL, fn, null, null, null);
|
|
10056
10292
|
};
|
|
10057
10293
|
/**
|
|
10058
10294
|
* Extract function into a synchronously loadable QRL.
|
|
@@ -10069,7 +10305,7 @@
|
|
|
10069
10305
|
serializedFn = fn.toString();
|
|
10070
10306
|
}
|
|
10071
10307
|
fn.serialized = serializedFn;
|
|
10072
|
-
return createQRL('', SYNC_QRL, fn, null, null, null
|
|
10308
|
+
return createQRL('', SYNC_QRL, fn, null, null, null);
|
|
10073
10309
|
};
|
|
10074
10310
|
|
|
10075
10311
|
/** @internal */
|
|
@@ -10788,6 +11024,21 @@
|
|
|
10788
11024
|
iCtx.$container$.$scheduler$(ChoreType.VISIBLE, task);
|
|
10789
11025
|
}
|
|
10790
11026
|
};
|
|
11027
|
+
const useRunTask = (task, eagerness) => {
|
|
11028
|
+
if (eagerness === 'intersection-observer') {
|
|
11029
|
+
useOn('qvisible', getTaskHandlerQrl(task));
|
|
11030
|
+
}
|
|
11031
|
+
else if (eagerness === 'document-ready') {
|
|
11032
|
+
useOnDocument('qinit', getTaskHandlerQrl(task));
|
|
11033
|
+
}
|
|
11034
|
+
else if (eagerness === 'document-idle') {
|
|
11035
|
+
useOnDocument('qidle', getTaskHandlerQrl(task));
|
|
11036
|
+
}
|
|
11037
|
+
};
|
|
11038
|
+
const getTaskHandlerQrl = (task) => {
|
|
11039
|
+
const taskHandler = createQRL(null, '_task', scheduleTask, null, null, [task]);
|
|
11040
|
+
return taskHandler;
|
|
11041
|
+
};
|
|
10791
11042
|
|
|
10792
11043
|
// <docs markdown="../readme.md#useResource">
|
|
10793
11044
|
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
|
|
@@ -11124,8 +11375,9 @@
|
|
|
11124
11375
|
exports.Slot = Slot;
|
|
11125
11376
|
exports._CONST_PROPS = _CONST_PROPS;
|
|
11126
11377
|
exports._DomContainer = DomContainer;
|
|
11378
|
+
exports._EFFECT_BACK_REF = _EFFECT_BACK_REF;
|
|
11127
11379
|
exports._EMPTY_ARRAY = EMPTY_ARRAY;
|
|
11128
|
-
exports._EffectData =
|
|
11380
|
+
exports._EffectData = SubscriptionData;
|
|
11129
11381
|
exports._IMMUTABLE = _IMMUTABLE;
|
|
11130
11382
|
exports._SharedContainer = _SharedContainer;
|
|
11131
11383
|
exports._VAR_PROPS = _VAR_PROPS;
|
|
@@ -11135,7 +11387,6 @@
|
|
|
11135
11387
|
exports._getContextEvent = _getContextEvent;
|
|
11136
11388
|
exports._getDomContainer = getDomContainer;
|
|
11137
11389
|
exports._getQContainerElement = _getQContainerElement;
|
|
11138
|
-
exports._hW = _hW;
|
|
11139
11390
|
exports._isJSXNode = isJSXNode;
|
|
11140
11391
|
exports._isStringifiable = isStringifiable;
|
|
11141
11392
|
exports._jsxBranch = _jsxBranch;
|
|
@@ -11149,7 +11400,9 @@
|
|
|
11149
11400
|
exports._qrlSync = _qrlSync;
|
|
11150
11401
|
exports._regSymbol = _regSymbol;
|
|
11151
11402
|
exports._restProps = _restProps;
|
|
11403
|
+
exports._run = queueQRL;
|
|
11152
11404
|
exports._serialize = _serialize;
|
|
11405
|
+
exports._task = scheduleTask;
|
|
11153
11406
|
exports._verifySerializable = verifySerializable;
|
|
11154
11407
|
exports._waitUntilRendered = _waitUntilRendered;
|
|
11155
11408
|
exports._walkJSX = _walkJSX;
|