2016-06-26 12:53:58 +08:00
'use strict' ;
Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
function _interopDefault ( ex ) { return ( ex && ( typeof ex === 'object' ) && 'default' in ex ) ? ex [ 'default' ] : ex ; }
var stream = require ( 'stream' ) ;
var stream _ _default = _interopDefault ( stream ) ;
var entities = require ( 'entities' ) ;
var NativeModule = _interopDefault ( require ( 'module' ) ) ;
var vm = _interopDefault ( require ( 'vm' ) ) ;
2016-06-28 10:25:12 +08:00
var MAX _STACK _DEPTH = 1000 ;
function createWriteFunction ( write , onError ) {
var stackDepth = 0 ;
var cachedWrite = function cachedWrite ( text , next ) {
if ( text && cachedWrite . caching ) {
cachedWrite . cacheBuffer [ cachedWrite . cacheBuffer . length - 1 ] += text ;
}
var waitForNext = write ( text , next ) ;
if ( ! waitForNext ) {
if ( stackDepth >= MAX _STACK _DEPTH ) {
process . nextTick ( function ( ) {
try {
next ( ) ;
} catch ( e ) {
onError ( e ) ;
}
} ) ;
} else {
stackDepth ++ ;
next ( ) ;
stackDepth -- ;
}
}
} ;
cachedWrite . caching = false ;
cachedWrite . cacheBuffer = [ ] ;
return cachedWrite ;
}
2016-06-26 12:53:58 +08:00
var inherits = function ( subClass , superClass ) {
if ( typeof superClass !== "function" && superClass !== null ) {
throw new TypeError ( "Super expression must either be null or a function, not " + typeof superClass ) ;
}
subClass . prototype = Object . create ( superClass && superClass . prototype , {
constructor : {
value : subClass ,
enumerable : false ,
writable : true ,
configurable : true
}
} ) ;
if ( superClass ) Object . setPrototypeOf ? Object . setPrototypeOf ( subClass , superClass ) : subClass . _ _proto _ _ = superClass ;
} ;
var possibleConstructorReturn = function ( self , call ) {
if ( ! self ) {
throw new ReferenceError ( "this hasn't been initialised - super() hasn't been called" ) ;
}
return call && ( typeof call === "object" || typeof call === "function" ) ? call : self ;
} ;
/ * *
* Original RenderStream implmentation by Sasha Aickin ( @ aickin )
* Licensed under the Apache License , Version 2.0
* Modified by Evan You ( @ yyx990803 )
* /
var RenderStream = function ( _stream$Readable ) {
inherits ( RenderStream , _stream$Readable ) ;
function RenderStream ( render ) {
var _this = possibleConstructorReturn ( this , _stream$Readable . call ( this ) ) ;
_this . buffer = '' ;
_this . render = render ;
_this . expectedSize = 0 ;
_this . stackDepth = 0 ;
2016-06-28 10:25:12 +08:00
_this . write = createWriteFunction ( function ( text , next ) {
2016-06-26 12:53:58 +08:00
var n = _this . expectedSize ;
_this . buffer += text ;
if ( _this . buffer . length >= n ) {
_this . next = next ;
_this . pushBySize ( n ) ;
2016-06-28 10:25:12 +08:00
return true ; // we will decide when to call next
2016-06-26 12:53:58 +08:00
}
2016-06-28 10:25:12 +08:00
} , function ( err ) {
_this . emit ( 'error' , err ) ;
} ) ;
2016-06-26 12:53:58 +08:00
_this . end = function ( ) {
// the rendering is finished; we should push out the last of the buffer.
_this . done = true ;
_this . push ( _this . buffer ) ;
} ;
return _this ;
}
RenderStream . prototype . pushBySize = function pushBySize ( n ) {
var bufferToPush = this . buffer . substring ( 0 , n ) ;
this . buffer = this . buffer . substring ( n ) ;
this . push ( bufferToPush ) ;
} ;
RenderStream . prototype . tryRender = function tryRender ( ) {
try {
this . render ( this . write , this . end ) ;
} catch ( e ) {
this . emit ( 'error' , e ) ;
}
} ;
RenderStream . prototype . tryNext = function tryNext ( ) {
try {
this . next ( ) ;
} catch ( e ) {
this . emit ( 'error' , e ) ;
}
} ;
RenderStream . prototype . _read = function _read ( n ) {
this . expectedSize = n ;
// it's possible that the last chunk added bumped the buffer up to > 2 * n,
// which means we will need to go through multiple read calls to drain it
// down to < n.
if ( this . done ) {
this . push ( null ) ;
return ;
}
if ( this . buffer . length >= n ) {
this . pushBySize ( n ) ;
return ;
}
if ( ! this . next ) {
// start the rendering chain.
this . tryRender ( ) ;
} else {
// continue with the rendering.
this . tryNext ( ) ;
}
} ;
return RenderStream ;
} ( stream _ _default . Readable ) ;
/ * *
* Convert a value to a string that is actually rendered .
* /
2016-06-28 10:25:12 +08:00
function _toString ( val ) {
2016-06-26 12:53:58 +08:00
return val == null ? '' : typeof val === 'object' ? JSON . stringify ( val , null , 2 ) : String ( val ) ;
}
/ * *
* 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 ;
}
/ * *
* 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-06-26 12:53:58 +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 ) {
return str . replace ( camelizeRE , function ( _ , c ) {
return c ? c . toUpperCase ( ) : '' ;
} ) ;
} ) ;
/ * *
* Capitalize a string .
* /
var capitalize = cached ( function ( str ) {
return str . charAt ( 0 ) . toUpperCase ( ) + str . slice ( 1 ) ;
} ) ;
/ * *
* Hyphenate a camelCase string .
* /
2016-07-08 05:53:22 +08:00
var hyphenateRE = /([^-])([A-Z])/g ;
2016-06-26 12:53:58 +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-06-26 12:53:58 +08:00
} ) ;
/ * *
* Simple bind , faster than native
* /
function bind ( fn , ctx ) {
2016-07-17 13:53:44 +08:00
function boundFn ( a ) {
2016-06-26 12:53:58 +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-06-26 12:53:58 +08:00
}
/ * *
* Convert an Array - like object to a real Array .
* /
function toArray$1 ( 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 .
* /
function extend ( to , _from ) {
for ( var _key in _from ) {
to [ _key ] = _from [ _key ] ;
}
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 ;
}
/ * *
* 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 .
* /
function noop ( ) { }
/ * *
* Always return false .
* /
var no = function no ( ) {
return false ;
} ;
2016-07-08 05:53:22 +08:00
/ * *
* Generate a static keys string from compiler modules .
* /
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 ,
/ * *
* Whether to enable devtools
* /
devtools : process . env . NODE _ENV !== 'production' ,
/ * *
* Error handler for watcher errors
* /
errorHandler : null ,
/ * *
* Ignore certain custom elements
* /
ignoredElements : null ,
/ * *
* Custom user key aliases for v - on
* /
keyCodes : Object . create ( null ) ,
/ * *
* 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 ,
/ * *
* Get the namespace of an element
* /
getTagNamespace : noop ,
/ * *
* 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-07-08 05:53:22 +08:00
/ * *
* List of lifecycle hooks .
* /
_lifecycleHooks : [ 'beforeCreate' , 'created' , 'beforeMount' , 'mounted' , 'beforeUpdate' , 'updated' , 'beforeDestroy' , 'destroyed' , 'activated' , 'deactivated' ] ,
/ * *
* Max circular updates allowed in a scheduler flush cycle .
* /
_maxUpdateCount : 100 ,
/ * *
* Server rendering ?
* /
_isServer : process . env . VUE _ENV === 'server'
} ;
var warn = void 0 ;
var formatComponentName = void 0 ;
if ( process . env . NODE _ENV !== '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-07-08 05:53:22 +08:00
}
} ;
formatComponentName = function formatComponentName ( vm ) {
if ( vm . $root === vm ) {
2016-07-17 13:53:44 +08:00
return 'root instance' ;
2016-07-08 05:53:22 +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' ) {
str += ' - use the "name" option for better debugging messages.)' ;
}
return '(found in ' + str + ')' ;
2016-07-08 05:53:22 +08:00
} ;
} ) ( ) ;
}
2016-06-26 12:53:58 +08:00
/ * *
* Check if a string starts with $ or _
* /
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-06-26 12:53:58 +08:00
function parsePath ( path ) {
if ( bailRE . test ( path ) ) {
return ;
} else {
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 ;
}
}
/* 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
2016-07-08 05:53:22 +08:00
var UA$1 = inBrowser && window . navigator . userAgent . toLowerCase ( ) ;
var isIos = UA$1 && /(iphone|ipad|ipod|ios)/i . test ( UA$1 ) ;
var iosVersionMatch = UA$1 && isIos && UA$1 . match ( /os ([\d_]+)/ ) ;
2016-06-26 12:53:58 +08:00
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 ;
/ * *
* 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 ;
var timerFunc = void 0 ;
function nextTickHandler ( ) {
pending = false ;
var copies = callbacks . slice ( 0 ) ;
callbacks = [ ] ;
for ( var i = 0 ; i < copies . length ; i ++ ) {
copies [ i ] ( ) ;
}
}
/* istanbul ignore else */
if ( typeof MutationObserver !== 'undefined' && ! hasMutationObserverBug ) {
( function ( ) {
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 ) ;
} ;
} ) ( ) ;
} 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-06-26 12:53:58 +08:00
/* istanbul ignore if */
if ( typeof Set !== 'undefined' && /native code/ . test ( Set . toString ( ) ) ) {
// use native Set when available.
2016-06-28 10:25:12 +08:00
_Set = Set ;
2016-06-26 12:53:58 +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-26 12:53:58 +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-07-08 05:53:22 +08:00
var hasProxy = void 0 ;
var proxyHandlers = void 0 ;
var initProxy = void 0 ;
2016-06-26 12:53:58 +08:00
if ( process . env . NODE _ENV !== 'production' ) {
( function ( ) {
2016-07-08 05:53:22 +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,__webpack_require__' // for Webpack/Browserify
) ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
hasProxy = typeof Proxy !== 'undefined' && Proxy . toString ( ) . match ( /native code/ ) ;
proxyHandlers = {
has : function has ( target , key ) {
var has = key in target ;
var isAllowedGlobal = allowedGlobals ( key ) ;
if ( ! has && ! isAllowedGlobal ) {
warn ( 'Trying to access non-existent property "' + key + '" while rendering. ' + 'Make sure to declare reactive data properties in the data option.' , target ) ;
}
return ! isAllowedGlobal ;
2016-06-26 12:53:58 +08:00
}
} ;
2016-07-08 05:53:22 +08:00
initProxy = function initProxy ( vm ) {
if ( hasProxy ) {
vm . _renderProxy = new Proxy ( vm , proxyHandlers ) ;
} else {
vm . _renderProxy = vm ;
2016-06-26 12:53:58 +08:00
}
} ;
} ) ( ) ;
}
2016-07-08 05:53:22 +08:00
var uid$2 = 0 ;
2016-06-26 12:53:58 +08:00
/ * *
* A dep is an observable that can have multiple
* directives subscribing to it .
* /
var Dep = function ( ) {
function Dep ( ) {
2016-07-08 05:53:22 +08:00
this . id = uid$2 ++ ;
2016-06-26 12:53:58 +08:00
this . subs = [ ] ;
}
Dep . prototype . addSub = function addSub ( sub ) {
this . subs . push ( sub ) ;
} ;
Dep . prototype . removeSub = function removeSub ( sub ) {
remove ( this . subs , sub ) ;
} ;
Dep . prototype . depend = function depend ( ) {
if ( Dep . target ) {
Dep . target . addDep ( this ) ;
}
} ;
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 ( ) ;
}
} ;
return Dep ;
} ( ) ;
Dep . target = null ;
var targetStack = [ ] ;
function pushTarget ( _target ) {
if ( Dep . target ) targetStack . push ( Dep . target ) ;
Dep . target = _target ;
}
function popTarget ( ) {
Dep . target = targetStack . pop ( ) ;
}
2016-07-08 05:53:22 +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-06-26 12:53:58 +08:00
/ * *
2016-07-08 05:53:22 +08:00
* Reset the scheduler ' s state .
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
function resetSchedulerState ( ) {
queue . length = 0 ;
has = { } ;
if ( process . env . NODE _ENV !== 'production' ) {
circular = { } ;
}
2016-07-17 13:53:44 +08:00
waiting = flushing = false ;
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* Flush both queues and run the watchers .
* /
function flushSchedulerQueue ( ) {
2016-07-17 13:53:44 +08:00
flushing = true ;
2016-06-26 12:53:58 +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-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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-07-08 05:53:22 +08:00
var id = watcher . id ;
has [ id ] = null ;
watcher . run ( ) ;
// in dev build, check and stop circular updates.
if ( process . env . NODE _ENV !== '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-07-08 05:53:22 +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-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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 .
* /
function queueWatcher ( watcher ) {
var id = watcher . id ;
if ( has [ id ] == null ) {
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-07-08 05:53:22 +08:00
// queue the flush
if ( ! waiting ) {
waiting = true ;
nextTick ( flushSchedulerQueue ) ;
}
}
}
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 .
* /
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 ;
this . sync = ! ! options . sync ;
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 = [ ] ;
this . depIds = new _Set ( ) ;
this . newDepIds = new _Set ( ) ;
// parse expression for getter
if ( typeof expOrFn === 'function' ) {
this . getter = expOrFn ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
this . getter = parsePath ( expOrFn ) ;
if ( ! this . getter ) {
this . getter = function ( ) { } ;
process . env . NODE _ENV !== 'production' && warn ( 'Failed watching path: "' + expOrFn + '" ' + 'Watcher only accepts simple dot-delimited paths. ' + 'For full control, use a function instead.' , vm ) ;
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
this . value = this . lazy ? undefined : this . get ( ) ;
2016-06-26 12:53:58 +08:00
}
/ * *
2016-07-08 05:53:22 +08:00
* Evaluate the getter , and re - collect dependencies .
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
Watcher . prototype . get = function get ( ) {
pushTarget ( this ) ;
2016-07-17 13:53:44 +08:00
var value = this . getter . call ( this . vm , this . vm ) ;
2016-07-08 05:53:22 +08:00
// "touch" every property so they are all tracked as
// dependencies for deep watching
if ( this . deep ) {
traverse ( value ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
popTarget ( ) ;
this . cleanupDeps ( ) ;
return value ;
2016-06-26 12:53:58 +08:00
} ;
/ * *
2016-07-08 05:53:22 +08:00
* Add a dependency to this directive .
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +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-06-26 12:53:58 +08:00
}
} ;
2016-07-08 05:53:22 +08:00
/ * *
* Clean up for dependency collection .
* /
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
Watcher . prototype . cleanupDeps = function cleanupDeps ( ) {
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-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* Subscriber interface .
* Will be called when a dependency changes .
* /
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
Watcher . prototype . update = function update ( ) {
/* istanbul ignore else */
if ( this . lazy ) {
this . dirty = true ;
} else if ( this . sync ) {
this . run ( ) ;
} else {
queueWatcher ( this ) ;
}
} ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* Scheduler job interface .
* Will be called by the scheduler .
* /
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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 ;
if ( this . user ) {
try {
this . cb . call ( this . vm , value , oldValue ) ;
} catch ( e ) {
process . env . NODE _ENV !== '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 ;
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} else {
this . cb . call ( this . vm , value , oldValue ) ;
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
} ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* Evaluate the value of the watcher .
* This only gets called for lazy watchers .
* /
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
Watcher . prototype . evaluate = function evaluate ( ) {
this . value = this . get ( ) ;
this . dirty = false ;
2016-06-26 12:53:58 +08:00
} ;
2016-07-08 05:53:22 +08:00
/ * *
* Depend on all deps collected by this watcher .
* /
Watcher . prototype . depend = function depend ( ) {
var i = this . deps . length ;
while ( i -- ) {
this . deps [ i ] . depend ( ) ;
2016-06-26 12:53:58 +08:00
}
} ;
2016-07-08 05:53:22 +08:00
/ * *
* Remove self from all dependencies ' subcriber list .
* /
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
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 ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} ;
return Watcher ;
} ( ) ;
var seenObjects = new _Set ( ) ;
function traverse ( val , seen ) {
var i = void 0 ,
keys = void 0 ;
if ( ! seen ) {
seen = seenObjects ;
seen . clear ( ) ;
}
var isA = Array . isArray ( val ) ;
var isO = isObject ( val ) ;
if ( ( isA || isO ) && Object . isExtensible ( val ) ) {
if ( val . _ _ob _ _ ) {
var depId = val . _ _ob _ _ . dep . id ;
if ( seen . has ( depId ) ) {
return ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
seen . add ( depId ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
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 ) ;
}
}
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
var arrayProto = Array . prototype ;
var arrayMethods = Object . create ( arrayProto )
2016-06-26 12:53:58 +08:00
/ * *
2016-07-08 05:53:22 +08:00
* Intercept mutating methods and emit events
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
; [ '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 _ _ ;
var inserted = void 0 ;
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 ;
} ) ;
2016-06-26 12:53:58 +08:00
} ) ;
2016-07-08 05:53:22 +08:00
var arrayKeys = Object . getOwnPropertyNames ( arrayMethods ) ;
2016-06-26 12:53:58 +08:00
/ * *
2016-07-08 05:53:22 +08:00
* 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 .
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
var observerState = {
shouldConvert : true ,
isSettingProps : false
2016-06-26 12:53:58 +08:00
} ;
/ * *
2016-07-08 05:53:22 +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-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
var Observer = function ( ) {
// number of vms that has this object as root $data
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
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-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
/ * *
* Walk through each property and convert them into
* getter / setters . This method should only be called when
* value type is Object .
* /
Observer . prototype . walk = function walk ( obj ) {
var val = this . value ;
for ( var key in obj ) {
defineReactive ( val , key , obj [ key ] ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} ;
/ * *
* Observe a list of Array items .
* /
Observer . prototype . observeArray = function observeArray ( items ) {
for ( var i = 0 , l = items . length ; i < l ; i ++ ) {
observe ( items [ i ] ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} ;
return Observer ;
} ( ) ;
// 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 */
2016-06-26 12:53:58 +08:00
}
/ * *
2016-07-08 05:53:22 +08:00
* Augment an target Object or Array by defining
* hidden properties .
*
* istanbul ignore next
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +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 ] ) ;
2016-06-26 12:53:58 +08:00
}
}
/ * *
2016-07-08 05:53:22 +08:00
* 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-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
function observe ( value ) {
if ( ! isObject ( value ) ) {
return ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
var ob = void 0 ;
if ( hasOwn ( value , '__ob__' ) && value . _ _ob _ _ instanceof Observer ) {
ob = value . _ _ob _ _ ;
} else if ( observerState . shouldConvert && ! config . _isServer && ( Array . isArray ( value ) || isPlainObject ( value ) ) && Object . isExtensible ( value ) && ! value . _isVue ) {
ob = new Observer ( value ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return ob ;
2016-06-26 12:53:58 +08:00
}
/ * *
2016-07-08 05:53:22 +08:00
* Define a reactive property on an Object .
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
function defineReactive ( obj , key , val , customSetter ) {
var dep = new Dep ( ) ;
var property = Object . getOwnPropertyDescriptor ( obj , key ) ;
if ( property && property . configurable === false ) {
return ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// 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 ( ) ;
}
if ( Array . isArray ( value ) ) {
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 ;
}
if ( process . env . NODE _ENV !== 'production' && customSetter ) {
customSetter ( ) ;
}
if ( setter ) {
setter . call ( obj , newVal ) ;
} else {
val = newVal ;
}
childOb = observe ( newVal ) ;
dep . notify ( ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} ) ;
2016-06-26 12:53:58 +08:00
}
/ * *
2016-07-08 05:53:22 +08:00
* Set a property on an object . Adds the new property and
* triggers change notification if the property doesn ' t
* already exist .
2016-06-26 12:53:58 +08:00
* /
2016-07-08 05:53:22 +08:00
function set$1 ( obj , key , val ) {
if ( Array . isArray ( obj ) ) {
obj . splice ( key , 1 , val ) ;
return val ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( hasOwn ( obj , key ) ) {
obj [ key ] = val ;
2016-06-26 12:53:58 +08:00
return ;
}
2016-07-08 05:53:22 +08:00
var ob = obj . _ _ob _ _ ;
if ( obj . _isVue || ob && ob . vmCount ) {
process . env . NODE _ENV !== 'production' && warn ( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - delcare it upfront in the data option.' ) ;
2016-06-26 12:53:58 +08:00
return ;
}
2016-07-08 05:53:22 +08:00
if ( ! ob ) {
obj [ key ] = val ;
2016-06-26 12:53:58 +08:00
return ;
}
2016-07-08 05:53:22 +08:00
defineReactive ( ob . value , key , val ) ;
ob . dep . notify ( ) ;
return val ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function initState ( vm ) {
vm . _watchers = [ ] ;
initProps ( vm ) ;
initData ( vm ) ;
initComputed ( vm ) ;
initMethods ( vm ) ;
initWatch ( vm ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function initProps ( vm ) {
var props = vm . $options . props ;
var propsData = vm . $options . propsData ;
if ( props ) {
var keys = vm . $options . _propKeys = Object . keys ( props ) ;
var isRoot = ! vm . $parent ;
// root instance props should be converted
observerState . shouldConvert = isRoot ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var _loop = function _loop ( i ) {
var key = keys [ i ] ;
/* istanbul ignore else */
if ( process . env . NODE _ENV !== 'production' ) {
defineReactive ( vm , key , validateProp ( key , props , propsData , vm ) , function ( ) {
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 ) ;
}
} ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
defineReactive ( vm , key , validateProp ( key , props , propsData , vm ) ) ;
2016-06-26 12:53:58 +08:00
}
} ;
2016-07-08 05:53:22 +08:00
for ( var i = 0 ; i < keys . length ; i ++ ) {
_loop ( i ) ;
}
observerState . shouldConvert = true ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function initData ( vm ) {
var data = vm . $options . data ;
data = vm . _data = typeof data === 'function' ? data . call ( vm ) : data || { } ;
if ( ! isPlainObject ( data ) ) {
data = { } ;
process . env . NODE _ENV !== 'production' && warn ( 'data functions should return an object.' , vm ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// proxy data on instance
var keys = Object . keys ( data ) ;
var props = vm . $options . props ;
var i = keys . length ;
while ( i -- ) {
if ( props && hasOwn ( props , keys [ i ] ) ) {
process . env . NODE _ENV !== 'production' && warn ( 'The data property "' + keys [ i ] + '" is already declared as a prop. ' + 'Use prop default value instead.' , vm ) ;
} else {
proxy ( vm , keys [ i ] ) ;
}
}
// observe data
observe ( data ) ;
data . _ _ob _ _ && data . _ _ob _ _ . vmCount ++ ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
var computedSharedDefinition = {
enumerable : true ,
configurable : true ,
get : noop ,
set : noop
} ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function initComputed ( vm ) {
var computed = vm . $options . computed ;
if ( computed ) {
for ( var _key in computed ) {
var userDef = computed [ _key ] ;
if ( typeof userDef === 'function' ) {
computedSharedDefinition . get = makeComputedGetter ( userDef , vm ) ;
computedSharedDefinition . set = noop ;
} else {
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-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
Object . defineProperty ( vm , _key , computedSharedDefinition ) ;
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
function makeComputedGetter ( getter , owner ) {
var watcher = new Watcher ( owner , getter , noop , {
lazy : true
} ) ;
return function computedGetter ( ) {
if ( watcher . dirty ) {
watcher . evaluate ( ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( Dep . target ) {
watcher . depend ( ) ;
}
return watcher . value ;
} ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function initMethods ( vm ) {
var methods = vm . $options . methods ;
if ( methods ) {
for ( var _key2 in methods ) {
vm [ _key2 ] = bind ( methods [ _key2 ] , vm ) ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function initWatch ( vm ) {
var watch = vm . $options . watch ;
if ( watch ) {
for ( var _key3 in watch ) {
var handler = watch [ _key3 ] ;
if ( Array . isArray ( handler ) ) {
for ( var i = 0 ; i < handler . length ; i ++ ) {
createWatcher ( vm , _key3 , handler [ i ] ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} else {
createWatcher ( vm , _key3 , handler ) ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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 ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function stateMixin ( Vue ) {
// 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-26 12:53:58 +08:00
} ;
2016-07-08 05:53:22 +08:00
if ( process . env . NODE _ENV !== 'production' ) {
dataDef . set = function ( newData ) {
warn ( 'Avoid replacing instance root $data. ' + 'Use nested data properties instead.' , this ) ;
} ;
}
Object . defineProperty ( Vue . prototype , '$data' , dataDef ) ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
Vue . prototype . $watch = function ( expOrFn , cb , options ) {
var vm = this ;
options = options || { } ;
options . user = true ;
var watcher = new Watcher ( vm , expOrFn , cb , options ) ;
if ( options . immediate ) {
cb . call ( vm , watcher . value ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return function unwatchFn ( ) {
watcher . teardown ( ) ;
} ;
2016-06-26 12:53:58 +08:00
} ;
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var VNode = function VNode ( tag , data , children , text , elm , ns , context , host , componentOptions ) {
this . tag = tag ;
this . data = data ;
this . children = children ;
this . text = text ;
this . elm = elm ;
this . ns = ns ;
this . context = context ;
this . host = host ;
this . key = data && data . key ;
this . componentOptions = componentOptions ;
this . child = undefined ;
this . parent = undefined ;
this . raw = false ;
// 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-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var emptyVNode = function emptyVNode ( ) {
return new VNode ( undefined , undefined , undefined , '' ) ;
} ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function normalizeChildren ( children , ns ) {
// invoke children thunks.
// components always receive their children as thunks so that they
// can perform the actual render inside their own dependency collection cycle.
if ( typeof children === 'function' ) {
children = children ( ) ;
}
if ( isPrimitive ( children ) ) {
return [ createTextVNode ( children ) ] ;
}
if ( Array . isArray ( children ) ) {
var res = [ ] ;
for ( var i = 0 , l = children . length ; i < l ; i ++ ) {
var c = children [ i ] ;
var last = res [ res . length - 1 ] ;
// nested
if ( Array . isArray ( c ) ) {
2016-07-17 13:53:44 +08:00
res . push . apply ( res , normalizeChildren ( c , ns ) ) ;
2016-07-08 05:53:22 +08:00
} else if ( isPrimitive ( c ) ) {
if ( last && last . text ) {
last . text += String ( c ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
// convert primitive to vnode
res . push ( createTextVNode ( c ) ) ;
}
} else if ( c instanceof VNode ) {
if ( c . text && last && last . text ) {
last . text += c . text ;
} else {
// inherit parent namespace
if ( ns ) {
applyNS ( c , ns ) ;
}
res . push ( c ) ;
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
return res ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function createTextVNode ( val ) {
return new VNode ( undefined , undefined , undefined , String ( val ) ) ;
}
2016-06-26 12:53:58 +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-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
}
function updateListeners ( on , oldOn , add , remove ) {
var name = void 0 ,
cur = void 0 ,
old = void 0 ,
fn = void 0 ,
event = void 0 ,
capture = void 0 ;
for ( name in on ) {
cur = on [ name ] ;
old = oldOn [ name ] ;
if ( ! old ) {
capture = name . charAt ( 0 ) === '!' ;
event = capture ? name . slice ( 1 ) : name ;
if ( Array . isArray ( cur ) ) {
add ( event , cur . invoker = arrInvoker ( cur ) , capture ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
fn = cur ;
cur = on [ name ] = { } ;
cur . fn = fn ;
add ( event , cur . invoker = fnInvoker ( cur ) , capture ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} else if ( Array . isArray ( old ) ) {
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-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
for ( name in oldOn ) {
if ( ! on [ name ] ) {
event = name . charAt ( 0 ) === '!' ? name . slice ( 1 ) : name ;
remove ( event , oldOn [ name ] . invoker ) ;
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
function arrInvoker ( arr ) {
return function ( ev ) {
var single = arguments . length === 1 ;
for ( var i = 0 ; i < arr . length ; i ++ ) {
single ? arr [ i ] ( ev ) : arr [ i ] . apply ( null , arguments ) ;
}
} ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function fnInvoker ( o ) {
return function ( ev ) {
var single = arguments . length === 1 ;
single ? o . fn ( ev ) : o . fn . apply ( null , arguments ) ;
} ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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-07-08 05:53:22 +08:00
}
2016-07-17 13:53:44 +08:00
vm . $parent = parent ;
vm . $root = parent ? parent . $root : vm ;
2016-07-08 05:53:22 +08:00
vm . $children = [ ] ;
vm . $refs = { } ;
vm . _watcher = null ;
vm . _inactive = false ;
vm . _isMounted = false ;
vm . _isDestroyed = false ;
vm . _isBeingDestroyed = false ;
}
function lifecycleMixin ( Vue ) {
Vue . prototype . _mount = function ( el , hydrating ) {
var vm = this ;
vm . $el = el ;
if ( ! vm . $options . render ) {
vm . $options . render = emptyVNode ;
if ( process . env . NODE _ENV !== 'production' ) {
/* 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 ) ;
} else {
warn ( 'Failed to mount component: template or render function not defined.' , vm ) ;
}
}
}
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 ;
} ;
Vue . prototype . _update = function ( vnode , hydrating ) {
var vm = this ;
if ( vm . _isMounted ) {
callHook ( vm , 'beforeUpdate' ) ;
}
var prevEl = vm . $el ;
if ( ! vm . _vnode ) {
// Vue.prototype.__patch__ is injected in entry points
// based on the rendering backend used.
vm . $el = vm . _ _patch _ _ ( vm . $el , vnode , hydrating ) ;
} else {
vm . $el = vm . _ _patch _ _ ( vm . _vnode , vnode ) ;
}
vm . _vnode = vnode ;
// update __vue__ reference
if ( prevEl ) {
prevEl . _ _vue _ _ = null ;
}
if ( vm . $el ) {
vm . $el . _ _vue _ _ = vm ;
}
// 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 ;
}
if ( vm . _isMounted ) {
callHook ( vm , 'updated' ) ;
}
} ;
Vue . prototype . _updateFromParent = function ( propsData , listeners , parentVnode , renderChildren ) {
var vm = this ;
vm . $options . _parentVnode = parentVnode ;
vm . $options . _renderChildren = renderChildren ;
// update props
if ( propsData && vm . $options . props ) {
observerState . shouldConvert = false ;
if ( process . env . NODE _ENV !== 'production' ) {
observerState . isSettingProps = true ;
}
var propKeys = vm . $options . _propKeys || [ ] ;
for ( var i = 0 ; i < propKeys . length ; i ++ ) {
var key = propKeys [ i ] ;
vm [ key ] = validateProp ( key , vm . $options . props , propsData , vm ) ;
}
observerState . shouldConvert = true ;
if ( process . env . NODE _ENV !== 'production' ) {
observerState . isSettingProps = false ;
}
}
// update listeners
if ( listeners ) {
var oldListeners = vm . $options . _parentListeners ;
vm . $options . _parentListeners = listeners ;
vm . _updateListeners ( listeners , oldListeners ) ;
}
} ;
Vue . prototype . $forceUpdate = function ( ) {
var vm = this ;
if ( vm . _watcher ) {
vm . _watcher . update ( ) ;
}
if ( vm . _watchers . length ) {
for ( var i = 0 ; i < vm . _watchers . length ; i ++ ) {
vm . _watchers [ i ] . update ( true /* shallow */ ) ;
}
}
} ;
Vue . prototype . $destroy = function ( ) {
var vm = this ;
if ( vm . _isBeingDestroyed ) {
return ;
}
callHook ( vm , 'beforeDestroy' ) ;
vm . _isBeingDestroyed = true ;
// remove self from parent
var parent = vm . $parent ;
2016-07-24 10:48:09 +08:00
if ( parent && ! parent . _isBeingDestroyed && ! vm . $options . abstract ) {
2016-07-08 05:53:22 +08:00
remove ( parent . $children , vm ) ;
}
// teardown watchers
if ( vm . _watcher ) {
vm . _watcher . teardown ( ) ;
}
var i = vm . _watchers . length ;
while ( i -- ) {
vm . _watchers [ i ] . teardown ( ) ;
}
// remove reference from data ob
// frozen object may not have observer.
if ( vm . _data . _ _ob _ _ ) {
vm . _data . _ _ob _ _ . vmCount -- ;
}
// call the last hook...
vm . _isDestroyed = true ;
callHook ( vm , 'destroyed' ) ;
// turn off all instance listeners.
vm . $off ( ) ;
// remove __vue__ reference
if ( vm . $el ) {
vm . $el . _ _vue _ _ = null ;
}
} ;
}
function callHook ( vm , hook ) {
vm . $emit ( 'pre-hook:' + 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 ) ;
function createComponent ( Ctor , data , parent , context , host , _children , tag ) {
// ensure children is a thunk
if ( process . env . NODE _ENV !== 'production' && _children && typeof _children !== 'function' ) {
warn ( 'A component\'s children should be a function that returns the ' + 'children array. This allows the component to track the children ' + 'dependencies and optimizes re-rendering.' ) ;
}
if ( ! Ctor ) {
return ;
}
if ( isObject ( Ctor ) ) {
Ctor = Vue . extend ( Ctor ) ;
}
if ( typeof Ctor !== 'function' ) {
if ( process . env . NODE _ENV !== 'production' ) {
warn ( 'Invalid Component definition: ' + Ctor , parent ) ;
}
return ;
}
// async component
if ( ! Ctor . cid ) {
if ( Ctor . resolved ) {
Ctor = Ctor . resolved ;
} else {
Ctor = resolveAsyncComponent ( Ctor , function ( ) {
// it's ok to queue this on every render because
// $forceUpdate is buffered. this is only called
// if the
parent . $forceUpdate ( ) ;
} ) ;
if ( ! Ctor ) {
// return nothing if this is indeed an async component
// wait for the callback to trigger parent update.
return ;
}
}
}
data = data || { } ;
// extract props
var propsData = extractProps ( data , Ctor ) ;
// functional component
if ( Ctor . options . functional ) {
var _ret = function ( ) {
var props = { } ;
var propOptions = Ctor . options . props ;
if ( propOptions ) {
Object . keys ( propOptions ) . forEach ( function ( key ) {
props [ key ] = validateProp ( key , propOptions , propsData ) ;
2016-06-26 12:53:58 +08:00
} ) ;
2016-07-08 05:53:22 +08:00
}
return {
2016-07-24 10:48:09 +08:00
v : Ctor . options . render . call ( null , parent . $createElement , {
props : props ,
parent : parent ,
data : data ,
children : function children ( ) {
2016-07-08 05:53:22 +08:00
return normalizeChildren ( _children ) ;
2016-07-24 10:48:09 +08:00
} ,
slots : function slots ( ) {
return resolveSlots ( _children ) ;
}
} )
2016-07-08 05:53:22 +08:00
} ;
} ( ) ;
if ( typeof _ret === "object" ) return _ret . v ;
}
// merge component management hooks onto the placeholder node
mergeHooks ( data ) ;
// 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-07-08 05:53:22 +08:00
// return a placeholder vnode
var name = Ctor . options . name || tag ;
var vnode = new VNode ( 'vue-component-' + Ctor . cid + ( name ? '-' + name : '' ) , data , undefined , undefined , undefined , undefined , context , host , { Ctor : Ctor , propsData : propsData , listeners : listeners , parent : parent , tag : tag , children : _children } ) ;
return vnode ;
}
function createComponentInstanceForVnode ( vnode // we know it's MountedComponentVNode but flow doesn't
) {
var vnodeComponentOptions = vnode . componentOptions ;
var options = {
_isComponent : true ,
parent : vnodeComponentOptions . parent ,
propsData : vnodeComponentOptions . propsData ,
_componentTag : vnodeComponentOptions . tag ,
_parentVnode : vnode ,
_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 ) ;
}
function init ( vnode , hydrating ) {
if ( ! vnode . child ) {
var child = vnode . child = createComponentInstanceForVnode ( vnode ) ;
child . $mount ( hydrating ? vnode . elm : undefined , hydrating ) ;
}
}
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-07-08 05:53:22 +08:00
options . listeners , // updated listeners
vnode , // new parent vnode
options . children // new children
) ;
2016-07-24 10:48:09 +08:00
// always update abstract components.
if ( child . $options . abstract ) {
child . $forceUpdate ( ) ;
}
2016-07-08 05:53:22 +08:00
}
function insert ( vnode ) {
if ( ! vnode . child . _isMounted ) {
vnode . child . _isMounted = true ;
callHook ( vnode . child , 'mounted' ) ;
}
if ( vnode . data . keepAlive ) {
vnode . child . _inactive = false ;
callHook ( vnode . child , 'activated' ) ;
}
}
function destroy ( vnode ) {
if ( ! vnode . child . _isDestroyed ) {
if ( ! vnode . data . keepAlive ) {
vnode . child . $destroy ( ) ;
} else {
vnode . child . _inactive = true ;
callHook ( vnode . child , 'deactivated' ) ;
}
}
}
function resolveAsyncComponent ( factory , cb ) {
if ( factory . requested ) {
// pool callbacks
factory . pendingCallbacks . push ( cb ) ;
} else {
var _ret2 = function ( ) {
factory . requested = true ;
var cbs = factory . pendingCallbacks = [ cb ] ;
var sync = true ;
factory (
// resolve
function ( res ) {
if ( isObject ( res ) ) {
res = Vue . extend ( res ) ;
}
// cache resolved
factory . resolved = res ;
// 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 ) ;
}
}
} ,
// reject
function ( reason ) {
process . env . NODE _ENV !== 'production' && warn ( 'Failed to resolve async component: ' + factory + ( reason ? '\nReason: ' + reason : '' ) ) ;
} ) ;
sync = false ;
// return in case resolved synchronously
return {
v : factory . resolved
} ;
} ( ) ;
if ( typeof _ret2 === "object" ) return _ret2 . v ;
}
}
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-07-08 05:53:22 +08:00
var staticAttrs = data . staticAttrs ;
2016-07-24 10:48:09 +08:00
if ( attrs || props || domProps || staticAttrs ) {
for ( var key in propOptions ) {
var altKey = hyphenate ( key ) ;
checkProp ( res , props , key , altKey , true ) || checkProp ( res , attrs , key , altKey ) || checkProp ( res , domProps , key , altKey ) || checkProp ( res , staticAttrs , key , altKey ) ;
}
2016-07-08 05:53:22 +08:00
}
return res ;
}
2016-07-24 10:48:09 +08:00
function checkProp ( res , hash , key , altKey , preserve ) {
2016-07-08 05:53:22 +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-07-08 05:53:22 +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-07-08 05:53:22 +08:00
return true ;
}
}
return false ;
}
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-07-08 05:53:22 +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 ( _ , _ _ ) ;
} ;
}
// 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-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-07-08 05:53:22 +08:00
}
2016-07-17 13:53:44 +08:00
function _createElement ( context , tag , data , children ) {
2016-07-08 05:53:22 +08:00
var parent = renderState . activeInstance ;
var host = context !== parent ? parent : undefined ;
if ( ! parent ) {
process . env . NODE _ENV !== 'production' && warn ( 'createElement cannot be called outside of component ' + 'render functions.' ) ;
return ;
}
2016-07-17 13:53:44 +08:00
if ( data && data . _ _ob _ _ ) {
process . env . NODE _ENV !== 'production' && warn ( 'Avoid using observed data object as vnode data: ' + JSON . stringify ( data ) + '\n' + 'Always create fresh vnode data objects in each render!' , context ) ;
return ;
}
2016-07-08 05:53:22 +08:00
if ( ! tag ) {
// in case of component :is set to falsy value
return emptyVNode ( ) ;
}
if ( typeof tag === 'string' ) {
var Ctor = void 0 ;
2016-07-17 13:53:44 +08:00
var ns = config . getTagNamespace ( tag ) ;
2016-07-08 05:53:22 +08:00
if ( config . isReservedTag ( tag ) ) {
// platform built-in elements
2016-07-17 13:53:44 +08:00
return new VNode ( tag , data , normalizeChildren ( children , ns ) , undefined , undefined , ns , context , host ) ;
2016-07-08 05:53:22 +08:00
} else if ( Ctor = resolveAsset ( context . $options , 'components' , tag ) ) {
// component
return createComponent ( Ctor , data , parent , context , host , children , tag ) ;
} 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
return new VNode ( tag , data , normalizeChildren ( children , ns ) , undefined , undefined , ns , context , host ) ;
}
} else {
// direct component options / constructor
return createComponent ( tag , data , parent , context , host , children ) ;
}
}
var renderState = {
activeInstance : null
} ;
function initRender ( vm ) {
vm . $vnode = null ; // the placeholder node in parent tree
vm . _vnode = null ; // the root of the child tree
vm . _staticTrees = null ;
vm . $slots = { } ;
// bind the public createElement fn to this instance
// so that we get proper render context inside it.
vm . $createElement = bind ( createElement , vm ) ;
if ( vm . $options . el ) {
vm . $mount ( vm . $options . el ) ;
}
}
function renderMixin ( Vue ) {
Vue . prototype . $nextTick = function ( fn ) {
nextTick ( fn , this ) ;
} ;
Vue . prototype . _render = function ( ) {
var vm = this ;
// set current active instance
var prev = renderState . activeInstance ;
renderState . activeInstance = vm ;
var _vm$$options = vm . $options ;
var render = _vm$$options . render ;
var staticRenderFns = _vm$$options . staticRenderFns ;
var _renderChildren = _vm$$options . _renderChildren ;
var _parentVnode = _vm$$options . _parentVnode ;
2016-07-17 13:53:44 +08:00
if ( staticRenderFns && ! vm . _staticTrees ) {
vm . _staticTrees = [ ] ;
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-07-08 05:53:22 +08:00
// resolve slots. becaues slots are rendered in parent scope,
// we set the activeInstance to parent.
2016-07-24 10:48:09 +08:00
vm . $slots = resolveSlots ( _renderChildren ) ;
2016-07-08 05:53:22 +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 ( process . env . NODE _ENV !== '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-07-08 05:53:22 +08:00
// return empty vnode in case the render function errored out
if ( ! ( vnode instanceof VNode ) ) {
if ( process . env . NODE _ENV !== 'production' && Array . isArray ( vnode ) ) {
warn ( 'Multiple root nodes returned from render function. Render function ' + 'should return a single root node.' , vm ) ;
}
vnode = emptyVNode ( ) ;
}
// set parent
vnode . parent = _parentVnode ;
// restore render state
renderState . activeInstance = prev ;
return vnode ;
} ;
// shorthands used in render functions
Vue . prototype . _h = createElement ;
// toString for mustaches
Vue . prototype . _s = _toString ;
// number conversion
Vue . prototype . _n = toNumber ;
//
Vue . prototype . _m = function renderStatic ( index ) {
return this . _staticTrees [ index ] || ( this . _staticTrees [ index ] = this . $options . staticRenderFns [ index ] . call ( this . _renderProxy ) ) ;
} ;
// filter resolution helper
var identity = function identity ( _ ) {
return _ ;
} ;
Vue . prototype . _f = function resolveFilter ( id ) {
return resolveAsset ( this . $options , 'filters' , id , true ) || identity ;
} ;
// render v-for
Vue . prototype . _l = function renderList ( val , render ) {
var ret = void 0 ,
i = void 0 ,
l = void 0 ,
keys = void 0 ,
key = void 0 ;
if ( Array . isArray ( val ) ) {
ret = new Array ( val . length ) ;
for ( i = 0 , l = val . length ; i < l ; i ++ ) {
ret [ i ] = render ( val [ i ] , i ) ;
}
} else if ( typeof val === 'number' ) {
ret = new Array ( val ) ;
for ( i = 0 ; i < val ; i ++ ) {
ret [ i ] = render ( i + 1 , i ) ;
}
} 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 ] ;
ret [ i ] = render ( val [ key ] , key , i ) ;
}
}
return ret ;
} ;
// apply v-bind object
2016-07-24 10:48:09 +08:00
Vue . prototype . _b = function bindProps ( vnode , value , asProp ) {
2016-07-08 05:53:22 +08:00
if ( value ) {
if ( ! isObject ( value ) ) {
process . env . NODE _ENV !== 'production' && warn ( 'v-bind without argument expects an Object or Array value' , this ) ;
} else {
if ( Array . isArray ( value ) ) {
value = toObject ( value ) ;
}
var data = vnode . data ;
for ( var key in value ) {
2016-07-24 10:48:09 +08:00
var hash = asProp || config . mustUseProp ( key ) ? data . domProps || ( data . domProps = { } ) : data . attrs || ( data . attrs = { } ) ;
2016-07-08 05:53:22 +08:00
hash [ key ] = value [ key ] ;
}
}
}
} ;
// expose v-on keyCodes
Vue . prototype . _k = function getKeyCodes ( key ) {
return config . keyCodes [ key ] ;
} ;
}
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-07-08 05:53:22 +08:00
} else {
2016-07-17 13:53:44 +08:00
slot . push ( child ) ;
2016-07-08 05:53:22 +08:00
}
2016-07-17 13:53:44 +08:00
} else {
defaultSlot . push ( child ) ;
2016-07-08 05:53:22 +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-07-08 05:53:22 +08:00
}
2016-07-24 10:48:09 +08:00
return slots ;
2016-07-08 05:53:22 +08:00
}
function initEvents ( vm ) {
vm . _events = Object . create ( null ) ;
// init parent attached events
var listeners = vm . $options . _parentListeners ;
var on = bind ( vm . $on , vm ) ;
var off = bind ( vm . $off , vm ) ;
vm . _updateListeners = function ( listeners , oldListeners ) {
updateListeners ( listeners , oldListeners || { } , on , off ) ;
} ;
if ( listeners ) {
vm . _updateListeners ( listeners ) ;
}
}
function eventsMixin ( Vue ) {
Vue . prototype . $on = function ( event , fn ) {
var vm = this ; ( vm . _events [ event ] || ( vm . _events [ event ] = [ ] ) ) . push ( fn ) ;
return vm ;
} ;
Vue . prototype . $once = function ( event , fn ) {
var vm = this ;
function on ( ) {
vm . $off ( event , on ) ;
fn . apply ( vm , arguments ) ;
}
on . fn = fn ;
vm . $on ( event , on ) ;
return vm ;
} ;
Vue . prototype . $off = function ( event , fn ) {
var vm = this ;
// all
if ( ! arguments . length ) {
vm . _events = Object . create ( null ) ;
return vm ;
}
// specific event
var cbs = vm . _events [ event ] ;
if ( ! cbs ) {
return vm ;
}
if ( arguments . length === 1 ) {
vm . _events [ event ] = null ;
return vm ;
}
// specific handler
var cb = void 0 ;
var i = cbs . length ;
while ( i -- ) {
cb = cbs [ i ] ;
if ( cb === fn || cb . fn === fn ) {
cbs . splice ( i , 1 ) ;
break ;
}
}
return vm ;
} ;
Vue . prototype . $emit = function ( event ) {
var vm = this ;
var cbs = vm . _events [ event ] ;
if ( cbs ) {
cbs = cbs . length > 1 ? toArray$1 ( cbs ) : cbs ;
var args = toArray$1 ( arguments , 1 ) ;
for ( var i = 0 , l = cbs . length ; i < l ; i ++ ) {
cbs [ i ] . apply ( vm , args ) ;
}
}
return vm ;
} ;
}
var uid = 0 ;
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 {
vm . $options = mergeOptions ( resolveConstructorOptions ( vm ) , options || { } , vm ) ;
}
/* istanbul ignore else */
if ( process . env . NODE _ENV !== 'production' ) {
initProxy ( vm ) ;
} else {
vm . _renderProxy = vm ;
}
// expose real self
vm . _self = vm ;
initLifecycle ( vm ) ;
initEvents ( vm ) ;
callHook ( vm , 'beforeCreate' ) ;
initState ( vm ) ;
callHook ( vm , 'created' ) ;
initRender ( vm ) ;
} ;
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 ;
}
}
function Vue ( options ) {
this . _init ( options ) ;
}
initMixin ( Vue ) ;
stateMixin ( Vue ) ;
eventsMixin ( Vue ) ;
lifecycleMixin ( Vue ) ;
renderMixin ( Vue ) ;
/ * *
* Option overwriting strategies are functions that handle
* how to merge a parent option value and a child option
* value into the final value .
* /
var strats = config . optionMergeStrategies ;
/ * *
* Options with restrictions
* /
if ( process . env . NODE _ENV !== '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 ) ;
} ;
strats . name = function ( parent , child , vm ) {
if ( vm ) {
warn ( 'options "name" can only be used as a component definition option, ' + 'not during instance creation.' ) ;
}
return defaultStrat ( parent , child ) ;
} ;
}
/ * *
* Helper that recursively merges two data objects together .
* /
function mergeData ( to , from ) {
var key = void 0 ,
toVal = void 0 ,
fromVal = void 0 ;
for ( key in from ) {
toVal = to [ key ] ;
fromVal = from [ key ] ;
if ( ! hasOwn ( to , key ) ) {
set$1 ( 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' ) {
process . env . NODE _ENV !== '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 ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
return defaultData ;
}
} ;
}
} ;
/ * *
* Hooks and param attributes are merged as arrays .
* /
function mergeHook ( parentVal , childVal ) {
return childVal ? parentVal ? parentVal . concat ( childVal ) : Array . isArray ( childVal ) ? childVal : [ childVal ] : parentVal ;
}
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 ) {
var res = Object . create ( parentVal || null ) ;
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 ) {
/* istanbul ignore if */
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 ] ;
if ( parent && ! Array . isArray ( parent ) ) {
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 .
* /
function normalizeComponents ( options ) {
if ( options . components ) {
var components = options . components ;
var def = void 0 ;
for ( var key in components ) {
var lower = key . toLowerCase ( ) ;
if ( isBuiltInTag ( lower ) || config . isReservedTag ( lower ) ) {
process . env . NODE _ENV !== '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 .
* /
function normalizeProps ( options ) {
var props = options . props ;
if ( ! props ) return ;
var res = { } ;
var i = void 0 ,
val = void 0 ,
name = void 0 ;
if ( Array . isArray ( props ) ) {
i = props . length ;
while ( i -- ) {
val = props [ i ] ;
if ( typeof val === 'string' ) {
name = camelize ( val ) ;
res [ name ] = { type : null } ;
} else if ( process . env . NODE _ENV !== '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 ;
}
/ * *
* Normalize raw function directives into object format .
* /
function normalizeDirectives ( options ) {
var dirs = options . directives ;
if ( dirs ) {
for ( var key in dirs ) {
var def = dirs [ key ] ;
if ( typeof def === 'function' ) {
dirs [ key ] = { bind : def , update : def } ;
}
}
}
}
/ * *
* Merge two option objects into a new one .
* Core utility used in both instantiation and inheritance .
* /
function mergeOptions ( parent , child , vm ) {
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 ) ;
}
if ( child . mixins ) {
for ( var i = 0 , l = child . mixins . length ; i < l ; i ++ ) {
var mixin = child . mixins [ i ] ;
if ( mixin . prototype instanceof Vue ) {
mixin = mixin . options ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
parent = mergeOptions ( parent , mixin , vm ) ;
}
}
var options = { } ;
var key = void 0 ;
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 ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* 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
assets [ camelize ( id ) ] ||
// Pascal Case ID
assets [ capitalize ( camelize ( id ) ) ] ;
if ( process . env . NODE _ENV !== 'production' && warnMissing && ! res ) {
warn ( 'Failed to resolve ' + type . slice ( 0 , - 1 ) + ': ' + id , options ) ;
}
return res ;
}
function validateProp ( key , propOptions , propsData , vm ) {
/* istanbul ignore if */
if ( ! propsData ) return ;
var prop = propOptions [ key ] ;
var absent = ! hasOwn ( propsData , key ) ;
var value = propsData [ key ] ;
// handle boolean props
if ( prop . type === Boolean ) {
if ( absent && ! hasOwn ( prop , 'default' ) ) {
value = false ;
} else if ( value === '' || value === hyphenate ( key ) ) {
value = true ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +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-06-26 12:53:58 +08:00
observerState . shouldConvert = true ;
2016-07-08 05:53:22 +08:00
observe ( value ) ;
2016-07-26 10:07:26 +08:00
observerState . shouldConvert = prevShouldConvert ;
2016-07-08 05:53:22 +08:00
}
if ( process . env . NODE _ENV !== 'production' ) {
assertProp ( prop , key , value , vm , absent ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return value ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
/ * *
* Get the default value of a prop .
* /
function getPropDefaultValue ( vm , prop , name ) {
// no default, return undefined
if ( ! hasOwn ( prop , 'default' ) ) {
return undefined ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
var def = prop . default ;
// warn against non-factory defaults for Object & Array
if ( isObject ( def ) ) {
process . env . NODE _ENV !== '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 ) {
warn ( 'Missing required prop: "' + name + '"' , vm ) ;
return ;
}
if ( value == null && ! prop . required ) {
return ;
}
var type = prop . type ;
var valid = ! type ;
var expectedTypes = [ ] ;
if ( type ) {
if ( ! Array . isArray ( type ) ) {
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 ) {
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 ;
}
var validator = prop . validator ;
if ( validator ) {
if ( ! validator ( value ) ) {
warn ( 'Invalid prop: custom validator check failed for prop "' + name + '".' , vm ) ;
}
}
}
/ * *
* Assert the type of a value
* /
function assertType ( value , type ) {
var valid = void 0 ;
var expectedType = void 0 ;
if ( type === String ) {
expectedType = 'string' ;
valid = typeof value === expectedType ;
} else if ( type === Number ) {
expectedType = 'number' ;
valid = typeof value === expectedType ;
} else if ( type === Boolean ) {
expectedType = 'boolean' ;
valid = typeof value === expectedType ;
} else if ( type === Function ) {
expectedType = 'function' ;
valid = typeof value === expectedType ;
} else if ( type === Object ) {
expectedType = 'Object' ;
valid = isPlainObject ( value ) ;
} else if ( type === Array ) {
expectedType = 'Array' ;
valid = Array . isArray ( value ) ;
} else {
expectedType = type . name || type . toString ( ) ;
valid = value instanceof type ;
}
return {
valid : valid ,
expectedType : expectedType
} ;
}
// 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' ) ;
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' ) ;
/* istanbul ignore next */
var isRenderableAttr = function isRenderableAttr ( name ) {
return isAttr ( name ) || name . indexOf ( 'data-' ) === 0 || name . indexOf ( 'aria-' ) === 0 ;
} ;
var propsToAttrMap = {
acceptCharset : 'accept-charset' ,
className : 'class' ,
htmlFor : 'for' ,
httpEquiv : 'http-equiv'
} ;
var isFalsyAttrValue = function isFalsyAttrValue ( val ) {
return val == null || val === false ;
} ;
function genClassForVnode ( vnode ) {
var data = vnode . data ;
// Important: check if this is a component container node
// or a child component root node
var i = void 0 ;
if ( ( i = vnode . child ) && ( i = i . _vnode . data ) ) {
data = mergeClassData ( i , data ) ;
}
if ( ( i = vnode . parent ) && ( i = i . data ) ) {
data = mergeClassData ( data , i ) ;
}
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 + ' ' ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return res . slice ( 0 , - 1 ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
/* istanbul ignore next */
return res ;
2016-06-26 12:53:58 +08:00
}
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-26 12:53:58 +08:00
2016-07-08 05:53:22 +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 ) ;
var isReservedTag = function isReservedTag ( tag ) {
return isHTMLTag ( tag ) || isSVG ( tag ) ;
} ;
2016-07-08 05:53:22 +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' ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
var UA = inBrowser && window . navigator . userAgent . toLowerCase ( ) ;
var isIE = UA && /msie|trident/ . test ( UA ) ;
var isIE9 = UA && UA . indexOf ( 'msie 9.0' ) > 0 ;
var isAndroid = UA && UA . indexOf ( 'android' ) > 0 ;
2016-07-26 10:07:26 +08:00
// some browsers, e.g. PhantomJS, encodes attribute values for innerHTML
// this causes problems with the in-browser parser.
var shouldDecodeAttr = inBrowser ? function ( ) {
var div = document . createElement ( 'div' ) ;
div . innerHTML = '<div a=">">' ;
return div . innerHTML . indexOf ( '>' ) > 0 ;
} ( ) : false ;
2016-07-08 05:53:22 +08:00
// Regular Expressions for parsing tags and attributes
var singleAttrIdentifier = /([^\s"'<>\/=]+)/ ;
2016-07-26 10:07:26 +08:00
var singleAttrAssign = /(?:=)/ ;
2016-07-08 05:53:22 +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-07-08 05:53:22 +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)
var isSpecialTag = makeMap ( 'script,style' , true ) ;
var reCache = { } ;
2016-07-26 10:07:26 +08:00
function parseHTML ( html , options ) {
2016-07-08 05:53:22 +08:00
var stack = [ ] ;
2016-07-26 10:07:26 +08:00
var expectHTML = options . expectHTML ;
var isUnaryTag = options . isUnaryTag || no ;
var shouldDecodeAttr = options . shouldDecodeAttr ;
2016-07-08 05:53:22 +08:00
var index = 0 ;
var last = void 0 ,
lastTag = void 0 ;
while ( html ) {
last = html ;
// Make sure we're not in a script or style element
if ( ! lastTag || ! isSpecialTag ( lastTag ) ) {
var textEnd = html . indexOf ( '<' ) ;
if ( textEnd === 0 ) {
// Comment:
if ( /^<!--/ . test ( html ) ) {
var commentEnd = html . indexOf ( '-->' ) ;
if ( commentEnd >= 0 ) {
advance ( commentEnd + 3 ) ;
continue ;
}
}
// http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
if ( /^<!\[/ . test ( html ) ) {
var conditionalEnd = html . indexOf ( ']>' ) ;
if ( conditionalEnd >= 0 ) {
advance ( conditionalEnd + 2 ) ;
continue ;
}
}
// Doctype:
var doctypeMatch = html . match ( doctype ) ;
if ( doctypeMatch ) {
advance ( doctypeMatch [ 0 ] . length ) ;
continue ;
}
// End tag:
var endTagMatch = html . match ( endTag ) ;
if ( endTagMatch ) {
var curIndex = index ;
advance ( endTagMatch [ 0 ] . length ) ;
parseEndTag ( endTagMatch [ 0 ] , endTagMatch [ 1 ] , curIndex , index ) ;
continue ;
}
// Start tag:
var startTagMatch = parseStartTag ( ) ;
if ( startTagMatch ) {
handleStartTag ( startTagMatch ) ;
continue ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
var text = void 0 ;
if ( textEnd >= 0 ) {
text = html . substring ( 0 , textEnd ) ;
advance ( textEnd ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
text = html ;
html = '' ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
2016-07-26 10:07:26 +08:00
if ( options . chars ) {
options . chars ( text ) ;
2016-07-08 05:53:22 +08:00
}
} else {
( function ( ) {
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' ) ;
}
2016-07-26 10:07:26 +08:00
if ( options . chars ) {
options . chars ( text ) ;
2016-07-08 05:53:22 +08:00
}
return '' ;
} ) ;
index += html . length - rest . length ;
html = rest ;
parseEndTag ( '</' + stackedTag + '>' , stackedTag , index - endTagLength , index ) ;
} ) ( ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( html === last ) {
throw new Error ( 'Error parsing template:\n\n' + html ) ;
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// Clean up any remaining tags
parseEndTag ( ) ;
function advance ( n ) {
index += n ;
html = html . substring ( n ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function parseStartTag ( ) {
var start = html . match ( startTagOpen ) ;
if ( start ) {
var match = {
tagName : start [ 1 ] ,
attrs : [ ] ,
start : index
} ;
advance ( start [ 0 ] . length ) ;
var end = void 0 ,
attr = void 0 ;
while ( ! ( end = html . match ( startTagClose ) ) && ( attr = html . match ( attribute ) ) ) {
advance ( attr [ 0 ] . length ) ;
match . attrs . push ( attr ) ;
}
if ( end ) {
match . unarySlash = end [ 1 ] ;
advance ( end [ 0 ] . length ) ;
match . end = index ;
return match ;
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function handleStartTag ( match ) {
var tagName = match . tagName ;
var unarySlash = match . unarySlash ;
if ( expectHTML ) {
if ( lastTag === 'p' && isNonPhrasingTag ( tagName ) ) {
parseEndTag ( '' , lastTag ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( canBeLeftOpenTag ( tagName ) && lastTag === tagName ) {
parseEndTag ( '' , tagName ) ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var unary = isUnaryTag ( tagName ) || tagName === 'html' && lastTag === 'head' || ! ! unarySlash ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var l = match . attrs . length ;
var attrs = new Array ( l ) ;
for ( var i = 0 ; i < l ; i ++ ) {
var args = match . attrs [ i ] ;
// 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-07-08 05:53:22 +08:00
attrs [ i ] = {
name : args [ 1 ] ,
2016-07-26 10:07:26 +08:00
value : shouldDecodeAttr ? entities . decodeHTML ( value , true ) : value
2016-07-08 05:53:22 +08:00
} ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function parseEndTag ( tag , tagName , start , end ) {
var pos = void 0 ;
if ( start == null ) start = index ;
if ( end == null ) end = index ;
// 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 ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
} 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-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +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-07-08 05:53:22 +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-07-08 05:53:22 +08:00
}
2016-07-26 10:07:26 +08:00
if ( options . end ) {
options . end ( tagName , start , end ) ;
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +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 ( ) ;
2016-06-26 12:53:58 +08:00
}
} else {
2016-07-08 05:53:22 +08:00
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 ; // }
}
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
if ( expression === undefined ) {
expression = exp . slice ( 0 , i ) . trim ( ) ;
} else if ( lastFilterIndex !== 0 ) {
pushFilter ( ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
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 ] ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
return expression ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
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 ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
var defaultTagRE = /\{\{((?:.|\\n)+?)\}\}/g ;
var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g ;
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 ;
if ( ! tagRE . test ( text ) ) {
2016-06-26 12:53:58 +08:00
return ;
}
2016-07-08 05:53:22 +08:00
var tokens = [ ] ;
var lastIndex = tagRE . lastIndex = 0 ;
var match = void 0 ,
index = void 0 ;
while ( match = tagRE . exec ( text ) ) {
index = match . index ;
// push text token
if ( index > lastIndex ) {
tokens . push ( JSON . stringify ( text . slice ( lastIndex , index ) ) ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// tag token
var exp = parseFilters ( match [ 1 ] . trim ( ) ) ;
tokens . push ( '_s(' + exp + ')' ) ;
lastIndex = index + match [ 0 ] . length ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( lastIndex < text . length ) {
tokens . push ( JSON . stringify ( text . slice ( lastIndex ) ) ) ;
}
return tokens . join ( '+' ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function baseWarn ( msg ) {
console . error ( '[Vue parser]: ' + msg ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function pluckModuleFunction ( modules , key ) {
return modules ? modules . map ( function ( m ) {
return m [ key ] ;
} ) . filter ( function ( _ ) {
return _ ;
} ) : [ ] ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function addProp ( el , name , value ) {
( el . props || ( el . props = [ ] ) ) . push ( { name : name , value : value } ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function addAttr ( el , name , value ) {
( el . attrs || ( el . attrs = [ ] ) ) . push ( { name : name , value : value } ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function addStaticAttr ( el , name , value ) {
( el . staticAttrs || ( el . staticAttrs = [ ] ) ) . push ( { name : name , value : value } ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function addDirective ( el , name , value , arg , modifiers ) {
( el . directives || ( el . directives = [ ] ) ) . push ( { name : name , value : value , arg : arg , modifiers : modifiers } ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function addHook ( el , name , code ) {
var hooks = el . hooks || ( el . hooks = { } ) ;
var hook = hooks [ name ] ;
/* istanbul ignore if */
if ( hook ) {
hook . push ( code ) ;
} else {
hooks [ name ] = [ code ] ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function addHandler ( el , name , value , modifiers ) {
// 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-07-08 05:53:22 +08:00
var newHandler = { value : value , modifiers : modifiers } ;
var handlers = events [ name ] ;
/* istanbul ignore if */
if ( Array . isArray ( handlers ) ) {
handlers . push ( newHandler ) ;
} else if ( handlers ) {
events [ name ] = [ handlers , newHandler ] ;
} else {
events [ name ] = newHandler ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function getBindingAttr ( el , name , getStatic ) {
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-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +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 ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
}
return val ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var dirRE = /^v-|^@|^:/ ;
var forAliasRE = /(.*)\s+(?:in|of)\s+(.*)/ ;
var forIteratorRE = /\(([^,]*),([^,]*)(?:,([^,]*))?\)/ ;
var bindRE = /^:|^v-bind:/ ;
var onRE = /^@|^v-on:/ ;
var argRE = /:(.*)$/ ;
var modifierRE = /\.[^\.]+/g ;
var decodeHTMLCached = cached ( entities . decodeHTML ) ;
// configurable state
var warn$1 = void 0 ;
var platformGetTagNamespace = void 0 ;
var platformMustUseProp = void 0 ;
var transforms = void 0 ;
var delimiters = void 0 ;
2016-06-28 10:25:12 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* Convert HTML string to AST .
* /
function parse ( template , options ) {
warn$1 = options . warn || baseWarn ;
platformGetTagNamespace = options . getTagNamespace || no ;
platformMustUseProp = options . mustUseProp || no ;
transforms = pluckModuleFunction ( options . modules , 'transformNode' ) ;
delimiters = options . delimiters ;
var stack = [ ] ;
var preserveWhitespace = options . preserveWhitespace !== false ;
var root = void 0 ;
var currentParent = void 0 ;
var inPre = false ;
var warned = false ;
parseHTML ( template , {
expectHTML : options . expectHTML ,
isUnaryTag : options . isUnaryTag ,
2016-07-26 10:07:26 +08:00
shouldDecodeAttr : options . shouldDecodeAttr ,
2016-07-08 05:53:22 +08:00
start : function start ( tag , attrs , unary ) {
// 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-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var element = {
type : 1 ,
tag : tag ,
attrsList : attrs ,
attrsMap : makeAttrsMap ( attrs ) ,
parent : currentParent ,
children : [ ]
} ;
if ( ns ) {
element . ns = ns ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( isForbiddenTag ( element ) ) {
element . forbidden = true ;
process . env . NODE _ENV !== '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-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( ! inPre ) {
processPre ( element ) ;
if ( element . pre ) {
inPre = true ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
if ( inPre ) {
processRawAttrs ( element ) ;
} else {
processFor ( element ) ;
processIf ( element ) ;
processOnce ( element ) ;
// determine whether this is a plain element after
// removing structural attributes
element . plain = ! element . key && ! attrs . length ;
processKey ( element ) ;
processRef ( element ) ;
processSlot ( element ) ;
processComponent ( element ) ;
2016-07-24 10:48:09 +08:00
for ( var i = 0 ; i < transforms . length ; i ++ ) {
transforms [ i ] ( element , options ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
processAttrs ( element ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// tree management
if ( ! root ) {
root = element ;
// check root element constraints
if ( process . env . NODE _ENV !== 'production' ) {
if ( tag === 'slot' || tag === 'template' ) {
warn$1 ( 'Cannot use <' + tag + '> as component root element because it may ' + 'contain multiple nodes:\n' + template ) ;
}
if ( element . attrsMap . hasOwnProperty ( 'v-for' ) ) {
warn$1 ( 'Cannot use v-for on stateful component root element because ' + 'it renders multiple elements:\n' + template ) ;
}
}
} else if ( process . env . NODE _ENV !== 'production' && ! stack . length && ! warned ) {
warned = true ;
warn$1 ( 'Component template should contain exactly one root element:\n\n' + template ) ;
}
if ( currentParent && ! element . forbidden ) {
if ( element . else ) {
processElse ( element , currentParent ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
currentParent . children . push ( element ) ;
element . parent = currentParent ;
}
}
if ( ! unary ) {
currentParent = element ;
stack . push ( element ) ;
}
} ,
end : function end ( ) {
// remove trailing whitespace
var element = stack [ stack . length - 1 ] ;
var lastNode = element . children [ element . children . length - 1 ] ;
if ( lastNode && lastNode . type === 3 && lastNode . text === ' ' ) {
element . children . pop ( ) ;
}
// pop stack
stack . length -= 1 ;
currentParent = stack [ stack . length - 1 ] ;
// check pre state
if ( element . pre ) {
inPre = false ;
}
} ,
chars : function chars ( text ) {
if ( ! currentParent ) {
if ( process . env . NODE _ENV !== 'production' && ! warned ) {
warned = true ;
warn$1 ( 'Component template should contain exactly one root element:\n\n' + template ) ;
}
return ;
}
text = currentParent . tag === 'pre' || text . trim ( ) ? decodeHTMLCached ( text )
// only preserve whitespace if its not right after a starting tag
: preserveWhitespace && currentParent . children . length ? ' ' : '' ;
if ( text ) {
var expression = void 0 ;
if ( ! inPre && text !== ' ' && ( expression = parseText ( text , delimiters ) ) ) {
currentParent . children . push ( {
type : 2 ,
expression : expression ,
text : text
} ) ;
} else {
currentParent . children . push ( {
type : 3 ,
text : text
} ) ;
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
} ) ;
return root ;
}
function processPre ( el ) {
if ( getAndRemoveAttr ( el , 'v-pre' ) != null ) {
el . pre = true ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function processRawAttrs ( el ) {
var l = el . attrsList . length ;
if ( l ) {
var attrs = el . staticAttrs = new Array ( l ) ;
for ( var i = 0 ; i < l ; i ++ ) {
attrs [ i ] = {
name : el . attrsList [ i ] . name ,
value : JSON . stringify ( el . attrsList [ i ] . value )
} ;
}
} else if ( ! el . pre ) {
// non root node in pre blocks with no attributes
el . plain = true ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function processKey ( el ) {
var exp = getBindingAttr ( el , 'key' ) ;
if ( exp ) {
el . key = exp ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function processRef ( el ) {
var ref = getBindingAttr ( el , 'ref' ) ;
if ( ref ) {
el . ref = ref ;
var parent = el ;
while ( parent ) {
if ( parent . for !== undefined ) {
el . refInFor = true ;
2016-06-26 12:53:58 +08:00
break ;
}
2016-07-08 05:53:22 +08:00
parent = parent . parent ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function processFor ( el ) {
var exp = void 0 ;
if ( exp = getAndRemoveAttr ( el , 'v-for' ) ) {
var inMatch = exp . match ( forAliasRE ) ;
if ( ! inMatch ) {
process . env . NODE _ENV !== '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 ) {
el . alias = iteratorMatch [ 1 ] . trim ( ) ;
el . iterator1 = iteratorMatch [ 2 ] . trim ( ) ;
if ( iteratorMatch [ 3 ] ) {
el . iterator2 = iteratorMatch [ 3 ] . trim ( ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} else {
el . alias = alias ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function processIf ( el ) {
var exp = getAndRemoveAttr ( el , 'v-if' ) ;
if ( exp ) {
el . if = exp ;
}
if ( getAndRemoveAttr ( el , 'v-else' ) != null ) {
el . else = true ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function processElse ( el , parent ) {
var prev = findPrevElement ( parent . children ) ;
if ( prev && prev . if ) {
prev . elseBlock = el ;
} else if ( process . env . NODE _ENV !== 'production' ) {
warn$1 ( 'v-else used on element <' + el . tag + '> without corresponding v-if.' ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function processOnce ( el ) {
var once = getAndRemoveAttr ( el , 'v-once' ) ;
if ( once != null ) {
el . once = true ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function processSlot ( el ) {
if ( el . tag === 'slot' ) {
el . slotName = getBindingAttr ( el , 'name' ) ;
} else {
var slotTarget = getBindingAttr ( el , 'slot' ) ;
if ( slotTarget ) {
el . slotTarget = slotTarget ;
}
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function processComponent ( el ) {
var binding = void 0 ;
if ( binding = getBindingAttr ( el , 'is' ) ) {
el . component = binding ;
}
if ( getAndRemoveAttr ( el , 'keep-alive' ) != null ) {
el . keepAlive = true ;
}
if ( getAndRemoveAttr ( el , 'inline-template' ) != null ) {
el . inlineTemplate = true ;
}
}
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-07-08 05:53:22 +08:00
for ( i = 0 , l = list . length ; i < l ; i ++ ) {
name = list [ i ] . name ;
value = list [ i ] . value ;
if ( dirRE . test ( name ) ) {
// 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-07-08 05:53:22 +08:00
addProp ( el , name , value ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
addAttr ( el , name , value ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} 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
var argMatch = name . match ( argRE ) ;
if ( argMatch && ( arg = argMatch [ 1 ] ) ) {
name = name . slice ( 0 , - ( arg . length + 1 ) ) ;
}
addDirective ( el , name , value , arg , modifiers ) ;
2016-06-26 12:53:58 +08:00
}
} else {
2016-07-08 05:53:22 +08:00
// literal attribute
if ( process . env . NODE _ENV !== '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-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
addStaticAttr ( el , name , JSON . stringify ( value ) ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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 ( process . env . NODE _ENV !== 'production' && map [ attrs [ i ] . name ] ) {
warn$1 ( 'duplicate attribute: ' + attrs [ i ] . name ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
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 ] ;
}
}
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 ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
return res ;
}
var isStaticKey = void 0 ;
var isPlatformReservedTag = void 0 ;
var genStaticKeysCached = cached ( genStaticKeys$1 ) ;
/ * *
* 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 ) {
if ( ! root ) return ;
isStaticKey = genStaticKeysCached ( options . staticKeys || '' ) ;
isPlatformReservedTag = options . isReservedTag || function ( ) {
return false ;
2016-06-26 12:53:58 +08:00
} ;
2016-07-08 05:53:22 +08:00
// first pass: mark all non-static nodes.
markStatic ( root ) ;
// second pass: mark static roots.
markStaticRoots ( root ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function genStaticKeys$1 ( keys ) {
return makeMap ( 'type,tag,attrsList,attrsMap,plain,parent,children,staticAttrs' + ( keys ? ',' + keys : '' ) ) ;
}
function markStatic ( node ) {
node . static = isStatic ( node ) ;
if ( node . type === 1 ) {
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-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function markStaticRoots ( node ) {
if ( node . type === 1 && ( node . once || node . static ) ) {
node . staticRoot = true ;
return ;
}
if ( node . children ) {
for ( var i = 0 , l = node . children . length ; i < l ; i ++ ) {
markStaticRoots ( node . children [ i ] ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
}
function isStatic ( node ) {
if ( node . type === 2 ) {
// expression
return false ;
}
if ( node . type === 3 ) {
// text
return true ;
}
return ! ! ( node . pre || ! node . if && ! node . for && // not v-if or v-for or v-else
! isBuiltInTag ( node . tag ) && // not a built-in
isPlatformReservedTag ( node . tag ) && ( // not a component
node . plain || Object . keys ( node ) . every ( isStaticKey ) ) // no dynamic bindings
) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +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-07-08 05:53:22 +08:00
for ( var name in events ) {
res += '"' + name + '":' + genHandler ( events [ name ] ) + ',' ;
}
return res . slice ( 0 , - 1 ) + '}' ;
}
function genHandler ( handler ) {
if ( ! handler ) {
return 'function(){}' ;
} else if ( Array . isArray ( handler ) ) {
return '[' + handler . map ( genHandler ) . join ( ',' ) + ']' ;
} else if ( ! handler . modifiers ) {
return simplePathRE . test ( handler . value ) ? handler . value : 'function($event){' + handler . value + '}' ;
} else {
var code = 'function($event){' ;
for ( var key in handler . modifiers ) {
code += modifierCode [ key ] || genKeyFilter ( key ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
var handlerCode = simplePathRE . test ( handler . value ) ? handler . value + '($event)' : handler . value ;
return code + handlerCode + '}' ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function genKeyFilter ( key ) {
var code = parseInt ( key , 10 ) || // number keyCode
keyCodes [ key ] || // built-in alias
'_k(' + JSON . stringify ( key ) + ')' ; // custom alias
if ( Array . isArray ( code ) ) {
return 'if(' + code . map ( function ( c ) {
return '$event.keyCode!==' + c ;
} ) . join ( '&&' ) + ')return;' ;
} else {
return 'if($event.keyCode!==' + code + ')return;' ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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-07-08 05:53:22 +08:00
}
var baseDirectives = {
bind : bind$1 ,
cloak : noop
} ;
// configurable state
var warn$2 = void 0 ;
var transforms$1 = void 0 ;
var dataGenFns = void 0 ;
var platformDirectives = void 0 ;
var isPlatformReservedTag$1 = void 0 ;
var staticRenderFns = void 0 ;
var currentOptions = void 0 ;
function generate ( ast , options ) {
// save previous staticRenderFns so generate calls can be nested
var prevStaticRenderFns = staticRenderFns ;
var currentStaticRenderFns = staticRenderFns = [ ] ;
currentOptions = options ;
warn$2 = options . warn || baseWarn ;
transforms$1 = pluckModuleFunction ( options . modules , 'transformCode' ) ;
dataGenFns = pluckModuleFunction ( options . modules , 'genData' ) ;
platformDirectives = options . directives || { } ;
isPlatformReservedTag$1 = options . isReservedTag || no ;
var code = ast ? genElement ( ast ) : '_h("div")' ;
staticRenderFns = prevStaticRenderFns ;
return {
render : 'with(this){return ' + code + '}' ,
staticRenderFns : currentStaticRenderFns
} ;
}
function genElement ( el ) {
if ( el . staticRoot && ! el . staticProcessed ) {
// hoist static sub-trees out
el . staticProcessed = true ;
staticRenderFns . push ( 'with(this){return ' + genElement ( el ) + '}' ) ;
return '_m(' + ( staticRenderFns . length - 1 ) + ')' ;
} else if ( el . for && ! el . forProcessed ) {
return genFor ( el ) ;
} else if ( el . if && ! el . ifProcessed ) {
return genIf ( el ) ;
} else if ( el . tag === 'template' && ! el . slotTarget ) {
return genChildren ( el ) || 'void 0' ;
} else if ( el . tag === 'slot' ) {
return genSlot ( el ) ;
} else {
// component or element
var code = void 0 ;
if ( el . component ) {
code = genComponent ( el ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
var data = genData ( el ) ;
// if the element is potentially a component,
// wrap its children as a thunk.
2016-07-17 13:53:44 +08:00
var children = ! el . inlineTemplate ? genChildren ( el , ! isPlatformReservedTag$1 ( el . tag ) /* asThunk */ ) : null ;
2016-07-08 05:53:22 +08:00
code = '_h(\'' + el . tag + '\'' + ( data ? ',' + data : '' // data
) + ( children ? ',' + children : '' // children
) + ')' ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// module transforms
for ( var i = 0 ; i < transforms$1 . length ; i ++ ) {
code = transforms$1 [ i ] ( el , code ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
// check keep-alive
if ( el . keepAlive ) {
code = '_h("KeepAlive",{props:{child:' + code + '}})' ;
}
return code ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function genIf ( el ) {
var exp = el . if ;
el . ifProcessed = true ; // avoid recursion
return '(' + exp + ')?' + genElement ( el ) + ':' + genElse ( el ) ;
}
function genElse ( el ) {
return el . elseBlock ? genElement ( el . elseBlock ) : 'void 0' ;
}
function genFor ( el ) {
var exp = el . for ;
var alias = el . alias ;
var iterator1 = el . iterator1 ? ',' + el . iterator1 : '' ;
var iterator2 = el . iterator2 ? ',' + el . iterator2 : '' ;
el . forProcessed = true ; // avoid recursion
return '(' + exp + ')&&_l((' + exp + '),' + ( 'function(' + alias + iterator1 + iterator2 + '){' ) + ( 'return ' + genElement ( el ) ) + '})' ;
}
function genData ( el ) {
if ( el . plain ) {
return ;
}
var data = '{' ;
// directives first.
// directives may mutate the el's other properties before they are generated.
var dirs = genDirectives ( el ) ;
if ( dirs ) data += dirs + ',' ;
// key
if ( el . key ) {
data += 'key:' + el . key + ',' ;
}
// ref
if ( el . ref ) {
data += 'ref:' + el . ref + ',' ;
}
if ( el . refInFor ) {
data += 'refInFor:true,' ;
}
// record original tag name for components using "is" attribute
if ( el . component ) {
data += 'tag:"' + el . tag + '",' ;
}
// slot target
if ( el . slotTarget ) {
data += 'slot:' + el . slotTarget + ',' ;
}
// module data generation functions
for ( var i = 0 ; i < dataGenFns . length ; i ++ ) {
data += dataGenFns [ i ] ( el ) ;
}
// v-show, used to avoid transition being applied
// since v-show takes it over
if ( el . attrsMap [ 'v-show' ] ) {
data += 'show:true,' ;
}
// attributes
if ( el . attrs ) {
data += 'attrs:{' + genProps ( el . attrs ) + '},' ;
}
// static attributes
if ( el . staticAttrs ) {
data += 'staticAttrs:{' + genProps ( el . staticAttrs ) + '},' ;
}
2016-07-24 10:48:09 +08:00
// DOM props
if ( el . props ) {
data += 'domProps:{' + genProps ( el . props ) + '},' ;
}
2016-07-08 05:53:22 +08:00
// hooks
if ( el . hooks ) {
data += 'hook:{' + genHooks ( el . hooks ) + '},' ;
}
// event handlers
if ( el . events ) {
data += genHandlers ( el . events ) + ',' ;
}
2016-07-24 10:48:09 +08:00
if ( el . nativeEvents ) {
data += '' + genHandlers ( el . nativeEvents , true ) ;
}
2016-07-08 05:53:22 +08:00
// inline-template
if ( el . inlineTemplate ) {
var ast = el . children [ 0 ] ;
if ( process . env . NODE _ENV !== '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-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
return data . replace ( /,$/ , '' ) + '}' ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function genDirectives ( el ) {
var dirs = el . directives ;
if ( ! dirs ) return ;
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 [ dir . name ] || baseDirectives [ dir . name ] ;
if ( gen ) {
// compile-time directive that manipulates AST.
// returns true if it also needs a runtime counterpart.
needRuntime = ! ! gen ( el , dir , warn$2 ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( needRuntime ) {
hasRuntime = true ;
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 ) : '' ) + '},' ;
}
}
if ( hasRuntime ) {
return res . slice ( 0 , - 1 ) + ']' ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function genChildren ( el , asThunk ) {
if ( ! el . children . length ) {
return ;
}
var code = '[' + el . children . map ( genNode ) . join ( ',' ) + ']' ;
return asThunk ? 'function(){return ' + code + '}' : code ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function genNode ( node ) {
if ( node . type === 1 ) {
return genElement ( node ) ;
} else {
return genText ( node ) ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function genText ( text ) {
return text . type === 2 ? text . expression // no need for () because already wrapped in _s()
: JSON . stringify ( text . text ) ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function genSlot ( el ) {
var slot = '$slots[' + ( el . slotName || '"default"' ) + ']' ;
var children = genChildren ( el ) ;
return children ? '(' + slot + '||' + children + ')' : slot ;
}
function genComponent ( el ) {
var children = genChildren ( el , true ) ;
return '_h(' + el . component + ',' + genData ( el ) + ( children ? ',' + children : '' ) + ')' ;
}
function genProps ( props ) {
var res = '' ;
for ( var i = 0 ; i < props . length ; i ++ ) {
var prop = props [ i ] ;
res += '"' + prop . name + '":' + prop . value + ',' ;
2016-06-28 10:25:12 +08:00
}
2016-07-08 05:53:22 +08:00
return res . slice ( 0 , - 1 ) ;
}
2016-06-28 10:25:12 +08:00
2016-07-08 05:53:22 +08:00
function genHooks ( hooks ) {
var res = '' ;
for ( var _key in hooks ) {
res += '"' + _key + '":function(n1,n2){' + hooks [ _key ] . join ( ';' ) + '},' ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return res . slice ( 0 , - 1 ) ;
}
2016-06-28 10:25:12 +08:00
2016-07-08 05:53:22 +08:00
/ * *
* Compile a template .
* /
function compile$1 ( template , options ) {
var ast = parse ( template . trim ( ) , options ) ;
optimize ( ast , options ) ;
var code = generate ( ast , options ) ;
return {
ast : ast ,
render : code . render ,
staticRenderFns : code . staticRenderFns
} ;
}
// 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
var identRE = /[A-Za-z_$][\w$]*/ ;
// strip strings in expressions
var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g ;
// detect problematic expressions in a template
function detectErrors ( ast ) {
var errors = [ ] ;
if ( ast ) {
checkNode ( ast , errors ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return errors ;
}
2016-06-28 10:25:12 +08:00
2016-07-08 05:53:22 +08:00
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 ) {
if ( name === 'v-for' ) {
checkFor ( node , 'v-for="' + value + '"' , errors ) ;
} else {
checkExpression ( value , name + '="' + value + '"' , errors ) ;
}
}
}
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +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-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +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 ) ;
}
}
function checkExpression ( exp , text , errors ) {
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 ) ) ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
errors . push ( '- invalid expression: ' + text ) ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function transformNode ( el , options ) {
var warn = options . warn || baseWarn ;
var staticClass = getAndRemoveAttr ( el , 'class' ) ;
if ( process . env . NODE _ENV !== '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.' ) ;
}
}
el . staticClass = JSON . stringify ( staticClass ) ;
var classBinding = getBindingAttr ( el , 'class' , false /* getStatic */ ) ;
if ( classBinding ) {
el . classBinding = classBinding ;
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
function genData$1 ( el ) {
var data = '' ;
if ( el . staticClass ) {
data += 'staticClass:' + el . staticClass + ',' ;
}
if ( el . classBinding ) {
data += 'class:' + el . classBinding + ',' ;
}
return data ;
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var klass = {
staticKeys : [ 'staticClass' ] ,
transformNode : transformNode ,
genData : genData$1
} ;
function transformNode$1 ( el ) {
var styleBinding = getBindingAttr ( el , 'style' , false /* getStatic */ ) ;
if ( styleBinding ) {
el . styleBinding = styleBinding ;
2016-06-28 10:25:12 +08:00
}
2016-07-08 05:53:22 +08:00
}
2016-06-28 10:25:12 +08:00
2016-07-08 05:53:22 +08:00
function genData$2 ( el ) {
return el . styleBinding ? 'style:(' + el . styleBinding + '),' : '' ;
}
2016-06-28 10:25:12 +08:00
2016-07-08 05:53:22 +08:00
var style = {
transformNode : transformNode$1 ,
genData : genData$2
} ;
2016-07-17 13:53:44 +08:00
var modules = [ klass , style ] ;
2016-07-08 05:53:22 +08:00
var warn$3 = void 0 ;
function model ( el , dir , _warn ) {
warn$3 = _warn ;
var value = dir . value ;
var modifiers = dir . modifiers ;
if ( el . tag === 'select' ) {
return genSelect ( el , value ) ;
} 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 ) {
if ( process . env . NODE _ENV !== '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.' ) ;
}
var valueBinding = getBindingAttr ( el , 'value' ) ;
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-07-24 10:48:09 +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}' ) ) ;
2016-07-08 05:53:22 +08:00
}
function genRadioModel ( el , value ) {
if ( process . env . NODE _ENV !== '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.' ) ;
}
var valueBinding = getBindingAttr ( el , 'value' ) ;
addProp ( el , 'checked' , '(' + value + ')===(' + valueBinding + ')' ) ;
addHandler ( el , 'change' , value + '=' + valueBinding ) ;
}
function genDefaultModel ( el , value , modifiers ) {
if ( process . env . NODE _ENV !== '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.' ) ;
}
}
var type = el . attrsMap . type ;
var _ref = modifiers || { } ;
var lazy = _ref . lazy ;
var number = _ref . number ;
var trim = _ref . trim ;
var event = lazy ? 'change' : 'input' ;
var needCompositionGuard = ! lazy && type !== 'range' ;
var isNative = el . tag === 'input' || el . tag === 'textarea' ;
var valueExpression = isNative ? '$event.target.value' + ( trim ? '.trim()' : '' ) : '$event' ;
var code = number || type === 'number' ? value + '=_n(' + valueExpression + ')' : value + '=' + valueExpression ;
if ( isNative && needCompositionGuard ) {
code = 'if($event.target.composing)return;' + code ;
}
addProp ( el , 'value' , isNative ? '_s(' + value + ')' : '(' + value + ')' ) ;
addHandler ( el , event , code ) ;
if ( needCompositionGuard ) {
// need runtime directive code to help with composition events
return true ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function genSelect ( el , value ) {
if ( process . env . NODE _ENV !== 'production' ) {
el . children . some ( checkOptionWarning ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
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]' : '' ) ;
addHandler ( el , 'change' , code ) ;
// need runtime to help with possible dynamically generated options
return true ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +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-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function text ( el , dir ) {
if ( dir . value ) {
addProp ( el , 'textContent' , '_s(' + dir . value + ')' ) ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
function html ( el , dir ) {
if ( dir . value ) {
addProp ( el , 'innerHTML' , '_s(' + dir . value + ')' ) ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
var directives = {
model : model ,
text : text ,
html : html
} ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var cache = Object . create ( null ) ;
var baseOptions = {
isIE : isIE ,
expectHTML : true ,
modules : modules ,
staticKeys : genStaticKeys ( modules ) ,
directives : directives ,
isReservedTag : isReservedTag ,
isUnaryTag : isUnaryTag ,
mustUseProp : mustUseProp ,
getTagNamespace : getTagNamespace
} ;
function compile ( template , options ) {
options = options ? extend ( extend ( { } , baseOptions ) , options ) : baseOptions ;
return compile$1 ( template , options ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function compileToFunctions ( template , options , vm ) {
var _warn = options && options . warn || warn ;
// detect possible CSP restriction
/* istanbul ignore if */
if ( process . env . NODE _ENV !== '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-06-26 12:53:58 +08:00
}
var res = { } ;
2016-07-08 05:53:22 +08:00
var compiled = compile ( template , options ) ;
res . render = makeFunction ( compiled . render ) ;
var l = compiled . staticRenderFns . length ;
res . staticRenderFns = new Array ( l ) ;
for ( var i = 0 ; i < l ; i ++ ) {
res . staticRenderFns [ i ] = makeFunction ( compiled . staticRenderFns [ i ] ) ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
if ( process . env . NODE _ENV !== '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-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
return cache [ key ] = res ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
function makeFunction ( code ) {
try {
return new Function ( code ) ;
} catch ( e ) {
return noop ;
2016-06-26 12:53:58 +08:00
}
}
2016-07-08 05:53:22 +08:00
var normalizeAsync = function normalizeAsync ( cache , method ) {
var fn = cache [ method ] ;
if ( ! fn ) {
return ;
} else if ( fn . length > 1 ) {
return function ( key , cb ) {
return fn . call ( cache , key , cb ) ;
} ;
2016-06-26 12:53:58 +08:00
} else {
2016-07-08 05:53:22 +08:00
return function ( key , cb ) {
return cb ( fn . call ( cache , key ) ) ;
} ;
2016-06-26 12:53:58 +08:00
}
2016-07-08 05:53:22 +08:00
} ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var compilationCache = Object . create ( null ) ;
var normalizeRender = function normalizeRender ( vm ) {
var _vm$$options = vm . $options ;
var render = _vm$$options . render ;
var template = _vm$$options . template ;
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
if ( ! render && template ) {
var renderFns = compilationCache [ template ] || ( compilationCache [ template ] = compileToFunctions ( template ) ) ;
Object . assign ( vm . $options , renderFns ) ;
}
2016-06-26 12:53:58 +08:00
} ;
2016-07-08 05:53:22 +08:00
function createRenderFunction ( modules , directives , isUnaryTag , cache ) {
if ( cache && ( ! cache . get || ! cache . set ) ) {
throw new Error ( 'renderer cache must implement at least get & set.' ) ;
}
var get = cache && normalizeAsync ( cache , 'get' ) ;
var has = cache && normalizeAsync ( cache , 'has' ) ;
2016-06-26 12:53:58 +08:00
function renderNode ( node , write , next , isRoot ) {
if ( node . componentOptions ) {
2016-06-28 10:25:12 +08:00
// check cache hit
var Ctor = node . componentOptions . Ctor ;
2016-07-08 05:53:22 +08:00
var getKey = Ctor . options . serverCacheKey ;
if ( getKey && cache ) {
( function ( ) {
2016-06-28 10:25:12 +08:00
var key = Ctor . cid + '::' + getKey ( node . componentOptions . propsData ) ;
2016-07-08 05:53:22 +08:00
if ( has ) {
has ( key , function ( hit ) {
if ( hit ) {
get ( key , function ( res ) {
return write ( res , next ) ;
} ) ;
} else {
renderComponentWithCache ( node , write , next , isRoot , cache , key ) ;
}
} ) ;
2016-06-28 10:25:12 +08:00
} else {
2016-07-08 05:53:22 +08:00
get ( key , function ( res ) {
if ( res ) {
write ( res , next ) ;
} else {
renderComponentWithCache ( node , write , next , isRoot , cache , key ) ;
}
} ) ;
2016-06-28 10:25:12 +08:00
}
2016-07-08 05:53:22 +08:00
} ) ( ) ;
} else {
if ( getKey ) {
console . error ( '[vue-server-renderer] Component ' + ( Ctor . options . name || '(anonymous)' ) + ' implemented serverCacheKey, ' + 'but no cache was provided to the renderer.' ) ;
}
renderComponent ( node , write , next , isRoot ) ;
2016-06-28 10:25:12 +08:00
}
2016-06-26 12:53:58 +08:00
} else {
if ( node . tag ) {
renderElement ( node , write , next , isRoot ) ;
} else {
2016-07-24 10:48:09 +08:00
write ( node . raw ? node . text : entities . encodeHTML ( String ( node . text ) ) , next ) ;
2016-06-26 12:53:58 +08:00
}
}
}
2016-07-08 05:53:22 +08:00
function renderComponent ( node , write , next , isRoot ) {
var child = createComponentInstanceForVnode ( node ) ;
normalizeRender ( child ) ;
var childNode = child . _render ( ) ;
childNode . parent = node ;
renderNode ( childNode , write , next , isRoot ) ;
}
function renderComponentWithCache ( node , write , next , isRoot , cache , key ) {
write . caching = true ;
var buffer = write . cacheBuffer ;
var bufferIndex = buffer . push ( '' ) - 1 ;
renderComponent ( node , write , function ( ) {
var result = buffer [ bufferIndex ] ;
cache . set ( key , result ) ;
if ( bufferIndex === 0 ) {
// this is a top-level cached component,
// exit caching mode.
write . caching = false ;
} else {
// parent component is also being cached,
// merge self into parent's result
buffer [ bufferIndex - 1 ] += result ;
}
buffer . length = bufferIndex ;
next ( ) ;
} , isRoot ) ;
}
2016-06-26 12:53:58 +08:00
function renderElement ( el , write , next , isRoot ) {
if ( isRoot ) {
if ( ! el . data ) el . data = { } ;
if ( ! el . data . attrs ) el . data . attrs = { } ;
el . data . attrs [ 'server-rendered' ] = 'true' ;
}
var startTag = renderStartingTag ( el ) ;
var endTag = '</' + el . tag + '>' ;
if ( isUnaryTag ( el . tag ) ) {
write ( startTag , next ) ;
} else if ( ! el . children || ! el . children . length ) {
write ( startTag + endTag , next ) ;
} else {
( function ( ) {
var children = el . children || [ ] ;
write ( startTag , function ( ) {
var total = children . length ;
var rendered = 0 ;
function renderChild ( child ) {
renderNode ( child , write , function ( ) {
rendered ++ ;
if ( rendered < total ) {
renderChild ( children [ rendered ] ) ;
} else {
write ( endTag , next ) ;
}
} , false ) ;
}
renderChild ( children [ 0 ] ) ;
} ) ;
} ) ( ) ;
}
}
function renderStartingTag ( node ) {
var markup = '<' + node . tag ;
if ( node . data ) {
// check directives
var dirs = node . data . directives ;
if ( dirs ) {
for ( var i = 0 ; i < dirs . length ; i ++ ) {
var dirRenderer = directives [ dirs [ i ] . name ] ;
if ( dirRenderer ) {
// directives mutate the node's data
// which then gets rendered by modules
dirRenderer ( node , dirs [ i ] ) ;
}
}
}
// apply other modules
for ( var _i = 0 ; _i < modules . length ; _i ++ ) {
var res = modules [ _i ] ( node ) ;
if ( res ) {
markup += res ;
}
}
}
// attach scoped CSS ID
var scopeId = void 0 ;
if ( node . host && ( scopeId = node . host . $options . _scopeId ) ) {
markup += ' ' + scopeId ;
}
2016-06-28 10:25:12 +08:00
while ( node ) {
if ( scopeId = node . context . $options . _scopeId ) {
2016-06-26 12:53:58 +08:00
markup += ' ' + scopeId ;
}
2016-06-28 10:25:12 +08:00
node = node . parent ;
2016-06-26 12:53:58 +08:00
}
2016-06-28 10:25:12 +08:00
return markup + '>' ;
2016-06-26 10:59:03 +08:00
}
2016-06-26 12:53:58 +08:00
return function render ( component , write , done ) {
2016-07-08 05:53:22 +08:00
normalizeRender ( component ) ;
2016-06-26 12:53:58 +08:00
renderNode ( component . _render ( ) , write , done , true ) ;
} ;
2016-06-08 09:53:43 +08:00
}
2016-06-26 12:53:58 +08:00
function createRenderer$1 ( ) {
var _ref = arguments . length <= 0 || arguments [ 0 ] === undefined ? { } : arguments [ 0 ] ;
var _ref$modules = _ref . modules ;
var modules = _ref$modules === undefined ? [ ] : _ref$modules ;
var _ref$directives = _ref . directives ;
var directives = _ref$directives === undefined ? { } : _ref$directives ;
var _ref$isUnaryTag = _ref . isUnaryTag ;
var isUnaryTag = _ref$isUnaryTag === undefined ? function ( ) {
return false ;
} : _ref$isUnaryTag ;
2016-07-08 05:53:22 +08:00
var cache = _ref . cache ;
2016-06-26 12:53:58 +08:00
if ( process . env . VUE _ENV !== 'server' ) {
warn ( 'You are using createRenderer without setting VUE_ENV enviroment variable to "server". ' + 'It is recommended to set VUE_ENV=server this will help rendering performance, ' + 'by turning data observation off.' ) ;
}
var render = createRenderFunction ( modules , directives , isUnaryTag , cache ) ;
2016-06-08 09:53:43 +08:00
return {
2016-06-26 12:53:58 +08:00
renderToString : function renderToString ( component , done ) {
var result = '' ;
2016-06-28 10:25:12 +08:00
var write = createWriteFunction ( function ( text ) {
result += text ;
} , done ) ;
2016-06-26 12:53:58 +08:00
try {
render ( component , write , function ( ) {
done ( null , result ) ;
} ) ;
} catch ( e ) {
done ( e ) ;
}
2016-06-08 09:53:43 +08:00
} ,
2016-06-26 12:53:58 +08:00
renderToStream : function renderToStream ( component ) {
return new RenderStream ( function ( write , done ) {
render ( component , write , done ) ;
} ) ;
}
} ;
}
function createContext ( context ) {
var sandbox = {
Buffer : Buffer ,
clearImmediate : clearImmediate ,
clearInterval : clearInterval ,
clearTimeout : clearTimeout ,
setImmediate : setImmediate ,
setInterval : setInterval ,
setTimeout : setTimeout ,
console : console ,
process : process ,
2016-06-28 10:25:12 +08:00
_ _VUE _SSR _CONTEXT _ _ : context
2016-06-26 12:53:58 +08:00
} ;
sandbox . global = sandbox ;
return sandbox ;
}
2016-06-28 10:25:12 +08:00
function runInVm ( code ) {
var _context = arguments . length <= 1 || arguments [ 1 ] === undefined ? { } : arguments [ 1 ] ;
return new Promise ( function ( resolve , reject ) {
var wrapper = NativeModule . wrap ( code ) ;
var context = createContext ( _context ) ;
var compiledWrapper = vm . runInNewContext ( wrapper , context , {
filename : '__vue_ssr_bundle__' ,
displayErrors : true
} ) ;
var m = { exports : { } } ;
compiledWrapper . call ( m . exports , m . exports , require , m ) ;
var res = Object . prototype . hasOwnProperty . call ( m . exports , 'default' ) ? m . exports . default : m ;
resolve ( typeof res === 'function' ? res ( _context ) : res ) ;
2016-06-26 12:53:58 +08:00
} ) ;
}
function createBundleRendererCreator ( createRenderer ) {
return function ( code , rendererOptions ) {
var renderer = createRenderer ( rendererOptions ) ;
return {
renderToString : function renderToString ( context , cb ) {
2016-06-28 10:25:12 +08:00
if ( typeof context === 'function' ) {
cb = context ;
context = { } ;
}
2016-06-26 12:53:58 +08:00
runInVm ( code , context ) . then ( function ( app ) {
renderer . renderToString ( app , cb ) ;
2016-06-28 10:25:12 +08:00
} ) . catch ( cb ) ;
2016-06-26 12:53:58 +08:00
} ,
renderToStream : function renderToStream ( context ) {
var res = new stream . PassThrough ( ) ;
runInVm ( code , context ) . then ( function ( app ) {
renderer . renderToStream ( app ) . pipe ( res ) ;
2016-06-28 10:25:12 +08:00
} ) . catch ( function ( err ) {
process . nextTick ( function ( ) {
res . emit ( 'error' , err ) ;
} ) ;
2016-06-26 12:53:58 +08:00
} ) ;
return res ;
}
} ;
} ;
}
function renderAttrs ( node ) {
var res = '' ;
if ( node . data . staticAttrs ) {
res += render ( node . data . staticAttrs ) ;
}
if ( node . data . attrs ) {
res += render ( node . data . attrs ) ;
}
return res ;
}
function render ( attrs ) {
var res = '' ;
for ( var _key in attrs ) {
if ( _key === 'style' ) {
// leave it to the style module
continue ;
}
res += renderAttr ( _key , attrs [ _key ] ) ;
}
return res ;
}
function renderAttr ( key , value ) {
if ( isBooleanAttr ( key ) ) {
if ( ! isFalsyAttrValue ( value ) ) {
return ' ' + key + '="' + key + '"' ;
}
} else if ( isEnumeratedAttr ( key ) ) {
return ' ' + key + '="' + ( isFalsyAttrValue ( value ) || value === 'false' ? 'false' : 'true' ) + '"' ;
} else if ( ! isFalsyAttrValue ( value ) ) {
return ' ' + key + '="' + value + '"' ;
}
return '' ;
}
2016-07-24 10:48:09 +08:00
function domProps ( node ) {
var props = node . data . domProps ;
2016-06-26 12:53:58 +08:00
var res = '' ;
if ( props ) {
for ( var key in props ) {
if ( key === 'innerHTML' ) {
setText ( node , props [ key ] , true ) ;
} else if ( key === 'textContent' ) {
setText ( node , props [ key ] ) ;
} else {
var attr = propsToAttrMap [ key ] || key . toLowerCase ( ) ;
if ( isRenderableAttr ( attr ) ) {
res += renderAttr ( attr , props [ key ] ) ;
}
}
}
}
return res ;
}
function setText ( node , text , raw ) {
var child = new VNode ( undefined , undefined , undefined , text ) ;
child . raw = raw ;
node . children = [ child ] ;
}
function renderClass ( node ) {
if ( node . data . class || node . data . staticClass ) {
return ' class="' + genClassForVnode ( node ) + '"' ;
}
}
function renderStyle ( node ) {
var staticStyle = node . data . staticAttrs && node . data . staticAttrs . style ;
if ( node . data . style || staticStyle ) {
var styles = node . data . style ;
var res = ' style="' ;
if ( styles ) {
if ( Array . isArray ( styles ) ) {
styles = toObject ( styles ) ;
}
for ( var key in styles ) {
res += hyphenate ( key ) + ':' + styles [ key ] + ';' ;
}
2016-04-27 01:29:27 +08:00
}
2016-06-26 12:53:58 +08:00
return res + ( staticStyle || '' ) + '"' ;
}
}
2016-07-24 10:48:09 +08:00
var modules$1 = [ renderAttrs , domProps , renderClass , renderStyle ] ;
2016-06-26 12:53:58 +08:00
function show ( node , dir ) {
if ( ! dir . value ) {
var style = node . data . style || ( node . data . style = { } ) ;
style . display = 'none' ;
2016-04-27 01:29:27 +08:00
}
}
2016-06-26 12:53:58 +08:00
2016-07-08 05:53:22 +08:00
var baseDirectives$1 = {
2016-06-26 12:53:58 +08:00
show : show
} ;
function createRenderer ( ) {
var options = arguments . length <= 0 || arguments [ 0 ] === undefined ? { } : arguments [ 0 ] ;
// user can provide server-side implementations for custom directives
// when creating the renderer.
2016-07-08 05:53:22 +08:00
var directives = Object . assign ( baseDirectives$1 , options . directives ) ;
2016-06-26 12:53:58 +08:00
return createRenderer$1 ( {
isUnaryTag : isUnaryTag ,
2016-07-08 05:53:22 +08:00
modules : modules$1 ,
2016-06-26 12:53:58 +08:00
directives : directives ,
2016-07-08 05:53:22 +08:00
cache : options . cache
2016-06-26 12:53:58 +08:00
} ) ;
}
var createBundleRenderer = createBundleRendererCreator ( createRenderer ) ;
exports . createRenderer = createRenderer ;
exports . createBundleRenderer = createBundleRenderer ;