Skip to content

Commit a7a7d1e

Browse files
authored
fix: take blockers of components into account (#17153)
Fixes #17122
1 parent a0c7c3b commit a7a7d1e

File tree

10 files changed

+59
-5
lines changed

10 files changed

+59
-5
lines changed

.changeset/ready-flies-invite.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: take blockers of components into account

packages/svelte/src/compiler/phases/1-parse/state/element.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ export default function element(parser) {
242242
parser.allow_whitespace();
243243
}
244244

245+
if (element.type === 'Component') {
246+
element.metadata.expression = new ExpressionMetadata();
247+
}
248+
245249
if (element.type === 'SvelteComponent') {
246250
const index = element.attributes.findIndex(
247251
/** @param {any} attr */
@@ -257,6 +261,7 @@ export default function element(parser) {
257261
}
258262

259263
element.expression = get_attribute_expression(definition);
264+
element.metadata.expression = new ExpressionMetadata();
260265
}
261266

262267
if (element.type === 'SvelteElement') {

packages/svelte/src/compiler/phases/2-analyze/visitors/Component.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,11 @@ export function Component(node, context) {
1616
binding !== null &&
1717
(binding.kind !== 'normal' || node.name.includes('.'));
1818

19+
if (binding) {
20+
node.metadata.expression.has_state = node.metadata.dynamic;
21+
node.metadata.expression.dependencies.add(binding);
22+
node.metadata.expression.references.add(binding);
23+
}
24+
1925
visit_component(node, context);
2026
}

packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteComponent.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function SvelteComponent(node, context) {
1212
w.svelte_component_deprecated(node);
1313
}
1414

15-
context.visit(node.expression);
15+
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
1616

1717
visit_component(node, context);
1818
}

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ export function build_component(node, component_name, context) {
451451
};
452452
}
453453

454+
if (node.type !== 'SvelteSelf') {
455+
// Component name itself could be blocked on async values
456+
memoizer.check_blockers(node.metadata.expression);
457+
}
458+
454459
const statements = [...snippet_declarations, ...memoizer.deriveds(context.state.analysis.runes)];
455460

456461
if (is_component_dynamic) {

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,17 +325,26 @@ export function build_inline_component(node, expression, context) {
325325
);
326326
}
327327

328+
if (node.type !== 'SvelteSelf') {
329+
// Component name itself could be blocked on async values
330+
optimiser.check_blockers(node.metadata.expression);
331+
}
332+
328333
const is_async = optimiser.is_async();
329334

330335
if (is_async) {
331336
statement = create_async_block(
332-
b.block([optimiser.apply(), statement]),
337+
b.block([
338+
optimiser.apply(),
339+
dynamic && custom_css_props.length === 0
340+
? b.stmt(b.call('$$renderer.push', empty_comment))
341+
: b.empty,
342+
statement
343+
]),
333344
optimiser.blockers(),
334345
optimiser.has_await
335346
);
336-
}
337-
338-
if (dynamic && custom_css_props.length === 0) {
347+
} else if (dynamic && custom_css_props.length === 0) {
339348
context.state.template.push(empty_comment);
340349
}
341350

packages/svelte/src/compiler/types/template.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ export namespace AST {
308308
type: 'Component';
309309
/** @internal */
310310
metadata: {
311+
expression: ExpressionMetadata;
311312
scopes: Record<string, Scope>;
312313
dynamic: boolean;
313314
/** The set of locally-defined snippets that this component tag could render,
@@ -355,6 +356,7 @@ export namespace AST {
355356
expression: Expression;
356357
/** @internal */
357358
metadata: {
359+
expression: ExpressionMetadata;
358360
scopes: Record<string, Scope>;
359361
/** The set of locally-defined snippets that this component tag could render,
360362
* used for CSS pruning purposes */
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hi
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
mode: ['async-server', 'client', 'hydrate'],
6+
ssrHtml: 'Hi Hi Hi Hi',
7+
async test({ assert, target }) {
8+
await tick();
9+
assert.htmlEqual(target.innerHTML, 'Hi Hi Hi Hi');
10+
}
11+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
import Component from './Component.svelte'
3+
const X = $derived(await Promise.resolve(Component))
4+
const Y = await Promise.resolve(Component)
5+
</script>
6+
7+
<X />
8+
<svelte:component this={X} />
9+
<Y />
10+
<svelte:component this={Y} />

0 commit comments

Comments
 (0)