@@ -1275,12 +1275,16 @@ var emptyVNode = function emptyVNode() {
1275
1275
} ;
1276
1276
1277
1277
function 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' ) {
1282
1285
children = children ( ) ;
1283
1286
}
1287
+
1284
1288
if ( isPrimitive ( children ) ) {
1285
1289
return [ createTextVNode ( children ) ] ;
1286
1290
}
@@ -1570,7 +1574,6 @@ function lifecycleMixin(Vue) {
1570
1574
}
1571
1575
1572
1576
function callHook ( vm , hook ) {
1573
- vm . $emit ( 'pre-hook:' + hook ) ;
1574
1577
var handlers = vm . $options [ hook ] ;
1575
1578
if ( handlers ) {
1576
1579
for ( var i = 0 , j = handlers . length ; i < j ; i ++ ) {
@@ -1793,12 +1796,11 @@ function extractProps(data, Ctor) {
1793
1796
var attrs = data . attrs ;
1794
1797
var props = data . props ;
1795
1798
var domProps = data . domProps ;
1796
- var staticAttrs = data . staticAttrs ;
1797
1799
1798
- if ( attrs || props || domProps || staticAttrs ) {
1800
+ if ( attrs || props || domProps ) {
1799
1801
for ( var key in propOptions ) {
1800
1802
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 ) ;
1802
1804
}
1803
1805
}
1804
1806
return res ;
@@ -2890,7 +2892,7 @@ Object.defineProperty(Vue.prototype, '$isServer', {
2890
2892
}
2891
2893
} ) ;
2892
2894
2893
- Vue . version = '2.0.0-beta.5 ' ;
2895
+ Vue . version = '2.0.0-beta.6 ' ;
2894
2896
2895
2897
// attributes that should be using props for binding
2896
2898
var mustUseProp = makeMap ( 'value,selected,checked,muted' ) ;
@@ -2917,14 +2919,18 @@ var isFalsyAttrValue = function isFalsyAttrValue(val) {
2917
2919
2918
2920
function genClassForVnode ( vnode ) {
2919
2921
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
+ }
2925
2929
}
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
+ }
2928
2934
}
2929
2935
return genClassFromData ( data ) ;
2930
2936
}
@@ -3665,10 +3671,13 @@ function updateAttrs(oldVnode, vnode) {
3665
3671
var elm = vnode . elm ;
3666
3672
var oldAttrs = oldVnode . data . attrs || { } ;
3667
3673
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
+ }
3669
3678
3670
3679
for ( key in attrs ) {
3671
- cur = clonedAttrs [ key ] = attrs [ key ] ;
3680
+ cur = attrs [ key ] ;
3672
3681
old = oldAttrs [ key ] ;
3673
3682
if ( old !== cur ) {
3674
3683
setAttr ( elm , key , cur ) ;
@@ -3712,22 +3721,15 @@ function setAttr(el, key, value) {
3712
3721
}
3713
3722
3714
3723
var 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 ,
3724
3725
update : updateAttrs
3725
3726
} ;
3726
3727
3727
3728
function updateClass ( oldVnode , vnode ) {
3728
3729
var el = vnode . elm ;
3729
3730
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 ) ) {
3731
3733
return ;
3732
3734
}
3733
3735
@@ -3780,23 +3782,32 @@ function updateDOMProps(oldVnode, vnode) {
3780
3782
var elm = vnode . elm ;
3781
3783
var oldProps = oldVnode . data . domProps || { } ;
3782
3784
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
+ }
3784
3789
3785
3790
for ( key in oldProps ) {
3786
3791
if ( props [ key ] == null ) {
3787
3792
elm [ key ] = undefined ;
3788
3793
}
3789
3794
}
3790
3795
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 ] ;
3792
3803
if ( key === 'value' ) {
3793
3804
// store value as _value as well since
3794
3805
// non-string values will be stringified
3795
3806
elm . _value = cur ;
3796
3807
// 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 ;
3800
3811
}
3801
3812
} else {
3802
3813
elm [ key ] = cur ;
@@ -3836,23 +3847,26 @@ function updateStyle(oldVnode, vnode) {
3836
3847
var elm = vnode . elm ;
3837
3848
var oldStyle = oldVnode . data . style || { } ;
3838
3849
var style = vnode . data . style || { } ;
3850
+ var needClone = style . __ob__ ;
3839
3851
3840
3852
// handle array syntax
3841
3853
if ( Array . isArray ( style ) ) {
3842
- style = toObject ( style ) ;
3854
+ style = vnode . data . style = toObject ( style ) ;
3843
3855
}
3844
3856
3845
3857
// clone the style for future updates,
3846
3858
// 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
+ }
3848
3862
3849
3863
for ( name in oldStyle ) {
3850
3864
if ( ! style [ name ] ) {
3851
3865
elm . style [ normalize ( name ) ] = '' ;
3852
3866
}
3853
3867
}
3854
3868
for ( name in style ) {
3855
- cur = clonedStyle [ name ] = style [ name ] ;
3869
+ cur = style [ name ] ;
3856
3870
if ( cur !== oldStyle [ name ] ) {
3857
3871
// ie9 setting to null has no effect, must use empty string
3858
3872
elm . style [ normalize ( name ) ] = cur || '' ;
@@ -4376,11 +4390,17 @@ function trigger(el, type) {
4376
4390
el . dispatchEvent ( e ) ;
4377
4391
}
4378
4392
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
+
4379
4398
var show = {
4380
4399
bind : function bind ( el , _ref , vnode ) {
4381
4400
var value = _ref . value ;
4382
4401
4383
- var transition = vnode . data . transition ;
4402
+ vnode = locateNode ( vnode ) ;
4403
+ var transition = vnode . data && vnode . data . transition ;
4384
4404
if ( value && transition && transition . appear && ! isIE9 ) {
4385
4405
enter ( vnode ) ;
4386
4406
}
@@ -4389,7 +4409,8 @@ var show = {
4389
4409
update : function update ( el , _ref2 , vnode ) {
4390
4410
var value = _ref2 . value ;
4391
4411
4392
- var transition = vnode . data . transition ;
4412
+ vnode = locateNode ( vnode ) ;
4413
+ var transition = vnode . data && vnode . data . transition ;
4393
4414
if ( transition && ! isIE9 ) {
4394
4415
if ( value ) {
4395
4416
enter ( vnode ) ;
@@ -4452,16 +4473,11 @@ var Transition = {
4452
4473
return ;
4453
4474
}
4454
4475
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
-
4460
4476
// filter out text nodes (possible whitespaces)
4461
4477
children = children . filter ( function ( c ) {
4462
4478
return c . tag ;
4463
4479
} ) ;
4464
-
4480
+ /* istanbul ignore if */
4465
4481
if ( ! children . length ) {
4466
4482
return ;
4467
4483
}
0 commit comments