Skip to content

Conversation

alex-snezhko
Copy link
Contributor

@alex-snezhko alex-snezhko commented Oct 5, 2025

close #13436

Expand cases under which the selected attribute is added onto an option tag in SSR:

  • Consider text nodes/interpolations as direct children of the option
  • Consider v-text

An additional side effect of this PR is to fix the current behavior showcased by this playground example, which I believe to be a bug: link

Example

const app = createSSRApp({
  setup() {
    const r = ref('asdf')
    const val = 'asdf'
    return { r, val }
  },
  template: `
    <select v-model="r">
      <option>{{ val }}</option>
      <option>fdsa</option>
    </select>
  `
})

// SSR output: <select><option selected>asdf</option><option>fdsa</option></select>

Summary by CodeRabbit

  • New Features

    • Improved SSR handling for select v-model so option values resolve from plain text, interpolations, v-text, loops, slots, templates and nested content.
  • Bug Fixes

    • More reliable selected-state computation in SSR for single and multiple select scenarios, including when option values are derived rather than explicitly bound.
  • Tests

    • Added extensive SSR tests covering many select/v-model permutations and mixed option content.

Copy link

coderabbitai bot commented Oct 5, 2025

Walkthrough

Reworks SSR v-model option value extraction to derive values from bound attributes, text directives, or collapsed text/interpolations; adds collapse utility; updates selected-state codegen; and adds extensive SSR tests for / scenarios. No public API changes. Changes Cohort / File(s) Summary SSR v-model transformpackages/compiler-ssr/src/transforms/ssrVModel.ts Adds internal OptionValue type and findOptionValue() to resolve option values from value bindings, v-text, or collapsed text/interpolations; introduces collapseTextBetweenComments(); updates imports (TemplateLiteral, TextNode, createTemplateLiteral, findDir); and adjusts selected-state SSR codegen to use the derived value source. SSR compiler testspackages/compiler-ssr/__tests__/ssrVModel.spec.ts Adds many new SSR unit tests and inline snapshots covering options with literal text, trimmed/spaced text, interpolations, v-text, v-for, slots/content, optgroups, and template/conditional combinations to validate option value derivation and selected logic. SSR renderer testspackages/server-renderer/__tests__/ssrDirectives.spec.ts Adds two tests verifying interpolation and v-text inside <option> render expected text and selected state in SSR output. Sequence Diagram(s) sequenceDiagram autonumber participant Template as Template (AST) participant Compiler as SSR Compiler participant Transform as ssrVModel Transform participant Helper as Utilities (collapseTextBetweenComments) participant Codegen as SSR Codegen participant Runtime as SSR Helpers Template->>Compiler: parse -> AST Compiler->>Transform: apply v-model transform on <select>/<option> Transform->>Transform: findOptionValue()\n- if `value` binding -> use bound expr\n- else if `v-text` dir -> use text expr\n- else -> call Helper to collapse TEXT/INTERPOLATION/COMMENT\nHelper-->>Transform: sequence or TemplateLiteral value Transform->>Codegen: emit selected logic using derived value\nCodegen->>Runtime: reference _ssrLooseContain/_ssrLooseEqual helpers Note right of Runtime: Helpers evaluate at render time to set `selected` Estimated code review effort 🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs #13487 — Modifies the same packages/compiler-ssr/src/transforms/ssrVModel.ts area to improve SSR handling of <select>/<option> value extraction and child processing. Suggested labels ready to merge, 🔨 p3-minor-bug Poem I’m a rabbit in the build, nibbling bits of text, I fold interpolations, chase comments next. Value bound or written, I tuck it neat— Then hop to mark the selected seat. 🐇✨ Pre-merge checks and finishing touches ❌ Failed checks (1 warning) Check name Status Explanation Resolution Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage. ✅ Passed checks (4 passed) Check name Status Explanation Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled. Title Check ✅ Passed The title clearly and concisely describes the primary change of expanding the SSR v-model option selection logic in the compiler-ssr transform, directly reflecting the key modifications without extraneous details. Linked Issues Check ✅ Passed The PR implements the fix from issue #13436 by introducing a findOptionValue function that derives option values from text nodes, interpolations, and v-text directives and updates the SSR selected-attribute logic accordingly, with matching tests covering the specified scenarios. Out of Scope Changes Check ✅ Passed All changes pertain exclusively to enhancing SSR v-model option selection and related tests, and no unrelated features or code areas have been modified. ✨ Finishing touches [ ] 📝 Generate docstrings 🧪 Generate unit tests (beta) [ ] Create PR with unit tests [ ] Post copyable unit tests in a comment 📜 Recent review details Configuration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📥 Commits Reviewing files that changed from the base of the PR and between 15d6f92 and cced68b. 📒 Files selected for processing (3) packages/compiler-ssr/__tests__/ssrVModel.spec.ts (1 hunks) packages/compiler-ssr/src/transforms/ssrVModel.ts (4 hunks) packages/server-renderer/__tests__/ssrDirectives.spec.ts (1 hunks) 🚧 Files skipped from review as they are similar to previous changes (1) packages/compiler-ssr/tests/ssrVModel.spec.ts 🧰 Additional context used 🧬 Code graph analysis (1) packages/compiler-ssr/src/transforms/ssrVModel.ts (2) packages/compiler-core/src/ast.ts (7) PlainElementNode (140-149) ExpressionNode (91-91) TemplateLiteral (449-452) createSimpleExpression (685-698) createTemplateLiteral (801-809) TemplateChildNode (93-102) TextNode (176-179) packages/compiler-core/src/utils.ts (2) findProp (299-320) findDir (282-297) ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5) GitHub Check: test / unit-test-windows GitHub Check: test / e2e-test GitHub Check: Redirect rules GitHub Check: Header rules GitHub Check: Pages changed 🔇 Additional comments (2) packages/server-renderer/__tests__/ssrDirectives.spec.ts (1) 125-145: LGTM! Excellent test coverage for the new option value derivation logic. The new test cases properly validate: Interpolation within option text (f{{ zero }}o → "f0o") v-text directive bindings (opt1Val → "foo", opt2Val → "bar") Both scenarios confirm that SSR correctly marks options as selected when the derived text content matches the v-model value. packages/compiler-ssr/src/transforms/ssrVModel.ts (1) 259-295: LGTM! Clean implementation of text node collapsing. The collapseTextBetweenComments utility correctly: Merges adjacent text nodes Handles spacing between merged nodes (removes duplicate spaces at boundaries) Skips comment nodes Preserves non-text nodes in sequence 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 X Mastodon Reddit LinkedIn Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

