mirror of https://github.com/sveltejs/svelte
parent
0fd39219d3
commit
8bb4083b67
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': minor
|
||||
---
|
||||
|
||||
feat: link top-level `using` declarations in components to lifecycle
|
@ -0,0 +1,26 @@
|
||||
import { teardown } from '../reactivity/effects.js';
|
||||
|
||||
/**
|
||||
* @param {...any} disposables
|
||||
*/
|
||||
export function dispose(...disposables) {
|
||||
teardown(() => {
|
||||
for (const disposable of disposables) {
|
||||
disposable?.[Symbol.dispose]();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* In dev, check that a value used with `using` is in fact disposable. We need this
|
||||
* because we're replacing `using foo = ...` with `const foo = ...` if the
|
||||
* declaration is at the top level of a component
|
||||
* @param {any} value
|
||||
*/
|
||||
export function disposable(value) {
|
||||
if (value != null && !value[Symbol.dispose]) {
|
||||
throw new TypeError('Symbol(Symbol.dispose) is not a function');
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
let { message } = $props();
|
||||
|
||||
using x = {
|
||||
message,
|
||||
[Symbol.dispose]() {
|
||||
console.log(`disposing ${message}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>{x.message}</p>
|
@ -0,0 +1,18 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
// TODO unskip this for applicable node versions, once supported
|
||||
skip: true,
|
||||
|
||||
html: `<button>toggle</button><p>hello</p>`,
|
||||
|
||||
test({ assert, target, logs }) {
|
||||
const [button] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => button.click());
|
||||
assert.htmlEqual(target.innerHTML, `<button>toggle</button>`);
|
||||
|
||||
assert.deepEqual(logs, ['disposing hello']);
|
||||
}
|
||||
});
|
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
import Child from './Child.svelte';
|
||||
|
||||
let message = $state('hello');
|
||||
</script>
|
||||
|
||||
<button onclick={() => message = message ? null : 'hello'}>
|
||||
toggle
|
||||
</button>
|
||||
|
||||
{#if message}
|
||||
<Child {message} />
|
||||
{/if}
|
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true
|
||||
}
|
||||
});
|
@ -0,0 +1,28 @@
|
||||
import 'svelte/internal/disclose-version';
|
||||
|
||||
Using_top_level[$.FILENAME] = 'packages/svelte/tests/snapshot/samples/using-top-level/index.svelte';
|
||||
|
||||
import * as $ from 'svelte/internal/client';
|
||||
|
||||
var root = $.add_locations($.from_html(`<p> </p>`), Using_top_level[$.FILENAME], [[12, 0]]);
|
||||
|
||||
export default function Using_top_level($$anchor, $$props) {
|
||||
$.check_target(new.target);
|
||||
$.push($$props, true, Using_top_level);
|
||||
|
||||
const x = $.disposable({
|
||||
message: $$props.message,
|
||||
[Symbol.dispose]() {
|
||||
console.log(...$.log_if_contains_state('log', `disposing ${$$props.message}`));
|
||||
}
|
||||
});
|
||||
|
||||
var p = root();
|
||||
var text = $.child(p, true);
|
||||
|
||||
$.reset(p);
|
||||
$.template_effect(() => $.set_text(text, x.message));
|
||||
$.append($$anchor, p);
|
||||
$.dispose(x);
|
||||
return $.pop({ ...$.legacy_api() });
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
Using_top_level[$.FILENAME] = 'packages/svelte/tests/snapshot/samples/using-top-level/index.svelte';
|
||||
|
||||
import * as $ from 'svelte/internal/server';
|
||||
|
||||
function Using_top_level($$payload, $$props) {
|
||||
$.push(Using_top_level);
|
||||
|
||||
let { message } = $$props;
|
||||
|
||||
using x = {
|
||||
message,
|
||||
[Symbol.dispose]() {
|
||||
console.log(`disposing ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
$$payload.out += `<p>`;
|
||||
$.push_element($$payload, 'p', 12, 0);
|
||||
$$payload.out += `${$.escape(x.message)}</p>`;
|
||||
$.pop_element();
|
||||
$.pop();
|
||||
}
|
||||
|
||||
Using_top_level.render = function () {
|
||||
throw new Error('Component.render(...) is no longer valid in Svelte 5. See https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes for more information');
|
||||
};
|
||||
|
||||
export default Using_top_level;
|
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
let { message } = $props();
|
||||
|
||||
using x = {
|
||||
message,
|
||||
[Symbol.dispose]() {
|
||||
console.log(`disposing ${message}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>{x.message}</p>
|
Loading…
Reference in new issue