Skip to content

fix(compiler-core): prefix dynamic keys on v-memo elements#14922

Open
edison1105 wants to merge 1 commit into
mainfrom
edison/fix/14920
Open

fix(compiler-core): prefix dynamic keys on v-memo elements#14922
edison1105 wants to merge 1 commit into
mainfrom
edison/fix/14920

Conversation

@edison1105
Copy link
Copy Markdown
Member

@edison1105 edison1105 commented Jun 5, 2026

close #14920

Summary by CodeRabbit

  • Bug Fixes

    • Corrected handling of dynamic keys for v-memo so directive arguments are processed correctly both outside and inside v-for contexts.
  • Tests

    • Added tests covering v-memo with dynamic keys on normal elements and nested v-memo + dynamic-key-in-v-for scenarios.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Add a WeakSet on TransformContext to track v-for memo-keyed nodes, record memo-keyed nodes in transformFor, restrict skipping of :key processing for v-memo to v-for scopes, and add tests covering dynamic :key on plain elements and inside v-for.

Changes

v-memo + v-for key handling

Layer / File(s) Summary
TransformContext: add vForMemoKeyedNodes
packages/compiler-core/src/transform.ts
TransformContext gains vForMemoKeyedNodes: WeakSet<ElementNode> and it is initialized in createTransformContext.
Record memo-keyed v-for nodes
packages/compiler-core/src/transforms/vFor.ts
When processing non-browser <template v-for> with v-memo, the node is added to context.vForMemoKeyedNodes.
Restrict v-memo :key skip to v-for scopes
packages/compiler-core/src/transforms/transformExpression.ts
The directive-argument skip that previously avoided processing :key for v-memo now also requires context.scopes.vFor > 0, so plain elements' :key expressions are processed.
Tests: dynamic :key with v-memo (plain & v-for)
packages/compiler-core/__tests__/transforms/vMemo.spec.ts
Add tests compiling v-memo="[updateKey]" with dynamic :key on a plain element and a nested v-for case; assert generated code includes memo deps and correctly prefixed/computed key expressions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • vuejs/core#14861: Both PRs adjust compiler-core handling of v-memo + v-for + :key, addressing related code paths.

Suggested labels

ready to merge, scope: compiler, :hammer: p3-minor-bug

Suggested reviewers

  • sxzz
  • baiwusanyu-c
  • KazariEX

Poem

