Skip to content

Commit 00a8db4

Browse files
committed
[Svelte] Migrate from destroy to unmount for Svelte 5 compatibility when controller is disconnected
1 parent bb715d1 commit 00a8db4

File tree

4 files changed

+41
-12
lines changed

4 files changed

+41
-12
lines changed

src/Svelte/assets/dist/render_controller.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ export default class extends Controller<Element & {
1515
intro: BooleanConstructor;
1616
};
1717
connect(): Promise<void>;
18-
disconnect(): void;
19-
_destroyIfExists(): void;
18+
disconnect(): Promise<void>;
19+
_destroyIfExists(): Promise<void>;
2020
private dispatchEvent;
2121
private mountSvelteComponent;
2222
}

src/Svelte/assets/dist/render_controller.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class default_1 extends Controller {
77
this.intro = this.introValue ?? undefined;
88
this.dispatchEvent('connect');
99
const Component = window.resolveSvelteComponent(this.componentValue);
10-
this._destroyIfExists();
10+
await this._destroyIfExists();
1111
this.app = await this.mountSvelteComponent(Component, {
1212
target: this.element,
1313
props: this.props,
@@ -18,13 +18,19 @@ class default_1 extends Controller {
1818
component: Component,
1919
});
2020
}
21-
disconnect() {
22-
this._destroyIfExists();
21+
async disconnect() {
22+
await this._destroyIfExists();
2323
this.dispatchEvent('unmount');
2424
}
25-
_destroyIfExists() {
25+
async _destroyIfExists() {
2626
if (this.element.root !== undefined) {
27-
this.element.root.$destroy();
27+
const { unmount } = await import('svelte');
28+
if (unmount) {
29+
unmount(this.element.root);
30+
}
31+
else {
32+
this.element.root.$destroy();
33+
}
2834
delete this.element.root;
2935
}
3036
}

src/Svelte/assets/src/render_controller.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export default class extends Controller<Element & { root?: SvelteComponent }> {
2727

2828
const Component = window.resolveSvelteComponent(this.componentValue);
2929

30-
this._destroyIfExists();
30+
await this._destroyIfExists();
3131

3232
this.app = await this.mountSvelteComponent(Component, {
3333
target: this.element,
@@ -42,14 +42,21 @@ export default class extends Controller<Element & { root?: SvelteComponent }> {
4242
});
4343
}
4444

45-
disconnect() {
46-
this._destroyIfExists();
45+
async disconnect() {
46+
await this._destroyIfExists();
4747
this.dispatchEvent('unmount');
4848
}
4949

50-
_destroyIfExists() {
50+
async _destroyIfExists() {
5151
if (this.element.root !== undefined) {
52-
this.element.root.$destroy();
52+
// @ts-ignore
53+
const { unmount } = await import('svelte');
54+
if (unmount) {
55+
// `unmount` is only available in Svelte >= 5
56+
unmount(this.element.root);
57+
} else {
58+
this.element.root.$destroy();
59+
}
5360
delete this.element.root;
5461
}
5562
}

src/Svelte/assets/test/render_controller.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,22 @@ describe('SvelteController', () => {
8484
await waitFor(() => expect(component.innerHTML).toContain('<div><div>Hello without props</div></div>'));
8585
});
8686

87+
it('unmount correctly', async () => {
88+
const container = mountDOM(`
89+
<div data-testid="component" id="container"
90+
data-controller="check svelte"
91+
data-svelte-component-value="SvelteComponent" />
92+
`);
93+
94+
const component = getByTestId(container, 'component');
95+
96+
application = startStimulus();
97+
98+
await waitFor(() => expect(component.innerHTML).toContain('<div><div>Hello without props</div></div>'));
99+
component.remove();
100+
await waitFor(() => expect(component).not.toBeInTheDocument());
101+
});
102+
87103
// Disabled for Svelte 5 : https://github.com/sveltejs/svelte/issues/11280
88104
it.skipIf(SVELTE_VERSION >= '5')('connect with props and intro', async () => {
89105
const container = mountDOM(`

0 commit comments

Comments
 (0)