Skip to content

Commit 5dbe834

Browse files
authored
fix(rumtime-core): custom dom props should be cloned when cloning a hoisted DOM (#3080)
fix #3072
1 parent eb1fae6 commit 5dbe834

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { nodeOps } from '../src/nodeOps'
2+
3+
describe('nodeOps', () => {
4+
test('the _value property should be cloned', () => {
5+
const el = nodeOps.createElement('input') as HTMLDivElement & {
6+
_value: any
7+
}
8+
el._value = 1
9+
const cloned = nodeOps.cloneNode!(el) as HTMLDivElement & { _value: any }
10+
expect(cloned._value).toBe(1)
11+
})
12+
})

packages/runtime-dom/src/nodeOps.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,20 @@ export const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {
4747
},
4848

4949
cloneNode(el) {
50-
return el.cloneNode(true)
50+
const cloned = el.cloneNode(true)
51+
// #3072
52+
// - in `patchDOMProp`, we store the actual value in the `el._value` property.
53+
// - normally, elements using `:value` bindings will not be hoisted, but if
54+
// the bound value is a constant, e.g. `:value="true"` - they do get
55+
// hoisted.
56+
// - in production, hoisted nodes are cloned when subsequent inserts, but
57+
// cloneNode() does not copy the custom property we attached.
58+
// - This may need to account for other custom DOM properties we attach to
59+
// elements in addition to `_value` in the future.
60+
if (`_value` in el) {
61+
;(cloned as any)._value = (el as any)._value
62+
}
63+
return cloned
5164
},
5265

5366
// __UNSAFE__

0 commit comments

Comments
 (0)