diff --git a/.changeset/heavy-lions-tap.md b/.changeset/heavy-lions-tap.md new file mode 100644 index 0000000000..5cf97fda77 --- /dev/null +++ b/.changeset/heavy-lions-tap.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: lift "flushSync cannot be called in effects" restriction diff --git a/documentation/docs/98-reference/.generated/client-errors.md b/documentation/docs/98-reference/.generated/client-errors.md index 3f1cb8f76b..fa8533928a 100644 --- a/documentation/docs/98-reference/.generated/client-errors.md +++ b/documentation/docs/98-reference/.generated/client-errors.md @@ -136,16 +136,6 @@ Often when encountering this issue, the value in question shouldn't be state (fo Cannot use `fork(...)` unless the `experimental.async` compiler option is `true` ``` -### flush_sync_in_effect - -``` -Cannot use `flushSync` inside an effect -``` - -The `flushSync()` function can be used to flush any pending effects synchronously. It cannot be used if effects are currently being flushed — in other words, you can call it after a state change but _not_ inside an effect. - -This restriction only applies when using the `experimental.async` option, which will be active by default in Svelte 6. - ### fork_discarded ``` diff --git a/packages/svelte/messages/client-errors/errors.md b/packages/svelte/messages/client-errors/errors.md index ae7d811b2e..b75dc9cc6a 100644 --- a/packages/svelte/messages/client-errors/errors.md +++ b/packages/svelte/messages/client-errors/errors.md @@ -104,14 +104,6 @@ Often when encountering this issue, the value in question shouldn't be state (fo > Cannot use `fork(...)` unless the `experimental.async` compiler option is `true` -## flush_sync_in_effect - -> Cannot use `flushSync` inside an effect - -The `flushSync()` function can be used to flush any pending effects synchronously. It cannot be used if effects are currently being flushed — in other words, you can call it after a state change but _not_ inside an effect. - -This restriction only applies when using the `experimental.async` option, which will be active by default in Svelte 6. - ## fork_discarded > Cannot commit a fork that was already discarded diff --git a/packages/svelte/src/internal/client/errors.js b/packages/svelte/src/internal/client/errors.js index 8a5fde4f3b..c132382569 100644 --- a/packages/svelte/src/internal/client/errors.js +++ b/packages/svelte/src/internal/client/errors.js @@ -245,22 +245,6 @@ export function experimental_async_fork() { } } -/** - * Cannot use `flushSync` inside an effect - * @returns {never} - */ -export function flush_sync_in_effect() { - if (DEV) { - const error = new Error(`flush_sync_in_effect\nCannot use \`flushSync\` inside an effect\nhttps://svelte.dev/e/flush_sync_in_effect`); - - error.name = 'Svelte error'; - - throw error; - } else { - throw new Error(`https://svelte.dev/e/flush_sync_in_effect`); - } -} - /** * Cannot commit a fork that was already discarded * @returns {never} diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index 84308ef3ed..1f35d382fb 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -528,11 +528,6 @@ export class Batch { * @returns {T} */ export function flushSync(fn) { - if (async_mode_flag && active_effect !== null) { - // We disallow this because it creates super-hard to reason about stack trace and because it's generally a bad idea - e.flush_sync_in_effect(); - } - var was_flushing_sync = is_flushing_sync; is_flushing_sync = true; diff --git a/packages/svelte/tests/runtime-runes/samples/flush-sync-inside-attachment/_config.js b/packages/svelte/tests/runtime-runes/samples/flush-sync-inside-attachment/_config.js index ec8858b2c6..b34a90e901 100644 --- a/packages/svelte/tests/runtime-runes/samples/flush-sync-inside-attachment/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/flush-sync-inside-attachment/_config.js @@ -1,12 +1,8 @@ -import { async_mode } from '../../../helpers'; import { test } from '../../test'; export default test({ - // In legacy mode this succeeds and logs 'hello' - // In async mode this throws an error because flushSync is called inside an effect async test({ assert, target, logs }) { assert.htmlEqual(target.innerHTML, `
hello
`); assert.deepEqual(logs, ['hello']); - }, - runtime_error: async_mode ? 'flush_sync_in_effect' : undefined + } });