Skip to content

feat(js/nursery): add noSvelteNoUnnecessaryStateWrap rule#10545

Merged
ematipico merged 13 commits into
biomejs:mainfrom
Mokto:feat/no-svelte-no-unnecessary-state-wrap
Jun 24, 2026
Merged

feat(js/nursery): add noSvelteNoUnnecessaryStateWrap rule#10545
ematipico merged 13 commits into
biomejs:mainfrom
Mokto:feat/no-svelte-no-unnecessary-state-wrap

Conversation

@Mokto

@Mokto Mokto commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

This PR was written primarily by Claude Code.

Summary

Adds the noSvelteUnnecessaryStateWrap nursery rule, which reports unnecessary $state() wrapping of classes from svelte/reactivity that are already deeply reactive.

Closes part of #10540.

Reported classes (from svelte/reactivity): SvelteSet, SvelteMap, SvelteURL, SvelteURLSearchParams, SvelteDate, MediaQuery.

Options:

  • additionalReactiveClasses — extend the list with custom reactive classes
  • allowReassign — suppress the report for variables that are reassigned after declaration (requires $state to track the reference change)

Fix: unsafe — strips the $state() wrapper, leaving just the inner expression.

Test Plan

  • 6 invalid cases covering all built-in reactive classes
  • Valid usage (no wrapper, different import source)
  • allowReassign: true with a reassigned variable → no diagnostic
  • allowReassign: true with a non-reassigned variable → still flagged
  • additionalReactiveClasses: ["MyReactiveClass"] → custom class flagged

8 snapshot tests, all green.

Docs

Rule documentation is inline (rustdoc). N/A for website PR.

@changeset-bot

changeset-bot Bot commented Jun 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 987c199

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

✅ Organic activity

No automation signals detected in the analyzed events.

View full analysis →

This is an automated analysis by AgentScan

@github-actions github-actions Bot added A-CLI Area: CLI A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis L-HTML Language: HTML and super languages labels Jun 2, 2026
@Mokto Mokto force-pushed the feat/no-svelte-no-unnecessary-state-wrap branch from 6bc6e89 to ab01ffa Compare June 2, 2026 20:07
@github-actions github-actions Bot removed the L-HTML Language: HTML and super languages label Jun 2, 2026
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR introduces noSvelteUnnecessaryStateWrap, a new Svelte nursery linter rule that flags redundant $state() wrapping of reactive classes from svelte/reactivity. The rule identifies $state(new X(...)) or $state(X(...)) patterns where X is a reactive class (built-in such as SvelteMap or custom via options), validates that built-in classes are imported from the correct module, and offers an unsafe autofix to unwrap the expression. The implementation includes comprehensive test fixtures covering invalid, valid, and configurable scenarios with allowReassign option support.

Suggested reviewers

  • ematipico
  • dyc3
🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'feat(js/nursery): add noSvelteNoUnnecessaryStateWrap rule' contains a typo—it says 'noSvelteNoUnnecessaryStateWrap' but the actual rule name throughout the changeset is 'noSvelteUnnecessaryStateWrap' (missing 'No' in the middle). Correct the title to 'feat(js/nursery): add noSvelteUnnecessaryStateWrap rule' to match the actual rule name implemented in the changeset.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the rule's purpose, options, test coverage, and documentation status, all of which align directly with the changeset's additions and modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/add-svelte-no-unnecessary-state-wrap.md:
- Around line 1-5: Update the changeset to use a minor bump instead of patch for
the new nursery rule: change the release type from "patch" to "minor" in the
.changeset/add-svelte-no-unnecessary-state-wrap.md file so the addition of the
noSvelteNoUnnecessaryStateWrap rule is published as a non-breaking feature
targeting the next branch; keep the current rule slug as-is for now but note the
rule name (noSvelteNoUnnecessaryStateWrap / no-svelte-no-unnecessary-state-wrap)
will be renamed later and adjust the changeset if that slug changes before
release.

In
`@crates/biome_js_analyze/src/lint/nursery/no_svelte_no_unnecessary_state_wrap.rs`:
- Around line 63-71: Rename the rule to remove the redundant "No": change the
type and identifier NoSvelteNoUnnecessaryStateWrap to
NoSvelteUnnecessaryStateWrap and update the "name" value from
"noSvelteNoUnnecessaryStateWrap" to "noSvelteUnnecessaryStateWrap"; also rename
related symbols and resources (NoSvelteNoUnnecessaryStateWrapOptions →
NoSvelteUnnecessaryStateWrapOptions, the source file name, registry/module
entries that reference NoSvelteNoUnnecessaryStateWrap, the test spec directory
for this rule, and the changeset documentation link) so all references
consistently use NoSvelteUnnecessaryStateWrap.

In
`@crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/invalid.svelte`:
- Around line 1-13: Add a new spec that exercises the additionalReactiveClasses
option by creating a custom reactive class instance wrapped in $state(...) so
the rule emits the same "unnecessary state wrap" diagnostics as for built-ins;
include an .options.json for that fixture with additionalReactiveClasses listing
your custom class name and set allowReassign: false to exercise the reassignment
path, and mirror the invalid.svelte pattern (i.e., const foo = $state(new
YourCustomClass())) so the analyzer flags it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a93d2453-1cf7-43ef-9865-246d4d7af9f5

📥 Commits

Reviewing files that changed from the base of the PR and between 99bc7df and ab01ffa.

