2016-04-27 01:29:27 +08:00
/ * !
2016-08-21 02:04:54 +08:00
* Vue . js v2 . 0.0 - rc . 3
2016-04-27 01:29:27 +08:00
* ( c ) 2014 - 2016 Evan You
* Released under the MIT License .
* /
( function ( global , factory ) {
typeof exports === 'object' && typeof module !== 'undefined' ? module . exports = factory ( ) :
typeof define === 'function' && define . amd ? define ( factory ) :
( global . Vue = factory ( ) ) ;
} ( this , function ( ) { 'use strict' ;
/ * *
* Convert a value to a string that is actually rendered .
* /
2016-06-28 10:25:12 +08:00
function _toString ( val ) {
2016-04-27 01:29:27 +08:00
return val == null ? '' : typeof val === 'object' ? JSON . stringify ( val , null , 2 ) : String ( val ) ;
}
2016-06-28 10:25:12 +08:00
/ * *
* Convert a input value to a number for persistence .
* If the conversion fails , return original string .
* /
function toNumber ( val ) {
var n = parseFloat ( val , 10 ) ;
return n || n === 0 ? n : val ;
}
2016-04-27 01:29:27 +08:00
/ * *
* Make a map and return a function for checking if a key
* is in that map .
* /
function makeMap ( str , expectsLowerCase ) {
var map = Object . create ( null ) ;
var list = str . split ( ',' ) ;
for ( var i = 0 ; i < list . length ; i ++ ) {
map [ list [ i ] ] = true ;
}
return expectsLowerCase ? function ( val ) {
return map [ val . toLowerCase ( ) ] ;
} : function ( val ) {
return map [ val ] ;
} ;
}
/ * *
* Check if a tag is a built - in tag .
* /
2016-07-17 13:53:44 +08:00
var isBuiltInTag = makeMap ( 'slot,component' , true ) ;
2016-04-27 01:29:27 +08:00
/ * *
* Remove an item from an array
* /
function remove ( arr , item ) {
if ( arr . length ) {
var index = arr . indexOf ( item ) ;
if ( index > - 1 ) {
return arr . splice ( index , 1 ) ;
}
}
}
/ * *
* Check whether the object has the property .
* /
var hasOwnProperty = Object . prototype . hasOwnProperty ;
function hasOwn ( obj , key ) {
return hasOwnProperty . call ( obj , key ) ;
}
/ * *
* Check if value is primitive
* /
function isPrimitive ( value ) {
return typeof value === 'string' || typeof value === 'number' ;
}
/ * *
* Create a cached version of a pure function .
* /
function cached ( fn ) {
var cache = Object . create ( null ) ;
return function cachedFn ( str ) {
var hit = cache [ str ] ;
return hit || ( cache [ str ] = fn ( str ) ) ;
} ;
}
/ * *
* Camelize a hyphen - delmited string .
* /
var camelizeRE = /-(\w)/g ;
var camelize = cached ( function ( str ) {
2016-06-08 09:53:43 +08:00
return str . replace ( camelizeRE , function ( _ , c ) {
return c ? c . toUpperCase ( ) : '' ;
} ) ;
2016-04-27 01:29:27 +08:00
} ) ;
2016-06-08 09:53:43 +08:00
/ * *
* Capitalize a string .
* /
var capitalize = cached ( function ( str ) {
return str . charAt ( 0 ) . toUpperCase ( ) + str . slice ( 1 ) ;
} ) ;
2016-04-27 01:29:27 +08:00
/ * *
* Hyphenate a camelCase string .
* /
2016-07-08 05:53:22 +08:00
var hyphenateRE = /([^-])([A-Z])/g ;
2016-04-27 01:29:27 +08:00
var hyphenate = cached ( function ( str ) {
2016-07-08 05:53:22 +08:00
return str . replace ( hyphenateRE , '$1-$2' ) . replace ( hyphenateRE , '$1-$2' ) . toLowerCase ( ) ;
2016-04-27 01:29:27 +08:00
} ) ;
/ * *
* Simple bind , faster than native
* /
function bind ( fn , ctx ) {
2016-07-17 13:53:44 +08:00
function boundFn ( a ) {
2016-04-27 01:29:27 +08:00
var l = arguments . length ;
return l ? l > 1 ? fn . apply ( ctx , arguments ) : fn . call ( ctx , a ) : fn . call ( ctx ) ;
2016-07-17 13:53:44 +08:00
}
// record original fn length
boundFn . _length = fn . length ;
return boundFn ;
2016-04-27 01:29:27 +08:00
}
/ * *
* Convert an Array - like object to a real Array .
* /
function toArray ( list , start ) {
start = start || 0 ;
var i = list . length - start ;
var ret = new Array ( i ) ;
while ( i -- ) {
ret [ i ] = list [ i + start ] ;
}
return ret ;
}
/ * *
* Mix properties into target object .
* /
2016-06-08 09:53:43 +08:00
function extend ( to , _from ) {
for ( var _key in _from ) {
to [ _key ] = _from [ _key ] ;
2016-04-27 01:29:27 +08:00
}
return to ;
}
/ * *
* Quick object check - this is primarily used to tell
* Objects from primitive values when we know the value
* is a JSON - compliant type .
* /
function isObject ( obj ) {
return obj !== null && typeof obj === 'object' ;
}
/ * *
* Strict object type check . Only returns true
* for plain JavaScript objects .
* /
var toString = Object . prototype . toString ;
var OBJECT _STRING = '[object Object]' ;
function isPlainObject ( obj ) {
return toString . call ( obj ) === OBJECT _STRING ;
}
/ * *
2016-06-08 09:53:43 +08:00
* Merge an Array of Objects into a single Object .
* /
function toObject ( arr ) {
var res = arr [ 0 ] || { } ;
for ( var i = 1 ; i < arr . length ; i ++ ) {
if ( arr [ i ] ) {
extend ( res , arr [ i ] ) ;
}
}
return res ;
}
/ * *
* Perform no operation .
2016-04-27 01:29:27 +08:00
* /
2016-06-08 09:53:43 +08:00
function noop ( ) { }
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Always return false .
* /
var no = function no ( ) {
return false ;
} ;
2016-04-27 01:29:27 +08:00
/ * *
2016-06-08 09:53:43 +08:00
* Generate a static keys string from compiler modules .
2016-04-27 01:29:27 +08:00
* /
2016-06-08 09:53:43 +08:00
function genStaticKeys ( modules ) {
return modules . reduce ( function ( keys , m ) {
return keys . concat ( m . staticKeys || [ ] ) ;
} , [ ] ) . join ( ',' ) ;
}
var config = {
/ * *
* Option merge strategies ( used in core / util / options )
* /
optionMergeStrategies : Object . create ( null ) ,
/ * *
* Whether to suppress warnings .
* /
silent : false ,
2016-06-23 03:33:53 +08:00
/ * *
* Whether to enable devtools
* /
devtools : "development" !== 'production' ,
2016-06-08 09:53:43 +08:00
/ * *
* Error handler for watcher errors
* /
errorHandler : null ,
2016-06-17 01:00:55 +08:00
/ * *
* Ignore certain custom elements
* /
ignoredElements : null ,
2016-06-23 03:33:53 +08:00
/ * *
* Custom user key aliases for v - on
* /
keyCodes : Object . create ( null ) ,
2016-06-08 09:53:43 +08:00
/ * *
* Check if a tag is reserved so that it cannot be registered as a
* component . This is platform - dependent and may be overwritten .
* /
isReservedTag : no ,
/ * *
* Check if a tag is an unknown element .
* Platform - dependent .
* /
isUnknownElement : no ,
2016-06-28 10:25:12 +08:00
/ * *
* Get the namespace of an element
* /
getTagNamespace : noop ,
2016-06-08 09:53:43 +08:00
/ * *
* Check if an attribute must be bound using property , e . g . value
* Platform - dependent .
* /
mustUseProp : no ,
/ * *
* List of asset types that a component can own .
* /
2016-07-17 13:53:44 +08:00
_assetTypes : [ 'component' , 'directive' , 'filter' ] ,
2016-06-08 09:53:43 +08:00
/ * *
* List of lifecycle hooks .
* /
2016-06-28 10:25:12 +08:00
_lifecycleHooks : [ 'beforeCreate' , 'created' , 'beforeMount' , 'mounted' , 'beforeUpdate' , 'updated' , 'beforeDestroy' , 'destroyed' , 'activated' , 'deactivated' ] ,
2016-06-08 09:53:43 +08:00
/ * *
* Max circular updates allowed in a scheduler flush cycle .
* /
_maxUpdateCount : 100 ,
/ * *
* Server rendering ?
* /
2016-06-28 10:25:12 +08:00
_isServer : "client" === 'server'
2016-06-08 09:53:43 +08:00
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Check if a string starts with $ or _
* /
2016-04-27 01:29:27 +08:00
function isReserved ( str ) {
var c = ( str + '' ) . charCodeAt ( 0 ) ;
return c === 0x24 || c === 0x5F ;
}
/ * *
* Define a property .
* /
function def ( obj , key , val , enumerable ) {
Object . defineProperty ( obj , key , {
value : val ,
enumerable : ! ! enumerable ,
writable : true ,
configurable : true
} ) ;
}
/ * *
* Parse simple path .
* /
2016-07-08 05:53:22 +08:00
var bailRE = /[^\w\.\$]/ ;
2016-04-27 01:29:27 +08:00
function parsePath ( path ) {
if ( bailRE . test ( path ) ) {
return ;
} else {
2016-06-08 09:53:43 +08:00
var _ret = function ( ) {
var segments = path . split ( '.' ) ;
return {
v : function v ( obj ) {
for ( var i = 0 ; i < segments . length ; i ++ ) {
if ( ! obj ) return ;
obj = obj [ segments [ i ] ] ;
}
return obj ;
}
} ;
} ( ) ;
if ( typeof _ret === "object" ) return _ret . v ;
2016-04-27 01:29:27 +08:00
}
}
/* global MutationObserver */
// can we use __proto__?
var hasProto = '__proto__' in { } ;
// Browser environment sniffing
var inBrowser = typeof window !== 'undefined' && Object . prototype . toString . call ( window ) !== '[object Object]' ;
// detect devtools
var devtools = inBrowser && window . _ _VUE _DEVTOOLS _GLOBAL _HOOK _ _ ;
// UA sniffing for working around browser-specific quirks
var UA = inBrowser && window . navigator . userAgent . toLowerCase ( ) ;
var isIos = UA && /(iphone|ipad|ipod|ios)/i . test ( UA ) ;
2016-06-08 09:53:43 +08:00
var iosVersionMatch = UA && isIos && UA . match ( /os ([\d_]+)/ ) ;
var iosVersion = iosVersionMatch && iosVersionMatch [ 1 ] . split ( '_' ) ;
// MutationObserver is unreliable in iOS 9.3 UIWebView
// detecting it by checking presence of IndexedDB
// ref #3027
var hasMutationObserverBug = iosVersion && Number ( iosVersion [ 0 ] ) >= 9 && Number ( iosVersion [ 1 ] ) >= 3 && ! window . indexedDB ;
2016-04-27 01:29:27 +08:00
/ * *
* Defer a task to execute it asynchronously . Ideally this
* should be executed as a microtask , so we leverage
* MutationObserver if it ' s available , and fallback to
* setTimeout ( 0 ) .
*
* @ param { Function } cb
* @ param { Object } ctx
* /
var nextTick = function ( ) {
var callbacks = [ ] ;
var pending = false ;
2016-06-08 09:53:43 +08:00
var timerFunc = void 0 ;
2016-04-27 01:29:27 +08:00
function nextTickHandler ( ) {
pending = false ;
var copies = callbacks . slice ( 0 ) ;
callbacks = [ ] ;
for ( var i = 0 ; i < copies . length ; i ++ ) {
copies [ i ] ( ) ;
}
}
2016-06-08 09:53:43 +08:00
/* istanbul ignore else */
if ( typeof MutationObserver !== 'undefined' && ! hasMutationObserverBug ) {
2016-08-21 02:04:54 +08:00
var counter = 1 ;
var observer = new MutationObserver ( nextTickHandler ) ;
var textNode = document . createTextNode ( String ( counter ) ) ;
observer . observe ( textNode , {
characterData : true
} ) ;
timerFunc = function timerFunc ( ) {
counter = ( counter + 1 ) % 2 ;
textNode . data = String ( counter ) ;
} ;
2016-04-27 01:29:27 +08:00
} else {
// webpack attempts to inject a shim for setImmediate
// if it is used as a global, so we have to work around that to
// avoid bundling unnecessary code.
var context = inBrowser ? window : typeof global !== 'undefined' ? global : { } ;
timerFunc = context . setImmediate || setTimeout ;
}
return function ( cb , ctx ) {
var func = ctx ? function ( ) {
cb . call ( ctx ) ;
} : cb ;
callbacks . push ( func ) ;
if ( pending ) return ;
pending = true ;
timerFunc ( nextTickHandler , 0 ) ;
} ;
} ( ) ;
2016-06-28 10:25:12 +08:00
var _Set = void 0 ;
2016-04-27 01:29:27 +08:00
/* istanbul ignore if */
2016-06-14 07:36:46 +08:00
if ( typeof Set !== 'undefined' && /native code/ . test ( Set . toString ( ) ) ) {
2016-04-27 01:29:27 +08:00
// use native Set when available.
2016-06-28 10:25:12 +08:00
_Set = Set ;
2016-04-27 01:29:27 +08:00
} else {
// a non-standard Set polyfill that only works with primitive keys.
2016-06-28 10:25:12 +08:00
_Set = function ( ) {
2016-06-08 09:53:43 +08:00
function Set ( ) {
this . set = Object . create ( null ) ;
}
Set . prototype . has = function has ( key ) {
return this . set [ key ] !== undefined ;
} ;
Set . prototype . add = function add ( key ) {
this . set [ key ] = 1 ;
} ;
Set . prototype . clear = function clear ( ) {
this . set = Object . create ( null ) ;
} ;
return Set ;
} ( ) ;
2016-04-27 01:29:27 +08:00
}
var hasProxy = void 0 ;
var proxyHandlers = void 0 ;
var initProxy = void 0 ;
if ( "development" !== 'production' ) {
( function ( ) {
2016-08-21 02:04:54 +08:00
var allowedGlobals = makeMap ( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify
2016-06-11 07:23:32 +08:00
) ;
2016-04-27 01:29:27 +08:00
hasProxy = typeof Proxy !== 'undefined' && Proxy . toString ( ) . match ( /native code/ ) ;
proxyHandlers = {
has : function has ( target , key ) {
var has = key in target ;
2016-08-21 02:04:54 +08:00
var isAllowed = allowedGlobals ( key ) || key . charAt ( 0 ) === '_' ;
if ( ! has && ! isAllowed ) {
2016-08-16 11:39:07 +08:00
warn ( 'Property or method "' + key + '" is not defined on the instance but ' + 'referenced during render. Make sure to declare reactive data ' + 'properties in the data option.' , target ) ;
2016-04-27 01:29:27 +08:00
}
2016-08-21 02:04:54 +08:00
return has || ! isAllowed ;
2016-04-27 01:29:27 +08:00
}
} ;
initProxy = function initProxy ( vm ) {
if ( hasProxy ) {
vm . _renderProxy = new Proxy ( vm , proxyHandlers ) ;
} else {
vm . _renderProxy = vm ;
}
} ;
} ) ( ) ;
}
var uid$2 = 0 ;
/ * *
* A dep is an observable that can have multiple
* directives subscribing to it .
* /
2016-06-08 09:53:43 +08:00
var Dep = function ( ) {
function Dep ( ) {
this . id = uid$2 ++ ;
this . subs = [ ] ;
}
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Dep . prototype . addSub = function addSub ( sub ) {
this . subs . push ( sub ) ;
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Dep . prototype . removeSub = function removeSub ( sub ) {
remove ( this . subs , sub ) ;
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Dep . prototype . depend = function depend ( ) {
if ( Dep . target ) {
Dep . target . addDep ( this ) ;
}
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Dep . prototype . notify = function notify ( ) {
// stablize the subscriber list first
var subs = this . subs . slice ( ) ;
for ( var i = 0 , l = subs . length ; i < l ; i ++ ) {
subs [ i ] . update ( ) ;
}
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
return Dep ;
} ( ) ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Dep . target = null ;
2016-06-23 03:33:53 +08:00
var targetStack = [ ] ;
function pushTarget ( _target ) {
if ( Dep . target ) targetStack . push ( Dep . target ) ;
Dep . target = _target ;
}
function popTarget ( ) {
Dep . target = targetStack . pop ( ) ;
}
2016-04-27 01:29:27 +08:00
var queue = [ ] ;
var has = { } ;
var circular = { } ;
var waiting = false ;
2016-07-17 13:53:44 +08:00
var flushing = false ;
var index = 0 ;
2016-04-27 01:29:27 +08:00
/ * *
2016-06-08 09:53:43 +08:00
* Reset the scheduler ' s state .
2016-04-27 01:29:27 +08:00
* /
2016-06-08 09:53:43 +08:00
function resetSchedulerState ( ) {
queue . length = 0 ;
2016-04-27 01:29:27 +08:00
has = { } ;
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
circular = { } ;
}
2016-07-17 13:53:44 +08:00
waiting = flushing = false ;
2016-04-27 01:29:27 +08:00
}
/ * *
* Flush both queues and run the watchers .
* /
2016-06-08 09:53:43 +08:00
function flushSchedulerQueue ( ) {
2016-07-17 13:53:44 +08:00
flushing = true ;
2016-04-27 01:29:27 +08:00
2016-07-26 10:07:26 +08:00
// Sort queue before flush.
// This ensures that:
// 1. Components are updated from parent to child. (because parent is always
// created before the child)
// 2. A component's user watchers are run before its render watcher (because
// user watchers are created before the render watcher)
// 3. If a component is destroyed during a parent component's watcher run,
// its watchers can be skipped.
queue . sort ( function ( a , b ) {
return a . id - b . id ;
} ) ;
2016-04-27 01:29:27 +08:00
// do not cache length because more watchers might be pushed
// as we run existing watchers
2016-07-17 13:53:44 +08:00
for ( index = 0 ; index < queue . length ; index ++ ) {
var watcher = queue [ index ] ;
2016-04-27 01:29:27 +08:00
var id = watcher . id ;
has [ id ] = null ;
watcher . run ( ) ;
// in dev build, check and stop circular updates.
if ( "development" !== 'production' && has [ id ] != null ) {
circular [ id ] = ( circular [ id ] || 0 ) + 1 ;
if ( circular [ id ] > config . _maxUpdateCount ) {
2016-07-17 13:53:44 +08:00
warn ( 'You may have an infinite update loop ' + ( watcher . user ? 'in watcher with expression "' + watcher . expression + '"' : 'in a component render function.' ) , watcher . vm ) ;
2016-04-27 01:29:27 +08:00
break ;
}
}
}
2016-07-26 10:07:26 +08:00
// devtool hook
/* istanbul ignore if */
if ( devtools && config . devtools ) {
devtools . emit ( 'flush' ) ;
}
resetSchedulerState ( ) ;
2016-04-27 01:29:27 +08:00
}
/ * *
* Push a watcher into the watcher queue .
* Jobs with duplicate IDs will be skipped unless it ' s
* pushed when the queue is being flushed .
* /
2016-06-08 09:53:43 +08:00
function queueWatcher ( watcher ) {
2016-04-27 01:29:27 +08:00
var id = watcher . id ;
if ( has [ id ] == null ) {
2016-06-08 09:53:43 +08:00
has [ id ] = true ;
2016-07-17 13:53:44 +08:00
if ( ! flushing ) {
2016-07-26 10:07:26 +08:00
queue . push ( watcher ) ;
2016-07-17 13:53:44 +08:00
} else {
2016-07-26 10:07:26 +08:00
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
var i = queue . length - 1 ;
while ( i >= 0 && queue [ i ] . id > watcher . id ) {
2016-07-17 13:53:44 +08:00
i -- ;
}
2016-07-26 10:07:26 +08:00
queue . splice ( Math . max ( i , index ) + 1 , 0 , watcher ) ;
2016-07-17 13:53:44 +08:00
}
2016-06-08 09:53:43 +08:00
// queue the flush
if ( ! waiting ) {
waiting = true ;
nextTick ( flushSchedulerQueue ) ;
2016-04-27 01:29:27 +08:00
}
}
}
var uid$1 = 0 ;
/ * *
* A watcher parses an expression , collects dependencies ,
* and fires callback when the expression value changes .
* This is used for both the $watch ( ) api and directives .
* /
2016-06-08 09:53:43 +08:00
var Watcher = function ( ) {
function Watcher ( vm , expOrFn , cb ) {
var options = arguments . length <= 3 || arguments [ 3 ] === undefined ? { } : arguments [ 3 ] ;
this . vm = vm ;
vm . _watchers . push ( this ) ;
// options
this . deep = ! ! options . deep ;
this . user = ! ! options . user ;
this . lazy = ! ! options . lazy ;
2016-06-23 03:33:53 +08:00
this . sync = ! ! options . sync ;
2016-06-08 09:53:43 +08:00
this . expression = expOrFn . toString ( ) ;
this . cb = cb ;
this . id = ++ uid$1 ; // uid for batching
this . active = true ;
this . dirty = this . lazy ; // for lazy watchers
this . deps = [ ] ;
this . newDeps = [ ] ;
2016-06-28 10:25:12 +08:00
this . depIds = new _Set ( ) ;
this . newDepIds = new _Set ( ) ;
2016-06-08 09:53:43 +08:00
// parse expression for getter
if ( typeof expOrFn === 'function' ) {
this . getter = expOrFn ;
} else {
this . getter = parsePath ( expOrFn ) ;
if ( ! this . getter ) {
this . getter = function ( ) { } ;
2016-07-08 05:53:22 +08:00
"development" !== 'production' && warn ( 'Failed watching path: "' + expOrFn + '" ' + 'Watcher only accepts simple dot-delimited paths. ' + 'For full control, use a function instead.' , vm ) ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
this . value = this . lazy ? undefined : this . get ( ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
/ * *
* Evaluate the getter , and re - collect dependencies .
* /
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Watcher . prototype . get = function get ( ) {
2016-06-23 03:33:53 +08:00
pushTarget ( this ) ;
2016-07-17 13:53:44 +08:00
var value = this . getter . call ( this . vm , this . vm ) ;
2016-06-08 09:53:43 +08:00
// "touch" every property so they are all tracked as
// dependencies for deep watching
if ( this . deep ) {
traverse ( value ) ;
}
2016-06-23 03:33:53 +08:00
popTarget ( ) ;
this . cleanupDeps ( ) ;
2016-06-08 09:53:43 +08:00
return value ;
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Add a dependency to this directive .
* /
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Watcher . prototype . addDep = function addDep ( dep ) {
var id = dep . id ;
if ( ! this . newDepIds . has ( id ) ) {
this . newDepIds . add ( id ) ;
this . newDeps . push ( dep ) ;
if ( ! this . depIds . has ( id ) ) {
dep . addSub ( this ) ;
}
}
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Clean up for dependency collection .
* /
2016-04-27 01:29:27 +08:00
2016-06-23 03:33:53 +08:00
Watcher . prototype . cleanupDeps = function cleanupDeps ( ) {
2016-06-08 09:53:43 +08:00
var i = this . deps . length ;
while ( i -- ) {
var dep = this . deps [ i ] ;
if ( ! this . newDepIds . has ( dep . id ) ) {
dep . removeSub ( this ) ;
}
}
var tmp = this . depIds ;
this . depIds = this . newDepIds ;
this . newDepIds = tmp ;
this . newDepIds . clear ( ) ;
tmp = this . deps ;
this . deps = this . newDeps ;
this . newDeps = tmp ;
this . newDeps . length = 0 ;
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Subscriber interface .
* Will be called when a dependency changes .
* /
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Watcher . prototype . update = function update ( ) {
2016-06-23 03:33:53 +08:00
/* istanbul ignore else */
2016-06-08 09:53:43 +08:00
if ( this . lazy ) {
this . dirty = true ;
2016-06-23 03:33:53 +08:00
} else if ( this . sync ) {
this . run ( ) ;
2016-06-08 09:53:43 +08:00
} else {
queueWatcher ( this ) ;
}
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Scheduler job interface .
* Will be called by the scheduler .
* /
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Watcher . prototype . run = function run ( ) {
if ( this . active ) {
var value = this . get ( ) ;
if ( value !== this . value ||
// Deep watchers and watchers on Object/Arrays should fire even
// when the value is the same, because the value may
// have mutated.
isObject ( value ) || this . deep ) {
// set new value
var oldValue = this . value ;
this . value = value ;
2016-06-28 10:25:12 +08:00
if ( this . user ) {
try {
this . cb . call ( this . vm , value , oldValue ) ;
} catch ( e ) {
"development" !== 'production' && warn ( 'Error in watcher "' + this . expression + '"' , this . vm ) ;
/* istanbul ignore else */
if ( config . errorHandler ) {
config . errorHandler . call ( null , e , this . vm ) ;
} else {
throw e ;
}
}
} else {
this . cb . call ( this . vm , value , oldValue ) ;
}
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} ;
/ * *
* Evaluate the value of the watcher .
* This only gets called for lazy watchers .
* /
Watcher . prototype . evaluate = function evaluate ( ) {
this . value = this . get ( ) ;
this . dirty = false ;
} ;
/ * *
* Depend on all deps collected by this watcher .
* /
Watcher . prototype . depend = function depend ( ) {
2016-04-27 01:29:27 +08:00
var i = this . deps . length ;
while ( i -- ) {
2016-06-08 09:53:43 +08:00
this . deps [ i ] . depend ( ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Remove self from all dependencies ' subcriber list .
* /
Watcher . prototype . teardown = function teardown ( ) {
if ( this . active ) {
// remove self from vm's watcher list
// this is a somewhat expensive operation so we skip it
// if the vm is being destroyed or is performing a v-for
// re-render (the watcher list is then filtered by v-for).
if ( ! this . vm . _isBeingDestroyed && ! this . vm . _vForRemoving ) {
remove ( this . vm . _watchers , this ) ;
}
var i = this . deps . length ;
while ( i -- ) {
this . deps [ i ] . removeSub ( this ) ;
}
this . active = false ;
}
} ;
return Watcher ;
} ( ) ;
2016-04-27 01:29:27 +08:00
2016-06-28 10:25:12 +08:00
var seenObjects = new _Set ( ) ;
2016-04-27 01:29:27 +08:00
function traverse ( val , seen ) {
var i = void 0 ,
2016-06-08 09:53:43 +08:00
keys = void 0 ;
2016-04-27 01:29:27 +08:00
if ( ! seen ) {
seen = seenObjects ;
seen . clear ( ) ;
}
2016-06-08 09:53:43 +08:00
var isA = Array . isArray ( val ) ;
var isO = isObject ( val ) ;
2016-06-28 10:25:12 +08:00
if ( ( isA || isO ) && Object . isExtensible ( val ) ) {
2016-04-27 01:29:27 +08:00
if ( val . _ _ob _ _ ) {
var depId = val . _ _ob _ _ . dep . id ;
if ( seen . has ( depId ) ) {
return ;
} else {
seen . add ( depId ) ;
}
}
if ( isA ) {
i = val . length ;
while ( i -- ) {
traverse ( val [ i ] , seen ) ;
}
} else if ( isO ) {
keys = Object . keys ( val ) ;
i = keys . length ;
while ( i -- ) {
traverse ( val [ keys [ i ] ] , seen ) ;
}
}
}
}
var arrayProto = Array . prototype ;
var arrayMethods = Object . create ( arrayProto )
/ * *
* Intercept mutating methods and emit events
* /
; [ 'push' , 'pop' , 'shift' , 'unshift' , 'splice' , 'sort' , 'reverse' ] . forEach ( function ( method ) {
// cache original method
var original = arrayProto [ method ] ;
def ( arrayMethods , method , function mutator ( ) {
// avoid leaking arguments:
// http://jsperf.com/closure-with-arguments
var i = arguments . length ;
var args = new Array ( i ) ;
while ( i -- ) {
args [ i ] = arguments [ i ] ;
}
var result = original . apply ( this , args ) ;
var ob = this . _ _ob _ _ ;
2016-06-08 09:53:43 +08:00
var inserted = void 0 ;
2016-04-27 01:29:27 +08:00
switch ( method ) {
case 'push' :
inserted = args ;
break ;
case 'unshift' :
inserted = args ;
break ;
case 'splice' :
inserted = args . slice ( 2 ) ;
break ;
}
if ( inserted ) ob . observeArray ( inserted ) ;
// notify change
ob . dep . notify ( ) ;
return result ;
} ) ;
} ) ;
var arrayKeys = Object . getOwnPropertyNames ( arrayMethods ) ;
/ * *
* By default , when a reactive property is set , the new value is
* also converted to become reactive . However when passing down props ,
* we don ' t want to force conversion because the value may be a nested value
* under a frozen data structure . Converting it would defeat the optimization .
* /
var observerState = {
2016-06-08 09:53:43 +08:00
shouldConvert : true ,
isSettingProps : false
2016-04-27 01:29:27 +08:00
} ;
/ * *
* Observer class that are attached to each observed
* object . Once attached , the observer converts target
* object ' s property keys into getter / setters that
* collect dependencies and dispatches updates .
* /
2016-06-08 09:53:43 +08:00
var Observer = function ( ) {
// number of vms that has this object as root $data
function Observer ( value ) {
this . value = value ;
this . dep = new Dep ( ) ;
this . vmCount = 0 ;
def ( value , '__ob__' , this ) ;
if ( Array . isArray ( value ) ) {
var augment = hasProto ? protoAugment : copyAugment ;
augment ( value , arrayMethods , arrayKeys ) ;
this . observeArray ( value ) ;
} else {
this . walk ( value ) ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
/ * *
* Walk through each property and convert them into
* getter / setters . This method should only be called when
* value type is Object .
* /
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Observer . prototype . walk = function walk ( obj ) {
var val = this . value ;
for ( var key in obj ) {
defineReactive ( val , key , obj [ key ] ) ;
}
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
/ * *
* Observe a list of Array items .
* /
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
Observer . prototype . observeArray = function observeArray ( items ) {
for ( var i = 0 , l = items . length ; i < l ; i ++ ) {
observe ( items [ i ] ) ;
}
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
return Observer ;
} ( ) ;
2016-04-27 01:29:27 +08:00
// helpers
/ * *
* Augment an target Object or Array by intercepting
* the prototype chain using _ _proto _ _
* /
function protoAugment ( target , src ) {
/* eslint-disable no-proto */
target . _ _proto _ _ = src ;
/* eslint-enable no-proto */
}
/ * *
* Augment an target Object or Array by defining
* hidden properties .
*
2016-06-08 09:53:43 +08:00
* istanbul ignore next
2016-04-27 01:29:27 +08:00
* /
function copyAugment ( target , src , keys ) {
for ( var i = 0 , l = keys . length ; i < l ; i ++ ) {
var key = keys [ i ] ;
def ( target , key , src [ key ] ) ;
}
}
/ * *
* Attempt to create an observer instance for a value ,
* returns the new observer if successfully observed ,
* or the existing observer if the value already has one .
* /
2016-06-08 09:53:43 +08:00
function observe ( value ) {
2016-04-27 01:29:27 +08:00
if ( ! isObject ( value ) ) {
return ;
}
2016-06-08 09:53:43 +08:00
var ob = void 0 ;
2016-04-27 01:29:27 +08:00
if ( hasOwn ( value , '__ob__' ) && value . _ _ob _ _ instanceof Observer ) {
ob = value . _ _ob _ _ ;
2016-06-08 09:53:43 +08:00
} else if ( observerState . shouldConvert && ! config . _isServer && ( Array . isArray ( value ) || isPlainObject ( value ) ) && Object . isExtensible ( value ) && ! value . _isVue ) {
2016-04-27 01:29:27 +08:00
ob = new Observer ( value ) ;
}
return ob ;
}
/ * *
* Define a reactive property on an Object .
* /
2016-06-08 09:53:43 +08:00
function defineReactive ( obj , key , val , customSetter ) {
2016-04-27 01:29:27 +08:00
var dep = new Dep ( ) ;
var property = Object . getOwnPropertyDescriptor ( obj , key ) ;
if ( property && property . configurable === false ) {
return ;
}
// cater for pre-defined getter/setters
var getter = property && property . get ;
var setter = property && property . set ;
var childOb = observe ( val ) ;
Object . defineProperty ( obj , key , {
enumerable : true ,
configurable : true ,
get : function reactiveGetter ( ) {
var value = getter ? getter . call ( obj ) : val ;
if ( Dep . target ) {
dep . depend ( ) ;
if ( childOb ) {
childOb . dep . depend ( ) ;
}
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( value ) ) {
2016-04-27 01:29:27 +08:00
for ( var e , i = 0 , l = value . length ; i < l ; i ++ ) {
e = value [ i ] ;
e && e . _ _ob _ _ && e . _ _ob _ _ . dep . depend ( ) ;
}
}
}
return value ;
} ,
set : function reactiveSetter ( newVal ) {
var value = getter ? getter . call ( obj ) : val ;
if ( newVal === value ) {
return ;
}
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' && customSetter ) {
customSetter ( ) ;
}
2016-04-27 01:29:27 +08:00
if ( setter ) {
setter . call ( obj , newVal ) ;
} else {
val = newVal ;
}
childOb = observe ( newVal ) ;
dep . notify ( ) ;
}
} ) ;
}
/ * *
* Set a property on an object . Adds the new property and
* triggers change notification if the property doesn ' t
* already exist .
* /
function set ( obj , key , val ) {
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( obj ) ) {
obj . splice ( key , 1 , val ) ;
return val ;
2016-04-27 01:29:27 +08:00
}
if ( hasOwn ( obj , key ) ) {
obj [ key ] = val ;
return ;
}
2016-06-08 09:53:43 +08:00
var ob = obj . _ _ob _ _ ;
if ( obj . _isVue || ob && ob . vmCount ) {
"development" !== 'production' && warn ( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - delcare it upfront in the data option.' ) ;
2016-04-27 01:29:27 +08:00
return ;
}
if ( ! ob ) {
obj [ key ] = val ;
return ;
}
2016-06-08 09:53:43 +08:00
defineReactive ( ob . value , key , val ) ;
2016-04-27 01:29:27 +08:00
ob . dep . notify ( ) ;
return val ;
}
/ * *
* Delete a property and trigger change if necessary .
* /
function del ( obj , key ) {
2016-06-08 09:53:43 +08:00
var ob = obj . _ _ob _ _ ;
if ( obj . _isVue || ob && ob . vmCount ) {
"development" !== 'production' && warn ( 'Avoid deleting properties on a Vue instance or its root $data ' + '- just set it to null.' ) ;
return ;
}
2016-04-27 01:29:27 +08:00
if ( ! hasOwn ( obj , key ) ) {
return ;
}
delete obj [ key ] ;
if ( ! ob ) {
return ;
}
ob . dep . notify ( ) ;
}
function initState ( vm ) {
vm . _watchers = [ ] ;
initProps ( vm ) ;
initData ( vm ) ;
initComputed ( vm ) ;
initMethods ( vm ) ;
initWatch ( vm ) ;
}
function initProps ( vm ) {
var props = vm . $options . props ;
var propsData = vm . $options . propsData ;
if ( props ) {
2016-06-08 09:53:43 +08:00
var keys = vm . $options . _propKeys = Object . keys ( props ) ;
2016-04-27 01:29:27 +08:00
var isRoot = ! vm . $parent ;
// root instance props should be converted
observerState . shouldConvert = isRoot ;
2016-06-08 09:53:43 +08:00
var _loop = function _loop ( i ) {
2016-04-27 01:29:27 +08:00
var key = keys [ i ] ;
2016-06-08 09:53:43 +08:00
/* istanbul ignore else */
if ( "development" !== 'production' ) {
2016-07-08 05:53:22 +08:00
defineReactive ( vm , key , validateProp ( key , props , propsData , vm ) , function ( ) {
2016-06-08 09:53:43 +08:00
if ( vm . $parent && ! observerState . isSettingProps ) {
warn ( 'Avoid mutating a prop directly since the value will be ' + 'overwritten whenever the parent component re-renders. ' + 'Instead, use a data or computed property based on the prop\'s ' + ( 'value. Prop being mutated: "' + key + '"' ) , vm ) ;
}
} ) ;
} else { }
} ;
for ( var i = 0 ; i < keys . length ; i ++ ) {
_loop ( i ) ;
2016-04-27 01:29:27 +08:00
}
observerState . shouldConvert = true ;
}
}
function initData ( vm ) {
var data = vm . $options . data ;
2016-06-08 09:53:43 +08:00
data = vm . _data = typeof data === 'function' ? data . call ( vm ) : data || { } ;
2016-04-27 01:29:27 +08:00
if ( ! isPlainObject ( data ) ) {
data = { } ;
"development" !== 'production' && warn ( 'data functions should return an object.' , vm ) ;
}
// proxy data on instance
var keys = Object . keys ( data ) ;
2016-06-08 09:53:43 +08:00
var props = vm . $options . props ;
2016-04-27 01:29:27 +08:00
var i = keys . length ;
while ( i -- ) {
2016-06-08 09:53:43 +08:00
if ( props && hasOwn ( props , keys [ i ] ) ) {
"development" !== 'production' && warn ( 'The data property "' + keys [ i ] + '" is already declared as a prop. ' + 'Use prop default value instead.' , vm ) ;
} else {
proxy ( vm , keys [ i ] ) ;
}
2016-04-27 01:29:27 +08:00
}
// observe data
2016-06-08 09:53:43 +08:00
observe ( data ) ;
data . _ _ob _ _ && data . _ _ob _ _ . vmCount ++ ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
var computedSharedDefinition = {
enumerable : true ,
configurable : true ,
get : noop ,
set : noop
} ;
2016-04-27 01:29:27 +08:00
function initComputed ( vm ) {
var computed = vm . $options . computed ;
if ( computed ) {
2016-06-08 09:53:43 +08:00
for ( var _key in computed ) {
var userDef = computed [ _key ] ;
2016-04-27 01:29:27 +08:00
if ( typeof userDef === 'function' ) {
2016-06-08 09:53:43 +08:00
computedSharedDefinition . get = makeComputedGetter ( userDef , vm ) ;
computedSharedDefinition . set = noop ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
computedSharedDefinition . get = userDef . get ? userDef . cache !== false ? makeComputedGetter ( userDef . get , vm ) : bind ( userDef . get , vm ) : noop ;
computedSharedDefinition . set = userDef . set ? bind ( userDef . set , vm ) : noop ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
Object . defineProperty ( vm , _key , computedSharedDefinition ) ;
2016-04-27 01:29:27 +08:00
}
}
}
function makeComputedGetter ( getter , owner ) {
2016-06-08 09:53:43 +08:00
var watcher = new Watcher ( owner , getter , noop , {
2016-04-27 01:29:27 +08:00
lazy : true
} ) ;
return function computedGetter ( ) {
if ( watcher . dirty ) {
watcher . evaluate ( ) ;
}
if ( Dep . target ) {
watcher . depend ( ) ;
}
return watcher . value ;
} ;
}
function initMethods ( vm ) {
var methods = vm . $options . methods ;
if ( methods ) {
2016-06-08 09:53:43 +08:00
for ( var _key2 in methods ) {
vm [ _key2 ] = bind ( methods [ _key2 ] , vm ) ;
2016-04-27 01:29:27 +08:00
}
}
}
function initWatch ( vm ) {
var watch = vm . $options . watch ;
if ( watch ) {
2016-06-08 09:53:43 +08:00
for ( var _key3 in watch ) {
var handler = watch [ _key3 ] ;
if ( Array . isArray ( handler ) ) {
2016-04-27 01:29:27 +08:00
for ( var i = 0 ; i < handler . length ; i ++ ) {
2016-06-08 09:53:43 +08:00
createWatcher ( vm , _key3 , handler [ i ] ) ;
2016-04-27 01:29:27 +08:00
}
} else {
2016-06-08 09:53:43 +08:00
createWatcher ( vm , _key3 , handler ) ;
2016-04-27 01:29:27 +08:00
}
}
}
}
function createWatcher ( vm , key , handler ) {
var options = void 0 ;
if ( isPlainObject ( handler ) ) {
options = handler ;
handler = handler . handler ;
}
if ( typeof handler === 'string' ) {
handler = vm [ handler ] ;
}
vm . $watch ( key , handler , options ) ;
}
function stateMixin ( Vue ) {
2016-06-08 09:53:43 +08:00
// flow somehow has problems with directly declared definition object
// when using Object.defineProperty, so we have to procedurally build up
// the object here.
var dataDef = { } ;
dataDef . get = function ( ) {
return this . _data ;
} ;
2016-06-18 02:22:51 +08:00
if ( "development" !== 'production' ) {
dataDef . set = function ( newData ) {
warn ( 'Avoid replacing instance root $data. ' + 'Use nested data properties instead.' , this ) ;
} ;
}
2016-06-08 09:53:43 +08:00
Object . defineProperty ( Vue . prototype , '$data' , dataDef ) ;
2016-04-27 01:29:27 +08:00
2016-08-21 02:04:54 +08:00
Vue . prototype . $set = set ;
Vue . prototype . $delete = del ;
2016-06-08 09:53:43 +08:00
Vue . prototype . $watch = function ( expOrFn , cb , options ) {
var vm = this ;
2016-04-27 01:29:27 +08:00
options = options || { } ;
options . user = true ;
2016-06-08 09:53:43 +08:00
var watcher = new Watcher ( vm , expOrFn , cb , options ) ;
2016-04-27 01:29:27 +08:00
if ( options . immediate ) {
2016-06-08 09:53:43 +08:00
cb . call ( vm , watcher . value ) ;
2016-04-27 01:29:27 +08:00
}
return function unwatchFn ( ) {
watcher . teardown ( ) ;
} ;
} ;
}
2016-06-18 02:22:51 +08:00
function proxy ( vm , key ) {
if ( ! isReserved ( key ) ) {
Object . defineProperty ( vm , key , {
configurable : true ,
enumerable : true ,
get : function proxyGetter ( ) {
return vm . _data [ key ] ;
} ,
set : function proxySetter ( val ) {
vm . _data [ key ] = val ;
}
} ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-08-06 06:14:22 +08:00
var VNode = // hoisted static node
// compoennt placeholder node
// rendered in this component's scope
function VNode ( tag , data , children , text , elm , ns , context , componentOptions ) {
2016-06-28 10:25:12 +08:00
this . tag = tag ;
this . data = data ;
this . children = children ;
this . text = text ;
this . elm = elm ;
this . ns = ns ;
this . context = context ;
this . key = data && data . key ;
this . componentOptions = componentOptions ;
this . child = undefined ;
this . parent = undefined ;
this . raw = false ;
2016-07-27 12:25:41 +08:00
this . isStatic = false ;
2016-08-06 06:14:22 +08:00
this . isRootInsert = true ;
this . isComment = false ;
2016-06-28 10:25:12 +08:00
// apply construct hook.
// this is applied during render, before patch happens.
// unlike other hooks, this is applied on both client and server.
var constructHook = data && data . hook && data . hook . construct ;
if ( constructHook ) {
constructHook ( this ) ;
}
2016-08-06 06:14:22 +08:00
} // necessary for enter transition check
// contains raw HTML
// component instance
;
2016-06-08 09:53:43 +08:00
2016-06-11 07:23:32 +08:00
var emptyVNode = function emptyVNode ( ) {
2016-08-06 06:14:22 +08:00
var node = new VNode ( ) ;
node . text = '' ;
node . isComment = true ;
return node ;
2016-06-11 07:23:32 +08:00
} ;
2016-06-08 09:53:43 +08:00
2016-06-28 10:25:12 +08:00
function normalizeChildren ( children , ns ) {
if ( isPrimitive ( children ) ) {
return [ createTextVNode ( children ) ] ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( children ) ) {
2016-04-27 01:29:27 +08:00
var res = [ ] ;
for ( var i = 0 , l = children . length ; i < l ; i ++ ) {
var c = children [ i ] ;
2016-06-28 10:25:12 +08:00
var last = res [ res . length - 1 ] ;
2016-06-08 09:53:43 +08:00
// nested
if ( Array . isArray ( c ) ) {
2016-07-17 13:53:44 +08:00
res . push . apply ( res , normalizeChildren ( c , ns ) ) ;
2016-04-27 01:29:27 +08:00
} else if ( isPrimitive ( c ) ) {
2016-06-28 10:25:12 +08:00
if ( last && last . text ) {
last . text += String ( c ) ;
2016-08-06 06:14:22 +08:00
} else if ( c !== '' ) {
2016-06-28 10:25:12 +08:00
// convert primitive to vnode
res . push ( createTextVNode ( c ) ) ;
}
2016-06-08 09:53:43 +08:00
} else if ( c instanceof VNode ) {
2016-06-28 10:25:12 +08:00
if ( c . text && last && last . text ) {
last . text += c . text ;
} else {
// inherit parent namespace
2016-07-08 05:53:22 +08:00
if ( ns ) {
applyNS ( c , ns ) ;
}
2016-06-28 10:25:12 +08:00
res . push ( c ) ;
}
2016-04-27 01:29:27 +08:00
}
}
return res ;
}
2016-06-28 10:25:12 +08:00
}
function createTextVNode ( val ) {
return new VNode ( undefined , undefined , undefined , String ( val ) ) ;
2016-04-27 01:29:27 +08:00
}
2016-07-08 05:53:22 +08:00
function applyNS ( vnode , ns ) {
if ( vnode . tag && ! vnode . ns ) {
vnode . ns = ns ;
if ( vnode . children ) {
for ( var i = 0 , l = vnode . children . length ; i < l ; i ++ ) {
applyNS ( vnode . children [ i ] , ns ) ;
}
}
}
}
2016-08-10 12:55:30 +08:00
function getFirstComponentChild ( children ) {
return children && children . filter ( function ( c ) {
return c && c . componentOptions ;
} ) [ 0 ] ;
2016-07-08 05:53:22 +08:00
}
2016-07-17 13:53:44 +08:00
function mergeVNodeHook ( def , key , hook ) {
var oldHook = def [ key ] ;
if ( oldHook ) {
def [ key ] = function ( ) {
oldHook . apply ( this , arguments ) ;
hook . apply ( this , arguments ) ;
} ;
} else {
def [ key ] = hook ;
}
}
2016-06-08 09:53:43 +08:00
function updateListeners ( on , oldOn , add , remove ) {
2016-04-27 01:29:27 +08:00
var name = void 0 ,
cur = void 0 ,
old = void 0 ,
2016-06-08 09:53:43 +08:00
fn = void 0 ,
2016-04-27 01:29:27 +08:00
event = void 0 ,
capture = void 0 ;
for ( name in on ) {
cur = on [ name ] ;
old = oldOn [ name ] ;
2016-08-16 11:39:07 +08:00
if ( ! cur ) {
"development" !== 'production' && warn ( 'Handler for event "' + name + '" is undefined.' ) ;
} else if ( ! old ) {
2016-04-27 01:29:27 +08:00
capture = name . charAt ( 0 ) === '!' ;
event = capture ? name . slice ( 1 ) : name ;
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( cur ) ) {
add ( event , cur . invoker = arrInvoker ( cur ) , capture ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
fn = cur ;
cur = on [ name ] = { } ;
cur . fn = fn ;
add ( event , cur . invoker = fnInvoker ( cur ) , capture ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} else if ( Array . isArray ( old ) ) {
2016-04-27 01:29:27 +08:00
old . length = cur . length ;
for ( var i = 0 ; i < old . length ; i ++ ) {
old [ i ] = cur [ i ] ;
} on [ name ] = old ;
} else {
old . fn = cur ;
on [ name ] = old ;
}
}
2016-06-08 09:53:43 +08:00
for ( name in oldOn ) {
if ( ! on [ name ] ) {
event = name . charAt ( 0 ) === '!' ? name . slice ( 1 ) : name ;
remove ( event , oldOn [ name ] . invoker ) ;
}
}
2016-04-27 01:29:27 +08:00
}
function arrInvoker ( arr ) {
return function ( ev ) {
2016-06-08 09:53:43 +08:00
var single = arguments . length === 1 ;
2016-04-27 01:29:27 +08:00
for ( var i = 0 ; i < arr . length ; i ++ ) {
2016-06-08 09:53:43 +08:00
single ? arr [ i ] ( ev ) : arr [ i ] . apply ( null , arguments ) ;
2016-04-27 01:29:27 +08:00
}
} ;
}
function fnInvoker ( o ) {
return function ( ev ) {
2016-06-08 09:53:43 +08:00
var single = arguments . length === 1 ;
single ? o . fn ( ev ) : o . fn . apply ( null , arguments ) ;
2016-04-27 01:29:27 +08:00
} ;
}
2016-08-06 06:14:22 +08:00
var activeInstance = null ;
2016-04-27 01:29:27 +08:00
function initLifecycle ( vm ) {
var options = vm . $options ;
2016-07-17 13:53:44 +08:00
// locate first non-abstract parent
var parent = options . parent ;
2016-07-24 10:48:09 +08:00
if ( parent && ! options . abstract ) {
while ( parent . $options . abstract && parent . $parent ) {
2016-07-17 13:53:44 +08:00
parent = parent . $parent ;
}
parent . $children . push ( vm ) ;
2016-04-27 01:29:27 +08:00
}
2016-07-17 13:53:44 +08:00
vm . $parent = parent ;
vm . $root = parent ? parent . $root : vm ;
2016-04-27 01:29:27 +08:00
vm . $children = [ ] ;
vm . $refs = { } ;
2016-06-08 09:53:43 +08:00
vm . _watcher = null ;
2016-06-28 17:03:10 +08:00
vm . _inactive = false ;
2016-06-08 09:53:43 +08:00
vm . _isMounted = false ;
2016-04-27 01:29:27 +08:00
vm . _isDestroyed = false ;
vm . _isBeingDestroyed = false ;
}
function lifecycleMixin ( Vue ) {
2016-06-08 09:53:43 +08:00
Vue . prototype . _mount = function ( el , hydrating ) {
var vm = this ;
vm . $el = el ;
if ( ! vm . $options . render ) {
2016-06-11 07:23:32 +08:00
vm . $options . render = emptyVNode ;
2016-04-27 01:29:27 +08:00
if ( "development" !== 'production' ) {
2016-06-08 09:53:43 +08:00
/* istanbul ignore if */
if ( vm . $options . template ) {
warn ( 'You are using the runtime-only build of Vue where the template ' + 'option is not available. Either pre-compile the templates into ' + 'render functions, or use the compiler-included build.' , vm ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
warn ( 'Failed to mount component: template or render function not defined.' , vm ) ;
2016-04-27 01:29:27 +08:00
}
}
}
2016-06-08 09:53:43 +08:00
callHook ( vm , 'beforeMount' ) ;
vm . _watcher = new Watcher ( vm , function ( ) {
vm . _update ( vm . _render ( ) , hydrating ) ;
} , noop ) ;
hydrating = false ;
// root instance, call mounted on self
// mounted is called for child components in its inserted hook
if ( vm . $root === vm ) {
vm . _isMounted = true ;
callHook ( vm , 'mounted' ) ;
}
return vm ;
2016-04-27 01:29:27 +08:00
} ;
2016-06-08 09:53:43 +08:00
Vue . prototype . _update = function ( vnode , hydrating ) {
var vm = this ;
if ( vm . _isMounted ) {
callHook ( vm , 'beforeUpdate' ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-23 03:33:53 +08:00
var prevEl = vm . $el ;
2016-08-06 06:14:22 +08:00
var prevActiveInstance = activeInstance ;
activeInstance = vm ;
2016-08-16 11:39:07 +08:00
var prevVnode = vm . _vnode ;
vm . _vnode = vnode ;
if ( ! prevVnode ) {
2016-04-27 01:29:27 +08:00
// Vue.prototype.__patch__ is injected in entry points
// based on the rendering backend used.
2016-06-08 09:53:43 +08:00
vm . $el = vm . _ _patch _ _ ( vm . $el , vnode , hydrating ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-08-16 11:39:07 +08:00
vm . $el = vm . _ _patch _ _ ( prevVnode , vnode ) ;
2016-04-27 01:29:27 +08:00
}
2016-08-06 06:14:22 +08:00
activeInstance = prevActiveInstance ;
2016-06-23 03:33:53 +08:00
// update __vue__ reference
if ( prevEl ) {
prevEl . _ _vue _ _ = null ;
}
if ( vm . $el ) {
vm . $el . _ _vue _ _ = vm ;
}
2016-07-08 05:53:22 +08:00
// if parent is an HOC, update its $el as well
if ( vm . $vnode && vm . $parent && vm . $vnode === vm . $parent . _vnode ) {
vm . $parent . $el = vm . $el ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
if ( vm . _isMounted ) {
callHook ( vm , 'updated' ) ;
2016-04-27 01:29:27 +08:00
}
} ;
2016-06-08 09:53:43 +08:00
Vue . prototype . _updateFromParent = function ( propsData , listeners , parentVnode , renderChildren ) {
var vm = this ;
2016-08-06 06:14:22 +08:00
var hasChildren = ! ! ( vm . $options . _renderChildren || renderChildren ) ;
2016-06-08 09:53:43 +08:00
vm . $options . _parentVnode = parentVnode ;
vm . $options . _renderChildren = renderChildren ;
2016-04-27 01:29:27 +08:00
// update props
2016-06-08 09:53:43 +08:00
if ( propsData && vm . $options . props ) {
2016-04-27 01:29:27 +08:00
observerState . shouldConvert = false ;
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
observerState . isSettingProps = true ;
}
var propKeys = vm . $options . _propKeys || [ ] ;
2016-04-27 01:29:27 +08:00
for ( var i = 0 ; i < propKeys . length ; i ++ ) {
var key = propKeys [ i ] ;
2016-07-08 05:53:22 +08:00
vm [ key ] = validateProp ( key , vm . $options . props , propsData , vm ) ;
2016-04-27 01:29:27 +08:00
}
observerState . shouldConvert = true ;
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
observerState . isSettingProps = false ;
}
2016-04-27 01:29:27 +08:00
}
// update listeners
if ( listeners ) {
2016-06-08 09:53:43 +08:00
var oldListeners = vm . $options . _parentListeners ;
vm . $options . _parentListeners = listeners ;
vm . _updateListeners ( listeners , oldListeners ) ;
2016-04-27 01:29:27 +08:00
}
2016-08-10 12:55:30 +08:00
// resolve slots + force update if has children
2016-08-06 06:14:22 +08:00
if ( hasChildren ) {
2016-08-10 12:55:30 +08:00
vm . $slots = resolveSlots ( renderChildren ) ;
2016-08-06 06:14:22 +08:00
vm . $forceUpdate ( ) ;
}
2016-04-27 01:29:27 +08:00
} ;
Vue . prototype . $forceUpdate = function ( ) {
2016-06-08 09:53:43 +08:00
var vm = this ;
if ( vm . _watcher ) {
vm . _watcher . update ( ) ;
}
2016-04-27 01:29:27 +08:00
} ;
Vue . prototype . $destroy = function ( ) {
2016-06-08 09:53:43 +08:00
var vm = this ;
if ( vm . _isBeingDestroyed ) {
2016-04-27 01:29:27 +08:00
return ;
}
2016-06-08 09:53:43 +08:00
callHook ( vm , 'beforeDestroy' ) ;
vm . _isBeingDestroyed = true ;
2016-04-27 01:29:27 +08:00
// remove self from parent
2016-06-08 09:53:43 +08:00
var parent = vm . $parent ;
2016-07-24 10:48:09 +08:00
if ( parent && ! parent . _isBeingDestroyed && ! vm . $options . abstract ) {
2016-06-08 09:53:43 +08:00
remove ( parent . $children , vm ) ;
2016-04-27 01:29:27 +08:00
}
// teardown watchers
2016-06-08 09:53:43 +08:00
if ( vm . _watcher ) {
vm . _watcher . teardown ( ) ;
}
var i = vm . _watchers . length ;
2016-04-27 01:29:27 +08:00
while ( i -- ) {
2016-06-08 09:53:43 +08:00
vm . _watchers [ i ] . teardown ( ) ;
2016-04-27 01:29:27 +08:00
}
// remove reference from data ob
// frozen object may not have observer.
2016-06-08 09:53:43 +08:00
if ( vm . _data . _ _ob _ _ ) {
vm . _data . _ _ob _ _ . vmCount -- ;
2016-04-27 01:29:27 +08:00
}
// call the last hook...
2016-06-08 09:53:43 +08:00
vm . _isDestroyed = true ;
callHook ( vm , 'destroyed' ) ;
2016-04-27 01:29:27 +08:00
// turn off all instance listeners.
2016-06-08 09:53:43 +08:00
vm . $off ( ) ;
2016-06-23 03:33:53 +08:00
// remove __vue__ reference
if ( vm . $el ) {
vm . $el . _ _vue _ _ = null ;
}
2016-04-27 01:29:27 +08:00
} ;
}
function callHook ( vm , hook ) {
var handlers = vm . $options [ hook ] ;
if ( handlers ) {
for ( var i = 0 , j = handlers . length ; i < j ; i ++ ) {
handlers [ i ] . call ( vm ) ;
}
}
vm . $emit ( 'hook:' + hook ) ;
}
var hooks = { init : init , prepatch : prepatch , insert : insert , destroy : destroy } ;
var hooksToMerge = Object . keys ( hooks ) ;
2016-08-06 06:14:22 +08:00
function createComponent ( Ctor , data , context , children , tag ) {
2016-04-27 01:29:27 +08:00
if ( ! Ctor ) {
return ;
}
2016-06-28 10:25:12 +08:00
2016-04-27 01:29:27 +08:00
if ( isObject ( Ctor ) ) {
Ctor = Vue . extend ( Ctor ) ;
}
2016-06-28 10:25:12 +08:00
2016-06-08 09:53:43 +08:00
if ( typeof Ctor !== 'function' ) {
if ( "development" !== 'production' ) {
2016-08-06 06:14:22 +08:00
warn ( 'Invalid Component definition: ' + Ctor , context ) ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
return ;
}
// async component
if ( ! Ctor . cid ) {
if ( Ctor . resolved ) {
Ctor = Ctor . resolved ;
} else {
2016-06-08 09:53:43 +08:00
Ctor = resolveAsyncComponent ( Ctor , function ( ) {
2016-04-27 01:29:27 +08:00
// it's ok to queue this on every render because
2016-08-06 06:14:22 +08:00
// $forceUpdate is buffered by the scheduler.
context . $forceUpdate ( ) ;
2016-04-27 01:29:27 +08:00
} ) ;
2016-06-08 09:53:43 +08:00
if ( ! Ctor ) {
// return nothing if this is indeed an async component
// wait for the callback to trigger parent update.
return ;
}
2016-04-27 01:29:27 +08:00
}
}
data = data || { } ;
// extract props
var propsData = extractProps ( data , Ctor ) ;
2016-06-28 10:25:12 +08:00
// functional component
if ( Ctor . options . functional ) {
2016-08-21 02:04:54 +08:00
return createFunctionalComponent ( Ctor , propsData , data , context , children ) ;
2016-06-28 10:25:12 +08:00
}
2016-04-27 01:29:27 +08:00
// extract listeners, since these needs to be treated as
// child component listeners instead of DOM listeners
var listeners = data . on ;
2016-07-24 10:48:09 +08:00
// replace with listeners with .native modifier
data . on = data . nativeOn ;
2016-04-27 01:29:27 +08:00
2016-07-27 12:25:41 +08:00
if ( Ctor . options . abstract ) {
// abstract components do not keep anything
// other than props & listeners
data = { } ;
}
// merge component management hooks onto the placeholder node
mergeHooks ( data ) ;
2016-04-27 01:29:27 +08:00
// return a placeholder vnode
2016-06-08 09:53:43 +08:00
var name = Ctor . options . name || tag ;
2016-08-06 06:14:22 +08:00
var vnode = new VNode ( 'vue-component-' + Ctor . cid + ( name ? '-' + name : '' ) , data , undefined , undefined , undefined , undefined , context , { Ctor : Ctor , propsData : propsData , listeners : listeners , tag : tag , children : children } ) ;
2016-04-27 01:29:27 +08:00
return vnode ;
}
2016-08-21 02:04:54 +08:00
function createFunctionalComponent ( Ctor , propsData , data , context , children ) {
var props = { } ;
var propOptions = Ctor . options . props ;
if ( propOptions ) {
for ( var key in propOptions ) {
props [ key ] = validateProp ( key , propOptions , propsData ) ;
}
}
return Ctor . options . render . call ( null , context . $createElement , {
props : props ,
data : data ,
parent : context ,
children : normalizeChildren ( children ) ,
slots : function slots ( ) {
return resolveSlots ( children ) ;
}
} ) ;
}
2016-08-06 06:14:22 +08:00
function createComponentInstanceForVnode ( vnode , // we know it's MountedComponentVNode but flow doesn't
parent // activeInstance in lifecycle state
2016-06-08 09:53:43 +08:00
) {
var vnodeComponentOptions = vnode . componentOptions ;
var options = {
_isComponent : true ,
2016-08-06 06:14:22 +08:00
parent : parent ,
2016-06-08 09:53:43 +08:00
propsData : vnodeComponentOptions . propsData ,
_componentTag : vnodeComponentOptions . tag ,
2016-04-27 01:29:27 +08:00
_parentVnode : vnode ,
2016-06-08 09:53:43 +08:00
_parentListeners : vnodeComponentOptions . listeners ,
_renderChildren : vnodeComponentOptions . children
} ;
// check inline-template render functions
var inlineTemplate = vnode . data . inlineTemplate ;
if ( inlineTemplate ) {
options . render = inlineTemplate . render ;
options . staticRenderFns = inlineTemplate . staticRenderFns ;
}
return new vnodeComponentOptions . Ctor ( options ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
function init ( vnode , hydrating ) {
2016-08-16 11:39:07 +08:00
if ( ! vnode . child || vnode . child . _isDestroyed ) {
2016-08-06 06:14:22 +08:00
var child = vnode . child = createComponentInstanceForVnode ( vnode , activeInstance ) ;
2016-06-08 09:53:43 +08:00
child . $mount ( hydrating ? vnode . elm : undefined , hydrating ) ;
}
}
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
function prepatch ( oldVnode , vnode ) {
var options = vnode . componentOptions ;
2016-07-24 10:48:09 +08:00
var child = vnode . child = oldVnode . child ;
child . _updateFromParent ( options . propsData , // updated props
2016-06-08 09:53:43 +08:00
options . listeners , // updated listeners
2016-04-27 01:29:27 +08:00
vnode , // new parent vnode
2016-06-08 09:53:43 +08:00
options . children // new children
2016-04-27 01:29:27 +08:00
) ;
}
function insert ( vnode ) {
2016-06-08 09:53:43 +08:00
if ( ! vnode . child . _isMounted ) {
vnode . child . _isMounted = true ;
callHook ( vnode . child , 'mounted' ) ;
}
if ( vnode . data . keepAlive ) {
2016-06-28 17:03:10 +08:00
vnode . child . _inactive = false ;
2016-06-08 09:53:43 +08:00
callHook ( vnode . child , 'activated' ) ;
}
2016-04-27 01:29:27 +08:00
}
function destroy ( vnode ) {
2016-06-08 09:53:43 +08:00
if ( ! vnode . child . _isDestroyed ) {
if ( ! vnode . data . keepAlive ) {
vnode . child . $destroy ( ) ;
} else {
2016-06-28 17:03:10 +08:00
vnode . child . _inactive = true ;
2016-06-08 09:53:43 +08:00
callHook ( vnode . child , 'deactivated' ) ;
}
}
2016-04-27 01:29:27 +08:00
}
function resolveAsyncComponent ( factory , cb ) {
2016-06-08 09:53:43 +08:00
if ( factory . requested ) {
2016-04-27 01:29:27 +08:00
// pool callbacks
factory . pendingCallbacks . push ( cb ) ;
} else {
2016-08-21 02:04:54 +08:00
var _ret = function ( ) {
2016-04-27 01:29:27 +08:00
factory . requested = true ;
var cbs = factory . pendingCallbacks = [ cb ] ;
2016-06-08 09:53:43 +08:00
var sync = true ;
factory (
// resolve
function ( res ) {
2016-04-27 01:29:27 +08:00
if ( isObject ( res ) ) {
res = Vue . extend ( res ) ;
}
// cache resolved
factory . resolved = res ;
2016-06-08 09:53:43 +08:00
// invoke callbacks only if this is not a synchronous resolve
// (async resolves are shimmed as synchronous during SSR)
if ( ! sync ) {
for ( var i = 0 , l = cbs . length ; i < l ; i ++ ) {
cbs [ i ] ( res ) ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} ,
// reject
function ( reason ) {
2016-04-27 01:29:27 +08:00
"development" !== 'production' && warn ( 'Failed to resolve async component: ' + factory + ( reason ? '\nReason: ' + reason : '' ) ) ;
} ) ;
2016-06-08 09:53:43 +08:00
sync = false ;
// return in case resolved synchronously
return {
v : factory . resolved
} ;
} ( ) ;
2016-08-21 02:04:54 +08:00
if ( typeof _ret === "object" ) return _ret . v ;
2016-04-27 01:29:27 +08:00
}
}
function extractProps ( data , Ctor ) {
// we are only extrating raw values here.
// validation and default values are handled in the child
// component itself.
var propOptions = Ctor . options . props ;
if ( ! propOptions ) {
return ;
}
var res = { } ;
var attrs = data . attrs ;
var props = data . props ;
2016-07-24 10:48:09 +08:00
var domProps = data . domProps ;
2016-08-02 03:31:12 +08:00
if ( attrs || props || domProps ) {
2016-07-24 10:48:09 +08:00
for ( var key in propOptions ) {
var altKey = hyphenate ( key ) ;
2016-08-02 03:31:12 +08:00
checkProp ( res , props , key , altKey , true ) || checkProp ( res , attrs , key , altKey ) || checkProp ( res , domProps , key , altKey ) ;
2016-07-24 10:48:09 +08:00
}
2016-04-27 01:29:27 +08:00
}
return res ;
}
2016-07-24 10:48:09 +08:00
function checkProp ( res , hash , key , altKey , preserve ) {
2016-04-27 01:29:27 +08:00
if ( hash ) {
if ( hasOwn ( hash , key ) ) {
res [ key ] = hash [ key ] ;
2016-07-24 10:48:09 +08:00
if ( ! preserve ) {
delete hash [ key ] ;
}
2016-04-27 01:29:27 +08:00
return true ;
} else if ( hasOwn ( hash , altKey ) ) {
res [ key ] = hash [ altKey ] ;
2016-07-24 10:48:09 +08:00
if ( ! preserve ) {
delete hash [ altKey ] ;
}
2016-04-27 01:29:27 +08:00
return true ;
}
}
2016-06-08 09:53:43 +08:00
return false ;
2016-04-27 01:29:27 +08:00
}
function mergeHooks ( data ) {
2016-07-17 13:53:44 +08:00
if ( ! data . hook ) {
data . hook = { } ;
}
for ( var i = 0 ; i < hooksToMerge . length ; i ++ ) {
var key = hooksToMerge [ i ] ;
var fromParent = data . hook [ key ] ;
var ours = hooks [ key ] ;
data . hook [ key ] = fromParent ? mergeHook$1 ( ours , fromParent ) : ours ;
2016-04-27 01:29:27 +08:00
}
}
function mergeHook$1 ( a , b ) {
// since all hooks have at most two args, use fixed args
// to avoid having to use fn.apply().
return function ( _ , _ _ ) {
a ( _ , _ _ ) ;
b ( _ , _ _ ) ;
} ;
}
2016-06-28 10:25:12 +08:00
// wrapper function for providing a more flexible interface
// without getting yelled at by flow
function createElement ( tag , data , children ) {
if ( data && ( Array . isArray ( data ) || typeof data !== 'object' ) ) {
children = data ;
data = undefined ;
2016-06-08 09:53:43 +08:00
}
2016-07-17 13:53:44 +08:00
// make sure to use real instance instead of proxy as context
return _createElement ( this . _self , tag , data , children ) ;
2016-06-08 09:53:43 +08:00
}
2016-07-17 13:53:44 +08:00
function _createElement ( context , tag , data , children ) {
if ( data && data . _ _ob _ _ ) {
"development" !== '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 ;
}
2016-06-08 09:53:43 +08:00
if ( ! tag ) {
// in case of component :is set to falsy value
2016-06-11 07:23:32 +08:00
return emptyVNode ( ) ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
if ( typeof tag === 'string' ) {
var Ctor = void 0 ;
2016-07-17 13:53:44 +08:00
var ns = config . getTagNamespace ( tag ) ;
2016-04-27 01:29:27 +08:00
if ( config . isReservedTag ( tag ) ) {
2016-07-08 05:53:22 +08:00
// platform built-in elements
2016-08-06 06:14:22 +08:00
return new VNode ( tag , data , normalizeChildren ( children , ns ) , undefined , undefined , ns , context ) ;
2016-04-27 01:29:27 +08:00
} else if ( Ctor = resolveAsset ( context . $options , 'components' , tag ) ) {
2016-07-08 05:53:22 +08:00
// component
2016-08-06 06:14:22 +08:00
return createComponent ( Ctor , data , context , children , tag ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-07-17 13:53:44 +08:00
// unknown or unlisted namespaced elements
2016-07-08 05:53:22 +08:00
// check at runtime because it may get assigned a namespace when its
// parent normalizes children
2016-08-06 06:14:22 +08:00
return new VNode ( tag , data , normalizeChildren ( children , ns ) , undefined , undefined , ns , context ) ;
2016-04-27 01:29:27 +08:00
}
} else {
2016-07-08 05:53:22 +08:00
// direct component options / constructor
2016-08-06 06:14:22 +08:00
return createComponent ( tag , data , context , children ) ;
2016-04-27 01:29:27 +08:00
}
}
function initRender ( vm ) {
2016-07-08 05:53:22 +08:00
vm . $vnode = null ; // the placeholder node in parent tree
vm . _vnode = null ; // the root of the child tree
2016-04-27 01:29:27 +08:00
vm . _staticTrees = null ;
2016-08-10 12:55:30 +08:00
vm . $slots = resolveSlots ( vm . $options . _renderChildren ) ;
2016-04-27 01:29:27 +08:00
// bind the public createElement fn to this instance
// so that we get proper render context inside it.
2016-06-28 10:25:12 +08:00
vm . $createElement = bind ( createElement , vm ) ;
2016-04-27 01:29:27 +08:00
if ( vm . $options . el ) {
vm . $mount ( vm . $options . el ) ;
}
}
function renderMixin ( Vue ) {
2016-06-08 09:53:43 +08:00
Vue . prototype . $nextTick = function ( fn ) {
nextTick ( fn , this ) ;
} ;
2016-04-27 01:29:27 +08:00
Vue . prototype . _render = function ( ) {
2016-06-08 09:53:43 +08:00
var vm = this ;
var _vm$$options = vm . $options ;
var render = _vm$$options . render ;
2016-06-11 07:23:32 +08:00
var staticRenderFns = _vm$$options . staticRenderFns ;
2016-06-08 09:53:43 +08:00
var _parentVnode = _vm$$options . _parentVnode ;
2016-06-11 07:23:32 +08:00
2016-07-17 13:53:44 +08:00
if ( staticRenderFns && ! vm . _staticTrees ) {
vm . _staticTrees = [ ] ;
2016-06-11 07:23:32 +08:00
}
2016-07-08 05:53:22 +08:00
// set parent vnode. this allows render functions to have access
// to the data on the placeholder node.
2016-07-17 13:53:44 +08:00
vm . $vnode = _parentVnode ;
2016-04-27 01:29:27 +08:00
// render self
2016-07-17 13:53:44 +08:00
var vnode = void 0 ;
try {
vnode = render . call ( vm . _renderProxy , vm . $createElement ) ;
} catch ( e ) {
if ( "development" !== 'production' ) {
warn ( 'Error when rendering ' + formatComponentName ( vm ) + ':' ) ;
}
/* istanbul ignore else */
if ( config . errorHandler ) {
config . errorHandler . call ( null , e , vm ) ;
} else {
if ( config . _isServer ) {
throw e ;
} else {
setTimeout ( function ( ) {
throw e ;
} , 0 ) ;
}
}
// return previous vnode to prevent render error causing blank component
vnode = vm . _vnode ;
}
2016-06-08 09:53:43 +08:00
// return empty vnode in case the render function errored out
if ( ! ( vnode instanceof VNode ) ) {
if ( "development" !== 'production' && Array . isArray ( vnode ) ) {
warn ( 'Multiple root nodes returned from render function. Render function ' + 'should return a single root node.' , vm ) ;
}
2016-06-11 07:23:32 +08:00
vnode = emptyVNode ( ) ;
2016-06-08 09:53:43 +08:00
}
// set parent
vnode . parent = _parentVnode ;
2016-04-27 01:29:27 +08:00
return vnode ;
} ;
// shorthands used in render functions
2016-06-28 10:25:12 +08:00
Vue . prototype . _h = createElement ;
2016-04-27 01:29:27 +08:00
// toString for mustaches
2016-06-28 10:25:12 +08:00
Vue . prototype . _s = _toString ;
// number conversion
Vue . prototype . _n = toNumber ;
2016-07-27 12:25:41 +08:00
// render static tree by index
2016-08-10 12:55:30 +08:00
Vue . prototype . _m = function renderStatic ( index , isInFor ) {
2016-07-27 12:25:41 +08:00
var tree = this . _staticTrees [ index ] ;
2016-08-10 12:55:30 +08:00
// if has already-rendered static tree and not inside v-for,
// we can reuse the same tree by indentity.
if ( tree && ! isInFor ) {
return tree ;
}
// otherwise, render a fresh tree.
tree = this . _staticTrees [ index ] = this . $options . staticRenderFns [ index ] . call ( this . _renderProxy ) ;
if ( Array . isArray ( tree ) ) {
for ( var i = 0 ; i < tree . length ; i ++ ) {
tree [ i ] . isStatic = true ;
tree [ i ] . key = '__static__' + index + '_' + i ;
}
} else {
2016-07-27 12:25:41 +08:00
tree . isStatic = true ;
2016-08-10 12:55:30 +08:00
tree . key = '__static__' + index ;
2016-07-27 12:25:41 +08:00
}
return tree ;
2016-06-28 10:25:12 +08:00
} ;
2016-06-08 09:53:43 +08:00
// filter resolution helper
var identity = function identity ( _ ) {
return _ ;
} ;
2016-06-28 10:25:12 +08:00
Vue . prototype . _f = function resolveFilter ( id ) {
2016-06-08 09:53:43 +08:00
return resolveAsset ( this . $options , 'filters' , id , true ) || identity ;
} ;
2016-04-27 01:29:27 +08:00
// render v-for
2016-06-28 10:25:12 +08:00
Vue . prototype . _l = function renderList ( val , render ) {
2016-04-27 01:29:27 +08:00
var ret = void 0 ,
i = void 0 ,
l = void 0 ,
keys = void 0 ,
key = void 0 ;
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( val ) ) {
2016-04-27 01:29:27 +08:00
ret = new Array ( val . length ) ;
for ( i = 0 , l = val . length ; i < l ; i ++ ) {
2016-06-14 07:36:46 +08:00
ret [ i ] = render ( val [ i ] , i ) ;
2016-04-27 01:29:27 +08:00
}
} else if ( typeof val === 'number' ) {
ret = new Array ( val ) ;
for ( i = 0 ; i < val ; i ++ ) {
2016-06-14 07:36:46 +08:00
ret [ i ] = render ( i + 1 , i ) ;
2016-04-27 01:29:27 +08:00
}
} else if ( isObject ( val ) ) {
keys = Object . keys ( val ) ;
ret = new Array ( keys . length ) ;
for ( i = 0 , l = keys . length ; i < l ; i ++ ) {
key = keys [ i ] ;
2016-06-14 07:36:46 +08:00
ret [ i ] = render ( val [ key ] , key , i ) ;
2016-04-27 01:29:27 +08:00
}
}
return ret ;
} ;
2016-06-08 09:53:43 +08:00
// apply v-bind object
2016-07-24 10:48:09 +08:00
Vue . prototype . _b = function bindProps ( vnode , value , asProp ) {
2016-06-08 09:53:43 +08:00
if ( value ) {
if ( ! isObject ( value ) ) {
"development" !== 'production' && warn ( 'v-bind without argument expects an Object or Array value' , this ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( value ) ) {
value = toObject ( value ) ;
}
var data = vnode . data ;
2016-08-10 12:55:30 +08:00
for ( var _key in value ) {
if ( _key === 'class' || _key === 'style' ) {
data [ _key ] = value [ _key ] ;
2016-08-06 06:14:22 +08:00
} else {
2016-08-10 12:55:30 +08:00
var hash = asProp || config . mustUseProp ( _key ) ? data . domProps || ( data . domProps = { } ) : data . attrs || ( data . attrs = { } ) ;
hash [ _key ] = value [ _key ] ;
2016-08-06 06:14:22 +08:00
}
2016-04-27 01:29:27 +08:00
}
}
}
} ;
2016-06-23 03:33:53 +08:00
// expose v-on keyCodes
2016-06-28 10:25:12 +08:00
Vue . prototype . _k = function getKeyCodes ( key ) {
2016-06-23 03:33:53 +08:00
return config . keyCodes [ key ] ;
} ;
2016-04-27 01:29:27 +08:00
}
2016-07-24 10:48:09 +08:00
function resolveSlots ( renderChildren ) {
var slots = { } ;
if ( ! renderChildren ) {
return slots ;
}
2016-07-17 13:53:44 +08:00
var children = normalizeChildren ( renderChildren ) || [ ] ;
var defaultSlot = [ ] ;
var name = void 0 ,
child = void 0 ;
for ( var i = 0 , l = children . length ; i < l ; i ++ ) {
child = children [ i ] ;
if ( child . data && ( name = child . data . slot ) ) {
delete child . data . slot ;
var slot = slots [ name ] || ( slots [ name ] = [ ] ) ;
if ( child . tag === 'template' ) {
slot . push . apply ( slot , child . children ) ;
2016-06-08 09:53:43 +08:00
} else {
2016-07-17 13:53:44 +08:00
slot . push ( child ) ;
2016-04-27 01:29:27 +08:00
}
2016-07-17 13:53:44 +08:00
} else {
defaultSlot . push ( child ) ;
2016-04-27 01:29:27 +08:00
}
2016-07-17 13:53:44 +08:00
}
// ignore single whitespace
if ( defaultSlot . length && ! ( defaultSlot . length === 1 && defaultSlot [ 0 ] . text === ' ' ) ) {
slots . default = defaultSlot ;
2016-04-27 01:29:27 +08:00
}
2016-07-24 10:48:09 +08:00
return slots ;
2016-04-27 01:29:27 +08:00
}
function initEvents ( vm ) {
vm . _events = Object . create ( null ) ;
// init parent attached events
var listeners = vm . $options . _parentListeners ;
2016-06-08 09:53:43 +08:00
var on = bind ( vm . $on , vm ) ;
var off = bind ( vm . $off , vm ) ;
vm . _updateListeners = function ( listeners , oldListeners ) {
updateListeners ( listeners , oldListeners || { } , on , off ) ;
} ;
2016-04-27 01:29:27 +08:00
if ( listeners ) {
2016-06-08 09:53:43 +08:00
vm . _updateListeners ( listeners ) ;
2016-04-27 01:29:27 +08:00
}
}
function eventsMixin ( Vue ) {
Vue . prototype . $on = function ( event , fn ) {
2016-06-08 09:53:43 +08:00
var vm = this ; ( vm . _events [ event ] || ( vm . _events [ event ] = [ ] ) ) . push ( fn ) ;
return vm ;
2016-04-27 01:29:27 +08:00
} ;
Vue . prototype . $once = function ( event , fn ) {
2016-06-08 09:53:43 +08:00
var vm = this ;
2016-04-27 01:29:27 +08:00
function on ( ) {
2016-06-08 09:53:43 +08:00
vm . $off ( event , on ) ;
fn . apply ( vm , arguments ) ;
2016-04-27 01:29:27 +08:00
}
on . fn = fn ;
2016-06-08 09:53:43 +08:00
vm . $on ( event , on ) ;
return vm ;
2016-04-27 01:29:27 +08:00
} ;
Vue . prototype . $off = function ( event , fn ) {
2016-06-08 09:53:43 +08:00
var vm = this ;
2016-04-27 01:29:27 +08:00
// all
if ( ! arguments . length ) {
2016-06-08 09:53:43 +08:00
vm . _events = Object . create ( null ) ;
return vm ;
2016-04-27 01:29:27 +08:00
}
// specific event
2016-06-08 09:53:43 +08:00
var cbs = vm . _events [ event ] ;
2016-04-27 01:29:27 +08:00
if ( ! cbs ) {
2016-06-08 09:53:43 +08:00
return vm ;
2016-04-27 01:29:27 +08:00
}
if ( arguments . length === 1 ) {
2016-06-08 09:53:43 +08:00
vm . _events [ event ] = null ;
return vm ;
2016-04-27 01:29:27 +08:00
}
// specific handler
2016-06-08 09:53:43 +08:00
var cb = void 0 ;
2016-04-27 01:29:27 +08:00
var i = cbs . length ;
while ( i -- ) {
cb = cbs [ i ] ;
if ( cb === fn || cb . fn === fn ) {
cbs . splice ( i , 1 ) ;
break ;
}
}
2016-06-08 09:53:43 +08:00
return vm ;
2016-04-27 01:29:27 +08:00
} ;
Vue . prototype . $emit = function ( event ) {
2016-06-08 09:53:43 +08:00
var vm = this ;
var cbs = vm . _events [ event ] ;
2016-04-27 01:29:27 +08:00
if ( cbs ) {
cbs = cbs . length > 1 ? toArray ( cbs ) : cbs ;
var args = toArray ( arguments , 1 ) ;
for ( var i = 0 , l = cbs . length ; i < l ; i ++ ) {
2016-06-08 09:53:43 +08:00
cbs [ i ] . apply ( vm , args ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-08 09:53:43 +08:00
return vm ;
2016-04-27 01:29:27 +08:00
} ;
}
var uid = 0 ;
2016-06-08 09:53:43 +08:00
function initMixin ( Vue ) {
Vue . prototype . _init = function ( options ) {
var vm = this ;
// a uid
vm . _uid = uid ++ ;
// a flag to avoid this being observed
vm . _isVue = true ;
// merge options
if ( options && options . _isComponent ) {
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
initInternalComponent ( vm , options ) ;
} else {
2016-06-28 10:25:12 +08:00
vm . $options = mergeOptions ( resolveConstructorOptions ( vm ) , options || { } , vm ) ;
2016-06-08 09:53:43 +08:00
}
/* istanbul ignore else */
if ( "development" !== 'production' ) {
initProxy ( vm ) ;
} else { }
// expose real self
vm . _self = vm ;
initLifecycle ( vm ) ;
initEvents ( vm ) ;
2016-06-28 10:25:12 +08:00
callHook ( vm , 'beforeCreate' ) ;
2016-06-08 09:53:43 +08:00
initState ( vm ) ;
callHook ( vm , 'created' ) ;
initRender ( vm ) ;
} ;
2016-04-27 01:29:27 +08:00
2016-06-28 10:25:12 +08:00
function initInternalComponent ( vm , options ) {
var opts = vm . $options = Object . create ( resolveConstructorOptions ( vm ) ) ;
// doing this because it's faster than dynamic enumeration.
opts . parent = options . parent ;
opts . propsData = options . propsData ;
opts . _parentVnode = options . _parentVnode ;
opts . _parentListeners = options . _parentListeners ;
opts . _renderChildren = options . _renderChildren ;
opts . _componentTag = options . _componentTag ;
if ( options . render ) {
opts . render = options . render ;
opts . staticRenderFns = options . staticRenderFns ;
}
}
function resolveConstructorOptions ( vm ) {
var Ctor = vm . constructor ;
var options = Ctor . options ;
if ( Ctor . super ) {
var superOptions = Ctor . super . options ;
var cachedSuperOptions = Ctor . superOptions ;
if ( superOptions !== cachedSuperOptions ) {
// super option changed
Ctor . superOptions = superOptions ;
options = Ctor . options = mergeOptions ( superOptions , Ctor . extendOptions ) ;
if ( options . name ) {
options . components [ options . name ] = Ctor ;
}
}
}
return options ;
2016-06-08 09:53:43 +08:00
}
}
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
function Vue ( options ) {
this . _init ( options ) ;
}
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
initMixin ( Vue ) ;
2016-04-27 01:29:27 +08:00
stateMixin ( Vue ) ;
eventsMixin ( Vue ) ;
lifecycleMixin ( Vue ) ;
renderMixin ( Vue ) ;
var warn = void 0 ;
var formatComponentName = void 0 ;
if ( "development" !== 'production' ) {
( function ( ) {
var hasConsole = typeof console !== 'undefined' ;
warn = function warn ( msg , vm ) {
if ( hasConsole && ! config . silent ) {
2016-07-17 13:53:44 +08:00
console . error ( '[Vue warn]: ' + msg + ' ' + ( vm ? formatLocation ( formatComponentName ( vm ) ) : '' ) ) ;
2016-04-27 01:29:27 +08:00
}
} ;
formatComponentName = function formatComponentName ( vm ) {
2016-06-08 09:53:43 +08:00
if ( vm . $root === vm ) {
2016-07-17 13:53:44 +08:00
return 'root instance' ;
2016-06-08 09:53:43 +08:00
}
var name = vm . _isVue ? vm . $options . name || vm . $options . _componentTag : vm . name ;
2016-07-17 13:53:44 +08:00
return name ? 'component <' + name + '>' : 'anonymous component' ;
} ;
var formatLocation = function formatLocation ( str ) {
if ( str === 'anonymous component' ) {
2016-08-21 02:04:54 +08:00
str += ' - use the "name" option for better debugging messages.' ;
2016-07-17 13:53:44 +08:00
}
return '(found in ' + str + ')' ;
2016-04-27 01:29:27 +08:00
} ;
} ) ( ) ;
}
/ * *
* Option overwriting strategies are functions that handle
* how to merge a parent option value and a child option
* value into the final value .
* /
2016-06-08 09:53:43 +08:00
var strats = config . optionMergeStrategies ;
/ * *
* Options with restrictions
* /
if ( "development" !== 'production' ) {
strats . el = strats . propsData = function ( parent , child , vm , key ) {
if ( ! vm ) {
warn ( 'option "' + key + '" can only be used during instance ' + 'creation with the `new` keyword.' ) ;
}
return defaultStrat ( parent , child ) ;
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
strats . name = function ( parent , child , vm ) {
2016-08-21 02:04:54 +08:00
if ( vm && child ) {
2016-06-08 09:53:43 +08:00
warn ( 'options "name" can only be used as a component definition option, ' + 'not during instance creation.' ) ;
}
return defaultStrat ( parent , child ) ;
} ;
}
2016-04-27 01:29:27 +08:00
/ * *
* Helper that recursively merges two data objects together .
* /
function mergeData ( to , from ) {
2016-06-08 09:53:43 +08:00
var key = void 0 ,
toVal = void 0 ,
fromVal = void 0 ;
2016-04-27 01:29:27 +08:00
for ( key in from ) {
toVal = to [ key ] ;
fromVal = from [ key ] ;
if ( ! hasOwn ( to , key ) ) {
set ( to , key , fromVal ) ;
} else if ( isObject ( toVal ) && isObject ( fromVal ) ) {
mergeData ( toVal , fromVal ) ;
}
}
return to ;
}
/ * *
* Data
* /
strats . data = function ( parentVal , childVal , vm ) {
if ( ! vm ) {
// in a Vue.extend merge, both should be functions
if ( ! childVal ) {
return parentVal ;
}
if ( typeof childVal !== 'function' ) {
"development" !== 'production' && warn ( 'The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.' , vm ) ;
return parentVal ;
}
if ( ! parentVal ) {
return childVal ;
}
// when parentVal & childVal are both present,
// we need to return a function that returns the
// merged result of both functions... no need to
// check if parentVal is a function here because
// it has to be a function to pass previous merges.
return function mergedDataFn ( ) {
return mergeData ( childVal . call ( this ) , parentVal . call ( this ) ) ;
} ;
} else if ( parentVal || childVal ) {
return function mergedInstanceDataFn ( ) {
// instance merge
var instanceData = typeof childVal === 'function' ? childVal . call ( vm ) : childVal ;
var defaultData = typeof parentVal === 'function' ? parentVal . call ( vm ) : undefined ;
if ( instanceData ) {
return mergeData ( instanceData , defaultData ) ;
} else {
return defaultData ;
}
} ;
}
} ;
/ * *
* Hooks and param attributes are merged as arrays .
* /
function mergeHook ( parentVal , childVal ) {
2016-06-08 09:53:43 +08:00
return childVal ? parentVal ? parentVal . concat ( childVal ) : Array . isArray ( childVal ) ? childVal : [ childVal ] : parentVal ;
2016-04-27 01:29:27 +08:00
}
config . _lifecycleHooks . forEach ( function ( hook ) {
strats [ hook ] = mergeHook ;
} ) ;
/ * *
* Assets
*
* When a vm is present ( instance creation ) , we need to do
* a three - way merge between constructor options , instance
* options and parent options .
* /
function mergeAssets ( parentVal , childVal ) {
2016-06-08 09:53:43 +08:00
var res = Object . create ( parentVal || null ) ;
2016-04-27 01:29:27 +08:00
return childVal ? extend ( res , childVal ) : res ;
}
config . _assetTypes . forEach ( function ( type ) {
strats [ type + 's' ] = mergeAssets ;
} ) ;
/ * *
* Watchers .
*
* Watchers hashes should not overwrite one
* another , so we merge them as arrays .
* /
strats . watch = function ( parentVal , childVal ) {
2016-06-08 09:53:43 +08:00
/* istanbul ignore if */
2016-04-27 01:29:27 +08:00
if ( ! childVal ) return parentVal ;
if ( ! parentVal ) return childVal ;
var ret = { } ;
extend ( ret , parentVal ) ;
for ( var key in childVal ) {
var parent = ret [ key ] ;
var child = childVal [ key ] ;
2016-06-08 09:53:43 +08:00
if ( parent && ! Array . isArray ( parent ) ) {
2016-04-27 01:29:27 +08:00
parent = [ parent ] ;
}
ret [ key ] = parent ? parent . concat ( child ) : [ child ] ;
}
return ret ;
} ;
/ * *
* Other object hashes .
* /
strats . props = strats . methods = strats . computed = function ( parentVal , childVal ) {
if ( ! childVal ) return parentVal ;
if ( ! parentVal ) return childVal ;
var ret = Object . create ( null ) ;
extend ( ret , parentVal ) ;
extend ( ret , childVal ) ;
return ret ;
} ;
/ * *
* Default strategy .
* /
var defaultStrat = function defaultStrat ( parentVal , childVal ) {
return childVal === undefined ? parentVal : childVal ;
} ;
/ * *
* Make sure component options get converted to actual
* constructors .
* /
2016-06-08 09:53:43 +08:00
function normalizeComponents ( options ) {
2016-04-27 01:29:27 +08:00
if ( options . components ) {
var components = options . components ;
2016-06-08 09:53:43 +08:00
var def = void 0 ;
2016-04-27 01:29:27 +08:00
for ( var key in components ) {
2016-06-18 02:22:51 +08:00
var lower = key . toLowerCase ( ) ;
if ( isBuiltInTag ( lower ) || config . isReservedTag ( lower ) ) {
2016-04-27 01:29:27 +08:00
"development" !== 'production' && warn ( 'Do not use built-in or reserved HTML elements as component ' + 'id: ' + key ) ;
continue ;
}
def = components [ key ] ;
if ( isPlainObject ( def ) ) {
components [ key ] = Vue . extend ( def ) ;
}
}
}
}
/ * *
* Ensure all props option syntax are normalized into the
* Object - based format .
* /
2016-06-08 09:53:43 +08:00
function normalizeProps ( options ) {
2016-04-27 01:29:27 +08:00
var props = options . props ;
if ( ! props ) return ;
var res = { } ;
var i = void 0 ,
val = void 0 ,
name = void 0 ;
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( props ) ) {
2016-04-27 01:29:27 +08:00
i = props . length ;
while ( i -- ) {
val = props [ i ] ;
if ( typeof val === 'string' ) {
name = camelize ( val ) ;
res [ name ] = { type : null } ;
} else if ( "development" !== 'production' ) {
warn ( 'props must be strings when using array syntax.' ) ;
}
}
} else if ( isPlainObject ( props ) ) {
for ( var key in props ) {
val = props [ key ] ;
name = camelize ( key ) ;
res [ name ] = isPlainObject ( val ) ? val : { type : val } ;
}
}
options . props = res ;
}
2016-06-08 09:53:43 +08:00
/ * *
* Normalize raw function directives into object format .
* /
function normalizeDirectives ( options ) {
2016-04-27 01:29:27 +08:00
var dirs = options . directives ;
if ( dirs ) {
for ( var key in dirs ) {
2016-06-08 09:53:43 +08:00
var def = dirs [ key ] ;
if ( typeof def === 'function' ) {
dirs [ key ] = { bind : def , update : def } ;
2016-04-27 01:29:27 +08:00
}
}
}
}
/ * *
* Merge two option objects into a new one .
* Core utility used in both instantiation and inheritance .
* /
function mergeOptions ( parent , child , vm ) {
2016-06-08 09:53:43 +08:00
normalizeComponents ( child ) ;
normalizeProps ( child ) ;
normalizeDirectives ( child ) ;
var extendsFrom = child . extends ;
if ( extendsFrom ) {
parent = typeof extendsFrom === 'function' ? mergeOptions ( parent , extendsFrom . options , vm ) : mergeOptions ( parent , extendsFrom , vm ) ;
2016-04-27 01:29:27 +08:00
}
if ( child . mixins ) {
for ( var i = 0 , l = child . mixins . length ; i < l ; i ++ ) {
2016-06-08 09:53:43 +08:00
var mixin = child . mixins [ i ] ;
if ( mixin . prototype instanceof Vue ) {
mixin = mixin . options ;
}
parent = mergeOptions ( parent , mixin , vm ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-08 09:53:43 +08:00
var options = { } ;
var key = void 0 ;
2016-04-27 01:29:27 +08:00
for ( key in parent ) {
mergeField ( key ) ;
}
for ( key in child ) {
if ( ! hasOwn ( parent , key ) ) {
mergeField ( key ) ;
}
}
function mergeField ( key ) {
var strat = strats [ key ] || defaultStrat ;
options [ key ] = strat ( parent [ key ] , child [ key ] , vm , key ) ;
}
return options ;
}
/ * *
* Resolve an asset .
* This function is used because child instances need access
* to assets defined in its ancestor chain .
* /
function resolveAsset ( options , type , id , warnMissing ) {
/* istanbul ignore if */
if ( typeof id !== 'string' ) {
return ;
}
var assets = options [ type ] ;
var res = assets [ id ] ||
// camelCase ID
2016-06-08 09:53:43 +08:00
assets [ camelize ( id ) ] ||
2016-04-27 01:29:27 +08:00
// Pascal Case ID
2016-06-08 09:53:43 +08:00
assets [ capitalize ( camelize ( id ) ) ] ;
2016-04-27 01:29:27 +08:00
if ( "development" !== 'production' && warnMissing && ! res ) {
warn ( 'Failed to resolve ' + type . slice ( 0 , - 1 ) + ': ' + id , options ) ;
}
return res ;
}
2016-07-08 05:53:22 +08:00
function validateProp ( key , propOptions , propsData , vm ) {
2016-06-08 09:53:43 +08:00
/* istanbul ignore if */
2016-07-08 05:53:22 +08:00
if ( ! propsData ) return ;
var prop = propOptions [ key ] ;
2016-06-08 09:53:43 +08:00
var absent = ! hasOwn ( propsData , key ) ;
2016-04-27 01:29:27 +08:00
var value = propsData [ key ] ;
2016-06-08 09:53:43 +08:00
// handle boolean props
2016-08-11 13:43:09 +08:00
if ( getType ( prop . type ) === 'Boolean' ) {
2016-06-08 09:53:43 +08:00
if ( absent && ! hasOwn ( prop , 'default' ) ) {
value = false ;
} else if ( value === '' || value === hyphenate ( key ) ) {
value = true ;
}
}
2016-04-27 01:29:27 +08:00
// check default value
if ( value === undefined ) {
value = getPropDefaultValue ( vm , prop , key ) ;
// since the default value is a fresh copy,
// make sure to observe it.
2016-07-26 10:07:26 +08:00
var prevShouldConvert = observerState . shouldConvert ;
2016-04-27 01:29:27 +08:00
observerState . shouldConvert = true ;
observe ( value ) ;
2016-07-26 10:07:26 +08:00
observerState . shouldConvert = prevShouldConvert ;
2016-04-27 01:29:27 +08:00
}
if ( "development" !== 'production' ) {
assertProp ( prop , key , value , vm , absent ) ;
}
return value ;
}
/ * *
* Get the default value of a prop .
* /
function getPropDefaultValue ( vm , prop , name ) {
// no default, return undefined
if ( ! hasOwn ( prop , 'default' ) ) {
2016-06-08 09:53:43 +08:00
return undefined ;
2016-04-27 01:29:27 +08:00
}
var def = prop . default ;
// warn against non-factory defaults for Object & Array
if ( isObject ( def ) ) {
"development" !== 'production' && warn ( 'Invalid default value for prop "' + name + '": ' + 'Props with type Object/Array must use a factory function ' + 'to return the default value.' , vm ) ;
}
// call factory function for non-Function types
return typeof def === 'function' && prop . type !== Function ? def . call ( vm ) : def ;
}
/ * *
* Assert whether a prop is valid .
* /
function assertProp ( prop , name , value , vm , absent ) {
if ( prop . required && absent ) {
2016-06-08 09:53:43 +08:00
warn ( 'Missing required prop: "' + name + '"' , vm ) ;
return ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
if ( value == null && ! prop . required ) {
return ;
2016-04-27 01:29:27 +08:00
}
var type = prop . type ;
var valid = ! type ;
var expectedTypes = [ ] ;
if ( type ) {
2016-06-08 09:53:43 +08:00
if ( ! Array . isArray ( type ) ) {
2016-04-27 01:29:27 +08:00
type = [ type ] ;
}
for ( var i = 0 ; i < type . length && ! valid ; i ++ ) {
var assertedType = assertType ( value , type [ i ] ) ;
expectedTypes . push ( assertedType . expectedType ) ;
valid = assertedType . valid ;
}
}
if ( ! valid ) {
2016-06-08 09:53:43 +08:00
warn ( 'Invalid prop: type check failed for prop "' + name + '".' + ' Expected ' + expectedTypes . map ( capitalize ) . join ( ', ' ) + ', got ' + Object . prototype . toString . call ( value ) . slice ( 8 , - 1 ) + '.' , vm ) ;
return ;
2016-04-27 01:29:27 +08:00
}
var validator = prop . validator ;
if ( validator ) {
if ( ! validator ( value ) ) {
2016-06-08 09:53:43 +08:00
warn ( 'Invalid prop: custom validator check failed for prop "' + name + '".' , vm ) ;
2016-04-27 01:29:27 +08:00
}
}
}
/ * *
* Assert the type of a value
* /
function assertType ( value , type ) {
2016-06-08 09:53:43 +08:00
var valid = void 0 ;
2016-08-11 13:43:09 +08:00
var expectedType = getType ( type ) ;
if ( expectedType === 'String' ) {
valid = typeof value === ( expectedType = 'string' ) ;
} else if ( expectedType === 'Number' ) {
valid = typeof value === ( expectedType = 'number' ) ;
} else if ( expectedType === 'Boolean' ) {
valid = typeof value === ( expectedType = 'boolean' ) ;
} else if ( expectedType === 'Function' ) {
valid = typeof value === ( expectedType = 'function' ) ;
} else if ( expectedType === 'Object' ) {
2016-04-27 01:29:27 +08:00
valid = isPlainObject ( value ) ;
2016-08-11 13:43:09 +08:00
} else if ( expectedType === 'Array' ) {
2016-06-08 09:53:43 +08:00
valid = Array . isArray ( value ) ;
2016-04-27 01:29:27 +08:00
} else {
valid = value instanceof type ;
}
return {
valid : valid ,
expectedType : expectedType
} ;
}
2016-08-11 13:43:09 +08:00
/ * *
* Use function string name to check built - in types ,
* because a simple equality check will fail when running
* across different vms / iframes .
* /
function getType ( fn ) {
var match = fn && fn . toString ( ) . match ( /^\s*function (\w+)/ ) ;
return match && match [ 1 ] ;
}
2016-04-27 01:29:27 +08:00
var util = Object . freeze ( {
defineReactive : defineReactive ,
2016-06-28 10:25:12 +08:00
_toString : _toString ,
toNumber : toNumber ,
2016-04-27 01:29:27 +08:00
makeMap : makeMap ,
isBuiltInTag : isBuiltInTag ,
remove : remove ,
hasOwn : hasOwn ,
isPrimitive : isPrimitive ,
cached : cached ,
camelize : camelize ,
2016-06-08 09:53:43 +08:00
capitalize : capitalize ,
2016-04-27 01:29:27 +08:00
hyphenate : hyphenate ,
bind : bind ,
toArray : toArray ,
extend : extend ,
isObject : isObject ,
isPlainObject : isPlainObject ,
2016-06-08 09:53:43 +08:00
toObject : toObject ,
noop : noop ,
no : no ,
genStaticKeys : genStaticKeys ,
2016-04-27 01:29:27 +08:00
isReserved : isReserved ,
def : def ,
parsePath : parsePath ,
hasProto : hasProto ,
inBrowser : inBrowser ,
devtools : devtools ,
2016-06-14 07:36:46 +08:00
UA : UA ,
2016-04-27 01:29:27 +08:00
nextTick : nextTick ,
2016-06-28 10:25:12 +08:00
get _Set ( ) { return _Set ; } ,
2016-04-27 01:29:27 +08:00
mergeOptions : mergeOptions ,
resolveAsset : resolveAsset ,
get warn ( ) { return warn ; } ,
2016-07-17 13:53:44 +08:00
get formatComponentName ( ) { return formatComponentName ; } ,
2016-04-27 01:29:27 +08:00
validateProp : validateProp
} ) ;
function initUse ( Vue ) {
Vue . use = function ( plugin ) {
/* istanbul ignore if */
if ( plugin . installed ) {
return ;
}
// additional parameters
var args = toArray ( arguments , 1 ) ;
args . unshift ( this ) ;
if ( typeof plugin . install === 'function' ) {
plugin . install . apply ( plugin , args ) ;
} else {
plugin . apply ( null , args ) ;
}
plugin . installed = true ;
return this ;
} ;
}
2016-06-08 09:53:43 +08:00
function initMixin$1 ( Vue ) {
2016-04-27 01:29:27 +08:00
Vue . mixin = function ( mixin ) {
Vue . options = mergeOptions ( Vue . options , mixin ) ;
} ;
}
function initExtend ( Vue ) {
/ * *
* Each instance constructor , including Vue , has a unique
* cid . This enables us to create wrapped " child
* constructors " for prototypal inheritance and cache them .
* /
Vue . cid = 0 ;
var cid = 1 ;
/ * *
* Class inheritance
* /
Vue . extend = function ( extendOptions ) {
extendOptions = extendOptions || { } ;
var Super = this ;
var isFirstExtend = Super . cid === 0 ;
if ( isFirstExtend && extendOptions . _Ctor ) {
return extendOptions . _Ctor ;
}
var name = extendOptions . name || Super . options . name ;
if ( "development" !== 'production' ) {
if ( ! /^[a-zA-Z][\w-]*$/ . test ( name ) ) {
warn ( 'Invalid component name: "' + name + '". Component names ' + 'can only contain alphanumeric characaters and the hyphen.' ) ;
name = null ;
}
}
var Sub = function VueComponent ( options ) {
this . _init ( options ) ;
} ;
Sub . prototype = Object . create ( Super . prototype ) ;
Sub . prototype . constructor = Sub ;
Sub . cid = cid ++ ;
Sub . options = mergeOptions ( Super . options , extendOptions ) ;
Sub [ 'super' ] = Super ;
// allow further extension
Sub . extend = Super . extend ;
// create asset registers, so extended classes
// can have their private assets too.
config . _assetTypes . forEach ( function ( type ) {
Sub [ type ] = Super [ type ] ;
} ) ;
// enable recursive self-lookup
if ( name ) {
Sub . options . components [ name ] = Sub ;
}
2016-06-28 10:25:12 +08:00
// keep a reference to the super options at extension time.
// later at instantiation we can check if Super's options have
// been updated.
Sub . superOptions = Super . options ;
2016-06-08 09:53:43 +08:00
Sub . extendOptions = extendOptions ;
2016-04-27 01:29:27 +08:00
// cache constructor
if ( isFirstExtend ) {
extendOptions . _Ctor = Sub ;
}
return Sub ;
} ;
}
function initAssetRegisters ( Vue ) {
/ * *
2016-06-08 09:53:43 +08:00
* Create asset registration methods .
* /
2016-04-27 01:29:27 +08:00
config . _assetTypes . forEach ( function ( type ) {
Vue [ type ] = function ( id , definition ) {
if ( ! definition ) {
return this . options [ type + 's' ] [ id ] ;
} else {
/* istanbul ignore if */
if ( "development" !== 'production' ) {
if ( type === 'component' && config . isReservedTag ( id ) ) {
warn ( 'Do not use built-in or reserved HTML elements as component ' + 'id: ' + id ) ;
}
}
if ( type === 'component' && isPlainObject ( definition ) ) {
2016-06-11 07:23:32 +08:00
definition . name = definition . name || id ;
2016-04-27 01:29:27 +08:00
definition = Vue . extend ( definition ) ;
}
2016-07-08 05:53:22 +08:00
if ( type === 'directive' && typeof definition === 'function' ) {
definition = { bind : definition , update : definition } ;
}
2016-04-27 01:29:27 +08:00
this . options [ type + 's' ] [ id ] = definition ;
return definition ;
}
} ;
} ) ;
}
2016-06-08 09:53:43 +08:00
var KeepAlive = {
name : 'keep-alive' ,
2016-07-24 10:48:09 +08:00
abstract : true ,
2016-06-08 09:53:43 +08:00
created : function created ( ) {
this . cache = Object . create ( null ) ;
} ,
render : function render ( ) {
2016-08-10 12:55:30 +08:00
var vnode = getFirstComponentChild ( this . $slots . default ) ;
if ( vnode && vnode . componentOptions ) {
var opts = vnode . componentOptions ;
var key = vnode . key == null
2016-07-17 13:53:44 +08:00
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
2016-08-10 12:55:30 +08:00
? opts . Ctor . cid + '::' + opts . tag : vnode . key ;
2016-07-17 13:53:44 +08:00
if ( this . cache [ key ] ) {
2016-08-16 11:39:07 +08:00
vnode . child = this . cache [ key ] . child ;
2016-07-17 13:53:44 +08:00
} else {
2016-08-10 12:55:30 +08:00
this . cache [ key ] = vnode ;
2016-07-17 13:53:44 +08:00
}
2016-08-10 12:55:30 +08:00
vnode . data . keepAlive = true ;
2016-06-08 09:53:43 +08:00
}
2016-08-10 12:55:30 +08:00
return vnode ;
2016-06-08 09:53:43 +08:00
} ,
destroyed : function destroyed ( ) {
for ( var key in this . cache ) {
var vnode = this . cache [ key ] ;
callHook ( vnode . child , 'deactivated' ) ;
vnode . child . $destroy ( ) ;
}
}
} ;
var builtInComponents = {
KeepAlive : KeepAlive
} ;
2016-04-27 01:29:27 +08:00
function initGlobalAPI ( Vue ) {
2016-06-23 03:33:53 +08:00
// config
var configDef = { } ;
configDef . get = function ( ) {
return config ;
} ;
if ( "development" !== 'production' ) {
configDef . set = function ( ) {
warn ( 'Do not replace the Vue.config object, set individual fields instead.' ) ;
} ;
}
Object . defineProperty ( Vue , 'config' , configDef ) ;
2016-04-27 01:29:27 +08:00
Vue . util = util ;
Vue . set = set ;
Vue . delete = del ;
Vue . nextTick = nextTick ;
2016-06-08 09:53:43 +08:00
Vue . options = Object . create ( null ) ;
config . _assetTypes . forEach ( function ( type ) {
Vue . options [ type + 's' ] = Object . create ( null ) ;
} ) ;
extend ( Vue . options . components , builtInComponents ) ;
2016-04-27 01:29:27 +08:00
initUse ( Vue ) ;
2016-06-08 09:53:43 +08:00
initMixin$1 ( Vue ) ;
2016-04-27 01:29:27 +08:00
initExtend ( Vue ) ;
initAssetRegisters ( Vue ) ;
}
initGlobalAPI ( Vue ) ;
2016-06-08 09:53:43 +08:00
Object . defineProperty ( Vue . prototype , '$isServer' , {
get : function get ( ) {
return config . _isServer ;
}
} ) ;
2016-08-21 02:04:54 +08:00
Vue . version = '2.0.0-rc.3' ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
// attributes that should be using props for binding
var mustUseProp = makeMap ( 'value,selected,checked,muted' ) ;
var isEnumeratedAttr = makeMap ( 'contenteditable,draggable,spellcheck' ) ;
var isBooleanAttr = makeMap ( 'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' + 'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' + 'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' + 'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' + 'required,reversed,scoped,seamless,selected,sortable,translate,' + 'truespeed,typemustmatch,visible' ) ;
2016-06-16 02:22:40 +08:00
var isAttr = makeMap ( 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' + 'form,formaction,headers,<th>,height,hidden,high,href,hreflang,http-equiv,' + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' + 'target,title,type,usemap,value,width,wrap' ) ;
2016-06-08 09:53:43 +08:00
var xlinkNS = 'http://www.w3.org/1999/xlink' ;
var isXlink = function isXlink ( name ) {
return name . charAt ( 5 ) === ':' && name . slice ( 0 , 5 ) === 'xlink' ;
} ;
var getXlinkProp = function getXlinkProp ( name ) {
return isXlink ( name ) ? name . slice ( 6 , name . length ) : '' ;
} ;
var isFalsyAttrValue = function isFalsyAttrValue ( val ) {
return val == null || val === false ;
} ;
function genClassForVnode ( vnode ) {
var data = vnode . data ;
2016-08-02 03:31:12 +08:00
var parentNode = vnode ;
var childNode = vnode ;
while ( childNode . child ) {
childNode = childNode . child . _vnode ;
if ( childNode . data ) {
data = mergeClassData ( childNode . data , data ) ;
}
2016-06-08 09:53:43 +08:00
}
2016-08-02 03:31:12 +08:00
while ( parentNode = parentNode . parent ) {
if ( parentNode . data ) {
data = mergeClassData ( data , parentNode . data ) ;
}
2016-06-08 09:53:43 +08:00
}
return genClassFromData ( data ) ;
}
function mergeClassData ( child , parent ) {
return {
staticClass : concat ( child . staticClass , parent . staticClass ) ,
class : child . class ? [ child . class , parent . class ] : parent . class
} ;
}
function genClassFromData ( data ) {
var dynamicClass = data . class ;
var staticClass = data . staticClass ;
if ( staticClass || dynamicClass ) {
return concat ( staticClass , stringifyClass ( dynamicClass ) ) ;
}
/* istanbul ignore next */
return '' ;
}
function concat ( a , b ) {
return a ? b ? a + ' ' + b : a : b || '' ;
}
function stringifyClass ( value ) {
var res = '' ;
if ( ! value ) {
return res ;
}
if ( typeof value === 'string' ) {
return value ;
}
if ( Array . isArray ( value ) ) {
var stringified = void 0 ;
for ( var i = 0 , l = value . length ; i < l ; i ++ ) {
if ( value [ i ] ) {
if ( stringified = stringifyClass ( value [ i ] ) ) {
res += stringified + ' ' ;
}
}
}
return res . slice ( 0 , - 1 ) ;
}
if ( isObject ( value ) ) {
for ( var key in value ) {
if ( value [ key ] ) res += key + ' ' ;
}
return res . slice ( 0 , - 1 ) ;
}
/* istanbul ignore next */
return res ;
}
var namespaceMap = {
svg : 'http://www.w3.org/2000/svg' ,
math : 'http://www.w3.org/1998/Math/MathML'
} ;
2016-07-17 13:53:44 +08:00
var isHTMLTag = makeMap ( 'html,body,base,head,link,meta,style,title,' + 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' + 'div,dd,dl,dt,figcaption,figure,hr,img,li,main,ol,p,pre,ul,' + 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' + 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' + 'embed,object,param,source,canvas,script,noscript,del,ins,' + 'caption,col,colgroup,table,thead,tbody,td,th,tr,' + 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' + 'output,progress,select,textarea,' + 'details,dialog,menu,menuitem,summary,' + 'content,element,shadow,template' ) ;
2016-06-08 09:53:43 +08:00
var isUnaryTag = makeMap ( 'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' + 'link,meta,param,source,track,wbr' , true ) ;
// Elements that you can, intentionally, leave open
// (and which close themselves)
var canBeLeftOpenTag = makeMap ( 'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source' , true ) ;
// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3
// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
var isNonPhrasingTag = makeMap ( 'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' + 'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' + 'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' + 'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' + 'title,tr,track' , true ) ;
2016-07-17 13:53:44 +08:00
// this map is intentionally selective, only covering SVG elements that may
// contain child elements.
var isSVG = makeMap ( 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font,' + 'font-face,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' + 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view' , true ) ;
2016-08-02 03:31:12 +08:00
var isPreTag = function isPreTag ( tag ) {
return tag === 'pre' ;
} ;
2016-07-17 13:53:44 +08:00
var isReservedTag = function isReservedTag ( tag ) {
return isHTMLTag ( tag ) || isSVG ( tag ) ;
} ;
2016-06-08 09:53:43 +08:00
function getTagNamespace ( tag ) {
if ( isSVG ( tag ) ) {
return 'svg' ;
}
// basic support for MathML
// note it doesn't support other MathML elements being component roots
if ( tag === 'math' ) {
return 'math' ;
}
}
var unknownElementCache = Object . create ( null ) ;
function isUnknownElement ( tag ) {
/* istanbul ignore if */
if ( ! inBrowser ) {
return true ;
}
2016-07-24 10:48:09 +08:00
if ( isReservedTag ( tag ) ) {
return false ;
}
2016-06-08 09:53:43 +08:00
tag = tag . toLowerCase ( ) ;
/* istanbul ignore if */
if ( unknownElementCache [ tag ] != null ) {
return unknownElementCache [ tag ] ;
}
var el = document . createElement ( tag ) ;
if ( tag . indexOf ( '-' ) > - 1 ) {
// http://stackoverflow.com/a/28210364/1070244
return unknownElementCache [ tag ] = el . constructor === window . HTMLUnknownElement || el . constructor === window . HTMLElement ;
} else {
2016-06-14 07:36:46 +08:00
return unknownElementCache [ tag ] = /HTMLUnknownElement/ . test ( el . toString ( ) ) ;
2016-06-08 09:53:43 +08:00
}
}
var UA$1 = inBrowser && window . navigator . userAgent . toLowerCase ( ) ;
var isIE = UA$1 && /msie|trident/ . test ( UA$1 ) ;
var isIE9 = UA$1 && UA$1 . indexOf ( 'msie 9.0' ) > 0 ;
var isAndroid = UA$1 && UA$1 . indexOf ( 'android' ) > 0 ;
2016-08-10 12:55:30 +08:00
// According to
// https://w3c.github.io/DOM-Parsing/#dfn-serializing-an-attribute-value
// when serializing innerHTML, <, >, ", & should be encoded as entities.
// However, only some browsers, e.g. PhantomJS, encodes < and >.
2016-07-26 10:07:26 +08:00
// this causes problems with the in-browser parser.
2016-07-27 12:25:41 +08:00
var shouldDecodeTags = inBrowser ? function ( ) {
2016-07-26 10:07:26 +08:00
var div = document . createElement ( 'div' ) ;
div . innerHTML = '<div a=">">' ;
return div . innerHTML . indexOf ( '>' ) > 0 ;
} ( ) : false ;
2016-06-08 09:53:43 +08:00
/ * *
* Query an element selector if it ' s not an element already .
* /
function query ( el ) {
if ( typeof el === 'string' ) {
var selector = el ;
el = document . querySelector ( el ) ;
if ( ! el ) {
"development" !== 'production' && warn ( 'Cannot find element: ' + selector ) ;
return document . createElement ( 'div' ) ;
}
}
return el ;
}
2016-06-28 10:25:12 +08:00
function createElement$1 ( tagName ) {
2016-06-08 09:53:43 +08:00
return document . createElement ( tagName ) ;
}
function createElementNS ( namespace , tagName ) {
return document . createElementNS ( namespaceMap [ namespace ] , tagName ) ;
}
function createTextNode ( text ) {
return document . createTextNode ( text ) ;
}
2016-08-06 06:14:22 +08:00
function createComment ( text ) {
return document . createComment ( text ) ;
}
2016-06-08 09:53:43 +08:00
function insertBefore ( parentNode , newNode , referenceNode ) {
parentNode . insertBefore ( newNode , referenceNode ) ;
}
function removeChild ( node , child ) {
node . removeChild ( child ) ;
}
function appendChild ( node , child ) {
node . appendChild ( child ) ;
}
function parentNode ( node ) {
return node . parentNode ;
}
function nextSibling ( node ) {
return node . nextSibling ;
}
function tagName ( node ) {
return node . tagName ;
}
function setTextContent ( node , text ) {
node . textContent = text ;
}
function childNodes ( node ) {
return node . childNodes ;
}
2016-06-11 07:23:32 +08:00
function setAttribute ( node , key , val ) {
node . setAttribute ( key , val ) ;
}
2016-06-08 09:53:43 +08:00
var nodeOps = Object . freeze ( {
2016-06-28 10:25:12 +08:00
createElement : createElement$1 ,
2016-06-08 09:53:43 +08:00
createElementNS : createElementNS ,
createTextNode : createTextNode ,
2016-08-06 06:14:22 +08:00
createComment : createComment ,
2016-06-08 09:53:43 +08:00
insertBefore : insertBefore ,
removeChild : removeChild ,
appendChild : appendChild ,
parentNode : parentNode ,
nextSibling : nextSibling ,
tagName : tagName ,
setTextContent : setTextContent ,
2016-06-11 07:23:32 +08:00
childNodes : childNodes ,
setAttribute : setAttribute
2016-06-08 09:53:43 +08:00
} ) ;
2016-08-21 02:04:54 +08:00
var ref = {
create : function create ( _ , vnode ) {
registerRef ( vnode ) ;
} ,
update : function update ( oldVnode , vnode ) {
if ( oldVnode . data . ref !== vnode . data . ref ) {
registerRef ( oldVnode , true ) ;
registerRef ( vnode ) ;
}
} ,
destroy : function destroy ( vnode ) {
registerRef ( vnode , true ) ;
}
} ;
function registerRef ( vnode , isRemoval ) {
var key = vnode . data . ref ;
if ( ! key ) return ;
var vm = vnode . context ;
var ref = vnode . child || vnode . elm ;
var refs = vm . $refs ;
if ( isRemoval ) {
if ( Array . isArray ( refs [ key ] ) ) {
remove ( refs [ key ] , ref ) ;
} else if ( refs [ key ] === ref ) {
refs [ key ] = undefined ;
}
} else {
if ( vnode . data . refInFor ) {
if ( Array . isArray ( refs [ key ] ) ) {
refs [ key ] . push ( ref ) ;
} else {
refs [ key ] = [ ref ] ;
}
} else {
refs [ key ] = ref ;
}
}
}
2016-06-28 17:03:10 +08:00
var emptyData = { } ;
var emptyNode = new VNode ( '' , emptyData , [ ] ) ;
2016-06-08 09:53:43 +08:00
var hooks$1 = [ 'create' , 'update' , 'postpatch' , 'remove' , 'destroy' ] ;
2016-04-27 01:29:27 +08:00
function isUndef ( s ) {
2016-06-08 09:53:43 +08:00
return s == null ;
2016-04-27 01:29:27 +08:00
}
function isDef ( s ) {
2016-06-08 09:53:43 +08:00
return s != null ;
2016-04-27 01:29:27 +08:00
}
function sameVnode ( vnode1 , vnode2 ) {
2016-08-06 06:14:22 +08:00
return vnode1 . key === vnode2 . key && vnode1 . tag === vnode2 . tag && vnode1 . isComment === vnode2 . isComment && ! vnode1 . data === ! vnode2 . data ;
2016-04-27 01:29:27 +08:00
}
function createKeyToOldIdx ( children , beginIdx , endIdx ) {
var i = void 0 ,
key = void 0 ;
var map = { } ;
for ( i = beginIdx ; i <= endIdx ; ++ i ) {
key = children [ i ] . key ;
if ( isDef ( key ) ) map [ key ] = i ;
}
return map ;
}
function createPatchFunction ( backend ) {
var i = void 0 ,
j = void 0 ;
var cbs = { } ;
var modules = backend . modules ;
var nodeOps = backend . nodeOps ;
for ( i = 0 ; i < hooks$1 . length ; ++ i ) {
cbs [ hooks$1 [ i ] ] = [ ] ;
for ( j = 0 ; j < modules . length ; ++ j ) {
if ( modules [ j ] [ hooks$1 [ i ] ] !== undefined ) cbs [ hooks$1 [ i ] ] . push ( modules [ j ] [ hooks$1 [ i ] ] ) ;
}
}
function emptyNodeAt ( elm ) {
2016-06-08 09:53:43 +08:00
return new VNode ( nodeOps . tagName ( elm ) . toLowerCase ( ) , { } , [ ] , undefined , elm ) ;
2016-04-27 01:29:27 +08:00
}
function createRmCb ( childElm , listeners ) {
function remove ( ) {
if ( -- remove . listeners === 0 ) {
removeElement ( childElm ) ;
}
}
remove . listeners = listeners ;
return remove ;
}
function removeElement ( el ) {
var parent = nodeOps . parentNode ( el ) ;
nodeOps . removeChild ( parent , el ) ;
}
2016-08-06 06:14:22 +08:00
function createElm ( vnode , insertedVnodeQueue , nested ) {
2016-04-27 01:29:27 +08:00
var i = void 0 ,
elm = void 0 ;
var data = vnode . data ;
2016-08-06 06:14:22 +08:00
vnode . isRootInsert = ! nested ;
2016-04-27 01:29:27 +08:00
if ( isDef ( data ) ) {
if ( isDef ( i = data . hook ) && isDef ( i = i . init ) ) i ( vnode ) ;
// after calling the init hook, if the vnode is a child component
// it should've created a child instance and mounted it. the child
// component also has set the placeholder vnode's elm.
// in that case we can just return the element and be done.
if ( isDef ( i = vnode . child ) ) {
2016-08-06 06:14:22 +08:00
initComponent ( vnode , insertedVnodeQueue ) ;
2016-04-27 01:29:27 +08:00
return vnode . elm ;
}
}
var children = vnode . children ;
var tag = vnode . tag ;
if ( isDef ( tag ) ) {
2016-07-08 05:53:22 +08:00
if ( "development" !== 'production' ) {
if ( ! vnode . ns && ! ( config . ignoredElements && config . ignoredElements . indexOf ( tag ) > - 1 ) && config . isUnknownElement ( tag ) ) {
warn ( 'Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.' , vnode . context ) ;
}
}
2016-04-27 01:29:27 +08:00
elm = vnode . elm = vnode . ns ? nodeOps . createElementNS ( vnode . ns , tag ) : nodeOps . createElement ( tag ) ;
2016-06-11 07:23:32 +08:00
setScope ( vnode ) ;
2016-04-27 01:29:27 +08:00
if ( Array . isArray ( children ) ) {
for ( i = 0 ; i < children . length ; ++ i ) {
2016-08-06 06:14:22 +08:00
nodeOps . appendChild ( elm , createElm ( children [ i ] , insertedVnodeQueue , true ) ) ;
2016-04-27 01:29:27 +08:00
}
} else if ( isPrimitive ( vnode . text ) ) {
nodeOps . appendChild ( elm , nodeOps . createTextNode ( vnode . text ) ) ;
}
if ( isDef ( data ) ) {
invokeCreateHooks ( vnode , insertedVnodeQueue ) ;
}
2016-08-06 06:14:22 +08:00
} else if ( vnode . isComment ) {
elm = vnode . elm = nodeOps . createComment ( vnode . text ) ;
2016-04-27 01:29:27 +08:00
} else {
elm = vnode . elm = nodeOps . createTextNode ( vnode . text ) ;
}
return vnode . elm ;
}
2016-08-16 11:39:07 +08:00
function isPatchable ( vnode ) {
while ( vnode . child ) {
vnode = vnode . child . _vnode ;
}
return isDef ( vnode . tag ) ;
}
2016-04-27 01:29:27 +08:00
function invokeCreateHooks ( vnode , insertedVnodeQueue ) {
for ( var _i = 0 ; _i < cbs . create . length ; ++ _i ) {
cbs . create [ _i ] ( emptyNode , vnode ) ;
}
i = vnode . data . hook ; // Reuse variable
if ( isDef ( i ) ) {
if ( i . create ) i . create ( emptyNode , vnode ) ;
if ( i . insert ) insertedVnodeQueue . push ( vnode ) ;
}
}
2016-08-06 06:14:22 +08:00
function initComponent ( vnode , insertedVnodeQueue ) {
if ( vnode . data . pendingInsert ) {
insertedVnodeQueue . push . apply ( insertedVnodeQueue , vnode . data . pendingInsert ) ;
}
vnode . elm = vnode . child . $el ;
2016-08-16 11:39:07 +08:00
if ( isPatchable ( vnode ) ) {
invokeCreateHooks ( vnode , insertedVnodeQueue ) ;
setScope ( vnode ) ;
} else {
2016-08-21 02:04:54 +08:00
// empty component root.
// skip all element-related modules except for ref (#3455)
registerRef ( vnode ) ;
// make sure to invoke the insert hook
2016-08-16 11:39:07 +08:00
insertedVnodeQueue . push ( vnode ) ;
}
2016-08-06 06:14:22 +08:00
}
2016-06-11 07:23:32 +08:00
// set scope id attribute for scoped CSS.
// this is implemented as a special case to avoid the overhead
// of going through the normal attribute patching process.
function setScope ( vnode ) {
var i = void 0 ;
2016-08-06 06:14:22 +08:00
if ( isDef ( i = vnode . context ) && isDef ( i = i . $options . _scopeId ) ) {
2016-06-16 02:22:40 +08:00
nodeOps . setAttribute ( vnode . elm , i , '' ) ;
}
2016-08-06 06:14:22 +08:00
if ( isDef ( i = activeInstance ) && i !== vnode . context && isDef ( i = i . $options . _scopeId ) ) {
2016-06-11 07:23:32 +08:00
nodeOps . setAttribute ( vnode . elm , i , '' ) ;
}
}
2016-04-27 01:29:27 +08:00
function addVnodes ( parentElm , before , vnodes , startIdx , endIdx , insertedVnodeQueue ) {
for ( ; startIdx <= endIdx ; ++ startIdx ) {
nodeOps . insertBefore ( parentElm , createElm ( vnodes [ startIdx ] , insertedVnodeQueue ) , before ) ;
}
}
function invokeDestroyHook ( vnode ) {
var i = void 0 ,
j = void 0 ;
var data = vnode . data ;
if ( isDef ( data ) ) {
if ( isDef ( i = data . hook ) && isDef ( i = i . destroy ) ) i ( vnode ) ;
for ( i = 0 ; i < cbs . destroy . length ; ++ i ) {
cbs . destroy [ i ] ( vnode ) ;
}
2016-06-08 09:53:43 +08:00
}
2016-06-28 17:03:10 +08:00
if ( isDef ( i = vnode . child ) && ! data . keepAlive ) {
2016-06-08 09:53:43 +08:00
invokeDestroyHook ( i . _vnode ) ;
}
if ( isDef ( i = vnode . children ) ) {
for ( j = 0 ; j < vnode . children . length ; ++ j ) {
invokeDestroyHook ( vnode . children [ j ] ) ;
2016-04-27 01:29:27 +08:00
}
}
}
function removeVnodes ( parentElm , vnodes , startIdx , endIdx ) {
for ( ; startIdx <= endIdx ; ++ startIdx ) {
var ch = vnodes [ startIdx ] ;
if ( isDef ( ch ) ) {
if ( isDef ( ch . tag ) ) {
removeAndInvokeRemoveHook ( ch ) ;
2016-08-21 02:04:54 +08:00
invokeDestroyHook ( ch ) ;
2016-04-27 01:29:27 +08:00
} else {
// Text node
nodeOps . removeChild ( parentElm , ch . elm ) ;
}
}
}
}
function removeAndInvokeRemoveHook ( vnode , rm ) {
if ( rm || isDef ( vnode . data ) ) {
var listeners = cbs . remove . length + 1 ;
if ( ! rm ) {
// directly removing
rm = createRmCb ( vnode . elm , listeners ) ;
} else {
// we have a recursively passed down rm callback
// increase the listeners count
rm . listeners += listeners ;
}
// recursively invoke hooks on child component root node
if ( isDef ( i = vnode . child ) && isDef ( i = i . _vnode ) && isDef ( i . data ) ) {
removeAndInvokeRemoveHook ( i , rm ) ;
}
for ( i = 0 ; i < cbs . remove . length ; ++ i ) {
cbs . remove [ i ] ( vnode , rm ) ;
}
if ( isDef ( i = vnode . data . hook ) && isDef ( i = i . remove ) ) {
i ( vnode , rm ) ;
} else {
rm ( ) ;
}
} else {
removeElement ( vnode . elm ) ;
}
}
2016-07-17 13:53:44 +08:00
function updateChildren ( parentElm , oldCh , newCh , insertedVnodeQueue , removeOnly ) {
2016-04-27 01:29:27 +08:00
var oldStartIdx = 0 ;
var newStartIdx = 0 ;
var oldEndIdx = oldCh . length - 1 ;
var oldStartVnode = oldCh [ 0 ] ;
var oldEndVnode = oldCh [ oldEndIdx ] ;
var newEndIdx = newCh . length - 1 ;
var newStartVnode = newCh [ 0 ] ;
var newEndVnode = newCh [ newEndIdx ] ;
var oldKeyToIdx = void 0 ,
idxInOld = void 0 ,
elmToMove = void 0 ,
before = void 0 ;
2016-07-17 13:53:44 +08:00
// removeOnly is a special flag used only by <transition-group>
// to ensure removed elements stay in correct relative positions
// during leaving transitions
var canMove = ! removeOnly ;
2016-04-27 01:29:27 +08:00
while ( oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx ) {
if ( isUndef ( oldStartVnode ) ) {
oldStartVnode = oldCh [ ++ oldStartIdx ] ; // Vnode has been moved left
} else if ( isUndef ( oldEndVnode ) ) {
2016-06-28 10:25:12 +08:00
oldEndVnode = oldCh [ -- oldEndIdx ] ;
} else if ( sameVnode ( oldStartVnode , newStartVnode ) ) {
patchVnode ( oldStartVnode , newStartVnode , insertedVnodeQueue ) ;
oldStartVnode = oldCh [ ++ oldStartIdx ] ;
newStartVnode = newCh [ ++ newStartIdx ] ;
} else if ( sameVnode ( oldEndVnode , newEndVnode ) ) {
patchVnode ( oldEndVnode , newEndVnode , insertedVnodeQueue ) ;
oldEndVnode = oldCh [ -- oldEndIdx ] ;
newEndVnode = newCh [ -- newEndIdx ] ;
} else if ( sameVnode ( oldStartVnode , newEndVnode ) ) {
// Vnode moved right
patchVnode ( oldStartVnode , newEndVnode , insertedVnodeQueue ) ;
2016-07-17 13:53:44 +08:00
canMove && nodeOps . insertBefore ( parentElm , oldStartVnode . elm , nodeOps . nextSibling ( oldEndVnode . elm ) ) ;
2016-06-28 10:25:12 +08:00
oldStartVnode = oldCh [ ++ oldStartIdx ] ;
newEndVnode = newCh [ -- newEndIdx ] ;
} else if ( sameVnode ( oldEndVnode , newStartVnode ) ) {
// Vnode moved left
patchVnode ( oldEndVnode , newStartVnode , insertedVnodeQueue ) ;
2016-07-17 13:53:44 +08:00
canMove && nodeOps . insertBefore ( parentElm , oldEndVnode . elm , oldStartVnode . elm ) ;
2016-06-28 10:25:12 +08:00
oldEndVnode = oldCh [ -- oldEndIdx ] ;
newStartVnode = newCh [ ++ newStartIdx ] ;
} else {
if ( isUndef ( oldKeyToIdx ) ) oldKeyToIdx = createKeyToOldIdx ( oldCh , oldStartIdx , oldEndIdx ) ;
2016-08-10 12:55:30 +08:00
idxInOld = isDef ( newStartVnode . key ) ? oldKeyToIdx [ newStartVnode . key ] : null ;
if ( isUndef ( idxInOld ) ) {
2016-06-28 10:25:12 +08:00
// New element
nodeOps . insertBefore ( parentElm , createElm ( newStartVnode , insertedVnodeQueue ) , oldStartVnode . elm ) ;
2016-04-27 01:29:27 +08:00
newStartVnode = newCh [ ++ newStartIdx ] ;
} else {
2016-06-28 10:25:12 +08:00
elmToMove = oldCh [ idxInOld ] ;
/* istanbul ignore if */
if ( "development" !== 'production' && ! elmToMove ) {
warn ( 'It seems there are duplicate keys that is causing an update error. ' + 'Make sure each v-for item has a unique key.' ) ;
}
if ( elmToMove . tag !== newStartVnode . tag ) {
// same key but different element. treat as new element
2016-04-27 01:29:27 +08:00
nodeOps . insertBefore ( parentElm , createElm ( newStartVnode , insertedVnodeQueue ) , oldStartVnode . elm ) ;
newStartVnode = newCh [ ++ newStartIdx ] ;
} else {
2016-06-28 10:25:12 +08:00
patchVnode ( elmToMove , newStartVnode , insertedVnodeQueue ) ;
oldCh [ idxInOld ] = undefined ;
2016-07-17 13:53:44 +08:00
canMove && nodeOps . insertBefore ( parentElm , newStartVnode . elm , oldStartVnode . elm ) ;
2016-06-28 10:25:12 +08:00
newStartVnode = newCh [ ++ newStartIdx ] ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-28 10:25:12 +08:00
}
2016-04-27 01:29:27 +08:00
}
if ( oldStartIdx > oldEndIdx ) {
before = isUndef ( newCh [ newEndIdx + 1 ] ) ? null : newCh [ newEndIdx + 1 ] . elm ;
addVnodes ( parentElm , before , newCh , newStartIdx , newEndIdx , insertedVnodeQueue ) ;
} else if ( newStartIdx > newEndIdx ) {
removeVnodes ( parentElm , oldCh , oldStartIdx , oldEndIdx ) ;
}
}
2016-07-17 13:53:44 +08:00
function patchVnode ( oldVnode , vnode , insertedVnodeQueue , removeOnly ) {
2016-08-10 12:55:30 +08:00
if ( oldVnode === vnode ) {
return ;
}
if ( vnode . isStatic && oldVnode . isStatic && vnode . key === oldVnode . key ) {
vnode . elm = oldVnode . elm ;
return ;
}
2016-04-27 01:29:27 +08:00
var i = void 0 ,
hook = void 0 ;
2016-06-28 17:03:10 +08:00
var hasData = isDef ( i = vnode . data ) ;
2016-07-08 05:53:22 +08:00
if ( hasData && isDef ( hook = i . hook ) && isDef ( i = hook . prepatch ) ) {
i ( oldVnode , vnode ) ;
2016-04-27 01:29:27 +08:00
}
var elm = vnode . elm = oldVnode . elm ;
var oldCh = oldVnode . children ;
var ch = vnode . children ;
2016-08-16 11:39:07 +08:00
if ( hasData && isPatchable ( vnode ) ) {
2016-04-27 01:29:27 +08:00
for ( i = 0 ; i < cbs . update . length ; ++ i ) {
cbs . update [ i ] ( oldVnode , vnode ) ;
2016-06-08 09:53:43 +08:00
} if ( isDef ( hook ) && isDef ( i = hook . update ) ) i ( oldVnode , vnode ) ;
2016-04-27 01:29:27 +08:00
}
if ( isUndef ( vnode . text ) ) {
if ( isDef ( oldCh ) && isDef ( ch ) ) {
2016-07-17 13:53:44 +08:00
if ( oldCh !== ch ) updateChildren ( elm , oldCh , ch , insertedVnodeQueue , removeOnly ) ;
2016-04-27 01:29:27 +08:00
} else if ( isDef ( ch ) ) {
if ( isDef ( oldVnode . text ) ) nodeOps . setTextContent ( elm , '' ) ;
addVnodes ( elm , null , ch , 0 , ch . length - 1 , insertedVnodeQueue ) ;
} else if ( isDef ( oldCh ) ) {
removeVnodes ( elm , oldCh , 0 , oldCh . length - 1 ) ;
} else if ( isDef ( oldVnode . text ) ) {
nodeOps . setTextContent ( elm , '' ) ;
}
} else if ( oldVnode . text !== vnode . text ) {
nodeOps . setTextContent ( elm , vnode . text ) ;
}
2016-06-28 17:03:10 +08:00
if ( hasData ) {
2016-06-08 09:53:43 +08:00
for ( i = 0 ; i < cbs . postpatch . length ; ++ i ) {
cbs . postpatch [ i ] ( oldVnode , vnode ) ;
} if ( isDef ( hook ) && isDef ( i = hook . postpatch ) ) i ( oldVnode , vnode ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-07-17 13:53:44 +08:00
function invokeInsertHook ( vnode , queue , initial ) {
// delay insert hooks for component root nodes, invoke them after the
// element is really inserted
if ( initial && vnode . parent ) {
vnode . parent . data . pendingInsert = queue ;
} else {
for ( var _i2 = 0 ; _i2 < queue . length ; ++ _i2 ) {
queue [ _i2 ] . data . hook . insert ( queue [ _i2 ] ) ;
}
2016-04-27 01:29:27 +08:00
}
}
2016-08-06 06:14:22 +08:00
var bailed = false ;
2016-04-27 01:29:27 +08:00
function hydrate ( elm , vnode , insertedVnodeQueue ) {
if ( "development" !== 'production' ) {
if ( ! assertNodeMatch ( elm , vnode ) ) {
return false ;
}
}
vnode . elm = elm ;
var tag = vnode . tag ;
var data = vnode . data ;
var children = vnode . children ;
if ( isDef ( data ) ) {
2016-06-08 09:53:43 +08:00
if ( isDef ( i = data . hook ) && isDef ( i = i . init ) ) i ( vnode , true /* hydrating */ ) ;
2016-04-27 01:29:27 +08:00
if ( isDef ( i = vnode . child ) ) {
// child component. it should have hydrated its own tree.
2016-08-06 06:14:22 +08:00
initComponent ( vnode , insertedVnodeQueue ) ;
2016-04-27 01:29:27 +08:00
return true ;
}
}
if ( isDef ( tag ) ) {
if ( isDef ( children ) ) {
2016-06-08 09:53:43 +08:00
var childNodes = nodeOps . childNodes ( elm ) ;
2016-08-06 06:14:22 +08:00
var childrenMatch = true ;
if ( childNodes . length !== children . length ) {
childrenMatch = false ;
} else {
for ( var _i3 = 0 ; _i3 < children . length ; _i3 ++ ) {
if ( ! hydrate ( childNodes [ _i3 ] , children [ _i3 ] , insertedVnodeQueue ) ) {
childrenMatch = false ;
break ;
}
}
}
if ( ! childrenMatch ) {
if ( "development" !== 'production' && typeof console !== 'undefined' && ! bailed ) {
bailed = true ;
console . warn ( 'Parent: ' , elm ) ;
console . warn ( 'Mismatching childNodes vs. VNodes: ' , childNodes , children ) ;
2016-04-27 01:29:27 +08:00
}
2016-08-06 06:14:22 +08:00
return false ;
2016-04-27 01:29:27 +08:00
}
}
if ( isDef ( data ) ) {
invokeCreateHooks ( vnode , insertedVnodeQueue ) ;
}
}
return true ;
}
function assertNodeMatch ( node , vnode ) {
2016-08-06 06:14:22 +08:00
if ( vnode . tag ) {
return vnode . tag . indexOf ( 'vue-component' ) === 0 || vnode . tag === nodeOps . tagName ( node ) . toLowerCase ( ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-08-06 06:14:22 +08:00
return _toString ( vnode . text ) === node . data ;
2016-07-24 10:48:09 +08:00
}
2016-04-27 01:29:27 +08:00
}
2016-07-17 13:53:44 +08:00
return function patch ( oldVnode , vnode , hydrating , removeOnly ) {
2016-06-08 09:53:43 +08:00
var elm = void 0 ,
parent = void 0 ;
2016-07-17 13:53:44 +08:00
var isInitialPatch = false ;
2016-04-27 01:29:27 +08:00
var insertedVnodeQueue = [ ] ;
if ( ! oldVnode ) {
// empty mount, create new root element
2016-07-17 13:53:44 +08:00
isInitialPatch = true ;
2016-04-27 01:29:27 +08:00
createElm ( vnode , insertedVnodeQueue ) ;
} else {
2016-06-08 09:53:43 +08:00
var isRealElement = isDef ( oldVnode . nodeType ) ;
if ( ! isRealElement && sameVnode ( oldVnode , vnode ) ) {
2016-07-17 13:53:44 +08:00
patchVnode ( oldVnode , vnode , insertedVnodeQueue , removeOnly ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
if ( isRealElement ) {
2016-04-27 01:29:27 +08:00
// mounting to a real element
// check if this is server-rendered content and if we can perform
// a successful hydration.
2016-08-06 06:14:22 +08:00
if ( oldVnode . nodeType === 1 && oldVnode . hasAttribute ( 'server-rendered' ) ) {
2016-04-27 01:29:27 +08:00
oldVnode . removeAttribute ( 'server-rendered' ) ;
2016-06-08 09:53:43 +08:00
hydrating = true ;
}
if ( hydrating ) {
2016-04-27 01:29:27 +08:00
if ( hydrate ( oldVnode , vnode , insertedVnodeQueue ) ) {
2016-07-17 13:53:44 +08:00
invokeInsertHook ( vnode , insertedVnodeQueue , true ) ;
2016-04-27 01:29:27 +08:00
return oldVnode ;
2016-08-06 06:14:22 +08:00
} else if ( "development" !== 'production' ) {
warn ( 'The client-side rendered virtual DOM tree is not matching ' + 'server-rendered content. This is likely caused by incorrect ' + 'HTML markup, for example nesting block-level elements inside ' + '<p>, or missing <tbody>. Bailing hydration and performing ' + 'full client-side render.' ) ;
2016-04-27 01:29:27 +08:00
}
}
// either not server-rendered, or hydration failed.
// create an empty node and replace it
oldVnode = emptyNodeAt ( oldVnode ) ;
}
elm = oldVnode . elm ;
parent = nodeOps . parentNode ( elm ) ;
createElm ( vnode , insertedVnodeQueue ) ;
2016-07-08 05:53:22 +08:00
// component root element replaced.
// update parent placeholder node element.
if ( vnode . parent ) {
vnode . parent . elm = vnode . elm ;
2016-08-16 11:39:07 +08:00
if ( isPatchable ( vnode ) ) {
for ( var _i4 = 0 ; _i4 < cbs . create . length ; ++ _i4 ) {
cbs . create [ _i4 ] ( emptyNode , vnode . parent ) ;
}
2016-07-08 05:53:22 +08:00
}
}
2016-04-27 01:29:27 +08:00
if ( parent !== null ) {
nodeOps . insertBefore ( parent , vnode . elm , nodeOps . nextSibling ( elm ) ) ;
removeVnodes ( parent , [ oldVnode ] , 0 , 0 ) ;
2016-06-08 09:53:43 +08:00
} else if ( isDef ( oldVnode . tag ) ) {
invokeDestroyHook ( oldVnode ) ;
2016-04-27 01:29:27 +08:00
}
}
}
2016-07-17 13:53:44 +08:00
invokeInsertHook ( vnode , insertedVnodeQueue , isInitialPatch ) ;
2016-04-27 01:29:27 +08:00
return vnode . elm ;
} ;
}
2016-06-08 09:53:43 +08:00
var directives = {
create : function bindDirectives ( oldVnode , vnode ) {
applyDirectives ( oldVnode , vnode , 'bind' ) ;
} ,
update : function updateDirectives ( oldVnode , vnode ) {
applyDirectives ( oldVnode , vnode , 'update' ) ;
} ,
postpatch : function postupdateDirectives ( oldVnode , vnode ) {
2016-07-08 05:53:22 +08:00
applyDirectives ( oldVnode , vnode , 'componentUpdated' ) ;
2016-06-08 09:53:43 +08:00
} ,
destroy : function unbindDirectives ( vnode ) {
applyDirectives ( vnode , vnode , 'unbind' ) ;
}
} ;
2016-04-27 01:29:27 +08:00
2016-07-08 05:53:22 +08:00
var emptyModifiers = Object . create ( null ) ;
2016-06-08 09:53:43 +08:00
function applyDirectives ( oldVnode , vnode , hook ) {
var dirs = vnode . data . directives ;
if ( dirs ) {
var oldDirs = oldVnode . data . directives ;
var isUpdate = hook === 'update' ;
for ( var i = 0 ; i < dirs . length ; i ++ ) {
var dir = dirs [ i ] ;
var def = resolveAsset ( vnode . context . $options , 'directives' , dir . name , true ) ;
var fn = def && def [ hook ] ;
if ( fn ) {
if ( isUpdate && oldDirs ) {
2016-07-08 05:53:22 +08:00
dir . oldValue = oldDirs [ i ] . value ;
}
if ( ! dir . modifiers ) {
dir . modifiers = emptyModifiers ;
2016-06-08 09:53:43 +08:00
}
fn ( vnode . elm , dir , vnode , oldVnode ) ;
}
}
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
var baseModules = [ ref , directives ] ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
function updateAttrs ( oldVnode , vnode ) {
if ( ! oldVnode . data . attrs && ! vnode . data . attrs ) {
return ;
}
var key = void 0 ,
cur = void 0 ,
old = void 0 ;
var elm = vnode . elm ;
var oldAttrs = oldVnode . data . attrs || { } ;
var attrs = vnode . data . attrs || { } ;
2016-08-02 03:31:12 +08:00
// clone observed objects, as the user probably wants to mutate it
if ( attrs . _ _ob _ _ ) {
attrs = vnode . data . attrs = extend ( { } , attrs ) ;
}
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
for ( key in attrs ) {
2016-08-02 03:31:12 +08:00
cur = attrs [ key ] ;
2016-06-08 09:53:43 +08:00
old = oldAttrs [ key ] ;
if ( old !== cur ) {
setAttr ( elm , key , cur ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
}
for ( key in oldAttrs ) {
if ( attrs [ key ] == null ) {
if ( isXlink ( key ) ) {
elm . removeAttributeNS ( xlinkNS , getXlinkProp ( key ) ) ;
} else if ( ! isEnumeratedAttr ( key ) ) {
elm . removeAttribute ( key ) ;
}
}
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
function setAttr ( el , key , value ) {
if ( isBooleanAttr ( key ) ) {
// set attribute for blank value
// e.g. <option disabled>Select one</option>
if ( isFalsyAttrValue ( value ) ) {
el . removeAttribute ( key ) ;
} else {
el . setAttribute ( key , key ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} else if ( isEnumeratedAttr ( key ) ) {
el . setAttribute ( key , isFalsyAttrValue ( value ) || value === 'false' ? 'false' : 'true' ) ;
} else if ( isXlink ( key ) ) {
if ( isFalsyAttrValue ( value ) ) {
el . removeAttributeNS ( xlinkNS , getXlinkProp ( key ) ) ;
} else {
el . setAttributeNS ( xlinkNS , key , value ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} else {
if ( isFalsyAttrValue ( value ) ) {
el . removeAttribute ( key ) ;
} else {
el . setAttribute ( key , value ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-08 09:53:43 +08:00
}
var attrs = {
2016-08-02 03:31:12 +08:00
create : updateAttrs ,
2016-06-08 09:53:43 +08:00
update : updateAttrs
2016-04-27 01:29:27 +08:00
} ;
2016-06-08 09:53:43 +08:00
function updateClass ( oldVnode , vnode ) {
var el = vnode . elm ;
var data = vnode . data ;
2016-08-02 03:31:12 +08:00
var oldData = oldVnode . data ;
if ( ! data . staticClass && ! data . class && ( ! oldData || ! oldData . staticClass && ! oldData . class ) ) {
2016-06-08 09:53:43 +08:00
return ;
}
var cls = genClassForVnode ( vnode ) ;
// handle transition classes
var transitionClass = el . _transitionClasses ;
if ( transitionClass ) {
cls = concat ( cls , stringifyClass ( transitionClass ) ) ;
}
// set the class
if ( cls !== el . _prevClass ) {
el . setAttribute ( 'class' , cls ) ;
el . _prevClass = cls ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
var klass = {
create : updateClass ,
update : updateClass
} ;
function updateDOMListeners ( oldVnode , vnode ) {
if ( ! oldVnode . data . on && ! vnode . data . on ) {
return ;
}
var on = vnode . data . on || { } ;
var oldOn = oldVnode . data . on || { } ;
var add = vnode . elm . _v _add || ( vnode . elm . _v _add = function ( event , handler , capture ) {
vnode . elm . addEventListener ( event , handler , capture ) ;
} ) ;
var remove = vnode . elm . _v _remove || ( vnode . elm . _v _remove = function ( event , handler ) {
vnode . elm . removeEventListener ( event , handler ) ;
} ) ;
updateListeners ( on , oldOn , add , remove ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
var events = {
create : updateDOMListeners ,
update : updateDOMListeners
} ;
2016-07-24 10:48:09 +08:00
function updateDOMProps ( oldVnode , vnode ) {
if ( ! oldVnode . data . domProps && ! vnode . data . domProps ) {
2016-06-08 09:53:43 +08:00
return ;
}
var key = void 0 ,
cur = void 0 ;
var elm = vnode . elm ;
2016-07-24 10:48:09 +08:00
var oldProps = oldVnode . data . domProps || { } ;
var props = vnode . data . domProps || { } ;
2016-08-02 03:31:12 +08:00
// clone observed objects, as the user probably wants to mutate it
if ( props . _ _ob _ _ ) {
props = vnode . data . domProps = extend ( { } , props ) ;
}
2016-06-08 09:53:43 +08:00
for ( key in oldProps ) {
if ( props [ key ] == null ) {
elm [ key ] = undefined ;
}
}
for ( key in props ) {
2016-08-02 03:31:12 +08:00
// ignore children if the node has textContent or innerHTML,
// as these will throw away existing DOM nodes and cause removal errors
// on subsequent patches (#3360)
if ( ( key === 'textContent' || key === 'innerHTML' ) && vnode . children ) {
vnode . children . length = 0 ;
}
cur = props [ key ] ;
2016-06-08 09:53:43 +08:00
if ( key === 'value' ) {
// store value as _value as well since
// non-string values will be stringified
elm . _value = cur ;
// avoid resetting cursor position when value is the same
2016-08-02 03:31:12 +08:00
var strCur = cur == null ? '' : String ( cur ) ;
if ( elm . value !== strCur ) {
elm . value = strCur ;
2016-06-08 09:53:43 +08:00
}
} else {
elm [ key ] = cur ;
}
}
2016-04-27 01:29:27 +08:00
}
2016-07-24 10:48:09 +08:00
var domProps = {
create : updateDOMProps ,
update : updateDOMProps
2016-06-08 09:53:43 +08:00
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
var prefixes = [ 'Webkit' , 'Moz' , 'ms' ] ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
var testEl = void 0 ;
var normalize = cached ( function ( prop ) {
testEl = testEl || document . createElement ( 'div' ) ;
prop = camelize ( prop ) ;
if ( prop !== 'filter' && prop in testEl . style ) {
return prop ;
}
var upper = prop . charAt ( 0 ) . toUpperCase ( ) + prop . slice ( 1 ) ;
for ( var i = 0 ; i < prefixes . length ; i ++ ) {
var prefixed = prefixes [ i ] + upper ;
if ( prefixed in testEl . style ) {
return prefixed ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
} ) ;
function updateStyle ( oldVnode , vnode ) {
2016-08-06 06:14:22 +08:00
if ( ( ! oldVnode . data || ! oldVnode . data . style ) && ! vnode . data . style ) {
2016-06-08 09:53:43 +08:00
return ;
}
var cur = void 0 ,
name = void 0 ;
2016-08-06 06:14:22 +08:00
var el = vnode . elm ;
2016-06-08 09:53:43 +08:00
var oldStyle = oldVnode . data . style || { } ;
var style = vnode . data . style || { } ;
2016-08-06 06:14:22 +08:00
// handle string
if ( typeof style === 'string' ) {
el . style . cssText = style ;
return ;
}
2016-08-02 03:31:12 +08:00
var needClone = style . _ _ob _ _ ;
2016-06-08 09:53:43 +08:00
// handle array syntax
if ( Array . isArray ( style ) ) {
2016-08-02 03:31:12 +08:00
style = vnode . data . style = toObject ( style ) ;
2016-06-08 09:53:43 +08:00
}
2016-07-17 13:53:44 +08:00
// clone the style for future updates,
// in case the user mutates the style object in-place.
2016-08-02 03:31:12 +08:00
if ( needClone ) {
style = vnode . data . style = extend ( { } , style ) ;
}
2016-07-17 13:53:44 +08:00
2016-06-08 09:53:43 +08:00
for ( name in oldStyle ) {
if ( ! style [ name ] ) {
2016-08-06 06:14:22 +08:00
el . style [ normalize ( name ) ] = '' ;
2016-06-08 09:53:43 +08:00
}
}
for ( name in style ) {
2016-08-02 03:31:12 +08:00
cur = style [ name ] ;
2016-06-08 09:53:43 +08:00
if ( cur !== oldStyle [ name ] ) {
// ie9 setting to null has no effect, must use empty string
2016-08-06 06:14:22 +08:00
el . style [ normalize ( name ) ] = cur || '' ;
2016-06-08 09:53:43 +08:00
}
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
var style = {
create : updateStyle ,
update : updateStyle
} ;
2016-04-27 01:29:27 +08:00
/ * *
2016-06-08 09:53:43 +08:00
* Add class with compatibility for SVG since classList is not supported on
* SVG elements in IE
2016-04-27 01:29:27 +08:00
* /
function addClass ( el , cls ) {
2016-06-08 09:53:43 +08:00
/* istanbul ignore else */
2016-04-27 01:29:27 +08:00
if ( el . classList ) {
if ( cls . indexOf ( ' ' ) > - 1 ) {
cls . split ( /\s+/ ) . forEach ( function ( c ) {
return el . classList . add ( c ) ;
} ) ;
} else {
el . classList . add ( cls ) ;
}
} else {
2016-06-08 09:53:43 +08:00
var cur = ' ' + el . getAttribute ( 'class' ) + ' ' ;
2016-04-27 01:29:27 +08:00
if ( cur . indexOf ( ' ' + cls + ' ' ) < 0 ) {
2016-06-08 09:53:43 +08:00
el . setAttribute ( 'class' , ( cur + cls ) . trim ( ) ) ;
2016-04-27 01:29:27 +08:00
}
}
}
/ * *
2016-06-08 09:53:43 +08:00
* Remove class with compatibility for SVG since classList is not supported on
* SVG elements in IE
2016-04-27 01:29:27 +08:00
* /
function removeClass ( el , cls ) {
2016-06-08 09:53:43 +08:00
/* istanbul ignore else */
2016-04-27 01:29:27 +08:00
if ( el . classList ) {
if ( cls . indexOf ( ' ' ) > - 1 ) {
cls . split ( /\s+/ ) . forEach ( function ( c ) {
return el . classList . remove ( c ) ;
} ) ;
} else {
el . classList . remove ( cls ) ;
}
} else {
2016-06-08 09:53:43 +08:00
var cur = ' ' + el . getAttribute ( 'class' ) + ' ' ;
2016-04-27 01:29:27 +08:00
var tar = ' ' + cls + ' ' ;
while ( cur . indexOf ( tar ) >= 0 ) {
cur = cur . replace ( tar , ' ' ) ;
}
2016-06-08 09:53:43 +08:00
el . setAttribute ( 'class' , cur . trim ( ) ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-08 09:53:43 +08:00
var hasTransition = inBrowser && ! isIE9 ;
2016-04-27 01:29:27 +08:00
var TRANSITION = 'transition' ;
var ANIMATION = 'animation' ;
// Transition property/event sniffing
2016-06-08 09:53:43 +08:00
var transitionProp = 'transition' ;
var transitionEndEvent = 'transitionend' ;
var animationProp = 'animation' ;
var animationEndEvent = 'animationend' ;
if ( hasTransition ) {
/* istanbul ignore if */
if ( window . ontransitionend === undefined && window . onwebkittransitionend !== undefined ) {
transitionProp = 'WebkitTransition' ;
transitionEndEvent = 'webkitTransitionEnd' ;
}
if ( window . onanimationend === undefined && window . onwebkitanimationend !== undefined ) {
animationProp = 'WebkitAnimation' ;
animationEndEvent = 'webkitAnimationEnd' ;
}
2016-04-27 01:29:27 +08:00
}
var raf = inBrowser && window . requestAnimationFrame || setTimeout ;
function nextFrame ( fn ) {
raf ( function ( ) {
raf ( fn ) ;
} ) ;
}
2016-07-17 13:53:44 +08:00
function addTransitionClass ( el , cls ) {
( el . _transitionClasses || ( el . _transitionClasses = [ ] ) ) . push ( cls ) ;
addClass ( el , cls ) ;
}
function removeTransitionClass ( el , cls ) {
if ( el . _transitionClasses ) {
remove ( el . _transitionClasses , cls ) ;
}
removeClass ( el , cls ) ;
}
2016-07-27 12:25:41 +08:00
function whenTransitionEnds ( el , expectedType , cb ) {
var _getTransitionInfo = getTransitionInfo ( el , expectedType ) ;
2016-07-17 13:53:44 +08:00
var type = _getTransitionInfo . type ;
var timeout = _getTransitionInfo . timeout ;
var propCount = _getTransitionInfo . propCount ;
if ( ! type ) return cb ( ) ;
var event = type === TRANSITION ? transitionEndEvent : animationEndEvent ;
var ended = 0 ;
var end = function end ( ) {
el . removeEventListener ( event , onEnd ) ;
cb ( ) ;
} ;
var onEnd = function onEnd ( ) {
if ( ++ ended >= propCount ) {
end ( ) ;
}
} ;
setTimeout ( function ( ) {
if ( ended < propCount ) {
end ( ) ;
}
} , timeout + 1 ) ;
el . addEventListener ( event , onEnd ) ;
}
var transformRE = /\b(transform|all)(,|$)/ ;
2016-07-27 12:25:41 +08:00
function getTransitionInfo ( el , expectedType ) {
2016-07-17 13:53:44 +08:00
var styles = window . getComputedStyle ( el ) ;
var transitioneDelays = styles [ transitionProp + 'Delay' ] . split ( ', ' ) ;
var transitionDurations = styles [ transitionProp + 'Duration' ] . split ( ', ' ) ;
2016-07-27 12:25:41 +08:00
var transitionTimeout = getTimeout ( transitioneDelays , transitionDurations ) ;
2016-07-17 13:53:44 +08:00
var animationDelays = styles [ animationProp + 'Delay' ] . split ( ', ' ) ;
var animationDurations = styles [ animationProp + 'Duration' ] . split ( ', ' ) ;
var animationTimeout = getTimeout ( animationDelays , animationDurations ) ;
2016-07-27 12:25:41 +08:00
var type = void 0 ;
var timeout = 0 ;
var propCount = 0 ;
/* istanbul ignore if */
if ( expectedType === TRANSITION ) {
if ( transitionTimeout > 0 ) {
type = TRANSITION ;
timeout = transitionTimeout ;
propCount = transitionDurations . length ;
}
} else if ( expectedType === ANIMATION ) {
if ( animationTimeout > 0 ) {
type = ANIMATION ;
timeout = animationTimeout ;
propCount = animationDurations . length ;
}
} else {
timeout = Math . max ( transitionTimeout , animationTimeout ) ;
type = timeout > 0 ? transitionTimeout > animationTimeout ? TRANSITION : ANIMATION : null ;
propCount = type ? type === TRANSITION ? transitionDurations . length : animationDurations . length : 0 ;
}
var hasTransform = type === TRANSITION && transformRE . test ( styles [ transitionProp + 'Property' ] ) ;
2016-07-17 13:53:44 +08:00
return {
type : type ,
timeout : timeout ,
2016-07-27 12:25:41 +08:00
propCount : propCount ,
hasTransform : hasTransform
2016-07-17 13:53:44 +08:00
} ;
}
function getTimeout ( delays , durations ) {
return Math . max . apply ( null , durations . map ( function ( d , i ) {
return toMs ( d ) + toMs ( delays [ i ] ) ;
} ) ) ;
}
function toMs ( s ) {
return Number ( s . slice ( 0 , - 1 ) ) * 1000 ;
}
2016-04-27 01:29:27 +08:00
function enter ( vnode ) {
var el = vnode . elm ;
2016-07-17 13:53:44 +08:00
2016-04-27 01:29:27 +08:00
// call leave callback now
if ( el . _leaveCb ) {
el . _leaveCb . cancelled = true ;
el . _leaveCb ( ) ;
}
2016-06-28 10:25:12 +08:00
2016-07-17 13:53:44 +08:00
var data = resolveTransition ( vnode . data . transition ) ;
2016-04-27 01:29:27 +08:00
if ( ! data ) {
return ;
}
2016-07-17 13:53:44 +08:00
/* istanbul ignore if */
2016-08-10 12:55:30 +08:00
if ( el . _enterCb || el . nodeType !== 1 ) {
2016-07-17 13:53:44 +08:00
return ;
}
2016-04-27 01:29:27 +08:00
2016-07-17 13:53:44 +08:00
var css = data . css ;
2016-07-27 12:25:41 +08:00
var type = data . type ;
2016-07-17 13:53:44 +08:00
var enterClass = data . enterClass ;
var enterActiveClass = data . enterActiveClass ;
var appearClass = data . appearClass ;
var appearActiveClass = data . appearActiveClass ;
var beforeEnter = data . beforeEnter ;
var enter = data . enter ;
var afterEnter = data . afterEnter ;
var enterCancelled = data . enterCancelled ;
var beforeAppear = data . beforeAppear ;
var appear = data . appear ;
var afterAppear = data . afterAppear ;
var appearCancelled = data . appearCancelled ;
2016-04-27 01:29:27 +08:00
2016-08-06 06:14:22 +08:00
// activeInstance will always be the <transition> component managing this
// transition. One edge case to check is when the <transition> is placed
// as the root node of a child component. In that case we need to check
// <transition>'s parent for appear check.
var transitionNode = activeInstance . $vnode ;
var context = transitionNode && transitionNode . parent ? transitionNode . parent . context : activeInstance ;
var isAppear = ! context . _isMounted || ! vnode . isRootInsert ;
2016-04-27 01:29:27 +08:00
2016-06-28 10:25:12 +08:00
if ( isAppear && ! appear && appear !== '' ) {
return ;
}
2016-06-08 09:53:43 +08:00
var startClass = isAppear ? appearClass : enterClass ;
var activeClass = isAppear ? appearActiveClass : enterActiveClass ;
var beforeEnterHook = isAppear ? beforeAppear || beforeEnter : beforeEnter ;
2016-07-08 05:53:22 +08:00
var enterHook = isAppear ? typeof appear === 'function' ? appear : enter : enter ;
2016-06-08 09:53:43 +08:00
var afterEnterHook = isAppear ? afterAppear || afterEnter : afterEnter ;
var enterCancelledHook = isAppear ? appearCancelled || enterCancelled : enterCancelled ;
2016-07-17 13:53:44 +08:00
var expectsCSS = css !== false && ! isIE9 ;
var userWantsControl = enterHook &&
// enterHook may be a bound method which exposes
// the length of original fn as _length
( enterHook . _length || enterHook . length ) > 1 ;
2016-04-27 01:29:27 +08:00
var cb = el . _enterCb = once ( function ( ) {
2016-06-08 09:53:43 +08:00
if ( expectsCSS ) {
removeTransitionClass ( el , activeClass ) ;
2016-04-27 01:29:27 +08:00
}
if ( cb . cancelled ) {
2016-06-08 09:53:43 +08:00
if ( expectsCSS ) {
removeTransitionClass ( el , startClass ) ;
}
2016-07-17 13:53:44 +08:00
enterCancelledHook && enterCancelledHook ( el ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-07-17 13:53:44 +08:00
afterEnterHook && afterEnterHook ( el ) ;
2016-04-27 01:29:27 +08:00
}
el . _enterCb = null ;
} ) ;
2016-08-16 11:39:07 +08:00
if ( ! vnode . data . show ) {
// remove pending leave element on enter by injecting an insert hook
2016-08-21 02:04:54 +08:00
var hooks = vnode . data . hook || ( vnode . data . hook = { } ) ;
hooks . _transitionInsert = function ( ) {
2016-08-16 11:39:07 +08:00
var parent = el . parentNode ;
2016-08-21 02:04:54 +08:00
var pendingNode = parent && parent . _pending && parent . _pending [ vnode . key ] ;
2016-08-16 11:39:07 +08:00
if ( pendingNode && pendingNode . tag === vnode . tag && pendingNode . elm . _leaveCb ) {
pendingNode . elm . _leaveCb ( ) ;
}
enterHook && enterHook ( el , cb ) ;
2016-08-21 02:04:54 +08:00
} ;
if ( ! vnode . data . transitionInjected ) {
vnode . data . transitionInjected = true ;
mergeVNodeHook ( hooks , 'insert' , function ( ) {
hooks . _transitionInsert ( ) ;
} ) ;
}
2016-08-16 11:39:07 +08:00
}
2016-07-17 13:53:44 +08:00
// start enter transition
beforeEnterHook && beforeEnterHook ( el ) ;
2016-06-08 09:53:43 +08:00
if ( expectsCSS ) {
addTransitionClass ( el , startClass ) ;
2016-06-28 10:25:12 +08:00
addTransitionClass ( el , activeClass ) ;
2016-04-27 01:29:27 +08:00
nextFrame ( function ( ) {
2016-06-08 09:53:43 +08:00
removeTransitionClass ( el , startClass ) ;
2016-06-28 10:25:12 +08:00
if ( ! cb . cancelled && ! userWantsControl ) {
2016-07-27 12:25:41 +08:00
whenTransitionEnds ( el , type , cb ) ;
2016-04-27 01:29:27 +08:00
}
} ) ;
}
2016-07-17 13:53:44 +08:00
2016-08-16 11:39:07 +08:00
if ( vnode . data . show ) {
enterHook && enterHook ( el , cb ) ;
}
2016-06-08 09:53:43 +08:00
if ( ! expectsCSS && ! userWantsControl ) {
2016-04-27 01:29:27 +08:00
cb ( ) ;
}
}
function leave ( vnode , rm ) {
var el = vnode . elm ;
2016-07-17 13:53:44 +08:00
2016-04-27 01:29:27 +08:00
// call enter callback now
if ( el . _enterCb ) {
el . _enterCb . cancelled = true ;
el . _enterCb ( ) ;
}
2016-07-17 13:53:44 +08:00
var data = resolveTransition ( vnode . data . transition ) ;
2016-04-27 01:29:27 +08:00
if ( ! data ) {
return rm ( ) ;
}
2016-07-17 13:53:44 +08:00
/* istanbul ignore if */
2016-08-10 12:55:30 +08:00
if ( el . _leaveCb || el . nodeType !== 1 ) {
2016-07-17 13:53:44 +08:00
return ;
}
var css = data . css ;
2016-07-27 12:25:41 +08:00
var type = data . type ;
2016-07-17 13:53:44 +08:00
var leaveClass = data . leaveClass ;
var leaveActiveClass = data . leaveActiveClass ;
var beforeLeave = data . beforeLeave ;
var leave = data . leave ;
var afterLeave = data . afterLeave ;
var leaveCancelled = data . leaveCancelled ;
var delayLeave = data . delayLeave ;
2016-04-27 01:29:27 +08:00
2016-07-17 13:53:44 +08:00
var expectsCSS = css !== false && ! isIE9 ;
var userWantsControl = leave &&
// leave hook may be a bound method which exposes
// the length of original fn as _length
( leave . _length || leave . length ) > 1 ;
2016-04-27 01:29:27 +08:00
var cb = el . _leaveCb = once ( function ( ) {
2016-07-17 13:53:44 +08:00
if ( el . parentNode && el . parentNode . _pending ) {
el . parentNode . _pending [ vnode . key ] = null ;
}
2016-06-08 09:53:43 +08:00
if ( expectsCSS ) {
2016-04-27 01:29:27 +08:00
removeTransitionClass ( el , leaveActiveClass ) ;
}
if ( cb . cancelled ) {
2016-06-08 09:53:43 +08:00
if ( expectsCSS ) {
removeTransitionClass ( el , leaveClass ) ;
}
2016-07-17 13:53:44 +08:00
leaveCancelled && leaveCancelled ( el ) ;
2016-04-27 01:29:27 +08:00
} else {
rm ( ) ;
2016-07-17 13:53:44 +08:00
afterLeave && afterLeave ( el ) ;
2016-04-27 01:29:27 +08:00
}
el . _leaveCb = null ;
} ) ;
2016-06-08 09:53:43 +08:00
if ( delayLeave ) {
delayLeave ( performLeave ) ;
} else {
performLeave ( ) ;
}
function performLeave ( ) {
2016-07-17 13:53:44 +08:00
// the delayed leave may have already been cancelled
if ( cb . cancelled ) {
return ;
}
// record leaving element
if ( ! vnode . data . show ) {
( el . parentNode . _pending || ( el . parentNode . _pending = { } ) ) [ vnode . key ] = vnode ;
}
beforeLeave && beforeLeave ( el ) ;
2016-06-08 09:53:43 +08:00
if ( expectsCSS ) {
addTransitionClass ( el , leaveClass ) ;
2016-06-28 10:25:12 +08:00
addTransitionClass ( el , leaveActiveClass ) ;
2016-06-08 09:53:43 +08:00
nextFrame ( function ( ) {
removeTransitionClass ( el , leaveClass ) ;
2016-06-28 10:25:12 +08:00
if ( ! cb . cancelled && ! userWantsControl ) {
2016-07-27 12:25:41 +08:00
whenTransitionEnds ( el , type , cb ) ;
2016-06-08 09:53:43 +08:00
}
} ) ;
}
2016-07-17 13:53:44 +08:00
leave && leave ( el , cb ) ;
2016-06-08 09:53:43 +08:00
if ( ! expectsCSS && ! userWantsControl ) {
cb ( ) ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
}
2016-07-17 13:53:44 +08:00
function resolveTransition ( def ) {
if ( ! def ) {
return ;
2016-04-27 01:29:27 +08:00
}
2016-07-17 13:53:44 +08:00
/* istanbul ignore else */
if ( typeof def === 'object' ) {
var res = { } ;
if ( def . css !== false ) {
extend ( res , autoCssTransition ( def . name || 'v' ) ) ;
}
extend ( res , def ) ;
return res ;
} else if ( typeof def === 'string' ) {
return autoCssTransition ( def ) ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
}
var autoCssTransition = cached ( function ( name ) {
return {
enterClass : name + '-enter' ,
leaveClass : name + '-leave' ,
2016-06-08 09:53:43 +08:00
appearClass : name + '-enter' ,
2016-04-27 01:29:27 +08:00
enterActiveClass : name + '-enter-active' ,
2016-06-08 09:53:43 +08:00
leaveActiveClass : name + '-leave-active' ,
appearActiveClass : name + '-enter-active'
2016-04-27 01:29:27 +08:00
} ;
} ) ;
function once ( fn ) {
var called = false ;
return function ( ) {
if ( ! called ) {
called = true ;
fn ( ) ;
}
} ;
}
2016-07-17 13:53:44 +08:00
var transition = inBrowser ? {
2016-04-27 01:29:27 +08:00
create : function create ( _ , vnode ) {
2016-07-17 13:53:44 +08:00
if ( ! vnode . data . show ) {
2016-04-27 01:29:27 +08:00
enter ( vnode ) ;
}
} ,
remove : function remove ( vnode , rm ) {
2016-07-17 13:53:44 +08:00
/* istanbul ignore else */
if ( ! vnode . data . show ) {
2016-04-27 01:29:27 +08:00
leave ( vnode , rm ) ;
} else {
rm ( ) ;
}
}
2016-06-08 09:53:43 +08:00
} : { } ;
2016-07-24 10:48:09 +08:00
var platformModules = [ attrs , klass , events , domProps , style , transition ] ;
2016-06-08 09:53:43 +08:00
// the directive module should be applied last, after all
// built-in modules have been applied.
var modules = platformModules . concat ( baseModules ) ;
var patch = createPatchFunction ( { nodeOps : nodeOps , modules : modules } ) ;
2016-06-23 03:33:53 +08:00
var modelableTagRE = /^input|select|textarea|vue-component-[0-9]+(-[0-9a-zA-Z_\-]*)?$/ ;
2016-06-08 09:53:43 +08:00
/* istanbul ignore if */
if ( isIE9 ) {
// http://www.matts411.com/post/internet-explorer-9-oninput/
document . addEventListener ( 'selectionchange' , function ( ) {
var el = document . activeElement ;
if ( el && el . vmodel ) {
trigger ( el , 'input' ) ;
}
} ) ;
}
var model = {
bind : function bind ( el , binding , vnode ) {
if ( "development" !== 'production' ) {
2016-06-23 03:33:53 +08:00
if ( ! modelableTagRE . test ( vnode . tag ) ) {
2016-06-08 09:53:43 +08:00
warn ( 'v-model is not supported on element type: <' + vnode . tag + '>. ' + 'If you are working with contenteditable, it\'s recommended to ' + 'wrap a library dedicated for that purpose inside a custom component.' , vnode . context ) ;
}
}
if ( vnode . tag === 'select' ) {
2016-07-08 05:53:22 +08:00
setSelected ( el , binding , vnode . context ) ;
2016-06-08 09:53:43 +08:00
} else {
if ( ! isAndroid ) {
el . addEventListener ( 'compositionstart' , onCompositionStart ) ;
el . addEventListener ( 'compositionend' , onCompositionEnd ) ;
}
/* istanbul ignore if */
if ( isIE9 ) {
el . vmodel = true ;
}
}
} ,
2016-07-08 05:53:22 +08:00
componentUpdated : function componentUpdated ( el , binding , vnode ) {
2016-06-08 09:53:43 +08:00
if ( vnode . tag === 'select' ) {
2016-07-08 05:53:22 +08:00
setSelected ( el , binding , vnode . context ) ;
2016-06-08 09:53:43 +08:00
// in case the options rendered by v-for have changed,
// it's possible that the value is out-of-sync with the rendered options.
// detect such cases and filter out values that no longer has a matchig
// option in the DOM.
2016-07-08 05:53:22 +08:00
var needReset = el . multiple ? binding . value . some ( function ( v ) {
2016-06-08 09:53:43 +08:00
return hasNoMatchingOption ( v , el . options ) ;
2016-07-08 05:53:22 +08:00
} ) : hasNoMatchingOption ( binding . value , el . options ) ;
2016-06-08 09:53:43 +08:00
if ( needReset ) {
trigger ( el , 'change' ) ;
}
}
}
2016-04-27 01:29:27 +08:00
} ;
2016-07-08 05:53:22 +08:00
function setSelected ( el , binding , vm ) {
var value = binding . value ;
2016-06-08 09:53:43 +08:00
var isMultiple = el . multiple ;
if ( ! isMultiple ) {
el . selectedIndex = - 1 ;
2016-07-08 05:53:22 +08:00
} else if ( ! Array . isArray ( value ) ) {
"development" !== 'production' && warn ( '<select multiple v-model="' + binding . expression + '"> ' + ( 'expects an Array value for its binding, but got ' + Object . prototype . toString . call ( value ) . slice ( 8 , - 1 ) ) , vm ) ;
return ;
2016-06-08 09:53:43 +08:00
}
for ( var i = 0 , l = el . options . length ; i < l ; i ++ ) {
var option = el . options [ i ] ;
if ( isMultiple ) {
option . selected = value . indexOf ( getValue ( option ) ) > - 1 ;
} else {
if ( getValue ( option ) === value ) {
el . selectedIndex = i ;
break ;
}
}
}
}
function hasNoMatchingOption ( value , options ) {
for ( var i = 0 , l = options . length ; i < l ; i ++ ) {
if ( getValue ( options [ i ] ) === value ) {
return false ;
}
}
return true ;
}
function getValue ( option ) {
return '_value' in option ? option . _value : option . value || option . text ;
}
function onCompositionStart ( e ) {
e . target . composing = true ;
}
function onCompositionEnd ( e ) {
e . target . composing = false ;
trigger ( e . target , 'input' ) ;
}
function trigger ( el , type ) {
var e = document . createEvent ( 'HTMLEvents' ) ;
e . initEvent ( type , true , true ) ;
el . dispatchEvent ( e ) ;
}
2016-08-02 03:31:12 +08:00
// recursively search for possible transition defined inside the component root
function locateNode ( vnode ) {
return vnode . child && ( ! vnode . data || ! vnode . data . transition ) ? locateNode ( vnode . child . _vnode ) : vnode ;
}
2016-04-27 01:29:27 +08:00
var show = {
2016-06-08 09:53:43 +08:00
bind : function bind ( el , _ref , vnode ) {
var value = _ref . value ;
2016-08-02 03:31:12 +08:00
vnode = locateNode ( vnode ) ;
var transition = vnode . data && vnode . data . transition ;
2016-06-08 09:53:43 +08:00
if ( value && transition && transition . appear && ! isIE9 ) {
2016-04-27 01:29:27 +08:00
enter ( vnode ) ;
}
2016-08-21 02:04:54 +08:00
var originalDisplay = el . style . display === 'none' ? '' : el . style . display ;
2016-08-16 11:39:07 +08:00
el . style . display = value ? originalDisplay : 'none' ;
el . _ _vOriginalDisplay = originalDisplay ;
2016-04-27 01:29:27 +08:00
} ,
2016-06-08 09:53:43 +08:00
update : function update ( el , _ref2 , vnode ) {
var value = _ref2 . value ;
2016-08-10 12:55:30 +08:00
var oldValue = _ref2 . oldValue ;
2016-06-08 09:53:43 +08:00
2016-08-10 12:55:30 +08:00
/* istanbul ignore if */
if ( value === oldValue ) return ;
2016-08-02 03:31:12 +08:00
vnode = locateNode ( vnode ) ;
var transition = vnode . data && vnode . data . transition ;
2016-04-27 01:29:27 +08:00
if ( transition && ! isIE9 ) {
if ( value ) {
enter ( vnode ) ;
2016-08-16 11:39:07 +08:00
el . style . display = el . _ _vOriginalDisplay ;
2016-04-27 01:29:27 +08:00
} else {
leave ( vnode , function ( ) {
el . style . display = 'none' ;
} ) ;
}
} else {
2016-08-16 11:39:07 +08:00
el . style . display = value ? el . _ _vOriginalDisplay : 'none' ;
2016-04-27 01:29:27 +08:00
}
}
} ;
var platformDirectives = {
model : model ,
show : show
} ;
2016-07-17 13:53:44 +08:00
var transitionProps = {
name : String ,
appear : Boolean ,
css : Boolean ,
mode : String ,
2016-07-27 12:25:41 +08:00
type : String ,
2016-07-17 13:53:44 +08:00
enterClass : String ,
leaveClass : String ,
enterActiveClass : String ,
leaveActiveClass : String ,
appearClass : String ,
appearActiveClass : String
} ;
2016-08-10 12:55:30 +08:00
// in case the child is also an abstract component, e.g. <keep-alive>
// we want to recrusively retrieve the real component to be rendered
function getRealChild ( vnode ) {
var compOptions = vnode && vnode . componentOptions ;
if ( compOptions && compOptions . Ctor . options . abstract ) {
return getRealChild ( getFirstComponentChild ( compOptions . children ) ) ;
} else {
return vnode ;
}
}
2016-07-17 13:53:44 +08:00
function extractTransitionData ( comp ) {
var data = { } ;
var options = comp . $options ;
// props
for ( var key in options . propsData ) {
data [ key ] = comp [ key ] ;
}
// events.
// extract listeners and pass them directly to the transition methods
var listeners = options . _parentListeners ;
for ( var _key in listeners ) {
data [ camelize ( _key ) ] = listeners [ _key ] . fn ;
}
return data ;
}
2016-08-16 11:39:07 +08:00
function placeholder ( h , rawChild ) {
return ( /\d-keep-alive$/ . test ( rawChild . tag ) ? h ( 'keep-alive' ) : null
) ;
}
function hasParentTransition ( vnode ) {
while ( vnode = vnode . parent ) {
if ( vnode . data . transition ) {
return true ;
}
}
}
2016-07-17 13:53:44 +08:00
var Transition = {
name : 'transition' ,
props : transitionProps ,
2016-07-24 10:48:09 +08:00
abstract : true ,
2016-07-17 13:53:44 +08:00
render : function render ( h ) {
2016-06-08 09:53:43 +08:00
var _this = this ;
2016-04-27 01:29:27 +08:00
2016-07-17 13:53:44 +08:00
var children = this . $slots . default ;
if ( ! children ) {
return ;
}
// filter out text nodes (possible whitespaces)
children = children . filter ( function ( c ) {
return c . tag ;
} ) ;
2016-08-02 03:31:12 +08:00
/* istanbul ignore if */
2016-07-17 13:53:44 +08:00
if ( ! children . length ) {
return ;
}
// warn multiple elements
if ( "development" !== 'production' && children . length > 1 ) {
warn ( '<transition> can only be used on a single element. Use ' + '<transition-group> for lists.' , this . $parent ) ;
}
var mode = this . mode ;
// warn invalid mode
if ( "development" !== 'production' && mode && mode !== 'in-out' && mode !== 'out-in' ) {
warn ( 'invalid <transition> mode: ' + mode , this . $parent ) ;
}
var rawChild = children [ 0 ] ;
// if this is a component root node and the component's
// parent container node also has transition, skip.
2016-08-16 11:39:07 +08:00
if ( hasParentTransition ( this . $vnode ) ) {
2016-07-17 13:53:44 +08:00
return rawChild ;
}
// apply transition data to child
// use getRealChild() to ignore abstract components e.g. keep-alive
var child = getRealChild ( rawChild ) ;
/* istanbul ignore if */
2016-08-10 12:55:30 +08:00
if ( ! child ) {
return rawChild ;
}
2016-08-16 11:39:07 +08:00
if ( this . _leaving ) {
return placeholder ( h , rawChild ) ;
}
2016-08-10 12:55:30 +08:00
child . key = child . key == null ? '__v' + ( child . tag + this . _uid ) + '__' : child . key ;
2016-07-17 13:53:44 +08:00
var data = ( child . data || ( child . data = { } ) ) . transition = extractTransitionData ( this ) ;
var oldRawChild = this . _vnode ;
var oldChild = getRealChild ( oldRawChild ) ;
2016-08-21 02:04:54 +08:00
// mark v-show
// so that the transition module can hand over the control to the directive
if ( child . data . directives && child . data . directives . some ( function ( d ) {
return d . name === 'show' ;
} ) ) {
child . data . show = true ;
}
2016-07-24 10:48:09 +08:00
if ( oldChild && oldChild . data && oldChild . key !== child . key ) {
// replace old child transition data with fresh one
// important for dynamic transitions!
var oldData = oldChild . data . transition = extend ( { } , data ) ;
// handle transition mode
2016-07-17 13:53:44 +08:00
if ( mode === 'out-in' ) {
2016-08-16 11:39:07 +08:00
// return placeholder node and queue update when leave finishes
this . _leaving = true ;
2016-07-17 13:53:44 +08:00
mergeVNodeHook ( oldData , 'afterLeave' , function ( ) {
2016-08-16 11:39:07 +08:00
_this . _leaving = false ;
2016-07-17 13:53:44 +08:00
_this . $forceUpdate ( ) ;
2016-06-08 09:53:43 +08:00
} ) ;
2016-08-16 11:39:07 +08:00
return placeholder ( h , rawChild ) ;
2016-07-17 13:53:44 +08:00
} else if ( mode === 'in-out' ) {
2016-08-21 02:04:54 +08:00
var delayedLeave ;
var performLeave = function performLeave ( ) {
delayedLeave ( ) ;
} ;
mergeVNodeHook ( data , 'afterEnter' , performLeave ) ;
mergeVNodeHook ( data , 'enterCancelled' , performLeave ) ;
mergeVNodeHook ( oldData , 'delayLeave' , function ( leave ) {
delayedLeave = leave ;
} ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-07-17 13:53:44 +08:00
return rawChild ;
2016-04-27 01:29:27 +08:00
}
} ;
2016-07-24 10:48:09 +08:00
var props = extend ( {
2016-07-17 13:53:44 +08:00
tag : String ,
moveClass : String
} , transitionProps ) ;
2016-07-24 10:48:09 +08:00
delete props . mode ;
2016-07-17 13:53:44 +08:00
var TransitionGroup = {
2016-07-24 10:48:09 +08:00
props : props ,
2016-07-17 13:53:44 +08:00
render : function render ( h ) {
var tag = this . tag || this . $vnode . data . tag || 'span' ;
var map = Object . create ( null ) ;
var prevChildren = this . prevChildren = this . children ;
var rawChildren = this . $slots . default || [ ] ;
var children = this . children = [ ] ;
var transitionData = extractTransitionData ( this ) ;
for ( var i = 0 ; i < rawChildren . length ; i ++ ) {
var c = rawChildren [ i ] ;
if ( c . tag ) {
if ( c . key != null ) {
children . push ( c ) ;
map [ c . key ] = c ; ( c . data || ( c . data = { } ) ) . transition = transitionData ;
} else if ( "development" !== 'production' ) {
var opts = c . componentOptions ;
var name = opts ? opts . Ctor . options . name || opts . tag : c . tag ;
warn ( '<transition-group> children must be keyed: <' + name + '>' ) ;
}
}
}
if ( prevChildren ) {
var kept = [ ] ;
var removed = [ ] ;
for ( var _i = 0 ; _i < prevChildren . length ; _i ++ ) {
var _c = prevChildren [ _i ] ;
2016-07-24 10:48:09 +08:00
_c . data . transition = transitionData ;
2016-07-17 13:53:44 +08:00
_c . data . pos = _c . elm . getBoundingClientRect ( ) ;
if ( map [ _c . key ] ) {
kept . push ( _c ) ;
} else {
removed . push ( _c ) ;
}
}
this . kept = h ( tag , null , kept ) ;
this . removed = removed ;
}
return h ( tag , null , children ) ;
} ,
beforeUpdate : function beforeUpdate ( ) {
// force removing pass
this . _ _patch _ _ ( this . _vnode , this . kept , false , // hydrating
true // removeOnly (!important, avoids unnecessary moves)
) ;
this . _vnode = this . kept ;
} ,
updated : function updated ( ) {
var children = this . prevChildren ;
var moveClass = this . moveClass || this . name + '-move' ;
if ( ! children . length || ! this . hasMove ( children [ 0 ] . elm , moveClass ) ) {
return ;
}
children . forEach ( function ( c ) {
2016-07-24 10:48:09 +08:00
/* istanbul ignore if */
if ( c . elm . _moveCb ) {
c . elm . _moveCb ( ) ;
}
/* istanbul ignore if */
if ( c . elm . _enterCb ) {
c . elm . _enterCb ( ) ;
}
2016-07-17 13:53:44 +08:00
var oldPos = c . data . pos ;
2016-07-24 10:48:09 +08:00
var newPos = c . data . pos = c . elm . getBoundingClientRect ( ) ;
2016-07-17 13:53:44 +08:00
var dx = oldPos . left - newPos . left ;
var dy = oldPos . top - newPos . top ;
if ( dx || dy ) {
c . data . moved = true ;
var s = c . elm . style ;
s . transform = s . WebkitTransform = 'translate(' + dx + 'px,' + dy + 'px)' ;
s . transitionDuration = '0s' ;
}
} ) ;
// force reflow to put everything in position
var f = document . body . offsetHeight ; // eslint-disable-line
children . forEach ( function ( c ) {
if ( c . data . moved ) {
2016-08-21 02:04:54 +08:00
var el = c . elm ;
var s = el . style ;
addTransitionClass ( el , moveClass ) ;
s . transform = s . WebkitTransform = s . transitionDuration = '' ;
el . _moveDest = c . data . pos ;
el . addEventListener ( transitionEndEvent , el . _moveCb = function cb ( e ) {
if ( ! e || /transform$/ . test ( e . propertyName ) ) {
el . removeEventListener ( transitionEndEvent , cb ) ;
el . _moveCb = null ;
removeTransitionClass ( el , moveClass ) ;
}
} ) ;
2016-07-17 13:53:44 +08:00
}
} ) ;
} ,
methods : {
hasMove : function hasMove ( el , moveClass ) {
/* istanbul ignore if */
if ( ! hasTransition ) {
return false ;
}
if ( this . _hasMove != null ) {
return this . _hasMove ;
}
addTransitionClass ( el , moveClass ) ;
var info = getTransitionInfo ( el ) ;
removeTransitionClass ( el , moveClass ) ;
return this . _hasMove = info . hasTransform ;
}
2016-06-08 09:53:43 +08:00
}
2016-07-17 13:53:44 +08:00
} ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
var platformComponents = {
2016-07-17 13:53:44 +08:00
Transition : Transition ,
TransitionGroup : TransitionGroup
2016-06-08 09:53:43 +08:00
} ;
2016-04-27 01:29:27 +08:00
// install platform specific utils
Vue . config . isUnknownElement = isUnknownElement ;
Vue . config . isReservedTag = isReservedTag ;
2016-06-28 10:25:12 +08:00
Vue . config . getTagNamespace = getTagNamespace ;
2016-06-08 09:53:43 +08:00
Vue . config . mustUseProp = mustUseProp ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
// install platform runtime directives & components
extend ( Vue . options . directives , platformDirectives ) ;
extend ( Vue . options . components , platformComponents ) ;
2016-04-27 01:29:27 +08:00
// install platform patch function
2016-06-08 09:53:43 +08:00
Vue . prototype . _ _patch _ _ = config . _isServer ? noop : patch ;
2016-04-27 01:29:27 +08:00
// wrap mount
2016-06-08 09:53:43 +08:00
Vue . prototype . $mount = function ( el , hydrating ) {
2016-06-28 10:25:12 +08:00
el = el && ! config . _isServer ? query ( el ) : undefined ;
return this . _mount ( el , hydrating ) ;
2016-04-27 01:29:27 +08:00
} ;
2016-06-23 03:33:53 +08:00
// devtools global hook
/* istanbul ignore next */
setTimeout ( function ( ) {
if ( config . devtools ) {
if ( devtools ) {
devtools . emit ( 'init' , Vue ) ;
} else if ( "development" !== 'production' && inBrowser && /Chrome\/\d+/ . test ( window . navigator . userAgent ) ) {
console . log ( 'Download the Vue Devtools for a better development experience:\n' + 'https://github.com/vuejs/vue-devtools' ) ;
}
}
} , 0 ) ;
2016-04-27 01:29:27 +08:00
var decoder = document . createElement ( 'div' ) ;
2016-07-27 12:25:41 +08:00
function decodeHTML ( html ) {
2016-04-27 01:29:27 +08:00
decoder . innerHTML = html ;
return decoder . textContent ;
}
// Regular Expressions for parsing tags and attributes
var singleAttrIdentifier = /([^\s"'<>\/=]+)/ ;
2016-07-26 10:07:26 +08:00
var singleAttrAssign = /(?:=)/ ;
2016-04-27 01:29:27 +08:00
var singleAttrValues = [
// attr value double quotes
/"([^"]*)"+/ . source ,
// attr value, single quotes
/'([^']*)'+/ . source ,
// attr value, no quotes
/([^\s"'=<>`]+)/ . source ] ;
2016-07-26 10:07:26 +08:00
var attribute = new RegExp ( '^\\s*' + singleAttrIdentifier . source + '(?:\\s*(' + singleAttrAssign . source + ')' + '\\s*(?:' + singleAttrValues . join ( '|' ) + '))?' ) ;
2016-04-27 01:29:27 +08:00
// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName
// but for Vue templates we can enforce a simple charset
var ncname = '[a-zA-Z_][\\w\\-\\.]*' ;
var qnameCapture = '((?:' + ncname + '\\:)?' + ncname + ')' ;
var startTagOpen = new RegExp ( '^<' + qnameCapture ) ;
var startTagClose = /^\s*(\/?)>/ ;
var endTag = new RegExp ( '^<\\/' + qnameCapture + '[^>]*>' ) ;
var doctype = /^<!DOCTYPE [^>]+>/i ;
var IS _REGEX _CAPTURING _BROKEN = false ;
'x' . replace ( /x(.)?/g , function ( m , g ) {
IS _REGEX _CAPTURING _BROKEN = g === '' ;
} ) ;
// Special Elements (can contain anything)
2016-06-14 07:36:46 +08:00
var isSpecialTag = makeMap ( 'script,style' , true ) ;
2016-04-27 01:29:27 +08:00
var reCache = { } ;
2016-07-27 12:25:41 +08:00
var ampRE = /&/g ;
var ltRE = /</g ;
var gtRE = />/g ;
2016-08-10 12:55:30 +08:00
var quoteRE = /"/g ;
2016-07-27 12:25:41 +08:00
function decodeAttr ( value , shouldDecodeTags ) {
if ( shouldDecodeTags ) {
value = value . replace ( ltRE , '<' ) . replace ( gtRE , '>' ) ;
}
2016-08-10 12:55:30 +08:00
return value . replace ( ampRE , '&' ) . replace ( quoteRE , '"' ) ;
2016-07-27 12:25:41 +08:00
}
2016-07-26 10:07:26 +08:00
function parseHTML ( html , options ) {
2016-04-27 01:29:27 +08:00
var stack = [ ] ;
2016-07-26 10:07:26 +08:00
var expectHTML = options . expectHTML ;
var isUnaryTag = options . isUnaryTag || no ;
2016-07-27 12:25:41 +08:00
var isFromDOM = options . isFromDOM ;
var shouldDecodeTags = options . shouldDecodeTags ;
2016-06-14 07:36:46 +08:00
var index = 0 ;
2016-04-27 01:29:27 +08:00
var last = void 0 ,
lastTag = void 0 ;
while ( html ) {
last = html ;
// Make sure we're not in a script or style element
2016-06-08 09:53:43 +08:00
if ( ! lastTag || ! isSpecialTag ( lastTag ) ) {
2016-04-27 01:29:27 +08:00
var textEnd = html . indexOf ( '<' ) ;
if ( textEnd === 0 ) {
// Comment:
if ( /^<!--/ . test ( html ) ) {
var commentEnd = html . indexOf ( '-->' ) ;
if ( commentEnd >= 0 ) {
2016-06-14 07:36:46 +08:00
advance ( commentEnd + 3 ) ;
2016-04-27 01:29:27 +08:00
continue ;
}
}
// http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
if ( /^<!\[/ . test ( html ) ) {
var conditionalEnd = html . indexOf ( ']>' ) ;
if ( conditionalEnd >= 0 ) {
2016-06-14 07:36:46 +08:00
advance ( conditionalEnd + 2 ) ;
2016-04-27 01:29:27 +08:00
continue ;
}
}
// Doctype:
var doctypeMatch = html . match ( doctype ) ;
if ( doctypeMatch ) {
2016-06-14 07:36:46 +08:00
advance ( doctypeMatch [ 0 ] . length ) ;
2016-04-27 01:29:27 +08:00
continue ;
}
// End tag:
var endTagMatch = html . match ( endTag ) ;
if ( endTagMatch ) {
2016-06-14 07:36:46 +08:00
var curIndex = index ;
advance ( endTagMatch [ 0 ] . length ) ;
parseEndTag ( endTagMatch [ 0 ] , endTagMatch [ 1 ] , curIndex , index ) ;
2016-04-27 01:29:27 +08:00
continue ;
}
// Start tag:
2016-06-14 07:36:46 +08:00
var startTagMatch = parseStartTag ( ) ;
2016-04-27 01:29:27 +08:00
if ( startTagMatch ) {
handleStartTag ( startTagMatch ) ;
continue ;
}
}
2016-06-08 09:53:43 +08:00
var text = void 0 ;
2016-04-27 01:29:27 +08:00
if ( textEnd >= 0 ) {
text = html . substring ( 0 , textEnd ) ;
2016-06-14 07:36:46 +08:00
advance ( textEnd ) ;
2016-04-27 01:29:27 +08:00
} else {
text = html ;
html = '' ;
}
2016-07-26 10:07:26 +08:00
if ( options . chars ) {
options . chars ( text ) ;
2016-04-27 01:29:27 +08:00
}
} else {
2016-08-21 02:04:54 +08:00
var stackedTag = lastTag . toLowerCase ( ) ;
var reStackedTag = reCache [ stackedTag ] || ( reCache [ stackedTag ] = new RegExp ( '([\\s\\S]*?)(</' + stackedTag + '[^>]*>)' , 'i' ) ) ;
var endTagLength = 0 ;
var rest = html . replace ( reStackedTag , function ( all , text , endTag ) {
endTagLength = endTag . length ;
if ( stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript' ) {
text = text . replace ( /<!--([\s\S]*?)-->/g , '$1' ) . replace ( /<!\[CDATA\[([\s\S]*?)\]\]>/g , '$1' ) ;
}
if ( options . chars ) {
options . chars ( text ) ;
}
return '' ;
} ) ;
index += html . length - rest . length ;
html = rest ;
parseEndTag ( '</' + stackedTag + '>' , stackedTag , index - endTagLength , index ) ;
2016-04-27 01:29:27 +08:00
}
if ( html === last ) {
throw new Error ( 'Error parsing template:\n\n' + html ) ;
}
}
2016-06-14 07:36:46 +08:00
// Clean up any remaining tags
parseEndTag ( ) ;
function advance ( n ) {
index += n ;
html = html . substring ( n ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-14 07:36:46 +08:00
function parseStartTag ( ) {
var start = html . match ( startTagOpen ) ;
2016-04-27 01:29:27 +08:00
if ( start ) {
var match = {
tagName : start [ 1 ] ,
2016-06-14 07:36:46 +08:00
attrs : [ ] ,
start : index
2016-04-27 01:29:27 +08:00
} ;
2016-06-14 07:36:46 +08:00
advance ( start [ 0 ] . length ) ;
2016-06-08 09:53:43 +08:00
var end = void 0 ,
attr = void 0 ;
2016-06-14 07:36:46 +08:00
while ( ! ( end = html . match ( startTagClose ) ) && ( attr = html . match ( attribute ) ) ) {
advance ( attr [ 0 ] . length ) ;
2016-04-27 01:29:27 +08:00
match . attrs . push ( attr ) ;
}
if ( end ) {
match . unarySlash = end [ 1 ] ;
2016-06-14 07:36:46 +08:00
advance ( end [ 0 ] . length ) ;
match . end = index ;
2016-04-27 01:29:27 +08:00
return match ;
}
}
}
function handleStartTag ( match ) {
var tagName = match . tagName ;
var unarySlash = match . unarySlash ;
if ( expectHTML ) {
if ( lastTag === 'p' && isNonPhrasingTag ( tagName ) ) {
parseEndTag ( '' , lastTag ) ;
}
if ( canBeLeftOpenTag ( tagName ) && lastTag === tagName ) {
parseEndTag ( '' , tagName ) ;
}
}
var unary = isUnaryTag ( tagName ) || tagName === 'html' && lastTag === 'head' || ! ! unarySlash ;
2016-06-08 09:53:43 +08:00
var l = match . attrs . length ;
var attrs = new Array ( l ) ;
for ( var i = 0 ; i < l ; i ++ ) {
var args = match . attrs [ i ] ;
2016-04-27 01:29:27 +08:00
// hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778
if ( IS _REGEX _CAPTURING _BROKEN && args [ 0 ] . indexOf ( '""' ) === - 1 ) {
if ( args [ 3 ] === '' ) {
delete args [ 3 ] ;
}
if ( args [ 4 ] === '' ) {
delete args [ 4 ] ;
}
if ( args [ 5 ] === '' ) {
delete args [ 5 ] ;
}
}
2016-07-26 10:07:26 +08:00
var value = args [ 3 ] || args [ 4 ] || args [ 5 ] || '' ;
2016-06-08 09:53:43 +08:00
attrs [ i ] = {
2016-04-27 01:29:27 +08:00
name : args [ 1 ] ,
2016-07-27 12:25:41 +08:00
value : isFromDOM ? decodeAttr ( value , shouldDecodeTags ) : value
2016-04-27 01:29:27 +08:00
} ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
if ( ! unary ) {
stack . push ( { tag : tagName , attrs : attrs } ) ;
lastTag = tagName ;
unarySlash = '' ;
}
2016-07-26 10:07:26 +08:00
if ( options . start ) {
options . start ( tagName , attrs , unary , match . start , match . end ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-14 07:36:46 +08:00
function parseEndTag ( tag , tagName , start , end ) {
2016-06-08 09:53:43 +08:00
var pos = void 0 ;
2016-06-14 07:36:46 +08:00
if ( start == null ) start = index ;
if ( end == null ) end = index ;
2016-04-27 01:29:27 +08:00
// Find the closest opened tag of the same type
if ( tagName ) {
var needle = tagName . toLowerCase ( ) ;
for ( pos = stack . length - 1 ; pos >= 0 ; pos -- ) {
if ( stack [ pos ] . tag . toLowerCase ( ) === needle ) {
break ;
}
}
} else {
// If no tag name is provided, clean shop
pos = 0 ;
}
if ( pos >= 0 ) {
// Close all the open elements, up the stack
for ( var i = stack . length - 1 ; i >= pos ; i -- ) {
2016-07-26 10:07:26 +08:00
if ( options . end ) {
options . end ( stack [ i ] . tag , start , end ) ;
2016-04-27 01:29:27 +08:00
}
}
// Remove the open elements from the stack
stack . length = pos ;
lastTag = pos && stack [ pos - 1 ] . tag ;
} else if ( tagName . toLowerCase ( ) === 'br' ) {
2016-07-26 10:07:26 +08:00
if ( options . start ) {
options . start ( tagName , [ ] , true , start , end ) ;
2016-04-27 01:29:27 +08:00
}
} else if ( tagName . toLowerCase ( ) === 'p' ) {
2016-07-26 10:07:26 +08:00
if ( options . start ) {
options . start ( tagName , [ ] , false , start , end ) ;
2016-04-27 01:29:27 +08:00
}
2016-07-26 10:07:26 +08:00
if ( options . end ) {
options . end ( tagName , start , end ) ;
2016-04-27 01:29:27 +08:00
}
}
}
}
2016-06-08 09:53:43 +08:00
function parseFilters ( exp ) {
var inSingle = false ;
var inDouble = false ;
var curly = 0 ;
var square = 0 ;
var paren = 0 ;
var lastFilterIndex = 0 ;
var c = void 0 ,
prev = void 0 ,
i = void 0 ,
expression = void 0 ,
filters = void 0 ;
for ( i = 0 ; i < exp . length ; i ++ ) {
prev = c ;
c = exp . charCodeAt ( i ) ;
if ( inSingle ) {
// check single quote
if ( c === 0x27 && prev !== 0x5C ) inSingle = ! inSingle ;
} else if ( inDouble ) {
// check double quote
if ( c === 0x22 && prev !== 0x5C ) inDouble = ! inDouble ;
} else if ( c === 0x7C && // pipe
exp . charCodeAt ( i + 1 ) !== 0x7C && exp . charCodeAt ( i - 1 ) !== 0x7C && ! curly && ! square && ! paren ) {
if ( expression === undefined ) {
// first filter, end of expression
lastFilterIndex = i + 1 ;
expression = exp . slice ( 0 , i ) . trim ( ) ;
} else {
pushFilter ( ) ;
}
} else {
switch ( c ) {
case 0x22 :
inDouble = true ; break ; // "
case 0x27 :
inSingle = true ; break ; // '
case 0x28 :
paren ++ ; break ; // (
case 0x29 :
paren -- ; break ; // )
case 0x5B :
square ++ ; break ; // [
case 0x5D :
square -- ; break ; // ]
case 0x7B :
curly ++ ; break ; // {
case 0x7D :
curly -- ; break ; // }
}
}
}
if ( expression === undefined ) {
expression = exp . slice ( 0 , i ) . trim ( ) ;
} else if ( lastFilterIndex !== 0 ) {
pushFilter ( ) ;
}
function pushFilter ( ) {
( filters || ( filters = [ ] ) ) . push ( exp . slice ( lastFilterIndex , i ) . trim ( ) ) ;
lastFilterIndex = i + 1 ;
}
if ( filters ) {
for ( i = 0 ; i < filters . length ; i ++ ) {
expression = wrapFilter ( expression , filters [ i ] ) ;
}
}
return expression ;
}
function wrapFilter ( exp , filter ) {
var i = filter . indexOf ( '(' ) ;
if ( i < 0 ) {
// _f: resolveFilter
return '_f("' + filter + '")(' + exp + ')' ;
} else {
var name = filter . slice ( 0 , i ) ;
var args = filter . slice ( i + 1 ) ;
return '_f("' + name + '")(' + exp + ',' + args ;
}
}
var defaultTagRE = /\{\{((?:.|\\n)+?)\}\}/g ;
var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g ;
2016-04-27 01:29:27 +08:00
2016-06-08 09:53:43 +08:00
var buildRegex = cached ( function ( delimiters ) {
var open = delimiters [ 0 ] . replace ( regexEscapeRE , '\\$&' ) ;
var close = delimiters [ 1 ] . replace ( regexEscapeRE , '\\$&' ) ;
return new RegExp ( open + '((?:.|\\n)+?)' + close , 'g' ) ;
} ) ;
function parseText ( text , delimiters ) {
var tagRE = delimiters ? buildRegex ( delimiters ) : defaultTagRE ;
2016-04-27 01:29:27 +08:00
if ( ! tagRE . test ( text ) ) {
2016-06-08 09:53:43 +08:00
return ;
2016-04-27 01:29:27 +08:00
}
var tokens = [ ] ;
var lastIndex = tagRE . lastIndex = 0 ;
2016-06-08 09:53:43 +08:00
var match = void 0 ,
index = void 0 ;
2016-04-27 01:29:27 +08:00
while ( match = tagRE . exec ( text ) ) {
index = match . index ;
// push text token
if ( index > lastIndex ) {
tokens . push ( JSON . stringify ( text . slice ( lastIndex , index ) ) ) ;
}
// tag token
2016-06-08 09:53:43 +08:00
var exp = parseFilters ( match [ 1 ] . trim ( ) ) ;
tokens . push ( '_s(' + exp + ')' ) ;
2016-04-27 01:29:27 +08:00
lastIndex = index + match [ 0 ] . length ;
}
if ( lastIndex < text . length ) {
tokens . push ( JSON . stringify ( text . slice ( lastIndex ) ) ) ;
}
return tokens . join ( '+' ) ;
}
2016-06-08 09:53:43 +08:00
function baseWarn ( msg ) {
console . error ( '[Vue parser]: ' + msg ) ;
}
2016-06-11 07:23:32 +08:00
function pluckModuleFunction ( modules , key ) {
return modules ? modules . map ( function ( m ) {
return m [ key ] ;
} ) . filter ( function ( _ ) {
return _ ;
} ) : [ ] ;
}
2016-04-27 01:29:27 +08:00
function addProp ( el , name , value ) {
( el . props || ( el . props = [ ] ) ) . push ( { name : name , value : value } ) ;
}
function addAttr ( el , name , value ) {
( el . attrs || ( el . attrs = [ ] ) ) . push ( { name : name , value : value } ) ;
}
function addDirective ( el , name , value , arg , modifiers ) {
( el . directives || ( el . directives = [ ] ) ) . push ( { name : name , value : value , arg : arg , modifiers : modifiers } ) ;
}
2016-07-17 13:53:44 +08:00
function addHook ( el , name , code ) {
2016-04-27 01:29:27 +08:00
var hooks = el . hooks || ( el . hooks = { } ) ;
var hook = hooks [ name ] ;
2016-06-08 09:53:43 +08:00
/* istanbul ignore if */
2016-04-27 01:29:27 +08:00
if ( hook ) {
hook . push ( code ) ;
} else {
hooks [ name ] = [ code ] ;
}
}
2016-08-21 02:04:54 +08:00
function addHandler ( el , name , value , modifiers , important ) {
2016-04-27 01:29:27 +08:00
// check capture modifier
if ( modifiers && modifiers . capture ) {
delete modifiers . capture ;
name = '!' + name ; // mark the event as captured
}
2016-07-24 10:48:09 +08:00
var events = void 0 ;
if ( modifiers && modifiers . native ) {
delete modifiers . native ;
events = el . nativeEvents || ( el . nativeEvents = { } ) ;
} else {
events = el . events || ( el . events = { } ) ;
}
2016-04-27 01:29:27 +08:00
var newHandler = { value : value , modifiers : modifiers } ;
var handlers = events [ name ] ;
2016-06-08 09:53:43 +08:00
/* istanbul ignore if */
if ( Array . isArray ( handlers ) ) {
2016-08-21 02:04:54 +08:00
important ? handlers . unshift ( newHandler ) : handlers . push ( newHandler ) ;
2016-04-27 01:29:27 +08:00
} else if ( handlers ) {
2016-08-21 02:04:54 +08:00
events [ name ] = important ? [ newHandler , handlers ] : [ handlers , newHandler ] ;
2016-04-27 01:29:27 +08:00
} else {
events [ name ] = newHandler ;
}
}
function getBindingAttr ( el , name , getStatic ) {
2016-06-08 09:53:43 +08:00
var dynamicValue = getAndRemoveAttr ( el , ':' + name ) || getAndRemoveAttr ( el , 'v-bind:' + name ) ;
if ( dynamicValue != null ) {
return dynamicValue ;
} else if ( getStatic !== false ) {
var staticValue = getAndRemoveAttr ( el , name ) ;
if ( staticValue != null ) {
return JSON . stringify ( staticValue ) ;
}
}
2016-04-27 01:29:27 +08:00
}
function getAndRemoveAttr ( el , name ) {
var val = void 0 ;
if ( ( val = el . attrsMap [ name ] ) != null ) {
var list = el . attrsList ;
for ( var i = 0 , l = list . length ; i < l ; i ++ ) {
if ( list [ i ] . name === name ) {
list . splice ( i , 1 ) ;
break ;
}
}
}
return val ;
}
var dirRE = /^v-|^@|^:/ ;
2016-06-16 02:22:40 +08:00
var forAliasRE = /(.*)\s+(?:in|of)\s+(.*)/ ;
var forIteratorRE = /\(([^,]*),([^,]*)(?:,([^,]*))?\)/ ;
2016-04-27 01:29:27 +08:00
var bindRE = /^:|^v-bind:/ ;
var onRE = /^@|^v-on:/ ;
var argRE = /:(.*)$/ ;
var modifierRE = /\.[^\.]+/g ;
var decodeHTMLCached = cached ( decodeHTML ) ;
2016-06-08 09:53:43 +08:00
// configurable state
2016-04-27 01:29:27 +08:00
var warn$1 = void 0 ;
var platformGetTagNamespace = void 0 ;
var platformMustUseProp = void 0 ;
2016-08-02 03:31:12 +08:00
var platformIsPreTag = void 0 ;
2016-07-27 12:25:41 +08:00
var preTransforms = void 0 ;
2016-06-11 07:23:32 +08:00
var transforms = void 0 ;
2016-07-27 12:25:41 +08:00
var postTransforms = void 0 ;
2016-06-08 09:53:43 +08:00
var delimiters = void 0 ;
2016-08-16 11:39:07 +08:00
var seenSlots = void 0 ;
2016-04-27 01:29:27 +08:00
/ * *
* Convert HTML string to AST .
* /
function parse ( template , options ) {
warn$1 = options . warn || baseWarn ;
2016-06-08 09:53:43 +08:00
platformGetTagNamespace = options . getTagNamespace || no ;
platformMustUseProp = options . mustUseProp || no ;
2016-08-02 03:31:12 +08:00
platformIsPreTag = options . isPreTag || no ;
2016-07-27 12:25:41 +08:00
preTransforms = pluckModuleFunction ( options . modules , 'preTransformNode' ) ;
2016-06-11 07:23:32 +08:00
transforms = pluckModuleFunction ( options . modules , 'transformNode' ) ;
2016-07-27 12:25:41 +08:00
postTransforms = pluckModuleFunction ( options . modules , 'postTransformNode' ) ;
2016-06-08 09:53:43 +08:00
delimiters = options . delimiters ;
2016-08-16 11:39:07 +08:00
seenSlots = Object . create ( null ) ;
2016-04-27 01:29:27 +08:00
var stack = [ ] ;
2016-06-16 02:22:40 +08:00
var preserveWhitespace = options . preserveWhitespace !== false ;
2016-04-27 01:29:27 +08:00
var root = void 0 ;
var currentParent = void 0 ;
2016-08-02 03:31:12 +08:00
var inVPre = false ;
2016-04-27 01:29:27 +08:00
var inPre = false ;
var warned = false ;
parseHTML ( template , {
expectHTML : options . expectHTML ,
isUnaryTag : options . isUnaryTag ,
2016-07-27 12:25:41 +08:00
isFromDOM : options . isFromDOM ,
shouldDecodeTags : options . shouldDecodeTags ,
2016-04-27 01:29:27 +08:00
start : function start ( tag , attrs , unary ) {
2016-06-08 09:53:43 +08:00
// check namespace.
// inherit parent ns if there is one
var ns = currentParent && currentParent . ns || platformGetTagNamespace ( tag ) ;
// handle IE svg bug
/* istanbul ignore if */
if ( options . isIE && ns === 'svg' ) {
attrs = guardIESVGBug ( attrs ) ;
}
2016-04-27 01:29:27 +08:00
var element = {
2016-06-08 09:53:43 +08:00
type : 1 ,
2016-04-27 01:29:27 +08:00
tag : tag ,
attrsList : attrs ,
attrsMap : makeAttrsMap ( attrs ) ,
parent : currentParent ,
children : [ ]
} ;
2016-06-08 09:53:43 +08:00
if ( ns ) {
2016-04-27 01:29:27 +08:00
element . ns = ns ;
}
2016-08-16 11:39:07 +08:00
if ( "client" !== 'server' && isForbiddenTag ( element ) ) {
2016-06-08 09:53:43 +08:00
element . forbidden = true ;
"development" !== 'production' && warn$1 ( 'Templates should only be responsbile for mapping the state to the ' + 'UI. Avoid placing tags with side-effects in your templates, such as ' + ( '<' + tag + '>.' ) ) ;
}
2016-07-27 12:25:41 +08:00
// apply pre-transforms
for ( var i = 0 ; i < preTransforms . length ; i ++ ) {
preTransforms [ i ] ( element , options ) ;
}
2016-08-02 03:31:12 +08:00
if ( ! inVPre ) {
2016-04-27 01:29:27 +08:00
processPre ( element ) ;
if ( element . pre ) {
2016-08-02 03:31:12 +08:00
inVPre = true ;
2016-04-27 01:29:27 +08:00
}
}
2016-08-02 03:31:12 +08:00
if ( platformIsPreTag ( element . tag ) ) {
inPre = true ;
}
if ( inVPre ) {
2016-04-27 01:29:27 +08:00
processRawAttrs ( element ) ;
} else {
processFor ( element ) ;
processIf ( element ) ;
processOnce ( element ) ;
2016-06-18 02:22:51 +08:00
2016-04-27 01:29:27 +08:00
// determine whether this is a plain element after
2016-06-18 02:22:51 +08:00
// removing structural attributes
2016-06-08 09:53:43 +08:00
element . plain = ! element . key && ! attrs . length ;
2016-06-18 02:22:51 +08:00
processKey ( element ) ;
processRef ( element ) ;
2016-04-27 01:29:27 +08:00
processSlot ( element ) ;
processComponent ( element ) ;
2016-07-27 12:25:41 +08:00
for ( var _i = 0 ; _i < transforms . length ; _i ++ ) {
transforms [ _i ] ( element , options ) ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
processAttrs ( element ) ;
}
2016-08-02 03:31:12 +08:00
function checkRootConstraints ( el ) {
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
2016-08-02 03:31:12 +08:00
if ( el . tag === 'slot' || el . tag === 'template' ) {
warn$1 ( 'Cannot use <' + el . tag + '> as component root element because it may ' + 'contain multiple nodes:\n' + template ) ;
2016-06-08 09:53:43 +08:00
}
2016-08-02 03:31:12 +08:00
if ( el . attrsMap . hasOwnProperty ( 'v-for' ) ) {
2016-06-18 02:22:51 +08:00
warn$1 ( 'Cannot use v-for on stateful component root element because ' + 'it renders multiple elements:\n' + template ) ;
2016-06-08 09:53:43 +08:00
}
}
2016-08-02 03:31:12 +08:00
}
// tree management
if ( ! root ) {
root = element ;
checkRootConstraints ( root ) ;
2016-04-27 01:29:27 +08:00
} else if ( "development" !== 'production' && ! stack . length && ! warned ) {
2016-08-02 03:31:12 +08:00
// allow 2 root elements with v-if and v-else
if ( root . attrsMap . hasOwnProperty ( 'v-if' ) && element . attrsMap . hasOwnProperty ( 'v-else' ) ) {
checkRootConstraints ( element ) ;
} else {
warned = true ;
warn$1 ( 'Component template should contain exactly one root element:\n\n' + template ) ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
if ( currentParent && ! element . forbidden ) {
2016-04-27 01:29:27 +08:00
if ( element . else ) {
processElse ( element , currentParent ) ;
} else {
currentParent . children . push ( element ) ;
element . parent = currentParent ;
}
}
if ( ! unary ) {
currentParent = element ;
stack . push ( element ) ;
}
2016-07-27 12:25:41 +08:00
// apply post-transforms
for ( var _i2 = 0 ; _i2 < postTransforms . length ; _i2 ++ ) {
postTransforms [ _i2 ] ( element , options ) ;
}
2016-04-27 01:29:27 +08:00
} ,
2016-06-08 09:53:43 +08:00
end : function end ( ) {
2016-04-27 01:29:27 +08:00
// remove trailing whitespace
var element = stack [ stack . length - 1 ] ;
var lastNode = element . children [ element . children . length - 1 ] ;
2016-06-08 09:53:43 +08:00
if ( lastNode && lastNode . type === 3 && lastNode . text === ' ' ) {
element . children . pop ( ) ;
}
2016-04-27 01:29:27 +08:00
// pop stack
stack . length -= 1 ;
currentParent = stack [ stack . length - 1 ] ;
// check pre state
if ( element . pre ) {
2016-08-02 03:31:12 +08:00
inVPre = false ;
}
if ( platformIsPreTag ( element . tag ) ) {
2016-04-27 01:29:27 +08:00
inPre = false ;
}
} ,
chars : function chars ( text ) {
if ( ! currentParent ) {
if ( "development" !== 'production' && ! warned ) {
warned = true ;
warn$1 ( 'Component template should contain exactly one root element:\n\n' + template ) ;
}
return ;
}
2016-08-02 03:31:12 +08:00
text = inPre || text . trim ( ) ? decodeHTMLCached ( text )
2016-04-27 01:29:27 +08:00
// only preserve whitespace if its not right after a starting tag
2016-06-16 02:22:40 +08:00
: preserveWhitespace && currentParent . children . length ? ' ' : '' ;
2016-04-27 01:29:27 +08:00
if ( text ) {
var expression = void 0 ;
2016-08-02 03:31:12 +08:00
if ( ! inVPre && text !== ' ' && ( expression = parseText ( text , delimiters ) ) ) {
2016-06-08 09:53:43 +08:00
currentParent . children . push ( {
type : 2 ,
expression : expression ,
text : text
} ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
currentParent . children . push ( {
type : 3 ,
text : text
} ) ;
2016-04-27 01:29:27 +08:00
}
}
}
} ) ;
return root ;
}
function processPre ( el ) {
if ( getAndRemoveAttr ( el , 'v-pre' ) != null ) {
el . pre = true ;
}
}
function processRawAttrs ( el ) {
var l = el . attrsList . length ;
if ( l ) {
2016-08-02 03:31:12 +08:00
var attrs = el . attrs = new Array ( l ) ;
2016-04-27 01:29:27 +08:00
for ( var i = 0 ; i < l ; i ++ ) {
2016-06-08 09:53:43 +08:00
attrs [ i ] = {
2016-04-27 01:29:27 +08:00
name : el . attrsList [ i ] . name ,
value : JSON . stringify ( el . attrsList [ i ] . value )
} ;
}
2016-06-08 09:53:43 +08:00
} else if ( ! el . pre ) {
// non root node in pre blocks with no attributes
el . plain = true ;
}
}
function processKey ( el ) {
var exp = getBindingAttr ( el , 'key' ) ;
if ( exp ) {
el . key = exp ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-18 02:22:51 +08:00
function processRef ( el ) {
var ref = getBindingAttr ( el , 'ref' ) ;
if ( ref ) {
el . ref = ref ;
2016-08-16 11:39:07 +08:00
el . refInFor = checkInFor ( el ) ;
2016-06-18 02:22:51 +08:00
}
}
2016-04-27 01:29:27 +08:00
function processFor ( el ) {
var exp = void 0 ;
if ( exp = getAndRemoveAttr ( el , 'v-for' ) ) {
var inMatch = exp . match ( forAliasRE ) ;
if ( ! inMatch ) {
"development" !== 'production' && warn$1 ( 'Invalid v-for expression: ' + exp ) ;
return ;
}
el . for = inMatch [ 2 ] . trim ( ) ;
var alias = inMatch [ 1 ] . trim ( ) ;
var iteratorMatch = alias . match ( forIteratorRE ) ;
if ( iteratorMatch ) {
2016-06-14 07:36:46 +08:00
el . alias = iteratorMatch [ 1 ] . trim ( ) ;
el . iterator1 = iteratorMatch [ 2 ] . trim ( ) ;
if ( iteratorMatch [ 3 ] ) {
el . iterator2 = iteratorMatch [ 3 ] . trim ( ) ;
}
2016-04-27 01:29:27 +08:00
} else {
el . alias = alias ;
}
}
}
function processIf ( el ) {
var exp = getAndRemoveAttr ( el , 'v-if' ) ;
if ( exp ) {
el . if = exp ;
}
if ( getAndRemoveAttr ( el , 'v-else' ) != null ) {
el . else = true ;
}
}
function processElse ( el , parent ) {
var prev = findPrevElement ( parent . children ) ;
2016-06-08 09:53:43 +08:00
if ( prev && prev . if ) {
prev . elseBlock = el ;
2016-04-27 01:29:27 +08:00
} else if ( "development" !== 'production' ) {
2016-06-08 09:53:43 +08:00
warn$1 ( 'v-else used on element <' + el . tag + '> without corresponding v-if.' ) ;
2016-04-27 01:29:27 +08:00
}
}
function processOnce ( el ) {
var once = getAndRemoveAttr ( el , 'v-once' ) ;
if ( once != null ) {
el . once = true ;
}
}
function processSlot ( el ) {
if ( el . tag === 'slot' ) {
2016-08-16 11:39:07 +08:00
if ( "development" !== 'production' ) {
if ( ! el . attrsMap [ ':name' ] && ! el . attrsMap [ 'v-bind:name' ] && checkInFor ( el ) ) {
warn$1 ( 'Static <slot> found inside v-for: they will not render correctly. ' + 'Render the list in parent scope and use a single <slot> instead.' ) ;
}
}
2016-04-27 01:29:27 +08:00
el . slotName = getBindingAttr ( el , 'name' ) ;
2016-08-16 11:39:07 +08:00
if ( "development" !== 'production' ) {
var name = el . slotName ;
if ( seenSlots [ name ] ) {
warn$1 ( 'Duplicate ' + ( name ? '<slot> with name ' + name : 'default <slot>' ) + ' ' + 'found in the same template.' ) ;
}
seenSlots [ name ] = true ;
}
2016-04-27 01:29:27 +08:00
} else {
var slotTarget = getBindingAttr ( el , 'slot' ) ;
if ( slotTarget ) {
el . slotTarget = slotTarget ;
}
}
}
function processComponent ( el ) {
2016-06-08 09:53:43 +08:00
var binding = void 0 ;
if ( binding = getBindingAttr ( el , 'is' ) ) {
el . component = binding ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
if ( getAndRemoveAttr ( el , 'inline-template' ) != null ) {
el . inlineTemplate = true ;
2016-04-27 01:29:27 +08:00
}
}
function processAttrs ( el ) {
var list = el . attrsList ;
var i = void 0 ,
l = void 0 ,
name = void 0 ,
value = void 0 ,
arg = void 0 ,
2016-07-24 10:48:09 +08:00
modifiers = void 0 ,
isProp = void 0 ;
2016-04-27 01:29:27 +08:00
for ( i = 0 , l = list . length ; i < l ; i ++ ) {
name = list [ i ] . name ;
value = list [ i ] . value ;
if ( dirRE . test ( name ) ) {
2016-08-02 03:31:12 +08:00
// mark element as dynamic
el . hasBindings = true ;
2016-04-27 01:29:27 +08:00
// modifiers
modifiers = parseModifiers ( name ) ;
if ( modifiers ) {
name = name . replace ( modifierRE , '' ) ;
}
if ( bindRE . test ( name ) ) {
// v-bind
name = name . replace ( bindRE , '' ) ;
2016-07-24 10:48:09 +08:00
if ( modifiers && modifiers . prop ) {
isProp = true ;
name = camelize ( name ) ;
if ( name === 'innerHtml' ) name = 'innerHTML' ;
}
if ( isProp || platformMustUseProp ( name ) ) {
2016-04-27 01:29:27 +08:00
addProp ( el , name , value ) ;
} else {
addAttr ( el , name , value ) ;
}
} else if ( onRE . test ( name ) ) {
// v-on
name = name . replace ( onRE , '' ) ;
addHandler ( el , name , value , modifiers ) ;
} else {
// normal directives
name = name . replace ( dirRE , '' ) ;
// parse arg
2016-06-08 09:53:43 +08:00
var argMatch = name . match ( argRE ) ;
if ( argMatch && ( arg = argMatch [ 1 ] ) ) {
2016-04-27 01:29:27 +08:00
name = name . slice ( 0 , - ( arg . length + 1 ) ) ;
}
addDirective ( el , name , value , arg , modifiers ) ;
}
} else {
// literal attribute
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
var expression = parseText ( value , delimiters ) ;
if ( expression ) {
warn$1 ( name + '="' + value + '": ' + 'Interpolation inside attributes has been deprecated. ' + 'Use v-bind or the colon shorthand instead.' ) ;
}
2016-04-27 01:29:27 +08:00
}
2016-08-02 03:31:12 +08:00
addAttr ( el , name , JSON . stringify ( value ) ) ;
2016-04-27 01:29:27 +08:00
}
}
}
2016-08-16 11:39:07 +08:00
function checkInFor ( el ) {
var parent = el ;
while ( parent ) {
if ( parent . for !== undefined ) {
return true ;
}
parent = parent . parent ;
}
return false ;
}
2016-04-27 01:29:27 +08:00
function parseModifiers ( name ) {
var match = name . match ( modifierRE ) ;
if ( match ) {
var _ret = function ( ) {
var ret = { } ;
match . forEach ( function ( m ) {
ret [ m . slice ( 1 ) ] = true ;
} ) ;
return {
v : ret
} ;
} ( ) ;
if ( typeof _ret === "object" ) return _ret . v ;
}
}
function makeAttrsMap ( attrs ) {
var map = { } ;
for ( var i = 0 , l = attrs . length ; i < l ; i ++ ) {
if ( "development" !== 'production' && map [ attrs [ i ] . name ] ) {
warn$1 ( 'duplicate attribute: ' + attrs [ i ] . name ) ;
}
map [ attrs [ i ] . name ] = attrs [ i ] . value ;
}
return map ;
}
function findPrevElement ( children ) {
var i = children . length ;
while ( i -- ) {
if ( children [ i ] . tag ) return children [ i ] ;
}
}
2016-06-08 09:53:43 +08:00
function isForbiddenTag ( el ) {
return el . tag === 'style' || el . tag === 'script' && ( ! el . attrsMap . type || el . attrsMap . type === 'text/javascript' ) ;
}
var ieNSBug = /^xmlns:NS\d+/ ;
var ieNSPrefix = /^NS\d+:/ ;
/* istanbul ignore next */
function guardIESVGBug ( attrs ) {
var res = [ ] ;
for ( var i = 0 ; i < attrs . length ; i ++ ) {
var attr = attrs [ i ] ;
if ( ! ieNSBug . test ( attr . name ) ) {
attr . name = attr . name . replace ( ieNSPrefix , '' ) ;
res . push ( attr ) ;
}
}
return res ;
}
var isStaticKey = void 0 ;
2016-04-27 01:29:27 +08:00
var isPlatformReservedTag = void 0 ;
2016-06-08 09:53:43 +08:00
var genStaticKeysCached = cached ( genStaticKeys$1 ) ;
2016-04-27 01:29:27 +08:00
/ * *
* Goal of the optimizier : walk the generated template AST tree
* and detect sub - trees that are purely static , i . e . parts of
* the DOM that never needs to change .
*
* Once we detect these sub - trees , we can :
*
* 1. Hoist them into constants , so that we no longer need to
* create fresh nodes for them on each re - render ;
* 2. Completely skip them in the patching process .
* /
function optimize ( root , options ) {
2016-06-08 09:53:43 +08:00
if ( ! root ) return ;
isStaticKey = genStaticKeysCached ( options . staticKeys || '' ) ;
2016-04-27 01:29:27 +08:00
isPlatformReservedTag = options . isReservedTag || function ( ) {
return false ;
} ;
// first pass: mark all non-static nodes.
markStatic ( root ) ;
// second pass: mark static roots.
2016-08-10 12:55:30 +08:00
markStaticRoots ( root , false ) ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
function genStaticKeys$1 ( keys ) {
2016-08-02 03:31:12 +08:00
return makeMap ( 'type,tag,attrsList,attrsMap,plain,parent,children,attrs' + ( keys ? ',' + keys : '' ) ) ;
2016-06-08 09:53:43 +08:00
}
2016-04-27 01:29:27 +08:00
function markStatic ( node ) {
node . static = isStatic ( node ) ;
2016-06-08 09:53:43 +08:00
if ( node . type === 1 ) {
2016-04-27 01:29:27 +08:00
for ( var i = 0 , l = node . children . length ; i < l ; i ++ ) {
var child = node . children [ i ] ;
markStatic ( child ) ;
if ( ! child . static ) {
node . static = false ;
}
}
}
}
2016-08-10 12:55:30 +08:00
function markStaticRoots ( node , isInFor ) {
if ( node . type === 1 ) {
if ( node . once || node . static ) {
node . staticRoot = true ;
node . staticInFor = isInFor ;
return ;
}
if ( node . children ) {
for ( var i = 0 , l = node . children . length ; i < l ; i ++ ) {
markStaticRoots ( node . children [ i ] , ! ! node . for ) ;
}
2016-04-27 01:29:27 +08:00
}
}
}
function isStatic ( node ) {
2016-06-08 09:53:43 +08:00
if ( node . type === 2 ) {
// expression
return false ;
}
if ( node . type === 3 ) {
// text
return true ;
}
2016-08-02 03:31:12 +08:00
return ! ! ( node . pre || ! node . hasBindings && // no dynamic bindings
! node . if && ! node . for && // not v-if or v-for or v-else
2016-06-08 09:53:43 +08:00
! isBuiltInTag ( node . tag ) && // not a built-in
2016-08-02 03:31:12 +08:00
isPlatformReservedTag ( node . tag ) && // not a component
Object . keys ( node ) . every ( isStaticKey ) ) ;
2016-04-27 01:29:27 +08:00
}
var simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/ ;
// keyCode aliases
var keyCodes = {
esc : 27 ,
tab : 9 ,
enter : 13 ,
space : 32 ,
up : 38 ,
left : 37 ,
right : 39 ,
down : 40 ,
'delete' : [ 8 , 46 ]
} ;
var modifierCode = {
stop : '$event.stopPropagation();' ,
prevent : '$event.preventDefault();' ,
self : 'if($event.target !== $event.currentTarget)return;'
} ;
2016-07-24 10:48:09 +08:00
function genHandlers ( events , native ) {
var res = native ? 'nativeOn:{' : 'on:{' ;
2016-04-27 01:29:27 +08:00
for ( var name in events ) {
res += '"' + name + '":' + genHandler ( events [ name ] ) + ',' ;
}
return res . slice ( 0 , - 1 ) + '}' ;
}
function genHandler ( handler ) {
if ( ! handler ) {
return 'function(){}' ;
2016-06-08 09:53:43 +08:00
} else if ( Array . isArray ( handler ) ) {
2016-04-27 01:29:27 +08:00
return '[' + handler . map ( genHandler ) . join ( ',' ) + ']' ;
} else if ( ! handler . modifiers ) {
return simplePathRE . test ( handler . value ) ? handler . value : 'function($event){' + handler . value + '}' ;
} else {
2016-08-21 02:04:54 +08:00
var code = '' ;
var keys = [ ] ;
2016-04-27 01:29:27 +08:00
for ( var key in handler . modifiers ) {
2016-08-21 02:04:54 +08:00
if ( modifierCode [ key ] ) {
code += modifierCode [ key ] ;
} else {
keys . push ( key ) ;
}
}
if ( keys . length ) {
code = genKeyFilter ( keys ) + code ;
2016-04-27 01:29:27 +08:00
}
var handlerCode = simplePathRE . test ( handler . value ) ? handler . value + '($event)' : handler . value ;
2016-08-21 02:04:54 +08:00
return 'function($event){' + code + handlerCode + '}' ;
2016-04-27 01:29:27 +08:00
}
}
2016-08-21 02:04:54 +08:00
function genKeyFilter ( keys ) {
var code = keys . length === 1 ? normalizeKeyCode ( keys [ 0 ] ) : Array . prototype . concat . apply ( [ ] , keys . map ( normalizeKeyCode ) ) ;
2016-06-08 09:53:43 +08:00
if ( Array . isArray ( code ) ) {
2016-04-27 01:29:27 +08:00
return 'if(' + code . map ( function ( c ) {
return '$event.keyCode!==' + c ;
} ) . join ( '&&' ) + ')return;' ;
} else {
return 'if($event.keyCode!==' + code + ')return;' ;
}
}
2016-08-21 02:04:54 +08:00
function normalizeKeyCode ( key ) {
return parseInt ( key , 10 ) || // number keyCode
keyCodes [ key ] || // built-in alias
'_k(' + JSON . stringify ( key ) + ')' // custom alias
;
}
2016-06-08 09:53:43 +08:00
function bind$1 ( el , dir ) {
2016-07-24 10:48:09 +08:00
addHook ( el , 'construct' , '_b(n1,' + dir . value + ( dir . modifiers && dir . modifiers . prop ? ',true' : '' ) + ')' ) ;
2016-04-27 01:29:27 +08:00
}
var baseDirectives = {
2016-06-08 09:53:43 +08:00
bind : bind$1 ,
cloak : noop
2016-04-27 01:29:27 +08:00
} ;
2016-06-08 09:53:43 +08:00
// configurable state
var warn$2 = void 0 ;
2016-06-11 07:23:32 +08:00
var transforms$1 = void 0 ;
var dataGenFns = void 0 ;
2016-04-27 01:29:27 +08:00
var platformDirectives$1 = void 0 ;
var staticRenderFns = void 0 ;
2016-06-08 09:53:43 +08:00
var currentOptions = void 0 ;
2016-04-27 01:29:27 +08:00
function generate ( ast , options ) {
2016-06-08 09:53:43 +08:00
// save previous staticRenderFns so generate calls can be nested
var prevStaticRenderFns = staticRenderFns ;
var currentStaticRenderFns = staticRenderFns = [ ] ;
currentOptions = options ;
warn$2 = options . warn || baseWarn ;
2016-06-11 07:23:32 +08:00
transforms$1 = pluckModuleFunction ( options . modules , 'transformCode' ) ;
dataGenFns = pluckModuleFunction ( options . modules , 'genData' ) ;
2016-04-27 01:29:27 +08:00
platformDirectives$1 = options . directives || { } ;
2016-06-28 10:25:12 +08:00
var code = ast ? genElement ( ast ) : '_h("div")' ;
2016-06-08 09:53:43 +08:00
staticRenderFns = prevStaticRenderFns ;
2016-04-27 01:29:27 +08:00
return {
2016-06-08 09:53:43 +08:00
render : 'with(this){return ' + code + '}' ,
staticRenderFns : currentStaticRenderFns
2016-04-27 01:29:27 +08:00
} ;
}
function genElement ( el ) {
2016-06-28 10:25:12 +08:00
if ( el . staticRoot && ! el . staticProcessed ) {
// hoist static sub-trees out
el . staticProcessed = true ;
staticRenderFns . push ( 'with(this){return ' + genElement ( el ) + '}' ) ;
2016-08-10 12:55:30 +08:00
return '_m(' + ( staticRenderFns . length - 1 ) + ( el . staticInFor ? ',true' : '' ) + ')' ;
2016-06-28 10:25:12 +08:00
} else if ( el . for && ! el . forProcessed ) {
2016-04-27 01:29:27 +08:00
return genFor ( el ) ;
2016-06-16 02:22:40 +08:00
} else if ( el . if && ! el . ifProcessed ) {
2016-04-27 01:29:27 +08:00
return genIf ( el ) ;
} else if ( el . tag === 'template' && ! el . slotTarget ) {
2016-06-08 09:53:43 +08:00
return genChildren ( el ) || 'void 0' ;
2016-04-27 01:29:27 +08:00
} else if ( el . tag === 'slot' ) {
return genSlot ( el ) ;
} else {
2016-06-08 09:53:43 +08:00
// component or element
var code = void 0 ;
if ( el . component ) {
code = genComponent ( el ) ;
2016-04-27 01:29:27 +08:00
} else {
2016-06-08 09:53:43 +08:00
var data = genData ( el ) ;
2016-08-06 06:14:22 +08:00
var children = el . inlineTemplate ? null : genChildren ( el ) ;
2016-06-28 10:25:12 +08:00
code = '_h(\'' + el . tag + '\'' + ( data ? ',' + data : '' // data
) + ( children ? ',' + children : '' // children
2016-06-08 09:53:43 +08:00
) + ')' ;
}
2016-06-11 07:23:32 +08:00
// module transforms
for ( var i = 0 ; i < transforms$1 . length ; i ++ ) {
code = transforms$1 [ i ] ( el , code ) ;
2016-06-08 09:53:43 +08:00
}
return code ;
2016-04-27 01:29:27 +08:00
}
}
function genIf ( el ) {
var exp = el . if ;
2016-06-16 02:22:40 +08:00
el . ifProcessed = true ; // avoid recursion
2016-06-08 09:53:43 +08:00
return '(' + exp + ')?' + genElement ( el ) + ':' + genElse ( el ) ;
2016-04-27 01:29:27 +08:00
}
function genElse ( el ) {
2016-06-08 09:53:43 +08:00
return el . elseBlock ? genElement ( el . elseBlock ) : 'void 0' ;
2016-04-27 01:29:27 +08:00
}
function genFor ( el ) {
var exp = el . for ;
var alias = el . alias ;
2016-06-14 07:36:46 +08:00
var iterator1 = el . iterator1 ? ',' + el . iterator1 : '' ;
var iterator2 = el . iterator2 ? ',' + el . iterator2 : '' ;
2016-06-16 02:22:40 +08:00
el . forProcessed = true ; // avoid recursion
2016-06-14 07:36:46 +08:00
return '(' + exp + ')&&_l((' + exp + '),' + ( 'function(' + alias + iterator1 + iterator2 + '){' ) + ( 'return ' + genElement ( el ) ) + '})' ;
2016-04-27 01:29:27 +08:00
}
function genData ( el ) {
if ( el . plain ) {
2016-06-08 09:53:43 +08:00
return ;
2016-04-27 01:29:27 +08:00
}
var data = '{' ;
// directives first.
// directives may mutate the el's other properties before they are generated.
2016-06-08 09:53:43 +08:00
var dirs = genDirectives ( el ) ;
if ( dirs ) data += dirs + ',' ;
2016-04-27 01:29:27 +08:00
// key
if ( el . key ) {
data += 'key:' + el . key + ',' ;
}
2016-06-08 09:53:43 +08:00
// ref
if ( el . ref ) {
2016-06-18 02:22:51 +08:00
data += 'ref:' + el . ref + ',' ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
if ( el . refInFor ) {
data += 'refInFor:true,' ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
// record original tag name for components using "is" attribute
if ( el . component ) {
data += 'tag:"' + el . tag + '",' ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
// slot target
if ( el . slotTarget ) {
data += 'slot:' + el . slotTarget + ',' ;
2016-04-27 01:29:27 +08:00
}
2016-06-11 07:23:32 +08:00
// module data generation functions
for ( var i = 0 ; i < dataGenFns . length ; i ++ ) {
data += dataGenFns [ i ] ( el ) ;
2016-04-27 01:29:27 +08:00
}
// attributes
if ( el . attrs ) {
data += 'attrs:{' + genProps ( el . attrs ) + '},' ;
}
2016-07-24 10:48:09 +08:00
// DOM props
if ( el . props ) {
data += 'domProps:{' + genProps ( el . props ) + '},' ;
}
2016-04-27 01:29:27 +08:00
// hooks
if ( el . hooks ) {
data += 'hook:{' + genHooks ( el . hooks ) + '},' ;
}
// event handlers
if ( el . events ) {
2016-06-08 09:53:43 +08:00
data += genHandlers ( el . events ) + ',' ;
}
2016-07-24 10:48:09 +08:00
if ( el . nativeEvents ) {
2016-08-16 11:39:07 +08:00
data += genHandlers ( el . nativeEvents , true ) + ',' ;
2016-07-24 10:48:09 +08:00
}
2016-06-08 09:53:43 +08:00
// inline-template
if ( el . inlineTemplate ) {
var ast = el . children [ 0 ] ;
if ( "development" !== 'production' && ( el . children . length > 1 || ast . type !== 1 ) ) {
warn$2 ( 'Inline-template components must have exactly one child element.' ) ;
}
if ( ast . type === 1 ) {
var inlineRenderFns = generate ( ast , currentOptions ) ;
data += 'inlineTemplate:{render:function(){' + inlineRenderFns . render + '},staticRenderFns:[' + inlineRenderFns . staticRenderFns . map ( function ( code ) {
return 'function(){' + code + '}' ;
} ) . join ( ',' ) + ']}' ;
}
2016-04-27 01:29:27 +08:00
}
return data . replace ( /,$/ , '' ) + '}' ;
}
function genDirectives ( el ) {
var dirs = el . directives ;
2016-06-08 09:53:43 +08:00
if ( ! dirs ) return ;
2016-04-27 01:29:27 +08:00
var res = 'directives:[' ;
var hasRuntime = false ;
var i = void 0 ,
l = void 0 ,
dir = void 0 ,
needRuntime = void 0 ;
for ( i = 0 , l = dirs . length ; i < l ; i ++ ) {
dir = dirs [ i ] ;
needRuntime = true ;
var gen = platformDirectives$1 [ dir . name ] || baseDirectives [ dir . name ] ;
if ( gen ) {
// compile-time directive that manipulates AST.
// returns true if it also needs a runtime counterpart.
2016-06-08 09:53:43 +08:00
needRuntime = ! ! gen ( el , dir , warn$2 ) ;
2016-04-27 01:29:27 +08:00
}
if ( needRuntime ) {
hasRuntime = true ;
2016-06-23 03:33:53 +08:00
res += '{name:"' + dir . name + '"' + ( dir . value ? ',value:(' + dir . value + '),expression:' + JSON . stringify ( dir . value ) : '' ) + ( dir . arg ? ',arg:"' + dir . arg + '"' : '' ) + ( dir . modifiers ? ',modifiers:' + JSON . stringify ( dir . modifiers ) : '' ) + '},' ;
2016-04-27 01:29:27 +08:00
}
}
if ( hasRuntime ) {
return res . slice ( 0 , - 1 ) + ']' ;
}
}
2016-08-06 06:14:22 +08:00
function genChildren ( el ) {
if ( el . children . length ) {
return '[' + el . children . map ( genNode ) . join ( ',' ) + ']' ;
2016-04-27 01:29:27 +08:00
}
}
function genNode ( node ) {
2016-06-08 09:53:43 +08:00
if ( node . type === 1 ) {
2016-04-27 01:29:27 +08:00
return genElement ( node ) ;
} else {
return genText ( node ) ;
}
}
function genText ( text ) {
2016-06-28 10:25:12 +08:00
return text . type === 2 ? text . expression // no need for () because already wrapped in _s()
: JSON . stringify ( text . text ) ;
2016-04-27 01:29:27 +08:00
}
function genSlot ( el ) {
2016-06-08 09:53:43 +08:00
var slot = '$slots[' + ( el . slotName || '"default"' ) + ']' ;
var children = genChildren ( el ) ;
return children ? '(' + slot + '||' + children + ')' : slot ;
2016-04-27 01:29:27 +08:00
}
function genComponent ( el ) {
2016-08-06 06:14:22 +08:00
var children = genChildren ( el ) ;
2016-06-28 10:25:12 +08:00
return '_h(' + el . component + ',' + genData ( el ) + ( children ? ',' + children : '' ) + ')' ;
2016-04-27 01:29:27 +08:00
}
function genProps ( props ) {
var res = '' ;
for ( var i = 0 ; i < props . length ; i ++ ) {
var prop = props [ i ] ;
res += '"' + prop . name + '":' + prop . value + ',' ;
}
return res . slice ( 0 , - 1 ) ;
}
function genHooks ( hooks ) {
var res = '' ;
2016-06-08 09:53:43 +08:00
for ( var _key in hooks ) {
res += '"' + _key + '":function(n1,n2){' + hooks [ _key ] . join ( ';' ) + '},' ;
2016-04-27 01:29:27 +08:00
}
return res . slice ( 0 , - 1 ) ;
}
/ * *
* Compile a template .
* /
function compile$1 ( template , options ) {
var ast = parse ( template . trim ( ) , options ) ;
optimize ( ast , options ) ;
2016-06-08 09:53:43 +08:00
var code = generate ( ast , options ) ;
return {
ast : ast ,
render : code . render ,
staticRenderFns : code . staticRenderFns
} ;
}
2016-06-16 02:22:40 +08:00
// operators like typeof, instanceof and in are allowed
var prohibitedKeywordRE = new RegExp ( '\\b' + ( 'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' + 'super,throw,while,yield,delete,export,import,return,switch,default,' + 'extends,finally,continue,debugger,function,arguments' ) . split ( ',' ) . join ( '\\b|\\b' ) + '\\b' ) ;
// check valid identifier for v-for
2016-06-17 01:00:55 +08:00
var identRE = /[A-Za-z_$][\w$]*/ ;
2016-06-23 03:33:53 +08:00
// strip strings in expressions
var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g ;
2016-06-11 07:23:32 +08:00
2016-06-08 09:53:43 +08:00
// detect problematic expressions in a template
function detectErrors ( ast ) {
var errors = [ ] ;
if ( ast ) {
checkNode ( ast , errors ) ;
}
return errors ;
}
function checkNode ( node , errors ) {
if ( node . type === 1 ) {
for ( var name in node . attrsMap ) {
if ( dirRE . test ( name ) ) {
var value = node . attrsMap [ name ] ;
if ( value ) {
2016-06-16 02:22:40 +08:00
if ( name === 'v-for' ) {
checkFor ( node , 'v-for="' + value + '"' , errors ) ;
} else {
checkExpression ( value , name + '="' + value + '"' , errors ) ;
}
2016-06-08 09:53:43 +08:00
}
}
}
if ( node . children ) {
for ( var i = 0 ; i < node . children . length ; i ++ ) {
checkNode ( node . children [ i ] , errors ) ;
}
}
} else if ( node . type === 2 ) {
checkExpression ( node . expression , node . text , errors ) ;
}
}
2016-06-16 02:22:40 +08:00
function checkFor ( node , text , errors ) {
checkExpression ( node . for || '' , text , errors ) ;
checkIdentifier ( node . alias , 'v-for alias' , text , errors ) ;
checkIdentifier ( node . iterator1 , 'v-for iterator' , text , errors ) ;
checkIdentifier ( node . iterator2 , 'v-for iterator' , text , errors ) ;
}
function checkIdentifier ( ident , type , text , errors ) {
if ( typeof ident === 'string' && ! identRE . test ( ident ) ) {
errors . push ( '- invalid ' + type + ' "' + ident + '" in expression: ' + text ) ;
}
}
2016-06-08 09:53:43 +08:00
function checkExpression ( exp , text , errors ) {
2016-06-23 03:33:53 +08:00
try {
new Function ( 'return ' + exp ) ;
} catch ( e ) {
var keywordMatch = exp . replace ( stripStringRE , '' ) . match ( prohibitedKeywordRE ) ;
if ( keywordMatch ) {
errors . push ( '- avoid using JavaScript keyword as property name: ' + ( '"' + keywordMatch [ 0 ] + '" in expression ' + text ) ) ;
} else {
2016-06-11 07:23:32 +08:00
errors . push ( '- invalid expression: ' + text ) ;
}
2016-06-08 09:53:43 +08:00
}
}
function transformNode ( el , options ) {
var warn = options . warn || baseWarn ;
var staticClass = getAndRemoveAttr ( el , 'class' ) ;
if ( "development" !== 'production' && staticClass ) {
var expression = parseText ( staticClass , options . delimiters ) ;
if ( expression ) {
warn ( 'class="' + staticClass + '": ' + 'Interpolation inside attributes has been deprecated. ' + 'Use v-bind or the colon shorthand instead.' ) ;
}
}
2016-08-06 06:14:22 +08:00
if ( staticClass ) {
el . staticClass = JSON . stringify ( staticClass ) ;
}
2016-06-08 09:53:43 +08:00
var classBinding = getBindingAttr ( el , 'class' , false /* getStatic */ ) ;
if ( classBinding ) {
el . classBinding = classBinding ;
}
}
function genData$1 ( el ) {
var data = '' ;
if ( el . staticClass ) {
data += 'staticClass:' + el . staticClass + ',' ;
}
if ( el . classBinding ) {
data += 'class:' + el . classBinding + ',' ;
}
return data ;
}
var klass$1 = {
staticKeys : [ 'staticClass' ] ,
transformNode : transformNode ,
genData : genData$1
} ;
function transformNode$1 ( el ) {
var styleBinding = getBindingAttr ( el , 'style' , false /* getStatic */ ) ;
if ( styleBinding ) {
el . styleBinding = styleBinding ;
}
}
function genData$2 ( el ) {
return el . styleBinding ? 'style:(' + el . styleBinding + '),' : '' ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
var style$1 = {
transformNode : transformNode$1 ,
genData : genData$2
} ;
2016-07-17 13:53:44 +08:00
var modules$1 = [ klass$1 , style$1 ] ;
2016-06-08 09:53:43 +08:00
var warn$3 = void 0 ;
function model$1 ( el , dir , _warn ) {
warn$3 = _warn ;
2016-04-27 01:29:27 +08:00
var value = dir . value ;
var modifiers = dir . modifiers ;
if ( el . tag === 'select' ) {
2016-06-08 09:53:43 +08:00
return genSelect ( el , value ) ;
2016-04-27 01:29:27 +08:00
} else {
switch ( el . attrsMap . type ) {
case 'checkbox' :
genCheckboxModel ( el , value ) ;
break ;
case 'radio' :
genRadioModel ( el , value ) ;
break ;
default :
return genDefaultModel ( el , value , modifiers ) ;
}
}
}
function genCheckboxModel ( el , value ) {
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' && el . attrsMap . checked != null ) {
warn$3 ( '<' + el . tag + ' v-model="' + value + '" checked>:\n' + 'inline checked attributes will be ignored when using v-model. ' + 'Declare initial values in the component\'s data option instead.' ) ;
}
2016-04-27 01:29:27 +08:00
var valueBinding = getBindingAttr ( el , 'value' ) ;
2016-06-08 09:53:43 +08:00
var trueValueBinding = getBindingAttr ( el , 'true-value' ) || 'true' ;
var falseValueBinding = getBindingAttr ( el , 'false-value' ) || 'false' ;
addProp ( el , 'checked' , 'Array.isArray(' + value + ')' + ( '?(' + value + ').indexOf(' + valueBinding + ')>-1' ) + ( ':(' + value + ')===(' + trueValueBinding + ')' ) ) ;
2016-08-21 02:04:54 +08:00
addHandler ( el , 'change' , 'var $$a=' + value + ',' + '$$el=$event.target,' + ( '$$c=$$el.checked?(' + trueValueBinding + '):(' + falseValueBinding + ');' ) + 'if(Array.isArray($$a)){' + ( 'var $$v=' + valueBinding + ',' ) + '$$i=$$a.indexOf($$v);' + ( 'if($$c){$$i<0&&(' + value + '=$$a.concat($$v))}' ) + ( 'else{$$i>-1&&(' + value + '=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}' ) + ( '}else{' + value + '=$$c}' ) , null , true ) ;
2016-04-27 01:29:27 +08:00
}
function genRadioModel ( el , value ) {
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' && el . attrsMap . checked != null ) {
warn$3 ( '<' + el . tag + ' v-model="' + value + '" checked>:\n' + 'inline checked attributes will be ignored when using v-model. ' + 'Declare initial values in the component\'s data option instead.' ) ;
}
2016-04-27 01:29:27 +08:00
var valueBinding = getBindingAttr ( el , 'value' ) ;
2016-06-08 09:53:43 +08:00
addProp ( el , 'checked' , '(' + value + ')===(' + valueBinding + ')' ) ;
2016-08-21 02:04:54 +08:00
addHandler ( el , 'change' , value + '=' + valueBinding , null , true ) ;
2016-04-27 01:29:27 +08:00
}
function genDefaultModel ( el , value , modifiers ) {
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
if ( el . tag === 'input' && el . attrsMap . value ) {
warn$3 ( '<' + el . tag + ' v-model="' + value + '" value="' + el . attrsMap . value + '">:\n' + 'inline value attributes will be ignored when using v-model. ' + 'Declare initial values in the component\'s data option instead.' ) ;
}
if ( el . tag === 'textarea' && el . children . length ) {
warn$3 ( '<textarea v-model="' + value + '">:\n' + 'inline content inside <textarea> will be ignored when using v-model. ' + 'Declare initial values in the component\'s data option instead.' ) ;
}
}
2016-04-27 01:29:27 +08:00
var type = el . attrsMap . type ;
var _ref = modifiers || { } ;
var lazy = _ref . lazy ;
var number = _ref . number ;
var trim = _ref . trim ;
2016-08-16 11:39:07 +08:00
var event = lazy || isIE && type === 'range' ? 'change' : 'input' ;
2016-04-27 01:29:27 +08:00
var needCompositionGuard = ! lazy && type !== 'range' ;
2016-07-08 05:53:22 +08:00
var isNative = el . tag === 'input' || el . tag === 'textarea' ;
2016-04-27 01:29:27 +08:00
2016-07-08 05:53:22 +08:00
var valueExpression = isNative ? '$event.target.value' + ( trim ? '.trim()' : '' ) : '$event' ;
2016-06-28 10:25:12 +08:00
var code = number || type === 'number' ? value + '=_n(' + valueExpression + ')' : value + '=' + valueExpression ;
2016-07-08 05:53:22 +08:00
if ( isNative && needCompositionGuard ) {
2016-04-27 01:29:27 +08:00
code = 'if($event.target.composing)return;' + code ;
}
2016-07-08 05:53:22 +08:00
addProp ( el , 'value' , isNative ? '_s(' + value + ')' : '(' + value + ')' ) ;
2016-08-21 02:04:54 +08:00
addHandler ( el , event , code , null , true ) ;
2016-04-27 01:29:27 +08:00
if ( needCompositionGuard ) {
// need runtime directive code to help with composition events
return true ;
}
}
function genSelect ( el , value ) {
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
el . children . some ( checkOptionWarning ) ;
}
var code = value + '=Array.prototype.filter' + '.call($event.target.options,function(o){return o.selected})' + '.map(function(o){return "_value" in o ? o._value : o.value})' + ( el . attrsMap . multiple == null ? '[0]' : '' ) ;
2016-08-21 02:04:54 +08:00
addHandler ( el , 'change' , code , null , true ) ;
2016-06-08 09:53:43 +08:00
// need runtime to help with possible dynamically generated options
return true ;
2016-04-27 01:29:27 +08:00
}
2016-06-08 09:53:43 +08:00
function checkOptionWarning ( option ) {
if ( option . type === 1 && option . tag === 'option' && option . attrsMap . selected != null ) {
var parentModel = option . parent && option . parent . type === 1 && option . parent . attrsMap [ 'v-model' ] ;
warn$3 ( '<select v-model="' + parentModel + '">:\n' + 'inline selected attributes on <option> will be ignored when using v-model. ' + 'Declare initial values in the component\'s data option instead.' ) ;
return true ;
}
2016-04-27 01:29:27 +08:00
}
function text ( el , dir ) {
2016-06-08 09:53:43 +08:00
if ( dir . value ) {
addProp ( el , 'textContent' , '_s(' + dir . value + ')' ) ;
}
2016-04-27 01:29:27 +08:00
}
function html ( el , dir ) {
2016-06-08 09:53:43 +08:00
if ( dir . value ) {
addProp ( el , 'innerHTML' , '_s(' + dir . value + ')' ) ;
}
2016-04-27 01:29:27 +08:00
}
var directives$1 = {
model : model$1 ,
text : text ,
html : html
} ;
2016-06-11 07:23:32 +08:00
var cache = Object . create ( null ) ;
2016-04-27 01:29:27 +08:00
var baseOptions = {
2016-06-08 09:53:43 +08:00
isIE : isIE ,
2016-04-27 01:29:27 +08:00
expectHTML : true ,
2016-06-08 09:53:43 +08:00
modules : modules$1 ,
staticKeys : genStaticKeys ( modules$1 ) ,
2016-04-27 01:29:27 +08:00
directives : directives$1 ,
isReservedTag : isReservedTag ,
isUnaryTag : isUnaryTag ,
mustUseProp : mustUseProp ,
2016-08-02 03:31:12 +08:00
getTagNamespace : getTagNamespace ,
isPreTag : isPreTag
2016-04-27 01:29:27 +08:00
} ;
function compile ( template , options ) {
options = options ? extend ( extend ( { } , baseOptions ) , options ) : baseOptions ;
return compile$1 ( template , options ) ;
}
2016-06-08 09:53:43 +08:00
function compileToFunctions ( template , options , vm ) {
var _warn = options && options . warn || warn ;
// detect possible CSP restriction
/* istanbul ignore if */
if ( "development" !== 'production' ) {
try {
new Function ( 'return 1' ) ;
} catch ( e ) {
if ( e . toString ( ) . match ( /unsafe-eval|CSP/ ) ) {
_warn ( 'It seems you are using the standalone build of Vue.js in an ' + 'environment with Content Security Policy that prohibits unsafe-eval. ' + 'The template compiler cannot work in this environment. Consider ' + 'relaxing the policy to allow unsafe-eval or pre-compiling your ' + 'templates into render functions.' ) ;
}
}
}
var key = options && options . delimiters ? String ( options . delimiters ) + template : template ;
if ( cache [ key ] ) {
return cache [ key ] ;
2016-04-27 01:29:27 +08:00
}
var res = { } ;
2016-06-08 09:53:43 +08:00
var compiled = compile ( template , options ) ;
res . render = makeFunction ( compiled . render ) ;
2016-04-27 01:29:27 +08:00
var l = compiled . staticRenderFns . length ;
2016-06-08 09:53:43 +08:00
res . staticRenderFns = new Array ( l ) ;
for ( var i = 0 ; i < l ; i ++ ) {
res . staticRenderFns [ i ] = makeFunction ( compiled . staticRenderFns [ i ] ) ;
}
if ( "development" !== 'production' ) {
if ( res . render === noop || res . staticRenderFns . some ( function ( fn ) {
return fn === noop ;
} ) ) {
_warn ( 'failed to compile template:\n\n' + template + '\n\n' + detectErrors ( compiled . ast ) . join ( '\n' ) + '\n\n' , vm ) ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-08 09:53:43 +08:00
return cache [ key ] = res ;
}
function makeFunction ( code ) {
try {
return new Function ( code ) ;
} catch ( e ) {
return noop ;
}
2016-04-27 01:29:27 +08:00
}
var idToTemplate = cached ( function ( id ) {
2016-06-08 09:53:43 +08:00
var el = query ( id ) ;
return el && el . innerHTML ;
2016-04-27 01:29:27 +08:00
} ) ;
2016-06-08 09:53:43 +08:00
var mount = Vue . prototype . $mount ;
Vue . prototype . $mount = function ( el , hydrating ) {
2016-04-27 01:29:27 +08:00
el = el && query ( el ) ;
2016-08-21 02:04:54 +08:00
if ( el === document . body || el === document . documentElement ) {
"development" !== 'production' && warn ( 'Do not mount Vue to <html> or <body> - mount to normal elements instead.' ) ;
return this ;
}
2016-04-27 01:29:27 +08:00
var options = this . $options ;
// resolve template/el and convert to render function
if ( ! options . render ) {
var template = options . template ;
2016-07-26 10:07:26 +08:00
var isFromDOM = false ;
2016-04-27 01:29:27 +08:00
if ( template ) {
if ( typeof template === 'string' ) {
if ( template . charAt ( 0 ) === '#' ) {
2016-07-26 10:07:26 +08:00
isFromDOM = true ;
2016-04-27 01:29:27 +08:00
template = idToTemplate ( template ) ;
}
} else if ( template . nodeType ) {
2016-07-26 10:07:26 +08:00
isFromDOM = true ;
2016-04-27 01:29:27 +08:00
template = template . innerHTML ;
} else {
2016-06-08 09:53:43 +08:00
if ( "development" !== 'production' ) {
warn ( 'invalid template option:' + template , this ) ;
}
return this ;
2016-04-27 01:29:27 +08:00
}
} else if ( el ) {
2016-07-26 10:07:26 +08:00
isFromDOM = true ;
2016-04-27 01:29:27 +08:00
template = getOuterHTML ( el ) ;
}
if ( template ) {
var _compileToFunctions = compileToFunctions ( template , {
2016-07-27 12:25:41 +08:00
warn : warn ,
isFromDOM : isFromDOM ,
shouldDecodeTags : shouldDecodeTags ,
delimiters : options . delimiters
2016-06-08 09:53:43 +08:00
} , this ) ;
2016-04-27 01:29:27 +08:00
var render = _compileToFunctions . render ;
var staticRenderFns = _compileToFunctions . staticRenderFns ;
options . render = render ;
options . staticRenderFns = staticRenderFns ;
}
}
2016-06-08 09:53:43 +08:00
return mount . call ( this , el , hydrating ) ;
2016-04-27 01:29:27 +08:00
} ;
/ * *
* Get outerHTML of elements , taking care
* of SVG elements in IE as well .
* /
function getOuterHTML ( el ) {
if ( el . outerHTML ) {
return el . outerHTML ;
} else {
var container = document . createElement ( 'div' ) ;
container . appendChild ( el . cloneNode ( true ) ) ;
return container . innerHTML ;
}
}
Vue . compile = compileToFunctions ;
return Vue ;
} ) ) ;