diff --git a/.changeset/gold-pens-sell.md b/.changeset/gold-pens-sell.md
new file mode 100644
index 000000000000..945c795890d8
--- /dev/null
+++ b/.changeset/gold-pens-sell.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+feat: support migrating `svelte:self`
diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js
index 393b34f5b2ad..e0d8cd55dff9 100644
--- a/packages/svelte/src/compiler/migrate/index.js
+++ b/packages/svelte/src/compiler/migrate/index.js
@@ -27,9 +27,10 @@ const style_placeholder = '/*$$__STYLE_CONTENT__$$*/';
* May throw an error if the code is too complex to migrate automatically.
*
* @param {string} source
+ * @param {{filename?: string}} [options]
* @returns {{ code: string; }}
*/
-export function migrate(source) {
+export function migrate(source, { filename } = {}) {
try {
// Blank CSS, could contain SCSS or similar that needs a preprocessor.
// Since we don't care about CSS in this migration, we'll just ignore it.
@@ -41,7 +42,7 @@ export function migrate(source) {
});
reset_warning_filter(() => false);
- reset(source, { filename: 'migrate.svelte' });
+ reset(source, { filename: filename ?? 'migrate.svelte' });
let parsed = parse(source);
@@ -68,6 +69,7 @@ export function migrate(source) {
let state = {
scope: analysis.instance.scope,
analysis,
+ filename,
str,
indent,
props: [],
@@ -90,12 +92,14 @@ export function migrate(source) {
createBubbler: analysis.root.unique('createBubbler').name,
bubble: analysis.root.unique('bubble').name,
passive: analysis.root.unique('passive').name,
- nonpassive: analysis.root.unique('nonpassive').name
+ nonpassive: analysis.root.unique('nonpassive').name,
+ svelte_self: analysis.root.unique('SvelteSelf').name
},
legacy_imports: new Set(),
script_insertions: new Set(),
derived_components: new Map(),
- derived_labeled_statements: new Set()
+ derived_labeled_statements: new Set(),
+ has_svelte_self: false
};
if (parsed.module) {
@@ -122,12 +126,21 @@ export function migrate(source) {
state.script_insertions.size > 0 ||
state.props.length > 0 ||
analysis.uses_rest_props ||
- analysis.uses_props;
+ analysis.uses_props ||
+ state.has_svelte_self;
if (!parsed.instance && need_script) {
str.appendRight(0, '
+
+{#if false}
+
+
+
+
+ child
+
+
+ child
+
+
+ child
+
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/tests/migrate/samples/svelte-self-name-conflict/output.svelte b/packages/svelte/tests/migrate/samples/svelte-self-name-conflict/output.svelte
new file mode 100644
index 000000000000..827d06c3a32c
--- /dev/null
+++ b/packages/svelte/tests/migrate/samples/svelte-self-name-conflict/output.svelte
@@ -0,0 +1,22 @@
+
+
+{#if false}
+
+
+
+
+ child
+
+
+ child
+
+
+ child
+
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/_config.js b/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/_config.js
new file mode 100644
index 000000000000..9c8f6f9c78f1
--- /dev/null
+++ b/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/_config.js
@@ -0,0 +1,5 @@
+import { test } from '../../test';
+
+export default test({
+ skip_filename: true
+});
diff --git a/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/input.svelte b/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/input.svelte
new file mode 100644
index 000000000000..340b257fc1be
--- /dev/null
+++ b/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/input.svelte
@@ -0,0 +1,3 @@
+{#if false}
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/output.svelte b/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/output.svelte
new file mode 100644
index 000000000000..59ae5ff19ca0
--- /dev/null
+++ b/packages/svelte/tests/migrate/samples/svelte-self-skip-filename/output.svelte
@@ -0,0 +1,4 @@
+{#if false}
+
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/tests/migrate/samples/svelte-self/input.svelte b/packages/svelte/tests/migrate/samples/svelte-self/input.svelte
new file mode 100644
index 000000000000..09eb5767be9e
--- /dev/null
+++ b/packages/svelte/tests/migrate/samples/svelte-self/input.svelte
@@ -0,0 +1,15 @@
+{#if false}
+
+
+
+
+ child
+
+
+ child
+
+
+ child
+
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/tests/migrate/samples/svelte-self/output.svelte b/packages/svelte/tests/migrate/samples/svelte-self/output.svelte
new file mode 100644
index 000000000000..7e7ebae21595
--- /dev/null
+++ b/packages/svelte/tests/migrate/samples/svelte-self/output.svelte
@@ -0,0 +1,21 @@
+
+
+{#if false}
+
+
+
+
+ child
+
+
+ child
+
+
+ child
+
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/tests/migrate/test.ts b/packages/svelte/tests/migrate/test.ts
index 5aa86a194f0f..e26e8e376bba 100644
--- a/packages/svelte/tests/migrate/test.ts
+++ b/packages/svelte/tests/migrate/test.ts
@@ -4,7 +4,9 @@ import { migrate } from 'svelte/compiler';
import { try_read_file } from '../helpers.js';
import { suite, type BaseTest } from '../suite.js';
-interface ParserTest extends BaseTest {}
+interface ParserTest extends BaseTest {
+ skip_filename?: boolean;
+}
const { test, run } = suite(async (config, cwd) => {
const input = fs
@@ -12,7 +14,9 @@ const { test, run } = suite(async (config, cwd) => {
.replace(/\s+$/, '')
.replace(/\r/g, '');
- const actual = migrate(input).code;
+ const actual = migrate(input, {
+ filename: config.skip_filename ? undefined : `${cwd}/output.svelte`
+ }).code;
// run `UPDATE_SNAPSHOTS=true pnpm test migrate` to update parser tests
if (process.env.UPDATE_SNAPSHOTS || !fs.existsSync(`${cwd}/output.svelte`)) {
diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts
index 22b47d35ecbd..e64abef0c5ca 100644
--- a/packages/svelte/types/index.d.ts
+++ b/packages/svelte/types/index.d.ts
@@ -1264,7 +1264,9 @@ declare module 'svelte/compiler' {
* May throw an error if the code is too complex to migrate automatically.
*
* */
- export function migrate(source: string): {
+ export function migrate(source: string, { filename }?: {
+ filename?: string;
+ } | undefined): {
code: string;
};
namespace Css {
diff --git a/sites/svelte-5-preview/src/lib/Output/Compiler.js b/sites/svelte-5-preview/src/lib/Output/Compiler.js
index ae363682411a..94484ecf3951 100644
--- a/sites/svelte-5-preview/src/lib/Output/Compiler.js
+++ b/sites/svelte-5-preview/src/lib/Output/Compiler.js
@@ -80,7 +80,8 @@ export default class Compiler {
this.worker.postMessage({
id,
type: 'migrate',
- source: file.source
+ source: file.source,
+ filename: `${file.name}.${file.type}`
});
});
}
diff --git a/sites/svelte-5-preview/src/lib/workers/compiler/index.js b/sites/svelte-5-preview/src/lib/workers/compiler/index.js
index 46853c3984b4..9247894dd6e3 100644
--- a/sites/svelte-5-preview/src/lib/workers/compiler/index.js
+++ b/sites/svelte-5-preview/src/lib/workers/compiler/index.js
@@ -133,9 +133,9 @@ function compile({ id, source, options, return_ast }) {
}
/** @param {import("../workers").MigrateMessageData} param0 */
-function migrate({ id, source }) {
+function migrate({ id, source, filename }) {
try {
- const result = svelte.migrate(source);
+ const result = svelte.migrate(source, { filename });
return {
id,