Skip to content

Commit 4999734

Browse files
fix: check boundary pending attribute at runtime on server (#16855)
* fix: check boundary `pending` attribute at runtime on server * fix --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 4f653dd commit 4999734

File tree

5 files changed

+55
-13
lines changed

5 files changed

+55
-13
lines changed

.changeset/lazy-cooks-return.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: check boundary `pending` attribute at runtime on server

packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
block_open,
88
block_open_else,
99
build_attribute_value,
10+
build_template,
1011
create_async_block
1112
} from './shared/utils.js';
1213

@@ -19,6 +20,11 @@ export function SvelteBoundary(node, context) {
1920
const pending_attribute = /** @type {AST.Attribute} */ (
2021
node.attributes.find((node) => node.type === 'Attribute' && node.name === 'pending')
2122
);
23+
const is_pending_attr_nullish =
24+
pending_attribute &&
25+
typeof pending_attribute.value === 'object' &&
26+
!Array.isArray(pending_attribute.value) &&
27+
!context.state.scope.evaluate(pending_attribute.value.expression).is_defined;
2228

2329
const pending_snippet = /** @type {AST.SnippetBlock} */ (
2430
node.fragment.nodes.find(
@@ -27,20 +33,38 @@ export function SvelteBoundary(node, context) {
2733
);
2834

2935
if (pending_attribute || pending_snippet) {
30-
const pending = pending_attribute
31-
? b.call(
32-
build_attribute_value(
33-
pending_attribute.value,
34-
context,
35-
(expression) => expression,
36-
false,
37-
true
38-
),
39-
b.id('$$renderer')
36+
if (pending_attribute && is_pending_attr_nullish && !pending_snippet) {
37+
const callee = build_attribute_value(
38+
pending_attribute.value,
39+
context,
40+
(expression) => expression,
41+
false,
42+
true
43+
);
44+
const pending = b.call(callee, b.id('$$renderer'));
45+
const block = /** @type {BlockStatement} */ (context.visit(node.fragment));
46+
context.state.template.push(
47+
b.if(
48+
callee,
49+
b.block(build_template([block_open_else, pending, block_close])),
50+
b.block(build_template([block_open, block, block_close]))
4051
)
41-
: /** @type {BlockStatement} */ (context.visit(pending_snippet.body));
42-
43-
context.state.template.push(block_open_else, pending, block_close);
52+
);
53+
} else {
54+
const pending = pending_attribute
55+
? b.call(
56+
build_attribute_value(
57+
pending_attribute.value,
58+
context,
59+
(expression) => expression,
60+
false,
61+
true
62+
),
63+
b.id('$$renderer')
64+
)
65+
: /** @type {BlockStatement} */ (context.visit(pending_snippet.body));
66+
context.state.template.push(block_open_else, pending, block_close);
67+
}
4468
} else {
4569
const block = /** @type {BlockStatement} */ (context.visit(node.fragment));
4670
const statement = node.fragment.metadata.has_await

packages/svelte/src/compiler/phases/scope.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ class Evaluation {
260260
break;
261261
}
262262

263+
if (binding.initial?.type === 'SnippetBlock') {
264+
this.is_defined = true;
265+
this.is_known = false;
266+
break;
267+
}
268+
263269
if (!binding.updated && binding.initial !== null && !is_prop) {
264270
binding.scope.evaluate(/** @type {Expression} */ (binding.initial), this.values);
265271
break;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!--[--><!--[--><!---->awaited<!--]--><!--]-->
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let pending = null;
3+
</script>
4+
<svelte:boundary {pending}>
5+
{await 'awaited'}
6+
</svelte:boundary>

0 commit comments

Comments
 (0)