ripple 0.3.12 → 0.3.13
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 +36 -0
- package/package.json +8 -2
- package/src/compiler/phases/1-parse/index.js +73 -30
- package/src/compiler/phases/2-analyze/index.js +28 -58
- package/src/compiler/phases/3-transform/client/index.js +127 -164
- package/src/compiler/phases/3-transform/segments.js +4 -8
- package/src/compiler/phases/3-transform/server/index.js +210 -360
- package/src/compiler/types/import.d.ts +0 -12
- package/src/compiler/types/index.d.ts +12 -5
- package/src/compiler/types/parse.d.ts +2 -0
- package/src/compiler/utils.js +39 -44
- package/src/helpers.d.ts +2 -0
- package/src/runtime/index-client.js +15 -13
- package/src/runtime/index-server.js +18 -11
- package/src/runtime/internal/client/blocks.js +19 -23
- package/src/runtime/internal/client/constants.js +20 -9
- package/src/runtime/internal/client/index.js +14 -4
- package/src/runtime/internal/client/runtime.js +435 -173
- package/src/runtime/internal/client/try.js +334 -156
- package/src/runtime/internal/client/types.d.ts +26 -0
- package/src/runtime/internal/server/blocks.js +183 -0
- package/src/runtime/internal/server/constants.js +7 -0
- package/src/runtime/internal/server/index.js +780 -148
- package/src/runtime/internal/server/types.d.ts +35 -0
- package/src/server/index.js +1 -1
- package/src/utils/async.js +35 -0
- package/src/utils/builders.js +3 -1
- package/tests/client/__snapshots__/computed-properties.test.rsrx.snap +49 -0
- package/tests/client/__snapshots__/for.test.rsrx.snap +319 -0
- package/tests/client/__snapshots__/html.test.rsrx.snap +40 -0
- package/tests/client/_etc.test.rsrx +7 -0
- package/tests/client/array/{array.static.test.ripple → array.static.test.rsrx} +18 -20
- package/tests/client/async-suspend.test.rsrx +662 -0
- package/tests/client/basic/__snapshots__/basic.attributes.test.rsrx.snap +60 -0
- package/tests/client/basic/__snapshots__/basic.rendering.test.rsrx.snap +59 -0
- package/tests/client/basic/{basic.errors.test.ripple → basic.errors.test.rsrx} +2 -2
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +12 -0
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.rsrx.snap +46 -0
- package/tests/client/compiler/{compiler.try-in-function.test.ripple → compiler.try-in-function.test.rsrx} +8 -6
- package/tests/client/composite/__snapshots__/composite.render.test.rsrx.snap +37 -0
- package/tests/client/{function-overload.test.ripple → function-overload.test.rsrx} +1 -1
- package/tests/client/try.test.rsrx +1702 -0
- package/tests/hydration/build-components.js +5 -3
- package/tests/hydration/compiled/client/head.js +11 -11
- package/tests/hydration/compiled/client/mixed-control-flow.js +55 -70
- package/tests/hydration/compiled/client/nested-control-flow.js +72 -88
- package/tests/hydration/compiled/client/try.js +42 -54
- package/tests/hydration/compiled/server/basic.js +491 -369
- package/tests/hydration/compiled/server/composite.js +153 -128
- package/tests/hydration/compiled/server/events.js +166 -145
- package/tests/hydration/compiled/server/for.js +821 -677
- package/tests/hydration/compiled/server/head.js +200 -165
- package/tests/hydration/compiled/server/hmr.js +62 -54
- package/tests/hydration/compiled/server/html-in-template.js +64 -55
- package/tests/hydration/compiled/server/html.js +1477 -1360
- package/tests/hydration/compiled/server/if-children.js +448 -408
- package/tests/hydration/compiled/server/if.js +204 -171
- package/tests/hydration/compiled/server/mixed-control-flow.js +237 -195
- package/tests/hydration/compiled/server/nested-control-flow.js +533 -467
- package/tests/hydration/compiled/server/portal.js +94 -107
- package/tests/hydration/compiled/server/reactivity.js +87 -64
- package/tests/hydration/compiled/server/return.js +1424 -1174
- package/tests/hydration/compiled/server/switch.js +268 -238
- package/tests/hydration/compiled/server/try.js +98 -87
- package/tests/hydration/components/{mixed-control-flow.ripple → mixed-control-flow.rsrx} +2 -2
- package/tests/hydration/components/{try.ripple → try.rsrx} +4 -2
- package/tests/hydration/mixed-control-flow.test.js +14 -0
- package/tests/hydration/nested-control-flow.test.js +50 -48
- package/tests/hydration/try.test.js +25 -0
- package/tests/server/__snapshots__/compiler.test.ripple.snap +0 -32
- package/tests/server/__snapshots__/compiler.test.rsrx.snap +95 -0
- package/tests/server/{compiler.test.ripple → compiler.test.rsrx} +0 -17
- package/tests/server/{html-nesting-validation.test.ripple → html-nesting-validation.test.rsrx} +3 -3
- package/tests/server/streaming-ssr.test.rsrx +115 -0
- package/tests/server/try.test.rsrx +503 -0
- package/tests/utils/compiler-compat-config.test.js +3 -3
- package/tests/utils/vite-plugin-config.test.js +1 -1
- package/tests/utils/vite-plugin-hmr.test.js +5 -5
- package/tsconfig.json +2 -0
- package/types/index.d.ts +13 -23
- package/types/server.d.ts +43 -16
- package/tests/client/_etc.test.ripple +0 -5
- package/tests/client/async-suspend.test.ripple +0 -94
- package/tests/client/try.test.ripple +0 -196
- package/tests/server/streaming-ssr.test.ripple +0 -68
- package/tests/server/try.test.ripple +0 -82
- /package/tests/client/array/{array.copy-within.test.ripple → array.copy-within.test.rsrx} +0 -0
- /package/tests/client/array/{array.derived.test.ripple → array.derived.test.rsrx} +0 -0
- /package/tests/client/array/{array.iteration.test.ripple → array.iteration.test.rsrx} +0 -0
- /package/tests/client/array/{array.mutations.test.ripple → array.mutations.test.rsrx} +0 -0
- /package/tests/client/array/{array.to-methods.test.ripple → array.to-methods.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.attributes.test.ripple → basic.attributes.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.collections.test.ripple → basic.collections.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.components.test.ripple → basic.components.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.events.test.ripple → basic.events.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.get-set.test.ripple → basic.get-set.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.hmr.test.ripple → basic.hmr.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.reactivity.test.ripple → basic.reactivity.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.rendering.test.ripple → basic.rendering.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.styling.test.ripple → basic.styling.test.rsrx} +0 -0
- /package/tests/client/basic/{basic.utilities.test.ripple → basic.utilities.test.rsrx} +0 -0
- /package/tests/client/{boundaries.test.ripple → boundaries.test.rsrx} +0 -0
- /package/tests/client/compiler/{compiler.assignments.test.ripple → compiler.assignments.test.rsrx} +0 -0
- /package/tests/client/compiler/{compiler.attributes.test.ripple → compiler.attributes.test.rsrx} +0 -0
- /package/tests/client/compiler/{compiler.basic.test.ripple → compiler.basic.test.rsrx} +0 -0
- /package/tests/client/compiler/{compiler.regex.test.ripple → compiler.regex.test.rsrx} +0 -0
- /package/tests/client/compiler/{compiler.tracked-access.test.ripple → compiler.tracked-access.test.rsrx} +0 -0
- /package/tests/client/compiler/{compiler.typescript.test.ripple → compiler.typescript.test.rsrx} +0 -0
- /package/tests/client/composite/{composite.dynamic-components.test.ripple → composite.dynamic-components.test.rsrx} +0 -0
- /package/tests/client/composite/{composite.generics.test.ripple → composite.generics.test.rsrx} +0 -0
- /package/tests/client/composite/{composite.props.test.ripple → composite.props.test.rsrx} +0 -0
- /package/tests/client/composite/{composite.reactivity.test.ripple → composite.reactivity.test.rsrx} +0 -0
- /package/tests/client/composite/{composite.render.test.ripple → composite.render.test.rsrx} +0 -0
- /package/tests/client/{computed-properties.test.ripple → computed-properties.test.rsrx} +0 -0
- /package/tests/client/{context.test.ripple → context.test.rsrx} +0 -0
- /package/tests/client/css/{global-additional-cases.test.ripple → global-additional-cases.test.rsrx} +0 -0
- /package/tests/client/css/{global-advanced-selectors.test.ripple → global-advanced-selectors.test.rsrx} +0 -0
- /package/tests/client/css/{global-at-rules.test.ripple → global-at-rules.test.rsrx} +0 -0
- /package/tests/client/css/{global-basic.test.ripple → global-basic.test.rsrx} +0 -0
- /package/tests/client/css/{global-classes-ids.test.ripple → global-classes-ids.test.rsrx} +0 -0
- /package/tests/client/css/{global-combinators.test.ripple → global-combinators.test.rsrx} +0 -0
- /package/tests/client/css/{global-complex-nesting.test.ripple → global-complex-nesting.test.rsrx} +0 -0
- /package/tests/client/css/{global-edge-cases.test.ripple → global-edge-cases.test.rsrx} +0 -0
- /package/tests/client/css/{global-keyframes.test.ripple → global-keyframes.test.rsrx} +0 -0
- /package/tests/client/css/{global-nested.test.ripple → global-nested.test.rsrx} +0 -0
- /package/tests/client/css/{global-pseudo.test.ripple → global-pseudo.test.rsrx} +0 -0
- /package/tests/client/css/{global-scoping.test.ripple → global-scoping.test.rsrx} +0 -0
- /package/tests/client/css/{style-identifier.test.ripple → style-identifier.test.rsrx} +0 -0
- /package/tests/client/{date.test.ripple → date.test.rsrx} +0 -0
- /package/tests/client/{dynamic-elements.test.ripple → dynamic-elements.test.rsrx} +0 -0
- /package/tests/client/{events.test.ripple → events.test.rsrx} +0 -0
- /package/tests/client/{for.test.ripple → for.test.rsrx} +0 -0
- /package/tests/client/{function-overload-import.ripple → function-overload-import.rsrx} +0 -0
- /package/tests/client/{head.test.ripple → head.test.rsrx} +0 -0
- /package/tests/client/{html.test.ripple → html.test.rsrx} +0 -0
- /package/tests/client/{input-value.test.ripple → input-value.test.rsrx} +0 -0
- /package/tests/client/{lazy-destructuring.test.ripple → lazy-destructuring.test.rsrx} +0 -0
- /package/tests/client/{map.test.ripple → map.test.rsrx} +0 -0
- /package/tests/client/{media-query.test.ripple → media-query.test.rsrx} +0 -0
- /package/tests/client/{object.test.ripple → object.test.rsrx} +0 -0
- /package/tests/client/{portal.test.ripple → portal.test.rsrx} +0 -0
- /package/tests/client/{ref.test.ripple → ref.test.rsrx} +0 -0
- /package/tests/client/{return.test.ripple → return.test.rsrx} +0 -0
- /package/tests/client/{set.test.ripple → set.test.rsrx} +0 -0
- /package/tests/client/{svg.test.ripple → svg.test.rsrx} +0 -0
- /package/tests/client/{switch.test.ripple → switch.test.rsrx} +0 -0
- /package/tests/client/{tsx.test.ripple → tsx.test.rsrx} +0 -0
- /package/tests/client/{typescript-generics.test.ripple → typescript-generics.test.rsrx} +0 -0
- /package/tests/client/url/{url.derived.test.ripple → url.derived.test.rsrx} +0 -0
- /package/tests/client/url/{url.parsing.test.ripple → url.parsing.test.rsrx} +0 -0
- /package/tests/client/url/{url.partial-removal.test.ripple → url.partial-removal.test.rsrx} +0 -0
- /package/tests/client/url/{url.reactivity.test.ripple → url.reactivity.test.rsrx} +0 -0
- /package/tests/client/url/{url.serialization.test.ripple → url.serialization.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.derived.test.ripple → url-search-params.derived.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.initialization.test.ripple → url-search-params.initialization.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.iteration.test.ripple → url-search-params.iteration.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.mutation.test.ripple → url-search-params.mutation.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.retrieval.test.ripple → url-search-params.retrieval.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.serialization.test.ripple → url-search-params.serialization.test.rsrx} +0 -0
- /package/tests/client/url-search-params/{url-search-params.tracked-url.test.ripple → url-search-params.tracked-url.test.rsrx} +0 -0
- /package/tests/hydration/components/{basic.ripple → basic.rsrx} +0 -0
- /package/tests/hydration/components/{composite.ripple → composite.rsrx} +0 -0
- /package/tests/hydration/components/{events.ripple → events.rsrx} +0 -0
- /package/tests/hydration/components/{for.ripple → for.rsrx} +0 -0
- /package/tests/hydration/components/{head.ripple → head.rsrx} +0 -0
- /package/tests/hydration/components/{hmr.ripple → hmr.rsrx} +0 -0
- /package/tests/hydration/components/{html-in-template.ripple → html-in-template.rsrx} +0 -0
- /package/tests/hydration/components/{html.ripple → html.rsrx} +0 -0
- /package/tests/hydration/components/{if-children.ripple → if-children.rsrx} +0 -0
- /package/tests/hydration/components/{if.ripple → if.rsrx} +0 -0
- /package/tests/hydration/components/{nested-control-flow.ripple → nested-control-flow.rsrx} +0 -0
- /package/tests/hydration/components/{portal.ripple → portal.rsrx} +0 -0
- /package/tests/hydration/components/{reactivity.ripple → reactivity.rsrx} +0 -0
- /package/tests/hydration/components/{return.ripple → return.rsrx} +0 -0
- /package/tests/hydration/components/{switch.ripple → switch.rsrx} +0 -0
- /package/tests/server/{await.test.ripple → await.test.rsrx} +0 -0
- /package/tests/server/{basic.attributes.test.ripple → basic.attributes.test.rsrx} +0 -0
- /package/tests/server/{basic.components.test.ripple → basic.components.test.rsrx} +0 -0
- /package/tests/server/{basic.test.ripple → basic.test.rsrx} +0 -0
- /package/tests/server/{composite.props.test.ripple → composite.props.test.rsrx} +0 -0
- /package/tests/server/{composite.test.ripple → composite.test.rsrx} +0 -0
- /package/tests/server/{context.test.ripple → context.test.rsrx} +0 -0
- /package/tests/server/{dynamic-elements.test.ripple → dynamic-elements.test.rsrx} +0 -0
- /package/tests/server/{for.test.ripple → for.test.rsrx} +0 -0
- /package/tests/server/{head.test.ripple → head.test.rsrx} +0 -0
- /package/tests/server/{if.test.ripple → if.test.rsrx} +0 -0
- /package/tests/server/{lazy-destructuring.test.ripple → lazy-destructuring.test.rsrx} +0 -0
- /package/tests/server/{return.test.ripple → return.test.rsrx} +0 -0
- /package/tests/server/{style-identifier.test.ripple → style-identifier.test.rsrx} +0 -0
- /package/tests/server/{switch.test.ripple → switch.test.rsrx} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** @import { Block } from '#client' */
|
|
1
|
+
/** @import { Block, TryBoundaryState, BlockWithTryBoundary, BlockWithTryBoundaryAndCatch } from '#client' */
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
boundary_fn_running_block,
|
|
5
5
|
create_try_block,
|
|
6
6
|
destroy_block,
|
|
7
7
|
is_destroyed,
|
|
@@ -20,67 +20,158 @@ import {
|
|
|
20
20
|
import { get_next_sibling } from './operations.js';
|
|
21
21
|
import {
|
|
22
22
|
active_block,
|
|
23
|
-
active_component,
|
|
24
|
-
active_reaction,
|
|
25
23
|
queue_microtask,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
set_active_reaction,
|
|
29
|
-
set_tracking,
|
|
30
|
-
tracking,
|
|
24
|
+
queue_post_block_flush_callback,
|
|
25
|
+
with_block,
|
|
31
26
|
} from './runtime.js';
|
|
32
27
|
|
|
28
|
+
/**
|
|
29
|
+
@typedef {(
|
|
30
|
+
anchor: Node,
|
|
31
|
+
error: any,
|
|
32
|
+
reset?: () => void
|
|
33
|
+
) => void} CatchFunction;
|
|
34
|
+
|
|
35
|
+
@typedef {(anchor: Node) => void} PendingFunction
|
|
36
|
+
*/
|
|
37
|
+
|
|
33
38
|
/**
|
|
34
39
|
* @param {Node} node
|
|
35
|
-
* @param {(anchor: Node) => void}
|
|
36
|
-
* @param {
|
|
37
|
-
* @param {
|
|
40
|
+
* @param {(anchor: Node, block?: Block) => void} try_fn
|
|
41
|
+
* @param {CatchFunction | null} catch_fn
|
|
42
|
+
* @param {PendingFunction | null} [pending_fn=null]
|
|
38
43
|
* @returns {void}
|
|
39
44
|
*/
|
|
40
|
-
export function try_block(node,
|
|
45
|
+
export function try_block(node, try_fn, catch_fn, pending_fn = null) {
|
|
41
46
|
var anchor = node;
|
|
47
|
+
var pending_count = 0;
|
|
48
|
+
var request_version = 0;
|
|
49
|
+
/** @type {Set<number>} */
|
|
50
|
+
var active_requests = new Set();
|
|
42
51
|
/** @type {Block | null} */
|
|
43
|
-
var
|
|
52
|
+
var try_block = null;
|
|
44
53
|
/** @type {Block | null} */
|
|
45
|
-
var
|
|
46
|
-
|
|
54
|
+
var resolved_branch = null;
|
|
55
|
+
/** @type {Block | null} */
|
|
56
|
+
var pending_branch = null;
|
|
57
|
+
/** @type {Block | null} */
|
|
58
|
+
var catch_branch = null;
|
|
47
59
|
/** @type {DocumentFragment | null} */
|
|
48
60
|
var offscreen_fragment = null;
|
|
49
61
|
var has_resolved = false;
|
|
62
|
+
/** @type {'resolved' | 'pending' | 'catch'} */
|
|
63
|
+
var mode = 'resolved';
|
|
64
|
+
/** @type {Map<number, (reason: any) => void>} */
|
|
65
|
+
var pending_deferreds = new Map();
|
|
66
|
+
/** @type {Set<Block>} */
|
|
67
|
+
var paused_blocks = new Set();
|
|
50
68
|
|
|
51
|
-
function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
b = branch(() => {
|
|
63
|
-
/** @type {(anchor: Node) => void} */ (pending_fn)(anchor);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
});
|
|
69
|
+
function clear_paused_blocks() {
|
|
70
|
+
paused_blocks.clear();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
function resume_paused_blocks() {
|
|
77
|
+
if (paused_blocks.size === 0) {
|
|
78
|
+
return false;
|
|
67
79
|
}
|
|
68
80
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
var blocks = paused_blocks;
|
|
82
|
+
paused_blocks = new Set();
|
|
83
|
+
var resumed = false;
|
|
84
|
+
|
|
85
|
+
for (var block of blocks) {
|
|
86
|
+
if (!is_destroyed(block)) {
|
|
87
|
+
resume_block(block);
|
|
88
|
+
resumed = true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return resumed;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function show_resolved_fragment() {
|
|
96
|
+
if (offscreen_fragment !== null) {
|
|
97
|
+
/** @type {ChildNode} */ (anchor).before(offscreen_fragment);
|
|
98
|
+
offscreen_fragment = null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
has_resolved = true;
|
|
102
|
+
mode = 'resolved';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function render_resolved() {
|
|
106
|
+
if (
|
|
107
|
+
try_block !== null &&
|
|
108
|
+
!is_destroyed(try_block) &&
|
|
109
|
+
(resolved_branch === null || is_destroyed(resolved_branch))
|
|
110
|
+
) {
|
|
111
|
+
if (catch_branch !== null) {
|
|
112
|
+
destroy_block(catch_branch);
|
|
113
|
+
catch_branch = null;
|
|
82
114
|
}
|
|
115
|
+
mode = 'resolved';
|
|
116
|
+
if (active_block !== try_block) {
|
|
117
|
+
with_block(try_block, () => {
|
|
118
|
+
resolved_branch = boundary_fn_running_block(() => try_fn(anchor));
|
|
119
|
+
});
|
|
120
|
+
} else {
|
|
121
|
+
resolved_branch = boundary_fn_running_block(() => try_fn(anchor));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function destroy_resolved() {
|
|
127
|
+
if (resolved_branch !== null && !is_destroyed(resolved_branch)) {
|
|
128
|
+
destroy_block(resolved_branch);
|
|
129
|
+
}
|
|
130
|
+
resolved_branch = null;
|
|
131
|
+
offscreen_fragment = null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function move_resolved_offscreen() {
|
|
135
|
+
if (resolved_branch !== null) {
|
|
136
|
+
if (!offscreen_fragment) {
|
|
137
|
+
// if offcreen_fragment exists, it means the resolved_branch is already offscreen,
|
|
138
|
+
// so we can skip moving it again
|
|
139
|
+
offscreen_fragment = document.createDocumentFragment();
|
|
140
|
+
move_block(resolved_branch, offscreen_fragment);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function render_pending() {
|
|
146
|
+
if (pending_fn === null || mode === 'pending') {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
move_resolved_offscreen();
|
|
151
|
+
|
|
152
|
+
mode = 'pending';
|
|
153
|
+
|
|
154
|
+
var create_pending = () => {
|
|
155
|
+
pending_branch = boundary_fn_running_block(() => {
|
|
156
|
+
/** @type {PendingFunction} */ (pending_fn)(anchor);
|
|
157
|
+
});
|
|
83
158
|
};
|
|
159
|
+
|
|
160
|
+
// with_block ensures the branch is parented under the TRY_BLOCK when called
|
|
161
|
+
// from async contexts (microtasks) where active_block is null. During synchronous
|
|
162
|
+
// execution (try_block not yet assigned), active_block is already the TRY_BLOCK.
|
|
163
|
+
if (try_block !== null && !is_destroyed(try_block) && active_block !== try_block) {
|
|
164
|
+
with_block(try_block, create_pending);
|
|
165
|
+
} else {
|
|
166
|
+
create_pending();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function destroy_pending() {
|
|
171
|
+
if (pending_branch !== null && !is_destroyed(pending_branch)) {
|
|
172
|
+
destroy_block(pending_branch);
|
|
173
|
+
}
|
|
174
|
+
pending_branch = null;
|
|
84
175
|
}
|
|
85
176
|
|
|
86
177
|
/**
|
|
@@ -88,157 +179,244 @@ export function try_block(node, fn, catch_fn, pending_fn = null) {
|
|
|
88
179
|
* @returns {void}
|
|
89
180
|
*/
|
|
90
181
|
function handle_error(error) {
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
182
|
+
if (mode === 'catch') {
|
|
183
|
+
// we don't want to do this again and render catch block again
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
pending_count = 0;
|
|
187
|
+
active_requests.clear();
|
|
188
|
+
clear_paused_blocks();
|
|
189
|
+
|
|
190
|
+
// Reject all pending deferred promises so dependent async tracked settle
|
|
191
|
+
// handlers fire and clean up. The settle will see the request already
|
|
192
|
+
// cleared and skip error routing, avoiding double-catch.
|
|
193
|
+
if (pending_deferreds.size > 0) {
|
|
194
|
+
for (var [, reject_fn] of pending_deferreds) {
|
|
195
|
+
reject_fn(error);
|
|
196
|
+
}
|
|
197
|
+
pending_deferreds.clear();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (mode === 'pending') {
|
|
201
|
+
destroy_pending();
|
|
202
|
+
} else if (mode === 'resolved') {
|
|
203
|
+
move_resolved_offscreen();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
mode = 'catch';
|
|
207
|
+
|
|
208
|
+
var create_catch = () => {
|
|
209
|
+
catch_branch = boundary_fn_running_block(() => {
|
|
210
|
+
/** @type {CatchFunction} */ (catch_fn)(anchor, error, render_resolved);
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// with_block ensures the branch is parented under the TRY_BLOCK when called
|
|
215
|
+
// from async contexts where active_block is null. During synchronous
|
|
216
|
+
// execution (try_block not yet assigned), active_block is already the TRY_BLOCK.
|
|
217
|
+
if (try_block !== null && !is_destroyed(try_block) && active_block !== try_block) {
|
|
218
|
+
with_block(try_block, create_catch);
|
|
219
|
+
} else {
|
|
220
|
+
create_catch();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
destroy_resolved();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function begin_request() {
|
|
227
|
+
var request_id = ++request_version;
|
|
228
|
+
active_requests.add(request_id);
|
|
229
|
+
|
|
230
|
+
if (pending_count++ === 0 && pending_fn !== null && !has_resolved) {
|
|
231
|
+
queue_microtask(() => {
|
|
232
|
+
if (try_block !== null && !is_destroyed(try_block) && pending_count > 0 && !has_resolved) {
|
|
233
|
+
render_pending();
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return request_id;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @param {number} old_request_id
|
|
243
|
+
* @returns {number}
|
|
244
|
+
*/
|
|
245
|
+
function replace_request(old_request_id) {
|
|
246
|
+
active_requests.delete(old_request_id);
|
|
247
|
+
pending_deferreds.delete(old_request_id);
|
|
248
|
+
// pending_count unchanged — one out, one in
|
|
249
|
+
var request_id = ++request_version;
|
|
250
|
+
active_requests.add(request_id);
|
|
251
|
+
return request_id;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @param {number} request_id
|
|
256
|
+
* @param {boolean} [show_resolved_branch=true]
|
|
257
|
+
* @returns {boolean}
|
|
258
|
+
*/
|
|
259
|
+
function complete_request(request_id, show_resolved_branch = true) {
|
|
260
|
+
if (!active_requests.delete(request_id)) {
|
|
261
|
+
return false;
|
|
96
262
|
}
|
|
97
263
|
|
|
98
|
-
|
|
99
|
-
|
|
264
|
+
pending_deferreds.delete(request_id);
|
|
265
|
+
|
|
266
|
+
pending_count--;
|
|
267
|
+
|
|
268
|
+
if (pending_count === 0) {
|
|
269
|
+
if (!show_resolved_branch) {
|
|
270
|
+
clear_paused_blocks();
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
resume_paused_blocks();
|
|
275
|
+
|
|
276
|
+
queue_post_block_flush_callback(() => {
|
|
277
|
+
// run this only after the blocks have a chance to run
|
|
278
|
+
// and find more pending requests (and pause themselves) before we are
|
|
279
|
+
// certain to render the resolved state.
|
|
280
|
+
// Otherwise, we'll have multiple renders.
|
|
281
|
+
if (try_block === null || is_destroyed(try_block) || pending_count > 0) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (mode === 'pending') {
|
|
286
|
+
destroy_pending();
|
|
287
|
+
show_resolved_fragment();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
has_resolved = true;
|
|
291
|
+
mode = 'resolved';
|
|
292
|
+
});
|
|
293
|
+
// this is more just in case here and shouldn't really cause anything to run
|
|
294
|
+
// most likely the scheduling is already there
|
|
295
|
+
// leaving it here in case there are some weird edge cases
|
|
296
|
+
queue_microtask();
|
|
100
297
|
}
|
|
101
298
|
|
|
102
|
-
|
|
103
|
-
/** @type {(anchor: Node, error: any) => void} */ (catch_fn)(anchor, error);
|
|
104
|
-
});
|
|
299
|
+
return true;
|
|
105
300
|
}
|
|
106
301
|
|
|
302
|
+
/** @type {TryBoundaryState} */
|
|
107
303
|
var state = {
|
|
108
|
-
|
|
304
|
+
p: pending_fn !== null,
|
|
305
|
+
b: begin_request,
|
|
306
|
+
r: complete_request,
|
|
109
307
|
c: catch_fn !== null ? handle_error : null,
|
|
308
|
+
/** @param {number} request_id @param {(reason: any) => void} reject_fn */
|
|
309
|
+
rd: (request_id, reject_fn) => {
|
|
310
|
+
pending_deferreds.set(request_id, reject_fn);
|
|
311
|
+
},
|
|
312
|
+
/** @param {Block} block */
|
|
313
|
+
pb: (block) => {
|
|
314
|
+
paused_blocks.add(block);
|
|
315
|
+
},
|
|
316
|
+
rp: replace_request,
|
|
110
317
|
};
|
|
111
318
|
|
|
112
|
-
if (hydrating && pending_fn !== null) {
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
hydrate_next(); // consume <!--[-->_try
|
|
120
|
-
var end = skip_to_hydration_end(); // find matching <!--]-->_try
|
|
121
|
-
// Remove SSR pending+resolved nodes that sit between the two markers
|
|
122
|
-
var n = hydrate_node;
|
|
123
|
-
while (n !== null && n !== end) {
|
|
124
|
-
var next_n = get_next_sibling(n);
|
|
125
|
-
if (n.parentNode) n.parentNode.removeChild(n);
|
|
126
|
-
n = next_n;
|
|
127
|
-
}
|
|
128
|
-
set_hydrate_node(end); // position cursor at <!--]-->_try
|
|
129
|
-
set_hydrating(false);
|
|
130
|
-
|
|
131
|
-
// Save a reference to the nearest ancestor branch-block so we can update its
|
|
132
|
-
// DOM-range tracking (s.start) to cover the fresh client-side nodes we are
|
|
133
|
-
// about to insert. Without this, destroy_block on the parent would try to
|
|
134
|
-
// remove the already-removed SSR node and miss the new content entirely.
|
|
135
|
-
var hydration_parent = active_block;
|
|
136
|
-
// Remember what was before anchor so we can find the first new node afterward.
|
|
137
|
-
var prev_sibling_before = anchor.previousSibling;
|
|
138
|
-
|
|
139
|
-
create_try_block(() => {
|
|
140
|
-
b = branch(() => {
|
|
141
|
-
fn(anchor);
|
|
142
|
-
});
|
|
143
|
-
}, state);
|
|
144
|
-
|
|
145
|
-
// fn(anchor) inserted new DOM immediately before `anchor`.
|
|
146
|
-
// Find the first of those newly inserted nodes and update the parent block's
|
|
147
|
-
// s.start so that destroy_block can later remove both the hydration markers
|
|
148
|
-
// (<!--[-->/<!--]-->) and the fresh content in one range sweep.
|
|
149
|
-
var new_first =
|
|
150
|
-
prev_sibling_before !== null
|
|
151
|
-
? get_next_sibling(prev_sibling_before)
|
|
152
|
-
: anchor.parentNode
|
|
153
|
-
? anchor.parentNode.firstChild
|
|
154
|
-
: null;
|
|
155
|
-
if (
|
|
156
|
-
new_first !== null &&
|
|
157
|
-
new_first !== anchor &&
|
|
158
|
-
hydration_parent !== null &&
|
|
159
|
-
hydration_parent.s !== null
|
|
160
|
-
) {
|
|
161
|
-
hydration_parent.s.start = new_first;
|
|
319
|
+
if (hydrating && (pending_fn !== null || catch_fn !== null)) {
|
|
320
|
+
// Server wraps try_fn body with <!--[-->...<!--]--> markers when pending or catch is present.
|
|
321
|
+
// Server resolves all async content fully (pending is only for future streaming SSR),
|
|
322
|
+
// so the SSR HTML contains resolved content.
|
|
323
|
+
// Mark as already resolved so begin_request's microtask won't transition to pending.
|
|
324
|
+
if (pending_fn !== null) {
|
|
325
|
+
has_resolved = true;
|
|
162
326
|
}
|
|
163
|
-
|
|
164
|
-
set_hydrating(true);
|
|
165
|
-
return;
|
|
327
|
+
hydrate_next(); // consume <!--[-->
|
|
166
328
|
}
|
|
167
329
|
|
|
168
|
-
create_try_block(() => {
|
|
169
|
-
|
|
170
|
-
fn(anchor);
|
|
171
|
-
});
|
|
330
|
+
try_block = create_try_block(() => {
|
|
331
|
+
resolved_branch = boundary_fn_running_block(() => try_fn(anchor));
|
|
172
332
|
}, state);
|
|
173
333
|
}
|
|
174
334
|
|
|
175
335
|
/**
|
|
176
|
-
* @
|
|
336
|
+
* @param {Block | null} block
|
|
337
|
+
* @returns {BlockWithTryBoundary | null}
|
|
177
338
|
*/
|
|
178
|
-
export function
|
|
179
|
-
var current =
|
|
339
|
+
export function get_pending_boundary(block) {
|
|
340
|
+
var current = block;
|
|
180
341
|
|
|
181
342
|
while (current !== null) {
|
|
182
|
-
var state = current.s;
|
|
183
|
-
if ((current.f & TRY_BLOCK) !== 0 && state.
|
|
184
|
-
return
|
|
343
|
+
var state = /** @type {BlockWithTryBoundary} */ (current).s;
|
|
344
|
+
if ((current.f & TRY_BLOCK) !== 0 && state.p) {
|
|
345
|
+
return /** @type {BlockWithTryBoundary} */ (current);
|
|
185
346
|
}
|
|
186
347
|
current = current.p;
|
|
187
348
|
}
|
|
188
349
|
|
|
189
|
-
|
|
350
|
+
return null;
|
|
190
351
|
}
|
|
191
352
|
|
|
192
353
|
/**
|
|
193
|
-
* @
|
|
354
|
+
* @param {Block} block
|
|
355
|
+
* @returns {BlockWithTryBoundaryAndCatch | null}
|
|
356
|
+
*/
|
|
357
|
+
export function get_boundary_with_catch(block) {
|
|
358
|
+
/** @type {Block | null} */
|
|
359
|
+
var current = block;
|
|
360
|
+
|
|
361
|
+
while (current !== null) {
|
|
362
|
+
var state = /** @type {BlockWithTryBoundary} */ (current).s;
|
|
363
|
+
if ((current.f & TRY_BLOCK) !== 0 && state.c !== null) {
|
|
364
|
+
return /** @type {BlockWithTryBoundaryAndCatch} */ (current);
|
|
365
|
+
}
|
|
366
|
+
current = current.p;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* @param {BlockWithTryBoundary} boundary
|
|
374
|
+
* @returns {number}
|
|
194
375
|
*/
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
set_active_reaction(null);
|
|
198
|
-
set_active_block(null);
|
|
199
|
-
set_active_component(null);
|
|
376
|
+
export function begin_boundary_request(boundary) {
|
|
377
|
+
return boundary.s.b();
|
|
200
378
|
}
|
|
201
379
|
|
|
202
380
|
/**
|
|
203
|
-
* @
|
|
381
|
+
* @param {BlockWithTryBoundary} boundary
|
|
382
|
+
* @param {number} old_request_id
|
|
383
|
+
* @returns {number}
|
|
204
384
|
*/
|
|
205
|
-
export function
|
|
206
|
-
|
|
207
|
-
var previous_block = active_block;
|
|
208
|
-
var previous_reaction = active_reaction;
|
|
209
|
-
var previous_component = active_component;
|
|
210
|
-
|
|
211
|
-
return () => {
|
|
212
|
-
set_tracking(previous_tracking);
|
|
213
|
-
set_active_block(previous_block);
|
|
214
|
-
set_active_reaction(previous_reaction);
|
|
215
|
-
set_active_component(previous_component);
|
|
216
|
-
|
|
217
|
-
queue_microtask(exit);
|
|
218
|
-
};
|
|
385
|
+
export function replace_boundary_request(boundary, old_request_id) {
|
|
386
|
+
return boundary.s.rp(old_request_id);
|
|
219
387
|
}
|
|
220
388
|
|
|
221
389
|
/**
|
|
390
|
+
* @param {BlockWithTryBoundary | null} boundary
|
|
391
|
+
* @param {number} request_id
|
|
392
|
+
* @param {boolean} [show_resolved_branch=true]
|
|
222
393
|
* @returns {boolean}
|
|
223
394
|
*/
|
|
224
|
-
export function
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return is_destroyed(active_block);
|
|
395
|
+
export function complete_boundary_request(boundary, request_id, show_resolved_branch = true) {
|
|
396
|
+
return boundary !== null && !is_destroyed(boundary)
|
|
397
|
+
? boundary.s.r(request_id, show_resolved_branch)
|
|
398
|
+
: false;
|
|
229
399
|
}
|
|
230
400
|
|
|
231
401
|
/**
|
|
232
|
-
* @
|
|
233
|
-
* @param {
|
|
234
|
-
* @
|
|
402
|
+
* @param {BlockWithTryBoundary | null} boundary
|
|
403
|
+
* @param {number} request_id
|
|
404
|
+
* @param {(reason: any) => void} reject_fn
|
|
405
|
+
* @returns {void}
|
|
235
406
|
*/
|
|
236
|
-
export
|
|
237
|
-
|
|
238
|
-
|
|
407
|
+
export function register_boundary_deferred(boundary, request_id, reject_fn) {
|
|
408
|
+
if (boundary !== null && !is_destroyed(boundary) && boundary.s?.rd) {
|
|
409
|
+
boundary.s.rd(request_id, reject_fn);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
239
412
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
413
|
+
/**
|
|
414
|
+
* @param {BlockWithTryBoundary | null} boundary
|
|
415
|
+
* @param {Block} block
|
|
416
|
+
* @returns {void}
|
|
417
|
+
*/
|
|
418
|
+
export function register_boundary_paused_block(boundary, block) {
|
|
419
|
+
if (boundary !== null && !is_destroyed(boundary) && boundary.s?.pb) {
|
|
420
|
+
boundary.s.pb(block);
|
|
421
|
+
}
|
|
244
422
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Context } from './context.js';
|
|
2
2
|
|
|
3
3
|
export type Component = {
|
|
4
|
+
b: null | Block;
|
|
4
5
|
c: null | Map<Context<any>, any>;
|
|
5
6
|
e: null | Array<{
|
|
6
7
|
b: Block;
|
|
@@ -22,6 +23,7 @@ export type Tracked<V = any> = {
|
|
|
22
23
|
a: { get?: Function; set?: Function };
|
|
23
24
|
b: Block;
|
|
24
25
|
c: number;
|
|
26
|
+
d: null | DeferredTrackedEntry[];
|
|
25
27
|
f: number;
|
|
26
28
|
__v: V;
|
|
27
29
|
readonly [0]: V;
|
|
@@ -31,6 +33,11 @@ export type Tracked<V = any> = {
|
|
|
31
33
|
[Symbol.iterator](): Iterator<V | Tracked<V>>;
|
|
32
34
|
};
|
|
33
35
|
|
|
36
|
+
export type DeferredTrackedEntry = {
|
|
37
|
+
b: Block; // boundary block
|
|
38
|
+
r: number; // request version id
|
|
39
|
+
};
|
|
40
|
+
|
|
34
41
|
export type Derived = {
|
|
35
42
|
DO_NOT_ACCESS_THIS_OBJECT_DIRECTLY?: true;
|
|
36
43
|
a: { get?: Function; set?: Function };
|
|
@@ -64,6 +71,24 @@ export type Block = {
|
|
|
64
71
|
t: (() => {}) | null;
|
|
65
72
|
};
|
|
66
73
|
|
|
74
|
+
export type TryBoundaryState = {
|
|
75
|
+
p: boolean; // whether pending_fn exists
|
|
76
|
+
b: () => number; // begin request, returns request id
|
|
77
|
+
r: (request_id: number, show_resolved_branch?: boolean) => boolean; // complete request, returns whether the request was active
|
|
78
|
+
c: ((error: any) => void) | null; // catch function
|
|
79
|
+
rd: (request_id: number, reject_fn: (reason: any) => void) => void; // register deferred reject function
|
|
80
|
+
pb: (block: Block) => void; // register paused block
|
|
81
|
+
rp: (old_request_id: number) => number; // replace request, returns new request id
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export type BlockWithTryBoundary = Omit<Block, 's'> & {
|
|
85
|
+
s: TryBoundaryState;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type BlockWithTryBoundaryAndCatch = Omit<BlockWithTryBoundary, 's'> & {
|
|
89
|
+
s: TryBoundaryState & { c: NonNullable<TryBoundaryState['c']> };
|
|
90
|
+
};
|
|
91
|
+
|
|
67
92
|
export type CompatApi = {
|
|
68
93
|
createRoot: () => void;
|
|
69
94
|
createComponent: (node: any, children_fn: () => any) => void;
|
|
@@ -81,6 +106,7 @@ declare global {
|
|
|
81
106
|
value?: string;
|
|
82
107
|
};
|
|
83
108
|
__click?: () => void;
|
|
109
|
+
__ripple_block?: Block;
|
|
84
110
|
}
|
|
85
111
|
|
|
86
112
|
interface Event {
|