fix: wrap `abort` in `without_reactive_context` (#16570)

* fix: wrap `abort` in `without_reactive_context`

* only call without_reactive_context when the controller exists

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/16587/head
Paolo Ricciuti 4 weeks ago committed by GitHub
parent 97f263c3d4
commit 548ad7b7eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: wrap `abort` in `without_reactive_context`

@ -42,6 +42,7 @@ import { get_next_sibling } from '../dom/operations.js';
import { component_context, dev_current_component_function, dev_stack } from '../context.js'; import { component_context, dev_current_component_function, dev_stack } from '../context.js';
import { Batch, schedule_effect } from './batch.js'; import { Batch, schedule_effect } from './batch.js';
import { flatten } from './async.js'; import { flatten } from './async.js';
import { without_reactive_context } from '../dom/elements/bindings/shared.js';
/** /**
* @param {'$effect' | '$effect.pre' | '$inspect'} rune * @param {'$effect' | '$effect.pre' | '$inspect'} rune
@ -406,7 +407,13 @@ export function destroy_effect_children(signal, remove_dom = false) {
signal.first = signal.last = null; signal.first = signal.last = null;
while (effect !== null) { while (effect !== null) {
effect.ac?.abort(STALE_REACTION); const controller = effect.ac;
if (controller !== null) {
without_reactive_context(() => {
controller.abort(STALE_REACTION);
});
}
var next = effect.next; var next = effect.next;

@ -46,6 +46,7 @@ import { Batch, batch_deriveds, flushSync, schedule_effect } from './reactivity/
import { handle_error } from './error-handling.js'; import { handle_error } from './error-handling.js';
import { UNINITIALIZED } from '../../constants.js'; import { UNINITIALIZED } from '../../constants.js';
import { captured_signals } from './legacy.js'; import { captured_signals } from './legacy.js';
import { without_reactive_context } from './dom/elements/bindings/shared.js';
export let is_updating_effect = false; export let is_updating_effect = false;
@ -278,7 +279,10 @@ export function update_reaction(reaction) {
update_version = ++read_version; update_version = ++read_version;
if (reaction.ac !== null) { if (reaction.ac !== null) {
reaction.ac.abort(STALE_REACTION); without_reactive_context(() => {
/** @type {AbortController} */ (reaction.ac).abort(STALE_REACTION);
});
reaction.ac = null; reaction.ac = null;
} }

@ -0,0 +1,12 @@
import { ok, test } from '../../test';
import { flushSync } from 'svelte';
export default test({
async test({ assert, target, errors }) {
const btn = target.querySelector('button');
flushSync(() => {
btn?.click();
});
assert.deepEqual(errors, []);
}
});

@ -0,0 +1,24 @@
<script lang="ts">
import { getAbortSignal } from "svelte";
let aborted = $state(0);
let count = $state(0);
let der = $derived.by(()=>{
const signal = getAbortSignal();
signal.addEventListener("abort", () => {
try{
aborted++;
}catch(e){
console.error(e);
}
});
return count;
})
</script>
{der}
<button onclick={() => count++}></button>
Loading…
Cancel
Save