From d8c6afde944a61c648c6b6f416f5ccafde272d44 Mon Sep 17 00:00:00 2001 From: 7nik Date: Fri, 18 Apr 2025 18:48:27 +0300 Subject: [PATCH 1/4] fix: emit error on wrong placement of the `:global` block selector (#15794) Co-authored-by: 7nik --- .changeset/pretty-beers-care.md | 5 +++++ .../docs/98-reference/.generated/compile-errors.md | 6 ++++++ packages/svelte/messages/compile-errors/style.md | 4 ++++ packages/svelte/src/compiler/errors.js | 9 +++++++++ .../src/compiler/phases/2-analyze/css/css-analyze.js | 6 +++++- .../samples/css-global-block-in-pseudoclass/_config.js | 9 +++++++++ .../samples/css-global-block-in-pseudoclass/main.svelte | 4 ++++ 7 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 .changeset/pretty-beers-care.md create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/main.svelte diff --git a/.changeset/pretty-beers-care.md b/.changeset/pretty-beers-care.md new file mode 100644 index 0000000000..821bad41c4 --- /dev/null +++ b/.changeset/pretty-beers-care.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: emit error on wrong placement of the `:global` block selector diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index 6196a85ade..e8669ead53 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/messages/compile-errors/style.md b/packages/svelte/messages/compile-errors/style.md index f08a2156a3..272efbccce 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/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index aa328764e1..c99f597468 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/phases/2-analyze/css/css-analyze.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js index 2dc3435648..d6052c9c3e 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/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 0000000000..c987725d74 --- /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 0000000000..53060df97d --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-in-pseudoclass/main.svelte @@ -0,0 +1,4 @@ + From 3d808840298dcd7fbb40dfa90700082911e514e7 Mon Sep 17 00:00:00 2001 From: Paolo Ricciuti Date: Fri, 18 Apr 2025 17:50:38 +0200 Subject: [PATCH 2/4] fix: `update_version` after `delete` if `source` is `undefined` and `prop` in `target` (#15796) * fix: `update_version` after `delete` if `source` is `undefined` and `prop` in `target` * chore: remove submodule * tweak test --------- Co-authored-by: Rich Harris --- .changeset/great-colts-film.md | 5 +++++ packages/svelte/src/internal/client/proxy.js | 1 + .../samples/delete-proxy-key/_config.js | 13 +++++++++++++ .../samples/delete-proxy-key/main.svelte | 13 +++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 .changeset/great-colts-film.md create mode 100644 packages/svelte/tests/runtime-runes/samples/delete-proxy-key/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/delete-proxy-key/main.svelte diff --git a/.changeset/great-colts-film.md b/.changeset/great-colts-film.md new file mode 100644 index 0000000000..273509c107 --- /dev/null +++ b/.changeset/great-colts-film.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: `update_version` after `delete` if `source` is `undefined` and `prop` in `target` diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index d690790e3a..fd5706eaf2 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/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 0000000000..23141a01cd --- /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 0000000000..d3c519c401 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/delete-proxy-key/main.svelte @@ -0,0 +1,13 @@ + + + + +{#each keys as key} +

{key}

+{/each} From b2d5787a09bffefb716d72706460d8b66e96c862 Mon Sep 17 00:00:00 2001 From: zeroberry <98147817+zeroberry@users.noreply.github.com> Date: Sat, 19 Apr 2025 01:16:25 +0900 Subject: [PATCH 3/4] fix: ensure `` properly removes error content in production mode (#15793) * fix: ensure properly removes error content in production mode * add changeset --- .changeset/eleven-roses-speak.md | 5 ++ .../svelte/src/internal/client/runtime.js | 79 ++++++++----------- .../samples/error-boundary-22/Child.svelte | 3 + .../samples/error-boundary-22/_config.js | 11 +++ .../samples/error-boundary-22/main.svelte | 15 ++++ 5 files changed, 69 insertions(+), 44 deletions(-) create mode 100644 .changeset/eleven-roses-speak.md create mode 100644 packages/svelte/tests/runtime-runes/samples/error-boundary-22/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/error-boundary-22/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/error-boundary-22/main.svelte diff --git a/.changeset/eleven-roses-speak.md b/.changeset/eleven-roses-speak.md new file mode 100644 index 0000000000..0d906f3b5f --- /dev/null +++ b/.changeset/eleven-roses-speak.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure properly removes error content in production mode diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 7595aa4a19..fccea3e856 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); 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 0000000000..ea60542af9 --- /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 0000000000..c6be4a8cfd --- /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 0000000000..39b2fb2eb2 --- /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} +
From e40e9eb1a444426eb5ab27bf39cbda6225283574 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Apr 2025 12:19:20 -0400 Subject: [PATCH 4/4] Version Packages (#15800) * Version Packages * Update packages/svelte/CHANGELOG.md --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Rich Harris --- .changeset/eleven-roses-speak.md | 5 ----- .changeset/great-colts-film.md | 5 ----- .changeset/pretty-beers-care.md | 5 ----- packages/svelte/CHANGELOG.md | 10 ++++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 6 files changed, 12 insertions(+), 17 deletions(-) delete mode 100644 .changeset/eleven-roses-speak.md delete mode 100644 .changeset/great-colts-film.md delete mode 100644 .changeset/pretty-beers-care.md diff --git a/.changeset/eleven-roses-speak.md b/.changeset/eleven-roses-speak.md deleted file mode 100644 index 0d906f3b5f..0000000000 --- a/.changeset/eleven-roses-speak.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: ensure properly removes error content in production mode diff --git a/.changeset/great-colts-film.md b/.changeset/great-colts-film.md deleted file mode 100644 index 273509c107..0000000000 --- a/.changeset/great-colts-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: `update_version` after `delete` if `source` is `undefined` and `prop` in `target` diff --git a/.changeset/pretty-beers-care.md b/.changeset/pretty-beers-care.md deleted file mode 100644 index 821bad41c4..0000000000 --- a/.changeset/pretty-beers-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: emit error on wrong placement of the `:global` block selector diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 8c01c71099..cb3b356cc7 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,15 @@ # svelte +## 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/package.json b/packages/svelte/package.json index 784b14ea26..c91fbdd7d3 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.1", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 4418204eca..a19a773cd1 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.1'; export const PUBLIC_VERSION = '5';