@@ -1275,12 +1275,16 @@ var emptyVNode = function emptyVNode() {
12751275} ;
12761276
12771277function normalizeChildren ( children , ns ) {
1278- // invoke children thunks.
1279- // components always receive their children as thunks so that they
1280- // can perform the actual render inside their own dependency collection cycle.
1281- if ( typeof children === 'function' ) {
1278+ // Invoke children thunks. Components always receive their children
1279+ // as thunks so that they can perform the actual render inside their
1280+ // own dependency collection cycle. Also, since JSX automatically
1281+ // wraps component children in a thunk, we handle nested thunks to
1282+ // prevent situations such as <MyComponent>{ children }</MyComponent>
1283+ // from failing when it produces a double thunk.
1284+ while ( typeof children === 'function' ) {
12821285 children = children ( ) ;
12831286 }
1287+
12841288 if ( isPrimitive ( children ) ) {
12851289 return [ createTextVNode ( children ) ] ;
12861290 }
@@ -1570,7 +1574,6 @@ function lifecycleMixin(Vue) {
15701574}
15711575
15721576function callHook ( vm , hook ) {
1573- vm . $emit ( 'pre-hook:' + hook ) ;
15741577 var handlers = vm . $options [ hook ] ;
15751578 if ( handlers ) {
15761579 for ( var i = 0 , j = handlers . length ; i < j ; i ++ ) {
@@ -1793,12 +1796,11 @@ function extractProps(data, Ctor) {
17931796 var attrs = data . attrs ;
17941797 var props = data . props ;
17951798 var domProps = data . domProps ;
1796- var staticAttrs = data . staticAttrs ;
17971799
1798- if ( attrs || props || domProps || staticAttrs ) {
1800+ if ( attrs || props || domProps ) {
17991801 for ( var key in propOptions ) {
18001802 var altKey = hyphenate ( key ) ;
1801- checkProp ( res , props , key , altKey , true ) || checkProp ( res , attrs , key , altKey ) || checkProp ( res , domProps , key , altKey ) || checkProp ( res , staticAttrs , key , altKey ) ;
1803+ checkProp ( res , props , key , altKey , true ) || checkProp ( res , attrs , key , altKey ) || checkProp ( res , domProps , key , altKey ) ;
18021804 }
18031805 }
18041806 return res ;
@@ -2890,7 +2892,7 @@ Object.defineProperty(Vue.prototype, '$isServer', {
28902892 }
28912893} ) ;
28922894
2893- Vue . version = '2.0.0-beta.5 ' ;
2895+ Vue . version = '2.0.0-beta.6 ' ;
28942896
28952897// attributes that should be using props for binding
28962898var mustUseProp = makeMap ( 'value,selected,checked,muted' ) ;
@@ -2917,14 +2919,18 @@ var isFalsyAttrValue = function isFalsyAttrValue(val) {
29172919
29182920function genClassForVnode ( vnode ) {
29192921 var data = vnode . data ;
2920- // Important: check if this is a component container node
2921- // or a child component root node
2922- var i = void 0 ;
2923- if ( ( i = vnode . child ) && ( i = i . _vnode . data ) ) {
2924- data = mergeClassData ( i , data ) ;
2922+ var parentNode = vnode ;
2923+ var childNode = vnode ;
2924+ while ( childNode . child ) {
2925+ childNode = childNode . child . _vnode ;
2926+ if ( childNode . data ) {
2927+ data = mergeClassData ( childNode . data , data ) ;
2928+ }
29252929 }
2926- if ( ( i = vnode . parent ) && ( i = i . data ) ) {
2927- data = mergeClassData ( data , i ) ;
2930+ while ( parentNode = parentNode . parent ) {
2931+ if ( parentNode . data ) {
2932+ data = mergeClassData ( data , parentNode . data ) ;
2933+ }
29282934 }
29292935 return genClassFromData ( data ) ;
29302936}
@@ -3665,10 +3671,13 @@ function updateAttrs(oldVnode, vnode) {
36653671 var elm = vnode . elm ;
36663672 var oldAttrs = oldVnode . data . attrs || { } ;
36673673 var attrs = vnode . data . attrs || { } ;
3668- var clonedAttrs = vnode . data . attrs = { } ;
3674+ // clone observed objects, as the user probably wants to mutate it
3675+ if ( attrs . __ob__ ) {
3676+ attrs = vnode . data . attrs = extend ( { } , attrs ) ;
3677+ }
36693678
36703679 for ( key in attrs ) {
3671- cur = clonedAttrs [ key ] = attrs [ key ] ;
3680+ cur = attrs [ key ] ;
36723681 old = oldAttrs [ key ] ;
36733682 if ( old !== cur ) {
36743683 setAttr ( elm , key , cur ) ;
@@ -3712,22 +3721,15 @@ function setAttr(el, key, value) {
37123721}
37133722
37143723var attrs = {
3715- create : function create ( _ , vnode ) {
3716- var attrs = vnode . data . staticAttrs ;
3717- if ( attrs ) {
3718- for ( var key in attrs ) {
3719- setAttr ( vnode . elm , key , attrs [ key ] ) ;
3720- }
3721- }
3722- updateAttrs ( _ , vnode ) ;
3723- } ,
3724+ create : updateAttrs ,
37243725 update : updateAttrs
37253726} ;
37263727
37273728function updateClass ( oldVnode , vnode ) {
37283729 var el = vnode . elm ;
37293730 var data = vnode . data ;
3730- if ( ! data . staticClass && ! data . class ) {
3731+ var oldData = oldVnode . data ;
3732+ if ( ! data . staticClass && ! data . class && ( ! oldData || ! oldData . staticClass && ! oldData . class ) ) {
37313733 return ;
37323734 }
37333735
@@ -3780,23 +3782,32 @@ function updateDOMProps(oldVnode, vnode) {
37803782 var elm = vnode . elm ;
37813783 var oldProps = oldVnode . data . domProps || { } ;
37823784 var props = vnode . data . domProps || { } ;
3783- var clonedProps = vnode . data . domProps = { } ;
3785+ // clone observed objects, as the user probably wants to mutate it
3786+ if ( props . __ob__ ) {
3787+ props = vnode . data . domProps = extend ( { } , props ) ;
3788+ }
37843789
37853790 for ( key in oldProps ) {
37863791 if ( props [ key ] == null ) {
37873792 elm [ key ] = undefined ;
37883793 }
37893794 }
37903795 for ( key in props ) {
3791- cur = clonedProps [ key ] = props [ key ] ;
3796+ // ignore children if the node has textContent or innerHTML,
3797+ // as these will throw away existing DOM nodes and cause removal errors
3798+ // on subsequent patches (#3360)
3799+ if ( ( key === 'textContent' || key === 'innerHTML' ) && vnode . children ) {
3800+ vnode . children . length = 0 ;
3801+ }
3802+ cur = props [ key ] ;
37923803 if ( key === 'value' ) {
37933804 // store value as _value as well since
37943805 // non-string values will be stringified
37953806 elm . _value = cur ;
37963807 // avoid resetting cursor position when value is the same
3797- if ( elm . value ! = cur ) {
3798- // eslint-disable-line
3799- elm . value = cur ;
3808+ var strCur = cur == null ? '' : String ( cur ) ;
3809+ if ( elm . value !== strCur ) {
3810+ elm . value = strCur ;
38003811 }
38013812 } else {
38023813 elm [ key ] = cur ;
@@ -3836,23 +3847,26 @@ function updateStyle(oldVnode, vnode) {
38363847 var elm = vnode . elm ;
38373848 var oldStyle = oldVnode . data . style || { } ;
38383849 var style = vnode . data . style || { } ;
3850+ var needClone = style . __ob__ ;
38393851
38403852 // handle array syntax
38413853 if ( Array . isArray ( style ) ) {
3842- style = toObject ( style ) ;
3854+ style = vnode . data . style = toObject ( style ) ;
38433855 }
38443856
38453857 // clone the style for future updates,
38463858 // in case the user mutates the style object in-place.
3847- var clonedStyle = vnode . data . style = { } ;
3859+ if ( needClone ) {
3860+ style = vnode . data . style = extend ( { } , style ) ;
3861+ }
38483862
38493863 for ( name in oldStyle ) {
38503864 if ( ! style [ name ] ) {
38513865 elm . style [ normalize ( name ) ] = '' ;
38523866 }
38533867 }
38543868 for ( name in style ) {
3855- cur = clonedStyle [ name ] = style [ name ] ;
3869+ cur = style [ name ] ;
38563870 if ( cur !== oldStyle [ name ] ) {
38573871 // ie9 setting to null has no effect, must use empty string
38583872 elm . style [ normalize ( name ) ] = cur || '' ;
@@ -4376,11 +4390,17 @@ function trigger(el, type) {
43764390 el . dispatchEvent ( e ) ;
43774391}
43784392
4393+ // recursively search for possible transition defined inside the component root
4394+ function locateNode ( vnode ) {
4395+ return vnode . child && ( ! vnode . data || ! vnode . data . transition ) ? locateNode ( vnode . child . _vnode ) : vnode ;
4396+ }
4397+
43794398var show = {
43804399 bind : function bind ( el , _ref , vnode ) {
43814400 var value = _ref . value ;
43824401
4383- var transition = vnode . data . transition ;
4402+ vnode = locateNode ( vnode ) ;
4403+ var transition = vnode . data && vnode . data . transition ;
43844404 if ( value && transition && transition . appear && ! isIE9 ) {
43854405 enter ( vnode ) ;
43864406 }
@@ -4389,7 +4409,8 @@ var show = {
43894409 update : function update ( el , _ref2 , vnode ) {
43904410 var value = _ref2 . value ;
43914411
4392- var transition = vnode . data . transition ;
4412+ vnode = locateNode ( vnode ) ;
4413+ var transition = vnode . data && vnode . data . transition ;
43934414 if ( transition && ! isIE9 ) {
43944415 if ( value ) {
43954416 enter ( vnode ) ;
@@ -4452,16 +4473,11 @@ var Transition = {
44524473 return ;
44534474 }
44544475
4455- // warn text nodes
4456- if ( process . env . NODE_ENV !== 'production' && children . length === 1 && ! children [ 0 ] . tag ) {
4457- warn ( '<transition> can only be used on elements or components, not text nodes.' , this . $parent ) ;
4458- }
4459-
44604476 // filter out text nodes (possible whitespaces)
44614477 children = children . filter ( function ( c ) {
44624478 return c . tag ;
44634479 } ) ;
4464-
4480+ /* istanbul ignore if */
44654481 if ( ! children . length ) {
44664482 return ;
44674483 }
0 commit comments