⛔ Files ignored due to path filters (10)
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/domain_selector.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/invalid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.svelte.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (8)
  • .changeset/add-svelte-no-unnecessary-state-wrap.md
  • crates/biome_js_analyze/src/lint/nursery/no_svelte_no_unnecessary_state_wrap.rs
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/invalid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.svelte
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_svelte_no_unnecessary_state_wrap.rs

Comment thread .changeset/add-svelte-no-unnecessary-state-wrap.md Outdated
Comment thread crates/biome_js_analyze/src/lint/nursery/no_svelte_no_unnecessary_state_wrap.rs Outdated
@codspeed-hq

codspeed-hq Bot commented Jun 2, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 59 untouched benchmarks
⏩ 195 skipped benchmarks1


Comparing Mokto:feat/no-svelte-no-unnecessary-state-wrap (987c199) with main (d9b5133)

Open in CodSpeed

Footnotes

  1. 195 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Mokto Mokto force-pushed the feat/no-svelte-no-unnecessary-state-wrap branch 2 times, most recently from dea65cd to 9d19921 Compare June 3, 2026 02:47
@Mokto Mokto changed the title WIP: feat(js/nursery): add noSvelteNoUnnecessaryStateWrap rule feat(js/nursery): add noSvelteNoUnnecessaryStateWrap rule Jun 3, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.svelte (1)

6-6: 💤 Low value

Consider let here for a sharper test.

With const, reassignment is impossible, so this only confirms "no reassignment ⇒ still flagged" in a context where reassignment couldn't happen anyway. A let map = $state(new SvelteMap()); (never reassigned) would exercise the all_writes skip branch more meaningfully. Optional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.svelte`
at line 6, Change the test variable declaration from immutable to mutable so the
linter's "all_writes" skip path is exercised: replace the const declaration of
map created with $state(new SvelteMap()) by using let (i.e., declare map with
let map = $state(new SvelteMap());) while keeping the variable unmodified in the
test so the scenario remains "never reassigned" but allows the analyzer to
consider reassignment-capable bindings for the all_writes branch.
crates/biome_js_analyze/src/lint/nursery/no_svelte_unnecessary_state_wrap.rs (1)

37-41: ⚡ Quick win

Options lack the standard documentation block.

The rule exposes additionalReactiveClasses and allowReassign, but the rustdoc only mentions them in prose. Contributor docs ask for a default-value statement, a JSON options block, and an example using use_options for each option. As per coding guidelines, "Rule documentation for options must include a default value statement, a JSON options block, and a code example with the expect_diagnostic or use_options directive".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/nursery/no_svelte_unnecessary_state_wrap.rs`
around lines 37 - 41, Update the rustdoc for the rule in
no_svelte_unnecessary_state_wrap.rs to include standard option docs: add a
default-value sentence for each option (additionalReactiveClasses defaults to an
empty array, allowReassign defaults to false), add a JSON options block showing
both options and their default values, and add a short code example
demonstrating use_options or expect_diagnostic that configures each option (one
example showing additionalReactiveClasses set and one showing allowReassign:
true). Ensure these additions are placed in the rule's doc comment where
additionalReactiveClasses and allowReassign are discussed so reviewers can find
the documented defaults, JSON example, and use_options usage together.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@crates/biome_js_analyze/src/lint/nursery/no_svelte_unnecessary_state_wrap.rs`:
- Around line 37-41: Update the rustdoc for the rule in
no_svelte_unnecessary_state_wrap.rs to include standard option docs: add a
default-value sentence for each option (additionalReactiveClasses defaults to an
empty array, allowReassign defaults to false), add a JSON options block showing
both options and their default values, and add a short code example
demonstrating use_options or expect_diagnostic that configures each option (one
example showing additionalReactiveClasses set and one showing allowReassign:
true). Ensure these additions are placed in the rule's doc comment where
additionalReactiveClasses and allowReassign are discussed so reviewers can find
the documented defaults, JSON example, and use_options usage together.

In
`@crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.svelte`:
- Line 6: Change the test variable declaration from immutable to mutable so the
linter's "all_writes" skip path is exercised: replace the const declaration of
map created with $state(new SvelteMap()) by using let (i.e., declare map with
let map = $state(new SvelteMap());) while keeping the variable unmodified in the
test so the scenario remains "never reassigned" but allows the analyzer to
consider reassignment-capable bindings for the all_writes branch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9ceeb6fb-3881-4894-bd07-ad8cf8f8ee80

📥 Commits

Reviewing files that changed from the base of the PR and between ab01ffa and dea65cd.

⛔ Files ignored due to path filters (15)
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/domain_selector.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/invalid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_additional_classes.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid_allow_reassign.svelte.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (16)
  • .changeset/add-svelte-no-unnecessary-state-wrap.md
  • crates/biome_js_analyze/src/lint/nursery/no_svelte_unnecessary_state_wrap.rs
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/invalid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_additional_classes.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_additional_classes.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid_allow_reassign.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid_allow_reassign.svelte
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_svelte_unnecessary_state_wrap.rs
✅ Files skipped from review due to trivial changes (6)
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid_allow_reassign.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/valid.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteUnnecessaryStateWrap/invalid_allow_reassign.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/invalid.svelte
  • crates/biome_rule_options/src/lib.rs
  • .changeset/add-svelte-no-unnecessary-state-wrap.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.svelte
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid_allow_reassign.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noSvelteNoUnnecessaryStateWrap/valid.svelte

