Fix runtime effect issues

pull/9417/head
Dominic Gannaway 3 years ago
parent 6d7caf3fd3
commit 1e81913a50

@ -251,6 +251,8 @@ export const function_visitor = (node, context) => {
const in_constructor = parent.type === 'MethodDefinition' && parent.kind === 'constructor'; const in_constructor = parent.type === 'MethodDefinition' && parent.kind === 'constructor';
state = { ...context.state, in_constructor }; state = { ...context.state, in_constructor };
} else {
state = { ...context.state, in_constructor: false };
} }
if (metadata?.hoistable === true) { if (metadata?.hoistable === true) {

@ -343,7 +343,13 @@ function destroy_references(signal) {
if (references !== null) { if (references !== null) {
let i; let i;
for (i = 0; i < references.length; i++) { for (i = 0; i < references.length; i++) {
destroy_signal(references[i]); const reference = references[i];
if ((reference.flags & IS_EFFECT) !== 0) {
destroy_signal(reference);
} else {
remove_consumer(reference, 0, true);
reference.dependencies = null;
}
} }
} }
} }
@ -710,7 +716,7 @@ export function exposable(fn) {
export function get(signal) { export function get(signal) {
const flags = signal.flags; const flags = signal.flags;
if ((flags & DESTROYED) !== 0) { if ((flags & DESTROYED) !== 0) {
return /** @type {V} */ (UNINITIALIZED); return signal.value;
} }
if (is_signal_exposed && current_should_capture_signal) { if (is_signal_exposed && current_should_capture_signal) {
@ -1156,6 +1162,11 @@ export function managed_pre_effect(init, sync) {
* @returns {import('./types.js').EffectSignal} * @returns {import('./types.js').EffectSignal}
*/ */
export function pre_effect(init) { export function pre_effect(init) {
if (current_effect === null) {
throw new Error(
'The Svelte $effect.pre rune can only be used during component initialisation.'
);
}
const sync = current_effect !== null && (current_effect.flags & RENDER_EFFECT) !== 0; const sync = current_effect !== null && (current_effect.flags & RENDER_EFFECT) !== 0;
return internal_create_effect( return internal_create_effect(
PRE_EFFECT, PRE_EFFECT,

@ -0,0 +1,13 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<button>10</button>`,
ssrHtml: `<button>0</button>`,
async test({ assert, target }) {
flushSync();
assert.htmlEqual(target.innerHTML, `<button>10</button>`);
}
});

@ -0,0 +1,14 @@
<script>
class Counter {
count = $state(0);
constructor() {
$effect(() => {
this.count = 10;
});
}
}
const counter = new Counter();
</script>
<button on:click={() => counter.count++}>{counter.count}</button>

@ -0,0 +1,13 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<button>10</button>`,
ssrHtml: `<button>0</button>`,
async test({ assert, target }) {
flushSync();
assert.htmlEqual(target.innerHTML, `<button>10</button>`);
}
});

@ -0,0 +1,22 @@
<script>
class Counter {
#count = $state(0);
constructor() {
$effect(() => {
this.#count = 10;
});
}
getCount() {
return this.#count;
}
increment() {
this.#count++;
}
}
const counter = new Counter();
</script>
<button on:click={() => counter.increment()}>{counter.getCount()}</button>

@ -0,0 +1,19 @@
import { test } from '../../test';
import { flushSync } from 'svelte';
export default test({
get props() {
return { log: [] };
},
async test({ assert, target, component }) {
const [b1] = target.querySelectorAll('button');
flushSync(() => {
b1.click();
});
flushSync(() => {
b1.click();
});
assert.deepEqual(component.log, ['init 0', 'cleanup 2', 'init 2', 'cleanup 4', 'init 4']);
}
});

@ -0,0 +1,17 @@
<script>
const {log} = $props();
let count = $state(0);
$effect(() => {
let double = $derived(count * 2)
log.push('init ' + double);
return () => {
log.push('cleanup ' + double);
};
})
</script>
<button on:click={() => count++ }>Click</button>
Loading…
Cancel
Save