From 94b4268ce30078cdb29f5af3e12b671005718d09 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 24 Apr 2024 09:30:55 -0400 Subject: [PATCH] chore: markdown runtime errors/warnings (#11304) * chore: markdown runtime warnings * on second thoughts * start adding errors too * lint * centralise --- .prettierignore | 3 ++ eslint.config.js | 3 ++ .../svelte/messages/client-errors/effects.md | 3 ++ .../messages/client-errors/lifecycle.md | 7 +++ .../messages/client-warnings/warnings.md | 7 +++ .../messages/shared-warnings/warnings.md | 3 ++ .../svelte/scripts/process-messages/index.js | 4 ++ .../templates/client-errors.js | 17 ++++++ .../templates/client-warnings.js | 17 ++++++ .../templates/shared-warnings.js | 19 +++++++ packages/svelte/src/index-client.js | 13 ++--- .../src/internal/client/dev/ownership.js | 7 ++- packages/svelte/src/internal/client/errors.js | 53 +++++++++++++++++++ packages/svelte/src/internal/client/render.js | 5 +- .../svelte/src/internal/client/runtime.js | 39 +++++++------- .../svelte/src/internal/client/warnings.js | 33 ++++++++++++ .../svelte/src/internal/shared/validate.js | 4 +- .../svelte/src/internal/shared/warnings.js | 21 ++++++++ .../samples/component-nested-deep/_config.js | 2 +- .../samples/destroy-twice/_config.js | 4 +- .../_config.js | 2 +- .../_config.js | 2 +- .../_config.js | 2 +- .../_config.js | 2 +- .../_config.js | 2 +- .../svelte/tests/runtime-legacy/shared.ts | 10 +++- packages/svelte/tests/signals/test.ts | 4 +- 27 files changed, 243 insertions(+), 45 deletions(-) create mode 100644 packages/svelte/messages/client-errors/effects.md create mode 100644 packages/svelte/messages/client-errors/lifecycle.md create mode 100644 packages/svelte/messages/client-warnings/warnings.md create mode 100644 packages/svelte/messages/shared-warnings/warnings.md create mode 100644 packages/svelte/scripts/process-messages/templates/client-errors.js create mode 100644 packages/svelte/scripts/process-messages/templates/client-warnings.js create mode 100644 packages/svelte/scripts/process-messages/templates/shared-warnings.js create mode 100644 packages/svelte/src/internal/client/errors.js create mode 100644 packages/svelte/src/internal/client/warnings.js create mode 100644 packages/svelte/src/internal/shared/warnings.js diff --git a/.prettierignore b/.prettierignore index 4eea07c2e766..0e08fae5e9a7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,6 +5,9 @@ packages/**/config/*.js packages/svelte/messages/**/*.md packages/svelte/src/compiler/errors.js packages/svelte/src/compiler/warnings.js +packages/svelte/src/internal/client/errors.js +packages/svelte/src/internal/client/warnings.js +packages/svelte/src/internal/shared/warnings.js packages/svelte/tests/**/*.svelte packages/svelte/tests/**/_expected* packages/svelte/tests/**/_actual* diff --git a/eslint.config.js b/eslint.config.js index a86f724d34e3..569d237cd8da 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -35,6 +35,9 @@ export default [ '**/tests', 'packages/svelte/scripts/process-messages/templates/*.js', 'packages/svelte/src/compiler/errors.js', + 'packages/svelte/src/internal/client/errors.js', + 'packages/svelte/src/internal/client/warnings.js', + 'packages/svelte/src/internal/shared/warnings.js', 'packages/svelte/compiler/index.js', // documentation can contain invalid examples 'documentation', diff --git a/packages/svelte/messages/client-errors/effects.md b/packages/svelte/messages/client-errors/effects.md new file mode 100644 index 000000000000..f720575c49ee --- /dev/null +++ b/packages/svelte/messages/client-errors/effects.md @@ -0,0 +1,3 @@ +## effect_update_depth_exceeded + +Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops diff --git a/packages/svelte/messages/client-errors/lifecycle.md b/packages/svelte/messages/client-errors/lifecycle.md new file mode 100644 index 000000000000..7b1ce19a0e50 --- /dev/null +++ b/packages/svelte/messages/client-errors/lifecycle.md @@ -0,0 +1,7 @@ +## lifecycle_outside_component + +`%name%(...)` can only be used during component initialisation + +## lifecycle_legacy_only + +`%name%(...)` cannot be used in runes mode diff --git a/packages/svelte/messages/client-warnings/warnings.md b/packages/svelte/messages/client-warnings/warnings.md new file mode 100644 index 000000000000..a3e2b6e3fece --- /dev/null +++ b/packages/svelte/messages/client-warnings/warnings.md @@ -0,0 +1,7 @@ +## lifecycle_double_unmount + +Tried to unmount a component that was not mounted + +## ownership_invalid_binding + +%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent% diff --git a/packages/svelte/messages/shared-warnings/warnings.md b/packages/svelte/messages/shared-warnings/warnings.md new file mode 100644 index 000000000000..07c3fd50bf2b --- /dev/null +++ b/packages/svelte/messages/shared-warnings/warnings.md @@ -0,0 +1,3 @@ +## dynamic_void_element_content + +`` is a void element — it cannot have content diff --git a/packages/svelte/scripts/process-messages/index.js b/packages/svelte/scripts/process-messages/index.js index 80c3a811d977..b02696a1dd3a 100644 --- a/packages/svelte/scripts/process-messages/index.js +++ b/packages/svelte/scripts/process-messages/index.js @@ -220,3 +220,7 @@ function transform(name, dest) { transform('compile-errors', 'src/compiler/errors.js'); transform('compile-warnings', 'src/compiler/warnings.js'); + +transform('client-warnings', 'src/internal/client/warnings.js'); +transform('client-errors', 'src/internal/client/errors.js'); +transform('shared-warnings', 'src/internal/shared/warnings.js'); diff --git a/packages/svelte/scripts/process-messages/templates/client-errors.js b/packages/svelte/scripts/process-messages/templates/client-errors.js new file mode 100644 index 000000000000..c63a22da96a4 --- /dev/null +++ b/packages/svelte/scripts/process-messages/templates/client-errors.js @@ -0,0 +1,17 @@ +import { DEV } from 'esm-env'; + +/** + * MESSAGE + * @param {string} PARAMETER + * @returns {never} + */ +export function CODE(PARAMETER) { + if (DEV) { + const error = new Error(`${'CODE'}\n${MESSAGE}`); + error.name = 'Svelte error'; + throw error; + } else { + // TODO print a link to the documentation + throw new Error('CODE'); + } +} diff --git a/packages/svelte/scripts/process-messages/templates/client-warnings.js b/packages/svelte/scripts/process-messages/templates/client-warnings.js new file mode 100644 index 000000000000..d40a59ec0c8d --- /dev/null +++ b/packages/svelte/scripts/process-messages/templates/client-warnings.js @@ -0,0 +1,17 @@ +import { DEV } from 'esm-env'; + +var bold = 'font-weight: bold'; +var normal = 'font-weight: normal'; + +/** + * MESSAGE + * @param {string} PARAMETER + */ +export function CODE(PARAMETER) { + if (DEV) { + console.warn(`%c[svelte] ${'CODE'}\n%c${MESSAGE}`, bold, normal); + } else { + // TODO print a link to the documentation + console.warn('CODE'); + } +} diff --git a/packages/svelte/scripts/process-messages/templates/shared-warnings.js b/packages/svelte/scripts/process-messages/templates/shared-warnings.js new file mode 100644 index 000000000000..801785f17632 --- /dev/null +++ b/packages/svelte/scripts/process-messages/templates/shared-warnings.js @@ -0,0 +1,19 @@ +import { DEV } from 'esm-env'; + +var bold = 'font-weight: bold'; +var normal = 'font-weight: normal'; + +/** + * MESSAGE + * @param {boolean} trace + * @param {string} PARAMETER + */ +export function CODE(trace, PARAMETER) { + if (DEV) { + console.warn(`%c[svelte] ${'CODE'}\n%c${MESSAGE}`, bold, normal); + if (trace) console.trace('stack trace'); + } else { + // TODO print a link to the documentation + console.warn('CODE'); + } +} diff --git a/packages/svelte/src/index-client.js b/packages/svelte/src/index-client.js index 83fede3863d1..ea909fe4d9e1 100644 --- a/packages/svelte/src/index-client.js +++ b/packages/svelte/src/index-client.js @@ -1,6 +1,7 @@ import { current_component_context, flush_sync, untrack } from './internal/client/runtime.js'; import { is_array } from './internal/client/utils.js'; import { user_effect } from './internal/client/index.js'; +import * as e from './internal/client/errors.js'; /** * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. @@ -18,7 +19,7 @@ import { user_effect } from './internal/client/index.js'; */ export function onMount(fn) { if (current_component_context === null) { - throw new Error('onMount can only be used during component initialisation.'); + e.lifecycle_outside_component('onMount'); } if (current_component_context.l !== null) { @@ -43,7 +44,7 @@ export function onMount(fn) { */ export function onDestroy(fn) { if (current_component_context === null) { - throw new Error('onDestroy can only be used during component initialisation.'); + e.lifecycle_outside_component('onDestroy'); } onMount(() => () => untrack(fn)); @@ -87,7 +88,7 @@ function create_custom_event(type, detail, { bubbles = false, cancelable = false export function createEventDispatcher() { const component_context = current_component_context; if (component_context === null) { - throw new Error('createEventDispatcher can only be used during component initialisation.'); + e.lifecycle_outside_component('createEventDispatcher'); } return (type, detail, options) => { @@ -126,7 +127,7 @@ export function createEventDispatcher() { */ export function beforeUpdate(fn) { if (current_component_context === null) { - throw new Error('beforeUpdate can only be used during component initialisation'); + e.lifecycle_outside_component('beforeUpdate'); } if (current_component_context.l === null) { @@ -150,11 +151,11 @@ export function beforeUpdate(fn) { */ export function afterUpdate(fn) { if (current_component_context === null) { - throw new Error('afterUpdate can only be used during component initialisation.'); + e.lifecycle_outside_component('afterUpdate'); } if (current_component_context.l === null) { - throw new Error('afterUpdate cannot be used in runes mode'); + e.lifecycle_legacy_only('afterUpdate'); } init_update_callbacks(current_component_context).a.push(fn); diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index 30dceab48686..4fac7837fdbd 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -4,6 +4,7 @@ import { STATE_SYMBOL } from '../constants.js'; import { render_effect } from '../reactivity/effects.js'; import { current_component_context, untrack } from '../runtime.js'; import { get_prototype_of } from '../utils.js'; +import * as w from '../warnings.js'; /** @type {Record>} */ const boundaries = {}; @@ -115,10 +116,7 @@ export function add_owner(object, owner, global = false) { let original = get_owner(metadata); if (owner.filename !== component.filename) { - let message = `${component.filename} passed a value to ${owner.filename} with \`bind:\`, but the value is owned by ${original.filename}. Consider creating a binding between ${original.filename} and ${component.filename}`; - - // eslint-disable-next-line no-console - console.warn(message); + w.ownership_invalid_binding(component.filename, owner.filename, original.filename); } } } @@ -234,6 +232,7 @@ export function check_ownership(metadata) { `${component.filename} mutated a value owned by ${original.filename}. This is strongly discouraged` : 'Mutating a value outside the component that created it is strongly discouraged'; + // TODO get rid of this, but implement message overloads first // eslint-disable-next-line no-console console.warn( `${message}. Consider passing values to child components with \`bind:\`, or use a callback instead.` diff --git a/packages/svelte/src/internal/client/errors.js b/packages/svelte/src/internal/client/errors.js new file mode 100644 index 000000000000..a3bbc71b6554 --- /dev/null +++ b/packages/svelte/src/internal/client/errors.js @@ -0,0 +1,53 @@ +/* This file is generated by scripts/process-messages.js. Do not edit! */ + +import { DEV } from 'esm-env'; + +/** + * Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops + * @returns {never} + */ +export function effect_update_depth_exceeded() { + if (DEV) { + const error = new Error(`${"effect_update_depth_exceeded"}\n${"Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops"}`); + + error.name = 'Svelte error'; + throw error; + } else { + // TODO print a link to the documentation + throw new Error("effect_update_depth_exceeded"); + } +} + +/** + * `%name%(...)` can only be used during component initialisation + * @param {string} name + * @returns {never} + */ +export function lifecycle_outside_component(name) { + if (DEV) { + const error = new Error(`${"lifecycle_outside_component"}\n${`\`${name}(...)\` can only be used during component initialisation`}`); + + error.name = 'Svelte error'; + throw error; + } else { + // TODO print a link to the documentation + throw new Error("lifecycle_outside_component"); + } +} + +/** + * `%name%(...)` cannot be used in runes mode + * @param {string} name + * @returns {never} + */ +export function lifecycle_legacy_only(name) { + if (DEV) { + const error = new Error(`${"lifecycle_legacy_only"}\n${`\`${name}(...)\` cannot be used in runes mode`}`); + + error.name = 'Svelte error'; + throw error; + } else { + // TODO print a link to the documentation + throw new Error("lifecycle_legacy_only"); + } +} \ No newline at end of file diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index c1b1316cca64..698935ff44d0 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -19,6 +19,7 @@ import { import { array_from } from './utils.js'; import { handle_event_propagation } from './dom/elements/events.js'; import { reset_head_anchor } from './dom/blocks/svelte-head.js'; +import * as w from './warnings.js'; /** @type {Set} */ export const all_registered_events = new Set(); @@ -269,6 +270,7 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro target.removeEventListener(event_name, bound_event_listener); } root_event_handles.delete(event_handle); + mounted_components.delete(component); }; }); @@ -289,8 +291,9 @@ let mounted_components = new WeakMap(); export function unmount(component) { const fn = mounted_components.get(component); if (DEV && !fn) { + w.lifecycle_double_unmount(); // eslint-disable-next-line no-console - console.warn('Tried to unmount a component that was not mounted.'); + console.trace('stack trace'); } fn?.(); } diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index e8233fbc90b0..c593f79f09a1 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -22,6 +22,7 @@ import { add_owner } from './dev/ownership.js'; import { mutate, set, source } from './reactivity/sources.js'; import { update_derived } from './reactivity/deriveds.js'; import { inspect_captured_signals, inspect_fn, set_inspect_fn } from './dev/inspect.js'; +import * as e from './errors.js'; const FLUSH_MICROTASK = 0; const FLUSH_SYNC = 1; @@ -412,13 +413,7 @@ export function execute_effect(effect) { function infinite_loop_guard() { if (flush_count > 1000) { flush_count = 0; - throw new Error( - 'ERR_SVELTE_TOO_MANY_UPDATES' + - (DEV - ? ': Maximum update depth exceeded. This can happen when a reactive block or effect ' + - 'repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops.' - : '') - ); + e.effect_update_depth_exceeded(); } flush_count++; } @@ -880,12 +875,12 @@ export function is_signal(val) { * @returns {T} */ export function getContext(key) { - const context_map = get_or_init_context_map(); + const context_map = get_or_init_context_map('getContext'); const result = /** @type {T} */ (context_map.get(key)); if (DEV) { // @ts-expect-error - const fn = current_component_context?.function; + const fn = current_component_context.function; if (fn) { add_owner(result, fn, true); } @@ -908,7 +903,7 @@ export function getContext(key) { * @returns {T} */ export function setContext(key, context) { - const context_map = get_or_init_context_map(); + const context_map = get_or_init_context_map('setContext'); context_map.set(key, context); return context; } @@ -922,7 +917,7 @@ export function setContext(key, context) { * @returns {boolean} */ export function hasContext(key) { - const context_map = get_or_init_context_map(); + const context_map = get_or_init_context_map('hasContext'); return context_map.has(key); } @@ -936,7 +931,7 @@ export function hasContext(key) { * @returns {T} */ export function getAllContexts() { - const context_map = get_or_init_context_map(); + const context_map = get_or_init_context_map('getAllContexts'); if (DEV) { // @ts-expect-error @@ -951,16 +946,18 @@ export function getAllContexts() { return /** @type {T} */ (context_map); } -/** @returns {Map} */ -function get_or_init_context_map() { - const component_context = current_component_context; - if (component_context === null) { - throw new Error( - 'ERR_SVELTE_ORPHAN_CONTEXT' + - (DEV ? 'Context can only be used during component initialisation.' : '') - ); +/** + * @param {string} name + * @returns {Map} + */ +function get_or_init_context_map(name) { + if (current_component_context === null) { + e.lifecycle_outside_component(name); } - return (component_context.c ??= new Map(get_parent_context(component_context) || undefined)); + + return (current_component_context.c ??= new Map( + get_parent_context(current_component_context) || undefined + )); } /** diff --git a/packages/svelte/src/internal/client/warnings.js b/packages/svelte/src/internal/client/warnings.js new file mode 100644 index 000000000000..6cf03e5d9851 --- /dev/null +++ b/packages/svelte/src/internal/client/warnings.js @@ -0,0 +1,33 @@ +/* This file is generated by scripts/process-messages.js. Do not edit! */ + +import { DEV } from 'esm-env'; + +var bold = 'font-weight: bold'; +var normal = 'font-weight: normal'; + +/** + * Tried to unmount a component that was not mounted + */ +export function lifecycle_double_unmount() { + if (DEV) { + console.warn(`%c[svelte] ${"lifecycle_double_unmount"}\n%c${"Tried to unmount a component that was not mounted"}`, bold, normal); + } else { + // TODO print a link to the documentation + console.warn("lifecycle_double_unmount"); + } +} + +/** + * %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent% + * @param {string} parent + * @param {string} child + * @param {string} owner + */ +export function ownership_invalid_binding(parent, child, owner) { + if (DEV) { + console.warn(`%c[svelte] ${"ownership_invalid_binding"}\n%c${`${parent} passed a value to ${child} with \`bind:\`, but the value is owned by ${owner}. Consider creating a binding between ${owner} and ${parent}`}`, bold, normal); + } else { + // TODO print a link to the documentation + console.warn("ownership_invalid_binding"); + } +} \ No newline at end of file diff --git a/packages/svelte/src/internal/shared/validate.js b/packages/svelte/src/internal/shared/validate.js index 692a62fa070f..65dde3011c23 100644 --- a/packages/svelte/src/internal/shared/validate.js +++ b/packages/svelte/src/internal/shared/validate.js @@ -1,4 +1,5 @@ import { is_void } from '../../compiler/phases/1-parse/utils/names.js'; +import * as w from './warnings.js'; const snippet_symbol = Symbol.for('svelte.snippet'); @@ -42,8 +43,7 @@ export function validate_component(component_fn) { export function validate_void_dynamic_element(tag_fn) { const tag = tag_fn(); if (tag && is_void(tag)) { - // eslint-disable-next-line no-console - console.warn(` is self-closing and cannot have content.`); + w.dynamic_void_element_content(false, tag); } } diff --git a/packages/svelte/src/internal/shared/warnings.js b/packages/svelte/src/internal/shared/warnings.js new file mode 100644 index 000000000000..7d85dcf154f4 --- /dev/null +++ b/packages/svelte/src/internal/shared/warnings.js @@ -0,0 +1,21 @@ +/* This file is generated by scripts/process-messages.js. Do not edit! */ + +import { DEV } from 'esm-env'; + +var bold = 'font-weight: bold'; +var normal = 'font-weight: normal'; + +/** + * `` is a void element — it cannot have content + * @param {boolean} trace + * @param {string} tag + */ +export function dynamic_void_element_content(trace, tag) { + if (DEV) { + console.warn(`%c[svelte] ${"dynamic_void_element_content"}\n%c${`\`\` is a void element — it cannot have content`}`, bold, normal); + if (trace) console.trace('stack trace'); + } else { + // TODO print a link to the documentation + console.warn("dynamic_void_element_content"); + } +} \ No newline at end of file diff --git a/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js index da6b9c044209..62685edd8dd6 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js @@ -6,5 +6,5 @@ export default test({ unmount(component.l1); }, - warnings: ['Tried to unmount a component that was not mounted.'] + warnings: ['Tried to unmount a component that was not mounted'] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js b/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js index bfdf090cbdf1..d6900ef91d33 100644 --- a/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js @@ -8,7 +8,7 @@ export default test({ }, warnings: [ - 'Tried to unmount a component that was not mounted.', - 'Tried to unmount a component that was not mounted.' + 'Tried to unmount a component that was not mounted', + 'Tried to unmount a component that was not mounted' ] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-1/_config.js b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-1/_config.js index 4ba1c2e001ea..d880635a59f9 100644 --- a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-1/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-1/_config.js @@ -7,5 +7,5 @@ export default test({ get props() { return { tag: 'br' }; }, - warnings: [' is self-closing and cannot have content.'] + warnings: ['`` is a void element — it cannot have content'] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-2/_config.js b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-2/_config.js index 4ba1c2e001ea..d880635a59f9 100644 --- a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-2/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-2/_config.js @@ -7,5 +7,5 @@ export default test({ get props() { return { tag: 'br' }; }, - warnings: [' is self-closing and cannot have content.'] + warnings: ['`` is a void element — it cannot have content'] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-3/_config.js b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-3/_config.js index 4ba1c2e001ea..d880635a59f9 100644 --- a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-3/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-3/_config.js @@ -7,5 +7,5 @@ export default test({ get props() { return { tag: 'br' }; }, - warnings: [' is self-closing and cannot have content.'] + warnings: ['`` is a void element — it cannot have content'] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-4/_config.js b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-4/_config.js index bde68337f04a..51e056d429d1 100644 --- a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-4/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-4/_config.js @@ -8,5 +8,5 @@ export default test({ return { tag: 'br' }; }, html: '
', - warnings: [' is self-closing and cannot have content.'] + warnings: ['`` is a void element — it cannot have content'] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-5/_config.js b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-5/_config.js index a41a39d9809d..86f63d9d32c6 100644 --- a/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-5/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/dynamic-element-void-with-content-5/_config.js @@ -4,5 +4,5 @@ export default test({ compileOptions: { dev: true }, - warnings: [' is self-closing and cannot have content.'] + warnings: ['`` is a void element — it cannot have content'] }); diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index 039cf64eb033..029b9e4cef97 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -178,7 +178,15 @@ async function run_test_variant( if (str.slice(0, i).includes('warnings') || config.warnings) { // eslint-disable-next-line no-console - console.warn = (...args) => warnings.push(...args); + console.warn = (...args) => { + if (args[0].startsWith('%c[svelte]')) { + // TODO convert this to structured data, for more robust comparison? + const message = args[0]; + warnings.push(message.slice(message.indexOf('%c', 2) + 2)); + } else { + warnings.push(...args); + } + }; } } diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index a6efb9aefad0..d7dc76558cfe 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -327,7 +327,7 @@ describe('signals', () => { try { flushSync(); } catch (e: any) { - assert.include(e.message, 'ERR_SVELTE_TOO_MANY_UPDATES'); + assert.include(e.message, 'effect_update_depth_exceeded'); errored = true; } assert.equal(errored, true); @@ -348,7 +348,7 @@ describe('signals', () => { try { flushSync(); } catch (e: any) { - assert.include(e.message, 'ERR_SVELTE_TOO_MANY_UPDATES'); + assert.include(e.message, 'effect_update_depth_exceeded'); errored = true; } assert.equal(errored, true);