From dd9fc0d1ad948f264a48e2ebdf4f7f5fb8ddb876 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 11:00:50 +0100 Subject: [PATCH] Warn on non-destructured `$props()` reads in runes mode (#17708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Non-destructured `$props()` access in runes mode silently skipped the `state_referenced_locally` warning, leading to missed guidance when users read `props` via identifiers or member expressions. - **Analyzer behavior** - Include `rest_prop` bindings in `state_referenced_locally` detection so reads of `$props()` identifiers warn consistently with destructured props. - **Validation coverage** - Add a validator fixture for `$props()` identifiers and update the `props-identifier` snapshot expectations to capture the new warnings. Example: ```svelte ```
Original prompt > > ---- > > *This section details on the original issue you should resolve* > > False negative for `state_referenced_locally` warning on not destructured `$props` access? > ### Describe the bug > > I was looking for a workaround for sveltejs/svelte#17669 and thought of not destructuring the `$props` directly; to my surprise there were no warnings at all. > > > ### Reproduction > > ```js > const props = $props(); > const { model } = props; // missing warning > > const value = props.model.value; // missing warning > ``` > > [Playground](https://svelte.dev/playground/untitled?version=5.50.2#H4sIAAAAAAAACn2QT4vCQAzFv0oIe1CQ9l51YY97lj1tPYxtXAam6TAT_1H63U0HUax1j3nvJeT3OmTTEBb4w2LFUY0L3FtHEYvfDuXiB28QVL8lv7zP4pGcDNrORJrSq5aFWPQMrmIVrJfPkktROQp00LQ1OehhDR8-tD7O5ku174GjcQdSM8WyNC0hz4HOniqhGk4msOW_klf54zrPNkTwzVUbgsZuz8z1G6GzYCHhQP3iDdV47Zltwv2XMEGN6Cbgk5vIGhujAj3AXstI4WxcycvivZFn7q1OxrqT5RqLvXGR-itXywVk_AEAAA) > > ### Logs > > ```shell > > ``` > > ### System Info > > ```shell > REPL - Svelte v.5.50.2 > ``` > > ### Severity > > annoyance > > ## Comments on the Issue (you are @copilot in this section) > > > >
- Fixes sveltejs/svelte#17685 --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Rich-Harris <1162160+Rich-Harris@users.noreply.github.com> Co-authored-by: Rich Harris Co-authored-by: Paolo Ricciuti --- .changeset/loose-baboons-visit.md | 5 + .../phases/2-analyze/visitors/Identifier.js | 3 +- .../client/index.svelte.warnings.json | 142 ++++++++++++++++++ .../server/index.svelte.warnings.json | 142 ++++++++++++++++++ .../input.svelte | 6 + .../warnings.json | 26 ++++ 6 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 .changeset/loose-baboons-visit.md create mode 100644 packages/svelte/tests/snapshot/samples/props-identifier/_expected/client/index.svelte.warnings.json create mode 100644 packages/svelte/tests/snapshot/samples/props-identifier/_expected/server/index.svelte.warnings.json create mode 100644 packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/input.svelte create mode 100644 packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/warnings.json diff --git a/.changeset/loose-baboons-visit.md b/.changeset/loose-baboons-visit.md new file mode 100644 index 0000000000..09c50deb5e --- /dev/null +++ b/.changeset/loose-baboons-visit.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: emit state_referenced_locally warning for non-destructured props diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js index 9daae33dd7..5c1e8031b8 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js @@ -115,7 +115,8 @@ export function Identifier(node, context) { !should_proxy(binding.initial.arguments[0], context.state.scope)))) || binding.kind === 'raw_state' || binding.kind === 'derived' || - binding.kind === 'prop') && + binding.kind === 'prop' || + binding.kind === 'rest_prop') && // We're only concerned with reads here (parent.type !== 'AssignmentExpression' || parent.left !== node) && parent.type !== 'UpdateExpression' diff --git a/packages/svelte/tests/snapshot/samples/props-identifier/_expected/client/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/props-identifier/_expected/client/index.svelte.warnings.json new file mode 100644 index 0000000000..81149a92f8 --- /dev/null +++ b/packages/svelte/tests/snapshot/samples/props-identifier/_expected/client/index.svelte.warnings.json @@ -0,0 +1,142 @@ +[ + { + "code": "state_referenced_locally", + "message": "This reference only captures the initial value of `props`. Did you mean to reference it inside a closure instead?\nhttps://svelte.dev/e/state_referenced_locally", + "filename": "packages/svelte/tests/snapshot/samples/props-identifier/index.svelte", + "start": { + "line": 3, + "column": 1, + "character": 33 + }, + "end": { + "line": 3, + "column": 6, + "character": 38 + }, + "position": [ + 33, + 38 + ], + "frame": "1: " + }, + { + "code": "state_referenced_locally", + "message": "This reference only captures the initial value of `props`. Did you mean to reference it inside a closure instead?\nhttps://svelte.dev/e/state_referenced_locally", + "filename": "packages/svelte/tests/snapshot/samples/props-identifier/index.svelte", + "start": { + "line": 9, + "column": 1, + "character": 120 + }, + "end": { + "line": 9, + "column": 6, + "character": 125 + }, + "position": [ + 120, + 125 + ], + "frame": " 7: props.a = true;\n 8: props[a] = true;\n 9: props;\n ^\n10: \n11: " + } +] \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/props-identifier/_expected/server/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/props-identifier/_expected/server/index.svelte.warnings.json new file mode 100644 index 0000000000..81149a92f8 --- /dev/null +++ b/packages/svelte/tests/snapshot/samples/props-identifier/_expected/server/index.svelte.warnings.json @@ -0,0 +1,142 @@ +[ + { + "code": "state_referenced_locally", + "message": "This reference only captures the initial value of `props`. Did you mean to reference it inside a closure instead?\nhttps://svelte.dev/e/state_referenced_locally", + "filename": "packages/svelte/tests/snapshot/samples/props-identifier/index.svelte", + "start": { + "line": 3, + "column": 1, + "character": 33 + }, + "end": { + "line": 3, + "column": 6, + "character": 38 + }, + "position": [ + 33, + 38 + ], + "frame": "1: " + }, + { + "code": "state_referenced_locally", + "message": "This reference only captures the initial value of `props`. Did you mean to reference it inside a closure instead?\nhttps://svelte.dev/e/state_referenced_locally", + "filename": "packages/svelte/tests/snapshot/samples/props-identifier/index.svelte", + "start": { + "line": 9, + "column": 1, + "character": 120 + }, + "end": { + "line": 9, + "column": 6, + "character": 125 + }, + "position": [ + 120, + 125 + ], + "frame": " 7: props.a = true;\n 8: props[a] = true;\n 9: props;\n ^\n10: \n11: " + } +] \ No newline at end of file diff --git a/packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/input.svelte b/packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/input.svelte new file mode 100644 index 0000000000..980debdfaf --- /dev/null +++ b/packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/input.svelte @@ -0,0 +1,6 @@ + diff --git a/packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/warnings.json b/packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/warnings.json new file mode 100644 index 0000000000..b1385037e1 --- /dev/null +++ b/packages/svelte/tests/validator/samples/state-referenced-locally-props-identifier/warnings.json @@ -0,0 +1,26 @@ +[ + { + "code": "state_referenced_locally", + "message": "This reference only captures the initial value of `props`. Did you mean to reference it inside a closure instead?", + "start": { + "line": 3, + "column": 19 + }, + "end": { + "line": 3, + "column": 24 + } + }, + { + "code": "state_referenced_locally", + "message": "This reference only captures the initial value of `props`. Did you mean to reference it inside a closure instead?", + "start": { + "line": 4, + "column": 15 + }, + "end": { + "line": 4, + "column": 20 + } + } +]