From 1807150c9a5c9e6819481b6a97241db842a9a18c Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Fri, 10 Sep 2021 11:51:47 +0800 Subject: [PATCH] build(mp): bump vue from 3.0.9 to 3.2.11 --- packages/uni-mp-alipay/dist/uni.api.esm.js | 8 +- packages/uni-mp-baidu/dist/uni.api.esm.js | 8 +- packages/uni-mp-kuaishou/dist/uni.api.esm.js | 8 +- packages/uni-mp-qq/dist/uni.api.esm.js | 8 +- packages/uni-mp-toutiao/dist/uni.api.esm.js | 8 +- packages/uni-mp-toutiao/dist/uni.mp.esm.js | 4 +- packages/uni-mp-vue/dist/vue.runtime.esm.js | 5312 +++++++++-------- packages/uni-mp-weixin/dist/uni.api.esm.js | 8 +- .../uni-quickapp-webview/dist/uni.api.esm.js | 8 +- .../uni-quickapp-webview/dist/uni.mp.esm.js | 4 +- 10 files changed, 2891 insertions(+), 2485 deletions(-) diff --git a/packages/uni-mp-alipay/dist/uni.api.esm.js b/packages/uni-mp-alipay/dist/uni.api.esm.js index b319981ff..384669b02 100644 --- a/packages/uni-mp-alipay/dist/uni.api.esm.js +++ b/packages/uni-mp-alipay/dist/uni.api.esm.js @@ -736,9 +736,13 @@ const getLocale = () => { return uni.getSystemInfoSync().language || 'zh-Hans'; }; const setLocale = (locale) => { - const oldLocale = getApp().$vm.$locale; + const app = getApp(); + if (!app) { + return false; + } + const oldLocale = app.$vm.$locale; if (oldLocale !== locale) { - getApp().$vm.$locale = locale; + app.$vm.$locale = locale; onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); return true; } diff --git a/packages/uni-mp-baidu/dist/uni.api.esm.js b/packages/uni-mp-baidu/dist/uni.api.esm.js index 65a5f1308..00e9998b2 100644 --- a/packages/uni-mp-baidu/dist/uni.api.esm.js +++ b/packages/uni-mp-baidu/dist/uni.api.esm.js @@ -736,9 +736,13 @@ const getLocale = () => { return uni.getSystemInfoSync().language || 'zh-Hans'; }; const setLocale = (locale) => { - const oldLocale = getApp().$vm.$locale; + const app = getApp(); + if (!app) { + return false; + } + const oldLocale = app.$vm.$locale; if (oldLocale !== locale) { - getApp().$vm.$locale = locale; + app.$vm.$locale = locale; onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); return true; } diff --git a/packages/uni-mp-kuaishou/dist/uni.api.esm.js b/packages/uni-mp-kuaishou/dist/uni.api.esm.js index 7ad77fc21..9f4c38557 100644 --- a/packages/uni-mp-kuaishou/dist/uni.api.esm.js +++ b/packages/uni-mp-kuaishou/dist/uni.api.esm.js @@ -736,9 +736,13 @@ const getLocale = () => { return uni.getSystemInfoSync().language || 'zh-Hans'; }; const setLocale = (locale) => { - const oldLocale = getApp().$vm.$locale; + const app = getApp(); + if (!app) { + return false; + } + const oldLocale = app.$vm.$locale; if (oldLocale !== locale) { - getApp().$vm.$locale = locale; + app.$vm.$locale = locale; onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); return true; } diff --git a/packages/uni-mp-qq/dist/uni.api.esm.js b/packages/uni-mp-qq/dist/uni.api.esm.js index 9941b76b8..08206a251 100644 --- a/packages/uni-mp-qq/dist/uni.api.esm.js +++ b/packages/uni-mp-qq/dist/uni.api.esm.js @@ -736,9 +736,13 @@ const getLocale = () => { return uni.getSystemInfoSync().language || 'zh-Hans'; }; const setLocale = (locale) => { - const oldLocale = getApp().$vm.$locale; + const app = getApp(); + if (!app) { + return false; + } + const oldLocale = app.$vm.$locale; if (oldLocale !== locale) { - getApp().$vm.$locale = locale; + app.$vm.$locale = locale; onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); return true; } diff --git a/packages/uni-mp-toutiao/dist/uni.api.esm.js b/packages/uni-mp-toutiao/dist/uni.api.esm.js index bae0f5268..4959c6fba 100644 --- a/packages/uni-mp-toutiao/dist/uni.api.esm.js +++ b/packages/uni-mp-toutiao/dist/uni.api.esm.js @@ -736,9 +736,13 @@ const getLocale = () => { return uni.getSystemInfoSync().language || 'zh-Hans'; }; const setLocale = (locale) => { - const oldLocale = getApp().$vm.$locale; + const app = getApp(); + if (!app) { + return false; + } + const oldLocale = app.$vm.$locale; if (oldLocale !== locale) { - getApp().$vm.$locale = locale; + app.$vm.$locale = locale; onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); return true; } diff --git a/packages/uni-mp-toutiao/dist/uni.mp.esm.js b/packages/uni-mp-toutiao/dist/uni.mp.esm.js index de97b6799..0cddfda28 100644 --- a/packages/uni-mp-toutiao/dist/uni.mp.esm.js +++ b/packages/uni-mp-toutiao/dist/uni.mp.esm.js @@ -1333,7 +1333,7 @@ function handleLink({ detail: { vuePid, nodeId, webviewId }, }) { initInjections(vm); initProvide(vm); } - vm.$callSyncHook('created'); + vm.$callCreatedHook(); vm.$callHook('mounted'); vm.$callHook(ON_READY); } @@ -1356,7 +1356,7 @@ function initLifetimes(lifetimesOptions) { return extend(initLifetimes$1(lifetimesOptions), { ready() { if (this.$vm && lifetimesOptions.isPage(this)) { - this.$vm.$callSyncHook('created'); + this.$vm.$callCreatedHook(); this.$vm.$callHook('mounted'); this.$vm.$callHook(ON_READY); } diff --git a/packages/uni-mp-vue/dist/vue.runtime.esm.js b/packages/uni-mp-vue/dist/vue.runtime.esm.js index 1b6655123..43fe264f3 100644 --- a/packages/uni-mp-vue/dist/vue.runtime.esm.js +++ b/packages/uni-mp-vue/dist/vue.runtime.esm.js @@ -1,73 +1,229 @@ -import { isSymbol, extend, isMap, isObject, toRawType, def, isArray, isString, isFunction, isPromise, toHandlerKey, remove, EMPTY_OBJ, camelize, capitalize, normalizeClass, normalizeStyle, isOn, NOOP, isGloballyWhitelisted, isIntegerKey, hasOwn, hasChanged, invokeArrayFns as invokeArrayFns$1, makeMap, isSet, NO, toNumber, hyphenate, isReservedProp, EMPTY_ARR, toTypeString } from '@vue/shared'; +import { isSymbol, isObject, toRawType, def, isArray, isFunction, NOOP, remove, toHandlerKey, camelize, capitalize, isString, normalizeClass, extend, normalizeStyle, isOn, isPromise, EMPTY_OBJ, hasChanged, isSet, isMap, isPlainObject, invokeArrayFns, hasOwn, NO, isIntegerKey, toNumber, hyphenate, isReservedProp, EMPTY_ARR, makeMap, toTypeString } from '@vue/shared'; export { camelize } from '@vue/shared'; -const invokeArrayFns = (fns, arg) => { - let ret; - for (let i = 0; i < fns.length; i++) { - ret = fns[i](arg); +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_BACK_PRESS = 'onBackPress'; +const ON_PAGE_SCROLL = 'onPageScroll'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_SHARE_TIMELINE = 'onShareTimeline'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +const ON_SHARE_APP_MESSAGE = 'onShareAppMessage'; +// navigationBar +const ON_NAVIGATION_BAR_BUTTON_TAP = 'onNavigationBarButtonTap'; +const ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED = 'onNavigationBarSearchInputClicked'; +const ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED = 'onNavigationBarSearchInputChanged'; +const ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED = 'onNavigationBarSearchInputConfirmed'; +const ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED = 'onNavigationBarSearchInputFocusChanged'; +const UniLifecycleHooks = [ + ON_SHOW, + ON_HIDE, + ON_LAUNCH, + ON_ERROR, + ON_THEME_CHANGE, + ON_PAGE_NOT_FOUND, + ON_UNHANDLE_REJECTION, + ON_LOAD, + ON_READY, + ON_UNLOAD, + ON_RESIZE, + ON_BACK_PRESS, + ON_PAGE_SCROLL, + ON_TAB_ITEM_TAP, + ON_REACH_BOTTOM, + ON_PULL_DOWN_REFRESH, + ON_SHARE_TIMELINE, + ON_ADD_TO_FAVORITES, + ON_SHARE_APP_MESSAGE, + ON_NAVIGATION_BAR_BUTTON_TAP, + ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, + ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, + ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, + ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, +]; + +function warn(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} + +let activeEffectScope; +const effectScopeStack = []; +class EffectScope { + constructor(detached = false) { + this.active = true; + this.effects = []; + this.cleanups = []; + if (!detached && activeEffectScope) { + this.parent = activeEffectScope; + this.index = + (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this) - 1; + } + } + run(fn) { + if (this.active) { + try { + this.on(); + return fn(); + } + finally { + this.off(); + } + } + else if ((process.env.NODE_ENV !== 'production')) { + warn(`cannot run an inactive effect scope.`); + } + } + on() { + if (this.active) { + effectScopeStack.push(this); + activeEffectScope = this; + } + } + off() { + if (this.active) { + effectScopeStack.pop(); + activeEffectScope = effectScopeStack[effectScopeStack.length - 1]; + } + } + stop(fromParent) { + if (this.active) { + this.effects.forEach(e => e.stop()); + this.cleanups.forEach(cleanup => cleanup()); + if (this.scopes) { + this.scopes.forEach(e => e.stop(true)); + } + // nested scope, dereference from parent to avoid memory leaks + if (this.parent && !fromParent) { + // optimized O(1) removal + const last = this.parent.scopes.pop(); + if (last && last !== this) { + this.parent.scopes[this.index] = last; + last.index = this.index; + } + } + this.active = false; + } + } +} +function recordEffectScope(effect, scope) { + scope = scope || activeEffectScope; + if (scope && scope.active) { + scope.effects.push(effect); + } +} + +const createDep = (effects) => { + const dep = new Set(effects); + dep.w = 0; + dep.n = 0; + return dep; +}; +const wasTracked = (dep) => (dep.w & trackOpBit) > 0; +const newTracked = (dep) => (dep.n & trackOpBit) > 0; +const initDepMarkers = ({ deps }) => { + if (deps.length) { + for (let i = 0; i < deps.length; i++) { + deps[i].w |= trackOpBit; // set was tracked + } } - return ret; }; -const ON_ERROR = 'onError'; +const finalizeDepMarkers = (effect) => { + const { deps } = effect; + if (deps.length) { + let ptr = 0; + for (let i = 0; i < deps.length; i++) { + const dep = deps[i]; + if (wasTracked(dep) && !newTracked(dep)) { + dep.delete(effect); + } + else { + deps[ptr++] = dep; + } + // clear bits + dep.w &= ~trackOpBit; + dep.n &= ~trackOpBit; + } + deps.length = ptr; + } +}; const targetMap = new WeakMap(); +// The number of effects currently being tracked recursively. +let effectTrackDepth = 0; +let trackOpBit = 1; +/** + * The bitwise track markers support at most 30 levels op recursion. + * This value is chosen to enable modern JS engines to use a SMI on all platforms. + * When recursion depth is greater, fall back to using a full cleanup. + */ +const maxMarkerBits = 30; const effectStack = []; let activeEffect; const ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'iterate' : ''); const MAP_KEY_ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'Map key iterate' : ''); -function isEffect(fn) { - return fn && fn._isEffect === true; -} -function effect(fn, options = EMPTY_OBJ) { - if (isEffect(fn)) { - fn = fn.raw; - } - const effect = createReactiveEffect(fn, options); - if (!options.lazy) { - effect(); - } - return effect; -} -function stop(effect) { - if (effect.active) { - cleanup(effect); - if (effect.options.onStop) { - effect.options.onStop(); - } - effect.active = false; - } -} -let uid = 0; -function createReactiveEffect(fn, options) { - const effect = function reactiveEffect() { - if (!effect.active) { - return options.scheduler ? undefined : fn(); - } - if (!effectStack.includes(effect)) { - cleanup(effect); +class ReactiveEffect { + constructor(fn, scheduler = null, scope) { + this.fn = fn; + this.scheduler = scheduler; + this.active = true; + this.deps = []; + recordEffectScope(this, scope); + } + run() { + if (!this.active) { + return this.fn(); + } + if (!effectStack.includes(this)) { try { + effectStack.push((activeEffect = this)); enableTracking(); - effectStack.push(effect); - activeEffect = effect; - return fn(); + trackOpBit = 1 << ++effectTrackDepth; + if (effectTrackDepth <= maxMarkerBits) { + initDepMarkers(this); + } + else { + cleanupEffect(this); + } + return this.fn(); } finally { - effectStack.pop(); + if (effectTrackDepth <= maxMarkerBits) { + finalizeDepMarkers(this); + } + trackOpBit = 1 << --effectTrackDepth; resetTracking(); - activeEffect = effectStack[effectStack.length - 1]; + effectStack.pop(); + const n = effectStack.length; + activeEffect = n > 0 ? effectStack[n - 1] : undefined; } } - }; - effect.id = uid++; - effect.allowRecurse = !!options.allowRecurse; - effect._isEffect = true; - effect.active = true; - effect.raw = fn; - effect.deps = []; - effect.options = options; - return effect; -} -function cleanup(effect) { + } + stop() { + if (this.active) { + cleanupEffect(this); + if (this.onStop) { + this.onStop(); + } + this.active = false; + } + } +} +function cleanupEffect(effect) { const { deps } = effect; if (deps.length) { for (let i = 0; i < deps.length; i++) { @@ -76,6 +232,23 @@ function cleanup(effect) { deps.length = 0; } } +function effect(fn, options) { + if (fn.effect) { + fn = fn.effect.fn; + } + const _effect = new ReactiveEffect(fn); + if (options) { + extend(_effect, options); + if (options.scope) + recordEffectScope(_effect, options.scope); + } + if (!options || !options.lazy) { + _effect.run(); + } + const runner = _effect.run.bind(_effect); + runner.effect = _effect; + return runner; +} let shouldTrack = true; const trackStack = []; function pauseTracking() { @@ -91,7 +264,7 @@ function resetTracking() { shouldTrack = last === undefined ? true : last; } function track(target, type, key) { - if (!shouldTrack || activeEffect === undefined) { + if (!isTracking()) { return; } let depsMap = targetMap.get(target); @@ -100,18 +273,35 @@ function track(target, type, key) { } let dep = depsMap.get(key); if (!dep) { - depsMap.set(key, (dep = new Set())); + depsMap.set(key, (dep = createDep())); + } + const eventInfo = (process.env.NODE_ENV !== 'production') + ? { effect: activeEffect, target, type, key } + : undefined; + trackEffects(dep, eventInfo); +} +function isTracking() { + return shouldTrack && activeEffect !== undefined; +} +function trackEffects(dep, debuggerEventExtraInfo) { + let shouldTrack = false; + if (effectTrackDepth <= maxMarkerBits) { + if (!newTracked(dep)) { + dep.n |= trackOpBit; // set newly tracked + shouldTrack = !wasTracked(dep); + } + } + else { + // Full cleanup mode. + shouldTrack = !dep.has(activeEffect); } - if (!dep.has(activeEffect)) { + if (shouldTrack) { dep.add(activeEffect); activeEffect.deps.push(dep); - if ((process.env.NODE_ENV !== 'production') && activeEffect.options.onTrack) { - activeEffect.options.onTrack({ - effect: activeEffect, - target, - type, - key - }); + if ((process.env.NODE_ENV !== 'production') && activeEffect.onTrack) { + activeEffect.onTrack(Object.assign({ + effect: activeEffect + }, debuggerEventExtraInfo)); } } } @@ -121,82 +311,96 @@ function trigger(target, type, key, newValue, oldValue, oldTarget) { // never been tracked return; } - const effects = new Set(); - const add = (effectsToAdd) => { - if (effectsToAdd) { - effectsToAdd.forEach(effect => { - if (effect !== activeEffect || effect.allowRecurse) { - effects.add(effect); - } - }); - } - }; + let deps = []; if (type === "clear" /* CLEAR */) { // collection being cleared // trigger all effects for target - depsMap.forEach(add); + deps = [...depsMap.values()]; } else if (key === 'length' && isArray(target)) { depsMap.forEach((dep, key) => { if (key === 'length' || key >= newValue) { - add(dep); + deps.push(dep); } }); } else { // schedule runs for SET | ADD | DELETE if (key !== void 0) { - add(depsMap.get(key)); + deps.push(depsMap.get(key)); } // also run for iteration key on ADD | DELETE | Map.SET switch (type) { case "add" /* ADD */: if (!isArray(target)) { - add(depsMap.get(ITERATE_KEY)); + deps.push(depsMap.get(ITERATE_KEY)); if (isMap(target)) { - add(depsMap.get(MAP_KEY_ITERATE_KEY)); + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); } } else if (isIntegerKey(key)) { // new index added to array -> length changes - add(depsMap.get('length')); + deps.push(depsMap.get('length')); } break; case "delete" /* DELETE */: if (!isArray(target)) { - add(depsMap.get(ITERATE_KEY)); + deps.push(depsMap.get(ITERATE_KEY)); if (isMap(target)) { - add(depsMap.get(MAP_KEY_ITERATE_KEY)); + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); } } break; case "set" /* SET */: if (isMap(target)) { - add(depsMap.get(ITERATE_KEY)); + deps.push(depsMap.get(ITERATE_KEY)); } break; } } - const run = (effect) => { - if ((process.env.NODE_ENV !== 'production') && effect.options.onTrigger) { - effect.options.onTrigger({ - effect, - target, - key, - type, - newValue, - oldValue, - oldTarget - }); + const eventInfo = (process.env.NODE_ENV !== 'production') + ? { target, type, key, newValue, oldValue, oldTarget } + : undefined; + if (deps.length === 1) { + if (deps[0]) { + if ((process.env.NODE_ENV !== 'production')) { + triggerEffects(deps[0], eventInfo); + } + else { + triggerEffects(deps[0]); + } + } + } + else { + const effects = []; + for (const dep of deps) { + if (dep) { + effects.push(...dep); + } } - if (effect.options.scheduler) { - effect.options.scheduler(effect); + if ((process.env.NODE_ENV !== 'production')) { + triggerEffects(createDep(effects), eventInfo); } else { - effect(); + triggerEffects(createDep(effects)); } - }; - effects.forEach(run); + } +} +function triggerEffects(dep, debuggerEventExtraInfo) { + // spread into array for stabilization + for (const effect of isArray(dep) ? dep : [...dep]) { + if (effect !== activeEffect || effect.allowRecurse) { + if ((process.env.NODE_ENV !== 'production') && effect.onTrigger) { + effect.onTrigger(extend({ effect }, debuggerEventExtraInfo)); + } + if (effect.scheduler) { + effect.scheduler(); + } + else { + effect.run(); + } + } + } } const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`); @@ -207,34 +411,36 @@ const get = /*#__PURE__*/ createGetter(); const shallowGet = /*#__PURE__*/ createGetter(false, true); const readonlyGet = /*#__PURE__*/ createGetter(true); const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true); -const arrayInstrumentations = {}; -['includes', 'indexOf', 'lastIndexOf'].forEach(key => { - const method = Array.prototype[key]; - arrayInstrumentations[key] = function (...args) { - const arr = toRaw(this); - for (let i = 0, l = this.length; i < l; i++) { - track(arr, "get" /* GET */, i + ''); - } - // we run the method using the original args first (which may be reactive) - const res = method.apply(arr, args); - if (res === -1 || res === false) { - // if that didn't work, run it again using raw values. - return method.apply(arr, args.map(toRaw)); - } - else { +const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations(); +function createArrayInstrumentations() { + const instrumentations = {}; + ['includes', 'indexOf', 'lastIndexOf'].forEach(key => { + instrumentations[key] = function (...args) { + const arr = toRaw(this); + for (let i = 0, l = this.length; i < l; i++) { + track(arr, "get" /* GET */, i + ''); + } + // we run the method using the original args first (which may be reactive) + const res = arr[key](...args); + if (res === -1 || res === false) { + // if that didn't work, run it again using raw values. + return arr[key](...args.map(toRaw)); + } + else { + return res; + } + }; + }); + ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => { + instrumentations[key] = function (...args) { + pauseTracking(); + const res = toRaw(this)[key].apply(this, args); + resetTracking(); return res; - } - }; -}); -['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => { - const method = Array.prototype[key]; - arrayInstrumentations[key] = function (...args) { - pauseTracking(); - const res = method.apply(this, args); - resetTracking(); - return res; - }; -}); + }; + }); + return instrumentations; +} function createGetter(isReadonly = false, shallow = false) { return function get(target, key, receiver) { if (key === "__v_isReactive" /* IS_REACTIVE */) { @@ -259,9 +465,7 @@ function createGetter(isReadonly = false, shallow = false) { return Reflect.get(arrayInstrumentations, key, receiver); } const res = Reflect.get(target, key, receiver); - if (isSymbol(key) - ? builtInSymbols.has(key) - : isNonTrackableKeys(key)) { + if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { return res; } if (!isReadonly) { @@ -288,9 +492,10 @@ const set$1 = /*#__PURE__*/ createSetter(); const shallowSet = /*#__PURE__*/ createSetter(true); function createSetter(shallow = false) { return function set(target, key, value, receiver) { - const oldValue = target[key]; + let oldValue = target[key]; if (!shallow) { value = toRaw(value); + oldValue = toRaw(oldValue); if (!isArray(target) && isRef(oldValue) && !isRef(value)) { oldValue.value = value; return true; @@ -354,14 +559,14 @@ const readonlyHandlers = { return true; } }; -const shallowReactiveHandlers = extend({}, mutableHandlers, { +const shallowReactiveHandlers = /*#__PURE__*/ extend({}, mutableHandlers, { get: shallowGet, set: shallowSet }); // Props handlers are special in the sense that it should not unwrap top-level // refs (in order to allow refs to be explicitly passed down), but should // retain the reactivity of the normal readonly object. -const shallowReadonlyHandlers = extend({}, readonlyHandlers, { +const shallowReadonlyHandlers = /*#__PURE__*/ extend({}, readonlyHandlers, { get: shallowReadonlyGet }); @@ -387,6 +592,11 @@ function get$1(target, key, isReadonly = false, isShallow = false) { else if (has.call(rawTarget, rawKey)) { return wrap(target.get(rawKey)); } + else if (target !== rawTarget) { + // #3602 readonly(reactive(Map)) + // ensure that the nested reactive `Map` can do tracking for itself + target.get(key); + } } function has$1(key, isReadonly = false) { const target = this["__v_raw" /* RAW */]; @@ -527,73 +737,82 @@ function createReadonlyMethod(type) { return type === "delete" /* DELETE */ ? false : this; }; } -const mutableInstrumentations = { - get(key) { - return get$1(this, key); - }, - get size() { - return size(this); - }, - has: has$1, - add, - set: set$1$1, - delete: deleteEntry, - clear, - forEach: createForEach(false, false) -}; -const shallowInstrumentations = { - get(key) { - return get$1(this, key, false, true); - }, - get size() { - return size(this); - }, - has: has$1, - add, - set: set$1$1, - delete: deleteEntry, - clear, - forEach: createForEach(false, true) -}; -const readonlyInstrumentations = { - get(key) { - return get$1(this, key, true); - }, - get size() { - return size(this, true); - }, - has(key) { - return has$1.call(this, key, true); - }, - add: createReadonlyMethod("add" /* ADD */), - set: createReadonlyMethod("set" /* SET */), - delete: createReadonlyMethod("delete" /* DELETE */), - clear: createReadonlyMethod("clear" /* CLEAR */), - forEach: createForEach(true, false) -}; -const shallowReadonlyInstrumentations = { - get(key) { - return get$1(this, key, true, true); - }, - get size() { - return size(this, true); - }, - has(key) { - return has$1.call(this, key, true); - }, - add: createReadonlyMethod("add" /* ADD */), - set: createReadonlyMethod("set" /* SET */), - delete: createReadonlyMethod("delete" /* DELETE */), - clear: createReadonlyMethod("clear" /* CLEAR */), - forEach: createForEach(true, true) -}; -const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator]; -iteratorMethods.forEach(method => { - mutableInstrumentations[method] = createIterableMethod(method, false, false); - readonlyInstrumentations[method] = createIterableMethod(method, true, false); - shallowInstrumentations[method] = createIterableMethod(method, false, true); - shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true); -}); +function createInstrumentations() { + const mutableInstrumentations = { + get(key) { + return get$1(this, key); + }, + get size() { + return size(this); + }, + has: has$1, + add, + set: set$1$1, + delete: deleteEntry, + clear, + forEach: createForEach(false, false) + }; + const shallowInstrumentations = { + get(key) { + return get$1(this, key, false, true); + }, + get size() { + return size(this); + }, + has: has$1, + add, + set: set$1$1, + delete: deleteEntry, + clear, + forEach: createForEach(false, true) + }; + const readonlyInstrumentations = { + get(key) { + return get$1(this, key, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has$1.call(this, key, true); + }, + add: createReadonlyMethod("add" /* ADD */), + set: createReadonlyMethod("set" /* SET */), + delete: createReadonlyMethod("delete" /* DELETE */), + clear: createReadonlyMethod("clear" /* CLEAR */), + forEach: createForEach(true, false) + }; + const shallowReadonlyInstrumentations = { + get(key) { + return get$1(this, key, true, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has$1.call(this, key, true); + }, + add: createReadonlyMethod("add" /* ADD */), + set: createReadonlyMethod("set" /* SET */), + delete: createReadonlyMethod("delete" /* DELETE */), + clear: createReadonlyMethod("clear" /* CLEAR */), + forEach: createForEach(true, true) + }; + const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator]; + iteratorMethods.forEach(method => { + mutableInstrumentations[method] = createIterableMethod(method, false, false); + readonlyInstrumentations[method] = createIterableMethod(method, true, false); + shallowInstrumentations[method] = createIterableMethod(method, false, true); + shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true); + }); + return [ + mutableInstrumentations, + readonlyInstrumentations, + shallowInstrumentations, + shallowReadonlyInstrumentations + ]; +} +const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations(); function createInstrumentationGetter(isReadonly, shallow) { const instrumentations = shallow ? isReadonly @@ -618,16 +837,16 @@ function createInstrumentationGetter(isReadonly, shallow) { }; } const mutableCollectionHandlers = { - get: createInstrumentationGetter(false, false) + get: /*#__PURE__*/ createInstrumentationGetter(false, false) }; const shallowCollectionHandlers = { - get: createInstrumentationGetter(false, true) + get: /*#__PURE__*/ createInstrumentationGetter(false, true) }; const readonlyCollectionHandlers = { - get: createInstrumentationGetter(true, false) + get: /*#__PURE__*/ createInstrumentationGetter(true, false) }; const shallowReadonlyCollectionHandlers = { - get: createInstrumentationGetter(true, true) + get: /*#__PURE__*/ createInstrumentationGetter(true, true) }; function checkIdentityKeys(target, has, key) { const rawKey = toRaw(key); @@ -735,50 +954,87 @@ function isProxy(value) { return isReactive(value) || isReadonly(value); } function toRaw(observed) { - return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed); + const raw = observed && observed["__v_raw" /* RAW */]; + return raw ? toRaw(raw) : observed; } function markRaw(value) { def(value, "__v_skip" /* SKIP */, true); return value; } +function trackRefValue(ref) { + if (isTracking()) { + ref = toRaw(ref); + if (!ref.dep) { + ref.dep = createDep(); + } + if ((process.env.NODE_ENV !== 'production')) { + trackEffects(ref.dep, { + target: ref, + type: "get" /* GET */, + key: 'value' + }); + } + else { + trackEffects(ref.dep); + } + } +} +function triggerRefValue(ref, newVal) { + ref = toRaw(ref); + if (ref.dep) { + if ((process.env.NODE_ENV !== 'production')) { + triggerEffects(ref.dep, { + target: ref, + type: "set" /* SET */, + key: 'value', + newValue: newVal + }); + } + else { + triggerEffects(ref.dep); + } + } +} const convert = (val) => isObject(val) ? reactive(val) : val; function isRef(r) { return Boolean(r && r.__v_isRef === true); } function ref(value) { - return createRef(value); + return createRef(value, false); } function shallowRef(value) { return createRef(value, true); } class RefImpl { - constructor(_rawValue, _shallow = false) { - this._rawValue = _rawValue; + constructor(value, _shallow) { this._shallow = _shallow; + this.dep = undefined; this.__v_isRef = true; - this._value = _shallow ? _rawValue : convert(_rawValue); + this._rawValue = _shallow ? value : toRaw(value); + this._value = _shallow ? value : convert(value); } get value() { - track(toRaw(this), "get" /* GET */, 'value'); + trackRefValue(this); return this._value; } set value(newVal) { - if (hasChanged(toRaw(newVal), this._rawValue)) { + newVal = this._shallow ? newVal : toRaw(newVal); + if (hasChanged(newVal, this._rawValue)) { this._rawValue = newVal; this._value = this._shallow ? newVal : convert(newVal); - trigger(toRaw(this), "set" /* SET */, 'value', newVal); + triggerRefValue(this, newVal); } } } -function createRef(rawValue, shallow = false) { +function createRef(rawValue, shallow) { if (isRef(rawValue)) { return rawValue; } return new RefImpl(rawValue, shallow); } function triggerRef(ref) { - trigger(toRaw(ref), "set" /* SET */, 'value', (process.env.NODE_ENV !== 'production') ? ref.value : void 0); + triggerRefValue(ref, (process.env.NODE_ENV !== 'production') ? ref.value : void 0); } function unref(ref) { return isRef(ref) ? ref.value : ref; @@ -803,8 +1059,9 @@ function proxyRefs(objectWithRefs) { } class CustomRefImpl { constructor(factory) { + this.dep = undefined; this.__v_isRef = true; - const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value')); + const { get, set } = factory(() => trackRefValue(this), () => triggerRefValue(this)); this._get = get; this._set = set; } @@ -842,23 +1099,20 @@ class ObjectRefImpl { } } function toRef(object, key) { - return isRef(object[key]) - ? object[key] - : new ObjectRefImpl(object, key); + const val = object[key]; + return isRef(val) ? val : new ObjectRefImpl(object, key); } class ComputedRefImpl { constructor(getter, _setter, isReadonly) { this._setter = _setter; + this.dep = undefined; this._dirty = true; this.__v_isRef = true; - this.effect = effect(getter, { - lazy: true, - scheduler: () => { - if (!this._dirty) { - this._dirty = true; - trigger(toRaw(this), "set" /* SET */, 'value'); - } + this.effect = new ReactiveEffect(getter, () => { + if (!this._dirty) { + this._dirty = true; + triggerRefValue(this); } }); this["__v_isReadonly" /* IS_READONLY */] = isReadonly; @@ -866,18 +1120,18 @@ class ComputedRefImpl { get value() { // the computed ref may get wrapped by other proxies e.g. readonly() #3376 const self = toRaw(this); + trackRefValue(self); if (self._dirty) { - self._value = this.effect(); self._dirty = false; + self._value = self.effect.run(); } - track(self, "get" /* GET */, 'value'); return self._value; } set value(newValue) { this._setter(newValue); } } -function computed(getterOrOptions) { +function computed(getterOrOptions, debugOptions) { let getter; let setter; if (isFunction(getterOrOptions)) { @@ -892,550 +1146,746 @@ function computed(getterOrOptions) { getter = getterOrOptions.get; setter = getterOrOptions.set; } - return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set); + const cRef = new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set); + if ((process.env.NODE_ENV !== 'production') && debugOptions) { + cRef.effect.onTrack = debugOptions.onTrack; + cRef.effect.onTrigger = debugOptions.onTrigger; + } + return cRef; } -const stack = []; -function pushWarningContext(vnode) { - stack.push(vnode); -} -function popWarningContext() { - stack.pop(); -} -function warn(msg, ...args) { - // avoid props formatting or warn handler tracking deps that might be mutated - // during patch, leading to infinite recursion. - pauseTracking(); - const instance = stack.length ? stack[stack.length - 1].component : null; - const appWarnHandler = instance && instance.appContext.config.warnHandler; - const trace = getComponentTrace(); - if (appWarnHandler) { - callWithErrorHandling(appWarnHandler, instance, 11 /* APP_WARN_HANDLER */, [ - msg + args.join(''), - instance && instance.proxy, - trace - .map(({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`) - .join('\n'), - trace - ]); - } - else { - const warnArgs = [`[Vue warn]: ${msg}`, ...args]; - /* istanbul ignore if */ - if (trace.length && - // avoid spamming console during tests - !false) { - warnArgs.push(`\n`, ...formatTrace(trace)); +function emit(instance, event, ...rawArgs) { + const props = instance.vnode.props || EMPTY_OBJ; + if ((process.env.NODE_ENV !== 'production')) { + const { emitsOptions, propsOptions: [propsOptions] } = instance; + if (emitsOptions) { + if (!(event in emitsOptions) && + !(false )) { + if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { + warn$1(`Component emitted event "${event}" but it is neither declared in ` + + `the emits option nor as an "${toHandlerKey(event)}" prop.`); + } + } + else { + const validator = emitsOptions[event]; + if (isFunction(validator)) { + const isValid = validator(...rawArgs); + if (!isValid) { + warn$1(`Invalid event arguments: event validation failed for event "${event}".`); + } + } + } } - console.warn(...warnArgs); - } - resetTracking(); -} -function getComponentTrace() { - let currentVNode = stack[stack.length - 1]; - if (!currentVNode) { - return []; } - // we can't just use the stack because it will be incomplete during updates - // that did not start from the root. Re-construct the parent chain using - // instance parent pointers. - const normalizedStack = []; - while (currentVNode) { - const last = normalizedStack[0]; - if (last && last.vnode === currentVNode) { - last.recurseCount++; + let args = rawArgs; + const isModelListener = event.startsWith('update:'); + // for v-model update:xxx events, apply modifiers on args + const modelArg = isModelListener && event.slice(7); + if (modelArg && modelArg in props) { + const modifiersKey = `${modelArg === 'modelValue' ? 'model' : modelArg}Modifiers`; + const { number, trim } = props[modifiersKey] || EMPTY_OBJ; + if (trim) { + args = rawArgs.map(a => a.trim()); } - else { - normalizedStack.push({ - vnode: currentVNode, - recurseCount: 0 - }); + else if (number) { + args = rawArgs.map(toNumber); } - const parentInstance = currentVNode.component && currentVNode.component.parent; - currentVNode = parentInstance && parentInstance.vnode; } - return normalizedStack; -} -/* istanbul ignore next */ -function formatTrace(trace) { - const logs = []; - trace.forEach((entry, i) => { - logs.push(...(i === 0 ? [] : [`\n`]), ...formatTraceEntry(entry)); - }); - return logs; -} -function formatTraceEntry({ vnode, recurseCount }) { - const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``; - const isRoot = vnode.component ? vnode.component.parent == null : false; - const open = ` at <${formatComponentName(vnode.component, vnode.type, isRoot)}`; - const close = `>` + postfix; - return vnode.props - ? [open, ...formatProps(vnode.props), close] - : [open + close]; -} -/* istanbul ignore next */ -function formatProps(props) { - const res = []; - const keys = Object.keys(props); - keys.slice(0, 3).forEach(key => { - res.push(...formatProp(key, props[key])); - }); - if (keys.length > 3) { - res.push(` ...`); + if ((process.env.NODE_ENV !== 'production') || false) ; + if ((process.env.NODE_ENV !== 'production')) { + const lowerCaseEvent = event.toLowerCase(); + if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) { + warn$1(`Event "${lowerCaseEvent}" is emitted in component ` + + `${formatComponentName(instance, instance.type)} but the handler is registered for "${event}". ` + + `Note that HTML attributes are case-insensitive and you cannot use ` + + `v-on to listen to camelCase events when using in-DOM templates. ` + + `You should probably use "${hyphenate(event)}" instead of "${event}".`); + } + } + let handlerName; + let handler = props[(handlerName = toHandlerKey(event))] || + // also try camelCase event handler (#2249) + props[(handlerName = toHandlerKey(camelize(event)))]; + // for v-model update:xxx events, also trigger kebab-case equivalent + // for props passed via kebab-case + if (!handler && isModelListener) { + handler = props[(handlerName = toHandlerKey(hyphenate(event)))]; + } + if (handler) { + callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args); + } + const onceHandler = props[handlerName + `Once`]; + if (onceHandler) { + if (!instance.emitted) { + instance.emitted = {}; + } + else if (instance.emitted[handlerName]) { + return; + } + instance.emitted[handlerName] = true; + callWithAsyncErrorHandling(onceHandler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args); } - return res; } -/* istanbul ignore next */ -function formatProp(key, value, raw) { - if (isString(value)) { - value = JSON.stringify(value); - return raw ? value : [`${key}=${value}`]; +function normalizeEmitsOptions(comp, appContext, asMixin = false) { + const cache = appContext.emitsCache; + const cached = cache.get(comp); + if (cached !== undefined) { + return cached; } - else if (typeof value === 'number' || - typeof value === 'boolean' || - value == null) { - return raw ? value : [`${key}=${value}`]; + const raw = comp.emits; + let normalized = {}; + // apply mixin/extends props + let hasExtends = false; + if (__VUE_OPTIONS_API__ && !isFunction(comp)) { + const extendEmits = (raw) => { + const normalizedFromExtend = normalizeEmitsOptions(raw, appContext, true); + if (normalizedFromExtend) { + hasExtends = true; + extend(normalized, normalizedFromExtend); + } + }; + if (!asMixin && appContext.mixins.length) { + appContext.mixins.forEach(extendEmits); + } + if (comp.extends) { + extendEmits(comp.extends); + } + if (comp.mixins) { + comp.mixins.forEach(extendEmits); + } } - else if (isRef(value)) { - value = formatProp(key, toRaw(value.value), true); - return raw ? value : [`${key}=Ref<`, value, `>`]; + if (!raw && !hasExtends) { + cache.set(comp, null); + return null; } - else if (isFunction(value)) { - return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; + if (isArray(raw)) { + raw.forEach(key => (normalized[key] = null)); } else { - value = toRaw(value); - return raw ? value : [`${key}=`, value]; + extend(normalized, raw); + } + cache.set(comp, normalized); + return normalized; +} +// Check if an incoming prop key is a declared emit event listener. +// e.g. With `emits: { click: null }`, props named `onClick` and `onclick` are +// both considered matched listeners. +function isEmitListener(options, key) { + if (!options || !isOn(key)) { + return false; } + key = key.slice(2).replace(/Once$/, ''); + return (hasOwn(options, key[0].toLowerCase() + key.slice(1)) || + hasOwn(options, hyphenate(key)) || + hasOwn(options, key)); } -const ErrorTypeStrings = { - ["bc" /* BEFORE_CREATE */]: 'beforeCreate hook', - ["c" /* CREATED */]: 'created hook', - ["bm" /* BEFORE_MOUNT */]: 'beforeMount hook', - ["m" /* MOUNTED */]: 'mounted hook', - ["bu" /* BEFORE_UPDATE */]: 'beforeUpdate hook', - ["u" /* UPDATED */]: 'updated', - ["bum" /* BEFORE_UNMOUNT */]: 'beforeUnmount hook', - ["um" /* UNMOUNTED */]: 'unmounted hook', - ["a" /* ACTIVATED */]: 'activated hook', - ["da" /* DEACTIVATED */]: 'deactivated hook', - ["ec" /* ERROR_CAPTURED */]: 'errorCaptured hook', - ["rtc" /* RENDER_TRACKED */]: 'renderTracked hook', - ["rtg" /* RENDER_TRIGGERED */]: 'renderTriggered hook', - [0 /* SETUP_FUNCTION */]: 'setup function', - [1 /* RENDER_FUNCTION */]: 'render function', - [2 /* WATCH_GETTER */]: 'watcher getter', - [3 /* WATCH_CALLBACK */]: 'watcher callback', - [4 /* WATCH_CLEANUP */]: 'watcher cleanup function', - [5 /* NATIVE_EVENT_HANDLER */]: 'native event handler', - [6 /* COMPONENT_EVENT_HANDLER */]: 'component event handler', - [7 /* VNODE_HOOK */]: 'vnode hook', - [8 /* DIRECTIVE_HOOK */]: 'directive hook', - [9 /* TRANSITION_HOOK */]: 'transition hook', - [10 /* APP_ERROR_HANDLER */]: 'app errorHandler', - [11 /* APP_WARN_HANDLER */]: 'app warnHandler', - [12 /* FUNCTION_REF */]: 'ref function', - [13 /* ASYNC_COMPONENT_LOADER */]: 'async component loader', - [14 /* SCHEDULER */]: 'scheduler flush. This is likely a Vue internals bug. ' + - 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next' -}; -function callWithErrorHandling(fn, instance, type, args) { - let res; - try { - res = args ? fn(...args) : fn(); - } - catch (err) { - handleError(err, instance, type); - } - return res; -} -function callWithAsyncErrorHandling(fn, instance, type, args) { - if (isFunction(fn)) { - const res = callWithErrorHandling(fn, instance, type, args); - if (res && isPromise(res)) { - res.catch(err => { - handleError(err, instance, type); - }); +/** + * mark the current rendering instance for asset resolution (e.g. + * resolveComponent, resolveDirective) during render + */ +let currentRenderingInstance = null; +let currentScopeId = null; + +function markAttrsAccessed() { +} + +function provide(key, value) { + if (!currentInstance) { + if ((process.env.NODE_ENV !== 'production')) { + warn$1(`provide() can only be used inside setup().`); } - return res; - } - const values = []; - for (let i = 0; i < fn.length; i++) { - values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); } - return values; -} -function handleError(err, instance, type, throwInDev = true) { - const contextVNode = instance ? instance.vnode : null; - if (instance) { - let cur = instance.parent; - // the exposed instance is the render proxy to keep it consistent with 2.x - const exposedInstance = instance.proxy; - // in production the hook receives only the error code - const errorInfo = (process.env.NODE_ENV !== 'production') ? ErrorTypeStrings[type] || type : type; // fixed by xxxxxxx - while (cur) { - const errorCapturedHooks = cur.ec; - if (errorCapturedHooks) { - for (let i = 0; i < errorCapturedHooks.length; i++) { - if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) { - return; - } - } - } - cur = cur.parent; - } - // app-level handling - const appErrorHandler = instance.appContext.config.errorHandler; - if (appErrorHandler) { - callWithErrorHandling(appErrorHandler, null, 10 /* APP_ERROR_HANDLER */, [err, exposedInstance, errorInfo]); - return; + else { + let provides = currentInstance.provides; + // by default an instance inherits its parent's provides object + // but when it needs to provide values of its own, it creates its + // own provides object using parent provides object as prototype. + // this way in `inject` we can simply look up injections from direct + // parent and let the prototype chain do the work. + const parentProvides = currentInstance.parent && currentInstance.parent.provides; + if (parentProvides === provides) { + provides = currentInstance.provides = Object.create(parentProvides); } + // TS doesn't allow symbol as index type + provides[key] = value; } - logError(err, type, contextVNode, throwInDev); } -// fixed by xxxxxx -function logError(err, type, contextVNode, throwInDev = true) { - if ((process.env.NODE_ENV !== 'production')) { - const info = ErrorTypeStrings[type] || type; // fixed by xxxxxx - if (contextVNode) { - pushWarningContext(contextVNode); - } - warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`); - if (contextVNode) { - popWarningContext(); +function inject(key, defaultValue, treatDefaultAsFactory = false) { + // fallback to `currentRenderingInstance` so that this can be called in + // a functional component + const instance = currentInstance || currentRenderingInstance; + if (instance) { + // #2400 + // to support `app.use` plugins, + // fallback to appContext's `provides` if the intance is at root + const provides = instance.parent == null + ? instance.vnode.appContext && instance.vnode.appContext.provides + : instance.parent.provides; + if (provides && key in provides) { + // TS doesn't allow symbol as index type + return provides[key]; } - // crash in dev by default so it's more noticeable - if (throwInDev) { - throw err; + else if (arguments.length > 1) { + return treatDefaultAsFactory && isFunction(defaultValue) + ? defaultValue.call(instance.proxy) + : defaultValue; } - else { - console.error(err); + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`injection "${String(key)}" not found.`); } } - else { - // recover in prod to reduce the impact on end-user - console.error(err); + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`inject() can only be used inside setup() or functional components.`); } } -let isFlushing = false; -let isFlushPending = false; -// fixed by xxxxxx -const queue = []; -let flushIndex = 0; -const pendingPreFlushCbs = []; -let activePreFlushCbs = null; -let preFlushIndex = 0; -const pendingPostFlushCbs = []; -let activePostFlushCbs = null; -let postFlushIndex = 0; -const resolvedPromise = Promise.resolve(); -let currentFlushPromise = null; -let currentPreFlushParentJob = null; -const RECURSION_LIMIT = 100; -function nextTick(fn) { - const p = currentFlushPromise || resolvedPromise; - return fn ? p.then(this ? fn.bind(this) : fn) : p; +// implementation, close to no-op +function defineComponent(options) { + return isFunction(options) ? { setup: options, name: options.name } : options; +} + +const isKeepAlive = (vnode) => vnode.type.__isKeepAlive; +function onActivated(hook, target) { + registerKeepAliveHook(hook, "a" /* ACTIVATED */, target); } -// #2768 -// Use binary-search to find a suitable position in the queue, -// so that the queue maintains the increasing order of job's id, -// which can prevent the job from being skipped and also can avoid repeated patching. -function findInsertionIndex(job) { - // the start index should be `flushIndex + 1` - let start = flushIndex + 1; - let end = queue.length; - const jobId = getId(job); - while (start < end) { - const middle = (start + end) >>> 1; - const middleJobId = getId(queue[middle]); - middleJobId < jobId ? (start = middle + 1) : (end = middle); +function onDeactivated(hook, target) { + registerKeepAliveHook(hook, "da" /* DEACTIVATED */, target); +} +function registerKeepAliveHook(hook, type, target = currentInstance) { + // cache the deactivate branch check wrapper for injected hooks so the same + // hook can be properly deduped by the scheduler. "__wdc" stands for "with + // deactivation check". + const wrappedHook = hook.__wdc || + (hook.__wdc = () => { + // only fire the hook if the target instance is NOT in a deactivated branch. + let current = target; + while (current) { + if (current.isDeactivated) { + return; + } + current = current.parent; + } + hook(); + }); + injectHook(type, wrappedHook, target); + // In addition to registering it on the target instance, we walk up the parent + // chain and register it on all ancestor instances that are keep-alive roots. + // This avoids the need to walk the entire component tree when invoking these + // hooks, and more importantly, avoids the need to track child components in + // arrays. + if (target) { + let current = target.parent; + while (current && current.parent) { + if (isKeepAlive(current.parent.vnode)) { + injectToKeepAliveRoot(wrappedHook, type, target, current); + } + current = current.parent; + } } - return start; } -function queueJob(job) { - // the dedupe search uses the startIndex argument of Array.includes() - // by default the search index includes the current job that is being run - // so it cannot recursively trigger itself again. - // if the job is a watch() callback, the search will start with a +1 index to - // allow it recursively trigger itself - it is the user's responsibility to - // ensure it doesn't end up in an infinite loop. - if ((!queue.length || - !queue.includes(job, isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex)) && - job !== currentPreFlushParentJob) { - const pos = findInsertionIndex(job); - if (pos > -1) { - queue.splice(pos, 0, job); +function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { + // injectHook wraps the original for error handling, so make sure to remove + // the wrapped version. + const injected = injectHook(type, hook, keepAliveRoot, true /* prepend */); + onUnmounted(() => { + remove(keepAliveRoot[type], injected); + }, target); +} + +function injectHook(type, hook, target = currentInstance, prepend = false) { + if (target) { + const hooks = target[type] || (target[type] = []); + // cache the error handling wrapper for injected hooks so the same hook + // can be properly deduped by the scheduler. "__weh" stands for "with error + // handling". + const wrappedHook = hook.__weh || + (hook.__weh = (...args) => { + if (target.isUnmounted) { + return; + } + // disable tracking inside all lifecycle hooks + // since they can potentially be called inside effects. + pauseTracking(); + // Set currentInstance during hook invocation. + // This assumes the hook does not synchronously trigger other hooks, which + // can only be false when the user does something really funky. + setCurrentInstance(target); + const res = callWithAsyncErrorHandling(hook, target, type, args); + unsetCurrentInstance(); + resetTracking(); + return res; + }); + if (prepend) { + hooks.unshift(wrappedHook); } else { - queue.push(job); + hooks.push(wrappedHook); } - queueFlush(); + return wrappedHook; } -} -function queueFlush() { - if (!isFlushing && !isFlushPending) { - isFlushPending = true; - currentFlushPromise = resolvedPromise.then(flushJobs); + else if ((process.env.NODE_ENV !== 'production')) { + const apiName = toHandlerKey(ErrorTypeStrings[type].replace(/ hook$/, '')); + warn$1(`${apiName} is called when there is no active component instance to be ` + + `associated with. ` + + `Lifecycle injection APIs can only be used during execution of setup().` + + (``)); } } -function queueCb(cb, activeQueue, pendingQueue, index) { - if (!isArray(cb)) { - if (!activeQueue || - !activeQueue.includes(cb, cb.allowRecurse ? index + 1 : index)) { - pendingQueue.push(cb); +const createHook = (lifecycle) => (hook, target = currentInstance) => +// post-create lifecycle registrations are noops during SSR (except for serverPrefetch) +(!isInSSRComponentSetup || lifecycle === "sp" /* SERVER_PREFETCH */) && + injectHook(lifecycle, hook, target); +const onBeforeMount = createHook("bm" /* BEFORE_MOUNT */); +const onMounted = createHook("m" /* MOUNTED */); +const onBeforeUpdate = createHook("bu" /* BEFORE_UPDATE */); +const onUpdated = createHook("u" /* UPDATED */); +const onBeforeUnmount = createHook("bum" /* BEFORE_UNMOUNT */); +const onUnmounted = createHook("um" /* UNMOUNTED */); +const onServerPrefetch = createHook("sp" /* SERVER_PREFETCH */); +const onRenderTriggered = createHook("rtg" /* RENDER_TRIGGERED */); +const onRenderTracked = createHook("rtc" /* RENDER_TRACKED */); +function onErrorCaptured(hook, target = currentInstance) { + injectHook("ec" /* ERROR_CAPTURED */, hook, target); +} + +function createDuplicateChecker() { + const cache = Object.create(null); + return (type, key) => { + if (cache[key]) { + warn$1(`${type} property "${key}" is already defined in ${cache[key]}.`); } - } - else { - // if cb is an array, it is a component lifecycle hook which can only be - // triggered by a job, which is already deduped in the main queue, so - // we can skip duplicate check here to improve perf - pendingQueue.push(...cb); - } - queueFlush(); -} -function queuePreFlushCb(cb) { - queueCb(cb, activePreFlushCbs, pendingPreFlushCbs, preFlushIndex); -} -function queuePostFlushCb(cb) { - queueCb(cb, activePostFlushCbs, pendingPostFlushCbs, postFlushIndex); + else { + cache[key] = type; + } + }; } -function flushPreFlushCbs(seen, parentJob = null) { - if (pendingPreFlushCbs.length) { - currentPreFlushParentJob = parentJob; - activePreFlushCbs = [...new Set(pendingPreFlushCbs)]; - pendingPreFlushCbs.length = 0; - if ((process.env.NODE_ENV !== 'production')) { - seen = seen || new Map(); +let shouldCacheAccess = true; +function applyOptions$1(instance) { + const options = resolveMergedOptions(instance); + const publicThis = instance.proxy; + const ctx = instance.ctx; + // do not cache property access on public proxy during state initialization + shouldCacheAccess = false; + // call beforeCreate first before accessing other options since + // the hook may mutate resolved options (#2791) + if (options.beforeCreate) { + callHook(options.beforeCreate, instance, "bc" /* BEFORE_CREATE */); + } + const { + // state + data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions, + // lifecycle + created, beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy, beforeUnmount, destroyed, unmounted, render, renderTracked, renderTriggered, errorCaptured, serverPrefetch, + // public API + expose, inheritAttrs, + // assets + components, directives, filters } = options; + const checkDuplicateProperties = (process.env.NODE_ENV !== 'production') ? createDuplicateChecker() : null; + if ((process.env.NODE_ENV !== 'production')) { + const [propsOptions] = instance.propsOptions; + if (propsOptions) { + for (const key in propsOptions) { + checkDuplicateProperties("Props" /* PROPS */, key); + } } - for (preFlushIndex = 0; preFlushIndex < activePreFlushCbs.length; preFlushIndex++) { - if ((process.env.NODE_ENV !== 'production')) { - checkRecursiveUpdates(seen, activePreFlushCbs[preFlushIndex]); + } + // options initialization order (to be consistent with Vue 2): + // - props (already done outside of this function) + // - inject + // - methods + // - data (deferred since it relies on `this` access) + // - computed + // - watch (deferred since it relies on `this` access) + // fixed by xxxxxx + if (!__VUE_CREATED_DEFERRED__ && injectOptions) { + resolveInjections(injectOptions, ctx, checkDuplicateProperties, instance.appContext.config.unwrapInjectedRef); + } + if (methods) { + for (const key in methods) { + const methodHandler = methods[key]; + if (isFunction(methodHandler)) { + // In dev mode, we use the `createRenderContext` function to define + // methods to the proxy target, and those are read-only but + // reconfigurable, so it needs to be redefined here + if ((process.env.NODE_ENV !== 'production')) { + Object.defineProperty(ctx, key, { + value: methodHandler.bind(publicThis), + configurable: true, + enumerable: true, + writable: true + }); + } + else { + ctx[key] = methodHandler.bind(publicThis); + } + if ((process.env.NODE_ENV !== 'production')) { + checkDuplicateProperties("Methods" /* METHODS */, key); + } + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`Method "${key}" has type "${typeof methodHandler}" in the component definition. ` + + `Did you reference the function correctly?`); } - activePreFlushCbs[preFlushIndex](); } - activePreFlushCbs = null; - preFlushIndex = 0; - currentPreFlushParentJob = null; - // recursively flush until it drains - flushPreFlushCbs(seen, parentJob); } -} -function flushPostFlushCbs(seen) { - if (pendingPostFlushCbs.length) { - const deduped = [...new Set(pendingPostFlushCbs)]; - pendingPostFlushCbs.length = 0; - // #1947 already has active queue, nested flushPostFlushCbs call - if (activePostFlushCbs) { - activePostFlushCbs.push(...deduped); - return; + if (dataOptions) { + if ((process.env.NODE_ENV !== 'production') && !isFunction(dataOptions)) { + warn$1(`The data option must be a function. ` + + `Plain object usage is no longer supported.`); } - activePostFlushCbs = deduped; - if ((process.env.NODE_ENV !== 'production')) { - seen = seen || new Map(); + const data = dataOptions.call(publicThis, publicThis); + if ((process.env.NODE_ENV !== 'production') && isPromise(data)) { + warn$1(`data() returned a Promise - note data() cannot be async; If you ` + + `intend to perform data fetching before component renders, use ` + + `async setup() + .`); } - activePostFlushCbs.sort((a, b) => getId(a) - getId(b)); - for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + if (!isObject(data)) { + (process.env.NODE_ENV !== 'production') && warn$1(`data() should return an object.`); + } + else { + instance.data = reactive(data); if ((process.env.NODE_ENV !== 'production')) { - checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex]); + for (const key in data) { + checkDuplicateProperties("Data" /* DATA */, key); + // expose data on ctx during dev + if (key[0] !== '$' && key[0] !== '_') { + Object.defineProperty(ctx, key, { + configurable: true, + enumerable: true, + get: () => data[key], + set: NOOP + }); + } + } } - activePostFlushCbs[postFlushIndex](); } - activePostFlushCbs = null; - postFlushIndex = 0; - } -} -const getId = (job) => job.id == null ? Infinity : job.id; -function flushJobs(seen) { - isFlushPending = false; - isFlushing = true; - if ((process.env.NODE_ENV !== 'production')) { - seen = seen || new Map(); } - flushPreFlushCbs(seen); - // Sort queue before flush. - // This ensures that: - // 1. Components are updated from parent to child. (because parent is always - // created before the child so its render effect will have smaller - // priority number) - // 2. If a component is unmounted during a parent component's update, - // its update can be skipped. - queue.sort((a, b) => getId(a) - getId(b)); - try { - for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { - const job = queue[flushIndex]; - if (job) { - if ((process.env.NODE_ENV !== 'production')) { - checkRecursiveUpdates(seen, job); - } - callWithErrorHandling(job, null, 14 /* SCHEDULER */); + // state initialization complete at this point - start caching access + shouldCacheAccess = true; + if (computedOptions) { + for (const key in computedOptions) { + const opt = computedOptions[key]; + const get = isFunction(opt) + ? opt.bind(publicThis, publicThis) + : isFunction(opt.get) + ? opt.get.bind(publicThis, publicThis) + : NOOP; + if ((process.env.NODE_ENV !== 'production') && get === NOOP) { + warn$1(`Computed property "${key}" has no getter.`); + } + const set = !isFunction(opt) && isFunction(opt.set) + ? opt.set.bind(publicThis) + : (process.env.NODE_ENV !== 'production') + ? () => { + warn$1(`Write operation failed: computed property "${key}" is readonly.`); + } + : NOOP; + const c = computed({ + get, + set + }); + Object.defineProperty(ctx, key, { + enumerable: true, + configurable: true, + get: () => c.value, + set: v => (c.value = v) + }); + if ((process.env.NODE_ENV !== 'production')) { + checkDuplicateProperties("Computed" /* COMPUTED */, key); } } } - finally { - flushIndex = 0; - queue.length = 0; - flushPostFlushCbs(seen); - isFlushing = false; - currentFlushPromise = null; - // some postFlushCb queued jobs! - // keep flushing until it drains. - if (queue.length || pendingPostFlushCbs.length) { - flushJobs(seen); + if (watchOptions) { + for (const key in watchOptions) { + createWatcher(watchOptions[key], ctx, publicThis, key); } } -} -function checkRecursiveUpdates(seen, fn) { - if (!seen.has(fn)) { - seen.set(fn, 1); + // fixed by xxxxxx + if (!__VUE_CREATED_DEFERRED__) { + if (provideOptions) { + const provides = isFunction(provideOptions) + ? provideOptions.call(publicThis) + : provideOptions; + Reflect.ownKeys(provides).forEach(key => { + provide(key, provides[key]); + }); + } + } + // fixed by xxxxxx + if (__VUE_CREATED_DEFERRED__) { + ctx.$callCreatedHook = function (name) { + if (created) { + return callHook(created, instance, "c" /* CREATED */); + } + }; } else { - const count = seen.get(fn); - if (count > RECURSION_LIMIT) { - throw new Error(`Maximum recursive updates exceeded. ` + - `This means you have a reactive effect that is mutating its own ` + - `dependencies and thus recursively triggering itself. Possible sources ` + - `include component template, render function, updated hook or ` + - `watcher source function.`); + if (created) { + callHook(created, instance, "c" /* CREATED */); + } + } + function registerLifecycleHook(register, hook) { + if (isArray(hook)) { + hook.forEach(_hook => register(_hook.bind(publicThis))); + } + else if (hook) { + register(hook.bind(publicThis)); + } + } + registerLifecycleHook(onBeforeMount, beforeMount); + registerLifecycleHook(onMounted, mounted); + registerLifecycleHook(onBeforeUpdate, beforeUpdate); + registerLifecycleHook(onUpdated, updated); + registerLifecycleHook(onActivated, activated); + registerLifecycleHook(onDeactivated, deactivated); + registerLifecycleHook(onErrorCaptured, errorCaptured); + registerLifecycleHook(onRenderTracked, renderTracked); + registerLifecycleHook(onRenderTriggered, renderTriggered); + registerLifecycleHook(onBeforeUnmount, beforeUnmount); + registerLifecycleHook(onUnmounted, unmounted); + registerLifecycleHook(onServerPrefetch, serverPrefetch); + if (isArray(expose)) { + if (expose.length) { + const exposed = instance.exposed || (instance.exposed = {}); + expose.forEach(key => { + Object.defineProperty(exposed, key, { + get: () => publicThis[key], + set: val => (publicThis[key] = val) + }); + }); } - else { - seen.set(fn, count + 1); + else if (!instance.exposed) { + instance.exposed = {}; } } -} - -function emit(instance, event, ...rawArgs) { - const props = instance.vnode.props || EMPTY_OBJ; - if ((process.env.NODE_ENV !== 'production')) { - const { emitsOptions, propsOptions: [propsOptions] } = instance; - if (emitsOptions) { - if (!(event in emitsOptions)) { - if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { - warn(`Component emitted event "${event}" but it is neither declared in ` + - `the emits option nor as an "${toHandlerKey(event)}" prop.`); - } + // options that are handled when creating the instance but also need to be + // applied from mixins + if (render && instance.render === NOOP) { + instance.render = render; + } + if (inheritAttrs != null) { + instance.inheritAttrs = inheritAttrs; + } + // asset options. + if (components) + instance.components = components; + if (directives) + instance.directives = directives; + // fixed by xxxxxx + if (instance.ctx.$onApplyOptions) { + instance.ctx.$onApplyOptions(options, instance, publicThis); + } +} +function resolveInjections(injectOptions, ctx, checkDuplicateProperties = NOOP, unwrapRef = false) { + if (isArray(injectOptions)) { + injectOptions = normalizeInject(injectOptions); + } + for (const key in injectOptions) { + const opt = injectOptions[key]; + let injected; + if (isObject(opt)) { + if ('default' in opt) { + injected = inject(opt.from || key, opt.default, true /* treat default function as factory */); } else { - const validator = emitsOptions[event]; - if (isFunction(validator)) { - const isValid = validator(...rawArgs); - if (!isValid) { - warn(`Invalid event arguments: event validation failed for event "${event}".`); - } + injected = inject(opt.from || key); + } + } + else { + injected = inject(opt); + } + if (isRef(injected)) { + // TODO remove the check in 3.3 + if (unwrapRef) { + Object.defineProperty(ctx, key, { + enumerable: true, + configurable: true, + get: () => injected.value, + set: v => (injected.value = v) + }); + } + else { + if ((process.env.NODE_ENV !== 'production')) { + warn$1(`injected property "${key}" is a ref and will be auto-unwrapped ` + + `and no longer needs \`.value\` in the next minor release. ` + + `To opt-in to the new behavior now, ` + + `set \`app.config.unwrapInjectedRef = true\` (this config is ` + + `temporary and will not be needed in the future.)`); } + ctx[key] = injected; } } - } - let args = rawArgs; - const isModelListener = event.startsWith('update:'); - // for v-model update:xxx events, apply modifiers on args - const modelArg = isModelListener && event.slice(7); - if (modelArg && modelArg in props) { - const modifiersKey = `${modelArg === 'modelValue' ? 'model' : modelArg}Modifiers`; - const { number, trim } = props[modifiersKey] || EMPTY_OBJ; - if (trim) { - args = rawArgs.map(a => a.trim()); + else { + ctx[key] = injected; } - else if (number) { - args = rawArgs.map(toNumber); + if ((process.env.NODE_ENV !== 'production')) { + checkDuplicateProperties("Inject" /* INJECT */, key); } } - if ((process.env.NODE_ENV !== 'production') || false) ; - if ((process.env.NODE_ENV !== 'production')) { - const lowerCaseEvent = event.toLowerCase(); - if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) { - warn(`Event "${lowerCaseEvent}" is emitted in component ` + - `${formatComponentName(instance, instance.type)} but the handler is registered for "${event}". ` + - `Note that HTML attributes are case-insensitive and you cannot use ` + - `v-on to listen to camelCase events when using in-DOM templates. ` + - `You should probably use "${hyphenate(event)}" instead of "${event}".`); +} +function callHook(hook, instance, type) { + callWithAsyncErrorHandling(isArray(hook) + ? hook.map(h => h.bind(instance.proxy)) + : hook.bind(instance.proxy), instance, type); +} +function createWatcher(raw, ctx, publicThis, key) { + const getter = key.includes('.') + ? createPathGetter(publicThis, key) + : () => publicThis[key]; + if (isString(raw)) { + const handler = ctx[raw]; + if (isFunction(handler)) { + watch(getter, handler); + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`Invalid watch handler specified by key "${raw}"`, handler); } } - // convert handler name to camelCase. See issue #2249 - let handlerName = toHandlerKey(camelize(event)); - let handler = props[handlerName]; - // for v-model update:xxx events, also trigger kebab-case equivalent - // for props passed via kebab-case - if (!handler && isModelListener) { - handlerName = toHandlerKey(hyphenate(event)); - handler = props[handlerName]; - } - if (handler) { - callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args); + else if (isFunction(raw)) { + watch(getter, raw.bind(publicThis)); } - const onceHandler = props[handlerName + `Once`]; - if (onceHandler) { - if (!instance.emitted) { - (instance.emitted = {})[handlerName] = true; + else if (isObject(raw)) { + if (isArray(raw)) { + raw.forEach(r => createWatcher(r, ctx, publicThis, key)); } - else if (instance.emitted[handlerName]) { - return; + else { + const handler = isFunction(raw.handler) + ? raw.handler.bind(publicThis) + : ctx[raw.handler]; + if (isFunction(handler)) { + watch(getter, handler, raw); + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`Invalid watch handler specified by key "${raw.handler}"`, handler); + } } - callWithAsyncErrorHandling(onceHandler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args); + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`Invalid watch option: "${key}"`, raw); } } -function normalizeEmitsOptions(comp, appContext, asMixin = false) { - if (!appContext.deopt && comp.__emits !== undefined) { - return comp.__emits; +/** + * Resolve merged options and cache it on the component. + * This is done only once per-component since the merging does not involve + * instances. + */ +function resolveMergedOptions(instance) { + const base = instance.type; + const { mixins, extends: extendsOptions } = base; + const { mixins: globalMixins, optionsCache: cache, config: { optionMergeStrategies } } = instance.appContext; + const cached = cache.get(base); + let resolved; + if (cached) { + resolved = cached; + } + else if (!globalMixins.length && !mixins && !extendsOptions) { + { + resolved = base; + } } - const raw = comp.emits; - let normalized = {}; - // apply mixin/extends props - let hasExtends = false; - if (__VUE_OPTIONS_API__ && !isFunction(comp)) { - const extendEmits = (raw) => { - const normalizedFromExtend = normalizeEmitsOptions(raw, appContext, true); - if (normalizedFromExtend) { - hasExtends = true; - extend(normalized, normalizedFromExtend); - } - }; - if (!asMixin && appContext.mixins.length) { - appContext.mixins.forEach(extendEmits); + else { + resolved = {}; + if (globalMixins.length) { + globalMixins.forEach(m => mergeOptions(resolved, m, optionMergeStrategies, true)); } - if (comp.extends) { - extendEmits(comp.extends); + mergeOptions(resolved, base, optionMergeStrategies); + } + cache.set(base, resolved); + return resolved; +} +function mergeOptions(to, from, strats, asMixin = false) { + const { mixins, extends: extendsOptions } = from; + if (extendsOptions) { + mergeOptions(to, extendsOptions, strats, true); + } + if (mixins) { + mixins.forEach((m) => mergeOptions(to, m, strats, true)); + } + for (const key in from) { + if (asMixin && key === 'expose') { + (process.env.NODE_ENV !== 'production') && + warn$1(`"expose" option is ignored when declared in mixins or extends. ` + + `It should only be declared in the base component itself.`); } - if (comp.mixins) { - comp.mixins.forEach(extendEmits); + else { + const strat = internalOptionMergeStrats[key] || (strats && strats[key]); + to[key] = strat ? strat(to[key], from[key]) : from[key]; } } - if (!raw && !hasExtends) { - return (comp.__emits = null); + return to; +} +const internalOptionMergeStrats = { + data: mergeDataFn, + props: mergeObjectOptions, + emits: mergeObjectOptions, + // objects + methods: mergeObjectOptions, + computed: mergeObjectOptions, + // lifecycle + beforeCreate: mergeAsArray$1, + created: mergeAsArray$1, + beforeMount: mergeAsArray$1, + mounted: mergeAsArray$1, + beforeUpdate: mergeAsArray$1, + updated: mergeAsArray$1, + beforeDestroy: mergeAsArray$1, + beforeUnmount: mergeAsArray$1, + destroyed: mergeAsArray$1, + unmounted: mergeAsArray$1, + activated: mergeAsArray$1, + deactivated: mergeAsArray$1, + errorCaptured: mergeAsArray$1, + serverPrefetch: mergeAsArray$1, + // assets + components: mergeObjectOptions, + directives: mergeObjectOptions, + // watch + watch: mergeWatchOptions, + // provide / inject + provide: mergeDataFn, + inject: mergeInject +}; +function mergeDataFn(to, from) { + if (!from) { + return to; } - if (isArray(raw)) { - raw.forEach(key => (normalized[key] = null)); + if (!to) { + return from; } - else { - extend(normalized, raw); + return function mergedDataFn() { + return (extend)(isFunction(to) ? to.call(this, this) : to, isFunction(from) ? from.call(this, this) : from); + }; +} +function mergeInject(to, from) { + return mergeObjectOptions(normalizeInject(to), normalizeInject(from)); +} +function normalizeInject(raw) { + if (isArray(raw)) { + const res = {}; + for (let i = 0; i < raw.length; i++) { + res[raw[i]] = raw[i]; + } + return res; } - return (comp.__emits = normalized); + return raw; } -// Check if an incoming prop key is a declared emit event listener. -// e.g. With `emits: { click: null }`, props named `onClick` and `onclick` are -// both considered matched listeners. -function isEmitListener(options, key) { - if (!options || !isOn(key)) { - return false; +function mergeAsArray$1(to, from) { + return to ? [...new Set([].concat(to, from))] : from; +} +function mergeObjectOptions(to, from) { + return to ? extend(extend(Object.create(null), to), from) : from; +} +function mergeWatchOptions(to, from) { + if (!to) + return from; + if (!from) + return to; + const merged = extend(Object.create(null), to); + for (const key in from) { + merged[key] = mergeAsArray$1(to[key], from[key]); } - key = key.slice(2).replace(/Once$/, ''); - return (hasOwn(options, key[0].toLowerCase() + key.slice(1)) || - hasOwn(options, hyphenate(key)) || - hasOwn(options, key)); -} - -let isRenderingCompiledSlot = 0; -const setCompiledSlotRendering = (n) => (isRenderingCompiledSlot += n); - -/** - * mark the current rendering instance for asset resolution (e.g. - * resolveComponent, resolveDirective) during render - */ -let currentRenderingInstance = null; -let currentScopeId = null; - -function markAttrsAccessed() { + return merged; } function initProps(instance, rawProps, isStateful, // result of bitwise flag comparison @@ -1446,6 +1896,12 @@ isSSR = false) { def(attrs, '__vInternal', 1); instance.propsDefaults = Object.create(null); setFullProps(instance, rawProps, props, attrs); + // ensure all declared prop keys are present + for (const key in instance.propsOptions[0]) { + if (!(key in props)) { + props[key] = undefined; + } + } // validation if ((process.env.NODE_ENV !== 'production')) { validateProps(rawProps || {}, props, instance); @@ -1468,36 +1924,45 @@ isSSR = false) { } function setFullProps(instance, rawProps, props, attrs) { const [options, needCastKeys] = instance.propsOptions; + let hasAttrsChanged = false; + let rawCastValues; if (rawProps) { - for (const key in rawProps) { - const value = rawProps[key]; + for (let key in rawProps) { // key, ref are reserved and never passed down if (isReservedProp(key)) { continue; } + const value = rawProps[key]; // prop option names are camelized during normalization, so to support // kebab -> camel conversion here we need to camelize the key. let camelKey; if (options && hasOwn(options, (camelKey = camelize(key)))) { - props[camelKey] = value; + if (!needCastKeys || !needCastKeys.includes(camelKey)) { + props[camelKey] = value; + } + else { + (rawCastValues || (rawCastValues = {}))[camelKey] = value; + } } else if (!isEmitListener(instance.emitsOptions, key)) { - // Any non-declared (either as a prop or an emitted event) props are put - // into a separate `attrs` object for spreading. Make sure to preserve - // original key casing - attrs[key] = value; + if (value !== attrs[key]) { + attrs[key] = value; + hasAttrsChanged = true; + } } } } if (needCastKeys) { const rawCurrentProps = toRaw(props); + const castValues = rawCastValues || EMPTY_OBJ; for (let i = 0; i < needCastKeys.length; i++) { const key = needCastKeys[i]; - props[key] = resolvePropValue(options, rawCurrentProps, key, rawCurrentProps[key], instance); + props[key] = resolvePropValue(options, rawCurrentProps, key, castValues[key], instance, !hasOwn(castValues, key)); } } + return hasAttrsChanged; } -function resolvePropValue(options, props, key, value, instance) { +function resolvePropValue(options, props, key, value, instance, isAbsent) { const opt = options[key]; if (opt != null) { const hasDefault = hasOwn(opt, 'default'); @@ -1511,8 +1976,8 @@ function resolvePropValue(options, props, key, value, instance) { } else { setCurrentInstance(instance); - value = propsDefaults[key] = defaultValue(props); - setCurrentInstance(null); + value = propsDefaults[key] = defaultValue.call(null, props); + unsetCurrentInstance(); } } else { @@ -1521,7 +1986,7 @@ function resolvePropValue(options, props, key, value, instance) { } // boolean casting if (opt[0 /* shouldCast */]) { - if (!hasOwn(props, key) && !hasDefault) { + if (isAbsent && !hasDefault) { value = false; } else if (opt[1 /* shouldCastTrue */] && @@ -1533,8 +1998,10 @@ function resolvePropValue(options, props, key, value, instance) { return value; } function normalizePropsOptions(comp, appContext, asMixin = false) { - if (!appContext.deopt && comp.__props) { - return comp.__props; + const cache = appContext.propsCache; + const cached = cache.get(comp); + if (cached) { + return cached; } const raw = comp.props; const normalized = {}; @@ -1560,12 +2027,13 @@ function normalizePropsOptions(comp, appContext, asMixin = false) { } } if (!raw && !hasExtends) { - return (comp.__props = EMPTY_ARR); + cache.set(comp, EMPTY_ARR); + return EMPTY_ARR; } if (isArray(raw)) { for (let i = 0; i < raw.length; i++) { if ((process.env.NODE_ENV !== 'production') && !isString(raw[i])) { - warn(`props must be strings when using array syntax.`, raw[i]); + warn$1(`props must be strings when using array syntax.`, raw[i]); } const normalizedKey = camelize(raw[i]); if (validatePropName(normalizedKey)) { @@ -1575,7 +2043,7 @@ function normalizePropsOptions(comp, appContext, asMixin = false) { } else if (raw) { if ((process.env.NODE_ENV !== 'production') && !isObject(raw)) { - warn(`invalid props options`, raw); + warn$1(`invalid props options`, raw); } for (const key in raw) { const normalizedKey = camelize(key); @@ -1597,14 +2065,16 @@ function normalizePropsOptions(comp, appContext, asMixin = false) { } } } - return (comp.__props = [normalized, needCastKeys]); + const res = [normalized, needCastKeys]; + cache.set(comp, res); + return res; } function validatePropName(key) { if (key[0] !== '$') { return true; } else if ((process.env.NODE_ENV !== 'production')) { - warn(`Invalid prop name: "${key}" is a reserved property.`); + warn$1(`Invalid prop name: "${key}" is a reserved property.`); } return false; } @@ -1612,18 +2082,14 @@ function validatePropName(key) { // so that it works across vms / iframes. function getType(ctor) { const match = ctor && ctor.toString().match(/^\s*function (\w+)/); - return match ? match[1] : ''; + return match ? match[1] : ctor === null ? 'null' : ''; } function isSameType(a, b) { return getType(a) === getType(b); } function getTypeIndex(type, expectedTypes) { if (isArray(expectedTypes)) { - for (let i = 0, len = expectedTypes.length; i < len; i++) { - if (isSameType(expectedTypes[i], type)) { - return i; - } - } + return expectedTypes.findIndex(t => isSameType(t, type)); } else if (isFunction(expectedTypes)) { return isSameType(expectedTypes, type) ? 0 : -1; @@ -1650,7 +2116,7 @@ function validateProp(name, value, prop, isAbsent) { const { type, required, validator } = prop; // required! if (required && isAbsent) { - warn('Missing required prop: "' + name + '"'); + warn$1('Missing required prop: "' + name + '"'); return; } // missing but optional @@ -1669,13 +2135,13 @@ function validateProp(name, value, prop, isAbsent) { isValid = valid; } if (!isValid) { - warn(getInvalidTypeMessage(name, value, expectedTypes)); + warn$1(getInvalidTypeMessage(name, value, expectedTypes)); return; } } // custom validator if (validator && !validator(value)) { - warn('Invalid prop: custom validator check failed for prop "' + name + '".'); + warn$1('Invalid prop: custom validator check failed for prop "' + name + '".'); } } const isSimpleType = /*#__PURE__*/ makeMap('String,Number,Boolean,Function,Symbol,BigInt'); @@ -1699,6 +2165,9 @@ function assertType(value, type) { else if (expectedType === 'Array') { valid = isArray(value); } + else if (expectedType === 'null') { + valid = value === null; + } else { valid = value instanceof type; } @@ -1712,7 +2181,7 @@ function assertType(value, type) { */ function getInvalidTypeMessage(name, value, expectedTypes) { let message = `Invalid prop: type check failed for prop "${name}".` + - ` Expected ${expectedTypes.map(capitalize).join(', ')}`; + ` Expected ${expectedTypes.map(capitalize).join(' | ')}`; const expectedType = expectedTypes[0]; const receivedType = toRawType(value); const expectedValue = styleValue(value, expectedType); @@ -1758,1884 +2227,1804 @@ function isBoolean(...args) { return args.some(elem => elem.toLowerCase() === 'boolean'); } -function injectHook(type, hook, target = currentInstance, prepend = false) { - if (target) { - const hooks = target[type] || (target[type] = []); - // cache the error handling wrapper for injected hooks so the same hook - // can be properly deduped by the scheduler. "__weh" stands for "with error - // handling". - const wrappedHook = hook.__weh || - (hook.__weh = (...args) => { - if (target.isUnmounted) { - return; - } - // disable tracking inside all lifecycle hooks - // since they can potentially be called inside effects. - pauseTracking(); - // Set currentInstance during hook invocation. - // This assumes the hook does not synchronously trigger other hooks, which - // can only be false when the user does something really funky. - setCurrentInstance(target); - const res = callWithAsyncErrorHandling(hook, target, type, args); - setCurrentInstance(null); - resetTracking(); - return res; - }); - if (prepend) { - hooks.unshift(wrappedHook); - } - else { - hooks.push(wrappedHook); - } - return wrappedHook; +/** +Runtime helper for applying directives to a vnode. Example usage: + +const comp = resolveComponent('comp') +const foo = resolveDirective('foo') +const bar = resolveDirective('bar') + +return withDirectives(h(comp), [ + [foo, this.x], + [bar, this.y] +]) +*/ +const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text'); +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1('Do not use built-in directive ids as custom directive id: ' + name); } - else if ((process.env.NODE_ENV !== 'production')) { - const apiName = toHandlerKey(ErrorTypeStrings[type].replace(/ hook$/, '')); - warn(`${apiName} is called when there is no active component instance to be ` + - `associated with. ` + - `Lifecycle injection APIs can only be used during execution of setup().` + - (``)); +} +/** + * Adds directives to a VNode. + */ +function withDirectives(vnode, directives) { + { + (process.env.NODE_ENV !== 'production') && warn$1(`withDirectives can only be used inside render functions.`); + return vnode; } +} + +function createAppContext() { + return { + app: null, + config: { + isNativeTag: NO, + performance: false, + globalProperties: {}, + optionMergeStrategies: {}, + errorHandler: undefined, + warnHandler: undefined, + compilerOptions: {} + }, + mixins: [], + components: {}, + directives: {}, + provides: Object.create(null), + optionsCache: new WeakMap(), + propsCache: new WeakMap(), + emitsCache: new WeakMap() + }; } -const createHook = (lifecycle) => (hook, target = currentInstance) => -// post-create lifecycle registrations are noops during SSR -!isInSSRComponentSetup && injectHook(lifecycle, hook, target); -const onBeforeMount = createHook("bm" /* BEFORE_MOUNT */); -const onMounted = createHook("m" /* MOUNTED */); -const onBeforeUpdate = createHook("bu" /* BEFORE_UPDATE */); -const onUpdated = createHook("u" /* UPDATED */); -const onBeforeUnmount = createHook("bum" /* BEFORE_UNMOUNT */); -const onUnmounted = createHook("um" /* UNMOUNTED */); -const onRenderTriggered = createHook("rtg" /* RENDER_TRIGGERED */); -const onRenderTracked = createHook("rtc" /* RENDER_TRACKED */); -const onErrorCaptured = (hook, target = currentInstance) => { - injectHook("ec" /* ERROR_CAPTURED */, hook, target); -}; +let uid = 0; +// fixed by xxxxxx +function createAppAPI(render, hydrate) { + return function createApp(rootComponent, rootProps = null) { + if (rootProps != null && !isObject(rootProps)) { + (process.env.NODE_ENV !== 'production') && warn$1(`root props passed to app.mount() must be an object.`); + rootProps = null; + } + const context = createAppContext(); + const installedPlugins = new Set(); + // fixed by xxxxxx + // let isMounted = false + const app = (context.app = { + _uid: uid++, + _component: rootComponent, + _props: rootProps, + _container: null, + _context: context, + _instance: null, + version, + get config() { + return context.config; + }, + set config(v) { + if ((process.env.NODE_ENV !== 'production')) { + warn$1(`app.config cannot be replaced. Modify individual options instead.`); + } + }, + use(plugin, ...options) { + if (installedPlugins.has(plugin)) { + (process.env.NODE_ENV !== 'production') && warn$1(`Plugin has already been applied to target app.`); + } + else if (plugin && isFunction(plugin.install)) { + installedPlugins.add(plugin); + plugin.install(app, ...options); + } + else if (isFunction(plugin)) { + installedPlugins.add(plugin); + plugin(app, ...options); + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`A plugin must either be a function or an object with an "install" ` + + `function.`); + } + return app; + }, + mixin(mixin) { + if (__VUE_OPTIONS_API__) { + if (!context.mixins.includes(mixin)) { + context.mixins.push(mixin); + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1('Mixin has already been applied to target app' + + (mixin.name ? `: ${mixin.name}` : '')); + } + } + else if ((process.env.NODE_ENV !== 'production')) { + warn$1('Mixins are only available in builds supporting Options API'); + } + return app; + }, + component(name, component) { + if ((process.env.NODE_ENV !== 'production')) { + validateComponentName(name, context.config); + } + if (!component) { + return context.components[name]; + } + if ((process.env.NODE_ENV !== 'production') && context.components[name]) { + warn$1(`Component "${name}" has already been registered in target app.`); + } + context.components[name] = component; + return app; + }, + directive(name, directive) { + if ((process.env.NODE_ENV !== 'production')) { + validateDirectiveName(name); + } + if (!directive) { + return context.directives[name]; + } + if ((process.env.NODE_ENV !== 'production') && context.directives[name]) { + warn$1(`Directive "${name}" has already been registered in target app.`); + } + context.directives[name] = directive; + return app; + }, + // fixed by xxxxxx + mount() { }, + // fixed by xxxxxx + unmount() { }, + provide(key, value) { + if ((process.env.NODE_ENV !== 'production') && key in context.provides) { + warn$1(`App already provides property with key "${String(key)}". ` + + `It will be overwritten with the new value.`); + } + // TypeScript doesn't allow symbols as index type + // https://github.com/Microsoft/TypeScript/issues/24587 + context.provides[key] = value; + return app; + } + }); + // fixed by xxxxxx + // if (false) { + // installAppCompatProperties(app, context, render) + // } + return app; + }; +} -// Simple effect. -function watchEffect(effect, options) { - return doWatch(effect, null, options); +const queuePostRenderEffect = queuePostFlushCb; + +const isTeleport = (type) => type.__isTeleport; + +const COMPONENTS = 'components'; +const DIRECTIVES = 'directives'; +const NULL_DYNAMIC_COMPONENT = Symbol(); +/** + * @private + */ +function resolveDirective(name) { + return resolveAsset(DIRECTIVES, name); } -// initial value for watchers to trigger on undefined initial values -const INITIAL_WATCHER_VALUE = {}; // implementation -function watch(source, cb, options) { - if ((process.env.NODE_ENV !== 'production') && !isFunction(cb)) { - warn(`\`watch(fn, options?)\` signature has been moved to a separate API. ` + - `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` + - `supports \`watch(source, cb, options?) signature.`); - } - return doWatch(source, cb, options); -} -function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ, instance = currentInstance) { - if ((process.env.NODE_ENV !== 'production') && !cb) { - if (immediate !== undefined) { - warn(`watch() "immediate" option is only respected when using the ` + - `watch(source, callback, options?) signature.`); +function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { + const instance = currentInstance; + if (instance) { + const Component = instance.type; + // explicit self name has highest priority + if (type === COMPONENTS) { + const selfName = getComponentName(Component); + if (selfName && + (selfName === name || + selfName === camelize(name) || + selfName === capitalize(camelize(name)))) { + return Component; + } } - if (deep !== undefined) { - warn(`watch() "deep" option is only respected when using the ` + - `watch(source, callback, options?) signature.`); + const res = + // local registration + // check instance[type] first which is resolved for options API + resolve(instance[type] || Component[type], name) || + // window registration + resolve(instance.appContext[type], name); + if (!res && maybeSelfReference) { + // fallback to implicit self-reference + return Component; } + if ((process.env.NODE_ENV !== 'production') && warnMissing && !res) { + warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}`); + } + return res; } - const warnInvalidSource = (s) => { - warn(`Invalid watch source: `, s, `A watch source can only be a getter/effect function, a ref, ` + - `a reactive object, or an array of these types.`); - }; - let getter; - let forceTrigger = false; - if (isRef(source)) { - getter = () => source.value; - forceTrigger = !!source._shallow; - } - else if (isReactive(source)) { - getter = () => source; - deep = true; + else if ((process.env.NODE_ENV !== 'production')) { + warn$1(`resolve${capitalize(type.slice(0, -1))} ` + + `can only be used in render() or setup().`); } - else if (isArray(source)) { - getter = () => source.map(s => { - if (isRef(s)) { - return s.value; - } - else if (isReactive(s)) { - return traverse(s); - } - else if (isFunction(s)) { - return callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */, [ - instance && instance.proxy - ]); - } - else { - (process.env.NODE_ENV !== 'production') && warnInvalidSource(s); - } - }); +} +function resolve(registry, name) { + return (registry && + (registry[name] || + registry[camelize(name)] || + registry[capitalize(camelize(name))])); +} + +const Fragment = Symbol((process.env.NODE_ENV !== 'production') ? 'Fragment' : undefined); +const Text = Symbol((process.env.NODE_ENV !== 'production') ? 'Text' : undefined); +const Comment = Symbol((process.env.NODE_ENV !== 'production') ? 'Comment' : undefined); +Symbol((process.env.NODE_ENV !== 'production') ? 'Static' : undefined); +let currentBlock = null; +function isVNode(value) { + return value ? value.__v_isVNode === true : false; +} +const createVNodeWithArgsTransform = (...args) => { + return _createVNode(...(args)); +}; +const InternalObjectKey = `__vInternal`; +const normalizeKey = ({ key }) => key != null ? key : null; +const normalizeRef = ({ ref }) => { + return (ref != null + ? isString(ref) || isRef(ref) || isFunction(ref) + ? { i: currentRenderingInstance, r: ref } + : ref + : null); +}; +function createBaseVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, shapeFlag = type === Fragment ? 0 : 1 /* ELEMENT */, isBlockNode = false, needFullChildrenNormalization = false) { + const vnode = { + __v_isVNode: true, + __v_skip: true, + type, + props, + key: props && normalizeKey(props), + ref: props && normalizeRef(props), + scopeId: currentScopeId, + slotScopeIds: null, + children, + component: null, + suspense: null, + ssContent: null, + ssFallback: null, + dirs: null, + transition: null, + el: null, + anchor: null, + target: null, + targetAnchor: null, + staticCount: 0, + shapeFlag, + patchFlag, + dynamicProps, + dynamicChildren: null, + appContext: null + }; + if (needFullChildrenNormalization) { + normalizeChildren(vnode, children); } - else if (isFunction(source)) { - if (cb) { - // getter with cb - getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */, [ - instance && instance.proxy - ]); - } - else { - // no cb -> simple effect - getter = () => { - if (instance && instance.isUnmounted) { - return; - } - if (cleanup) { - cleanup(); - } - return callWithAsyncErrorHandling(source, instance, 3 /* WATCH_CALLBACK */, [onInvalidate]); - }; - } + else if (children) { + // compiled element vnode - if children is passed, only possible types are + // string or Array. + vnode.shapeFlag |= isString(children) + ? 8 /* TEXT_CHILDREN */ + : 16 /* ARRAY_CHILDREN */; } - else { - getter = NOOP; - (process.env.NODE_ENV !== 'production') && warnInvalidSource(source); + // validate key + if ((process.env.NODE_ENV !== 'production') && vnode.key !== vnode.key) { + warn$1(`VNode created with invalid key (NaN). VNode type:`, vnode.type); } - if (cb && deep) { - const baseGetter = getter; - getter = () => traverse(baseGetter()); + // track vnode for block tree + if (// avoid a block node from tracking itself + !isBlockNode && + // has current parent block + currentBlock && + // presence of a patch flag indicates this node needs patching on updates. + // component nodes also should always be patched, because even if the + // component doesn't need to update, it needs to persist the instance on to + // the next vnode so that it can be properly unmounted later. + (vnode.patchFlag > 0 || shapeFlag & 6 /* COMPONENT */) && + // the EVENTS flag is only for hydration and if it is the only flag, the + // vnode should not be considered dynamic due to handler caching. + vnode.patchFlag !== 32 /* HYDRATE_EVENTS */) { + currentBlock.push(vnode); } - let cleanup; - let onInvalidate = (fn) => { - cleanup = runner.options.onStop = () => { - callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */); - }; - }; - let oldValue = isArray(source) ? [] : INITIAL_WATCHER_VALUE; - const job = () => { - if (!runner.active) { - return; - } - if (cb) { - // watch(source, cb) - const newValue = runner(); - if (deep || forceTrigger || hasChanged(newValue, oldValue)) { - // cleanup before running cb again - if (cleanup) { - cleanup(); - } - callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [ - newValue, - // pass undefined as the old value when it's changed for the first time - oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue, - onInvalidate - ]); - oldValue = newValue; - } - } - else { - // watchEffect - runner(); + return vnode; +} +const createVNode = ((process.env.NODE_ENV !== 'production') ? createVNodeWithArgsTransform : _createVNode); +function _createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, isBlockNode = false) { + if (!type || type === NULL_DYNAMIC_COMPONENT) { + if ((process.env.NODE_ENV !== 'production') && !type) { + warn$1(`Invalid vnode type when creating vnode: ${type}.`); } - }; - // important: mark the job as a watcher callback so that scheduler knows - // it is allowed to self-trigger (#1727) - job.allowRecurse = !!cb; - let scheduler; - if (flush === 'sync') { - scheduler = job; - } - else if (flush === 'post') { - scheduler = () => queuePostRenderEffect(job, instance && instance.suspense); - } - else { - // default: 'pre' - scheduler = () => { - if (!instance || instance.isMounted) { - queuePreFlushCb(job); - } - else { - // with 'pre' option, the first call must happen before - // the component is mounted so it is called synchronously. - job(); - } - }; + type = Comment; } - const runner = effect(getter, { - lazy: true, - onTrack, - onTrigger, - scheduler - }); - recordInstanceBoundEffect(runner, instance); - // initial run - if (cb) { - if (immediate) { - job(); - } - else { - oldValue = runner(); + if (isVNode(type)) { + // createVNode receiving an existing vnode. This happens in cases like + // + // #2078 make sure to merge refs during the clone instead of overwriting it + const cloned = cloneVNode(type, props, true /* mergeRef: true */); + if (children) { + normalizeChildren(cloned, children); } + return cloned; } - else if (flush === 'post') { - queuePostRenderEffect(runner, instance && instance.suspense); - } - else { - runner(); + // class component normalization. + if (isClassComponent(type)) { + type = type.__vccOpts; } - return () => { - stop(runner); - if (instance) { - remove(instance.effects, runner); + // class & style normalization. + if (props) { + // for reactive or proxy objects, we need to clone it to enable mutation. + props = guardReactiveProps(props); + let { class: klass, style } = props; + if (klass && !isString(klass)) { + props.class = normalizeClass(klass); } - }; -} -// this.$watch -function instanceWatch(source, cb, options) { - const publicThis = this.proxy; - const getter = isString(source) - ? () => publicThis[source] - : source.bind(publicThis); - return doWatch(getter, cb.bind(publicThis), options, this); -} -function traverse(value, seen = new Set()) { - if (!isObject(value) || seen.has(value)) { - return value; - } - seen.add(value); - if (isRef(value)) { - traverse(value.value, seen); - } - else if (isArray(value)) { - for (let i = 0; i < value.length; i++) { - traverse(value[i], seen); + if (isObject(style)) { + // reactive state objects need to be cloned since they are likely to be + // mutated + if (isProxy(style) && !isArray(style)) { + style = extend({}, style); + } + props.style = normalizeStyle(style); } } - else if (isSet(value) || isMap(value)) { - value.forEach((v) => { - traverse(v, seen); - }); - } - else { - for (const key in value) { - traverse(value[key], seen); - } + // encode the vnode type information into a bitmap + const shapeFlag = isString(type) + ? 1 /* ELEMENT */ + : isTeleport(type) + ? 64 /* TELEPORT */ + : isObject(type) + ? 4 /* STATEFUL_COMPONENT */ + : isFunction(type) + ? 2 /* FUNCTIONAL_COMPONENT */ + : 0; + if ((process.env.NODE_ENV !== 'production') && shapeFlag & 4 /* STATEFUL_COMPONENT */ && isProxy(type)) { + type = toRaw(type); + warn$1(`Vue received a Component which was made a reactive object. This can ` + + `lead to unnecessary performance overhead, and should be avoided by ` + + `marking the component with \`markRaw\` or using \`shallowRef\` ` + + `instead of \`ref\`.`, `\nComponent that was made reactive: `, type); } - return value; -} - -const isKeepAlive = (vnode) => vnode.type.__isKeepAlive; -function onActivated(hook, target) { - registerKeepAliveHook(hook, "a" /* ACTIVATED */, target); + return createBaseVNode(type, props, children, patchFlag, dynamicProps, shapeFlag, isBlockNode, true); } -function onDeactivated(hook, target) { - registerKeepAliveHook(hook, "da" /* DEACTIVATED */, target); +function guardReactiveProps(props) { + if (!props) + return null; + return isProxy(props) || InternalObjectKey in props + ? extend({}, props) + : props; } -function registerKeepAliveHook(hook, type, target = currentInstance) { - // cache the deactivate branch check wrapper for injected hooks so the same - // hook can be properly deduped by the scheduler. "__wdc" stands for "with - // deactivation check". - const wrappedHook = hook.__wdc || - (hook.__wdc = () => { - // only fire the hook if the target instance is NOT in a deactivated branch. - let current = target; - while (current) { - if (current.isDeactivated) { - return; - } - current = current.parent; - } - hook(); - }); - injectHook(type, wrappedHook, target); - // In addition to registering it on the target instance, we walk up the parent - // chain and register it on all ancestor instances that are keep-alive roots. - // This avoids the need to walk the entire component tree when invoking these - // hooks, and more importantly, avoids the need to track child components in - // arrays. - if (target) { - let current = target.parent; - while (current && current.parent) { - if (isKeepAlive(current.parent.vnode)) { - injectToKeepAliveRoot(wrappedHook, type, target, current); - } - current = current.parent; - } - } +function cloneVNode(vnode, extraProps, mergeRef = false) { + // This is intentionally NOT using spread or extend to avoid the runtime + // key enumeration cost. + const { props, ref, patchFlag, children } = vnode; + const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props; + const cloned = { + __v_isVNode: true, + __v_skip: true, + type: vnode.type, + props: mergedProps, + key: mergedProps && normalizeKey(mergedProps), + ref: extraProps && extraProps.ref + ? // #2078 in the case of + // if the vnode itself already has a ref, cloneVNode will need to merge + // the refs so the single vnode can be set on multiple refs + mergeRef && ref + ? isArray(ref) + ? ref.concat(normalizeRef(extraProps)) + : [ref, normalizeRef(extraProps)] + : normalizeRef(extraProps) + : ref, + scopeId: vnode.scopeId, + slotScopeIds: vnode.slotScopeIds, + children: (process.env.NODE_ENV !== 'production') && patchFlag === -1 /* HOISTED */ && isArray(children) + ? children.map(deepCloneVNode) + : children, + target: vnode.target, + targetAnchor: vnode.targetAnchor, + staticCount: vnode.staticCount, + shapeFlag: vnode.shapeFlag, + // if the vnode is cloned with extra props, we can no longer assume its + // existing patch flag to be reliable and need to add the FULL_PROPS flag. + // note: perserve flag for fragments since they use the flag for children + // fast paths only. + patchFlag: extraProps && vnode.type !== Fragment + ? patchFlag === -1 // hoisted node + ? 16 /* FULL_PROPS */ + : patchFlag | 16 /* FULL_PROPS */ + : patchFlag, + dynamicProps: vnode.dynamicProps, + dynamicChildren: vnode.dynamicChildren, + appContext: vnode.appContext, + dirs: vnode.dirs, + transition: vnode.transition, + // These should technically only be non-null on mounted VNodes. However, + // they *should* be copied for kept-alive vnodes. So we just always copy + // them since them being non-null during a mount doesn't affect the logic as + // they will simply be overwritten. + component: vnode.component, + suspense: vnode.suspense, + ssContent: vnode.ssContent && cloneVNode(vnode.ssContent), + ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback), + el: vnode.el, + anchor: vnode.anchor + }; + return cloned; } -function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { - // injectHook wraps the original for error handling, so make sure to remove - // the wrapped version. - const injected = injectHook(type, hook, keepAliveRoot, true /* prepend */); - onUnmounted(() => { - remove(keepAliveRoot[type], injected); - }, target); -} - /** -Runtime helper for applying directives to a vnode. Example usage: - -const comp = resolveComponent('comp') -const foo = resolveDirective('foo') -const bar = resolveDirective('bar') - -return withDirectives(h(comp), [ - [foo, this.x], - [bar, this.y] -]) -*/ -const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text'); -function validateDirectiveName(name) { - if (isBuiltInDirective(name)) { - warn('Do not use built-in directive ids as custom directive id: ' + name); + * Dev only, for HMR of hoisted vnodes reused in v-for + * https://github.com/vitejs/vite/issues/2022 + */ +function deepCloneVNode(vnode) { + const cloned = cloneVNode(vnode); + if (isArray(vnode.children)) { + cloned.children = vnode.children.map(deepCloneVNode); } + return cloned; } /** - * Adds directives to a VNode. + * @private */ -function withDirectives(vnode, directives) { - { - (process.env.NODE_ENV !== 'production') && warn(`withDirectives can only be used inside render functions.`); - return vnode; - } -} - -function createAppContext() { - return { - app: null, - config: { - isNativeTag: NO, - performance: false, - globalProperties: {}, - optionMergeStrategies: {}, - isCustomElement: NO, - errorHandler: undefined, - warnHandler: undefined - }, - mixins: [], - components: {}, - directives: {}, - provides: Object.create(null) - }; +function createTextVNode(text = ' ', flag = 0) { + return createVNode(Text, null, text, flag); } -let uid$1 = 0; -// fixed by xxxxxx -function createAppAPI() { - return function createApp(rootComponent, rootProps = null) { - if (rootProps != null && !isObject(rootProps)) { - (process.env.NODE_ENV !== 'production') && warn(`root props passed to app.mount() must be an object.`); - rootProps = null; +function normalizeChildren(vnode, children) { + let type = 0; + const { shapeFlag } = vnode; + if (children == null) { + children = null; + } + else if (isArray(children)) { + type = 16 /* ARRAY_CHILDREN */; + } + else if (typeof children === 'object') { + if (shapeFlag & (1 /* ELEMENT */ | 64 /* TELEPORT */)) { + // Normalize slot to plain children for plain element and Teleport + const slot = children.default; + if (slot) { + // _c marker is added by withCtx() indicating this is a compiled slot + slot._c && (slot._d = false); + normalizeChildren(vnode, slot()); + slot._c && (slot._d = true); + } + return; } - const context = createAppContext(); - const installedPlugins = new Set(); - // fixed by xxxxxx - // let isMounted = false - const app = (context.app = { - _uid: uid$1++, - _component: rootComponent, - _props: rootProps, - _container: null, - _context: context, - version, - get config() { - return context.config; - }, - set config(v) { - if ((process.env.NODE_ENV !== 'production')) { - warn(`app.config cannot be replaced. Modify individual options instead.`); - } - }, - use(plugin, ...options) { - if (installedPlugins.has(plugin)) { - (process.env.NODE_ENV !== 'production') && warn(`Plugin has already been applied to target app.`); - } - else if (plugin && isFunction(plugin.install)) { - installedPlugins.add(plugin); - plugin.install(app, ...options); - } - else if (isFunction(plugin)) { - installedPlugins.add(plugin); - plugin(app, ...options); - } - else if ((process.env.NODE_ENV !== 'production')) { - warn(`A plugin must either be a function or an object with an "install" ` + - `function.`); - } - return app; - }, - mixin(mixin) { - if (__VUE_OPTIONS_API__) { - if (!context.mixins.includes(mixin)) { - context.mixins.push(mixin); - // window mixin with props/emits de-optimizes props/emits - // normalization caching. - if (mixin.props || mixin.emits) { - context.deopt = true; - } - } - else if ((process.env.NODE_ENV !== 'production')) { - warn('Mixin has already been applied to target app' + - (mixin.name ? `: ${mixin.name}` : '')); - } - } - else if ((process.env.NODE_ENV !== 'production')) { - warn('Mixins are only available in builds supporting Options API'); - } - return app; - }, - component(name, component) { - if ((process.env.NODE_ENV !== 'production')) { - validateComponentName(name, context.config); - } - if (!component) { - return context.components[name]; - } - if ((process.env.NODE_ENV !== 'production') && context.components[name]) { - warn(`Component "${name}" has already been registered in target app.`); - } - context.components[name] = component; - return app; - }, - directive(name, directive) { - if ((process.env.NODE_ENV !== 'production')) { - validateDirectiveName(name); - } - if (!directive) { - return context.directives[name]; + else { + type = 32 /* SLOTS_CHILDREN */; + const slotFlag = children._; + if (!slotFlag && !(InternalObjectKey in children)) { + children._ctx = currentRenderingInstance; + } + else if (slotFlag === 3 /* FORWARDED */ && currentRenderingInstance) { + // a child component receives forwarded slots from the parent. + // its slot type is determined by its parent's slot type. + if (currentRenderingInstance.slots._ === 1 /* STABLE */) { + children._ = 1 /* STABLE */; } - if ((process.env.NODE_ENV !== 'production') && context.directives[name]) { - warn(`Directive "${name}" has already been registered in target app.`); + else { + children._ = 2 /* DYNAMIC */; + vnode.patchFlag |= 1024 /* DYNAMIC_SLOTS */; } - context.directives[name] = directive; - return app; - }, - // fixed by xxxxxx - mount() { }, - // fixed by xxxxxx - unmount() { }, - provide(key, value) { - if ((process.env.NODE_ENV !== 'production') && key in context.provides) { - warn(`App already provides property with key "${String(key)}". ` + - `It will be overwritten with the new value.`); + } + } + } + else if (isFunction(children)) { + children = { default: children, _ctx: currentRenderingInstance }; + type = 32 /* SLOTS_CHILDREN */; + } + else { + children = String(children); + // force teleport children to array so it can be moved around + if (shapeFlag & 64 /* TELEPORT */) { + type = 16 /* ARRAY_CHILDREN */; + children = [createTextVNode(children)]; + } + else { + type = 8 /* TEXT_CHILDREN */; + } + } + vnode.children = children; + vnode.shapeFlag |= type; +} +function mergeProps(...args) { + const ret = {}; + for (let i = 0; i < args.length; i++) { + const toMerge = args[i]; + for (const key in toMerge) { + if (key === 'class') { + if (ret.class !== toMerge.class) { + ret.class = normalizeClass([ret.class, toMerge.class]); } - // TypeScript doesn't allow symbols as index type - // https://github.com/Microsoft/TypeScript/issues/24587 - context.provides[key] = value; - return app; } - }); - return app; - }; -} - -// implementation, close to no-op -function defineComponent(options) { - return isFunction(options) ? { setup: options, name: options.name } : options; + else if (key === 'style') { + ret.style = normalizeStyle([ret.style, toMerge.style]); + } + else if (isOn(key)) { + const existing = ret[key]; + const incoming = toMerge[key]; + if (existing !== incoming) { + ret[key] = existing + ? [].concat(existing, incoming) + : incoming; + } + } + else if (key !== '') { + ret[key] = toMerge[key]; + } + } + } + return ret; } -const queuePostRenderEffect = queuePostFlushCb; - -const isTeleport = (type) => type.__isTeleport; - -const COMPONENTS = 'components'; -const DIRECTIVES = 'directives'; -const NULL_DYNAMIC_COMPONENT = Symbol(); /** - * @private + * #2437 In Vue 3, functional components do not have a public instance proxy but + * they exist in the internal parent chain. For code that relies on traversing + * public $parent chains, skip functional ones and go to the parent instead. */ -function resolveDirective(name) { - return resolveAsset(DIRECTIVES, name); -} -// implementation -function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { - const instance = currentInstance; - if (instance) { - const Component = instance.type; - // explicit self name has highest priority - if (type === COMPONENTS) { - const selfName = getComponentName(Component); - if (selfName && - (selfName === name || - selfName === camelize(name) || - selfName === capitalize(camelize(name)))) { - return Component; - } +const getPublicInstance = (i) => { + if (!i) + return null; + if (isStatefulComponent(i)) + return getExposeProxy(i) || i.proxy; + return getPublicInstance(i.parent); +}; +const publicPropertiesMap = extend(Object.create(null), { + $: i => i, + $el: i => i.vnode.el, + $data: i => i.data, + $props: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.props) : i.props), + $attrs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.attrs) : i.attrs), + $slots: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.slots) : i.slots), + $refs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.refs) : i.refs), + $parent: i => getPublicInstance(i.parent), + $root: i => getPublicInstance(i.root), + $emit: i => i.emit, + $options: i => (__VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type), + $forceUpdate: i => () => queueJob(i.update), + // $nextTick: i => nextTick.bind(i.proxy!), // fixed by xxxxxx + $watch: i => (__VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP) +}); +const PublicInstanceProxyHandlers = { + get({ _: instance }, key) { + const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + // for internal formatters to know that this is a Vue instance + if ((process.env.NODE_ENV !== 'production') && key === '__isVue') { + return true; } - const res = - // local registration - // check instance[type] first for components with mixin or extends. - resolve(instance[type] || Component[type], name) || - // window registration - resolve(instance.appContext[type], name); - if (!res && maybeSelfReference) { - // fallback to implicit self-reference - return Component; + // prioritize