refactor(compiler-vapor): introduce a dedicated KEY IR node + generator path#14413
refactor(compiler-vapor): introduce a dedicated KEY IR node + generator path#14413edison1105 merged 5 commits intovuejs:minorfrom
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the
✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-sfc
@vue/compiler-ssr
@vue/compiler-vapor
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/runtime-vapor
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
Size ReportBundles
Usages
|
There was a problem hiding this comment.
Pull request overview
This PR refactors how :key is handled in compiler-vapor by introducing a dedicated KEY IR node + generator path, instead of encoding “keyed blocks” on BlockIRNode.
Changes:
- Introduces
transformKeyto emit a newIRNodeTypes.KEYoperation and a newgenKeycodegen implementation. - Updates template-wrapping logic so
:keycan be reserved/split correctly (notably forv-forwrapping). - Removes the previous keyed-block mechanism from
transformElement,BlockIRNode, and root codegen, and updates/relocates related tests & snapshots.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/compiler-vapor/src/transforms/vFor.ts | Ensures wrapTemplate also reserves key when processing v-for. |
| packages/compiler-vapor/src/transforms/utils.ts | Extends wrapTemplate to treat v-bind:key as reservable when dirs includes key. |
| packages/compiler-vapor/src/transforms/transformKey.ts | New transform that turns dynamic key bindings into a KEY IR operation. |
| packages/compiler-vapor/src/transforms/transformElement.ts | Removes prior keyed-block marking logic from element transform. |
| packages/compiler-vapor/src/ir/index.ts | Adds IRNodeTypes.KEY + KeyIRNode; removes keyed-block fields from BlockIRNode. |
| packages/compiler-vapor/src/index.ts | Exports the new transformKey. |
| packages/compiler-vapor/src/generators/operation.ts | Routes IRNodeTypes.KEY to the new genKey generator. |
| packages/compiler-vapor/src/generators/key.ts | New generator emitting createKeyedFragment calls for KEY ops. |
| packages/compiler-vapor/src/generators/block.ts | Removes old keyed-fragment wrapping helpers/logic from genBlock. |
| packages/compiler-vapor/src/generate.ts | Removes root-level keyed-block special casing; relies on KEY ops. |
| packages/compiler-vapor/src/compile.ts | Adds transformKey into the base transform preset. |
| packages/compiler-vapor/tests/transforms/vOnce.spec.ts | Adds coverage for v-once combined with :key. |
| packages/compiler-vapor/tests/transforms/transformKey.spec.ts | New test suite for KEY IR + codegen behavior. |
| packages/compiler-vapor/tests/transforms/transformElement.spec.ts | Removes key-related assertions now covered by transformKey tests. |
| packages/compiler-vapor/tests/transforms/logicalIndex.spec.ts | Adds logicalIndex/insertion-state coverage for key fragments. |
| packages/compiler-vapor/tests/transforms/snapshots/vOnce.spec.ts.snap | Snapshot updates for new v-once + key test. |
| packages/compiler-vapor/tests/transforms/snapshots/transformKey.spec.ts.snap | New snapshots for key transform/codegen cases. |
| packages/compiler-vapor/tests/transforms/snapshots/transformElement.spec.ts.snap | Removes keyed-fragment snapshots tied to old keyed-block behavior. |
| packages/compiler-vapor/tests/transforms/snapshots/logicalIndex.spec.ts.snap | Adds snapshots for new key insertion-state cases. |
| packages/compiler-vapor/tests/transforms/snapshots/TransformTransition.spec.ts.snap | Snapshot updates due to transform ordering/ID shifts with KEY ops. |
| packages/compiler-vapor/tests/transforms/TransformTransition.spec.ts | Adds transformKey to the transform chain and updates expectation string. |
Comments suppressed due to low confidence (1)
packages/compiler-vapor/src/transforms/utils.ts:90
wrapTemplatenow correctly reservesv-bind:key/:keywhendirsincludes'key'for non-<template>nodes, but thenode.tagType === ElementTypes.TEMPLATEbranch above still only checksdirs.includes(prop.name)and will not reserve:key(since its directive name is'bind'). In cases where a<template>needs to be wrapped (e.g. combining structural directives) this can push:keydown into the child, allowingtransformKeyto run on it (or leaving the key on the wrong node) and produce an extra keyed fragment.
Apply the same v-bind:key detection logic to the template-branch splitting as well so :key stays with the intended wrapper when dirs includes 'key'.
const reserved: Array<AttributeNode | DirectiveNode> = []
const pass: Array<AttributeNode | DirectiveNode> = []
node.props.forEach(prop => {
if (
prop.type === NodeTypes.DIRECTIVE &&
(dirs.includes(prop.name) ||
(prop.name === 'bind' &&
prop.arg &&
prop.arg.type === NodeTypes.SIMPLE_EXPRESSION &&
prop.arg.content === 'key' &&
dirs.includes('key')))
) {
reserved.push(prop)
} else {
pass.push(prop)
}
})
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/compiler-vapor/__tests__/transforms/transformKey.spec.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts`:
- Around line 220-224: The test uses an inconsistent Jest matcher: change the
incorrect expect(code).matchSnapshot() in the 'with key' test to the standard
expect(code).toMatchSnapshot() so it matches the other tests; locate the
assertion that calls matchSnapshot() (in the test that calls
compileWithOnce(`<div :key="foo" v-once />`)) and replace it with
toMatchSnapshot().
🧹 Nitpick comments (1)
packages/compiler-vapor/src/transforms/transformKey.ts (1)
23-23: Preferconstfor non-reassigned variables.
idis never reassigned after initialization.♻️ Suggested fix
- let id = context.reference() + const id = context.reference()
Summary by CodeRabbit
New Features
Tests
Refactor