ripple 0.3.128 → 0.4.0
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/CHANGELOG.md +267 -0
- package/package.json +10 -4
- package/src/runtime/element.js +23 -6
- package/src/runtime/index-client.js +81 -41
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/blocks.js +173 -91
- package/src/runtime/internal/client/component.js +4 -30
- package/src/runtime/internal/client/composite.js +12 -13
- package/src/runtime/internal/client/constants.js +9 -0
- package/src/runtime/internal/client/context.js +12 -19
- package/src/runtime/internal/client/css.js +7 -9
- package/src/runtime/internal/client/events.js +178 -90
- package/src/runtime/internal/client/expression.js +45 -25
- package/src/runtime/internal/client/for.js +409 -129
- package/src/runtime/internal/client/head.js +10 -5
- package/src/runtime/internal/client/html.js +1 -0
- package/src/runtime/internal/client/hydration.js +152 -10
- package/src/runtime/internal/client/if.js +239 -50
- package/src/runtime/internal/client/index.js +4 -12
- package/src/runtime/internal/client/operations.js +40 -61
- package/src/runtime/internal/client/portal.js +163 -85
- package/src/runtime/internal/client/render.js +39 -39
- package/src/runtime/internal/client/rpc.js +3 -3
- package/src/runtime/internal/client/runtime.js +592 -433
- package/src/runtime/internal/client/selector.js +5 -2
- package/src/runtime/internal/client/template.js +133 -158
- package/src/runtime/internal/client/transport.js +38 -0
- package/src/runtime/internal/client/try.js +465 -426
- package/src/runtime/internal/client/types.d.ts +56 -23
- package/src/runtime/internal/client/utils.js +1 -3
- package/src/runtime/internal/server/dynamic.js +20 -21
- package/src/runtime/internal/server/index.js +325 -275
- package/src/runtime/internal/server/rpc.js +3 -2
- package/src/runtime/internal/server/transport.js +16 -0
- package/src/runtime/transport.js +21 -0
- package/tests/client/__snapshots__/for.test.tsrx.snap +0 -5
- package/tests/client/array/array.copy-within.test.tsrx +12 -12
- package/tests/client/array/array.derived.test.tsrx +46 -46
- package/tests/client/array/array.iteration.test.tsrx +10 -10
- package/tests/client/array/array.mutations.test.tsrx +20 -20
- package/tests/client/array/array.static.test.tsrx +11 -11
- package/tests/client/array/array.to-methods.test.tsrx +6 -6
- package/tests/client/async-suspend.test.tsrx +74 -75
- package/tests/client/basic/basic.attributes.test.tsrx +86 -83
- package/tests/client/basic/basic.collections.test.tsrx +12 -12
- package/tests/client/basic/basic.components.test.tsrx +99 -25
- package/tests/client/basic/basic.errors.test.tsrx +18 -18
- package/tests/client/basic/basic.events.test.tsrx +42 -42
- package/tests/client/basic/basic.get-set.test.tsrx +8 -8
- package/tests/client/basic/basic.reactivity.test.tsrx +73 -38
- package/tests/client/basic/basic.rendering.test.tsrx +25 -25
- package/tests/client/basic/basic.utilities.test.tsrx +3 -3
- package/tests/client/boundaries.test.tsrx +8 -8
- package/tests/client/boxed-locals.test.tsrx +452 -0
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +6 -6
- package/tests/client/compiler/compiler.assignments.test.tsrx +9 -73
- package/tests/client/compiler/compiler.attributes.test.tsrx +23 -23
- package/tests/client/compiler/compiler.basic.test.tsrx +15 -60
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +18 -43
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +2 -2
- package/tests/client/composite/__snapshots__/composite.render.test.tsrx.snap +0 -1
- package/tests/client/composite/composite.dynamic-components.test.tsrx +77 -6
- package/tests/client/composite/composite.props.test.tsrx +149 -12
- package/tests/client/composite/composite.reactivity.test.tsrx +51 -52
- package/tests/client/composite/composite.render.test.tsrx +26 -9
- package/tests/client/css/scoped-styles.test.tsrx +8 -8
- package/tests/client/date.test.tsrx +42 -42
- package/tests/client/derived-release.test.tsrx +370 -0
- package/tests/client/dynamic-elements.test.tsrx +45 -45
- package/tests/client/events.test.tsrx +97 -71
- package/tests/client/for-selector.test.tsrx +14 -14
- package/tests/client/for-single-root-items.test.tsrx +118 -3
- package/tests/client/for.test.tsrx +332 -31
- package/tests/client/head.test.tsrx +19 -19
- package/tests/client/html.test.tsrx +11 -9
- package/tests/client/if-block.test.tsrx +80 -0
- package/tests/client/map.test.tsrx +16 -16
- package/tests/client/media-query.test.tsrx +7 -7
- package/tests/client/portal.test.tsrx +224 -26
- package/tests/client/primitive-text.test.tsrx +50 -0
- package/tests/client/prop-kind-switch.test.tsrx +141 -0
- package/tests/client/ref.test.tsrx +17 -17
- package/tests/client/return.test.tsrx +26 -3
- package/tests/client/root-boundary.test.tsrx +42 -0
- package/tests/client/scoped-flush.test.tsrx +8 -8
- package/tests/client/set.test.tsrx +6 -6
- package/tests/client/svg.test.tsrx +11 -11
- package/tests/client/switch.test.tsrx +44 -44
- package/tests/client/track-async-hydration.test.tsrx +4 -4
- package/tests/client/try.test.tsrx +151 -83
- package/tests/client/tsx.test.tsrx +43 -40
- package/tests/client/url/url.derived.test.tsrx +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +2 -2
- package/tests/hydration/basic.test.js +74 -1
- package/tests/hydration/build-components.js +22 -1
- package/tests/hydration/compiled/client/basic.js +1142 -713
- package/tests/hydration/compiled/client/composite.js +151 -100
- package/tests/hydration/compiled/client/events.js +184 -171
- package/tests/hydration/compiled/client/for.js +1472 -1132
- package/tests/hydration/compiled/client/fragment-cursor.js +2341 -0
- package/tests/hydration/compiled/client/head.js +254 -201
- package/tests/hydration/compiled/client/hmr.js +54 -41
- package/tests/hydration/compiled/client/html-in-template.js +54 -39
- package/tests/hydration/compiled/client/html.js +1633 -1263
- package/tests/hydration/compiled/client/if-children.js +420 -270
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +363 -317
- package/tests/hydration/compiled/client/if.js +229 -219
- package/tests/hydration/compiled/client/mixed-control-flow.js +420 -404
- package/tests/hydration/compiled/client/nested-control-flow.js +1326 -1277
- package/tests/hydration/compiled/client/portal.js +87 -95
- package/tests/hydration/compiled/client/reactivity.js +135 -101
- package/tests/hydration/compiled/client/return.js +28 -19
- package/tests/hydration/compiled/client/streaming.js +390 -306
- package/tests/hydration/compiled/client/switch.js +258 -266
- package/tests/hydration/compiled/client/track-async-serialization.js +448 -280
- package/tests/hydration/compiled/client/try.js +173 -129
- package/tests/hydration/compiled/client/typed-text.js +71 -0
- package/tests/hydration/compiled/fixtures/money.js +10 -0
- package/tests/hydration/compiled/server/basic.js +123 -6
- package/tests/hydration/compiled/server/composite.js +16 -30
- package/tests/hydration/compiled/server/events.js +66 -18
- package/tests/hydration/compiled/server/for.js +117 -41
- package/tests/hydration/compiled/server/fragment-cursor.js +1687 -0
- package/tests/hydration/compiled/server/head.js +20 -20
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +70 -238
- package/tests/hydration/compiled/server/if-children.js +107 -15
- package/tests/hydration/compiled/server/if.js +11 -15
- package/tests/hydration/compiled/server/mixed-control-flow.js +8 -8
- package/tests/hydration/compiled/server/portal.js +14 -22
- package/tests/hydration/compiled/server/reactivity.js +14 -14
- package/tests/hydration/compiled/server/streaming.js +19 -19
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/compiled/server/track-async-serialization.js +150 -23
- package/tests/hydration/compiled/server/try.js +8 -8
- package/tests/hydration/compiled/server/typed-text.js +17 -0
- package/tests/hydration/components/basic.tsrx +44 -8
- package/tests/hydration/components/composite.tsrx +2 -2
- package/tests/hydration/components/events.tsrx +25 -25
- package/tests/hydration/components/for.tsrx +115 -67
- package/tests/hydration/components/fragment-cursor.tsrx +650 -0
- package/tests/hydration/components/head.tsrx +16 -16
- package/tests/hydration/components/hmr.tsrx +2 -2
- package/tests/hydration/components/html.tsrx +7 -7
- package/tests/hydration/components/if-children.tsrx +72 -25
- package/tests/hydration/components/if.tsrx +18 -18
- package/tests/hydration/components/mixed-control-flow.tsrx +11 -11
- package/tests/hydration/components/portal.tsrx +3 -3
- package/tests/hydration/components/reactivity.tsrx +16 -16
- package/tests/hydration/components/streaming.tsrx +20 -20
- package/tests/hydration/components/switch.tsrx +20 -20
- package/tests/hydration/components/text-types.ts +4 -0
- package/tests/hydration/components/track-async-serialization.tsrx +80 -26
- package/tests/hydration/components/try.tsrx +8 -8
- package/tests/hydration/components/typed-text.tsrx +22 -0
- package/tests/hydration/fixtures/money.js +10 -0
- package/tests/hydration/for.test.js +36 -0
- package/tests/hydration/fragment-cursor.test.js +111 -0
- package/tests/hydration/if-children.test.js +24 -0
- package/tests/hydration/streaming.test.js +19 -0
- package/tests/hydration/track-async-serialization.test.js +87 -2
- package/tests/hydration/tsconfig.text-types.json +10 -0
- package/tests/hydration/typed-text.test.js +34 -0
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +42 -42
- package/tests/server/basic.components.test.tsrx +64 -8
- package/tests/server/basic.test.tsrx +34 -32
- package/tests/server/compiler.test.tsrx +1 -70
- package/tests/server/composite.props.test.tsrx +6 -6
- package/tests/server/dynamic-elements.test.tsrx +31 -8
- package/tests/server/for.test.tsrx +94 -0
- package/tests/server/head.test.tsrx +11 -11
- package/tests/server/scoped-styles.test.tsrx +2 -2
- package/tests/server/streaming-ssr.test.tsrx +48 -43
- package/tests/server/track-async-serialization.test.tsrx +204 -21
- package/tests/server/try.test.tsrx +48 -48
- package/tests/types/transport.ts +40 -0
- package/tests/utils/vite-plugin-config.test.js +23 -0
- package/types/index.d.ts +48 -7
- package/types/server.d.ts +3 -0
- package/types/transport.d.ts +15 -0
- package/src/runtime/internal/client/switch.js +0 -113
- package/src/utils/errors.js +0 -13
- package/tests/client/lazy-array.test.tsrx +0 -31
- package/tests/client/lazy-destructuring.test.tsrx +0 -438
- package/tests/client/tracked-index-access.test.tsrx +0 -113
- package/tests/server/lazy-destructuring.test.tsrx +0 -595
- package/tests/server/tracked-index-access.test.tsrx +0 -76
|
@@ -53,9 +53,9 @@ import {
|
|
|
53
53
|
} from '../client/constants.js';
|
|
54
54
|
import { DEV } from 'esm-env';
|
|
55
55
|
import { is_ripple_object } from '../client/utils.js';
|
|
56
|
-
import {
|
|
56
|
+
import { is_array } from '@tsrx/core/runtime/language-helpers';
|
|
57
57
|
import {
|
|
58
|
-
escape,
|
|
58
|
+
escape as escape_html,
|
|
59
59
|
escape_script,
|
|
60
60
|
is_boolean_attribute,
|
|
61
61
|
normalize_css_property_name,
|
|
@@ -79,10 +79,6 @@ import {
|
|
|
79
79
|
is_tag_valid_with_ancestor,
|
|
80
80
|
} from '../../../html-tree-validation.js';
|
|
81
81
|
import { get_async_track_result } from '../../../utils/async.js';
|
|
82
|
-
import {
|
|
83
|
-
throw_tracked_index_reference_error,
|
|
84
|
-
throw_tracked_index_value_error,
|
|
85
|
-
} from '../../../utils/errors.js';
|
|
86
82
|
import { get_track_async_script_id } from '../../../utils/track-async-serialization.js';
|
|
87
83
|
import * as devalue from 'devalue';
|
|
88
84
|
import {
|
|
@@ -94,12 +90,10 @@ import {
|
|
|
94
90
|
} from './blocks.js';
|
|
95
91
|
import { COMPONENT_BLOCK, ROOT_BLOCK, TRY_BLOCK } from './constants.js';
|
|
96
92
|
|
|
97
|
-
export { escape };
|
|
98
93
|
export { register_component_css as register_css } from './css-registry.js';
|
|
99
94
|
export { simple_hash, strong_hash } from '@tsrx/core/runtime/hash';
|
|
100
95
|
export { context } from './context.js';
|
|
101
96
|
export { try_block, component_block, regular_block } from './blocks.js';
|
|
102
|
-
export { array_slice };
|
|
103
97
|
export { is_tsrx_element, tsrx_element, normalize_children };
|
|
104
98
|
export { create_ref_prop };
|
|
105
99
|
|
|
@@ -181,6 +175,11 @@ export function render_expression(value) {
|
|
|
181
175
|
* @returns {void}
|
|
182
176
|
*/
|
|
183
177
|
export function render_component(fn, props) {
|
|
178
|
+
// An optional component (an undefined prop, an import that resolved to
|
|
179
|
+
// nothing) renders nothing; any other non-function is a programming error.
|
|
180
|
+
if (fn == null) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
184
183
|
if (typeof fn !== 'function' || is_tsrx_element(fn)) {
|
|
185
184
|
throw_invalid_component_type(fn);
|
|
186
185
|
}
|
|
@@ -283,7 +282,8 @@ let inside_async_track = false;
|
|
|
283
282
|
/** @type {ElementContext | undefined} */
|
|
284
283
|
let current_element;
|
|
285
284
|
/** @type {Set<string>} */
|
|
286
|
-
|
|
285
|
+
/** @type {Set<string> | null} */
|
|
286
|
+
let seen_warnings = null;
|
|
287
287
|
|
|
288
288
|
/**
|
|
289
289
|
* @returns {void}
|
|
@@ -294,7 +294,7 @@ export function reset_state() {
|
|
|
294
294
|
active_dependency = null;
|
|
295
295
|
inside_async_track = false;
|
|
296
296
|
tracking = false;
|
|
297
|
-
seen_warnings =
|
|
297
|
+
seen_warnings = null;
|
|
298
298
|
current_element = undefined;
|
|
299
299
|
}
|
|
300
300
|
|
|
@@ -461,6 +461,18 @@ function run_derived(computed) {
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
/**
|
|
465
|
+
* Runs `fn` after the current task's microtasks have drained, so work
|
|
466
|
+
* completing in the same task can be batched into it.
|
|
467
|
+
* @type {(fn: () => void) => void}
|
|
468
|
+
*/
|
|
469
|
+
const defer =
|
|
470
|
+
typeof setImmediate === 'function'
|
|
471
|
+
? setImmediate
|
|
472
|
+
: (fn) => {
|
|
473
|
+
setTimeout(fn, 0);
|
|
474
|
+
};
|
|
475
|
+
|
|
464
476
|
/**
|
|
465
477
|
* `<div translate={false}>` should be rendered as `<div translate="no">` and _not_
|
|
466
478
|
* `<div translate="false">`, which is equivalent to `<div translate="yes">`. There
|
|
@@ -481,8 +493,8 @@ export class Output {
|
|
|
481
493
|
#head = [];
|
|
482
494
|
/** @type {NestedArray<string>} */
|
|
483
495
|
#body = [];
|
|
484
|
-
/** @type {Set<string>} */
|
|
485
|
-
#css =
|
|
496
|
+
/** @type {Set<string> | null} root only */
|
|
497
|
+
#css = null;
|
|
486
498
|
/** @type {null | Output} */
|
|
487
499
|
#parent = null;
|
|
488
500
|
/** @type {StreamSink | null} */
|
|
@@ -501,8 +513,8 @@ export class Output {
|
|
|
501
513
|
#promise_reject = null;
|
|
502
514
|
#is_root = false;
|
|
503
515
|
#sync_run = false;
|
|
504
|
-
/** @type {Set<RegisteredAsyncOperation>} */
|
|
505
|
-
#async_operations =
|
|
516
|
+
/** @type {Set<RegisteredAsyncOperation> | null} created by the first registration */
|
|
517
|
+
#async_operations = null;
|
|
506
518
|
/** @type {null | 'head'} */
|
|
507
519
|
target = null;
|
|
508
520
|
/** @type {null | FlushUnit} */
|
|
@@ -513,13 +525,14 @@ export class Output {
|
|
|
513
525
|
#head_redirect = null;
|
|
514
526
|
// streaming state, only used on the root instance
|
|
515
527
|
#next_unit_id = 1;
|
|
516
|
-
/** @type {FlushUnit[]} */
|
|
517
|
-
#units =
|
|
518
|
-
/** @type {WeakMap<NestedArray<string>, FlushUnit>} */
|
|
519
|
-
#unit_slots =
|
|
520
|
-
/** @type {Set<string>} */
|
|
521
|
-
#sent_css =
|
|
528
|
+
/** @type {FlushUnit[] | null} */
|
|
529
|
+
#units = null;
|
|
530
|
+
/** @type {WeakMap<NestedArray<string>, FlushUnit> | null} */
|
|
531
|
+
#unit_slots = null;
|
|
532
|
+
/** @type {Set<string> | null} */
|
|
533
|
+
#sent_css = null;
|
|
522
534
|
#shell_flushed = false;
|
|
535
|
+
#flush_scheduled = false;
|
|
523
536
|
|
|
524
537
|
get root() {
|
|
525
538
|
return this.#root;
|
|
@@ -534,7 +547,7 @@ export class Output {
|
|
|
534
547
|
}
|
|
535
548
|
|
|
536
549
|
get css() {
|
|
537
|
-
return this.#css;
|
|
550
|
+
return /** @type {Set<string>} */ (this.#root.#css);
|
|
538
551
|
}
|
|
539
552
|
|
|
540
553
|
get promise() {
|
|
@@ -552,6 +565,10 @@ export class Output {
|
|
|
552
565
|
if (!parent) {
|
|
553
566
|
this.#root = this;
|
|
554
567
|
this.#is_root = true;
|
|
568
|
+
this.#css = new Set();
|
|
569
|
+
this.#units = [];
|
|
570
|
+
this.#unit_slots = new WeakMap();
|
|
571
|
+
this.#sent_css = new Set();
|
|
555
572
|
this.#promise = new Promise((resolve, reject) => {
|
|
556
573
|
this.#promise_resolve = resolve;
|
|
557
574
|
this.#promise_reject = reject;
|
|
@@ -654,7 +671,9 @@ export class Output {
|
|
|
654
671
|
}
|
|
655
672
|
this.#head.length = 0;
|
|
656
673
|
this.#body.length = 0;
|
|
657
|
-
this.#
|
|
674
|
+
if (this.#is_root) {
|
|
675
|
+
/** @type {Set<string>} */ (this.#css).clear();
|
|
676
|
+
}
|
|
658
677
|
}
|
|
659
678
|
|
|
660
679
|
/**
|
|
@@ -670,8 +689,9 @@ export class Output {
|
|
|
670
689
|
return;
|
|
671
690
|
}
|
|
672
691
|
if (root.#shell_flushed) {
|
|
673
|
-
|
|
674
|
-
|
|
692
|
+
var sent_css = /** @type {Set<string>} */ (root.#sent_css);
|
|
693
|
+
if (!sent_css.has(hash)) {
|
|
694
|
+
sent_css.add(hash);
|
|
675
695
|
var css_text = get_css_text(new Set([hash]));
|
|
676
696
|
if (css_text) {
|
|
677
697
|
root.#streamOutput.push('<style data-ripple-ssr>' + css_text + '</style>');
|
|
@@ -680,7 +700,7 @@ export class Output {
|
|
|
680
700
|
return;
|
|
681
701
|
}
|
|
682
702
|
}
|
|
683
|
-
root.#css.add(hash);
|
|
703
|
+
/** @type {Set<string>} */ (root.#css).add(hash);
|
|
684
704
|
}
|
|
685
705
|
|
|
686
706
|
/**
|
|
@@ -730,7 +750,7 @@ export class Output {
|
|
|
730
750
|
* @return {void}
|
|
731
751
|
*/
|
|
732
752
|
registerAsync(operation) {
|
|
733
|
-
this.#async_operations.add(operation);
|
|
753
|
+
(this.#async_operations ??= new Set()).add(operation);
|
|
734
754
|
this.#root._incrementPending();
|
|
735
755
|
}
|
|
736
756
|
|
|
@@ -739,19 +759,22 @@ export class Output {
|
|
|
739
759
|
* @returns {void}
|
|
740
760
|
*/
|
|
741
761
|
resolveAsync(operation) {
|
|
742
|
-
this.#async_operations
|
|
762
|
+
var operations = /** @type {Set<RegisteredAsyncOperation>} */ (this.#async_operations);
|
|
763
|
+
operations.delete(operation);
|
|
743
764
|
this.#root._decrementPending();
|
|
744
765
|
var unit = this.unit;
|
|
745
|
-
if (unit !== null && !unit.flushed && !unit.settled &&
|
|
766
|
+
if (unit !== null && !unit.flushed && !unit.settled && operations.size === 0) {
|
|
746
767
|
unit.settled = true;
|
|
747
768
|
this.#root._maybeFlushUnit(unit);
|
|
748
769
|
}
|
|
749
770
|
}
|
|
750
771
|
|
|
751
772
|
cancelAsyncOperations() {
|
|
752
|
-
|
|
773
|
+
var operations = this.#async_operations;
|
|
774
|
+
if (operations === null) return;
|
|
775
|
+
for (const operation of operations) {
|
|
753
776
|
operation.cancel();
|
|
754
|
-
|
|
777
|
+
operations.delete(operation);
|
|
755
778
|
this.clear();
|
|
756
779
|
this.#root._decrementPending();
|
|
757
780
|
}
|
|
@@ -761,7 +784,8 @@ export class Output {
|
|
|
761
784
|
* @returns {boolean}
|
|
762
785
|
*/
|
|
763
786
|
hasPendingAsyncOperations() {
|
|
764
|
-
|
|
787
|
+
var operations = this.#async_operations;
|
|
788
|
+
return operations !== null && operations.size > 0;
|
|
765
789
|
}
|
|
766
790
|
|
|
767
791
|
/**
|
|
@@ -804,8 +828,8 @@ export class Output {
|
|
|
804
828
|
error: null,
|
|
805
829
|
};
|
|
806
830
|
this.unit = unit;
|
|
807
|
-
root.#unit_slots.set(this.#body, unit);
|
|
808
|
-
root.#units.push(unit);
|
|
831
|
+
/** @type {WeakMap<NestedArray<string>, FlushUnit>} */ (root.#unit_slots).set(this.#body, unit);
|
|
832
|
+
/** @type {FlushUnit[]} */ (root.#units).push(unit);
|
|
809
833
|
return unit;
|
|
810
834
|
}
|
|
811
835
|
|
|
@@ -840,7 +864,9 @@ export class Output {
|
|
|
840
864
|
out += item;
|
|
841
865
|
continue;
|
|
842
866
|
}
|
|
843
|
-
var unit = this.#unit_slots.get(
|
|
867
|
+
var unit = /** @type {WeakMap<NestedArray<string>, FlushUnit>} */ (this.#unit_slots).get(
|
|
868
|
+
item,
|
|
869
|
+
);
|
|
844
870
|
if (unit !== undefined && !unit.flushed) {
|
|
845
871
|
if (unit.settled && !unit.errored) {
|
|
846
872
|
out += this.#collect_unit(unit, chunk);
|
|
@@ -877,9 +903,10 @@ export class Output {
|
|
|
877
903
|
#chunk_css(hashes) {
|
|
878
904
|
/** @type {Set<string>} */
|
|
879
905
|
var fresh = new Set();
|
|
906
|
+
var sent_css = /** @type {Set<string>} */ (this.#sent_css);
|
|
880
907
|
for (var hash of hashes) {
|
|
881
|
-
if (!
|
|
882
|
-
|
|
908
|
+
if (!sent_css.has(hash)) {
|
|
909
|
+
sent_css.add(hash);
|
|
883
910
|
fresh.add(hash);
|
|
884
911
|
}
|
|
885
912
|
}
|
|
@@ -901,33 +928,42 @@ export class Output {
|
|
|
901
928
|
if (this.#streamOutput === null || this.#stream_finished || !this.#shell_flushed) {
|
|
902
929
|
return;
|
|
903
930
|
}
|
|
904
|
-
if (!unit.settled || unit.flushed || !unit.slot_sent) {
|
|
931
|
+
if (!unit.settled || unit.flushed || !unit.slot_sent || this.#flush_scheduled) {
|
|
905
932
|
return;
|
|
906
933
|
}
|
|
907
|
-
|
|
908
|
-
|
|
934
|
+
// Units settling in the same macrotask (data arriving together, a
|
|
935
|
+
// batch of promises resolved by one timer or I/O callback) travel in
|
|
936
|
+
// one chunk: the flush runs once the current task's microtasks have
|
|
937
|
+
// drained. Closing the stream flushes whatever is still queued first.
|
|
938
|
+
this.#flush_scheduled = true;
|
|
939
|
+
defer(() => this.#flush_settled());
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
#flush_settled() {
|
|
943
|
+
this.#flush_scheduled = false;
|
|
944
|
+
if (!this.#stream_finished) {
|
|
945
|
+
this.#sweep_units();
|
|
946
|
+
}
|
|
909
947
|
}
|
|
910
948
|
|
|
911
949
|
/**
|
|
912
950
|
* @param {FlushUnit} unit
|
|
913
|
-
* @returns {
|
|
951
|
+
* @returns {string}
|
|
914
952
|
*/
|
|
915
|
-
#
|
|
916
|
-
var sink = /** @type {StreamSink} */ (this.#streamOutput);
|
|
953
|
+
#unit_chunk(unit) {
|
|
917
954
|
if (unit.errored) {
|
|
918
955
|
unit.flushed = true;
|
|
919
|
-
|
|
956
|
+
return (
|
|
920
957
|
'<script id="' +
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
958
|
+
STREAM_ERROR_SCRIPT_PREFIX +
|
|
959
|
+
unit.id +
|
|
960
|
+
'" type="application/json">' +
|
|
961
|
+
escape_inline_script(JSON.stringify({ message: unit.error })) +
|
|
962
|
+
'</script>' +
|
|
963
|
+
'<script>__RIPPLE_S__(' +
|
|
964
|
+
unit.id +
|
|
965
|
+
',1)</script>'
|
|
929
966
|
);
|
|
930
|
-
return;
|
|
931
967
|
}
|
|
932
968
|
/** @type {StreamChunk} */
|
|
933
969
|
var chunk = { css: new Set(), scripts: [], head: '' };
|
|
@@ -939,28 +975,32 @@ export class Output {
|
|
|
939
975
|
out += chunk.scripts.join('');
|
|
940
976
|
out += '<template ' + STREAM_CHUNK_ATTR + '="' + unit.id + '">' + html + '</template>';
|
|
941
977
|
out += '<script>__RIPPLE_S__(' + unit.id + ')</script>';
|
|
942
|
-
|
|
978
|
+
return out;
|
|
943
979
|
}
|
|
944
980
|
|
|
945
981
|
/**
|
|
946
|
-
*
|
|
947
|
-
* settled. Flushing a parent
|
|
948
|
-
* which can make further units eligible — loop until a fixpoint.
|
|
982
|
+
* Streams every unit whose slot has been sent and whose async work has
|
|
983
|
+
* settled, as one chunk. Flushing a parent marks nested unsettled slots
|
|
984
|
+
* as sent, which can make further units eligible — loop until a fixpoint.
|
|
949
985
|
* @returns {void}
|
|
950
986
|
*/
|
|
951
987
|
#sweep_units() {
|
|
952
|
-
var units = this.#units;
|
|
988
|
+
var units = /** @type {FlushUnit[]} */ (this.#units);
|
|
989
|
+
var out = '';
|
|
953
990
|
var progressed = true;
|
|
954
991
|
while (progressed) {
|
|
955
992
|
progressed = false;
|
|
956
993
|
for (var i = 0; i < units.length; i++) {
|
|
957
994
|
var unit = units[i];
|
|
958
995
|
if (unit.settled && !unit.flushed && unit.slot_sent) {
|
|
959
|
-
this.#
|
|
996
|
+
out += this.#unit_chunk(unit);
|
|
960
997
|
progressed = true;
|
|
961
998
|
}
|
|
962
999
|
}
|
|
963
1000
|
}
|
|
1001
|
+
if (out !== '') {
|
|
1002
|
+
/** @type {StreamSink} */ (this.#streamOutput).push(out);
|
|
1003
|
+
}
|
|
964
1004
|
}
|
|
965
1005
|
|
|
966
1006
|
/**
|
|
@@ -984,7 +1024,7 @@ export class Output {
|
|
|
984
1024
|
// the root boundary's slot is the shell body itself
|
|
985
1025
|
this.unit.slot_sent = true;
|
|
986
1026
|
}
|
|
987
|
-
for (var hash of this.#css) {
|
|
1027
|
+
for (var hash of /** @type {Set<string>} */ (this.#css)) {
|
|
988
1028
|
chunk.css.add(hash);
|
|
989
1029
|
}
|
|
990
1030
|
var template = this.#stream_template;
|
|
@@ -1003,8 +1043,9 @@ export class Output {
|
|
|
1003
1043
|
out += BLOCK_OPEN + body + BLOCK_CLOSE;
|
|
1004
1044
|
}
|
|
1005
1045
|
var has_open_units = false;
|
|
1006
|
-
|
|
1007
|
-
|
|
1046
|
+
var units = /** @type {FlushUnit[]} */ (this.#units);
|
|
1047
|
+
for (var i = 0; i < units.length; i++) {
|
|
1048
|
+
if (!units[i].flushed) {
|
|
1008
1049
|
has_open_units = true;
|
|
1009
1050
|
break;
|
|
1010
1051
|
}
|
|
@@ -1072,6 +1113,7 @@ export class Output {
|
|
|
1072
1113
|
_closeStream() {
|
|
1073
1114
|
if (this.#is_root) {
|
|
1074
1115
|
if (this.#streamOutput && this.#stream_started && !this.#stream_finished) {
|
|
1116
|
+
this.#sweep_units();
|
|
1075
1117
|
this.#stream_finished = true;
|
|
1076
1118
|
if (this.#stream_template !== null && this.#stream_template.after !== '') {
|
|
1077
1119
|
this.#streamOutput.push(this.#stream_template.after);
|
|
@@ -1113,17 +1155,28 @@ export class Output {
|
|
|
1113
1155
|
}
|
|
1114
1156
|
}
|
|
1115
1157
|
|
|
1158
|
+
/**
|
|
1159
|
+
* Concatenates a buffer tree (see `Output`) into one string. A hand-rolled
|
|
1160
|
+
* walk is far cheaper than `flat(Infinity).join('')` on a cold isolate, where
|
|
1161
|
+
* a render's cost is dominated by unoptimized code.
|
|
1162
|
+
* @param {NestedArray<string>} tree
|
|
1163
|
+
* @returns {string}
|
|
1164
|
+
*/
|
|
1165
|
+
function flatten_buffer(tree) {
|
|
1166
|
+
var out = '';
|
|
1167
|
+
for (var i = 0; i < tree.length; i++) {
|
|
1168
|
+
var item = tree[i];
|
|
1169
|
+
out += typeof item === 'string' ? item : flatten_buffer(item);
|
|
1170
|
+
}
|
|
1171
|
+
return out;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1116
1174
|
/**
|
|
1117
1175
|
* @param {RenderComponent} component
|
|
1118
|
-
* @param {BaseRenderOptions} [
|
|
1176
|
+
* @param {BaseRenderOptions} [options]
|
|
1119
1177
|
* @returns {Promise<RenderResult | RenderStreamResult>}
|
|
1120
1178
|
*/
|
|
1121
|
-
export async function render(component,
|
|
1122
|
-
/** @type {BaseRenderOptions} */
|
|
1123
|
-
var options = {
|
|
1124
|
-
...(passed_in_options.stream ? { closeStream: true } : {}),
|
|
1125
|
-
...passed_in_options,
|
|
1126
|
-
};
|
|
1179
|
+
export async function render(component, options = {}) {
|
|
1127
1180
|
/** @type {Error | null } */
|
|
1128
1181
|
var top_level_error = null;
|
|
1129
1182
|
var head = '';
|
|
@@ -1182,7 +1235,7 @@ export async function render(component, passed_in_options = {}) {
|
|
|
1182
1235
|
await output.promise;
|
|
1183
1236
|
reset_state();
|
|
1184
1237
|
|
|
1185
|
-
if (output.isStreamMode() && options.closeStream) {
|
|
1238
|
+
if (output.isStreamMode() && ('closeStream' in options ? options.closeStream : true)) {
|
|
1186
1239
|
output._closeStream();
|
|
1187
1240
|
}
|
|
1188
1241
|
|
|
@@ -1199,12 +1252,40 @@ export async function render(component, passed_in_options = {}) {
|
|
|
1199
1252
|
* @returns {void}
|
|
1200
1253
|
*/
|
|
1201
1254
|
function sync_buffers_to_string(output) {
|
|
1202
|
-
head =
|
|
1203
|
-
body = BLOCK_OPEN +
|
|
1255
|
+
head = flatten_buffer(output.head);
|
|
1256
|
+
body = BLOCK_OPEN + flatten_buffer(output.body) + BLOCK_CLOSE;
|
|
1204
1257
|
css = output.css;
|
|
1205
1258
|
}
|
|
1206
1259
|
}
|
|
1207
1260
|
|
|
1261
|
+
var CONTENT_SPECIAL = /[&<]/;
|
|
1262
|
+
var ATTR_SPECIAL = /[&"<]/;
|
|
1263
|
+
var SCRIPT_SPECIAL = /[<>]/;
|
|
1264
|
+
|
|
1265
|
+
/**
|
|
1266
|
+
* Escapes the characters that could end an inline `<script>` early. JSON
|
|
1267
|
+
* payloads rarely contain `<` or `>`, so one test replaces two global
|
|
1268
|
+
* replace scans in the common case.
|
|
1269
|
+
* @param {string} str
|
|
1270
|
+
* @returns {string}
|
|
1271
|
+
*/
|
|
1272
|
+
function escape_inline_script(str) {
|
|
1273
|
+
return SCRIPT_SPECIAL.test(str) ? escape_script(str) : str;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Escapes text or attribute content. Strings without a character to escape
|
|
1278
|
+
* (the common case) return as they are after a single regex test; anything
|
|
1279
|
+
* else goes through the general escaper.
|
|
1280
|
+
* @param {unknown} value
|
|
1281
|
+
* @param {boolean} [is_attr]
|
|
1282
|
+
* @returns {string}
|
|
1283
|
+
*/
|
|
1284
|
+
export function escape(value, is_attr) {
|
|
1285
|
+
var str = typeof value === 'string' ? value : value == null ? '' : String(value);
|
|
1286
|
+
return (is_attr ? ATTR_SPECIAL : CONTENT_SPECIAL).test(str) ? escape_html(str, is_attr) : str;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1208
1289
|
/**
|
|
1209
1290
|
* @returns {void}
|
|
1210
1291
|
*/
|
|
@@ -1213,7 +1294,7 @@ export function push_component() {
|
|
|
1213
1294
|
c: null,
|
|
1214
1295
|
p: active_component,
|
|
1215
1296
|
};
|
|
1216
|
-
active_block = component_block(
|
|
1297
|
+
active_block = component_block(noop);
|
|
1217
1298
|
}
|
|
1218
1299
|
|
|
1219
1300
|
/**
|
|
@@ -1268,7 +1349,11 @@ function print_nesting_error(message) {
|
|
|
1268
1349
|
`node_invalid_placement_ssr: ${message}\n\n` +
|
|
1269
1350
|
'This can cause content to shift around as the browser repairs the HTML, and will likely result in a hydration mismatch.';
|
|
1270
1351
|
|
|
1271
|
-
if (seen_warnings
|
|
1352
|
+
if (seen_warnings === null) {
|
|
1353
|
+
seen_warnings = new Set();
|
|
1354
|
+
} else if (seen_warnings.has(message)) {
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1272
1357
|
seen_warnings.add(message);
|
|
1273
1358
|
|
|
1274
1359
|
// eslint-disable-next-line no-console
|
|
@@ -1404,60 +1489,6 @@ export function get_derived(tracked) {
|
|
|
1404
1489
|
return g ? g(tracked.v) : tracked.v;
|
|
1405
1490
|
}
|
|
1406
1491
|
|
|
1407
|
-
/**
|
|
1408
|
-
* @param {any} lazy
|
|
1409
|
-
* @param {number} [index]
|
|
1410
|
-
* @returns {any}
|
|
1411
|
-
*/
|
|
1412
|
-
export function lazy_array_get(lazy, index = 0) {
|
|
1413
|
-
if (is_array(lazy)) {
|
|
1414
|
-
return lazy[index];
|
|
1415
|
-
}
|
|
1416
|
-
var flags = lazy.f;
|
|
1417
|
-
if (flags === TRACKED) {
|
|
1418
|
-
return index === 0
|
|
1419
|
-
? get_tracked(/** @type {Tracked} */ (lazy))
|
|
1420
|
-
: index === 1
|
|
1421
|
-
? lazy
|
|
1422
|
-
: undefined;
|
|
1423
|
-
}
|
|
1424
|
-
if (flags === DERIVED) {
|
|
1425
|
-
return index === 0
|
|
1426
|
-
? get_derived(/** @type {Derived} */ (lazy))
|
|
1427
|
-
: index === 1
|
|
1428
|
-
? lazy
|
|
1429
|
-
: undefined;
|
|
1430
|
-
}
|
|
1431
|
-
return iterable_array_from(lazy, index)[0];
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
/**
|
|
1435
|
-
* @param {any} lazy
|
|
1436
|
-
* @param {number} [index]
|
|
1437
|
-
* @returns {any[]}
|
|
1438
|
-
*/
|
|
1439
|
-
export function lazy_array_rest(lazy, index = 0) {
|
|
1440
|
-
if (is_array(lazy)) {
|
|
1441
|
-
return lazy.slice(index);
|
|
1442
|
-
}
|
|
1443
|
-
var flags = lazy.f;
|
|
1444
|
-
if (flags === TRACKED) {
|
|
1445
|
-
return index === 0
|
|
1446
|
-
? [get_tracked(/** @type {Tracked} */ (lazy)), lazy]
|
|
1447
|
-
: index === 1
|
|
1448
|
-
? [lazy]
|
|
1449
|
-
: [];
|
|
1450
|
-
}
|
|
1451
|
-
if (flags === DERIVED) {
|
|
1452
|
-
return index === 0
|
|
1453
|
-
? [get_derived(/** @type {Derived} */ (lazy)), lazy]
|
|
1454
|
-
: index === 1
|
|
1455
|
-
? [lazy]
|
|
1456
|
-
: [];
|
|
1457
|
-
}
|
|
1458
|
-
return iterable_array_from(lazy, index);
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
1492
|
/**
|
|
1462
1493
|
* @param {Derived | Tracked} tracked
|
|
1463
1494
|
* @param {any} value
|
|
@@ -1467,62 +1498,11 @@ export function set(tracked, value) {
|
|
|
1467
1498
|
|
|
1468
1499
|
if (value !== old_value) {
|
|
1469
1500
|
var s = tracked.a.set;
|
|
1470
|
-
tracked.v = s ? s(value, tracked.v) : value;
|
|
1501
|
+
tracked.v = typeof s === 'function' ? s(value, tracked.v) : value;
|
|
1471
1502
|
tracked.c = increment_clock();
|
|
1472
1503
|
}
|
|
1473
1504
|
}
|
|
1474
1505
|
|
|
1475
|
-
/**
|
|
1476
|
-
* @param {any} lazy
|
|
1477
|
-
* @param {any} value
|
|
1478
|
-
* @param {number} [index]
|
|
1479
|
-
* @returns {void}
|
|
1480
|
-
*/
|
|
1481
|
-
export function lazy_array_set(lazy, value, index = 0) {
|
|
1482
|
-
if (is_array(lazy)) {
|
|
1483
|
-
lazy[index] = value;
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
var flags = lazy.f;
|
|
1487
|
-
if (flags === TRACKED || flags === DERIVED) {
|
|
1488
|
-
if (index === 0) {
|
|
1489
|
-
set(/** @type {Derived | Tracked} */ (lazy), value);
|
|
1490
|
-
return;
|
|
1491
|
-
}
|
|
1492
|
-
if (index === 1) {
|
|
1493
|
-
throw_tracked_index_reference_error();
|
|
1494
|
-
}
|
|
1495
|
-
return;
|
|
1496
|
-
}
|
|
1497
|
-
lazy[index] = value;
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
/**
|
|
1501
|
-
* @param {any} lazy
|
|
1502
|
-
* @param {number} [index]
|
|
1503
|
-
* @param {number} [d]
|
|
1504
|
-
* @returns {number}
|
|
1505
|
-
*/
|
|
1506
|
-
export function lazy_array_update(lazy, index = 0, d = 1) {
|
|
1507
|
-
var value = lazy_array_get(lazy, index);
|
|
1508
|
-
var result = d === 1 ? value++ : value--;
|
|
1509
|
-
lazy_array_set(lazy, value, index);
|
|
1510
|
-
return result;
|
|
1511
|
-
}
|
|
1512
|
-
|
|
1513
|
-
/**
|
|
1514
|
-
* @param {any} lazy
|
|
1515
|
-
* @param {number} [index]
|
|
1516
|
-
* @param {number} [d]
|
|
1517
|
-
* @returns {number}
|
|
1518
|
-
*/
|
|
1519
|
-
export function lazy_array_update_pre(lazy, index = 0, d = 1) {
|
|
1520
|
-
var value = lazy_array_get(lazy, index);
|
|
1521
|
-
var new_value = d === 1 ? ++value : --value;
|
|
1522
|
-
lazy_array_set(lazy, new_value, index);
|
|
1523
|
-
return new_value;
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
1506
|
/**
|
|
1527
1507
|
* @param {Tracked} tracked
|
|
1528
1508
|
* @param {number} [d]
|
|
@@ -1645,11 +1625,10 @@ function get_styles(styles) {
|
|
|
1645
1625
|
|
|
1646
1626
|
/**
|
|
1647
1627
|
* @param {Record<string, any>} attrs
|
|
1648
|
-
* @param {string | undefined} css_hash
|
|
1649
|
-
* @param {string} [exclude_prop]
|
|
1628
|
+
* @param {string | undefined} [css_hash]
|
|
1650
1629
|
* @returns {string}
|
|
1651
1630
|
*/
|
|
1652
|
-
export function spread_attrs(attrs, css_hash
|
|
1631
|
+
export function spread_attrs(attrs, css_hash) {
|
|
1653
1632
|
let attr_str = '';
|
|
1654
1633
|
let name;
|
|
1655
1634
|
|
|
@@ -1664,7 +1643,6 @@ export function spread_attrs(attrs, css_hash, exclude_prop) {
|
|
|
1664
1643
|
name === 'children' ||
|
|
1665
1644
|
name === 'innerHTML' ||
|
|
1666
1645
|
name === '#class' ||
|
|
1667
|
-
name === exclude_prop ||
|
|
1668
1646
|
typeof value === 'function' ||
|
|
1669
1647
|
is_tsrx_element(value)
|
|
1670
1648
|
)
|
|
@@ -1707,11 +1685,11 @@ var empty_get_set = { get: undefined, set: undefined };
|
|
|
1707
1685
|
class TrackedValue {
|
|
1708
1686
|
/**
|
|
1709
1687
|
* @param {any} v
|
|
1710
|
-
* @param {{ get?: Function; set?: Function }} a
|
|
1688
|
+
* @param {{ get?: Function; set?: Function | true }} a
|
|
1711
1689
|
* @param {string} hash
|
|
1712
1690
|
*/
|
|
1713
1691
|
constructor(v, a, hash) {
|
|
1714
|
-
/** @type {{ get?: Function; set?: Function }} */
|
|
1692
|
+
/** @type {{ get?: Function; set?: Function | true }} */
|
|
1715
1693
|
this.a = a;
|
|
1716
1694
|
/** @type {AbortController | null} */
|
|
1717
1695
|
this.aa = null;
|
|
@@ -1729,18 +1707,6 @@ class TrackedValue {
|
|
|
1729
1707
|
this.v = v;
|
|
1730
1708
|
}
|
|
1731
1709
|
/** @returns {any} */
|
|
1732
|
-
get [0]() {
|
|
1733
|
-
return throw_tracked_index_value_error();
|
|
1734
|
-
}
|
|
1735
|
-
/** @param {any} v */
|
|
1736
|
-
set [0](v) {
|
|
1737
|
-
throw_tracked_index_value_error();
|
|
1738
|
-
}
|
|
1739
|
-
/** @returns {Tracked} */
|
|
1740
|
-
get [1]() {
|
|
1741
|
-
return throw_tracked_index_reference_error();
|
|
1742
|
-
}
|
|
1743
|
-
/** @returns {any} */
|
|
1744
1710
|
get value() {
|
|
1745
1711
|
return get_tracked(/** @type {Tracked} */ (this));
|
|
1746
1712
|
}
|
|
@@ -1748,25 +1714,25 @@ class TrackedValue {
|
|
|
1748
1714
|
set value(v) {
|
|
1749
1715
|
set(/** @type {Tracked} */ (this), v);
|
|
1750
1716
|
}
|
|
1751
|
-
/**
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1717
|
+
/**
|
|
1718
|
+
* A read-only view: a derived over this value, for a receiver that should
|
|
1719
|
+
* read but not write it. Equivalent to `track(() => tracked.value)`. The
|
|
1720
|
+
* view has no hash of its own: it is not a serialized value.
|
|
1721
|
+
* @returns {Derived}
|
|
1722
|
+
*/
|
|
1723
|
+
readOnly() {
|
|
1724
|
+
return derived(() => get_tracked(/** @type {Tracked} */ (this)));
|
|
1759
1725
|
}
|
|
1760
1726
|
}
|
|
1761
1727
|
|
|
1762
1728
|
class DerivedValue {
|
|
1763
1729
|
/**
|
|
1764
1730
|
* @param {Function} fn
|
|
1765
|
-
* @param {{ get?: Function; set?: Function }} a
|
|
1766
|
-
* @param {string} hash
|
|
1731
|
+
* @param {{ get?: Function; set?: Function | true }} a
|
|
1732
|
+
* @param {string} [hash]
|
|
1767
1733
|
*/
|
|
1768
1734
|
constructor(fn, a, hash) {
|
|
1769
|
-
/** @type {{ get?: Function; set?: Function }} */
|
|
1735
|
+
/** @type {{ get?: Function; set?: Function | true }} */
|
|
1770
1736
|
this.a = a;
|
|
1771
1737
|
// we always should have an active block
|
|
1772
1738
|
/** @type {Block} */
|
|
@@ -1781,24 +1747,12 @@ class DerivedValue {
|
|
|
1781
1747
|
this.f = DERIVED;
|
|
1782
1748
|
/** @type {Function} */
|
|
1783
1749
|
this.fn = fn;
|
|
1784
|
-
/** @type {string} */
|
|
1750
|
+
/** @type {string | undefined} */
|
|
1785
1751
|
this.h = hash;
|
|
1786
1752
|
/** @type {any} */
|
|
1787
1753
|
this.v = UNINITIALIZED;
|
|
1788
1754
|
}
|
|
1789
1755
|
/** @returns {any} */
|
|
1790
|
-
get [0]() {
|
|
1791
|
-
return throw_tracked_index_value_error();
|
|
1792
|
-
}
|
|
1793
|
-
/** @param {any} v */
|
|
1794
|
-
set [0](v) {
|
|
1795
|
-
throw_tracked_index_value_error();
|
|
1796
|
-
}
|
|
1797
|
-
/** @returns {Derived} */
|
|
1798
|
-
get [1]() {
|
|
1799
|
-
return throw_tracked_index_reference_error();
|
|
1800
|
-
}
|
|
1801
|
-
/** @returns {any} */
|
|
1802
1756
|
get value() {
|
|
1803
1757
|
return get_derived(/** @type {Derived} */ (this));
|
|
1804
1758
|
}
|
|
@@ -1806,14 +1760,16 @@ class DerivedValue {
|
|
|
1806
1760
|
set value(v) {
|
|
1807
1761
|
set(/** @type {Derived} */ (this), v);
|
|
1808
1762
|
}
|
|
1809
|
-
/**
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1763
|
+
/**
|
|
1764
|
+
* A read-only view (see `TrackedValue#readOnly`). A derived without a
|
|
1765
|
+
* setter is already read-only and is returned as is; a writable one is
|
|
1766
|
+
* wrapped in a derived that follows it.
|
|
1767
|
+
* @returns {Derived}
|
|
1768
|
+
*/
|
|
1769
|
+
readOnly() {
|
|
1770
|
+
return this.a.set === undefined
|
|
1771
|
+
? /** @type {Derived} */ (this)
|
|
1772
|
+
: derived(() => get_derived(/** @type {Derived} */ (this)));
|
|
1817
1773
|
}
|
|
1818
1774
|
}
|
|
1819
1775
|
|
|
@@ -1821,7 +1777,7 @@ class DerivedValue {
|
|
|
1821
1777
|
* @param {any} v
|
|
1822
1778
|
* @param {string} hash
|
|
1823
1779
|
* @param {(value: any) => any} [get]
|
|
1824
|
-
* @param {(next: any, prev: any) => any} [set]
|
|
1780
|
+
* @param {((next: any, prev: any) => any) | true} [set]
|
|
1825
1781
|
* @returns {Tracked}
|
|
1826
1782
|
*/
|
|
1827
1783
|
function tracked(v, hash, get, set) {
|
|
@@ -1830,29 +1786,11 @@ function tracked(v, hash, get, set) {
|
|
|
1830
1786
|
);
|
|
1831
1787
|
}
|
|
1832
1788
|
|
|
1833
|
-
/**
|
|
1834
|
-
* @param {Record<string, unknown>} obj
|
|
1835
|
-
* @param {string[]} exclude_keys
|
|
1836
|
-
* @returns {Record<string, unknown>}
|
|
1837
|
-
*/
|
|
1838
|
-
export function exclude_from_object(obj, exclude_keys) {
|
|
1839
|
-
/** @type {Record<string, unknown>} */
|
|
1840
|
-
var new_obj = {};
|
|
1841
|
-
|
|
1842
|
-
for (const key of Object.keys(obj)) {
|
|
1843
|
-
if (!exclude_keys.includes(key)) {
|
|
1844
|
-
new_obj[key] = obj[key];
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
return new_obj;
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
1789
|
/**
|
|
1852
1790
|
* @param {any} v
|
|
1853
|
-
* @param {string} hash
|
|
1791
|
+
* @param {string} [hash]
|
|
1854
1792
|
* @param {(value: any) => any} [get]
|
|
1855
|
-
* @param {(next: any, prev: any) => any} [set]
|
|
1793
|
+
* @param {((next: any, prev: any) => any) | true} [set]
|
|
1856
1794
|
* @returns {Derived}
|
|
1857
1795
|
*/
|
|
1858
1796
|
function derived(v, hash, get, set) {
|
|
@@ -1865,7 +1803,7 @@ function derived(v, hash, get, set) {
|
|
|
1865
1803
|
* @param {any} v
|
|
1866
1804
|
* @param {string} hash
|
|
1867
1805
|
* @param {(value: any) => any} [get]
|
|
1868
|
-
* @param {(next: any, prev: any) => any} [set]
|
|
1806
|
+
* @param {((next: any, prev: any) => any) | true} [set]
|
|
1869
1807
|
* @returns {Tracked | Derived}
|
|
1870
1808
|
*/
|
|
1871
1809
|
export function track(v, hash, get, set) {
|
|
@@ -1891,12 +1829,130 @@ export function track(v, hash, get, set) {
|
|
|
1891
1829
|
* @returns {void}
|
|
1892
1830
|
*/
|
|
1893
1831
|
function serialize_track_async_result(output, hash, value, deps) {
|
|
1894
|
-
/** @type {
|
|
1895
|
-
var envelope
|
|
1896
|
-
if (
|
|
1897
|
-
envelope
|
|
1832
|
+
/** @type {string} */
|
|
1833
|
+
var envelope;
|
|
1834
|
+
if (is_plain_data(value, null)) {
|
|
1835
|
+
// plain data: the value travels as raw JSON inside the envelope, so the
|
|
1836
|
+
// client reads it straight off `JSON.parse` with no devalue pass
|
|
1837
|
+
envelope = '{"ok":true,"value":' + JSON.stringify(value);
|
|
1838
|
+
if (deps && deps.length > 0) {
|
|
1839
|
+
envelope += ',"deps":' + JSON.stringify(deps);
|
|
1840
|
+
}
|
|
1841
|
+
envelope += '}';
|
|
1842
|
+
} else {
|
|
1843
|
+
/** @type {{ ok: true, payload: string, deps?: string[] }} */
|
|
1844
|
+
var object = { ok: true, payload: devalue.stringify(value) };
|
|
1845
|
+
if (deps && deps.length > 0) {
|
|
1846
|
+
object.deps = deps;
|
|
1847
|
+
}
|
|
1848
|
+
envelope = JSON.stringify(object);
|
|
1898
1849
|
}
|
|
1899
|
-
|
|
1850
|
+
output.push_serialized_result(
|
|
1851
|
+
'<script id="' +
|
|
1852
|
+
get_track_async_script_id(hash) +
|
|
1853
|
+
'" type="application/json">' +
|
|
1854
|
+
escape_inline_script(envelope) +
|
|
1855
|
+
'</script>',
|
|
1856
|
+
);
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
const default_track_async_serializer = serialize_track_async_result;
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* Switch once at registration, keeping the default serializer unchanged and
|
|
1863
|
+
* avoiding a transport lookup for every result. Unused registration code can
|
|
1864
|
+
* be removed from builds that only use the default renderer.
|
|
1865
|
+
* @param {Record<string, (value: any) => any> | undefined} reducers
|
|
1866
|
+
*/
|
|
1867
|
+
export function set_track_async_transport(reducers) {
|
|
1868
|
+
/** @type {typeof serialize_track_async_result} */
|
|
1869
|
+
const serializer =
|
|
1870
|
+
reducers === undefined
|
|
1871
|
+
? default_track_async_serializer
|
|
1872
|
+
: (output, hash, value, deps) => {
|
|
1873
|
+
// Reducers can claim plain objects: devalue must do the only walk.
|
|
1874
|
+
// Embed its JSON directly, avoiding another stringify of the payload
|
|
1875
|
+
// string and another JSON.parse on the client before revival.
|
|
1876
|
+
let envelope = '{"ok":true,"payload":' + devalue.stringify(value, reducers);
|
|
1877
|
+
if (deps && deps.length > 0) envelope += ',"deps":' + JSON.stringify(deps);
|
|
1878
|
+
envelope += '}';
|
|
1879
|
+
output.push_serialized_result(
|
|
1880
|
+
'<script id="' +
|
|
1881
|
+
get_track_async_script_id(hash) +
|
|
1882
|
+
'" type="application/json">' +
|
|
1883
|
+
escape_inline_script(envelope) +
|
|
1884
|
+
'</script>',
|
|
1885
|
+
);
|
|
1886
|
+
};
|
|
1887
|
+
// Keep the function declaration so unused registration leaves exactly the
|
|
1888
|
+
// original renderer in production bundles, without a mutable alias.
|
|
1889
|
+
// @ts-expect-error JavaScript permits reassigning a function declaration.
|
|
1890
|
+
serialize_track_async_result = serializer;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
/**
|
|
1894
|
+
* Whether a value is a plain data tree that `JSON.stringify` encodes without
|
|
1895
|
+
* loss: strings, finite numbers (not `-0`), booleans, `null`, arrays without
|
|
1896
|
+
* holes and plain objects, every object reachable exactly once. `JSON.parse`
|
|
1897
|
+
* on the client then yields exactly what `devalue.parse` would. Anything else
|
|
1898
|
+
* — `undefined`, `NaN`, `Infinity`, `-0`, bigints, symbols, functions, Dates,
|
|
1899
|
+
* Maps, Sets, class instances, null-prototype objects, symbol keys, cycles
|
|
1900
|
+
* and shared references — keeps its devalue encoding.
|
|
1901
|
+
* @param {unknown} value
|
|
1902
|
+
* @param {Set<object> | null} seen
|
|
1903
|
+
* @returns {boolean}
|
|
1904
|
+
*/
|
|
1905
|
+
function is_plain_data(value, seen) {
|
|
1906
|
+
switch (typeof value) {
|
|
1907
|
+
case 'string':
|
|
1908
|
+
case 'boolean':
|
|
1909
|
+
return true;
|
|
1910
|
+
case 'number':
|
|
1911
|
+
return (
|
|
1912
|
+
value === value &&
|
|
1913
|
+
value !== Infinity &&
|
|
1914
|
+
value !== -Infinity &&
|
|
1915
|
+
(value !== 0 || 1 / value > 0)
|
|
1916
|
+
);
|
|
1917
|
+
case 'object':
|
|
1918
|
+
break;
|
|
1919
|
+
default:
|
|
1920
|
+
return false;
|
|
1921
|
+
}
|
|
1922
|
+
if (value === null) {
|
|
1923
|
+
return true;
|
|
1924
|
+
}
|
|
1925
|
+
var proto = Object.getPrototypeOf(value);
|
|
1926
|
+
var is_list = proto === Array.prototype;
|
|
1927
|
+
if (!is_list && proto !== Object.prototype) {
|
|
1928
|
+
return false;
|
|
1929
|
+
}
|
|
1930
|
+
if (seen === null) {
|
|
1931
|
+
seen = new Set();
|
|
1932
|
+
} else if (seen.has(value)) {
|
|
1933
|
+
return false;
|
|
1934
|
+
}
|
|
1935
|
+
seen.add(value);
|
|
1936
|
+
if (is_list) {
|
|
1937
|
+
var list = /** @type {unknown[]} */ (value);
|
|
1938
|
+
for (var i = 0; i < list.length; i++) {
|
|
1939
|
+
if (!is_plain_data(list[i], seen)) {
|
|
1940
|
+
return false;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
return true;
|
|
1944
|
+
}
|
|
1945
|
+
if (Object.getOwnPropertySymbols(value).length !== 0) {
|
|
1946
|
+
return false;
|
|
1947
|
+
}
|
|
1948
|
+
var record = /** @type {Record<string, unknown>} */ (value);
|
|
1949
|
+
var keys = Object.keys(record);
|
|
1950
|
+
for (var k = 0; k < keys.length; k++) {
|
|
1951
|
+
if (!is_plain_data(record[keys[k]], seen)) {
|
|
1952
|
+
return false;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
return true;
|
|
1900
1956
|
}
|
|
1901
1957
|
|
|
1902
1958
|
/**
|
|
@@ -2075,7 +2131,7 @@ function settle_unit_after_catch(catch_block) {
|
|
|
2075
2131
|
* @returns {void}
|
|
2076
2132
|
*/
|
|
2077
2133
|
function push_script_for_hydration(push_fn, hash, envelope) {
|
|
2078
|
-
var serialized_envelope =
|
|
2134
|
+
var serialized_envelope = escape_inline_script(JSON.stringify(envelope));
|
|
2079
2135
|
|
|
2080
2136
|
push_fn(
|
|
2081
2137
|
'<script id="' +
|
|
@@ -2215,20 +2271,25 @@ function run_track_async(t, fn, block, dr, dj) {
|
|
|
2215
2271
|
}
|
|
2216
2272
|
|
|
2217
2273
|
/**
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2274
|
+
* The hashes of the compile-time tracked values a trackAsync read, recorded
|
|
2275
|
+
* in its hydration envelope so the client re-subscribes to them. A dependency
|
|
2276
|
+
* without a hash that is itself a derived (a `readOnly()` view, a derived made
|
|
2277
|
+
* outside a compiled call) stands for what it read: its own dependencies are
|
|
2278
|
+
* recorded in its place.
|
|
2220
2279
|
* @param {Dependency | null} head
|
|
2280
|
+
* @param {string[] | null} [hashes]
|
|
2221
2281
|
* @returns {string[] | null}
|
|
2222
2282
|
*/
|
|
2223
|
-
function collect_dep_hashes(head) {
|
|
2224
|
-
/** @type {string[] | null} */
|
|
2225
|
-
var hashes = null;
|
|
2283
|
+
function collect_dep_hashes(head, hashes = null) {
|
|
2226
2284
|
var dep = head;
|
|
2227
2285
|
while (dep !== null) {
|
|
2228
|
-
var
|
|
2286
|
+
var t = /** @type {{ h?: string; f: number; d?: Dependency | null }} */ (dep.t);
|
|
2287
|
+
var h = t.h;
|
|
2229
2288
|
if (h !== undefined) {
|
|
2230
2289
|
if (hashes === null) hashes = [];
|
|
2231
|
-
hashes.push(h);
|
|
2290
|
+
if (!hashes.includes(h)) hashes.push(h);
|
|
2291
|
+
} else if ((t.f & DERIVED) !== 0) {
|
|
2292
|
+
hashes = collect_dep_hashes(t.d ?? null, hashes);
|
|
2232
2293
|
}
|
|
2233
2294
|
dep = dep.n;
|
|
2234
2295
|
}
|
|
@@ -2511,15 +2572,4 @@ export function ripple_map(iterable) {
|
|
|
2511
2572
|
return new Map(iterable);
|
|
2512
2573
|
}
|
|
2513
2574
|
|
|
2514
|
-
/**
|
|
2515
|
-
* Returns the fallback value if the given value is undefined.
|
|
2516
|
-
* @template T
|
|
2517
|
-
* @param {T | undefined} value
|
|
2518
|
-
* @param {T} fallback
|
|
2519
|
-
* @returns {T}
|
|
2520
|
-
*/
|
|
2521
|
-
export function fallback(value, fallback) {
|
|
2522
|
-
return value === undefined ? fallback : value;
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
2575
|
export { dynamic_element } from './dynamic.js';
|