merge-hook
export function mergeVNodeHook(def,hookKey,hook){
if(def instanceof VNode){
def = def.data.hook || def.data.hook = {}
}
let invoker
const oldHook = def[hookKey]
function wrappedHook(){
hook.apply(this,arguments)
remove(invoker.fns,wrappedHook)
}
if(isUndef(oldHook)){
invoker = createFnInvoker([wrappedHook])
}else{
if(isDef(oldHook.fns) && isTrue(oldHook.merged)){
invoker = oldHook
invoker.fns.push(wrappedHook)
}else{
invoker = createFnInvoker([oldHook,warppedHook])
}
}
invoker.merged = true
def[hookKey] = invoker
}
extractPropsFormVNodeData
export function extractPropsFormVNodeData(data,Ctor,tag){
const propsOptions = Ctor.options.props
if(isUndef(propsOptions)){
return
}
const res = {}
const { attrs, props } = data
if(isDef(attrs) || isDef(props)){
for(const key in propsOptions){
const altKey = hyphenate(key)
...
checkProp(res,props,key,altKey,true) || checkProp(res,attrs,key,altKey,false)
}
}
return res
}
updateListeners
export function updateListeners(on,oldOn,add,remove,createOnceHandler,vm){
let name,def,cur,old,event
for(name in on){
def = cur = on[name]
old = oldOn[name]
event = normalizeEvent(name)
if(isUndef(cur)){
process.env.NODE_ENV !== 'production' && warn(`Invalid handler for event "${event.name}":got ` + String(cur))
}else if(isUndef(old)){
if(isUndef(cur.fns)){
cur = on[name] = createFnInvoker(cur,vm)
}
if(isTrue(event.once)){
cur = on[name] = createOnceHandler(event.name,cur,event.capture)
}
add(event.name,cur,event.capture,event.passive,event.params)
}else if(cur !== old){
old.fns = cur
on[name] = old
}
}
for(name in oldOn){
if(isUndef(on[name])){
event = normalizeEvent(name)
remove(event.name,oldOn[name],event.capture)
}
}
}
normalizeChildren
export function normalizeChildren(children){
return isPrimitive(children) ? [createTextVNode(children)] : Array.isArray(children) ? normalizeArrayChildren(children) : undefined
}
function normalizeArrayChildren(children,nestedIndex){
const res = []
let i,c,lastIndex,last
for(i = 0; i < children.length; i++){
c = children[i]
if(isUndef(c) || typeof c === 'boolean') continue
lastIndex = res.length - 1
last = res[lastIndex]
if(Array.isArray(c)){
if(c.length > 0){
c = normalizeArrayChildren(c,`${nestedIndex || ''}_${i}`)
if(isTextNode(c[0]) && isTextNode(last)){
res[lastIndex] = createTextVNode(last.text + c[0].text)
c.shift()
}
res.push.apply(res,c)
}
}else if(isPrimitive(c)){
if(isTextNode(last)){
res[lastIndex] = createTextVNode(last.text + c)
}else if(c !== ''){
res.push(createTextVNode(c))
}
}else{
if(isTextNode(c) && isTextNode(last)){
res[lastIndex] = createTextVNode(last.text + c.text)
}else{
if(isTrue(children._isVList) && isDef(c.tag) && isUndef(c.key) && isDef(nestedIndex)){
c.key = `_vlist${nestedIndex}_${i}__`
}
res.push(c)
}
}
}
return res
}
resolveAsyncComponent
export function resolveAsyncComponent(factory,baseCtor){
if(isTrue(factory.error) && isDef(factory.errorComp)){
return factory.errorComp
}
if(isDef(factory.resolved)){
return factory.resolved
}
const owner = currentRenderingInstance
if(owner && isDef(factory.owners) && factory.owners.indefOf(owner) === -1){
factory.owners.push(owner)
}
if(isTrue(factory.loading) && isDef(factory.loadingComp)){
return factory.loadingComp
}
if(owner && !isDef(factory.owners)){
const owners = factory.owners = [owner]
let sync = true
let timerLoading = null
let timerTimeout = null
owner.$on('hook:destroyed',() => remove(owners,owner))
const forceRender = (renderCompleted) => {
for(let i = 0; i < owners.length; i ++){
owners[i].$forceUpdate()
}
if(renderCompleted){
owners.length = 0
if(timerLoading !== null){
clearTimeout(timerLoading)
timerLoading = null
}
if(timerTimeout !== null){
clearTimeout(timerTimeout)
timerTimeout = null
}
}
}
const resolve = once((res) => {
factory.resolved = ensureCtor(res,baseCtor)
if(!sync){
forceRender(true)
}else{
owners.length = 0
}
})
const reject = once((reason) => {
process.env.NODE_ENV !== 'production' && warn(`Failed to resolve async component: ${String(factory)}` + (reason ? `\nReason:${reason}` : ''))
if(isDef(factory.errorComp)){
factory.error = true
forceRender(true)
}
})
const res = factory(resolve,reject)
if(isObject(res)){
if(isPromise(res)){
if(isUndef(factory.resolved)){
res.then(resolve,reject)
}
}else if(isPromise(res.component)){
res.component.then(resolve,reject)
if(isDef(factory.error)){
factory.errorComp = ensureCtor(res.error,baseCtor)
}
if(isDef(res.loading)){
factory.loadingComp = ensureCtor(res.loading,baseCtor)
if(res.delay === 0){
factory.loading = true
}else{
timerLoading = setTimeout(() => {
timerLoading = null
if(isUndef(factory.resolved) && isUndef(factory.error)){
factory.loading = true
forceRender(false)
}
},res.delay || 200)
}
}
if(isDef(res.timeout)){
timerTimeout = setTimeout(() => {
timerTimeout = null
if(isUndef(factory.resolved)){
reject(process.env.NODE_ENV !== 'production' ? `timeout (${res.timeout}ms)`:null)
}
},res.timeout)
}
}
}
sync = false
return factory.loading ? factory.loadingComp : factory.resolved
}
}
getFirstComponentChild
export function getFirstComponentChild(children){
if(Array.isArray(children)){
for(let i = 0; i < children.length; i ++){
const c = children[i]
if(isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))){
return c
}
}
}
}
isAsyncPlaceholder
export function isAsyncPlaceholder(node){
return node.isComment && node.asyncFactory
}
normalizeScopedSlots
export function normalizeScopedSlots(slots,normalSlots,prevSlots){
let res
const hasNormalSlots = Object.keys(normalSlots).length > 0
const isStable = slots ? !!slots.$stable : !hasNoramlSlots
const key = slots && slots.$key
if(!slots){
res = {}
}else if(slots._normalized){
return slots._normalized
}else if(isStable && prevSlots && prevSlots !== emptyObject && key === prevSlots.$key && !hasNormalSlots && !prevSlots.$hasNormal){
return prevSlots
}else {
res = {}
for(const key in slots){
if(slots[key] && key[0] !== '$'){
res[key] = normalizeScopeSlot(normalSlots,key,slots[key])
}
}
}
for(const key in normalSlots){
if(!key in res){
res[key] = proxyNormalSlot(normalSlots,key)
}
}
if(slots && Object.isExtensible(slots)){
slots._normalized = res
}
def(res,'$stable',isStable)
def(res,'$key',key)
def(res,'$hasNormal',hasNormalSlots)
return res
}