diff --git a/packages/svelte/src/internal/client/dev/tracing.js b/packages/svelte/src/internal/client/dev/tracing.js index 65c6379625..5834f5bffd 100644 --- a/packages/svelte/src/internal/client/dev/tracing.js +++ b/packages/svelte/src/internal/client/dev/tracing.js @@ -26,23 +26,6 @@ function log_entry(signal, entry) { return; } - if (signal.trace) { - var previous_captured_signals = captured_signals; - var captured = new Set(); - set_captured_signals(captured); - - try { - untrack(signal.trace); - } finally { - set_captured_signals(previous_captured_signals); - } - - if (captured.size > 0) { - for (const dep of captured) log_entry(dep); - return; - } - } - const type = (signal.f & DERIVED) !== 0 ? '$derived' : '$state'; const current_reaction = /** @type {Reaction} */ (active_reaction); const dirty = signal.wv > current_reaction.wv || current_reaction.wv === 0; @@ -103,19 +86,25 @@ export function trace(label, fn) { var value = fn(); var time = (performance.now() - start).toFixed(2); + var prefix = untrack(label); + if (!effect_tracking()) { // eslint-disable-next-line no-console - console.log(`${label()} %cran outside of an effect (${time}ms)`, 'color: grey'); + console.log(`${prefix} %cran outside of an effect (${time}ms)`, 'color: grey'); } else if (tracing_expressions.entries.size === 0) { // eslint-disable-next-line no-console - console.log(`${label()} %cno reactive dependencies (${time}ms)`, 'color: grey'); + console.log(`${prefix} %cno reactive dependencies (${time}ms)`, 'color: grey'); } else { // eslint-disable-next-line no-console - console.group(`${label()} %c(${time}ms)`, 'color: grey'); + console.group(`${prefix} %c(${time}ms)`, 'color: grey'); - for (const [signal, traces] of tracing_expressions.entries) { - log_entry(signal, traces); - } + var entries = tracing_expressions.entries; + + untrack(() => { + for (const [signal, traces] of entries) { + log_entry(signal, traces); + } + }); tracing_expressions = null; diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index c06705ce24..9544060959 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -39,6 +39,7 @@ import { set_dev_current_component_function } from './context.js'; import { handle_error, invoke_error_boundary } from './error-handling.js'; +import { snapshot } from '../shared/clone.js'; let is_flushing = false; @@ -769,6 +770,7 @@ export function get(signal) { if ( DEV && tracing_mode_flag && + !untracking && tracing_expressions !== null && active_reaction !== null && tracing_expressions.reaction === active_reaction diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index c0d1177a82..11ea9f6dda 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -3,7 +3,7 @@ import { setImmediate } from 'node:timers/promises'; import { globSync } from 'tinyglobby'; import { createClassComponent } from 'svelte/legacy'; import { proxy } from 'svelte/internal/client'; -import { flushSync, hydrate, mount, unmount } from 'svelte'; +import { flushSync, hydrate, mount, unmount, untrack } from 'svelte'; import { render } from 'svelte/server'; import { afterAll, assert, beforeAll } from 'vitest'; import { compile_directory, fragments } from '../helpers.js'; diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/Entry.svelte b/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/Entry.svelte new file mode 100644 index 0000000000..a22f006dcc --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/Entry.svelte @@ -0,0 +1,8 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/_config.js new file mode 100644 index 0000000000..94cd9d8aaf --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/_config.js @@ -0,0 +1,40 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; +import { normalise_trace_logs } from '../../../helpers.js'; + +export default test({ + compileOptions: { + dev: true + }, + + test({ assert, target, logs }) { + assert.deepEqual(normalise_trace_logs(logs), [ + { log: 'effect' }, + { log: '$state', highlighted: true }, + { log: 'array', highlighted: false }, + { log: [{ id: 1, hi: true }] }, + // this _doesn't_ appear in the browser, but it does appear during tests + // and i cannot for the life of me figure out why. this does at least + // test that we don't log `array[0].id` etc + { log: '$state', highlighted: true }, + { log: 'array[0]', highlighted: false }, + { log: { id: 1, hi: true } } + ]); + + logs.length = 0; + + const button = target.querySelector('button'); + button?.click(); + flushSync(); + + assert.deepEqual(normalise_trace_logs(logs), [ + { log: 'effect' }, + { log: '$state', highlighted: true }, + { log: 'array', highlighted: false }, + { log: [{ id: 1, hi: false }] }, + { log: '$state', highlighted: false }, + { log: 'array[0]', highlighted: false }, + { log: { id: 1, hi: false } } + ]); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/main.svelte b/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/main.svelte new file mode 100644 index 0000000000..e89ee7d9bc --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/inspect-trace-each/main.svelte @@ -0,0 +1,11 @@ + + + + +{#each array as entry (entry.id)} + +{/each}