Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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/chatty-gorillas-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: add migration task when there's a variable named that would conflict with a rune
50 changes: 50 additions & 0 deletions packages/svelte/src/compiler/migrate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ export function migrate(source, { filename, use_ts } = {}) {

insertion_point = state.props_insertion_point;

/**
* @param {"derived"|"props"|"bindable"} rune
*/
function check_rune_binding(rune) {
const has_rune_binding = !!state.scope.get(rune);
if (has_rune_binding) {
throw new MigrationError(
`migrating this component would require adding a \`$${rune}\` rune but there's already a variable named ${rune}.\n Rename the variable and try again or migrate by hand.`
);
}
}

if (state.props.length > 0 || analysis.uses_rest_props || analysis.uses_props) {
const has_many_props = state.props.length > 3;
const newline_separator = `\n${indent}${indent}`;
Expand All @@ -253,6 +265,7 @@ export function migrate(source, { filename, use_ts } = {}) {
let prop_str =
prop.local === prop.exported ? prop.local : `${prop.exported}: ${prop.local}`;
if (prop.bindable) {
check_rune_binding('bindable');
prop_str += ` = $bindable(${prop.init})`;
} else if (prop.init) {
prop_str += ` = ${prop.init}`;
Expand Down Expand Up @@ -300,11 +313,13 @@ export function migrate(source, { filename, use_ts } = {}) {
if (type) {
props_declaration = `${type}\n\n${indent}${props_declaration}`;
}
check_rune_binding('props');
props_declaration = `${props_declaration}${type ? `: ${type_name}` : ''} = $props();`;
} else {
if (type) {
props_declaration = `${state.props.length > 0 ? `${type}\n\n${indent}` : ''}/** @type {${state.props.length > 0 ? type_name : ''}${analysis.uses_props || analysis.uses_rest_props ? `${state.props.length > 0 ? ' & ' : ''}{ [key: string]: any }` : ''}} */\n${indent}${props_declaration}`;
}
check_rune_binding('props');
props_declaration = `${props_declaration} = $props();`;
}

Expand Down Expand Up @@ -361,13 +376,15 @@ export function migrate(source, { filename, use_ts } = {}) {
: insertion_point;

if (state.derived_components.size > 0) {
check_rune_binding('derived');
str.appendRight(
insertion_point,
`\n${indent}${[...state.derived_components.entries()].map(([init, name]) => `const ${name} = $derived(${init});`).join(`\n${indent}`)}\n`
);
}

if (state.derived_conflicting_slots.size > 0) {
check_rune_binding('derived');
str.appendRight(
insertion_point,
`\n${indent}${[...state.derived_conflicting_slots.entries()].map(([name, init]) => `const ${name} = $derived(${init});`).join(`\n${indent}`)}\n`
Expand Down Expand Up @@ -652,6 +669,18 @@ const instance_script = {
continue;
}

/**
* @param {"state"|"derived"} rune
*/
function check_rune_binding(rune) {
const has_rune_binding = !!state.scope.get(rune);
if (has_rune_binding) {
throw new MigrationError(
`can't migrate \`${state.str.original.substring(/** @type {number} */ (node.start), node.end)}\` to \`$${rune}\` because there's a variable named ${rune}.\n Rename the variable and try again or migrate by hand.`
);
}
}

// state
if (declarator.init) {
let { start, end } = /** @type {{ start: number, end: number }} */ (declarator.init);
Expand All @@ -661,6 +690,8 @@ const instance_script = {
while (state.str.original[end - 1] !== ')') end += 1;
}

check_rune_binding('state');

state.str.prependLeft(start, '$state(');
state.str.appendRight(end, ')');
} else {
Expand Down Expand Up @@ -755,6 +786,8 @@ const instance_script = {
}
}

check_rune_binding('derived');

// Someone wrote a `$: { ... }` statement which we can turn into a `$derived`
state.str.appendRight(
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
Expand Down Expand Up @@ -795,6 +828,8 @@ const instance_script = {
}
}
} else {
check_rune_binding('state');

state.str.prependLeft(
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
' = $state('
Expand Down Expand Up @@ -858,6 +893,18 @@ const instance_script = {

next();

/**
* @param {"state"|"derived"} rune
*/
function check_rune_binding(rune) {
const has_rune_binding = state.scope.get(rune);
if (has_rune_binding) {
throw new MigrationError(
`can't migrate \`$: ${state.str.original.substring(/** @type {number} */ (node.body.start), node.body.end)}\` to \`$${rune}\` because there's a variable named ${rune}.\n Rename the variable and try again or migrate by hand.`
);
}
}

if (
node.body.type === 'ExpressionStatement' &&
node.body.expression.type === 'AssignmentExpression'
Expand All @@ -878,6 +925,8 @@ const instance_script = {
node.body.expression.right
);

check_rune_binding('derived');

// $derived
state.str.update(
/** @type {number} */ (node.start),
Expand All @@ -902,6 +951,7 @@ const instance_script = {
} else {
for (const binding of reassigned_bindings) {
if (binding && (ids.includes(binding.node) || expression_ids.length === 0)) {
check_rune_binding('state');
const init =
binding.kind === 'state'
? ' = $state()'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
let bindable;
export let something;
</script>

<input bind:value={something} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- @migration-task Error while migrating Svelte code: migrating this component would require adding a `$bindable` rune but there's already a variable named bindable.
Rename the variable and try again or migrate by hand. -->
<script>
let bindable;
export let something;
</script>

<input bind:value={something} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script>
let name = 'world';

let derived;

$: other = name;
</script>

<input bind:value={name} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- @migration-task Error while migrating Svelte code: can't migrate `$: other = name;` to `$derived` because there's a variable named derived.
Rename the variable and try again or migrate by hand. -->
<script>
let name = 'world';

let derived;

$: other = name;
</script>

<input bind:value={name} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
let derived;
</script>

<svelte:component this={derived} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- @migration-task Error while migrating Svelte code: migrating this component would require adding a `$derived` rune but there's already a variable named derived.
Rename the variable and try again or migrate by hand. -->
<script>
let derived;
</script>

<svelte:component this={derived} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
let derived;
</script>
<Component>
<slot name="derived" slot="derived" />
</Component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- @migration-task Error while migrating Svelte code: This migration would change the name of a slot making the component unusable -->
<script>
let derived;
</script>
<Component>
<slot name="derived" slot="derived" />
</Component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
let name = 'world';

let derived;

let other;
$: other = name;
</script>

<input bind:value={name} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!-- @migration-task Error while migrating Svelte code: can't migrate `let other;` to `$derived` because there's a variable named derived.
Rename the variable and try again or migrate by hand. -->
<script>
let name = 'world';

let derived;

let other;
$: other = name;
</script>

<input bind:value={name} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<script>
let props;
export let something;
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!-- @migration-task Error while migrating Svelte code: migrating this component would require adding a `$props` rune but there's already a variable named props.
Rename the variable and try again or migrate by hand. -->
<script>
let props;
export let something;
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let state = 'world';

let other;
</script>

<input bind:value={other} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- @migration-task Error while migrating Svelte code: can't migrate `let other;` to `$state` because there's a variable named state.
Rename the variable and try again or migrate by hand. -->
<script>
let state = 'world';

let other;
</script>

<input bind:value={other} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let state = 'world';

let other = 42;
</script>

<input bind:value={other} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- @migration-task Error while migrating Svelte code: can't migrate `let other = 42;` to `$state` because there's a variable named state.
Rename the variable and try again or migrate by hand. -->
<script>
let state = 'world';

let other = 42;
</script>

<input bind:value={other} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
logs: [
'One or more `@migration-task` comments were added to `output.svelte`, please check them and complete the migration manually.'
],
errors: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let state = 'world';

$: other = 42;
</script>

<input bind:value={other} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- @migration-task Error while migrating Svelte code: can't migrate `$: other = 42;` to `$state` because there's a variable named state.
Rename the variable and try again or migrate by hand. -->
<script>
let state = 'world';

$: other = 42;
</script>

<input bind:value={other} />
Loading