warn observed vnode data + handle in place mutations for vdom modules (ref #3276)

This commit is contained in:
Evan You 2016-07-14 19:10:18 -04:00
parent e6dcd2157e
commit f0aef7556b
5 changed files with 20 additions and 9 deletions

View File

@ -82,7 +82,7 @@ function runSchedulerQueue (queue: Array<Watcher>) {
if (circular[id] > config._maxUpdateCount) {
warn(
'You may have an infinite update loop ' + (
watcher === watcher.vm._watcher
watcher === watcher.vm && watcher.vm._watcher
? `in a component render function.`
: `in watcher with expression "${watcher.expression}"`
),

View File

@ -37,6 +37,14 @@ function _createElement (
)
return
}
if (data && data.__ob__) {
process.env.NODE_ENV !== 'production' && warn(
`Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
'Always create fresh vnode data objects in each render!',
context
)
return
}
if (!tag) {
// in case of component :is set to falsy value
return emptyVNode()

View File

@ -17,9 +17,10 @@ function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
const elm = vnode.elm
const oldAttrs = oldVnode.data.attrs || {}
const attrs = vnode.data.attrs || {}
const clonedAttrs = vnode.data.attrs = {}
for (key in attrs) {
cur = attrs[key]
cur = clonedAttrs[key] = attrs[key]
old = oldAttrs[key]
if (old !== cur) {
setAttr(elm, key, cur)

View File

@ -8,6 +8,7 @@ function updateProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
const elm: any = vnode.elm
const oldProps = oldVnode.data.props || {}
const props = vnode.data.props || {}
const clonedProps = vnode.data.props = {}
for (key in oldProps) {
if (props[key] == null) {
@ -15,7 +16,7 @@ function updateProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
}
}
for (key in props) {
cur = props[key]
cur = clonedProps[key] = props[key]
if (key === 'value') {
// store value as _value as well since
// non-string values will be stringified

View File

@ -1,6 +1,6 @@
/* @flow */
import { cached, camelize, toObject, extend } from 'shared/util'
import { cached, camelize, toObject } from 'shared/util'
const prefixes = ['Webkit', 'Moz', 'ms']
@ -31,24 +31,25 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
// handle array syntax
if (Array.isArray(style)) {
style = vnode.data.style = toObject(style)
style = toObject(style)
}
// clone the style for future updates,
// in case the user mutates the style object in-place.
const clonedStyle = vnode.data.style = {}
for (name in oldStyle) {
if (!style[name]) {
elm.style[normalize(name)] = ''
}
}
for (name in style) {
cur = style[name]
cur = clonedStyle[name] = style[name]
if (cur !== oldStyle[name]) {
// ie9 setting to null has no effect, must use empty string
elm.style[normalize(name)] = cur || ''
}
}
// clone the style for future updates,
// in case the user mutates the style object in-place.
vnode.data.style = extend({}, style)
}
export default {