Skip to content

Commit a87e40b

Browse files
authored
fix(prefer-destructured-store-props): handle runes properly (#1440)
1 parent 817b137 commit a87e40b

File tree

8 files changed

+61
-0
lines changed

8 files changed

+61
-0
lines changed

.changeset/wet-kiwis-cover.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': patch
3+
---
4+
5+
fix(prefer-destructured-store-props): handle runes properly

packages/eslint-plugin-svelte/src/rules/prefer-destructured-store-props.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { keyword } from 'esutils';
55
import type { SuggestionReportDescriptor } from '../types.js';
66
import { createRule } from '../utils/index.js';
77
import { findAttribute, isExpressionIdentifier, findVariable } from '../utils/ast-utils.js';
8+
import { getSvelteContext } from '../utils/svelte-context.js';
9+
import { SVELTE_RUNES } from '../shared/runes.js';
810

911
type StoreMemberExpression = TSESTree.MemberExpression & {
1012
object: TSESTree.Identifier & { name: string };
@@ -29,6 +31,7 @@ export default createRule('prefer-destructured-store-props', {
2931
},
3032
create(context) {
3133
let mainScript: AST.SvelteScriptElement | null = null;
34+
const svelteContext = getSvelteContext(context);
3235

3336
// Store off instances of probably-destructurable statements
3437
const reports: StoreMemberExpression[] = [];
@@ -150,6 +153,8 @@ export default createRule('prefer-destructured-store-props', {
150153
node: StoreMemberExpression
151154
) {
152155
if (inScriptElement) return; // Within a script tag
156+
// Skip Svelte 5 runes (e.g., $derived.by, $state.raw, $effect.pre)
157+
if (svelteContext?.runes === true && SVELTE_RUNES.has(node.object.name)) return;
153158
storeMemberAccessStack.unshift({ node, identifiers: [] });
154159
},
155160
Identifier(node: TSESTree.Identifier) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const SVELTE_RUNES = new Set([
2+
'$state',
3+
'$derived',
4+
'$effect',
5+
'$props',
6+
'$bindable',
7+
'$inspect',
8+
'$host'
9+
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
- message: Destructure foo from $store for better change tracking & fewer redraws
2+
line: 10
3+
column: 18
4+
suggestions:
5+
- desc: 'Using destructuring like $: ({ foo } = $store); will run faster'
6+
messageId: fixUseDestructuring
7+
output: |
8+
<script>
9+
import store from './store.js';
10+
let count = $state(0);
11+
let doubled = $derived.by(() => count * 2);
12+
$: ({ foo } = $store);
13+
</script>
14+
15+
<!-- $state and $derived.by should be ignored (runes), but $store.foo should be reported -->
16+
<p>Count: {count}</p>
17+
<p>Doubled: {doubled}</p>
18+
<p>Store value: {foo}</p>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
import store from './store.js';
3+
let count = $state(0);
4+
let doubled = $derived.by(() => count * 2);
5+
</script>
6+
7+
<!-- $state and $derived.by should be ignored (runes), but $store.foo should be reported -->
8+
<p>Count: {count}</p>
9+
<p>Doubled: {doubled}</p>
10+
<p>Store value: {$store.foo}</p>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"svelte": ">=5.0.0-0"
3+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export class Test {
2+
a = $state(0);
3+
b = $derived.by(() => this.a * 2);
4+
5+
output() {
6+
console.log(this.a, this.b);
7+
}
8+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"svelte": ">=5.0.0-0"
3+
}

0 commit comments

Comments
 (0)