1
1
/*!
2
- * Vue.js v2.6.0-beta.1
2
+ * Vue.js v2.6.0-beta.2
3
3
* (c) 2014-2019 Evan You
4
4
* Released under the MIT License.
5
5
*/
@@ -358,7 +358,7 @@ var LIFECYCLE_HOOKS = [
358
358
'activated' ,
359
359
'deactivated' ,
360
360
'errorCaptured' ,
361
- 'ssrPrefetch '
361
+ 'serverPrefetch '
362
362
] ;
363
363
364
364
/* */
@@ -1878,6 +1878,8 @@ function logError (err, vm, info) {
1878
1878
1879
1879
/* */
1880
1880
1881
+ var isUsingMicroTask = false ;
1882
+
1881
1883
var callbacks = [ ] ;
1882
1884
var pending = false ;
1883
1885
@@ -1921,6 +1923,7 @@ if (typeof Promise !== 'undefined' && isNative(Promise)) {
1921
1923
// "force" the microtask queue to be flushed by adding an empty timer.
1922
1924
if ( isIOS ) { setTimeout ( noop ) ; }
1923
1925
} ;
1926
+ isUsingMicroTask = true ;
1924
1927
} else if ( ! isIE && typeof MutationObserver !== 'undefined' && (
1925
1928
isNative ( MutationObserver ) ||
1926
1929
// PhantomJS and iOS 7.x
@@ -1939,6 +1942,7 @@ if (typeof Promise !== 'undefined' && isNative(Promise)) {
1939
1942
counter = ( counter + 1 ) % 2 ;
1940
1943
textNode . data = String ( counter ) ;
1941
1944
} ;
1945
+ isUsingMicroTask = true ;
1942
1946
} else if ( typeof setImmediate !== 'undefined' && isNative ( setImmediate ) ) {
1943
1947
// Fallback to setImmediate.
1944
1948
// Techinically it leverages the (macro) task queue,
@@ -2737,13 +2741,14 @@ function isWhitespace (node) {
2737
2741
2738
2742
function resolveScopedSlots (
2739
2743
fns , // see flow/vnode
2744
+ hasDynamicKeys ,
2740
2745
res
2741
2746
) {
2742
- res = res || { } ;
2747
+ res = res || { $stable : ! hasDynamicKeys } ;
2743
2748
for ( var i = 0 ; i < fns . length ; i ++ ) {
2744
2749
var slot = fns [ i ] ;
2745
2750
if ( Array . isArray ( slot ) ) {
2746
- resolveScopedSlots ( slot , res ) ;
2751
+ resolveScopedSlots ( slot , hasDynamicKeys , res ) ;
2747
2752
} else {
2748
2753
res [ slot . key ] = slot . fn ;
2749
2754
}
@@ -2959,12 +2964,22 @@ function updateChildComponent (
2959
2964
}
2960
2965
2961
2966
// determine whether component has slot children
2962
- // we need to do this before overwriting $options._renderChildren
2963
- var hasChildren = ! ! (
2967
+ // we need to do this before overwriting $options._renderChildren.
2968
+
2969
+ // check if there are dynamic scopedSlots (hand-written or compiled but with
2970
+ // dynamic slot names). Static scoped slots compiled from template has the
2971
+ // "$stable" marker.
2972
+ var hasDynamicScopedSlot = ! ! (
2973
+ ( parentVnode . data . scopedSlots && ! parentVnode . data . scopedSlots . $stable ) ||
2974
+ ( vm . $scopedSlots !== emptyObject && ! vm . $scopedSlots . $stable )
2975
+ ) ;
2976
+ // Any static slot children from the parent may have changed during parent's
2977
+ // update. Dynamic scoped slots may also have changed. In such cases, a forced
2978
+ // update is necessary to ensure correctness.
2979
+ var needsForceUpdate = ! ! (
2964
2980
renderChildren || // has new static slots
2965
2981
vm . $options . _renderChildren || // has old static slots
2966
- parentVnode . data . scopedSlots || // has new scoped slots
2967
- vm . $scopedSlots !== emptyObject // has old scoped slots
2982
+ hasDynamicScopedSlot
2968
2983
) ;
2969
2984
2970
2985
vm . $options . _parentVnode = parentVnode ;
@@ -3003,7 +3018,7 @@ function updateChildComponent (
3003
3018
updateComponentListeners ( vm , listeners , oldListeners ) ;
3004
3019
3005
3020
// resolve slots + force update if has children
3006
- if ( hasChildren ) {
3021
+ if ( needsForceUpdate ) {
3007
3022
vm . $slots = resolveSlots ( renderChildren , parentVnode . context ) ;
3008
3023
vm . $forceUpdate ( ) ;
3009
3024
}
@@ -3094,10 +3109,32 @@ function resetSchedulerState () {
3094
3109
waiting = flushing = false ;
3095
3110
}
3096
3111
3112
+ // Async edge case #6566 requires saving the timestamp when event listeners are
3113
+ // attached. However, calling performance.now() has a perf overhead especially
3114
+ // if the page has thousands of event listeners. Instead, we take a timestamp
3115
+ // every time the scheduler flushes and use that for all event listeners
3116
+ // attached during that flush.
3117
+ var currentFlushTimestamp = 0 ;
3118
+
3119
+ // Async edge case fix requires storing an event listener's attach timestamp.
3120
+ var getNow = Date . now ;
3121
+
3122
+ // Determine what event timestamp the browser is using. Annoyingly, the
3123
+ // timestamp can either be hi-res ( relative to poge load) or low-res
3124
+ // (relative to UNIX epoch), so in order to compare time we have to use the
3125
+ // same timestamp type when saving the flush timestamp.
3126
+ if ( inBrowser && getNow ( ) > document . createEvent ( 'Event' ) . timeStamp ) {
3127
+ // if the low-res timestamp which is bigger than the event timestamp
3128
+ // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
3129
+ // and we need to use the hi-res version for event listeners as well.
3130
+ getNow = function ( ) { return performance . now ( ) ; } ;
3131
+ }
3132
+
3097
3133
/**
3098
3134
* Flush both queues and run the watchers.
3099
3135
*/
3100
3136
function flushSchedulerQueue ( ) {
3137
+ currentFlushTimestamp = getNow ( ) ;
3101
3138
flushing = true ;
3102
3139
var watcher , id ;
3103
3140
@@ -3854,7 +3891,7 @@ function normalizeScopedSlots (
3854
3891
} else {
3855
3892
res = { } ;
3856
3893
for ( var key in slots ) {
3857
- if ( slots [ key ] ) {
3894
+ if ( slots [ key ] && key [ 0 ] !== '$' ) {
3858
3895
res [ key ] = normalizeScopedSlot ( slots [ key ] ) ;
3859
3896
}
3860
3897
}
@@ -3866,6 +3903,7 @@ function normalizeScopedSlots (
3866
3903
}
3867
3904
}
3868
3905
res . _normalized = true ;
3906
+ res . $stable = slots && slots . $stable ;
3869
3907
return res
3870
3908
}
3871
3909
@@ -4144,6 +4182,31 @@ function bindObjectListeners (data, value) {
4144
4182
4145
4183
/* */
4146
4184
4185
+ function bindDynamicKeys ( baseObj , values ) {
4186
+ for ( var i = 0 ; i < values . length ; i += 2 ) {
4187
+ var key = values [ i ] ;
4188
+ if ( typeof key === 'string' && key ) {
4189
+ baseObj [ values [ i ] ] = values [ i + 1 ] ;
4190
+ } else if ( process . env . NODE_ENV !== 'production' && key !== '' && key !== null ) {
4191
+ // null is a speical value for explicitly removing a binding
4192
+ warn (
4193
+ ( "Invalid value for dynamic directive argument (expected string or null): " + key ) ,
4194
+ this
4195
+ ) ;
4196
+ }
4197
+ }
4198
+ return baseObj
4199
+ }
4200
+
4201
+ // helper to dynamically append modifier runtime markers to event names.
4202
+ // ensure only append when value is already string, otherwise it will be cast
4203
+ // to string and cause the type check to miss.
4204
+ function prependModifier ( value , symbol ) {
4205
+ return typeof value === 'string' ? symbol + value : value
4206
+ }
4207
+
4208
+ /* */
4209
+
4147
4210
function installRenderHelpers ( target ) {
4148
4211
target . _o = markOnce ;
4149
4212
target . _n = toNumber ;
@@ -4160,6 +4223,8 @@ function installRenderHelpers (target) {
4160
4223
target . _e = createEmptyVNode ;
4161
4224
target . _u = resolveScopedSlots ;
4162
4225
target . _g = bindObjectListeners ;
4226
+ target . _d = bindDynamicKeys ;
4227
+ target . _p = prependModifier ;
4163
4228
}
4164
4229
4165
4230
/* */
@@ -5265,7 +5330,7 @@ Object.defineProperty(Vue, 'FunctionalRenderContext', {
5265
5330
value : FunctionalRenderContext
5266
5331
} ) ;
5267
5332
5268
- Vue . version = '2.6.0-beta.1 ' ;
5333
+ Vue . version = '2.6.0-beta.2 ' ;
5269
5334
5270
5335
/* */
5271
5336
@@ -6409,6 +6474,7 @@ function _update (oldVnode, vnode) {
6409
6474
} else {
6410
6475
// existing directive, update
6411
6476
dir . oldValue = oldDir . value ;
6477
+ dir . oldArg = oldDir . arg ;
6412
6478
callHook$1 ( dir , 'update' , vnode , oldVnode ) ;
6413
6479
if ( dir . def && dir . def . componentUpdated ) {
6414
6480
dirsWithPostpatch . push ( dir ) ;
@@ -6686,17 +6752,17 @@ function add$1 (
6686
6752
capture ,
6687
6753
passive
6688
6754
) {
6689
- if ( isChrome ) {
6690
- // async edge case #6566: inner click event triggers patch, event handler
6691
- // attached to outer element during patch, and triggered again. This only
6692
- // happens in Chrome as it fires microtask ticks between event propagation.
6693
- // the solution is simple: we save the timestamp when a handler is attached,
6694
- // and the handler would only fire if the event passed to it was fired
6695
- // AFTER it was attached.
6696
- var now = performance . now ( ) ;
6755
+ // async edge case #6566: inner click event triggers patch, event handler
6756
+ // attached to outer element during patch, and triggered again. This
6757
+ // happens because browsers fire microtask ticks between event propagation.
6758
+ // the solution is simple: we save the timestamp when a handler is attached,
6759
+ // and the handler would only fire if the event passed to it was fired
6760
+ // AFTER it was attached.
6761
+ if ( isUsingMicroTask ) {
6762
+ var attachedTimestamp = currentFlushTimestamp ;
6697
6763
var original = handler ;
6698
6764
handler = original . _wrapper = function ( e ) {
6699
- if ( e . timeStamp >= now ) {
6765
+ if ( e . timeStamp >= attachedTimestamp ) {
6700
6766
return original . apply ( this , arguments )
6701
6767
}
6702
6768
} ;
@@ -6777,14 +6843,11 @@ function updateDOMProps (oldVnode, vnode) {
6777
6843
}
6778
6844
}
6779
6845
6780
- // #4521: if a click event triggers update before the change event is
6781
- // dispatched on a checkbox/radio input, the input's checked state will
6782
- // be reset and fail to trigger another update.
6783
- // The root cause here is that browsers may fire microtasks in between click/change.
6784
- // In Chrome / Firefox, click event fires before change, thus having this problem.
6785
- // In Safari / Edge, the order is opposite.
6786
- // Note: in Edge, if you click too fast, only the click event would fire twice.
6787
- if ( key === 'checked' && ! isNotInFocusAndDirty ( elm , cur ) ) {
6846
+ // skip the update if old and new VDOM state is the same.
6847
+ // the only exception is `value` where the DOM value may be temporarily
6848
+ // out of sync with VDOM state due to focus, composition and modifiers.
6849
+ // This also covers #4521 by skipping the unnecesarry `checked` update.
6850
+ if ( key !== 'value' && cur === oldProps [ key ] ) {
6788
6851
continue
6789
6852
}
6790
6853
0 commit comments