Visitar URL original
fix(compiler-vapor): do not decode static attribute values and comments twice by ValentinYoushkevich · Pull Request #15563 · vuejs/core · GitHub
Skip to content

fix(compiler-vapor): do not decode static attribute values and comments twice - #15563

Merged
edison1105 merged 2 commits into
vuejs:minorfrom
ValentinYoushkevich:fix/vapor-static-attr-double-decode
Sep 20, 2026
Merged

edison1105 merged 2 commits into
vuejs:minorfrom
ValentinYoushkevich:fix/vapor-static-attr-double-decode

Conversation

@ValentinYoushkevich

Copy link
Copy Markdown
Contributor
<div>&lt;b&gt;hi&lt;/b&gt;</div>
<input title="a &amp;amp; b" />

Vapor renders the first line in bold and the title as a & b; vdom keeps the literal tags and a &amp; b (playground). Static attribute values go the same way, and comment data is escaped where vdom leaves it raw.

The compiler resolves character references while parsing, then vapor hands its template string to the html parser a second time at runtime, so whatever is left in that string gets decoded again. Static values were escaped for " only. I escape them for that second parse, and write comment data raw the way document.createComment does.

stringifyStatic still double-escapes a comment inside a stringified element, so vdom is inconsistent with itself there. Separate compiler-dom bug, left alone.

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 15d50bbf-7a11-4328-9978-f82a1ecee00f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@pkg-pr-new

pkg-pr-new Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@15563
npm i https://pkg.pr.new/@vue/compiler-core@15563
yarn add https://pkg.pr.new/@vue/compiler-core@15563.tgz

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@15563
npm i https://pkg.pr.new/@vue/compiler-dom@15563
yarn add https://pkg.pr.new/@vue/compiler-dom@15563.tgz

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@15563
npm i https://pkg.pr.new/@vue/compiler-sfc@15563
yarn add https://pkg.pr.new/@vue/compiler-sfc@15563.tgz

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@15563
npm i https://pkg.pr.new/@vue/compiler-ssr@15563
yarn add https://pkg.pr.new/@vue/compiler-ssr@15563.tgz

@vue/compiler-vapor

pnpm add https://pkg.pr.new/@vue/compiler-vapor@15563
npm i https://pkg.pr.new/@vue/compiler-vapor@15563
yarn add https://pkg.pr.new/@vue/compiler-vapor@15563.tgz

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@15563
npm i https://pkg.pr.new/@vue/reactivity@15563
yarn add https://pkg.pr.new/@vue/reactivity@15563.tgz

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@15563
npm i https://pkg.pr.new/@vue/runtime-core@15563
yarn add https://pkg.pr.new/@vue/runtime-core@15563.tgz

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@15563
npm i https://pkg.pr.new/@vue/runtime-dom@15563
yarn add https://pkg.pr.new/@vue/runtime-dom@15563.tgz

@vue/runtime-vapor

pnpm add https://pkg.pr.new/@vue/runtime-vapor@15563
npm i https://pkg.pr.new/@vue/runtime-vapor@15563
yarn add https://pkg.pr.new/@vue/runtime-vapor@15563.tgz

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@15563
npm i https://pkg.pr.new/@vue/server-renderer@15563
yarn add https://pkg.pr.new/@vue/server-renderer@15563.tgz

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@15563
npm i https://pkg.pr.new/@vue/shared@15563
yarn add https://pkg.pr.new/@vue/shared@15563.tgz

vue

pnpm add https://pkg.pr.new/vue@15563
npm i https://pkg.pr.new/vue@15563
yarn add https://pkg.pr.new/vue@15563.tgz

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@15563
npm i https://pkg.pr.new/@vue/compat@15563
yarn add https://pkg.pr.new/@vue/compat@15563.tgz

commit: 8a259b0

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
compiler-dom.global.prod.js 87.2 kB 30.6 kB 26.9 kB
runtime-dom.global.prod.js 117 kB 44 kB 39.5 kB
vue.global.prod.js 177 kB 64.2 kB 57.1 kB

Usages

Name Size Gzip Brotli
createApp (CAPI only) 53.8 kB 20.9 kB 19.1 kB
createApp 62.6 kB 24.1 kB 21.9 kB
createApp + vaporInteropPlugin 122 kB 43.7 kB 39.4 kB
createVaporApp 30.8 kB 11.8 kB 10.9 kB
createSSRApp 67.8 kB 26.1 kB 23.7 kB
createVaporSSRApp 37.2 kB 14.1 kB 12.9 kB
defineCustomElement 69.1 kB 26 kB 23.7 kB
defineVaporCustomElement 46.2 kB 16.8 kB 15.4 kB
overall 78.1 kB 29.6 kB 26.9 kB

@edison1105

Copy link
Copy Markdown
Member

Thanks for the fix! For createElement-backed parents, text not starting with < still gets escaped before reaching createTextNode. For example, <my-element>Tom &amp; Jerry</my-element> (configured as a custom element) displays the literal &amp;.

Could we skip escaping for these parents in both the plain-text and folded-interpolation paths, while keeping the leading-< guard?

@edison1105 edison1105 added wait changes scope: vapor related to vapor mode labels Sep 18, 2026
@ValentinYoushkevich
ValentinYoushkevich force-pushed the fix/vapor-static-attr-double-decode branch from 56bd7dd to 0031564 Compare September 18, 2026 10:13
@ValentinYoushkevich

Copy link
Copy Markdown
Contributor Author

Done — text now goes into the template raw whenever the parent is createElement-backed, in both the plain-text branch and the folded-interpolation branch of transformText, and <my-element>Tom &amp; Jerry</my-element> renders the same as vdom again.

The leading-< guard has to stay for a reason unrelated to escaping: template() only takes the createTextNode fast path when the string does not start with <, so a raw literal like <b>x</b> would be handed to innerHTML and become markup. Both branches keep materializing that case imperatively.

One thing worth your attention: the same predicate also covers a nested plain <template> element, which shouldUseCreateElement treats the same way, so <div><template>Tom &amp; Jerry</template></div> was corrupted too and is fixed by the same change. Separately, and not touched here, hydrating any createElement-backed parent throws in isComment on a null hydration node — it reproduces on plain minor without this PR, so I left it alone.

@ValentinYoushkevich
ValentinYoushkevich force-pushed the fix/vapor-static-attr-double-decode branch from 0031564 to 8a259b0 Compare September 20, 2026 06:58
@edison1105
edison1105 merged commit 1fdd809 into vuejs:minor Sep 20, 2026
15 checks passed
zhiyuanzmj added a commit to vuejs/vue-jsx-vapor that referenced this pull request Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: vapor related to vapor mode wait changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants