diff --git a/.changeset/light-crews-deny.md b/.changeset/light-crews-deny.md new file mode 100644 index 0000000000..295357a74e --- /dev/null +++ b/.changeset/light-crews-deny.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: avoid reporting inspections when an exception occurs diff --git a/packages/svelte/src/internal/client/dev/inspect.js b/packages/svelte/src/internal/client/dev/inspect.js index c5765cfc07..e13ef470cf 100644 --- a/packages/svelte/src/internal/client/dev/inspect.js +++ b/packages/svelte/src/internal/client/dev/inspect.js @@ -1,3 +1,4 @@ +import { UNINITIALIZED } from '../../../constants.js'; import { snapshot } from '../../shared/clone.js'; import { inspect_effect, validate_effect } from '../reactivity/effects.js'; @@ -12,7 +13,24 @@ export function inspect(get_value, inspector = console.log) { let initial = true; inspect_effect(() => { - inspector(initial ? 'init' : 'update', ...snapshot(get_value(), true)); + /** @type {any} */ + var value = UNINITIALIZED; + + // Capturing the value might result in an exception due to the inspect effect being + // sync and thus operating on stale data. In the case we encounter an exception we + // can bail-out of reporting the value. Instead we simply console.error the error + // so at least it's known that an error occured, but we don't stop execution + try { + value = get_value(); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } + + if (value !== UNINITIALIZED) { + inspector(initial ? 'init' : 'update', ...snapshot(value, true)); + } + initial = false; }); } diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-exception/Component.svelte b/packages/svelte/tests/runtime-runes/samples/inspect-exception/Component.svelte new file mode 100644 index 0000000000..3902bd008c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/inspect-exception/Component.svelte @@ -0,0 +1,7 @@ + +

{a}

diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js new file mode 100644 index 0000000000..57caf6e08d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js @@ -0,0 +1,16 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true + }, + + async test({ assert, target, logs }) { + const b1 = target.querySelector('button'); + b1?.click(); + flushSync(); + + assert.deepEqual(logs, ['init', 'a', 'init', 'b']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-exception/main.svelte b/packages/svelte/tests/runtime-runes/samples/inspect-exception/main.svelte new file mode 100644 index 0000000000..98b15708f7 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/inspect-exception/main.svelte @@ -0,0 +1,13 @@ + + + + +{#if s.a} + {#each Object.entries(s.a) as [k, v]} + + {/each} +{/if}