github-actions bot commented Oct 5, 2025

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 102 kB 38.6 kB 34.8 kB
vue.global.prod.js 160 kB 58.7 kB 52.2 kB

Usages

Name Size Gzip Brotli
createApp (CAPI only) 46.7 kB 18.3 kB 16.7 kB
createApp 54.7 kB 21.3 kB 19.5 kB
createSSRApp 58.9 kB 23 kB 21 kB
defineCustomElement 60 kB 23 kB 21 kB
overall 68.8 kB 26.5 kB 24.2 kB

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c16f8a9 and fc0df0d.

📒 Files selected for processing (2)
  • packages/compiler-ssr/__tests__/ssrVModel.spec.ts (1 hunks)
  • packages/compiler-ssr/src/transforms/ssrVModel.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/compiler-ssr/src/transforms/ssrVModel.ts (3)
packages/compiler-core/src/ast.ts (9)
  • createConditionalExpression (758-772)
  • createCallExpression (728-739)
  • ExpressionNode (91-91)
  • TemplateLiteral (449-452)
  • PlainElementNode (140-149)
  • createSimpleExpression (685-698)
  • createTemplateLiteral (801-809)
  • TemplateChildNode (93-102)
  • TextNode (176-179)
packages/compiler-ssr/src/runtimeHelpers.ts (3)
  • SSR_INCLUDE_BOOLEAN_ATTR (15-17)
  • SSR_LOOSE_CONTAIN (19-19)
  • SSR_LOOSE_EQUAL (18-18)
packages/compiler-core/src/utils.ts (2)
  • findProp (299-320)
  • findDir (282-297)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Redirect rules
  • GitHub Check: Header rules
  • GitHub Check: Pages changed
  • GitHub Check: test / unit-test-windows

Copy link

pkg-pr-new bot commented Oct 5, 2025

Open in StackBlitz

@vue/compiler-core

npm i https://pkg.pr.new/@vue/compiler-core@13963

@vue/compiler-dom

npm i https://pkg.pr.new/@vue/compiler-dom@13963

@vue/compiler-sfc

npm i https://pkg.pr.new/@vue/compiler-sfc@13963

@vue/compiler-ssr

npm i https://pkg.pr.new/@vue/compiler-ssr@13963

@vue/reactivity

npm i https://pkg.pr.new/@vue/reactivity@13963

@vue/runtime-core

npm i https://pkg.pr.new/@vue/runtime-core@13963

@vue/runtime-dom

npm i https://pkg.pr.new/@vue/runtime-dom@13963

@vue/server-renderer

npm i https://pkg.pr.new/@vue/server-renderer@13963

@vue/shared

npm i https://pkg.pr.new/@vue/shared@13963

vue

npm i https://pkg.pr.new/vue@13963

@vue/compat

npm i https://pkg.pr.new/@vue/compat@13963

commit: cced68b

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc0df0d and 15d6f92.

📒 Files selected for processing (2)
  • packages/compiler-ssr/__tests__/ssrVModel.spec.ts (1 hunks)
  • packages/compiler-ssr/src/transforms/ssrVModel.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/compiler-ssr/tests/ssrVModel.spec.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/compiler-ssr/src/transforms/ssrVModel.ts (3)
packages/compiler-core/src/ast.ts (8)
  • createConditionalExpression (758-772)
  • createCallExpression (728-739)
  • ExpressionNode (91-91)
  • TemplateLiteral (449-452)
  • createSimpleExpression (685-698)
  • createTemplateLiteral (801-809)
  • TemplateChildNode (93-102)
  • TextNode (176-179)
packages/compiler-ssr/src/runtimeHelpers.ts (3)
  • SSR_INCLUDE_BOOLEAN_ATTR (15-17)
  • SSR_LOOSE_CONTAIN (19-19)
  • SSR_LOOSE_EQUAL (18-18)
packages/compiler-core/src/utils.ts (2)
  • findProp (299-320)
  • findDir (282-297)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Redirect rules
  • GitHub Check: Header rules
  • GitHub Check: Pages changed

@edison1105
Copy link
Member

The following example has a bug
Playground with this PR

@edison1105 edison1105 added scope: ssr 🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. wait changes labels Oct 9, 2025
@alex-snezhko
Copy link
Contributor Author

@edison1105 updated!

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

Labels

🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. scope: ssr wait changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

<option> without value attr won't have selected attr in the SSR output

2 participants