@Mokto Mokto force-pushed the feat/no-svelte-no-unnecessary-state-wrap branch 2 times, most recently from e12699e to ca9f33a Compare June 3, 2026 03:04

@dyc3 dyc3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

language: "js",
domains: &[RuleDomain::Svelte],
sources: &[RuleSource::EslintSvelte("no-unnecessary-state-wrap").same()],
recommended: false,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we make this recommended? is the source rule recommended in the eslint plugin?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think we should! will do now

@dyc3 dyc3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please be careful about what you commit

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to remove

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to remove

@Mokto

Mokto commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

My bad!

@Mokto Mokto requested a review from dyc3 June 4, 2026 03:23

@ematipico ematipico left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see that's your first lint rule. Please get familiar with the contribution guide yourself, many things don't follow it.

Comment on lines +76 to +77
/// The inner expression (the `new X()` / `X()` argument) to replace the call with.
inner_expr: AnyJsExpression,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You usually retrieve this in the action function. Not in the run function. Please remove it

Comment on lines +111 to +113
let AnyJsCallArgument::AnyJsExpression(arg_expr) = args.first()?.ok()? else {
return None;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use ok()?;. No need for let else

Comment on lines +121 to +123
let AnyJsExpression::JsIdentifierExpression(class_ident) = class_callee else {
return None;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

Comment on lines +130 to +133
let is_additional = options
.additional_reactive_classes
.as_deref()
.unwrap_or(&[])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not how we define defaults. Please refer to how other rules implement them

if options.allow_reassign.unwrap_or(false)
&& let Some(declarator) = call
.syntax()
.ancestors()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add skip(1)

}

// If `allowReassign` is enabled, skip variables that are reassigned after declaration.
if options.allow_reassign.unwrap_or(false)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if options.allow_reassign.unwrap_or(false)
if options.allow_reassign.unwrap_or_default()

That's the idiomatic rust way

}
}

// If `allowReassign` is enabled, skip variables that are reassigned after declaration.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If `allowReassign` is enabled, skip variables that are reassigned after declaration.

The comment isn't adding anything

&& let Ok(AnyJsBindingPattern::AnyJsBinding(AnyJsBinding::JsIdentifierBinding(
id_binding,
))) = declarator.id()
&& id_binding.all_writes(model).next().is_some()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this code doing? I would argue that's where you want a comment that explains things

Comment on lines +181 to +190
markup! {
<Emphasis>{state.class_name.text()}</Emphasis>" is already reactive, wrapping it in "<Emphasis>"$state()"</Emphasis>" is unnecessary."
},
)
.note(markup! {
"Classes from "<Emphasis>"svelte/reactivity"</Emphasis>" track their own mutations without needing a "<Emphasis>"$state"</Emphasis>" wrapper."
})
.note(markup! {
"Remove the "<Emphasis>"$state()"</Emphasis>" wrapper. If you need to reassign the variable itself, enable the "<Emphasis>"allowReassign"</Emphasis>" option."
}),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please read the contribution guide, and the rule pillars https://biomejs.dev/linter/#rule-pillars

  • first message, the error
  • then we explain the error
  • the code action is the third pillar

