Skip to content

Commit a53d54a

Browse files
committed
fix whitespace vnode identity breaking patch (fix #3043)
1 parent be51320 commit a53d54a

File tree

9 files changed

+40
-22
lines changed

9 files changed

+40
-22
lines changed

examples/tree/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
v-for="model in model.children"
4141
:model="model">
4242
</item>
43-
<li @click="addChild">+</li>
43+
<li class="add" @click="addChild">+</li>
4444
</ul>
4545
</li>
4646
</script>

src/core/instance/lifecycle.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function lifecycleMixin (Vue: Class<Component>) {
3131
const vm: Component = this
3232
vm.$el = el
3333
if (!vm.$options.render) {
34-
vm.$options.render = () => emptyVNode
34+
vm.$options.render = emptyVNode
3535
if (process.env.NODE_ENV !== 'production') {
3636
/* istanbul ignore if */
3737
if (vm.$options.template) {

src/core/instance/render.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function renderMixin (Vue: Class<Component>) {
7070
vm
7171
)
7272
}
73-
vnode = emptyVNode
73+
vnode = emptyVNode()
7474
}
7575
// set parent
7676
vnode.parent = _parentVnode

src/core/vdom/create-element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function renderElement (
4646
}
4747
if (!tag) {
4848
// in case of component :is set to falsy value
49-
return emptyVNode
49+
return emptyVNode()
5050
}
5151
if (typeof tag === 'string') {
5252
let Ctor

src/core/vdom/helpers.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import { isPrimitive } from '../util/index'
44
import VNode from './vnode'
55

6-
const whitespace = new VNode(undefined, undefined, undefined, ' ')
7-
86
export function normalizeChildren (children: any): Array<VNode> {
97
// invoke children thunks.
108
// components always receive their children as thunks so that they
@@ -23,13 +21,8 @@ export function normalizeChildren (children: any): Array<VNode> {
2321
if (Array.isArray(c)) {
2422
res.push.apply(res, normalizeChildren(c))
2523
} else if (isPrimitive(c)) {
26-
// optimize whitespace
27-
if (c === ' ') {
28-
res.push(whitespace)
29-
} else {
30-
// convert primitive to vnode
31-
res.push(new VNode(undefined, undefined, undefined, c))
32-
}
24+
// convert primitive to vnode
25+
res.push(new VNode(undefined, undefined, undefined, c))
3326
} else if (c instanceof VNode) {
3427
res.push(c)
3528
}

src/core/vdom/patch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,14 @@ export function createPatchFunction (backend) {
250250
}
251251

252252
function patchVnode (oldVnode, vnode, insertedVnodeQueue) {
253+
if (oldVnode === vnode) return
253254
let i, hook
254255
if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
255256
i(oldVnode, vnode)
256257
}
257258
const elm = vnode.elm = oldVnode.elm
258259
const oldCh = oldVnode.children
259260
const ch = vnode.children
260-
if (oldVnode === vnode) return
261261
if (isDef(vnode.data)) {
262262
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
263263
if (isDef(hook) && isDef(i = hook.update)) i(oldVnode, vnode)

src/core/vdom/vnode.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ export default class VNode {
4848
}
4949
}
5050

51-
export const emptyVNode = new VNode(undefined, undefined, undefined, '')
51+
export const emptyVNode = () => new VNode(undefined, undefined, undefined, '')

test/e2e/specs/tree.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,45 @@ module.exports = {
44
.url('http://localhost:8080/examples/tree/')
55
.waitForElementVisible('li', 1000)
66
.assert.count('.item', 12)
7+
.assert.count('.add', 4)
78
.assert.count('.item > ul', 4)
89
.assert.notVisible('#demo li ul')
910
.assert.containsText('#demo li div span', '[+]')
1011

12+
// expand root
1113
.click('.bold')
1214
.assert.visible('#demo ul')
13-
.assert.containsText('#demo li div span', '[-]')
14-
.assert.containsText('#demo ul > .item:nth-child(1)', 'hello')
15-
.assert.containsText('#demo ul > .item:nth-child(2)', 'wat')
16-
.assert.containsText('#demo ul > .item:nth-child(3)', 'child folder')
17-
.assert.containsText('#demo ul > .item:nth-child(3)', '[+]')
1815
.assert.evaluate(function () {
1916
return document.querySelector('#demo li ul').children.length === 4
2017
})
18+
.assert.containsText('#demo li div span', '[-]')
19+
.assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')
20+
.assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')
21+
.assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')
22+
.assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')
23+
24+
// add items to root
25+
.click('#demo > .item > ul > .add')
26+
.assert.evaluate(function () {
27+
return document.querySelector('#demo li ul').children.length === 5
28+
})
29+
.assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')
30+
.assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')
31+
.assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')
32+
.assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')
33+
.assert.containsText('#demo > .item > ul > .item:nth-child(4)', 'new stuff')
34+
35+
// add another item
36+
.click('#demo > .item > ul > .add')
37+
.assert.evaluate(function () {
38+
return document.querySelector('#demo li ul').children.length === 6
39+
})
40+
.assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')
41+
.assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')
42+
.assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')
43+
.assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')
44+
.assert.containsText('#demo > .item > ul > .item:nth-child(4)', 'new stuff')
45+
.assert.containsText('#demo > .item > ul > .item:nth-child(5)', 'new stuff')
2146

2247
.click('#demo ul .bold')
2348
.assert.visible('#demo ul ul')
@@ -34,7 +59,7 @@ module.exports = {
3459
.assert.containsText('#demo li div span', '[-]')
3560

3661
.dblClick('#demo ul > .item div')
37-
.assert.count('.item', 13)
62+
.assert.count('.item', 15)
3863
.assert.count('.item > ul', 5)
3964
.assert.containsText('#demo ul > .item:nth-child(1)', '[-]')
4065
.assert.evaluate(function () {

test/unit/modules/vdom/create-element.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe('create-element', () => {
7777
const _e = bind(renderElement, vm)
7878
renderState.activeInstance = vm
7979
const vnode = _e(null, {})
80-
expect(vnode).toEqual(emptyVNode)
80+
expect(vnode).toEqual(emptyVNode())
8181
})
8282

8383
it('render vnode with not string tag using renderElement', () => {

0 commit comments

Comments
 (0)