diff --git a/.changeset/strong-coins-peel.md b/.changeset/strong-coins-peel.md new file mode 100644 index 000000000000..013e8e44a107 --- /dev/null +++ b/.changeset/strong-coins-peel.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve error message for migration errors when slot would be renamed diff --git a/.changeset/wild-bulldogs-move.md b/.changeset/wild-bulldogs-move.md new file mode 100644 index 000000000000..c3c5580f7797 --- /dev/null +++ b/.changeset/wild-bulldogs-move.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: allow characters in the supplementary special-purpose plane diff --git a/documentation/docs/02-runes/07-$inspect.md b/documentation/docs/02-runes/07-$inspect.md index ff3d64757b6b..13ac8b79a33a 100644 --- a/documentation/docs/02-runes/07-$inspect.md +++ b/documentation/docs/02-runes/07-$inspect.md @@ -52,6 +52,7 @@ This rune, added in 5.14, causes the surrounding function to be _traced_ in deve import { doSomeWork } from './elsewhere'; $effect(() => { + +++// $inspect.trace must be the first statement of a function body+++ +++$inspect.trace();+++ doSomeWork(); }); diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index 6196a85ade62..e8669ead533d 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -274,6 +274,12 @@ A `:global` selector cannot modify an existing selector A `:global` selector can only be modified if it is a descendant of other selectors ``` +### css_global_block_invalid_placement + +``` +A `:global` selector cannot be inside a pseudoclass +``` + ### css_global_invalid_placement ``` diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 8c01c7109957..72cd00bc6abe 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,21 @@ # svelte +## 5.28.2 + +### Patch Changes + +- fix: don't mark selector lists inside `:global` with multiple items as unused ([#15817](https://github.com/sveltejs/svelte/pull/15817)) + +## 5.28.1 + +### Patch Changes + +- fix: ensure `` properly removes error content in production mode ([#15793](https://github.com/sveltejs/svelte/pull/15793)) + +- fix: `update_version` after `delete` if `source` is `undefined` and `prop` in `target` ([#15796](https://github.com/sveltejs/svelte/pull/15796)) + +- fix: emit error on wrong placement of the `:global` block selector ([#15794](https://github.com/sveltejs/svelte/pull/15794)) + ## 5.28.0 ### Minor Changes diff --git a/packages/svelte/messages/compile-errors/style.md b/packages/svelte/messages/compile-errors/style.md index f08a2156a35a..272efbccce7d 100644 --- a/packages/svelte/messages/compile-errors/style.md +++ b/packages/svelte/messages/compile-errors/style.md @@ -50,6 +50,10 @@ x y { > A `:global` selector can only be modified if it is a descendant of other selectors +## css_global_block_invalid_placement + +> A `:global` selector cannot be inside a pseudoclass + ## css_global_invalid_placement > `:global(...)` can be at the start or end of a selector sequence, but not in the middle diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 784b14ea26f6..ff71429d2f9c 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.28.0", + "version": "5.28.2", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index aa328764e14a..c99f59746863 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -581,6 +581,15 @@ export function css_global_block_invalid_modifier_start(node) { e(node, 'css_global_block_invalid_modifier_start', `A \`:global\` selector can only be modified if it is a descendant of other selectors\nhttps://svelte.dev/e/css_global_block_invalid_modifier_start`); } +/** + * A `:global` selector cannot be inside a pseudoclass + * @param {null | number | NodeLike} node + * @returns {never} + */ +export function css_global_block_invalid_placement(node) { + e(node, 'css_global_block_invalid_placement', `A \`:global\` selector cannot be inside a pseudoclass\nhttps://svelte.dev/e/css_global_block_invalid_placement`); +} + /** * `:global(...)` can be at the start or end of a selector sequence, but not in the middle * @param {null | number | NodeLike} node diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 75a9a6490539..2d5a4dcd9e5d 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -1307,7 +1307,7 @@ const template = { name = state.scope.generate(slot_name); if (name !== slot_name) { throw new MigrationError( - 'This migration would change the name of a slot making the component unusable' + `This migration would change the name of a slot (${slot_name} to ${name}) making the component unusable` ); } } @@ -1880,7 +1880,7 @@ function handle_identifier(node, state, path) { let new_name = state.scope.generate(name); if (new_name !== name) { throw new MigrationError( - 'This migration would change the name of a slot making the component unusable' + `This migration would change the name of a slot (${name} to ${new_name}) making the component unusable` ); } } diff --git a/packages/svelte/src/compiler/phases/1-parse/utils/html.js b/packages/svelte/src/compiler/phases/1-parse/utils/html.js index a68acb996faf..a0c2a5b06ffd 100644 --- a/packages/svelte/src/compiler/phases/1-parse/utils/html.js +++ b/packages/svelte/src/compiler/phases/1-parse/utils/html.js @@ -72,6 +72,8 @@ const NUL = 0; // to replace them ourselves // // Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters +// Also see: https://en.wikipedia.org/wiki/Plane_(Unicode) +// Also see: https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream /** @param {number} code */ function validate_code(code) { @@ -116,5 +118,10 @@ function validate_code(code) { return code; } + // supplementary special-purpose plane 0xe0000 - 0xe07f and 0xe0100 - 0xe01ef + if ((code >= 917504 && code <= 917631) || (code >= 917760 && code <= 917999)) { + return code; + } + return NUL; } diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js index 2dc343564831..d6052c9c3e4d 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js @@ -68,8 +68,12 @@ const css_visitors = { const global = node.children.find(is_global); if (global) { - const idx = node.children.indexOf(global); + const is_nested = context.path.at(-2)?.type === 'PseudoClassSelector'; + if (is_nested && !global.selectors[0].args) { + e.css_global_block_invalid_placement(global.selectors[0]); + } + const idx = node.children.indexOf(global); if (global.selectors[0].args !== null && idx !== 0 && idx !== node.children.length - 1) { // ensure `:global(...)` is not used in the middle of a selector (but multiple `global(...)` in sequence are ok) for (let i = idx + 1; i < node.children.length; i++) { diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index 9f1142cce9a7..cee7ab279122 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -196,9 +196,12 @@ const visitors = { next(); }, SelectorList(node, { state, next, path }) { + const parent = path.at(-1); + // Only add comments if we're not inside a complex selector that itself is unused or a global block if ( - (!is_in_global_block(path) || node.children.length > 1) && + (!is_in_global_block(path) || + (node.children.length > 1 && parent?.type === 'Rule' && parent.metadata.is_global_block)) && !path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used) ) { const children = node.children; @@ -260,7 +263,6 @@ const visitors = { // if this selector list belongs to a rule, require a specificity bump for the // first scoped selector but only if we're at the top level - let parent = path.at(-1); if (parent?.type === 'Rule') { specificity = { bumped: false }; @@ -376,7 +378,6 @@ const visitors = { }; /** - * * @param {Array} path */ function is_in_global_block(path) { diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index d690790e3a78..fd5706eaf270 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -100,6 +100,7 @@ export function proxy(value) { prop, with_parent(() => source(UNINITIALIZED, stack)) ); + update_version(version); } } else { // When working with arrays, we need to also ensure we update the length when removing diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 7595aa4a1914..7a926bf62457 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -291,31 +291,21 @@ export function handle_error(error, effect, previous_effect, component_context) is_throwing_error = true; } - if ( - !DEV || - component_context === null || - !(error instanceof Error) || - handled_errors.has(error) - ) { - propagate_error(error, effect); - return; - } - - handled_errors.add(error); + if (DEV && component_context !== null && error instanceof Error && !handled_errors.has(error)) { + handled_errors.add(error); - const component_stack = []; + const component_stack = []; - const effect_name = effect.fn?.name; + const effect_name = effect.fn?.name; - if (effect_name) { - component_stack.push(effect_name); - } + if (effect_name) { + component_stack.push(effect_name); + } - /** @type {ComponentContext | null} */ - let current_context = component_context; + /** @type {ComponentContext | null} */ + let current_context = component_context; - while (current_context !== null) { - if (DEV) { + while (current_context !== null) { /** @type {string} */ var filename = current_context.function?.[FILENAME]; @@ -323,35 +313,36 @@ export function handle_error(error, effect, previous_effect, component_context) const file = filename.split('/').pop(); component_stack.push(file); } + + current_context = current_context.p; } - current_context = current_context.p; - } + const indent = is_firefox ? ' ' : '\t'; + define_property(error, 'message', { + value: + error.message + `\n${component_stack.map((name) => `\n${indent}in ${name}`).join('')}\n` + }); + define_property(error, 'component_stack', { + value: component_stack + }); - const indent = is_firefox ? ' ' : '\t'; - define_property(error, 'message', { - value: error.message + `\n${component_stack.map((name) => `\n${indent}in ${name}`).join('')}\n` - }); - define_property(error, 'component_stack', { - value: component_stack - }); - - const stack = error.stack; - - // Filter out internal files from callstack - if (stack) { - const lines = stack.split('\n'); - const new_lines = []; - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - if (line.includes('svelte/src/internal')) { - continue; + const stack = error.stack; + + // Filter out internal files from callstack + if (stack) { + const lines = stack.split('\n'); + const new_lines = []; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (line.includes('svelte/src/internal')) { + continue; + } + new_lines.push(line); } - new_lines.push(line); + define_property(error, 'stack', { + value: new_lines.join('\n') + }); } - define_property(error, 'stack', { - value: new_lines.join('\n') - }); } propagate_error(error, effect); @@ -789,19 +780,12 @@ function process_effects(root) { } else if (is_branch) { effect.f ^= CLEAN; } else { - // Ensure we set the effect to be the active reaction - // to ensure that unowned deriveds are correctly tracked - // because we're flushing the current effect - var previous_active_reaction = active_reaction; try { - active_reaction = effect; if (check_dirtiness(effect)) { update_effect(effect); } } catch (error) { handle_error(error, effect, null, effect.ctx); - } finally { - active_reaction = previous_active_reaction; } } diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 4418204ecab7..a3a9979d6546 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.28.0'; +export const VERSION = '5.28.2'; export const PUBLIC_VERSION = '5'; diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/_config.js b/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/_config.js new file mode 100644 index 000000000000..c987725d743c --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'css_global_block_invalid_placement', + message: 'A `:global` selector cannot be inside a pseudoclass', + position: [28, 35] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/main.svelte b/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/main.svelte new file mode 100644 index 000000000000..53060df97da0 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/main.svelte @@ -0,0 +1,4 @@ + diff --git a/packages/svelte/tests/css/samples/global-block/_config.js b/packages/svelte/tests/css/samples/global-block/_config.js index a8b11a73ec14..18a56e9a97d1 100644 --- a/packages/svelte/tests/css/samples/global-block/_config.js +++ b/packages/svelte/tests/css/samples/global-block/_config.js @@ -7,28 +7,28 @@ export default test({ code: 'css_unused_selector', message: 'Unused CSS selector ".unused :global"', start: { - line: 69, + line: 73, column: 1, - character: 917 + character: 964 }, end: { - line: 69, + line: 73, column: 16, - character: 932 + character: 979 } }, { code: 'css_unused_selector', message: 'Unused CSS selector "unused :global"', start: { - line: 100, + line: 104, column: 29, - character: 1223 + character: 1270 }, end: { - line: 100, + line: 104, column: 43, - character: 1237 + character: 1284 } } ] diff --git a/packages/svelte/tests/css/samples/global-block/expected.css b/packages/svelte/tests/css/samples/global-block/expected.css index 12f9a75032ff..be1838fd98e3 100644 --- a/packages/svelte/tests/css/samples/global-block/expected.css +++ b/packages/svelte/tests/css/samples/global-block/expected.css @@ -3,6 +3,10 @@ .x { color: green; } + + .a, .selector, .list { + color: green; + } /*}*/ div.svelte-xyz { diff --git a/packages/svelte/tests/css/samples/global-block/input.svelte b/packages/svelte/tests/css/samples/global-block/input.svelte index ee05205d67c3..86d438031a96 100644 --- a/packages/svelte/tests/css/samples/global-block/input.svelte +++ b/packages/svelte/tests/css/samples/global-block/input.svelte @@ -5,6 +5,10 @@ .x { color: green; } + + .a, .selector, .list { + color: green; + } } div :global { diff --git a/packages/svelte/tests/migrate/samples/impossible-migrate-$derived-derived-var-3/output.svelte b/packages/svelte/tests/migrate/samples/impossible-migrate-$derived-derived-var-3/output.svelte index 9e4f086aedd3..26012e11151d 100644 --- a/packages/svelte/tests/migrate/samples/impossible-migrate-$derived-derived-var-3/output.svelte +++ b/packages/svelte/tests/migrate/samples/impossible-migrate-$derived-derived-var-3/output.svelte @@ -1,7 +1,7 @@ - + - \ No newline at end of file + diff --git a/packages/svelte/tests/migrate/samples/impossible-migrate-slot-change-name/output.svelte b/packages/svelte/tests/migrate/samples/impossible-migrate-slot-change-name/output.svelte index 2b6838a1d681..328966b63b6a 100644 --- a/packages/svelte/tests/migrate/samples/impossible-migrate-slot-change-name/output.svelte +++ b/packages/svelte/tests/migrate/samples/impossible-migrate-slot-change-name/output.svelte @@ -1,6 +1,6 @@ - + - \ No newline at end of file + diff --git a/packages/svelte/tests/migrate/samples/impossible-migrate-slot-non-identifier/output.svelte b/packages/svelte/tests/migrate/samples/impossible-migrate-slot-non-identifier/output.svelte index 6e5ab103109b..1e763577df34 100644 --- a/packages/svelte/tests/migrate/samples/impossible-migrate-slot-non-identifier/output.svelte +++ b/packages/svelte/tests/migrate/samples/impossible-migrate-slot-non-identifier/output.svelte @@ -1,2 +1,2 @@ - - \ No newline at end of file + + diff --git a/packages/svelte/tests/runtime-legacy/samples/ondestroy-prop-access/_config.js b/packages/svelte/tests/runtime-legacy/samples/ondestroy-prop-access/_config.js index 2ffb7e653f15..4f75e82aaea7 100644 --- a/packages/svelte/tests/runtime-legacy/samples/ondestroy-prop-access/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/ondestroy-prop-access/_config.js @@ -36,8 +36,6 @@ export default test({ btn1.click(); }); - console.warn(logs); - // the five components guarded by `count < 2` unmount and log assert.deepEqual(logs, [1, true, 1, true, 1, true, 1, true, 1, true]); diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index fc748ce6b299..14b6cff841bd 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -351,7 +351,7 @@ async function run_test_variant( // @ts-expect-error globalThis.__svelte.uid = 1; - if (manual_hydrate) { + if (manual_hydrate && variant === 'hydrate') { hydrate_fn = () => { instance = hydrate(mod.default, { target, @@ -469,10 +469,6 @@ async function run_test_variant( throw err; } } finally { - console.log = console_log; - console.warn = console_warn; - console.error = console_error; - config.after_test?.(); // Free up the microtask queue @@ -486,6 +482,10 @@ async function run_test_variant( process.on('unhandledRejection', listener); }); } + + console.log = console_log; + console.warn = console_warn; + console.error = console_error; } } diff --git a/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/_config.js b/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/_config.js new file mode 100644 index 000000000000..23141a01cd86 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/_config.js @@ -0,0 +1,13 @@ +import { test } from '../../test'; +import { flushSync } from 'svelte'; + +export default test({ + html: `

test

`, + + async test({ assert, target }) { + const btn = target.querySelector('button'); + + flushSync(() => btn?.click()); + assert.htmlEqual(target.innerHTML, ''); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/main.svelte b/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/main.svelte new file mode 100644 index 000000000000..d3c519c401c8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/main.svelte @@ -0,0 +1,13 @@ + + + + +{#each keys as key} +

{key}

+{/each} diff --git a/packages/svelte/tests/runtime-runes/samples/error-boundary-22/Child.svelte b/packages/svelte/tests/runtime-runes/samples/error-boundary-22/Child.svelte new file mode 100644 index 000000000000..ea60542af9cc --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/error-boundary-22/Child.svelte @@ -0,0 +1,3 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/error-boundary-22/_config.js b/packages/svelte/tests/runtime-runes/samples/error-boundary-22/_config.js new file mode 100644 index 000000000000..c6be4a8cfdf8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/error-boundary-22/_config.js @@ -0,0 +1,11 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['client'], + test({ assert, target }) { + flushSync(); + + assert.htmlEqual(target.innerHTML, '

error occurred

'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/error-boundary-22/main.svelte b/packages/svelte/tests/runtime-runes/samples/error-boundary-22/main.svelte new file mode 100644 index 000000000000..39b2fb2eb233 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/error-boundary-22/main.svelte @@ -0,0 +1,15 @@ + + + +

This should be removed

+ + {#if true} + + {/if} + + {#snippet failed()} +

error occurred

+ {/snippet} +
diff --git a/packages/svelte/tests/runtime-runes/samples/event-handler-component-invalid-warning/_config.js b/packages/svelte/tests/runtime-runes/samples/event-handler-component-invalid-warning/_config.js index 01ac3c9ad0d9..e77101066994 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-handler-component-invalid-warning/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-handler-component-invalid-warning/_config.js @@ -7,12 +7,8 @@ export default test({ dev: true }, - test({ assert, target, warnings }) { - /** @type {any} */ - let error; - + test({ assert, target, warnings, errors }) { const handler = (/** @type {any}} */ e) => { - error = e.error; e.stopImmediatePropagation(); }; @@ -20,9 +16,7 @@ export default test({ target.querySelector('button')?.click(); - assert.throws(() => { - throw error; - }, /state_unsafe_mutation/); + assert.include(errors[0], 'state_unsafe_mutation'); window.removeEventListener('error', handler, true); diff --git a/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-values/_config.js b/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-values/_config.js index d53812d4c39e..7ca12af774b0 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-values/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-values/_config.js @@ -1,4 +1,3 @@ -import { assertType } from 'vitest'; import { test } from '../../test'; export default test({ @@ -8,12 +7,8 @@ export default test({ dev: true }, - test({ assert, target, warnings, logs }) { - /** @type {any} */ - let error = null; - + test({ assert, target, warnings, logs, errors }) { const handler = (/** @type {any} */ e) => { - error = e.error; e.stopImmediatePropagation(); }; @@ -23,16 +18,12 @@ export default test({ b1.click(); assert.deepEqual(logs, []); - assert.equal(error, null); - - error = null; - logs.length = 0; + assert.deepEqual(errors, []); b2.click(); assert.deepEqual(logs, ['clicked']); - assert.equal(error, null); + assert.deepEqual(errors, []); - error = null; logs.length = 0; b3.click(); @@ -40,8 +31,7 @@ export default test({ assert.deepEqual(warnings, [ '`click` handler at main.svelte:10:17 should be a function. Did you mean to add a leading `() =>`?' ]); - assert.isNotNull(error); - assert.match(error.message, /is not a function/); + assert.include(errors[0], 'is not a function'); window.removeEventListener('error', handler, true); } diff --git a/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-warning/_config.js b/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-warning/_config.js index 423351a4c7cf..a0c792360e3b 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-warning/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-handler-invalid-warning/_config.js @@ -7,12 +7,8 @@ export default test({ dev: true }, - test({ assert, target, warnings }) { - /** @type {any} */ - let error; - + test({ assert, target, warnings, errors }) { const handler = (/** @type {any} */ e) => { - error = e.error; e.stopImmediatePropagation(); }; @@ -20,9 +16,7 @@ export default test({ target.querySelector('button')?.click(); - assert.throws(() => { - throw error; - }, /state_unsafe_mutation/); + assert.include(errors[0], 'state_unsafe_mutation'); window.removeEventListener('error', handler, true); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js index 57caf6e08dbc..e155ff236a48 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-exception/_config.js @@ -6,11 +6,12 @@ export default test({ dev: true }, - async test({ assert, target, logs }) { + async test({ assert, target, logs, errors }) { const b1 = target.querySelector('button'); b1?.click(); flushSync(); + assert.ok(errors.length > 0); assert.deepEqual(logs, ['init', 'a', 'init', 'b']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-trace-null/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-trace-null/_config.js index e779a835c2ef..7982e8c1c62c 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-trace-null/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-trace-null/_config.js @@ -1,8 +1,12 @@ +import { assert } from 'vitest'; import { test } from '../../test'; export default test({ compileOptions: { dev: true }, - test() {} + + test({ logs }) { + assert.ok(logs.length > 0); + } }); diff --git a/packages/svelte/tests/runtime-runes/samples/unhoist-function-accessing-snippet/main.svelte b/packages/svelte/tests/runtime-runes/samples/unhoist-function-accessing-snippet/main.svelte index e909d77fd670..9f3a56a9ede9 100644 --- a/packages/svelte/tests/runtime-runes/samples/unhoist-function-accessing-snippet/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/unhoist-function-accessing-snippet/main.svelte @@ -1,6 +1,6 @@ @@ -9,4 +9,4 @@ {#snippet snip()} snippet {x} -{/snippet} \ No newline at end of file +{/snippet} diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 3a427e939274..8421ae4a7cbf 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -15,6 +15,7 @@ import { derived } from '../../src/internal/client/reactivity/deriveds'; import { snapshot } from '../../src/internal/shared/clone.js'; import { SvelteSet } from '../../src/reactivity/set'; import { DESTROYED } from '../../src/internal/client/constants'; +import { noop } from 'svelte/internal/client'; /** * @param runes runes mode @@ -469,6 +470,9 @@ describe('signals', () => { test('schedules rerun when writing to signal before reading it', (runes) => { if (!runes) return () => {}; + const error = console.error; + console.error = noop; + const value = state({ count: 0 }); user_effect(() => { set(value, { count: 0 }); @@ -482,14 +486,19 @@ describe('signals', () => { } catch (e: any) { assert.include(e.message, 'effect_update_depth_exceeded'); errored = true; + } finally { + assert.equal(errored, true); + console.error = error; } - assert.equal(errored, true); }; }); test('schedules rerun when updating deeply nested value', (runes) => { if (!runes) return () => {}; + const error = console.error; + console.error = noop; + const value = proxy({ a: { b: { c: 0 } } }); user_effect(() => { value.a.b.c += 1; @@ -502,14 +511,19 @@ describe('signals', () => { } catch (e: any) { assert.include(e.message, 'effect_update_depth_exceeded'); errored = true; + } finally { + assert.equal(errored, true); + console.error = error; } - assert.equal(errored, true); }; }); test('schedules rerun when writing to signal before reading it', (runes) => { if (!runes) return () => {}; + const error = console.error; + console.error = noop; + const value = proxy({ arr: [] }); user_effect(() => { value.arr = []; @@ -523,8 +537,10 @@ describe('signals', () => { } catch (e: any) { assert.include(e.message, 'effect_update_depth_exceeded'); errored = true; + } finally { + assert.equal(errored, true); + console.error = error; } - assert.equal(errored, true); }; });