Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/ten-vans-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: migrated snippet shadowing prop and let directive removal
39 changes: 38 additions & 1 deletion packages/svelte/src/compiler/migrate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,11 @@ function migrate_slot_usage(node, path, state) {
let snippet_name = 'children';
let snippet_props = [];

// if we stop the transform because the name is not correct we don't want to
// remove the let directive and they could come before the name
let removal_queue = [];
let slot_name_found = false;

for (let attribute of node.attributes) {
if (
attribute.type === 'Attribute' &&
Expand All @@ -1112,6 +1117,24 @@ function migrate_slot_usage(node, path, state) {
);
return;
}
if (parent?.type === 'Component' || parent?.type === 'SvelteComponent') {
for (let attribute of parent.attributes) {
if (attribute.type === 'Attribute' || attribute.type === 'BindDirective') {
if (attribute.name === snippet_name) {
state.str.appendLeft(
node.start,
`<!-- @migration-task: migrate this slot by hand, \`${snippet_name}\` would shadow a prop on the parent component -->\n${state.indent}`
);
return;
}
}
}
}
slot_name_found = true;
// flush the queue after we found the name
for (let remove_let of removal_queue) {
remove_let();
}
state.str.remove(attribute.start, attribute.end);
}
if (attribute.type === 'LetDirective') {
Expand All @@ -1121,7 +1144,21 @@ function migrate_slot_usage(node, path, state) {
? `: ${state.str.original.substring(/** @type {number} */ (attribute.expression.start), /** @type {number} */ (attribute.expression.end))}`
: '')
);
state.str.remove(attribute.start, attribute.end);
function remove_let() {
state.str.remove(attribute.start, attribute.end);
}
// if we didn't find the name yet we just add to the queue else we call immediately
if (slot_name_found) {
remove_let();
} else {
removal_queue.push(remove_let);
}
}
}

if (!slot_name_found && removal_queue.length > 0) {
for (let remove_let of removal_queue) {
remove_let();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,31 @@
<svelte:fragment slot="stuff">
cool
</svelte:fragment>
</Comp>


<!-- don't remove the let directive if we don't migrate -->

<Comp>
<div let:shoudl_stay slot="cool:stuff">
cool
</div>
</Comp>

<Comp>
<div let:shoudl_stay slot="cool stuff">
cool
</div>
</Comp>

<Comp>
<svelte:fragment let:shoudl_stay slot="cool:stuff">
cool
</svelte:fragment>
</Comp>

<Comp>
<svelte:fragment let:shoudl_stay slot="cool stuff">
cool
</svelte:fragment>
</Comp>
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,35 @@
cool

{/snippet}
</Comp>


<!-- don't remove the let directive if we don't migrate -->

<Comp>
<!-- @migration-task: migrate this slot by hand, `cool:stuff` is an invalid identifier -->
<div let:shoudl_stay slot="cool:stuff">
cool
</div>
</Comp>

<Comp>
<!-- @migration-task: migrate this slot by hand, `cool stuff` is an invalid identifier -->
<div let:shoudl_stay slot="cool stuff">
cool
</div>
</Comp>

<Comp>
<!-- @migration-task: migrate this slot by hand, `cool:stuff` is an invalid identifier -->
<svelte:fragment let:shoudl_stay slot="cool:stuff">
cool
</svelte:fragment>
</Comp>

<Comp>
<!-- @migration-task: migrate this slot by hand, `cool stuff` is an invalid identifier -->
<svelte:fragment let:shoudl_stay slot="cool stuff">
cool
</svelte:fragment>
</Comp>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script>
import Comp from "./Component.svelte";
</script>

<Comp stuff="cool">
<div slot="stuff">
cool
</div>
</Comp>

<Comp stuff="cool">
<svelte:fragment slot="stuff">
cool
</svelte:fragment>
</Comp>

<!-- don't remove the let if we are not migrating -->

<Comp stuff="cool">
<div let:should_stay slot="stuff">
cool
</div>
</Comp>

<Comp stuff="cool">
<svelte:fragment let:should_stay slot="stuff">
cool
</svelte:fragment>
</Comp>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script>
import Comp from "./Component.svelte";
</script>

<Comp stuff="cool">
<!-- @migration-task: migrate this slot by hand, `stuff` would shadow a prop on the parent component -->
<div slot="stuff">
cool
</div>
</Comp>

<Comp stuff="cool">
<!-- @migration-task: migrate this slot by hand, `stuff` would shadow a prop on the parent component -->
<svelte:fragment slot="stuff">
cool
</svelte:fragment>
</Comp>

<!-- don't remove the let if we are not migrating -->

<Comp stuff="cool">
<!-- @migration-task: migrate this slot by hand, `stuff` would shadow a prop on the parent component -->
<div let:should_stay slot="stuff">
cool
</div>
</Comp>

<Comp stuff="cool">
<!-- @migration-task: migrate this slot by hand, `stuff` would shadow a prop on the parent component -->
<svelte:fragment let:should_stay slot="stuff">
cool
</svelte:fragment>
</Comp>