Comment on lines +139 to +142
pub struct RuleState {
/// Name of the reactive class being unnecessarily wrapped.
class_name: TokenText,
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could just have TokenText be the state

Comment on lines +12 to +14
/// When `true`, allows `$state()` wrapping for variables that are reassigned after declaration.
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_reassign: Option<bool>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the source rule implement this option? Why does it exist? I'm asking because we usually don't implement options without clear use cases.

Comment on lines +7 to +14
pub struct NoSvelteUnnecessaryStateWrapOptions {
/// Additional class names to treat as already reactive (beyond the built-in `svelte/reactivity` classes).
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_reactive_classes: Option<Box<[Box<str>]>>,

/// When `true`, allows `$state()` wrapping for variables that are reassigned after declaration.
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_reassign: Option<bool>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to implement a custom options migrator for these. There's a skill for it.

@ematipico

Copy link
Copy Markdown
Member

@Mokto, gentle bump. Are you still interested?

Mokto and others added 4 commits June 24, 2026 11:39
Adds RuleDomain::Svelte and RuleSource::EslintSvelte infrastructure (from
upstream biomejs#10503), plus a new JS nursery rule that reports $state() wrapping
of classes from svelte/reactivity (SvelteMap, SvelteSet, SvelteDate, etc.)
that are already deeply reactive without the rune.

Includes an unsafe fix to strip the wrapper, and two options:
- additionalReactiveClasses: extend the built-in list with custom classes
- allowReassign: permit $state for variables that are reassigned later

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mokto and others added 7 commits June 24, 2026 11:39
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diagnostic always fires for unnecessary $state wrapping; the autofix
is withheld when allowReassign is true and the variable is reassigned.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Import JsFileSource from biome_languages and split callee binding
so the ok()? check compiles after the rebase.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Mokto Mokto force-pushed the feat/no-svelte-no-unnecessary-state-wrap branch from a5365c9 to 33699bc Compare June 24, 2026 12:09
@Mokto

Mokto commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all comments from the review, rebased on current main. The one remaining let else for the $state callee check is now ok()? as well. Ready for re-review.

@Mokto

Mokto commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

I will fix the tests now

Comment thread crates/biome_js_analyze/src/lint/nursery/no_svelte_unnecessary_state_wrap.rs Outdated
@ematipico ematipico merged commit f3d4c00 into biomejs:main Jun 24, 2026
33 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 24, 2026
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Client that referenced this pull request Jul 4, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.5.1` -> `2.5.2`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.5.1/2.5.2) |

---

### Release Notes

<details>
<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>

### [`v2.5.2`](https://github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#252)

[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.1...@biomejs/biome@2.5.2)

##### Patch Changes

- [#&#8203;10595](biomejs/biome#10595) [`f458028`](biomejs/biome@f458028) Thanks [@&#8203;pkallos](https://github.com/pkallos)! - Added the option `ignoreBooleanCoercion` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). When enabled, Biome ignores `||` and `||=` used inside a `Boolean()` call, where coalescing on falsy values is intentional.

- [#&#8203;10798](biomejs/biome#10798) [`4a32b63`](biomejs/biome@4a32b63) Thanks [@&#8203;pkallos](https://github.com/pkallos)! - Added the option `ignorePrimitives` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). When enabled, Biome ignores `||`, `||=`, and ternary expressions whose non-nullish operands are all primitives the option opts out of. Use `true` to ignore all primitives, or an object selecting `string`, `number`, `boolean`, or `bigint`.

- [#&#8203;10545](biomejs/biome#10545) [`f3d4c00`](biomejs/biome@f3d4c00) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Added the new nursery rule [`noSvelteUnnecessaryStateWrap`](https://biomejs.dev/linter/rules/no-svelte-unnecessary-state-wrap/), which reports unnecessary `$state()` wrapping of classes from `svelte/reactivity` that are already reactive.

  ```svelte
  <script>
  import { SvelteMap } from "svelte/reactivity";
  const map = $state(new SvelteMap()); // redundant
  </script>
  ```

- [#&#8203;10752](biomejs/biome#10752) [`f62fb8b`](biomejs/biome@f62fb8b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10739](biomejs/biome#10739). Now the rule [`useValidAutocomplete`](https://biomejs.dev/linter/rules/use-valid-autocomplete/) correctly flags the `autoComplete` attribute.

- [#&#8203;10796](biomejs/biome#10796) [`f1b3ab2`](biomejs/biome@f1b3ab2) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10768](biomejs/biome#10768). Improved the performance of the Biome Language Server by cancelling certain in-flight operations when there are fast updates.

- [#&#8203;10719](biomejs/biome#10719) [`aa649b5`](biomejs/biome@aa649b5) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Fixed [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) false positive on returns that use a widening type assertion: `"a" as string` is no longer reported as misleading. The rule now also reports a literal-pinning assertion such as `false as false`, matching the existing `as const` behavior.

  ```ts
  // No longer flagged (returns are `string`):
  function getValue(b: boolean): string {
    if (b) return "a" as string;
    return "b" as string;
  }

  // Now also reported, like `as const` (returns `false`):
  function isReady(): boolean {
    return false as false;
  }
  ```

- [#&#8203;10678](biomejs/biome#10678) [`8f073a7`](biomejs/biome@8f073a7) Thanks [@&#8203;PranavAchar01](https://github.com/PranavAchar01)! - Fixed [#&#8203;7718](biomejs/biome#7718): Biome now correctly parses CSS nesting selectors when `&` appears as a trailing sub-selector after a type selector, e.g. `h1& { color: red; }`.

- [#&#8203;10756](biomejs/biome#10756) [`5ec965a`](biomejs/biome@5ec965a) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatter output for selector lists with `allowWrongLineComments` and `//` comments after a selector comma. Biome now keeps the selector before the line comment inline instead of breaking it across descendant combinators.

  ```diff
  -.powerPathNavigator
  -  .helm
  -  button.pressedButton, // pressed
  +.powerPathNavigator .helm button.pressedButton, // pressed
   .powerPathNavigator .helm button:active:not(.disabledButton) {
   }
  ```

- [#&#8203;10757](biomejs/biome#10757) [`6232fcd`](biomejs/biome@6232fcd) Thanks [@&#8203;PranavAchar01](https://github.com/PranavAchar01)! - Fixed [#&#8203;8269](biomejs/biome#8269): the CSS parser now accepts Tailwind `@variant` and `@utility` names that start with a digit, such as the `2xl` breakpoint.

  ```css
  @&#8203;utility container {
    @&#8203;variant 2xl {
      max-width: 1400px;
    }
  }
  ```

- [#&#8203;10777](biomejs/biome#10777) [`575ced6`](biomejs/biome@575ced6) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed an issue reported in [#&#8203;10708](biomejs/biome#10708): the GitLab reporter now handles `--verbose` diagnostics filtering correctly.

- [#&#8203;10281](biomejs/biome#10281) [`0efe244`](biomejs/biome@0efe244) Thanks [@&#8203;Zelys-DFKH](https://github.com/Zelys-DFKH)! - Fixed a bug where GritQL patterns rejected positional (unkeyed) arguments.

- [#&#8203;10758](biomejs/biome#10758) [`e36fd8a`](biomejs/biome@e36fd8a) Thanks [@&#8203;henrybrewer00-dotcom](https://github.com/henrybrewer00-dotcom)! - Fixed [#&#8203;10697](biomejs/biome#10697): The formatter no longer removes the parentheses around an `await` or `yield` expression used as the target of a TypeScript instantiation expression. For example, `(await makeFactory)<Value>` is no longer reformatted to `await makeFactory<Value>`, which would change the meaning of the code.

- [#&#8203;10586](biomejs/biome#10586) [`3617094`](biomejs/biome@3617094) Thanks [@&#8203;IxxyDev](https://github.com/IxxyDev)! - Fixed [#&#8203;9568](biomejs/biome#9568): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports a false positive when calling an overloaded function and the selected overload does not return a promise.

  ```ts
  function bestEffort(cb: () => Promise<number>): Promise<number>;
  function bestEffort(cb: () => number): number;
  function bestEffort(
    cb: () => number | Promise<number>,
  ): Promise<number> | number {
    return cb() as Promise<number> | number;
  }

  // This resolves to the second overload, which returns `number`, so it is no
  // longer flagged as a floating promise.
  bestEffort(() => 42);
  ```

- [#&#8203;10766](biomejs/biome#10766) [`7aff4c1`](biomejs/biome@7aff4c1) Thanks [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#&#8203;2862](biomejs/biome#2862): [`noInteractiveElementToNoninteractiveRole`](https://biomejs.dev/linter/rules/no-interactive-element-to-noninteractive-role/) no longer reports custom elements (a tag name containing a dash, e.g. `<my-button role="img" />`). Per the [W3C HTML-ARIA specification](https://www.w3.org/TR/html-aria/#el-autonomous-custom-element), a custom element may be given any role or none.

- [#&#8203;10680](biomejs/biome#10680) [`771daa4`](biomejs/biome@771daa4) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed [#&#8203;10635](biomejs/biome#10635): Biome now recognizes chained
  table tests such as `test.concurrent.each()` and `it.concurrent.each()` as test calls, fixing
  `noMisplacedAssertion` false positives and improving formatting for those test declarations.

- [#&#8203;10759](biomejs/biome#10759) [`34570b5`](biomejs/biome@34570b5) Thanks [@&#8203;henrybrewer00-dotcom](https://github.com/henrybrewer00-dotcom)! - Fixed [#&#8203;10636](biomejs/biome#10636): [noStaticElementInteractions](https://biomejs.dev/linter/rules/no-static-element-interactions/) no longer reports a false positive for event handlers on Svelte special elements such as `<svelte:window>`, `<svelte:document>`, and `<svelte:body>`. These are not real DOM elements, so they are now ignored by the rule.

- [#&#8203;10741](biomejs/biome#10741) [`bd2364e`](biomejs/biome@bd2364e) Thanks [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#&#8203;6686](biomejs/biome#6686): the `rage` command now respects the `--config-path` option and the `BIOME_CONFIG_PATH` environment variable when loading the Biome configuration. Previously it always used the default configuration resolution and reported the configuration as `Not set` when no `biome.json` existed in the working directory.

- [#&#8203;10763](biomejs/biome#10763) [`2c3e82d`](biomejs/biome@2c3e82d) Thanks [@&#8203;Aqu1bp](https://github.com/Aqu1bp)! - Fixed [#&#8203;10742](biomejs/biome#10742): [`noSolidDestructuredProps`](https://biomejs.dev/linter/rules/no-solid-destructured-props) now reports destructured props in Solid function components and JSX children.

- [#&#8203;10606](biomejs/biome#10606) [`a4cc4ab`](biomejs/biome@a4cc4ab) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Fixed false positives in `noUnusedImports`, `noUnusedVariables`, and `useImportType` for Svelte components that use both a `<script module>` and a `<script>` block. The two blocks compile to a single module and share a top-level scope, so a binding (import, function, or variable) declared in one block and used only in the other is no longer reported as unused.

- [#&#8203;10767](biomejs/biome#10767) [`36d5aa7`](biomejs/biome@36d5aa7) Thanks [@&#8203;otkrickey](https://github.com/otkrickey)! - Fixed [#&#8203;10754](biomejs/biome#10754): [`useVueValidVBind`](https://biomejs.dev/linter/rules/use-vue-valid-v-bind/) no longer reports the Vue 3.4+ same-name shorthand as missing a value. `:foo` and `v-bind:foo` are now accepted as equivalent to `:foo="foo"`, while `v-bind`, `v-bind:[dynamicArg]`, and `:[dynamicArg]` without a value continue to be reported.

- [#&#8203;10775](biomejs/biome#10775) [`a918af0`](biomejs/biome@a918af0) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed an issue reported in [#&#8203;10708](biomejs/biome#10708): `biome rage` didn't detect running Biome daemon pipes on Windows.

- [#&#8203;10730](biomejs/biome#10730) [`5a2e65b`](biomejs/biome@5a2e65b) Thanks [@&#8203;dinocosta](https://github.com/dinocosta)! - Fixed an issue where Biome was resolving [the well-known Zed settings file](https://biomejs.dev/guides/configure-biome/#well-known-files) from the wrong location on macOS and Windows.

- [#&#8203;10807](biomejs/biome#10807) [`d97fffe`](biomejs/biome@d97fffe) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where `.scss` files were incorrectly analyzed when running `biome check`.

- [#&#8203;10672](biomejs/biome#10672) [`53c6efc`](biomejs/biome@53c6efc) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a bug where Biome incorrectly formatted snippets that have parsing errors.

- [#&#8203;10719](biomejs/biome#10719) [`aa649b5`](biomejs/biome@aa649b5) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Fixed [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/) false positive when awaiting a custom thenable that is not the global `Promise`. A value with a callable `then` member is now recognized as awaitable.

  ```ts
  interface Thenable<T> {
    then(onfulfilled: (value: T) => void): void;
  }
  declare const t: Thenable<number>;
  async function f() {
    await t;
  }
  ```

- [#&#8203;10734](biomejs/biome#10734) [`4396496`](biomejs/biome@4396496) Thanks [@&#8203;BangDori](https://github.com/BangDori)! - Fixed [#&#8203;10708](biomejs/biome#10708): `biome migrate` now preserves trivia when migrating the deprecated `recommended` option to `preset`.

- [#&#8203;10683](biomejs/biome#10683) [`ae31a00`](biomejs/biome@ae31a00) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10657](biomejs/biome#10657) [#&#8203;10671](biomejs/biome#10671) [#&#8203;10661](biomejs/biome#10661) [#&#8203;10637](biomejs/biome#10637) [#&#8203;10718](biomejs/biome#10718): HTML rules now correctly handle dynamic attributes.

- [#&#8203;10746](biomejs/biome#10746) [`54e8239`](biomejs/biome@54e8239) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes) didn't correctly detect styles defined inside the Astro directive `is:global`.

- [#&#8203;10770](biomejs/biome#10770) [`dd1429c`](biomejs/biome@dd1429c) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the Biome Language Server DX by orchestrating certain operations, so that they won't block the editor during typing. This improvement is more visible in large documents.

- [#&#8203;10473](biomejs/biome#10473) [`d9b5133`](biomejs/biome@d9b5133) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Improved [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/), [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/), [`noUnusedFunctionParameters`](https://biomejs.dev/linter/rules/no-unused-function-parameters/), and [`useImportType`](https://biomejs.dev/linter/rules/use-import-type/) for Svelte, Vue, and Astro files (with `html.experimentalFullSupportEnabled`). Bindings used only in the template — including component tags, attribute interpolations, directives, `bind:` shorthand, and snippet parameters — are no longer reported as unused, while genuinely unused ones still are.

- [#&#8203;10796](biomejs/biome#10796) [`f1b3ab2`](biomejs/biome@f1b3ab2) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where the Biome Language Server didn't enable project or type-aware lint rules, even when they were explicitly enabled.

- [#&#8203;10746](biomejs/biome#10746) [`54e8239`](biomejs/biome@54e8239) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes) didn't detect styles declared inside HTML documents.

- [#&#8203;10774](biomejs/biome#10774) [`bde945b`](biomejs/biome@bde945b) Thanks [@&#8203;pattrickrice](https://github.com/pattrickrice)! - Fixed [#&#8203;10268](biomejs/biome#10268) where a race condition resulted in internal errors such as: `The file biome.json does not exist in the workspace`.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMzQuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIzNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Client/pulls/9
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Server that referenced this pull request Jul 8, 2026
This PR contains the following updates:

| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.5.1` -> `2.5.2`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.5.1/2.5.2) | `2.5.3` |

---

### Release Notes

<details>
<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>

### [`v2.5.2`](https://github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#252)

[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.1...@biomejs/biome@2.5.2)

##### Patch Changes

- [#&#8203;10595](biomejs/biome#10595) [`f458028`](biomejs/biome@f458028) Thanks [@&#8203;pkallos](https://github.com/pkallos)! - Added the option `ignoreBooleanCoercion` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). When enabled, Biome ignores `||` and `||=` used inside a `Boolean()` call, where coalescing on falsy values is intentional.

- [#&#8203;10798](biomejs/biome#10798) [`4a32b63`](biomejs/biome@4a32b63) Thanks [@&#8203;pkallos](https://github.com/pkallos)! - Added the option `ignorePrimitives` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). When enabled, Biome ignores `||`, `||=`, and ternary expressions whose non-nullish operands are all primitives the option opts out of. Use `true` to ignore all primitives, or an object selecting `string`, `number`, `boolean`, or `bigint`.

- [#&#8203;10545](biomejs/biome#10545) [`f3d4c00`](biomejs/biome@f3d4c00) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Added the new nursery rule [`noSvelteUnnecessaryStateWrap`](https://biomejs.dev/linter/rules/no-svelte-unnecessary-state-wrap/), which reports unnecessary `$state()` wrapping of classes from `svelte/reactivity` that are already reactive.

  ```svelte
  <script>
  import { SvelteMap } from "svelte/reactivity";
  const map = $state(new SvelteMap()); // redundant
  </script>
  ```

- [#&#8203;10752](biomejs/biome#10752) [`f62fb8b`](biomejs/biome@f62fb8b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10739](biomejs/biome#10739). Now the rule [`useValidAutocomplete`](https://biomejs.dev/linter/rules/use-valid-autocomplete/) correctly flags the `autoComplete` attribute.

- [#&#8203;10796](biomejs/biome#10796) [`f1b3ab2`](biomejs/biome@f1b3ab2) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10768](biomejs/biome#10768). Improved the performance of the Biome Language Server by cancelling certain in-flight operations when there are fast updates.

- [#&#8203;10719](biomejs/biome#10719) [`aa649b5`](biomejs/biome@aa649b5) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Fixed [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) false positive on returns that use a widening type assertion: `"a" as string` is no longer reported as misleading. The rule now also reports a literal-pinning assertion such as `false as false`, matching the existing `as const` behavior.

  ```ts
  // No longer flagged (returns are `string`):
  function getValue(b: boolean): string {
    if (b) return "a" as string;
    return "b" as string;
  }

  // Now also reported, like `as const` (returns `false`):
  function isReady(): boolean {
    return false as false;
  }
  ```

- [#&#8203;10678](biomejs/biome#10678) [`8f073a7`](biomejs/biome@8f073a7) Thanks [@&#8203;PranavAchar01](https://github.com/PranavAchar01)! - Fixed [#&#8203;7718](biomejs/biome#7718): Biome now correctly parses CSS nesting selectors when `&` appears as a trailing sub-selector after a type selector, e.g. `h1& { color: red; }`.

- [#&#8203;10756](biomejs/biome#10756) [`5ec965a`](biomejs/biome@5ec965a) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatter output for selector lists with `allowWrongLineComments` and `//` comments after a selector comma. Biome now keeps the selector before the line comment inline instead of breaking it across descendant combinators.

  ```diff
  -.powerPathNavigator
  -  .helm
  -  button.pressedButton, // pressed
  +.powerPathNavigator .helm button.pressedButton, // pressed
   .powerPathNavigator .helm button:active:not(.disabledButton) {
   }
  ```

- [#&#8203;10757](biomejs/biome#10757) [`6232fcd`](biomejs/biome@6232fcd) Thanks [@&#8203;PranavAchar01](https://github.com/PranavAchar01)! - Fixed [#&#8203;8269](biomejs/biome#8269): the CSS parser now accepts Tailwind `@variant` and `@utility` names that start with a digit, such as the `2xl` breakpoint.

  ```css
  @&#8203;utility container {
    @&#8203;variant 2xl {
      max-width: 1400px;
    }
  }
  ```

- [#&#8203;10777](biomejs/biome#10777) [`575ced6`](biomejs/biome@575ced6) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed an issue reported in [#&#8203;10708](biomejs/biome#10708): the GitLab reporter now handles `--verbose` diagnostics filtering correctly.

- [#&#8203;10281](biomejs/biome#10281) [`0efe244`](biomejs/biome@0efe244) Thanks [@&#8203;Zelys-DFKH](https://github.com/Zelys-DFKH)! - Fixed a bug where GritQL patterns rejected positional (unkeyed) arguments.

- [#&#8203;10758](biomejs/biome#10758) [`e36fd8a`](biomejs/biome@e36fd8a) Thanks [@&#8203;henrybrewer00-dotcom](https://github.com/henrybrewer00-dotcom)! - Fixed [#&#8203;10697](biomejs/biome#10697): The formatter no longer removes the parentheses around an `await` or `yield` expression used as the target of a TypeScript instantiation expression. For example, `(await makeFactory)<Value>` is no longer reformatted to `await makeFactory<Value>`, which would change the meaning of the code.

- [#&#8203;10586](biomejs/biome#10586) [`3617094`](biomejs/biome@3617094) Thanks [@&#8203;IxxyDev](https://github.com/IxxyDev)! - Fixed [#&#8203;9568](biomejs/biome#9568): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports a false positive when calling an overloaded function and the selected overload does not return a promise.

  ```ts
  function bestEffort(cb: () => Promise<number>): Promise<number>;
  function bestEffort(cb: () => number): number;
  function bestEffort(
    cb: () => number | Promise<number>,
  ): Promise<number> | number {
    return cb() as Promise<number> | number;
  }

  // This resolves to the second overload, which returns `number`, so it is no
  // longer flagged as a floating promise.
  bestEffort(() => 42);
  ```

- [#&#8203;10766](biomejs/biome#10766) [`7aff4c1`](biomejs/biome@7aff4c1) Thanks [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#&#8203;2862](biomejs/biome#2862): [`noInteractiveElementToNoninteractiveRole`](https://biomejs.dev/linter/rules/no-interactive-element-to-noninteractive-role/) no longer reports custom elements (a tag name containing a dash, e.g. `<my-button role="img" />`). Per the [W3C HTML-ARIA specification](https://www.w3.org/TR/html-aria/#el-autonomous-custom-element), a custom element may be given any role or none.

- [#&#8203;10680](biomejs/biome#10680) [`771daa4`](biomejs/biome@771daa4) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed [#&#8203;10635](biomejs/biome#10635): Biome now recognizes chained
  table tests such as `test.concurrent.each()` and `it.concurrent.each()` as test calls, fixing
  `noMisplacedAssertion` false positives and improving formatting for those test declarations.

- [#&#8203;10759](biomejs/biome#10759) [`34570b5`](biomejs/biome@34570b5) Thanks [@&#8203;henrybrewer00-dotcom](https://github.com/henrybrewer00-dotcom)! - Fixed [#&#8203;10636](biomejs/biome#10636): [noStaticElementInteractions](https://biomejs.dev/linter/rules/no-static-element-interactions/) no longer reports a false positive for event handlers on Svelte special elements such as `<svelte:window>`, `<svelte:document>`, and `<svelte:body>`. These are not real DOM elements, so they are now ignored by the rule.

- [#&#8203;10741](biomejs/biome#10741) [`bd2364e`](biomejs/biome@bd2364e) Thanks [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#&#8203;6686](biomejs/biome#6686): the `rage` command now respects the `--config-path` option and the `BIOME_CONFIG_PATH` environment variable when loading the Biome configuration. Previously it always used the default configuration resolution and reported the configuration as `Not set` when no `biome.json` existed in the working directory.

- [#&#8203;10763](biomejs/biome#10763) [`2c3e82d`](biomejs/biome@2c3e82d) Thanks [@&#8203;Aqu1bp](https://github.com/Aqu1bp)! - Fixed [#&#8203;10742](biomejs/biome#10742): [`noSolidDestructuredProps`](https://biomejs.dev/linter/rules/no-solid-destructured-props) now reports destructured props in Solid function components and JSX children.

- [#&#8203;10606](biomejs/biome#10606) [`a4cc4ab`](biomejs/biome@a4cc4ab) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Fixed false positives in `noUnusedImports`, `noUnusedVariables`, and `useImportType` for Svelte components that use both a `<script module>` and a `<script>` block. The two blocks compile to a single module and share a top-level scope, so a binding (import, function, or variable) declared in one block and used only in the other is no longer reported as unused.

- [#&#8203;10767](biomejs/biome#10767) [`36d5aa7`](biomejs/biome@36d5aa7) Thanks [@&#8203;otkrickey](https://github.com/otkrickey)! - Fixed [#&#8203;10754](biomejs/biome#10754): [`useVueValidVBind`](https://biomejs.dev/linter/rules/use-vue-valid-v-bind/) no longer reports the Vue 3.4+ same-name shorthand as missing a value. `:foo` and `v-bind:foo` are now accepted as equivalent to `:foo="foo"`, while `v-bind`, `v-bind:[dynamicArg]`, and `:[dynamicArg]` without a value continue to be reported.

- [#&#8203;10775](biomejs/biome#10775) [`a918af0`](biomejs/biome@a918af0) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed an issue reported in [#&#8203;10708](biomejs/biome#10708): `biome rage` didn't detect running Biome daemon pipes on Windows.

- [#&#8203;10730](biomejs/biome#10730) [`5a2e65b`](biomejs/biome@5a2e65b) Thanks [@&#8203;dinocosta](https://github.com/dinocosta)! - Fixed an issue where Biome was resolving [the well-known Zed settings file](https://biomejs.dev/guides/configure-biome/#well-known-files) from the wrong location on macOS and Windows.

- [#&#8203;10807](biomejs/biome#10807) [`d97fffe`](biomejs/biome@d97fffe) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where `.scss` files were incorrectly analyzed when running `biome check`.

- [#&#8203;10672](biomejs/biome#10672) [`53c6efc`](biomejs/biome@53c6efc) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a bug where Biome incorrectly formatted snippets that have parsing errors.

- [#&#8203;10719](biomejs/biome#10719) [`aa649b5`](biomejs/biome@aa649b5) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Fixed [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/) false positive when awaiting a custom thenable that is not the global `Promise`. A value with a callable `then` member is now recognized as awaitable.

  ```ts
  interface Thenable<T> {
    then(onfulfilled: (value: T) => void): void;
  }
  declare const t: Thenable<number>;
  async function f() {
    await t;
  }
  ```

- [#&#8203;10734](biomejs/biome#10734) [`4396496`](biomejs/biome@4396496) Thanks [@&#8203;BangDori](https://github.com/BangDori)! - Fixed [#&#8203;10708](biomejs/biome#10708): `biome migrate` now preserves trivia when migrating the deprecated `recommended` option to `preset`.

- [#&#8203;10683](biomejs/biome#10683) [`ae31a00`](biomejs/biome@ae31a00) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10657](biomejs/biome#10657) [#&#8203;10671](biomejs/biome#10671) [#&#8203;10661](biomejs/biome#10661) [#&#8203;10637](biomejs/biome#10637) [#&#8203;10718](biomejs/biome#10718): HTML rules now correctly handle dynamic attributes.

- [#&#8203;10746](biomejs/biome#10746) [`54e8239`](biomejs/biome@54e8239) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes) didn't correctly detect styles defined inside the Astro directive `is:global`.

- [#&#8203;10770](biomejs/biome#10770) [`dd1429c`](biomejs/biome@dd1429c) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the Biome Language Server DX by orchestrating certain operations, so that they won't block the editor during typing. This improvement is more visible in large documents.

- [#&#8203;10473](biomejs/biome#10473) [`d9b5133`](biomejs/biome@d9b5133) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Improved [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/), [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/), [`noUnusedFunctionParameters`](https://biomejs.dev/linter/rules/no-unused-function-parameters/), and [`useImportType`](https://biomejs.dev/linter/rules/use-import-type/) for Svelte, Vue, and Astro files (with `html.experimentalFullSupportEnabled`). Bindings used only in the template — including component tags, attribute interpolations, directives, `bind:` shorthand, and snippet parameters — are no longer reported as unused, while genuinely unused ones still are.

- [#&#8203;10796](biomejs/biome#10796) [`f1b3ab2`](biomejs/biome@f1b3ab2) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where the Biome Language Server didn't enable project or type-aware lint rules, even when they were explicitly enabled.

- [#&#8203;10746](biomejs/biome#10746) [`54e8239`](biomejs/biome@54e8239) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where [`noUndeclaredClasses`](https://biomejs.dev/linter/rules/no-undeclared-classes) didn't detect styles declared inside HTML documents.

- [#&#8203;10774](biomejs/biome#10774) [`bde945b`](biomejs/biome@bde945b) Thanks [@&#8203;pattrickrice](https://github.com/pattrickrice)! - Fixed [#&#8203;10268](biomejs/biome#10268) where a race condition resulted in internal errors such as: `The file biome.json does not exist in the workspace`.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDYuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI0Ni4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Project Area: project L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants