diff --git a/packages/svelte/src/internal/server/dev.js b/packages/svelte/src/internal/server/dev.js index cc43d642fe..16ca9a494b 100644 --- a/packages/svelte/src/internal/server/dev.js +++ b/packages/svelte/src/internal/server/dev.js @@ -50,6 +50,10 @@ function print_error(payload, parent, child) { payload.head.out += ``; } +export function reset_elements() { + parent = null; +} + /** * @param {Payload} payload * @param {string} tag diff --git a/packages/svelte/src/internal/server/index.js b/packages/svelte/src/internal/server/index.js index 422784d765..c43620e025 100644 --- a/packages/svelte/src/internal/server/index.js +++ b/packages/svelte/src/internal/server/index.js @@ -16,6 +16,7 @@ import { current_component, pop, push } from './context.js'; import { EMPTY_COMMENT, BLOCK_CLOSE, BLOCK_OPEN } from './hydration.js'; import { validate_store } from '../shared/validate.js'; import { is_boolean_attribute, is_void } from '../../utils.js'; +import { reset_elements } from './dev.js'; // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 // https://infra.spec.whatwg.org/#noncharacter @@ -100,6 +101,9 @@ export function render(component, options = {}) { on_destroy = []; payload.out += BLOCK_OPEN; + // prevent parent/child element state being corrupted by a bad render + reset_elements(); + if (options.context) { push(); /** @type {Component} */ (current_component).c = options.context; diff --git a/packages/svelte/tests/runtime-legacy/samples/store-dev-mode-error/main.svelte b/packages/svelte/tests/runtime-legacy/samples/store-dev-mode-error/main.svelte index 849de85acf..13c0f4cf29 100644 --- a/packages/svelte/tests/runtime-legacy/samples/store-dev-mode-error/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/store-dev-mode-error/main.svelte @@ -2,4 +2,4 @@ export let count; - \ No newline at end of file + diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index 358da8e829..b14c0bdf4b 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -60,6 +60,7 @@ export interface RuntimeTest = Record void | Promise; test_ssr?: (args: { logs: any[]; assert: Assert }) => void | Promise; @@ -70,6 +71,7 @@ export interface RuntimeTest = Record { + errors.push(...args); + }; + } } try { @@ -317,15 +327,6 @@ async function run_test_variant( config.before_test?.(); - // eslint-disable-next-line no-console - const error = console.error; - // eslint-disable-next-line no-console - console.error = (error) => { - if (typeof error === 'string' && error.startsWith('Hydration failed')) { - throw new Error(error); - } - }; - let instance: any; let props: any; let hydrate_fn: Function = () => { @@ -363,9 +364,6 @@ async function run_test_variant( }); } - // eslint-disable-next-line no-console - console.error = error; - if (config.error) { unintended_error = true; assert.fail('Expected a runtime error'); @@ -401,6 +399,7 @@ async function run_test_variant( compileOptions, logs, warnings, + errors, hydrate: hydrate_fn }); } @@ -424,6 +423,14 @@ async function run_test_variant( assert.fail('Received unexpected warnings'); } + if (config.errors) { + assert.deepEqual(errors, config.errors); + } else if (errors.length && console.error === console_error) { + unintended_error = true; + console_error.apply(console, errors); + assert.fail('Received unexpected errors'); + } + assert_html_equal( target.innerHTML, '', diff --git a/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js b/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js index e537add382..d815d10fc7 100644 --- a/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/invalid-html-ssr/_config.js @@ -1,12 +1,5 @@ import { test } from '../../test'; -let console_error = console.error; - -/** - * @type {any[]} - */ -const log = []; - export default test({ compileOptions: { dev: true @@ -18,27 +11,10 @@ export default test({ mode: ['hydrate'], - before_test() { - console.error = (x) => { - log.push(x); - }; - }, - - after_test() { - console.error = console_error; - log.length = 0; - }, - - async test({ assert }) { - assert.equal( - log[0].split('\n')[0], - 'node_invalid_placement_ssr: `

` (main.svelte:6:0) cannot contain `

` (h1.svelte:1:0)' - ); - assert.equal( - log[1].split('\n')[0], - 'node_invalid_placement_ssr: `
` (main.svelte:9:0) cannot contain `` (form.svelte:1:0)' - ); - }, + errors: [ + 'node_invalid_placement_ssr: `

` (main.svelte:6:0) cannot contain `

` (h1.svelte:1:0)\n\nThis can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.', + 'node_invalid_placement_ssr: `` (main.svelte:9:0) cannot contain `` (form.svelte:1:0)\n\nThis can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.' + ], warnings: [ 'Hydration failed because the initial UI does not match what was rendered on the server'