svelte 5.43.7 → 5.43.9
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/compiler/index.js +1 -1
- package/package.json +1 -1
- package/src/compiler/phases/1-parse/utils/create.js +1 -2
- package/src/compiler/phases/2-analyze/index.js +269 -187
- package/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +0 -4
- package/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +29 -15
- package/src/compiler/phases/3-transform/client/visitors/ConstTag.js +50 -14
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +5 -14
- package/src/compiler/phases/3-transform/client/visitors/SnippetBlock.js +2 -8
- package/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js +12 -2
- package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/ConstTag.js +25 -1
- package/src/compiler/phases/3-transform/server/visitors/EachBlock.js +2 -6
- package/src/compiler/phases/3-transform/server/visitors/Fragment.js +8 -1
- package/src/compiler/phases/3-transform/server/visitors/IfBlock.js +1 -5
- package/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js +0 -5
- package/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js +3 -10
- package/src/compiler/phases/3-transform/server/visitors/shared/component.js +1 -6
- package/src/compiler/phases/nodes.js +4 -0
- package/src/compiler/phases/scope.js +8 -4
- package/src/compiler/utils/builders.js +1 -1
- package/src/internal/client/dom/blocks/each.js +156 -236
- package/src/internal/client/reactivity/deriveds.js +5 -2
- package/src/internal/client/reactivity/effects.js +33 -37
- package/src/internal/client/reactivity/sources.js +17 -9
- package/src/version.js +1 -1
|
@@ -48,7 +48,11 @@ export function SvelteBoundary(node, context) {
|
|
|
48
48
|
if (child.type === 'ConstTag') {
|
|
49
49
|
has_const = true;
|
|
50
50
|
if (!context.state.options.experimental.async) {
|
|
51
|
-
context.visit(child, {
|
|
51
|
+
context.visit(child, {
|
|
52
|
+
...context.state,
|
|
53
|
+
consts: const_tags,
|
|
54
|
+
scope: context.state.scopes.get(node.fragment) ?? context.state.scope
|
|
55
|
+
});
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
}
|
|
@@ -101,7 +105,13 @@ export function SvelteBoundary(node, context) {
|
|
|
101
105
|
nodes.push(child);
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
const block = /** @type {BlockStatement} */ (
|
|
108
|
+
const block = /** @type {BlockStatement} */ (
|
|
109
|
+
context.visit(
|
|
110
|
+
{ ...node.fragment, nodes },
|
|
111
|
+
// Since we're creating a new fragment the reference in scopes can't match, so we gotta attach the right scope manually
|
|
112
|
+
{ ...context.state, scope: context.state.scopes.get(node.fragment) ?? context.state.scope }
|
|
113
|
+
)
|
|
114
|
+
);
|
|
105
115
|
|
|
106
116
|
if (!context.state.options.experimental.async) {
|
|
107
117
|
block.body.unshift(...const_tags);
|
|
@@ -105,7 +105,7 @@ export function process_children(nodes, initial, is_element, context) {
|
|
|
105
105
|
is_element &&
|
|
106
106
|
// In case it's wrapped in async the async logic will want to skip sibling nodes up until the end, hence we cannot make this controlled
|
|
107
107
|
// TODO switch this around and instead optimize for elements with a single block child and not require extra comments (neither for async nor normally)
|
|
108
|
-
!
|
|
108
|
+
!node.metadata.expression.is_async()
|
|
109
109
|
) {
|
|
110
110
|
node.metadata.is_controlled = true;
|
|
111
111
|
} else {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/** @import { AST } from '#compiler' */
|
|
3
3
|
/** @import { ComponentContext } from '../types.js' */
|
|
4
4
|
import * as b from '#compiler/builders';
|
|
5
|
+
import { extract_identifiers } from '../../../../utils/ast.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @param {AST.ConstTag} node
|
|
@@ -11,6 +12,29 @@ export function ConstTag(node, context) {
|
|
|
11
12
|
const declaration = node.declaration.declarations[0];
|
|
12
13
|
const id = /** @type {Pattern} */ (context.visit(declaration.id));
|
|
13
14
|
const init = /** @type {Expression} */ (context.visit(declaration.init));
|
|
15
|
+
const has_await = node.metadata.expression.has_await;
|
|
14
16
|
|
|
15
|
-
context.state.
|
|
17
|
+
if (has_await || context.state.async_consts) {
|
|
18
|
+
const run = (context.state.async_consts ??= {
|
|
19
|
+
id: b.id(context.state.scope.generate('promises')),
|
|
20
|
+
thunks: []
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const identifiers = extract_identifiers(declaration.id);
|
|
24
|
+
const bindings = context.state.scope.get_bindings(declaration);
|
|
25
|
+
|
|
26
|
+
for (const identifier of identifiers) {
|
|
27
|
+
context.state.init.push(b.let(identifier.name));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const assignment = b.assignment('=', id, init);
|
|
31
|
+
run.thunks.push(b.thunk(b.block([b.stmt(assignment)]), has_await));
|
|
32
|
+
|
|
33
|
+
const blocker = b.member(run.id, b.literal(run.thunks.length - 1), true);
|
|
34
|
+
for (const binding of bindings) {
|
|
35
|
+
binding.blocker = blocker;
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
context.state.init.push(b.const(id, init));
|
|
39
|
+
}
|
|
16
40
|
}
|
|
@@ -34,11 +34,7 @@ export function EachBlock(node, context) {
|
|
|
34
34
|
|
|
35
35
|
const new_body = /** @type {BlockStatement} */ (context.visit(node.body)).body;
|
|
36
36
|
|
|
37
|
-
if (node.body)
|
|
38
|
-
each.push(
|
|
39
|
-
// TODO get rid of fragment.has_await
|
|
40
|
-
...(node.body.metadata.has_await ? [create_async_block(b.block(new_body))] : new_body)
|
|
41
|
-
);
|
|
37
|
+
if (node.body) each.push(...new_body);
|
|
42
38
|
|
|
43
39
|
const for_loop = b.for(
|
|
44
40
|
b.declaration('let', [
|
|
@@ -61,7 +57,7 @@ export function EachBlock(node, context) {
|
|
|
61
57
|
b.if(
|
|
62
58
|
b.binary('!==', b.member(array_id, 'length'), b.literal(0)),
|
|
63
59
|
b.block([open, for_loop]),
|
|
64
|
-
|
|
60
|
+
fallback
|
|
65
61
|
)
|
|
66
62
|
);
|
|
67
63
|
} else {
|
|
@@ -28,7 +28,8 @@ export function Fragment(node, context) {
|
|
|
28
28
|
init: [],
|
|
29
29
|
template: [],
|
|
30
30
|
namespace,
|
|
31
|
-
skip_hydration_boundaries: is_standalone
|
|
31
|
+
skip_hydration_boundaries: is_standalone,
|
|
32
|
+
async_consts: undefined
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
for (const node of hoisted) {
|
|
@@ -42,5 +43,11 @@ export function Fragment(node, context) {
|
|
|
42
43
|
|
|
43
44
|
process_children(trimmed, { ...context, state });
|
|
44
45
|
|
|
46
|
+
if (state.async_consts && state.async_consts.thunks.length > 0) {
|
|
47
|
+
state.init.push(
|
|
48
|
+
b.var(state.async_consts.id, b.call('$$renderer.run', b.array(state.async_consts.thunks)))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
return b.block([...state.init, ...build_template(state.template)]);
|
|
46
53
|
}
|
|
@@ -25,11 +25,7 @@ export function IfBlock(node, context) {
|
|
|
25
25
|
|
|
26
26
|
const is_async = node.metadata.expression.is_async();
|
|
27
27
|
|
|
28
|
-
const has_await =
|
|
29
|
-
node.metadata.expression.has_await ||
|
|
30
|
-
// TODO get rid of this stuff
|
|
31
|
-
node.consequent.metadata.has_await ||
|
|
32
|
-
node.alternate?.metadata.has_await;
|
|
28
|
+
const has_await = node.metadata.expression.has_await;
|
|
33
29
|
|
|
34
30
|
if (is_async || has_await) {
|
|
35
31
|
statement = create_async_block(
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
/** @import { ComponentContext } from '../types.js' */
|
|
4
4
|
import { dev } from '../../../../state.js';
|
|
5
5
|
import * as b from '#compiler/builders';
|
|
6
|
-
import { create_async_block } from './shared/utils.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* @param {AST.SnippetBlock} node
|
|
@@ -16,10 +15,6 @@ export function SnippetBlock(node, context) {
|
|
|
16
15
|
/** @type {BlockStatement} */ (context.visit(node.body))
|
|
17
16
|
);
|
|
18
17
|
|
|
19
|
-
if (node.body.metadata.has_await) {
|
|
20
|
-
fn.body = b.block([create_async_block(fn.body)]);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
18
|
// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone
|
|
24
19
|
fn.___snippet = true;
|
|
25
20
|
|
|
@@ -7,8 +7,7 @@ import {
|
|
|
7
7
|
block_open,
|
|
8
8
|
block_open_else,
|
|
9
9
|
build_attribute_value,
|
|
10
|
-
build_template
|
|
11
|
-
create_async_block
|
|
10
|
+
build_template
|
|
12
11
|
} from './shared/utils.js';
|
|
13
12
|
|
|
14
13
|
/**
|
|
@@ -43,14 +42,11 @@ export function SvelteBoundary(node, context) {
|
|
|
43
42
|
);
|
|
44
43
|
const pending = b.call(callee, b.id('$$renderer'));
|
|
45
44
|
const block = /** @type {BlockStatement} */ (context.visit(node.fragment));
|
|
46
|
-
const statement = node.fragment.metadata.has_await
|
|
47
|
-
? create_async_block(b.block([block]))
|
|
48
|
-
: block;
|
|
49
45
|
context.state.template.push(
|
|
50
46
|
b.if(
|
|
51
47
|
callee,
|
|
52
48
|
b.block(build_template([block_open_else, b.stmt(pending), block_close])),
|
|
53
|
-
b.block(build_template([block_open,
|
|
49
|
+
b.block(build_template([block_open, block, block_close]))
|
|
54
50
|
)
|
|
55
51
|
);
|
|
56
52
|
} else {
|
|
@@ -70,9 +66,6 @@ export function SvelteBoundary(node, context) {
|
|
|
70
66
|
}
|
|
71
67
|
} else {
|
|
72
68
|
const block = /** @type {BlockStatement} */ (context.visit(node.fragment));
|
|
73
|
-
|
|
74
|
-
? create_async_block(b.block([block]))
|
|
75
|
-
: block;
|
|
76
|
-
context.state.template.push(block_open, statement, block_close);
|
|
69
|
+
context.state.template.push(block_open, block, block_close);
|
|
77
70
|
}
|
|
78
71
|
}
|
|
@@ -244,12 +244,7 @@ export function build_inline_component(node, expression, context) {
|
|
|
244
244
|
params.push(pattern);
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
const slot_fn = b.arrow(
|
|
248
|
-
params,
|
|
249
|
-
node.fragment.metadata.has_await
|
|
250
|
-
? b.block([create_async_block(b.block(block.body))])
|
|
251
|
-
: b.block(block.body)
|
|
252
|
-
);
|
|
247
|
+
const slot_fn = b.arrow(params, b.block(block.body));
|
|
253
248
|
|
|
254
249
|
if (slot_name === 'default' && !has_children_prop) {
|
|
255
250
|
if (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { BinaryOperator, ClassDeclaration, Expression, FunctionDeclaration, Identifier, ImportDeclaration, MemberExpression, LogicalOperator, Node, Pattern, UnaryOperator, VariableDeclarator, Super, SimpleLiteral, FunctionExpression, ArrowFunctionExpression } from 'estree' */
|
|
2
2
|
/** @import { Context, Visitor } from 'zimmerframe' */
|
|
3
3
|
/** @import { AST, BindingKind, DeclarationKind } from '#compiler' */
|
|
4
4
|
import is_reference from 'is-reference';
|
|
@@ -108,7 +108,10 @@ export class Binding {
|
|
|
108
108
|
/** @type {Array<{ node: Identifier; path: AST.SvelteNode[] }>} */
|
|
109
109
|
references = [];
|
|
110
110
|
|
|
111
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* (Re)assignments of this binding. Includes declarations such as `function x() {}`.
|
|
113
|
+
* @type {Array<{ value: Expression; scope: Scope }>}
|
|
114
|
+
*/
|
|
112
115
|
assignments = [];
|
|
113
116
|
|
|
114
117
|
/**
|
|
@@ -135,9 +138,10 @@ export class Binding {
|
|
|
135
138
|
/**
|
|
136
139
|
* Instance-level declarations may follow (or contain) a top-level `await`. In these cases,
|
|
137
140
|
* any reads that occur in the template must wait for the corresponding promise to resolve
|
|
138
|
-
* otherwise the initial value will not have been assigned
|
|
141
|
+
* otherwise the initial value will not have been assigned.
|
|
142
|
+
* It is a member expression of the form `$$blockers[n]`.
|
|
139
143
|
* TODO the blocker is set during transform which feels a bit grubby
|
|
140
|
-
* @type {
|
|
144
|
+
* @type {MemberExpression & { object: Identifier, property: SimpleLiteral & { value: number } } | null}
|
|
141
145
|
*/
|
|
142
146
|
blocker = null;
|
|
143
147
|
|
|
@@ -181,7 +181,7 @@ export function logical(operator, left, right) {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
|
-
* @param {'
|
|
184
|
+
* @param {ESTree.VariableDeclaration['kind']} kind
|
|
185
185
|
* @param {ESTree.VariableDeclarator[]} declarations
|
|
186
186
|
* @returns {ESTree.VariableDeclaration}
|
|
187
187
|
*/
|