From bd5480b9d08ef0022c03345b914694aa73e30d33 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:45:34 +0100 Subject: [PATCH 01/20] fix: reduce if block nesting (#17662) * fix: reduce if block nesting This reduces if block nesting similar to how we did it in #15250 (which got lost during the `await` feature introduction): If the if expression doesn't contain an await expression or is not dependent on a blocker that is not already resolved, then we can avoid creating a separate `$.if()` statement. The one trade-off is that we'll do re-invocations for all the conditions leading up to the condition that matches. Therefore non-simple if expressions are wrapper in `$.derived` to avoid excessive recomputations. closes #17659 (~320 markers in prod mode possible now; less in dev because of our "wrap this component with devtime info" method) helps with #15200 * tweak * feedback --- .changeset/wild-dolls-hang.md | 5 + .../phases/2-analyze/visitors/IfBlock.js | 19 ++ .../3-transform/client/visitors/Fragment.js | 6 +- .../3-transform/client/visitors/IfBlock.js | 85 +++++--- .../3-transform/server/visitors/IfBlock.js | 34 ++- packages/svelte/src/compiler/phases/nodes.js | 13 ++ .../svelte/src/compiler/types/template.d.ts | 2 + .../src/internal/client/dom/blocks/if.js | 36 ++-- .../src/internal/client/dom/hydration.js | 7 +- .../samples/async-if-nested/_config.js | 12 ++ .../samples/async-if-nested/main.svelte | 21 ++ .../async-state-new-branch/Child.svelte | 7 + .../samples/async-state-new-branch/_config.js | 47 ++++ .../async-state-new-branch/main.svelte | 28 +++ .../samples/async-if-chain/_config.js | 3 + .../_expected/client/index.svelte.js | 201 ++++++++++++++++++ .../_expected/server/index.svelte.js | 110 ++++++++++ .../samples/async-if-chain/index.svelte | 59 +++++ 18 files changed, 647 insertions(+), 48 deletions(-) create mode 100644 .changeset/wild-dolls-hang.md create mode 100644 packages/svelte/tests/runtime-runes/samples/async-if-nested/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-if-nested/main.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/async-state-new-branch/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/async-state-new-branch/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-state-new-branch/main.svelte create mode 100644 packages/svelte/tests/snapshot/samples/async-if-chain/_config.js create mode 100644 packages/svelte/tests/snapshot/samples/async-if-chain/_expected/client/index.svelte.js create mode 100644 packages/svelte/tests/snapshot/samples/async-if-chain/_expected/server/index.svelte.js create mode 100644 packages/svelte/tests/snapshot/samples/async-if-chain/index.svelte diff --git a/.changeset/wild-dolls-hang.md b/.changeset/wild-dolls-hang.md new file mode 100644 index 0000000000..a7b3436d69 --- /dev/null +++ b/.changeset/wild-dolls-hang.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: reduce if block nesting diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js index dcdae3587f..64855abdaf 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js @@ -24,4 +24,23 @@ export function IfBlock(node, context) { context.visit(node.consequent); if (node.alternate) context.visit(node.alternate); + + // Check if we can flatten branches + const alt = node.alternate; + + if (alt && alt.nodes.length === 1 && alt.nodes[0].type === 'IfBlock' && alt.nodes[0].elseif) { + const elseif = alt.nodes[0]; + + // Don't flatten if this else-if has an await expression or new blockers + // TODO would be nice to check the await expression itself to see if it's awaiting the same thing as a previous if expression + if ( + !elseif.metadata.expression.has_await && + !elseif.metadata.expression.has_more_blockers_than(node.metadata.expression) + ) { + // Roll the existing flattened branches (if any) into this one, then delete those of the else-if block + // to avoid processing them multiple times as we walk down the chain during code transformation. + node.metadata.flattened = [elseif, ...(elseif.metadata.flattened ?? [])]; + elseif.metadata.flattened = undefined; + } + } } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js index 00b0cfaa2e..be919d380c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Fragment.js @@ -47,7 +47,11 @@ export function Fragment(node, context) { const is_single_element = trimmed.length === 1 && trimmed[0].type === 'RegularElement'; const is_single_child_not_needing_template = trimmed.length === 1 && - (trimmed[0].type === 'SvelteFragment' || trimmed[0].type === 'TitleElement'); + (trimmed[0].type === 'SvelteFragment' || + trimmed[0].type === 'TitleElement' || + (trimmed[0].type === 'IfBlock' && + trimmed[0].elseif && + /** @type {AST.IfBlock} */ (parent).metadata.flattened?.includes(trimmed[0]))); const template_name = context.state.scope.root.unique('root'); // TODO infer name from parent /** @type {Statement[]} */ diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js index c0e66635df..0d31c42d11 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js @@ -1,4 +1,4 @@ -/** @import { BlockStatement, Expression } from 'estree' */ +/** @import { BlockStatement, Expression, IfStatement, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import * as b from '#compiler/builders'; @@ -10,40 +10,75 @@ import { build_expression, add_svelte_meta } from './shared/utils.js'; */ export function IfBlock(node, context) { context.state.template.push_comment(); + + /** @type {Statement[]} */ const statements = []; - const consequent = /** @type {BlockStatement} */ (context.visit(node.consequent)); - const consequent_id = b.id(context.state.scope.generate('consequent')); + const has_await = node.metadata.expression.has_await; + const has_blockers = node.metadata.expression.has_blockers(); + const expression = build_expression(context, node.test, node.metadata.expression); + + // Build the if/else-if/else chain + let index = 0; + /** @type {IfStatement | undefined} */ + let first_if; + /** @type {IfStatement | undefined} */ + let last_if; + /** @type {AST.IfBlock | undefined} */ + let last_alt; - statements.push(b.var(consequent_id, b.arrow([b.id('$$anchor')], consequent))); + for (const branch of [node, ...(node.metadata.flattened ?? [])]) { + const consequent = /** @type {BlockStatement} */ (context.visit(branch.consequent)); + const consequent_id = b.id(context.state.scope.generate('consequent')); + statements.push(b.var(consequent_id, b.arrow([b.id('$$anchor')], consequent))); - let alternate_id; + // Build the test expression for this branch + /** @type {Expression} */ + let test; - if (node.alternate) { - const alternate = /** @type {BlockStatement} */ (context.visit(node.alternate)); - alternate_id = b.id(context.state.scope.generate('alternate')); - statements.push(b.var(alternate_id, b.arrow([b.id('$$anchor')], alternate))); + if (branch.metadata.expression.has_await) { + // Top-level condition with await: already resolved by $.async wrapper + test = b.call('$.get', b.id('$$condition')); + } else { + const expression = build_expression(context, branch.test, branch.metadata.expression); + + if (branch.metadata.expression.has_call) { + const derived_id = b.id(context.state.scope.generate('d')); + statements.push(b.var(derived_id, b.call('$.derived', b.arrow([], expression)))); + test = b.call('$.get', derived_id); + } else { + test = expression; + } + } + + const render_call = b.stmt(b.call('$$render', consequent_id, index > 0 && b.literal(index))); + const new_if = b.if(test, render_call); + + if (last_if) { + last_if.alternate = new_if; + } else { + first_if = new_if; + } + + last_alt = branch; + last_if = new_if; + index++; } - const has_await = node.metadata.expression.has_await; - const has_blockers = node.metadata.expression.has_blockers(); + // Handle final alternate (else branch, remaining async chain, or nothing) + if (last_if && last_alt?.alternate) { + const alternate = /** @type {BlockStatement} */ (context.visit(last_alt.alternate)); + const alternate_id = b.id(context.state.scope.generate('alternate')); + statements.push(b.var(alternate_id, b.arrow([b.id('$$anchor')], alternate))); - const expression = build_expression(context, node.test, node.metadata.expression); - const test = has_await ? b.call('$.get', b.id('$$condition')) : expression; + last_if.alternate = b.stmt(b.call('$$render', alternate_id, b.literal(false))); + } + // Build $.if() arguments /** @type {Expression[]} */ const args = [ context.state.node, - b.arrow( - [b.id('$$render')], - b.block([ - b.if( - test, - b.stmt(b.call('$$render', consequent_id)), - alternate_id && b.stmt(b.call('$$render', alternate_id, b.literal(false))) - ) - ]) - ) + b.arrow([b.id('$$render')], first_if ? b.block([first_if]) : b.block([])) ]; if (node.elseif) { @@ -67,7 +102,9 @@ export function IfBlock(node, context) { // // ...even though they're logically equivalent. In the first case, the // transition will only play when `y` changes, but in the second it - // should play when `x` or `y` change — both are considered 'local' + // should play when `x` or `y` change — both are considered 'local'. + // This could also be a non-flattened elseif (because it has an async expression). + // In both cases mark as elseif so the runtime uses EFFECT_TRANSPARENT for transitions. args.push(b.true); } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js index 06b1b1e966..e3f5f88705 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/IfBlock.js @@ -1,4 +1,4 @@ -/** @import { BlockStatement, Expression, Statement } from 'estree' */ +/** @import { BlockStatement, Expression, IfStatement, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types.js' */ import * as b from '#compiler/builders'; @@ -9,23 +9,37 @@ import { block_close, block_open, block_open_else, create_child_block } from './ * @param {ComponentContext} context */ export function IfBlock(node, context) { - const test = /** @type {Expression} */ (context.visit(node.test)); const consequent = /** @type {BlockStatement} */ (context.visit(node.consequent)); + consequent.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open))); - const alternate = node.alternate - ? /** @type {BlockStatement} */ (context.visit(node.alternate)) - : b.block([]); + /** @type {IfStatement} */ + let if_statement = b.if(/** @type {Expression} */ (context.visit(node.test)), consequent); - consequent.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open))); + let index = 1; + let current_if = if_statement; + let alt = node.alternate; + + // Walk the else-if chain, flattening branches + for (const elseif of node.metadata.flattened ?? []) { + const branch = /** @type {BlockStatement} */ (context.visit(elseif.consequent)); + branch.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), b.literal(``)))); + + current_if = current_if.alternate = b.if( + /** @type {Expression} */ (context.visit(elseif.test)), + branch + ); + alt = elseif.alternate; + } - alternate.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open_else))); + // Handle final else (or remaining async chain) + const final_alternate = alt ? /** @type {BlockStatement} */ (context.visit(alt)) : b.block([]); - /** @type {Statement} */ - let statement = b.if(test, consequent, alternate); + final_alternate.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open_else))); + current_if.alternate = final_alternate; context.state.template.push( ...create_child_block( - [statement], + [if_statement], node.metadata.expression.blockers(), node.metadata.expression.has_await ), diff --git a/packages/svelte/src/compiler/phases/nodes.js b/packages/svelte/src/compiler/phases/nodes.js index f302603409..2e54f333a8 100644 --- a/packages/svelte/src/compiler/phases/nodes.js +++ b/packages/svelte/src/compiler/phases/nodes.js @@ -118,6 +118,19 @@ export class ExpressionMetadata { return this.#get_blockers().size > 0; } + /** + * @param {ExpressionMetadata} other + */ + has_more_blockers_than(other) { + for (const blocker of this.#get_blockers()) { + if (!other.#get_blockers().has(blocker)) { + return true; + } + } + + return false; + } + is_async() { return this.has_await || this.#get_blockers().size > 0; } diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index b924406d0f..d44a31349a 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -483,6 +483,8 @@ export namespace AST { alternate: Fragment | null; /** @internal */ metadata: { + /** List of else-if blocks that can be flattened into this if block */ + flattened?: IfBlock[]; expression: ExpressionMetadata; }; } diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index 7fa5ca464d..f2b1cf80a5 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -9,14 +9,12 @@ import { set_hydrating } from '../hydration.js'; import { block } from '../../reactivity/effects.js'; -import { HYDRATION_START_ELSE } from '../../../../constants.js'; import { BranchManager } from './branches.js'; - -// TODO reinstate https://github.com/sveltejs/svelte/pull/15250 +import { HYDRATION_START, HYDRATION_START_ELSE } from '../../../../constants.js'; /** * @param {TemplateNode} node - * @param {(branch: (fn: (anchor: Node) => void, flag?: boolean) => void) => void} fn + * @param {(branch: (fn: (anchor: Node) => void, key?: number | false) => void) => void} fn * @param {boolean} [elseif] True if this is an `{:else if ...}` block rather than an `{#if ...}`, as that affects which transitions are considered 'local' * @returns {void} */ @@ -29,14 +27,28 @@ export function if_block(node, fn, elseif = false) { var flags = elseif ? EFFECT_TRANSPARENT : 0; /** - * @param {boolean} condition, + * @param {number | false} key * @param {null | ((anchor: Node) => void)} fn */ - function update_branch(condition, fn) { + function update_branch(key, fn) { if (hydrating) { - const is_else = read_hydration_instruction(node) === HYDRATION_START_ELSE; + const data = read_hydration_instruction(node); + + /** + * @type {number | false} + * "[" = branch 0, "[1" = branch 1, "[2" = branch 2, ..., "[!" = else (false) + */ + var hydrated_key; + + if (data === HYDRATION_START) { + hydrated_key = 0; + } else if (data === HYDRATION_START_ELSE) { + hydrated_key = false; + } else { + hydrated_key = parseInt(data.substring(1)); // "[1", "[2", etc. + } - if (condition === is_else) { + if (key !== hydrated_key) { // Hydration mismatch: remove everything inside the anchor and start fresh. // This could happen with `{#if browser}...{/if}`, for example var anchor = skip_nodes(); @@ -45,22 +57,22 @@ export function if_block(node, fn, elseif = false) { branches.anchor = anchor; set_hydrating(false); - branches.ensure(condition, fn); + branches.ensure(key, fn); set_hydrating(true); return; } } - branches.ensure(condition, fn); + branches.ensure(key, fn); } block(() => { var has_branch = false; - fn((fn, flag = true) => { + fn((fn, key = 0) => { has_branch = true; - update_branch(flag, fn); + update_branch(key, fn); }); if (!has_branch) { diff --git a/packages/svelte/src/internal/client/dom/hydration.js b/packages/svelte/src/internal/client/dom/hydration.js index 7a9ef33d1b..83833f493d 100644 --- a/packages/svelte/src/internal/client/dom/hydration.js +++ b/packages/svelte/src/internal/client/dom/hydration.js @@ -95,7 +95,12 @@ export function skip_nodes(remove = true) { if (data === HYDRATION_END) { if (depth === 0) return node; depth -= 1; - } else if (data === HYDRATION_START || data === HYDRATION_START_ELSE) { + } else if ( + data === HYDRATION_START || + data === HYDRATION_START_ELSE || + // "[1", "[2", etc. for if blocks + (data[0] === '[' && !isNaN(Number(data.slice(1)))) + ) { depth += 1; } } diff --git a/packages/svelte/tests/runtime-runes/samples/async-if-nested/_config.js b/packages/svelte/tests/runtime-runes/samples/async-if-nested/_config.js new file mode 100644 index 0000000000..49cae28cc4 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-if-nested/_config.js @@ -0,0 +1,12 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['async-server', 'hydrate', 'client'], + ssrHtml: `bar blocking`, + + async test({ assert, target }) { + await tick(); + assert.htmlEqual(target.innerHTML, 'bar blocking'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-if-nested/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-if-nested/main.svelte new file mode 100644 index 0000000000..cfb17e3c76 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-if-nested/main.svelte @@ -0,0 +1,21 @@ + + +{#if foo} + foo +{:else if await bar} + bar +{:else} + else +{/if} + +{#if foo} + foo +{:else if !blocking} + blocking +{:else} + else +{/if} diff --git a/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/Child.svelte b/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/Child.svelte new file mode 100644 index 0000000000..6b765526c8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/Child.svelte @@ -0,0 +1,7 @@ + + +{x} diff --git a/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/_config.js b/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/_config.js new file mode 100644 index 0000000000..f2091eb6ab --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/_config.js @@ -0,0 +1,47 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + skip: true, // this fails on main, too; skip for now + async test({ assert, target, logs }) { + const [x, y, resolve] = target.querySelectorAll('button'); + + x.click(); + await tick(); + assert.deepEqual(logs, ['universe']); + + y.click(); + await tick(); + assert.deepEqual(logs, ['universe', 'world', '$effect: world']); + assert.htmlEqual( + target.innerHTML, + ` + + + + world + ` + ); + + resolve.click(); + await tick(); + assert.deepEqual(logs, [ + 'universe', + 'world', + '$effect: world', + '$effect: universe', + '$effect: universe' + ]); + assert.htmlEqual( + target.innerHTML, + ` + + + + universe + universe + universe + ` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/main.svelte new file mode 100644 index 0000000000..8edc718de2 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-state-new-branch/main.svelte @@ -0,0 +1,28 @@ + + + + + + + + +{#if x === 'universe'} + {await delay(x)} + +{/if} + +{#if y > 0} + +{/if} diff --git a/packages/svelte/tests/snapshot/samples/async-if-chain/_config.js b/packages/svelte/tests/snapshot/samples/async-if-chain/_config.js new file mode 100644 index 0000000000..2e30bbeb16 --- /dev/null +++ b/packages/svelte/tests/snapshot/samples/async-if-chain/_config.js @@ -0,0 +1,3 @@ +import { test } from '../../test'; + +export default test({ compileOptions: { experimental: { async: true } } }); diff --git a/packages/svelte/tests/snapshot/samples/async-if-chain/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/async-if-chain/_expected/client/index.svelte.js new file mode 100644 index 0000000000..b55e3010b8 --- /dev/null +++ b/packages/svelte/tests/snapshot/samples/async-if-chain/_expected/client/index.svelte.js @@ -0,0 +1,201 @@ +import 'svelte/internal/disclose-version'; +import 'svelte/internal/flags/async'; +import * as $ from 'svelte/internal/client'; + +var root = $.from_html(` `, 1); + +export default function Async_if_chain($$anchor) { + function complex1() { + return 1; + } + + let foo = true; + var blocking; + var $$promises = $.run([async () => blocking = await $.async_derived(() => foo)]); + var fragment = root(); + var node = $.first_child(fragment); + + $.async(node, [$$promises[0]], void 0, (node) => { + var consequent = ($$anchor) => { + var text = $.text('foo'); + + $.append($$anchor, text); + }; + + var consequent_1 = ($$anchor) => { + var text_1 = $.text('bar'); + + $.append($$anchor, text_1); + }; + + var alternate = ($$anchor) => { + var text_2 = $.text('else'); + + $.append($$anchor, text_2); + }; + + $.if(node, ($$render) => { + if (foo) $$render(consequent); else if (bar) $$render(consequent_1, 1); else $$render(alternate, false); + }); + }); + + var node_1 = $.sibling(node, 2); + + $.async(node_1, [$$promises[0]], [() => foo], (node_1, $$condition) => { + var consequent_2 = ($$anchor) => { + var text_3 = $.text('foo'); + + $.append($$anchor, text_3); + }; + + var consequent_3 = ($$anchor) => { + var text_4 = $.text('bar'); + + $.append($$anchor, text_4); + }; + + var alternate_2 = ($$anchor) => { + var fragment_1 = $.comment(); + var node_2 = $.first_child(fragment_1); + + $.async(node_2, [], [() => baz], (node_2, $$condition) => { + var consequent_4 = ($$anchor) => { + var text_5 = $.text('baz'); + + $.append($$anchor, text_5); + }; + + var alternate_1 = ($$anchor) => { + var text_6 = $.text('else'); + + $.append($$anchor, text_6); + }; + + $.if( + node_2, + ($$render) => { + if ($.get($$condition)) $$render(consequent_4); else $$render(alternate_1, false); + }, + true + ); + }); + + $.append($$anchor, fragment_1); + }; + + $.if(node_1, ($$render) => { + if ($.get($$condition)) $$render(consequent_2); else if (bar) $$render(consequent_3, 1); else $$render(alternate_2, false); + }); + }); + + var node_3 = $.sibling(node_1, 2); + + $.async(node_3, [$$promises[0]], [async () => (await $.save(foo))() > 10], (node_3, $$condition) => { + var consequent_5 = ($$anchor) => { + var text_7 = $.text('foo'); + + $.append($$anchor, text_7); + }; + + var consequent_6 = ($$anchor) => { + var text_8 = $.text('bar'); + + $.append($$anchor, text_8); + }; + + var alternate_4 = ($$anchor) => { + var fragment_2 = $.comment(); + var node_4 = $.first_child(fragment_2); + + $.async(node_4, [$$promises[0]], [async () => (await $.save(foo))() > 5], (node_4, $$condition) => { + var consequent_7 = ($$anchor) => { + var text_9 = $.text('baz'); + + $.append($$anchor, text_9); + }; + + var alternate_3 = ($$anchor) => { + var text_10 = $.text('else'); + + $.append($$anchor, text_10); + }; + + $.if( + node_4, + ($$render) => { + if ($.get($$condition)) $$render(consequent_7); else $$render(alternate_3, false); + }, + true + ); + }); + + $.append($$anchor, fragment_2); + }; + + $.if(node_3, ($$render) => { + if ($.get($$condition)) $$render(consequent_5); else if (bar) $$render(consequent_6, 1); else $$render(alternate_4, false); + }); + }); + + var node_5 = $.sibling(node_3, 2); + + { + var consequent_8 = ($$anchor) => { + var text_11 = $.text('foo'); + + $.append($$anchor, text_11); + }; + + var consequent_9 = ($$anchor) => { + var text_12 = $.text('bar'); + + $.append($$anchor, text_12); + }; + + var consequent_10 = ($$anchor) => { + var text_13 = $.text('baz'); + + $.append($$anchor, text_13); + }; + + var d = $.derived(() => complex1() * complex2 > 100); + + var alternate_5 = ($$anchor) => { + var text_14 = $.text('else'); + + $.append($$anchor, text_14); + }; + + $.if(node_5, ($$render) => { + if (simple1) $$render(consequent_8); else if (simple2 > 10) $$render(consequent_9, 1); else if ($.get(d)) $$render(consequent_10, 2); else $$render(alternate_5, false); + }); + } + + var node_6 = $.sibling(node_5, 2); + + $.async(node_6, [$$promises[0]], void 0, (node_6) => { + var consequent_11 = ($$anchor) => { + var text_15 = $.text('foo'); + + $.append($$anchor, text_15); + }; + + var consequent_12 = ($$anchor) => { + var text_16 = $.text('bar'); + + $.append($$anchor, text_16); + }; + + var alternate_6 = ($$anchor) => { + var text_17 = $.text('else'); + + $.append($$anchor, text_17); + }; + + $.if(node_6, ($$render) => { + if ($.get(blocking) > 10) $$render(consequent_11); else if ($.get(blocking) > 5) $$render(consequent_12, 1); else $$render(alternate_6, false); + }); + }); + + $.append($$anchor, fragment); +} \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/async-if-chain/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/async-if-chain/_expected/server/index.svelte.js new file mode 100644 index 0000000000..91315edb94 --- /dev/null +++ b/packages/svelte/tests/snapshot/samples/async-if-chain/_expected/server/index.svelte.js @@ -0,0 +1,110 @@ +import 'svelte/internal/flags/async'; +import * as $ from 'svelte/internal/server'; + +export default function Async_if_chain($$renderer) { + function complex1() { + return 1; + } + + let foo = true; + var blocking; + var $$promises = $$renderer.run([async () => blocking = await foo]); + + $$renderer.async_block([$$promises[0]], ($$renderer) => { + if (foo) { + $$renderer.push(''); + $$renderer.push(`foo`); + } else if (bar) { + $$renderer.push(''); + $$renderer.push(`bar`); + } else { + $$renderer.push(''); + $$renderer.push(`else`); + } + }); + + $$renderer.push(` `); + + $$renderer.async_block([$$promises[0]], async ($$renderer) => { + if ((await $.save(foo))()) { + $$renderer.push(''); + $$renderer.push(`foo`); + } else if (bar) { + $$renderer.push(''); + $$renderer.push(`bar`); + } else { + $$renderer.push(''); + + $$renderer.child_block(async ($$renderer) => { + if ((await $.save(baz))()) { + $$renderer.push(''); + $$renderer.push(`baz`); + } else { + $$renderer.push(''); + $$renderer.push(`else`); + } + }); + + $$renderer.push(``); + } + }); + + $$renderer.push(` `); + + $$renderer.async_block([$$promises[0]], async ($$renderer) => { + if ((await $.save(foo))() > 10) { + $$renderer.push(''); + $$renderer.push(`foo`); + } else if (bar) { + $$renderer.push(''); + $$renderer.push(`bar`); + } else { + $$renderer.push(''); + + $$renderer.async_block([$$promises[0]], async ($$renderer) => { + if ((await $.save(foo))() > 5) { + $$renderer.push(''); + $$renderer.push(`baz`); + } else { + $$renderer.push(''); + $$renderer.push(`else`); + } + }); + + $$renderer.push(``); + } + }); + + $$renderer.push(` `); + + if (simple1) { + $$renderer.push(''); + $$renderer.push(`foo`); + } else if (simple2 > 10) { + $$renderer.push(''); + $$renderer.push(`bar`); + } else if (complex1() * complex2 > 100) { + $$renderer.push(''); + $$renderer.push(`baz`); + } else { + $$renderer.push(''); + $$renderer.push(`else`); + } + + $$renderer.push(` `); + + $$renderer.async_block([$$promises[0]], ($$renderer) => { + if (blocking > 10) { + $$renderer.push(''); + $$renderer.push(`foo`); + } else if (blocking > 5) { + $$renderer.push(''); + $$renderer.push(`bar`); + } else { + $$renderer.push(''); + $$renderer.push(`else`); + } + }); + + $$renderer.push(``); +} \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/async-if-chain/index.svelte b/packages/svelte/tests/snapshot/samples/async-if-chain/index.svelte new file mode 100644 index 0000000000..1f216af0b0 --- /dev/null +++ b/packages/svelte/tests/snapshot/samples/async-if-chain/index.svelte @@ -0,0 +1,59 @@ + + + +{#if foo} + foo +{:else if bar} + bar +{:else} + else +{/if} + + +{#if await foo} + foo +{:else if bar} + bar +{:else if await baz} + baz +{:else} + else +{/if} + + +{#if await foo > 10} + foo +{:else if bar} + bar +{:else if await foo > 5} + baz +{:else} + else +{/if} + + +{#if simple1} + foo +{:else if simple2 > 10} + bar +{:else if complex1() * complex2 > 100} + baz +{:else} + else +{/if} + + +{#if blocking > 10} + foo +{:else if blocking > 5} + bar +{:else} + else +{/if} From 15fe6b85c09ab543f603f64121fb86df9dbb02f7 Mon Sep 17 00:00:00 2001 From: Mohit Kourav Date: Tue, 10 Feb 2026 20:36:26 +0530 Subject: [PATCH 02/20] feat: add warning when media.play() fails in bind:paused (#17656) * feat: add warning when media.play() fails in bind:paused * chore: fix formatting in media.js * chore: use Rich Harris's suggested approach for media.play() error handling * Apply suggestion from @Rich-Harris --------- Co-authored-by: Rich Harris --- .changeset/orange-wasps-visit.md | 5 +++++ .../src/internal/client/dom/elements/bindings/media.js | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .changeset/orange-wasps-visit.md diff --git a/.changeset/orange-wasps-visit.md b/.changeset/orange-wasps-visit.md new file mode 100644 index 0000000000..972ff636b8 --- /dev/null +++ b/.changeset/orange-wasps-visit.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: don't swallow `DOMException` when `media.play()` fails in `bind:paused` diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/media.js b/packages/svelte/src/internal/client/dom/elements/bindings/media.js index f96ee05989..87da950375 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/media.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/media.js @@ -175,8 +175,9 @@ export function bind_paused(media, get, set = get) { if (paused) { media.pause(); } else { - media.play().catch(() => { + media.play().catch((error) => { set((paused = true)); + throw error; }); } } From e3d7f3986f8b0117ce6358e1c6e54f5d5e38d3e8 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 10 Feb 2026 15:23:29 -0500 Subject: [PATCH 03/20] chore: update ESLint to v10 (#17670) * chore: update ESLint to v10 Update eslint and related plugins/configs. Bump CI lint job to Node 24 (ESLint 10 requires ^20.19.0 || ^22.13.0 || >=24). Replace removed Linter.FlatConfig type with Linter.Config. Co-Authored-By: Claude Opus 4.6 * fix: address new `no-useless-assignment` violations from ESLint 10 Co-Authored-By: Claude Opus 4.6 * dedupe --------- Co-authored-by: Claude Opus 4.6 --- .github/workflows/ci.yml | 2 +- eslint.config.js | 2 +- package.json | 18 +- .../phases/1-parse/utils/fuzzymatch.js | 3 +- .../server/visitors/shared/element.js | 2 +- packages/svelte/src/internal/client/proxy.js | 2 +- .../src/internal/client/reactivity/sources.js | 1 + pnpm-lock.yaml | 546 +++++++++--------- 8 files changed, 294 insertions(+), 282 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8dcf1e45dc..23d814d527 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,7 +86,7 @@ jobs: - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v6 with: - node-version: 18 + node-version: 24 cache: pnpm - name: install run: pnpm install --frozen-lockfile diff --git a/eslint.config.js b/eslint.config.js index 04d9294394..0e8382427b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -33,7 +33,7 @@ const no_compiler_imports = { } }; -/** @type {import('eslint').Linter.FlatConfig[]} */ +/** @type {import('eslint').Linter.Config[]} */ export default [ ...svelte_config, { diff --git a/package.json b/package.json index e7faf26c13..b305ce9cd1 100644 --- a/package.json +++ b/package.json @@ -27,22 +27,30 @@ }, "devDependencies": { "@changesets/cli": "^2.29.8", - "@sveltejs/eslint-config": "^8.3.3", + "@sveltejs/eslint-config": "^8.3.5", "@svitejs/changesets-changelog-github-compact": "^1.1.0", "@types/node": "^20.11.5", "@types/picomatch": "^4.0.2", "@vitest/coverage-v8": "^2.1.9", - "eslint": "^9.9.1", - "eslint-plugin-lube": "^0.4.3", - "eslint-plugin-svelte": "^3.11.0", + "@eslint/js": "^10.0.0", + "eslint": "^10.0.0", + "eslint-plugin-lube": "^0.5.1", + "eslint-plugin-svelte": "^3.15.0", "jsdom": "25.0.1", "playwright": "^1.58.0", "prettier": "^3.2.4", "prettier-plugin-svelte": "^3.4.0", "svelte": "workspace:^", "typescript": "^5.5.4", - "typescript-eslint": "^8.48.1", + "typescript-eslint": "^8.55.0", "v8-natives": "^1.2.5", "vitest": "^2.1.9" + }, + "pnpm": { + "peerDependencyRules": { + "allowedVersions": { + "eslint": "10" + } + } } } diff --git a/packages/svelte/src/compiler/phases/1-parse/utils/fuzzymatch.js b/packages/svelte/src/compiler/phases/1-parse/utils/fuzzymatch.js index 28b314cdd5..c8cf7f14ff 100644 --- a/packages/svelte/src/compiler/phases/1-parse/utils/fuzzymatch.js +++ b/packages/svelte/src/compiler/phases/1-parse/utils/fuzzymatch.js @@ -46,10 +46,11 @@ function levenshtein(str1, str2) { /** @type {number[]} */ const current = []; let prev = 0; - let value = 0; for (let i = 0; i <= str2.length; i++) { for (let j = 0; j <= str1.length; j++) { + let value; + if (i && j) { if (str1.charAt(j - 1) === str2.charAt(i - 1)) { value = prev; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js index f4f491c056..5bc8fb15b5 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js @@ -538,7 +538,7 @@ function build_attr_style(style_directives, expression, context, transform) { name = name.toLowerCase(); } - const property = b.init(directive.name, expression); + const property = b.init(name, expression); if (directive.modifiers.includes('important')) { important_properties.push(property); } else { diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index c8802e2672..51333e597f 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -126,7 +126,7 @@ export function proxy(value) { } var s = sources.get(prop); if (s === undefined) { - s = with_parent(() => { + with_parent(() => { var s = source(descriptor.value, stack); sources.set(prop, s); if (DEV && typeof prop === 'string') { diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index 3ef08588c4..52dd4ebe41 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -302,6 +302,7 @@ export function update_pre(source, d = 1) { var value = get(source); // @ts-expect-error + // eslint-disable-next-line no-useless-assignment -- `++`/`--` used for return value, not side effect on `value` return set(source, d === 1 ? ++value : --value); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d3e66825c..48c2a52cc5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,12 @@ importers: '@changesets/cli': specifier: ^2.29.8 version: 2.29.8(@types/node@20.19.17) + '@eslint/js': + specifier: ^10.0.0 + version: 10.0.1(eslint@10.0.0) '@sveltejs/eslint-config': - specifier: ^8.3.3 - version: 8.3.3(@stylistic/eslint-plugin-js@1.8.0(eslint@9.9.1))(eslint-config-prettier@9.1.0(eslint@9.9.1))(eslint-plugin-n@17.16.1(eslint@9.9.1)(typescript@5.5.4))(eslint-plugin-svelte@3.11.0(eslint@9.9.1)(svelte@packages+svelte))(eslint@9.9.1)(typescript-eslint@8.48.1(eslint@9.9.1)(typescript@5.5.4))(typescript@5.5.4) + specifier: ^8.3.5 + version: 8.3.5(@stylistic/eslint-plugin-js@1.8.0(eslint@10.0.0))(eslint-config-prettier@9.1.0(eslint@10.0.0))(eslint-plugin-n@17.16.1(eslint@10.0.0)(typescript@5.5.4))(eslint-plugin-svelte@3.15.0(eslint@10.0.0)(svelte@packages+svelte))(eslint@10.0.0)(typescript-eslint@8.55.0(eslint@10.0.0)(typescript@5.5.4))(typescript@5.5.4) '@svitejs/changesets-changelog-github-compact': specifier: ^1.1.0 version: 1.1.0 @@ -27,14 +30,14 @@ importers: specifier: ^2.1.9 version: 2.1.9(vitest@2.1.9(@types/node@20.19.17)(jsdom@25.0.1)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)) eslint: - specifier: ^9.9.1 - version: 9.9.1 + specifier: ^10.0.0 + version: 10.0.0 eslint-plugin-lube: - specifier: ^0.4.3 - version: 0.4.3 + specifier: ^0.5.1 + version: 0.5.1(eslint@10.0.0) eslint-plugin-svelte: - specifier: ^3.11.0 - version: 3.11.0(eslint@9.9.1)(svelte@packages+svelte) + specifier: ^3.15.0 + version: 3.15.0(eslint@10.0.0)(svelte@packages+svelte) jsdom: specifier: 25.0.1 version: 25.0.1 @@ -54,8 +57,8 @@ importers: specifier: ^5.5.4 version: 5.5.4 typescript-eslint: - specifier: ^8.48.1 - version: 8.48.1(eslint@9.9.1)(typescript@5.5.4) + specifier: ^8.55.0 + version: 8.55.0(eslint@10.0.0)(typescript@5.5.4) v8-natives: specifier: ^1.2.5 version: 1.2.5 @@ -570,8 +573,8 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -580,28 +583,49 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.18.0': - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.23.1': + resolution: {integrity: sha512-uVSdg/V4dfQmTjJzR0szNczjOH/J+FyUMMjYtr07xFRXR7EDf9i1qdxrD0VusZH9knj1/ecxzCQQxyic5NzAiA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/eslintrc@3.1.0': - resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.5.2': + resolution: {integrity: sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/js@9.9.1': - resolution: {integrity: sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@1.1.0': + resolution: {integrity: sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/object-schema@2.1.4': - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@10.0.1': + resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^10.0.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/object-schema@3.0.1': + resolution: {integrity: sha512-P9cq2dpr+LU8j3qbLygLcSZrl2/ds/pUpfnHNNuk5HW7mnngHs+6WSq5C9mO3rqRX8A1poxqLTC9cu0KOyJlBg==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/plugin-kit@0.6.0': + resolution: {integrity: sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.0': - resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} '@inquirer/external-editor@1.0.2': @@ -613,6 +637,14 @@ packages: '@types/node': optional: true + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.1': + resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} + engines: {node: 20 || >=22} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -841,8 +873,8 @@ packages: peerDependencies: acorn: ^8.9.0 - '@sveltejs/eslint-config@8.3.3': - resolution: {integrity: sha512-vkrQgEmhokFEOpuTo7NlVXJJMJJGNzxjmkQCTkHSwIOdzQSUukDIJ4038IjdcnIERSIlo4OpLAydWLx52BVyQA==} + '@sveltejs/eslint-config@8.3.5': + resolution: {integrity: sha512-f8g5v1GNQePIJq6Rh3mf0riXx+7+IsRaTS7nn8w7r2RZFPPkuBAHGcHST9BTJOQb5UCSnPmst7BJHEDIlVtP3A==} peerDependencies: '@stylistic/eslint-plugin-js': '>= 1' eslint: '>= 9' @@ -877,6 +909,9 @@ packages: '@types/eslint@8.56.12': resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -898,63 +933,63 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@typescript-eslint/eslint-plugin@8.48.1': - resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==} + '@typescript-eslint/eslint-plugin@8.55.0': + resolution: {integrity: sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.48.1 + '@typescript-eslint/parser': ^8.55.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.48.1': - resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==} + '@typescript-eslint/parser@8.55.0': + resolution: {integrity: sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.48.1': - resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==} + '@typescript-eslint/project-service@8.55.0': + resolution: {integrity: sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.48.1': - resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==} + '@typescript-eslint/scope-manager@8.55.0': + resolution: {integrity: sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.48.1': - resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==} + '@typescript-eslint/tsconfig-utils@8.55.0': + resolution: {integrity: sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.48.1': - resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==} + '@typescript-eslint/type-utils@8.55.0': + resolution: {integrity: sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.48.1': - resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==} + '@typescript-eslint/types@8.55.0': + resolution: {integrity: sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.48.1': - resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==} + '@typescript-eslint/typescript-estree@8.55.0': + resolution: {integrity: sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.48.1': - resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==} + '@typescript-eslint/utils@8.55.0': + resolution: {integrity: sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.48.1': - resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==} + '@typescript-eslint/visitor-keys@8.55.0': + resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitest/coverage-v8@2.1.9': @@ -1079,9 +1114,6 @@ packages: birpc@2.5.0: resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} @@ -1100,18 +1132,10 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - chardet@2.1.0: resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} @@ -1148,9 +1172,6 @@ packages: commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1295,8 +1316,10 @@ packages: peerDependencies: eslint: '>=8' - eslint-plugin-lube@0.4.3: - resolution: {integrity: sha512-BVO83tRo090d6a04cl45Gb761SD79cOT6wKxxWrpsH7Rv8I0SJvc79ijE11vvyxxCMiGUVq/w4NqqPJAHyYfSQ==} + eslint-plugin-lube@0.5.1: + resolution: {integrity: sha512-z01UM0LAI/Z+b9qGoVqN3RNycXbYXi6i4/QT0He58LdBVmmOd+z4tJQmvOqEh3A4TVtSQcGYq4/4wX/OebGISQ==} + peerDependencies: + eslint: '>=9.0.0' eslint-plugin-n@17.16.1: resolution: {integrity: sha512-/7FVAwjUrix9P5lycnsYRIQRwFo/DZROD+ZXWLpE+/EZWLyuLvyFaRdAPYJSz+nlAdZIZp+LAzlBerQSVYUNFg==} @@ -1304,11 +1327,11 @@ packages: peerDependencies: eslint: '>=8.23.0' - eslint-plugin-svelte@3.11.0: - resolution: {integrity: sha512-KliWlkieHyEa65aQIkRwUFfHzT5Cn4u3BQQsu3KlkJOs7c1u7ryn84EWaOjEzilbKgttT4OfBURA8Uc4JBSQIw==} + eslint-plugin-svelte@3.15.0: + resolution: {integrity: sha512-QKB7zqfuB8aChOfBTComgDptMf2yxiJx7FE04nneCmtQzgTHvY8UJkuh8J2Rz7KB9FFV9aTHX6r7rdYGvG8T9Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.1 || ^9.0.0 + eslint: ^8.57.1 || ^9.0.0 || ^10.0.0 svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: svelte: @@ -1318,6 +1341,10 @@ packages: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-scope@9.1.0: + resolution: {integrity: sha512-CkWE42hOJsNj9FJRaoMX9waUFYhqY4jmyLFdAdzZr6VaCg3ynLYx4WnOdkaIifGfH4gsUcBTn4OZbHXkpLD0FQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1326,9 +1353,13 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.9.1: - resolution: {integrity: sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.0: + resolution: {integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.0.0: + resolution: {integrity: sha512-O0piBKY36YSJhlFSG8p9VUdPV/SxxS4FYDWVpr/9GJuMaepzwlf4J8I4ov1b+ySQfDTPhc3DtLaxcT1fN0yqCg==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: jiti: '*' @@ -1343,6 +1374,10 @@ packages: resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@11.1.0: + resolution: {integrity: sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1352,8 +1387,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} esrap@2.2.2: @@ -1474,12 +1509,9 @@ packages: glob@10.5.0: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - globals@15.15.0: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} @@ -1488,6 +1520,10 @@ packages: resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} engines: {node: '>=18'} + globals@17.3.0: + resolution: {integrity: sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==} + engines: {node: '>=18'} + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -1495,9 +1531,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1544,10 +1577,6 @@ packages: immutable@4.3.7: resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1588,10 +1617,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} @@ -1751,9 +1776,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -1789,8 +1811,9 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@10.1.2: + resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} + engines: {node: 20 || >=22} minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} @@ -1883,10 +1906,6 @@ packages: package-manager-detector@0.2.11: resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} @@ -2028,10 +2047,6 @@ packages: resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} engines: {node: '>=8'} - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} @@ -2162,10 +2177,6 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2174,9 +2185,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte-eslint-parser@1.3.0: - resolution: {integrity: sha512-VCgMHKV7UtOGcGLGNFSbmdm6kEKjtzo5nnpGU/mnx4OsFY6bZ7QwRF5DUx+Hokw5Lvdyo8dpk8B1m8mliomrNg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + svelte-eslint-parser@1.4.1: + resolution: {integrity: sha512-1eqkfQ93goAhjAXxZiu1SaKI9+0/sxp4JIWQwUpsz7ybehRE5L8dNuz7Iry7K22R47p5/+s9EM+38nHV2OlgXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0, pnpm: 10.24.0} peerDependencies: svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -2203,9 +2214,6 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2268,8 +2276,8 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2283,8 +2291,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.48.1: - resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==} + typescript-eslint@8.55.0: + resolution: {integrity: sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2471,6 +2479,7 @@ packages: whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} @@ -2860,42 +2869,50 @@ snapshots: '@esbuild/win32-x64@0.25.11': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.9.1)': + '@eslint-community/eslint-utils@4.9.1(eslint@10.0.0)': dependencies: - eslint: 9.9.1 + eslint: 10.0.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.18.0': + '@eslint/config-array@0.23.1': dependencies: - '@eslint/object-schema': 2.1.4 + '@eslint/object-schema': 3.0.1 debug: 4.4.3 - minimatch: 3.1.2 + minimatch: 10.1.2 transitivePeerDependencies: - supports-color - '@eslint/eslintrc@3.1.0': + '@eslint/config-helpers@0.5.2': dependencies: - ajv: 6.12.6 - debug: 4.4.3 - espree: 10.1.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color + '@eslint/core': 1.1.0 - '@eslint/js@9.9.1': {} + '@eslint/core@1.1.0': + dependencies: + '@types/json-schema': 7.0.15 - '@eslint/object-schema@2.1.4': {} + '@eslint/js@10.0.1(eslint@10.0.0)': + optionalDependencies: + eslint: 10.0.0 + + '@eslint/object-schema@3.0.1': {} + + '@eslint/plugin-kit@0.6.0': + dependencies: + '@eslint/core': 1.1.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.0': {} + '@humanwhocodes/retry@0.4.3': {} '@inquirer/external-editor@1.0.2(@types/node@20.19.17)': dependencies: @@ -2904,6 +2921,12 @@ snapshots: optionalDependencies: '@types/node': 20.19.17 + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.1': + dependencies: + '@isaacs/balanced-match': 4.0.1 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -3087,12 +3110,12 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.52.5': optional: true - '@stylistic/eslint-plugin-js@1.8.0(eslint@9.9.1)': + '@stylistic/eslint-plugin-js@1.8.0(eslint@10.0.0)': dependencies: '@types/eslint': 8.56.12 acorn: 8.15.0 escape-string-regexp: 4.0.0 - eslint: 9.9.1 + eslint: 10.0.0 eslint-visitor-keys: 3.4.3 espree: 9.6.1 @@ -3100,16 +3123,16 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/eslint-config@8.3.3(@stylistic/eslint-plugin-js@1.8.0(eslint@9.9.1))(eslint-config-prettier@9.1.0(eslint@9.9.1))(eslint-plugin-n@17.16.1(eslint@9.9.1)(typescript@5.5.4))(eslint-plugin-svelte@3.11.0(eslint@9.9.1)(svelte@packages+svelte))(eslint@9.9.1)(typescript-eslint@8.48.1(eslint@9.9.1)(typescript@5.5.4))(typescript@5.5.4)': + '@sveltejs/eslint-config@8.3.5(@stylistic/eslint-plugin-js@1.8.0(eslint@10.0.0))(eslint-config-prettier@9.1.0(eslint@10.0.0))(eslint-plugin-n@17.16.1(eslint@10.0.0)(typescript@5.5.4))(eslint-plugin-svelte@3.15.0(eslint@10.0.0)(svelte@packages+svelte))(eslint@10.0.0)(typescript-eslint@8.55.0(eslint@10.0.0)(typescript@5.5.4))(typescript@5.5.4)': dependencies: - '@stylistic/eslint-plugin-js': 1.8.0(eslint@9.9.1) - eslint: 9.9.1 - eslint-config-prettier: 9.1.0(eslint@9.9.1) - eslint-plugin-n: 17.16.1(eslint@9.9.1)(typescript@5.5.4) - eslint-plugin-svelte: 3.11.0(eslint@9.9.1)(svelte@packages+svelte) - globals: 15.15.0 + '@stylistic/eslint-plugin-js': 1.8.0(eslint@10.0.0) + eslint: 10.0.0 + eslint-config-prettier: 9.1.0(eslint@10.0.0) + eslint-plugin-n: 17.16.1(eslint@10.0.0)(typescript@5.5.4) + eslint-plugin-svelte: 3.15.0(eslint@10.0.0)(svelte@packages+svelte) + globals: 17.3.0 typescript: 5.5.4 - typescript-eslint: 8.48.1(eslint@9.9.1)(typescript@5.5.4) + typescript-eslint: 8.55.0(eslint@10.0.0)(typescript@5.5.4) '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.0(svelte@packages+svelte)(vite@7.1.11(@types/node@24.5.2)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0)))(svelte@packages+svelte)(vite@7.1.11(@types/node@24.5.2)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))': dependencies: @@ -3146,6 +3169,8 @@ snapshots: '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 + '@types/esrecurse@4.3.1': {} + '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} @@ -3164,96 +3189,95 @@ snapshots: '@types/resolve@1.20.2': {} - '@typescript-eslint/eslint-plugin@8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.5.4))(eslint@10.0.0)(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.48.1(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 8.48.1 - '@typescript-eslint/type-utils': 8.48.1(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/utils': 8.48.1(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 8.48.1 - eslint: 9.9.1 - graphemer: 1.4.0 + '@typescript-eslint/parser': 8.55.0(eslint@10.0.0)(typescript@5.5.4) + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/type-utils': 8.55.0(eslint@10.0.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.55.0(eslint@10.0.0)(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 8.55.0 + eslint: 10.0.0 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.5.4) + ts-api-utils: 2.4.0(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.48.1(eslint@9.9.1)(typescript@5.5.4)': + '@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.5.4)': dependencies: - '@typescript-eslint/scope-manager': 8.48.1 - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 8.48.1 + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 8.55.0 debug: 4.4.3 - eslint: 9.9.1 + eslint: 10.0.0 typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.48.1(typescript@5.5.4)': + '@typescript-eslint/project-service@8.55.0(typescript@5.5.4)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.5.4) - '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.5.4) + '@typescript-eslint/types': 8.55.0 debug: 4.4.3 typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.48.1': + '@typescript-eslint/scope-manager@8.55.0': dependencies: - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/visitor-keys': 8.48.1 + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/visitor-keys': 8.55.0 - '@typescript-eslint/tsconfig-utils@8.48.1(typescript@5.5.4)': + '@typescript-eslint/tsconfig-utils@8.55.0(typescript@5.5.4)': dependencies: typescript: 5.5.4 - '@typescript-eslint/type-utils@8.48.1(eslint@9.9.1)(typescript@5.5.4)': + '@typescript-eslint/type-utils@8.55.0(eslint@10.0.0)(typescript@5.5.4)': dependencies: - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.5.4) - '@typescript-eslint/utils': 8.48.1(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.5.4) + '@typescript-eslint/utils': 8.55.0(eslint@10.0.0)(typescript@5.5.4) debug: 4.4.3 - eslint: 9.9.1 - ts-api-utils: 2.1.0(typescript@5.5.4) + eslint: 10.0.0 + ts-api-utils: 2.4.0(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.48.1': {} + '@typescript-eslint/types@8.55.0': {} - '@typescript-eslint/typescript-estree@8.48.1(typescript@5.5.4)': + '@typescript-eslint/typescript-estree@8.55.0(typescript@5.5.4)': dependencies: - '@typescript-eslint/project-service': 8.48.1(typescript@5.5.4) - '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.5.4) - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/visitor-keys': 8.48.1 + '@typescript-eslint/project-service': 8.55.0(typescript@5.5.4) + '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.5.4) + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/visitor-keys': 8.55.0 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 tinyglobby: 0.2.15 - ts-api-utils: 2.1.0(typescript@5.5.4) + ts-api-utils: 2.4.0(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.48.1(eslint@9.9.1)(typescript@5.5.4)': + '@typescript-eslint/utils@8.55.0(eslint@10.0.0)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.9.1) - '@typescript-eslint/scope-manager': 8.48.1 - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.5.4) - eslint: 9.9.1 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0) + '@typescript-eslint/scope-manager': 8.55.0 + '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.5.4) + eslint: 10.0.0 typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.48.1': + '@typescript-eslint/visitor-keys@8.55.0': dependencies: - '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/types': 8.55.0 eslint-visitor-keys: 4.2.1 '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@20.19.17)(jsdom@25.0.1)(lightningcss@1.23.0)(sass@1.70.0)(terser@5.27.0))': @@ -3380,11 +3404,6 @@ snapshots: birpc@2.5.0: {} - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -3401,8 +3420,6 @@ snapshots: cac@6.7.14: {} - callsites@3.1.0: {} - chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -3411,11 +3428,6 @@ snapshots: loupe: 3.2.1 pathval: 2.0.0 - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - chardet@2.1.0: {} check-error@2.1.1: {} @@ -3451,8 +3463,6 @@ snapshots: commondir@1.0.1: {} - concat-map@0.0.1: {} - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3599,31 +3609,33 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.5.1(eslint@9.9.1): + eslint-compat-utils@0.5.1(eslint@10.0.0): dependencies: - eslint: 9.9.1 + eslint: 10.0.0 semver: 7.7.3 - eslint-config-prettier@9.1.0(eslint@9.9.1): + eslint-config-prettier@9.1.0(eslint@10.0.0): dependencies: - eslint: 9.9.1 + eslint: 10.0.0 - eslint-plugin-es-x@7.8.0(eslint@9.9.1): + eslint-plugin-es-x@7.8.0(eslint@10.0.0): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.9.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0) '@eslint-community/regexpp': 4.12.2 - eslint: 9.9.1 - eslint-compat-utils: 0.5.1(eslint@9.9.1) + eslint: 10.0.0 + eslint-compat-utils: 0.5.1(eslint@10.0.0) - eslint-plugin-lube@0.4.3: {} + eslint-plugin-lube@0.5.1(eslint@10.0.0): + dependencies: + eslint: 10.0.0 - eslint-plugin-n@17.16.1(eslint@9.9.1)(typescript@5.5.4): + eslint-plugin-n@17.16.1(eslint@10.0.0)(typescript@5.5.4): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.9.1) - '@typescript-eslint/utils': 8.48.1(eslint@9.9.1)(typescript@5.5.4) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0) + '@typescript-eslint/utils': 8.55.0(eslint@10.0.0)(typescript@5.5.4) enhanced-resolve: 5.18.3 - eslint: 9.9.1 - eslint-plugin-es-x: 7.8.0(eslint@9.9.1) + eslint: 10.0.0 + eslint-plugin-es-x: 7.8.0(eslint@10.0.0) get-tsconfig: 4.13.0 globals: 15.15.0 ignore: 5.3.2 @@ -3634,11 +3646,11 @@ snapshots: - supports-color - typescript - eslint-plugin-svelte@3.11.0(eslint@9.9.1)(svelte@packages+svelte): + eslint-plugin-svelte@3.15.0(eslint@10.0.0)(svelte@packages+svelte): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.9.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0) '@jridgewell/sourcemap-codec': 1.5.0 - eslint: 9.9.1 + eslint: 10.0.0 esutils: 2.0.3 globals: 16.3.0 known-css-properties: 0.37.0 @@ -3646,7 +3658,7 @@ snapshots: postcss-load-config: 3.1.4(postcss@8.5.6) postcss-safe-parser: 7.0.1(postcss@8.5.6) semver: 7.7.3 - svelte-eslint-parser: 1.3.0(svelte@packages+svelte) + svelte-eslint-parser: 1.4.1(svelte@packages+svelte) optionalDependencies: svelte: link:packages/svelte transitivePeerDependencies: @@ -3657,29 +3669,39 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@9.1.0: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.8 + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} eslint-visitor-keys@4.2.1: {} - eslint@9.9.1: + eslint-visitor-keys@5.0.0: {} + + eslint@10.0.0: dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.9.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.18.0 - '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.9.1 + '@eslint/config-array': 0.23.1 + '@eslint/config-helpers': 0.5.2 + '@eslint/core': 1.1.0 + '@eslint/plugin-kit': 0.6.0 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.0 - '@nodelib/fs.walk': 1.2.8 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 ajv: 6.12.6 - chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.1.0 - esquery: 1.5.0 + eslint-scope: 9.1.0 + eslint-visitor-keys: 5.0.0 + espree: 11.1.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -3688,15 +3710,10 @@ snapshots: ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 10.1.2 natural-compare: 1.4.0 optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 transitivePeerDependencies: - supports-color @@ -3708,6 +3725,12 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 4.2.1 + espree@11.1.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 5.0.0 + espree@9.6.1: dependencies: acorn: 8.15.0 @@ -3716,7 +3739,7 @@ snapshots: esprima@4.0.1: {} - esquery@1.5.0: + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -3841,12 +3864,12 @@ snapshots: package-json-from-dist: 1.0.0 path-scurry: 1.11.1 - globals@14.0.0: {} - globals@15.15.0: {} globals@16.3.0: {} + globals@17.3.0: {} + globby@11.1.0: dependencies: array-union: 2.1.0 @@ -3858,8 +3881,6 @@ snapshots: graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - has-flag@4.0.0: {} hasown@2.0.0: @@ -3903,11 +3924,6 @@ snapshots: immutable@4.3.7: optional: true - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - imurmurhash@0.1.4: {} is-binary-path@2.1.0: @@ -3937,8 +3953,6 @@ snapshots: is-number@7.0.0: {} - is-path-inside@3.0.3: {} - is-potential-custom-element-name@1.0.1: {} is-reference@1.2.1: @@ -4102,8 +4116,6 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.merge@4.6.2: {} - lodash.startcase@4.4.0: {} loupe@3.2.1: {} @@ -4137,9 +4149,9 @@ snapshots: dependencies: mime-db: 1.52.0 - minimatch@3.1.2: + minimatch@10.1.2: dependencies: - brace-expansion: 1.1.12 + '@isaacs/brace-expansion': 5.0.1 minimatch@9.0.5: dependencies: @@ -4216,10 +4228,6 @@ snapshots: dependencies: quansync: 0.2.11 - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - parse5@7.1.2: dependencies: entities: 4.5.0 @@ -4327,8 +4335,6 @@ snapshots: regexparam@3.0.0: {} - resolve-from@4.0.0: {} - resolve-from@5.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -4466,15 +4472,13 @@ snapshots: strip-bom@3.0.0: {} - strip-json-comments@3.1.1: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 supports-preserve-symlinks-flag@1.0.0: {} - svelte-eslint-parser@1.3.0(svelte@packages+svelte): + svelte-eslint-parser@1.4.1(svelte@packages+svelte): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -4504,8 +4508,6 @@ snapshots: glob: 10.5.0 minimatch: 9.0.5 - text-table@0.2.0: {} - tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -4553,7 +4555,7 @@ snapshots: dependencies: typescript: 5.5.4 - ts-api-utils@2.1.0(typescript@5.5.4): + ts-api-utils@2.4.0(typescript@5.5.4): dependencies: typescript: 5.5.4 @@ -4566,13 +4568,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.48.1(eslint@9.9.1)(typescript@5.5.4): + typescript-eslint@8.55.0(eslint@10.0.0)(typescript@5.5.4): dependencies: - '@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/parser': 8.48.1(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.5.4) - '@typescript-eslint/utils': 8.48.1(eslint@9.9.1)(typescript@5.5.4) - eslint: 9.9.1 + '@typescript-eslint/eslint-plugin': 8.55.0(@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.5.4))(eslint@10.0.0)(typescript@5.5.4) + '@typescript-eslint/parser': 8.55.0(eslint@10.0.0)(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.5.4) + '@typescript-eslint/utils': 8.55.0(eslint@10.0.0)(typescript@5.5.4) + eslint: 10.0.0 typescript: 5.5.4 transitivePeerDependencies: - supports-color From b0ca0b84dec787697d76fe077c7acca8e102ab01 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 11 Feb 2026 16:25:14 +0100 Subject: [PATCH 04/20] fix: robustify blocker calculation (#17676) This was actually several bugs: - We used `scopes` for the blockers, that's actually the template scopes, should be `instance.scopes` instead - We missed setting the scope for `touch` - We didn't take return statements into account when calculating blockers. We cannot know when/if something within the return statement is called, so we gotta assume it is and touch everything transitively from it Combined this fixes #17667 (and possibly other cases not showing up in the issue tracker yet) Initially I just thought "ok I guess we have to traverse into functions, too" but then I thought that feels too unoptimized and came up with the return-statement-inspection, at which point I discovered the other bugs. ### Before submitting the PR, please make sure you do the following - [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs - [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`. - [x] This message body should clearly illustrate what problems it solves. - [x] Ideally, include a test that fails without this PR but passes with it. - [x] If this PR changes code within `packages/svelte/src`, add a changeset (`npx changeset`). ### Tests and linting - [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` --- .changeset/true-cities-retire.md | 5 ++ .../src/compiler/phases/2-analyze/index.js | 61 ++++++++++++------- .../_config.js | 14 +++++ .../main.svelte | 41 +++++++++++++ 4 files changed, 99 insertions(+), 22 deletions(-) create mode 100644 .changeset/true-cities-retire.md create mode 100644 packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/main.svelte diff --git a/.changeset/true-cities-retire.md b/.changeset/true-cities-retire.md new file mode 100644 index 0000000000..c1846e9267 --- /dev/null +++ b/.changeset/true-cities-retire.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: robustify blocker calculation diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index ef0b35f560..969af842cc 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -690,7 +690,7 @@ export function analyze_component(root, source, options) { } } - calculate_blockers(instance, scopes, analysis); + calculate_blockers(instance, analysis); if (analysis.runes) { const props_refs = module.scope.references.get('$$props'); @@ -940,11 +940,10 @@ export function analyze_component(root, source, options) { * top level statements. This includes indirect blockers such as functions referencing async top level statements. * * @param {Js} instance - * @param {Map} scopes * @param {ComponentAnalysis} analysis * @returns {void} */ -function calculate_blockers(instance, scopes, analysis) { +function calculate_blockers(instance, analysis) { /** * @param {ESTree.Node} expression * @param {Scope} scope @@ -959,6 +958,14 @@ function calculate_blockers(instance, scopes, analysis) { expression, { scope }, { + _(node, context) { + const scope = instance.scopes.get(node); + if (scope) { + context.next({ scope }); + } else { + context.next(); + } + }, ImportDeclaration(node) {}, Identifier(node, context) { const parent = /** @type {ESTree.Node} */ (context.path.at(-1)); @@ -979,14 +986,11 @@ function calculate_blockers(instance, scopes, analysis) { /** * @param {ESTree.Node} node - * @param {Set} seen * @param {Set} reads * @param {Set} writes + * @param {Scope} scope */ - const trace_references = (node, reads, writes, seen = new Set()) => { - if (seen.has(node)) return; - seen.add(node); - + const trace_references = (node, reads, writes, scope) => { /** * @param {ESTree.Pattern} node * @param {Scope} scope @@ -1005,10 +1009,10 @@ function calculate_blockers(instance, scopes, analysis) { walk( node, - { scope: instance.scope }, + { scope }, { _(node, context) { - const scope = scopes.get(node); + const scope = instance.scopes.get(node); if (scope) { context.next({ scope }); } else { @@ -1040,10 +1044,6 @@ function calculate_blockers(instance, scopes, analysis) { writes.add(b); } }, - // don't look inside functions until they are called - ArrowFunctionExpression(_, context) {}, - FunctionDeclaration(_, context) {}, - FunctionExpression(_, context) {}, Identifier(node, context) { const parent = /** @type {ESTree.Node} */ (context.path.at(-1)); if (is_reference(node, parent)) { @@ -1052,7 +1052,19 @@ function calculate_blockers(instance, scopes, analysis) { reads.add(binding); } } - } + }, + ReturnStatement(node, context) { + // We have to assume that anything returned from a function, even if it's a function itself, + // might be called immediately, so we have to touch all references within it. Example: + // function foo() { return () => blocker; } foo(); // blocker is touched + if (node.argument) { + touch(node.argument, context.state.scope, reads); + } + }, + // don't look inside functions until they are called + ArrowFunctionExpression(_, context) {}, + FunctionDeclaration(_, context) {}, + FunctionExpression(_, context) {} } ); }; @@ -1132,7 +1144,7 @@ function calculate_blockers(instance, scopes, analysis) { /** @type {Set} */ const writes = new Set(); - trace_references(declarator, reads, writes); + trace_references(declarator, reads, writes, instance.scope); const blocker = /** @type {NonNullable} */ ( b.member(promises, b.literal(analysis.instance_body.async.length), true) @@ -1160,7 +1172,7 @@ function calculate_blockers(instance, scopes, analysis) { /** @type {Set} */ const writes = new Set(); - trace_references(node, reads, writes); + trace_references(node, reads, writes, instance.scope); const blocker = /** @type {NonNullable} */ ( b.member(promises, b.literal(analysis.instance_body.async.length), true) @@ -1184,12 +1196,17 @@ function calculate_blockers(instance, scopes, analysis) { for (const fn of functions) { /** @type {Set} */ const reads_writes = new Set(); - const body = + const init = fn.type === 'VariableDeclarator' - ? /** @type {ESTree.FunctionExpression | ESTree.ArrowFunctionExpression} */ (fn.init).body - : fn.body; - - trace_references(body, reads_writes, reads_writes); + ? /** @type {ESTree.FunctionExpression | ESTree.ArrowFunctionExpression} */ (fn.init) + : fn; + + trace_references( + init.body, + reads_writes, + reads_writes, + /** @type {Scope} */ (instance.scopes.get(init)) + ); const max = [...reads_writes].reduce((max, binding) => { if (binding.blocker) { diff --git a/packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/_config.js b/packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/_config.js new file mode 100644 index 0000000000..080e2d278c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/_config.js @@ -0,0 +1,14 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['async-server', 'client', 'hydrate'], + ssrHtml: 'true true true true true', + + async test({ assert, target }) { + await new Promise((resolve) => setTimeout(resolve, 10)); + await tick(); + + assert.htmlEqual(target.innerHTML, 'true true true true true'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/main.svelte new file mode 100644 index 0000000000..5f79a14830 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-bind-factory-function-remote/main.svelte @@ -0,0 +1,41 @@ + + + +{#if true} + {checkedFactory()()} +{/if} +{#if true} + {indirectCheckedFactory()()} +{/if} +{#if true} + {callFactory(checkedFactory)()} +{/if} +{#if true} + {indirectCallFactory()()} +{/if} +{#if true} + {indirectChecked2()()} +{/if} From 3c6bb6faba559d23dac95eb8cd1d10db190ee4a7 Mon Sep 17 00:00:00 2001 From: Manuel <30698007+manuel3108@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:36:54 +0100 Subject: [PATCH 05/20] chore: provide proper public type for `parseCss` result (#17654) Currently, the [newly introduced `parseCss` from `svelte/compiler`](https://github.com/sveltejs/svelte/pull/17496) returns `Omit`. If you try to work with this in external tooling, everywhere where you pass around the result of this method, you need to use that type as well, which is quite cumbersome. (I'm trying to integrate this into `sv` to get rid of a workaround) This creates a new type in the CSS AST to differentiate between one stylesheet only having the roles, and one beeing the full one that is used in `parse` itself. Im 100% open on the name of the new type or any better ideas. ### Before submitting the PR, please make sure you do the following - [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs - [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`. - [x] This message body should clearly illustrate what problems it solves. - [ ] Ideally, include a test that fails without this PR but passes with it. - [x] If this PR changes code within `packages/svelte/src`, add a changeset (`npx changeset`). ### Tests and linting - [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` --------- Co-authored-by: Rich Harris --- .changeset/tender-pugs-hide.md | 5 +++++ packages/svelte/src/compiler/index.js | 4 ++-- packages/svelte/src/compiler/types/css.d.ts | 11 +++++++++-- packages/svelte/tests/css-parse.test.ts | 6 +++--- packages/svelte/types/index.d.ts | 13 ++++++++++--- 5 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 .changeset/tender-pugs-hide.md diff --git a/.changeset/tender-pugs-hide.md b/.changeset/tender-pugs-hide.md new file mode 100644 index 0000000000..260f49614e --- /dev/null +++ b/.changeset/tender-pugs-hide.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: provide proper public type for `parseCss` result diff --git a/packages/svelte/src/compiler/index.js b/packages/svelte/src/compiler/index.js index acfef6a320..e864c4a1f4 100644 --- a/packages/svelte/src/compiler/index.js +++ b/packages/svelte/src/compiler/index.js @@ -123,7 +123,7 @@ export function parse(source, { modern, loose } = {}) { * The parseCss function parses a CSS stylesheet, returning its abstract syntax tree. * * @param {string} source The CSS source code - * @returns {Omit} + * @returns {AST.CSS.StyleSheetFile} */ export function parseCss(source) { source = remove_bom(source); @@ -135,7 +135,7 @@ export function parseCss(source) { const children = parse_stylesheet(parser); return { - type: 'StyleSheet', + type: 'StyleSheetFile', start: 0, end: source.length, children diff --git a/packages/svelte/src/compiler/types/css.d.ts b/packages/svelte/src/compiler/types/css.d.ts index 154a06ffb1..13eb880d83 100644 --- a/packages/svelte/src/compiler/types/css.d.ts +++ b/packages/svelte/src/compiler/types/css.d.ts @@ -6,10 +6,17 @@ export namespace _CSS { end: number; } - export interface StyleSheet extends BaseNode { + export interface StyleSheetBase extends BaseNode { + children: Array; + } + + export interface StyleSheetFile extends StyleSheetBase { + type: 'StyleSheetFile'; + } + + export interface StyleSheet extends StyleSheetBase { type: 'StyleSheet'; attributes: any[]; // TODO - children: Array; content: { start: number; end: number; diff --git a/packages/svelte/tests/css-parse.test.ts b/packages/svelte/tests/css-parse.test.ts index 4d8ef8601b..3a53e97955 100644 --- a/packages/svelte/tests/css-parse.test.ts +++ b/packages/svelte/tests/css-parse.test.ts @@ -4,7 +4,7 @@ import { parseCss } from 'svelte/compiler'; describe('parseCss', () => { it('parses a simple rule', () => { const ast = parseCss('div { color: red; }'); - assert.equal(ast.type, 'StyleSheet'); + assert.equal(ast.type, 'StyleSheetFile'); assert.equal(ast.children.length, 1); assert.equal(ast.children[0].type, 'Rule'); }); @@ -57,7 +57,7 @@ describe('parseCss', () => { it('parses empty stylesheet', () => { const ast = parseCss(''); - assert.equal(ast.type, 'StyleSheet'); + assert.equal(ast.type, 'StyleSheetFile'); assert.equal(ast.children.length, 0); assert.equal(ast.start, 0); assert.equal(ast.end, 0); @@ -138,7 +138,7 @@ describe('parseCss', () => { it('parses escaped characters', () => { const ast = parseCss("div { background: url('./example.png?\\''); }"); - assert.equal(ast.type, 'StyleSheet'); + assert.equal(ast.type, 'StyleSheetFile'); assert.equal(ast.children.length, 1); const rule = ast.children[0]; assert.equal(rule.type, 'Rule'); diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 62c0e210be..e7aa5395b8 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -889,7 +889,7 @@ declare module 'svelte/compiler' { * * @param source The CSS source code * */ - export function parseCss(source: string): Omit; + export function parseCss(source: string): AST.CSS.StyleSheetFile; /** * @deprecated Replace this with `import { walk } from 'estree-walker'` * */ @@ -1673,10 +1673,17 @@ declare module 'svelte/compiler' { end: number; } - export interface StyleSheet extends BaseNode { + export interface StyleSheetBase extends BaseNode { + children: Array; + } + + export interface StyleSheetFile extends StyleSheetBase { + type: 'StyleSheetFile'; + } + + export interface StyleSheet extends StyleSheetBase { type: 'StyleSheet'; attributes: any[]; // TODO - children: Array; content: { start: number; end: number; From 684cdba2538bd7cfc695fcd8516ecbd21b3c08b5 Mon Sep 17 00:00:00 2001 From: Artyom Alekseevich <47069814+FrankFMY@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:53:23 +0100 Subject: [PATCH 06/20] fix: resolve effect_update_depth_exceeded with select bind:value in legacy mode (#17645) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixes #13768 `` elements, and call `invalidate_inner_signals` inline at the mutation point in `AssignmentExpression` — only when the binding is actually mutated, avoiding the read-write cycle. Based on the approach outlined in #16200. ## Changes - **`scope.js`**: Add `legacy_indirect_bindings` field to `Binding` class - **`RegularElement.js` (analyze)**: For `` with derived state in legacy mode diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js index c7b40109a3..bc65bd65db 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js @@ -16,6 +16,8 @@ import { regex_starts_with_newline } from '../../patterns.js'; import { check_element } from './shared/a11y/index.js'; import { validate_element } from './shared/element.js'; import { mark_subtree_dynamic } from './shared/fragment.js'; +import { object } from '../../../utils/ast.js'; +import { runes } from '../../../state.js'; /** * @param {AST.RegularElement} node @@ -64,6 +66,34 @@ export function RegularElement(node, context) { } } + // Special case: ` + + + + + `, + + async test({ assert, target, window, variant }) { + assert.htmlEqual( + target.innerHTML, + ` + + ` + ); + + const [select] = target.querySelectorAll('select'); + const options = target.querySelectorAll('option'); + + assert.equal(select.value, ''); + + const change = new window.Event('change'); + + // Select "UK" + options[2].selected = true; + await select.dispatchEvent(change); + + assert.equal(select.value, 'uk'); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-select-reactive-derived/main.svelte b/packages/svelte/tests/runtime-legacy/samples/binding-select-reactive-derived/main.svelte new file mode 100644 index 0000000000..57342347f5 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/binding-select-reactive-derived/main.svelte @@ -0,0 +1,21 @@ + + + From 015e744962e46a13011f8c7e3cdd4db7c9f742ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 16:08:12 -0500 Subject: [PATCH 07/20] Version Packages (#17668) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## svelte@5.50.2 ### Patch Changes - fix: resolve `effect_update_depth_exceeded` when using `bind:value` on `` with derived state in legacy mode diff --git a/.changeset/orange-wasps-visit.md b/.changeset/orange-wasps-visit.md deleted file mode 100644 index 972ff636b8..0000000000 --- a/.changeset/orange-wasps-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: don't swallow `DOMException` when `media.play()` fails in `bind:paused` diff --git a/.changeset/tender-pugs-hide.md b/.changeset/tender-pugs-hide.md deleted file mode 100644 index 260f49614e..0000000000 --- a/.changeset/tender-pugs-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -chore: provide proper public type for `parseCss` result diff --git a/.changeset/true-cities-retire.md b/.changeset/true-cities-retire.md deleted file mode 100644 index c1846e9267..0000000000 --- a/.changeset/true-cities-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: robustify blocker calculation diff --git a/.changeset/wild-dolls-hang.md b/.changeset/wild-dolls-hang.md deleted file mode 100644 index a7b3436d69..0000000000 --- a/.changeset/wild-dolls-hang.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: reduce if block nesting diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 3fcc8edfc1..5882398fb0 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,19 @@ # svelte +## 5.50.2 + +### Patch Changes + +- fix: resolve `effect_update_depth_exceeded` when using `bind:value` on `