Skip to content

fix(parse/html): read top-level Svelte script and style attributes as strings - #12189

Closed
MustafaKemal0146 wants to merge 1 commit into
biomejs:mainfrom
MustafaKemal0146:fix/html-svelte-script-generics
Closed

MustafaKemal0146 wants to merge 1 commit into
biomejs:mainfrom
MustafaKemal0146:fix/html-svelte-script-generics

Conversation

@MustafaKemal0146

Copy link
Copy Markdown
Contributor

Summary

Fixes #10896.

In Svelte, quoted attribute values were always parsed as templates, so generics="T extends { selected?: boolean }" on <script> was read as a {...} expression and failed to parse. Svelte reads attributes of top-level <script>/<style> as static strings (is_top_level_script_or_style in its element.js), so Biome now does the same. Nested ones, like a <script> inside <svelte:head>, still get templates.

Related: #10952 handles type references inside generics, this one only fixes the parse error.

This PR was written primarily by Claude Code.

Test Plan

  • New parser fixture ok/svelte/script_generics_with_braces.svelte: top-level <script>/<style> values are HtmlString, <div title="{...}"> and the ones in <svelte:head> stay templates.
  • New CLI test full_support_script_generics_with_braces: fails on main with a parse error, passes with the fix.
  • Ran the biome_html_parser and biome_html_formatter tests, the Svelte/Astro/Vue CLI cases, the Svelte analyzer specs, just f and just l.

Docs

No changes needed.

Copilot AI balanced review requested due to automatic review settings October 7, 2026 08:14
@changeset-bot

changeset-bot Bot commented Oct 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 646e0c6

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

This PR includes changesets to release 15 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-android-arm64 Patch
@biomejs/cli-android-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-win32-x64 Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/wasm-web 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

@agentscanapp

agentscanapp Bot commented Oct 7, 2026

Copy link
Copy Markdown

A maintainer will take a look as soon as they can. In the meantime, please make sure that:

  • the description follows our PR template
  • any related issues are linked
  • existing tests still pass

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added A-CLI Area: CLI A-Parser Area: parser L-HTML Language: HTML and super languages labels Oct 7, 2026
@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: biomejs/biome/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a50eea35-fc8a-4f8f-8eab-ece5375d030f
📥 Commits

Reviewing files that changed from the base of the PR and between 6ddce62 and 646e0c6.

⛔ Files ignored due to path filters (2)
  • crates/biome_cli/tests/snapshots/main_cases_handle_svelte_files/full_support_script_generics_with_braces.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_parser/tests/html_specs/ok/svelte/script_generics_with_braces.svelte.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (5)
  • .changeset/purple-cups-raise.md
  • crates/biome_cli/tests/cases/handle_svelte_files.rs
  • crates/biome_html_parser/src/syntax/mod.rs
  • crates/biome_html_parser/src/syntax/svelte.rs
  • crates/biome_html_parser/tests/html_specs/ok/svelte/script_generics_with_braces.svelte

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


Walkthrough

The HTML parser now tracks whether an element is at the document root. For direct-root Svelte <script> and <style> elements, it parses quoted attribute values as plain strings. Other Svelte attribute values retain template parsing. New parser and CLI tests cover a TypeScript generic constraint containing braces, and a patch changeset records the update.

Suggested reviewers: dyc3

Priority: ⬇️ Low

Change: Bug fix · Severity of issue fixed: Low

Merge Risk: ⚪ Minimal · up to 646e0

The change addresses the reported top-level Svelte generic parse error while preserving nested template parsing. No concrete merge-blocking issue remains in the supplied evidence.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to 646e0

The change corrects attribute interpretation within a narrowly defined Svelte context. The reviewed paths do not introduce new execution authority or weaken a security boundary, and nested elements retain their existing behavior.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected input surface is source text supplied to the existing HTML parser with Svelte support enabled. The changed behavior is limited to quoted attributes on direct-root script and style elements; no new tenant, credential or execution authority was identified in the inspected path.

Trust Boundaries and Controls

  • observed — The parser establishes root context internally rather than accepting it as an external privilege flag. The inspected service consumer converts attribute values and embedded content into parsing candidates; it contains no direct attribute-execution operation.

Resilience and Maintainability Implications

  • inferred — Static mode is local to a freshly constructed attribute list, avoiding cross-element state leakage. Speculative fallback retains the same root argument and restores parser and lexer checkpoints. Unterminated strings advance to EOF and use existing recovery, supporting failure containment within the parse operation.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the change to how top-level Svelte <script> and <style> attributes are parsed.
Description check ✅ Passed The description explains the parse error, the fix, its scope and the tests performed.
Linked Issues check ✅ Passed [ #10896 ] The parser now treats quoted attributes on top-level Svelte <script> and <style> elements as static strings. This prevents braces in generics from being parsed as a template. The new …
Out of Scope Changes check ✅ Passed The parser change, regression coverage, and changeset all support the fix for [ #10896 ]. No unrelated changes are reported.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@codspeed

codspeed Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 65 untouched benchmarks
⏩ 346 skipped benchmarks1


Comparing MustafaKemal0146:fix/html-svelte-script-generics (646e0c6) with main (6ddce62)

Open in CodSpeed

Footnotes

  1. 346 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. ↩

@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.

Thank you for the PR, but I don't this is the right fix. I added some comments. Why can't we emit the same CST we do for the Vue generics? See playground

}

#[test]
fn full_support_script_generics_with_braces() {

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.

The parser test was enough. At most, you could add a formatter test. This wasn't a CLI bug, after all

Comment on lines +412 to +414
// Svelte reads the attributes of a top-level `<script>` or `<style>` as plain
// strings, so `generics="T extends { id: string }"` holds no `{expression}`.
// Nested ones, such as a `<script>` inside `<svelte:head>`, keep templates.

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 don't think the comment is correct. What you want to say is that generics has special parsing only when it's in a top-level <script>. A script tag under a div, for example, triggers a parser error.

Also, we don't care how Svelte parses things; we care more about the parsing business logic (error path, happy path, etc.), because the "how" is our business logic.

initializer: HtmlAttributeInitializerClause {
eq_token: [email protected] "=" [] [],
value: HtmlString {
value_token: [email protected] "\"T extends { selected?: boolean; name?: string }\"" [] [],

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.

This is an incorrect representation of the code, we can't accept that. We're adding quotes even though there aren't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Parser Area: parser L-HTML Language: HTML and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

📝 parse error on Svelte <script> generics attribute containing curly braces

3 participants