"I nibble at keys and scopes all day,
A tiny rabbit in the compiler's hay.
I tuck memo nodes in a gentle set,
So keys are prefixed and bugs forget.
Hooray — no ReferenceError today!" 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately describes the main fix: properly prefixing dynamic :key expressions on v-memo elements, which is the core issue addressed across the codebase changes.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #14920: it ensures dynamic :key expressions on v-memo elements without v-for are properly prefixed by tracking memo-keyed nodes and adjusting transformExpression logic.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the v-memo dynamic :key prefixing issue; modifications to transform.ts, transformExpression.ts, vFor.ts, and test files are all necessary for addressing the bug.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch edison/fix/14920

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB 40.1 kB 36 kB
vue.global.prod.js 164 kB (+31 B) 60.1 kB (+14 B) 53.5 kB (-2 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.8 kB 19 kB 17.4 kB
createApp 56.9 kB 22 kB 20.1 kB
createSSRApp 61.2 kB 23.8 kB 21.7 kB
defineCustomElement 63.1 kB 23.9 kB 21.8 kB
overall 71.7 kB 27.4 kB 25 kB

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 5, 2026

Open in StackBlitz

@vue/compiler-core

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

@vue/compiler-dom

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

@vue/compiler-sfc

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

@vue/compiler-ssr

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

@vue/reactivity

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

@vue/runtime-core

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

@vue/runtime-dom

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

@vue/server-renderer

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

@vue/shared

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

vue

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

@vue/compat

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

commit: 2c46a65

Copy link
Copy Markdown

@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

🤖 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 `@packages/compiler-core/src/transforms/transformExpression.ts`:
- Around line 72-74: The condition that currently uses context.scopes.vFor > 0
to skip :key processing is too broad; change the logic to rely on a
node-specific ownership flag set by transformFor (e.g., transformFor should mark
the element/node with a boolean like node.__vForKeyed or node.vForKeyProcessed
when it actually handled the key), and then in transformExpression (the branch
that checks memo && context.scopes.vFor > 0 && arg) replace the
context.scopes.vFor check with a test against that node-specific flag (skip only
if node.__vForKeyed is true), and ensure transformFor sets that flag on the
exact node it pre-handles so nested non-owner v-memo elements still get their
keys prefixed.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7027883a-83d0-437e-bf9f-1d5b2293d4e6

📥 Commits

Reviewing files that changed from the base of the PR and between 9d92dbd and 431c27a.

📒 Files selected for processing (2)
  • packages/compiler-core/__tests__/transforms/vMemo.spec.ts
  • packages/compiler-core/src/transforms/transformExpression.ts

Comment thread packages/compiler-core/src/transforms/transformExpression.ts
Copy link
Copy Markdown

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

🧹 Nitpick comments (1)
packages/compiler-core/__tests__/transforms/vMemo.spec.ts (1)

24-43: ⚡ Quick win

Consider adding snapshot tests or negative assertions for additional coverage.

The current string-matching assertions effectively verify the bug fix, but you could strengthen these tests by:

  1. Adding negative assertions to confirm unprefixed identifiers are absent (e.g., expect(code).not.toContain('key: updateKey')).
  2. Using .toMatchSnapshot() for full output validation, similar to other tests in this file (lines 17, 21, 46, 55, 65, 75, 85, 95).

Both approaches would provide additional confidence that the generated code is fully correct and prevent subtle regressions.

🤖 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 `@packages/compiler-core/__tests__/transforms/vMemo.spec.ts` around lines 24 -
43, Add stronger assertions to the two tests using the existing compile(...)
helper: in each test ('on normal element with dynamic key' and 'on normal
element with dynamic key nested in v-for') add negative assertions like
expect(code).not.toContain('key: updateKey') and
expect(code).not.toContain('key: item.id') (or other unprefixed forms) to ensure
identifiers are properly prefixed, and also call expect(code).toMatchSnapshot()
to capture the full generated output for regression safety; update references to
the expected prefixed strings (_withMemo, _ctx.updateKey, _ctx.get(...)) remain
unchanged so the new assertions complement the existing checks.
🤖 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 `@packages/compiler-core/__tests__/transforms/vMemo.spec.ts`:
- Around line 24-43: Add stronger assertions to the two tests using the existing
compile(...) helper: in each test ('on normal element with dynamic key' and 'on
normal element with dynamic key nested in v-for') add negative assertions like
expect(code).not.toContain('key: updateKey') and
expect(code).not.toContain('key: item.id') (or other unprefixed forms) to ensure
identifiers are properly prefixed, and also call expect(code).toMatchSnapshot()
to capture the full generated output for regression safety; update references to
the expected prefixed strings (_withMemo, _ctx.updateKey, _ctx.get(...)) remain
unchanged so the new assertions complement the existing checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bdb2d2c0-66d5-4d25-a904-47423a4a8355

📥 Commits

Reviewing files that changed from the base of the PR and between 431c27a and 2c46a65.

📒 Files selected for processing (4)
  • packages/compiler-core/__tests__/transforms/vMemo.spec.ts
  • packages/compiler-core/src/transform.ts
  • packages/compiler-core/src/transforms/transformExpression.ts
  • packages/compiler-core/src/transforms/vFor.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/compiler-core/src/transforms/transformExpression.ts

@edison1105
Copy link
Copy Markdown
Member Author

/ecosystem-ci run

@edison1105 edison1105 added ready to merge The PR is ready to be merged. scope: compiler 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Jun 5, 2026
@vue-bot
Copy link
Copy Markdown
Contributor

vue-bot commented Jun 5, 2026

📝 Ran ecosystem CI: Open

suite result latest scheduled
router success success
language-tools success success
radix-vue failure failure
nuxt success success
vue-i18n success success
vitepress success success
primevue success success
quasar success success
vant success success
test-utils success success
vite-plugin-vue success success
pinia success success
vue-macros success success
vue-simple-compiler success success
vueuse success success
vuetify success success

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

Labels

🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged. scope: compiler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compiler-core: :key expression not prefixed when element has v-memo without v-for (ReferenceError at runtime)

2 participants