You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5978 lines
208 KiB
5978 lines
208 KiB
import { isRootHook, getValueByDataPath, isUniLifecycleHook, ON_ERROR, UniLifecycleHooks, invokeCreateErrorHandler, dynamicSlotName } from '@dcloudio/uni-shared'; |
|
import { extend, isObject, def, hasChanged, isArray, isString, isFunction, isPromise, EMPTY_OBJ, remove, toHandlerKey, camelize, capitalize, hasOwn, hyphenate, isReservedProp, toRawType, normalizeClass, normalizeStyle, isOn, toTypeString, NOOP, isMap, isIntegerKey, isSet, isPlainObject, makeMap, invokeArrayFns, NO, isSymbol, looseToNumber, isBuiltInDirective, EMPTY_ARR, isModelListener, toNumber, toDisplayString } from '@vue/shared'; |
|
export { EMPTY_OBJ, camelize, normalizeClass, normalizeProps, normalizeStyle, toDisplayString, toHandlerKey } from '@vue/shared'; |
|
|
|
function warn$1(msg, ...args) { |
|
console.warn(`[Vue warn] ${msg}`, ...args); |
|
} |
|
|
|
let activeEffectScope; |
|
class EffectScope { |
|
constructor(detached = false) { |
|
this.detached = detached; |
|
/** |
|
* @internal |
|
*/ |
|
this._active = true; |
|
/** |
|
* @internal |
|
*/ |
|
this.effects = []; |
|
/** |
|
* @internal |
|
*/ |
|
this.cleanups = []; |
|
this.parent = activeEffectScope; |
|
if (!detached && activeEffectScope) { |
|
this.index = |
|
(activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this) - 1; |
|
} |
|
} |
|
get active() { |
|
return this._active; |
|
} |
|
run(fn) { |
|
if (this._active) { |
|
const currentEffectScope = activeEffectScope; |
|
try { |
|
activeEffectScope = this; |
|
return fn(); |
|
} |
|
finally { |
|
activeEffectScope = currentEffectScope; |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn$1(`cannot run an inactive effect scope.`); |
|
} |
|
} |
|
/** |
|
* This should only be called on non-detached scopes |
|
* @internal |
|
*/ |
|
on() { |
|
activeEffectScope = this; |
|
} |
|
/** |
|
* This should only be called on non-detached scopes |
|
* @internal |
|
*/ |
|
off() { |
|
activeEffectScope = this.parent; |
|
} |
|
stop(fromParent) { |
|
if (this._active) { |
|
let i, l; |
|
for (i = 0, l = this.effects.length; i < l; i++) { |
|
this.effects[i].stop(); |
|
} |
|
for (i = 0, l = this.cleanups.length; i < l; i++) { |
|
this.cleanups[i](); |
|
} |
|
if (this.scopes) { |
|
for (i = 0, l = this.scopes.length; i < l; i++) { |
|
this.scopes[i].stop(true); |
|
} |
|
} |
|
// nested scope, dereference from parent to avoid memory leaks |
|
if (!this.detached && 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.parent = undefined; |
|
this._active = false; |
|
} |
|
} |
|
} |
|
function effectScope(detached) { |
|
return new EffectScope(detached); |
|
} |
|
function recordEffectScope(effect, scope = activeEffectScope) { |
|
if (scope && scope.active) { |
|
scope.effects.push(effect); |
|
} |
|
} |
|
function getCurrentScope() { |
|
return activeEffectScope; |
|
} |
|
function onScopeDispose(fn) { |
|
if (activeEffectScope) { |
|
activeEffectScope.cleanups.push(fn); |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn$1(`onScopeDispose() is called when there is no active effect scope` + |
|
` to be associated with.`); |
|
} |
|
} |
|
|
|
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 |
|
} |
|
} |
|
}; |
|
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 of 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; |
|
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' : ''); |
|
class ReactiveEffect { |
|
constructor(fn, scheduler = null, scope) { |
|
this.fn = fn; |
|
this.scheduler = scheduler; |
|
this.active = true; |
|
this.deps = []; |
|
this.parent = undefined; |
|
recordEffectScope(this, scope); |
|
} |
|
run() { |
|
if (!this.active) { |
|
return this.fn(); |
|
} |
|
let parent = activeEffect; |
|
let lastShouldTrack = shouldTrack; |
|
while (parent) { |
|
if (parent === this) { |
|
return; |
|
} |
|
parent = parent.parent; |
|
} |
|
try { |
|
this.parent = activeEffect; |
|
activeEffect = this; |
|
shouldTrack = true; |
|
trackOpBit = 1 << ++effectTrackDepth; |
|
if (effectTrackDepth <= maxMarkerBits) { |
|
initDepMarkers(this); |
|
} |
|
else { |
|
cleanupEffect(this); |
|
} |
|
return this.fn(); |
|
} |
|
finally { |
|
if (effectTrackDepth <= maxMarkerBits) { |
|
finalizeDepMarkers(this); |
|
} |
|
trackOpBit = 1 << --effectTrackDepth; |
|
activeEffect = this.parent; |
|
shouldTrack = lastShouldTrack; |
|
this.parent = undefined; |
|
if (this.deferStop) { |
|
this.stop(); |
|
} |
|
} |
|
} |
|
stop() { |
|
// stopped while running itself - defer the cleanup |
|
if (activeEffect === this) { |
|
this.deferStop = true; |
|
} |
|
else 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++) { |
|
deps[i].delete(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; |
|
} |
|
function stop(runner) { |
|
runner.effect.stop(); |
|
} |
|
let shouldTrack = true; |
|
const trackStack = []; |
|
function pauseTracking() { |
|
trackStack.push(shouldTrack); |
|
shouldTrack = false; |
|
} |
|
function resetTracking() { |
|
const last = trackStack.pop(); |
|
shouldTrack = last === undefined ? true : last; |
|
} |
|
function track(target, type, key) { |
|
if (shouldTrack && activeEffect) { |
|
let depsMap = targetMap.get(target); |
|
if (!depsMap) { |
|
targetMap.set(target, (depsMap = new Map())); |
|
} |
|
let dep = depsMap.get(key); |
|
if (!dep) { |
|
depsMap.set(key, (dep = createDep())); |
|
} |
|
const eventInfo = (process.env.NODE_ENV !== 'production') |
|
? { effect: activeEffect, target, type, key } |
|
: undefined; |
|
trackEffects(dep, eventInfo); |
|
} |
|
} |
|
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 (shouldTrack) { |
|
dep.add(activeEffect); |
|
activeEffect.deps.push(dep); |
|
if ((process.env.NODE_ENV !== 'production') && activeEffect.onTrack) { |
|
activeEffect.onTrack(Object.assign({ effect: activeEffect }, debuggerEventExtraInfo)); |
|
} |
|
} |
|
} |
|
function trigger(target, type, key, newValue, oldValue, oldTarget) { |
|
const depsMap = targetMap.get(target); |
|
if (!depsMap) { |
|
// never been tracked |
|
return; |
|
} |
|
let deps = []; |
|
if (type === "clear" /* TriggerOpTypes.CLEAR */) { |
|
// collection being cleared |
|
// trigger all effects for target |
|
deps = [...depsMap.values()]; |
|
} |
|
else if (key === 'length' && isArray(target)) { |
|
const newLength = Number(newValue); |
|
depsMap.forEach((dep, key) => { |
|
if (key === 'length' || key >= newLength) { |
|
deps.push(dep); |
|
} |
|
}); |
|
} |
|
else { |
|
// schedule runs for SET | ADD | DELETE |
|
if (key !== void 0) { |
|
deps.push(depsMap.get(key)); |
|
} |
|
// also run for iteration key on ADD | DELETE | Map.SET |
|
switch (type) { |
|
case "add" /* TriggerOpTypes.ADD */: |
|
if (!isArray(target)) { |
|
deps.push(depsMap.get(ITERATE_KEY)); |
|
if (isMap(target)) { |
|
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); |
|
} |
|
} |
|
else if (isIntegerKey(key)) { |
|
// new index added to array -> length changes |
|
deps.push(depsMap.get('length')); |
|
} |
|
break; |
|
case "delete" /* TriggerOpTypes.DELETE */: |
|
if (!isArray(target)) { |
|
deps.push(depsMap.get(ITERATE_KEY)); |
|
if (isMap(target)) { |
|
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); |
|
} |
|
} |
|
break; |
|
case "set" /* TriggerOpTypes.SET */: |
|
if (isMap(target)) { |
|
deps.push(depsMap.get(ITERATE_KEY)); |
|
} |
|
break; |
|
} |
|
} |
|
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 ((process.env.NODE_ENV !== 'production')) { |
|
triggerEffects(createDep(effects), eventInfo); |
|
} |
|
else { |
|
triggerEffects(createDep(effects)); |
|
} |
|
} |
|
} |
|
function triggerEffects(dep, debuggerEventExtraInfo) { |
|
// spread into array for stabilization |
|
const effects = isArray(dep) ? dep : [...dep]; |
|
for (const effect of effects) { |
|
if (effect.computed) { |
|
triggerEffect(effect, debuggerEventExtraInfo); |
|
} |
|
} |
|
for (const effect of effects) { |
|
if (!effect.computed) { |
|
triggerEffect(effect, debuggerEventExtraInfo); |
|
} |
|
} |
|
} |
|
function triggerEffect(effect, debuggerEventExtraInfo) { |
|
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(); |
|
} |
|
} |
|
} |
|
function getDepFromReactive(object, key) { |
|
var _a; |
|
return (_a = targetMap.get(object)) === null || _a === void 0 ? void 0 : _a.get(key); |
|
} |
|
|
|
const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`); |
|
const builtInSymbols = new Set( |
|
/*#__PURE__*/ |
|
Object.getOwnPropertyNames(Symbol) |
|
// ios10.x Object.getOwnPropertyNames(Symbol) can enumerate 'arguments' and 'caller' |
|
// but accessing them on Symbol leads to TypeError because Symbol is a strict mode |
|
// function |
|
.filter(key => key !== 'arguments' && key !== 'caller') |
|
.map(key => Symbol[key]) |
|
.filter(isSymbol)); |
|
const get$1 = /*#__PURE__*/ createGetter(); |
|
const shallowGet = /*#__PURE__*/ createGetter(false, true); |
|
const readonlyGet = /*#__PURE__*/ createGetter(true); |
|
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true); |
|
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" /* TrackOpTypes.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; |
|
}; |
|
}); |
|
return instrumentations; |
|
} |
|
function hasOwnProperty(key) { |
|
const obj = toRaw(this); |
|
track(obj, "has" /* TrackOpTypes.HAS */, key); |
|
return obj.hasOwnProperty(key); |
|
} |
|
function createGetter(isReadonly = false, shallow = false) { |
|
return function get(target, key, receiver) { |
|
if (key === "__v_isReactive" /* ReactiveFlags.IS_REACTIVE */) { |
|
return !isReadonly; |
|
} |
|
else if (key === "__v_isReadonly" /* ReactiveFlags.IS_READONLY */) { |
|
return isReadonly; |
|
} |
|
else if (key === "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */) { |
|
return shallow; |
|
} |
|
else if (key === "__v_raw" /* ReactiveFlags.RAW */ && |
|
receiver === |
|
(isReadonly |
|
? shallow |
|
? shallowReadonlyMap |
|
: readonlyMap |
|
: shallow |
|
? shallowReactiveMap |
|
: reactiveMap).get(target)) { |
|
return target; |
|
} |
|
const targetIsArray = isArray(target); |
|
if (!isReadonly) { |
|
if (targetIsArray && hasOwn(arrayInstrumentations, key)) { |
|
return Reflect.get(arrayInstrumentations, key, receiver); |
|
} |
|
if (key === 'hasOwnProperty') { |
|
return hasOwnProperty; |
|
} |
|
} |
|
const res = Reflect.get(target, key, receiver); |
|
if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { |
|
return res; |
|
} |
|
if (!isReadonly) { |
|
track(target, "get" /* TrackOpTypes.GET */, key); |
|
} |
|
if (shallow) { |
|
return res; |
|
} |
|
if (isRef(res)) { |
|
// ref unwrapping - skip unwrap for Array + integer key. |
|
return targetIsArray && isIntegerKey(key) ? res : res.value; |
|
} |
|
if (isObject(res)) { |
|
// Convert returned value into a proxy as well. we do the isObject check |
|
// here to avoid invalid value warning. Also need to lazy access readonly |
|
// and reactive here to avoid circular dependency. |
|
return isReadonly ? readonly(res) : reactive(res); |
|
} |
|
return res; |
|
}; |
|
} |
|
const set$1 = /*#__PURE__*/ createSetter(); |
|
const shallowSet = /*#__PURE__*/ createSetter(true); |
|
function createSetter(shallow = false) { |
|
return function set(target, key, value, receiver) { |
|
let oldValue = target[key]; |
|
if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) { |
|
return false; |
|
} |
|
if (!shallow) { |
|
if (!isShallow(value) && !isReadonly(value)) { |
|
oldValue = toRaw(oldValue); |
|
value = toRaw(value); |
|
} |
|
if (!isArray(target) && isRef(oldValue) && !isRef(value)) { |
|
oldValue.value = value; |
|
return true; |
|
} |
|
} |
|
const hadKey = isArray(target) && isIntegerKey(key) |
|
? Number(key) < target.length |
|
: hasOwn(target, key); |
|
const result = Reflect.set(target, key, value, receiver); |
|
// don't trigger if target is something up in the prototype chain of original |
|
if (target === toRaw(receiver)) { |
|
if (!hadKey) { |
|
trigger(target, "add" /* TriggerOpTypes.ADD */, key, value); |
|
} |
|
else if (hasChanged(value, oldValue)) { |
|
trigger(target, "set" /* TriggerOpTypes.SET */, key, value, oldValue); |
|
} |
|
} |
|
return result; |
|
}; |
|
} |
|
function deleteProperty(target, key) { |
|
const hadKey = hasOwn(target, key); |
|
const oldValue = target[key]; |
|
const result = Reflect.deleteProperty(target, key); |
|
if (result && hadKey) { |
|
trigger(target, "delete" /* TriggerOpTypes.DELETE */, key, undefined, oldValue); |
|
} |
|
return result; |
|
} |
|
function has$1(target, key) { |
|
const result = Reflect.has(target, key); |
|
if (!isSymbol(key) || !builtInSymbols.has(key)) { |
|
track(target, "has" /* TrackOpTypes.HAS */, key); |
|
} |
|
return result; |
|
} |
|
function ownKeys(target) { |
|
track(target, "iterate" /* TrackOpTypes.ITERATE */, isArray(target) ? 'length' : ITERATE_KEY); |
|
return Reflect.ownKeys(target); |
|
} |
|
const mutableHandlers = { |
|
get: get$1, |
|
set: set$1, |
|
deleteProperty, |
|
has: has$1, |
|
ownKeys |
|
}; |
|
const readonlyHandlers = { |
|
get: readonlyGet, |
|
set(target, key) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warn$1(`Set operation on key "${String(key)}" failed: target is readonly.`, target); |
|
} |
|
return true; |
|
}, |
|
deleteProperty(target, key) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warn$1(`Delete operation on key "${String(key)}" failed: target is readonly.`, target); |
|
} |
|
return true; |
|
} |
|
}; |
|
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 = /*#__PURE__*/ extend({}, readonlyHandlers, { |
|
get: shallowReadonlyGet |
|
}); |
|
|
|
const toShallow = (value) => value; |
|
const getProto = (v) => Reflect.getPrototypeOf(v); |
|
function get(target, key, isReadonly = false, isShallow = false) { |
|
// #1772: readonly(reactive(Map)) should return readonly + reactive version |
|
// of the value |
|
target = target["__v_raw" /* ReactiveFlags.RAW */]; |
|
const rawTarget = toRaw(target); |
|
const rawKey = toRaw(key); |
|
if (!isReadonly) { |
|
if (key !== rawKey) { |
|
track(rawTarget, "get" /* TrackOpTypes.GET */, key); |
|
} |
|
track(rawTarget, "get" /* TrackOpTypes.GET */, rawKey); |
|
} |
|
const { has } = getProto(rawTarget); |
|
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive; |
|
if (has.call(rawTarget, key)) { |
|
return wrap(target.get(key)); |
|
} |
|
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(key, isReadonly = false) { |
|
const target = this["__v_raw" /* ReactiveFlags.RAW */]; |
|
const rawTarget = toRaw(target); |
|
const rawKey = toRaw(key); |
|
if (!isReadonly) { |
|
if (key !== rawKey) { |
|
track(rawTarget, "has" /* TrackOpTypes.HAS */, key); |
|
} |
|
track(rawTarget, "has" /* TrackOpTypes.HAS */, rawKey); |
|
} |
|
return key === rawKey |
|
? target.has(key) |
|
: target.has(key) || target.has(rawKey); |
|
} |
|
function size(target, isReadonly = false) { |
|
target = target["__v_raw" /* ReactiveFlags.RAW */]; |
|
!isReadonly && track(toRaw(target), "iterate" /* TrackOpTypes.ITERATE */, ITERATE_KEY); |
|
return Reflect.get(target, 'size', target); |
|
} |
|
function add(value) { |
|
value = toRaw(value); |
|
const target = toRaw(this); |
|
const proto = getProto(target); |
|
const hadKey = proto.has.call(target, value); |
|
if (!hadKey) { |
|
target.add(value); |
|
trigger(target, "add" /* TriggerOpTypes.ADD */, value, value); |
|
} |
|
return this; |
|
} |
|
function set$2(key, value) { |
|
value = toRaw(value); |
|
const target = toRaw(this); |
|
const { has, get } = getProto(target); |
|
let hadKey = has.call(target, key); |
|
if (!hadKey) { |
|
key = toRaw(key); |
|
hadKey = has.call(target, key); |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
checkIdentityKeys(target, has, key); |
|
} |
|
const oldValue = get.call(target, key); |
|
target.set(key, value); |
|
if (!hadKey) { |
|
trigger(target, "add" /* TriggerOpTypes.ADD */, key, value); |
|
} |
|
else if (hasChanged(value, oldValue)) { |
|
trigger(target, "set" /* TriggerOpTypes.SET */, key, value, oldValue); |
|
} |
|
return this; |
|
} |
|
function deleteEntry(key) { |
|
const target = toRaw(this); |
|
const { has, get } = getProto(target); |
|
let hadKey = has.call(target, key); |
|
if (!hadKey) { |
|
key = toRaw(key); |
|
hadKey = has.call(target, key); |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
checkIdentityKeys(target, has, key); |
|
} |
|
const oldValue = get ? get.call(target, key) : undefined; |
|
// forward the operation before queueing reactions |
|
const result = target.delete(key); |
|
if (hadKey) { |
|
trigger(target, "delete" /* TriggerOpTypes.DELETE */, key, undefined, oldValue); |
|
} |
|
return result; |
|
} |
|
function clear() { |
|
const target = toRaw(this); |
|
const hadItems = target.size !== 0; |
|
const oldTarget = (process.env.NODE_ENV !== 'production') |
|
? isMap(target) |
|
? new Map(target) |
|
: new Set(target) |
|
: undefined; |
|
// forward the operation before queueing reactions |
|
const result = target.clear(); |
|
if (hadItems) { |
|
trigger(target, "clear" /* TriggerOpTypes.CLEAR */, undefined, undefined, oldTarget); |
|
} |
|
return result; |
|
} |
|
function createForEach(isReadonly, isShallow) { |
|
return function forEach(callback, thisArg) { |
|
const observed = this; |
|
const target = observed["__v_raw" /* ReactiveFlags.RAW */]; |
|
const rawTarget = toRaw(target); |
|
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive; |
|
!isReadonly && track(rawTarget, "iterate" /* TrackOpTypes.ITERATE */, ITERATE_KEY); |
|
return target.forEach((value, key) => { |
|
// important: make sure the callback is |
|
// 1. invoked with the reactive map as `this` and 3rd arg |
|
// 2. the value received should be a corresponding reactive/readonly. |
|
return callback.call(thisArg, wrap(value), wrap(key), observed); |
|
}); |
|
}; |
|
} |
|
function createIterableMethod(method, isReadonly, isShallow) { |
|
return function (...args) { |
|
const target = this["__v_raw" /* ReactiveFlags.RAW */]; |
|
const rawTarget = toRaw(target); |
|
const targetIsMap = isMap(rawTarget); |
|
const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap); |
|
const isKeyOnly = method === 'keys' && targetIsMap; |
|
const innerIterator = target[method](...args); |
|
const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive; |
|
!isReadonly && |
|
track(rawTarget, "iterate" /* TrackOpTypes.ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY); |
|
// return a wrapped iterator which returns observed versions of the |
|
// values emitted from the real iterator |
|
return { |
|
// iterator protocol |
|
next() { |
|
const { value, done } = innerIterator.next(); |
|
return done |
|
? { value, done } |
|
: { |
|
value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value), |
|
done |
|
}; |
|
}, |
|
// iterable protocol |
|
[Symbol.iterator]() { |
|
return this; |
|
} |
|
}; |
|
}; |
|
} |
|
function createReadonlyMethod(type) { |
|
return function (...args) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
const key = args[0] ? `on key "${args[0]}" ` : ``; |
|
console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this)); |
|
} |
|
return type === "delete" /* TriggerOpTypes.DELETE */ ? false : this; |
|
}; |
|
} |
|
function createInstrumentations() { |
|
const mutableInstrumentations = { |
|
get(key) { |
|
return get(this, key); |
|
}, |
|
get size() { |
|
return size(this); |
|
}, |
|
has, |
|
add, |
|
set: set$2, |
|
delete: deleteEntry, |
|
clear, |
|
forEach: createForEach(false, false) |
|
}; |
|
const shallowInstrumentations = { |
|
get(key) { |
|
return get(this, key, false, true); |
|
}, |
|
get size() { |
|
return size(this); |
|
}, |
|
has, |
|
add, |
|
set: set$2, |
|
delete: deleteEntry, |
|
clear, |
|
forEach: createForEach(false, true) |
|
}; |
|
const readonlyInstrumentations = { |
|
get(key) { |
|
return get(this, key, true); |
|
}, |
|
get size() { |
|
return size(this, true); |
|
}, |
|
has(key) { |
|
return has.call(this, key, true); |
|
}, |
|
add: createReadonlyMethod("add" /* TriggerOpTypes.ADD */), |
|
set: createReadonlyMethod("set" /* TriggerOpTypes.SET */), |
|
delete: createReadonlyMethod("delete" /* TriggerOpTypes.DELETE */), |
|
clear: createReadonlyMethod("clear" /* TriggerOpTypes.CLEAR */), |
|
forEach: createForEach(true, false) |
|
}; |
|
const shallowReadonlyInstrumentations = { |
|
get(key) { |
|
return get(this, key, true, true); |
|
}, |
|
get size() { |
|
return size(this, true); |
|
}, |
|
has(key) { |
|
return has.call(this, key, true); |
|
}, |
|
add: createReadonlyMethod("add" /* TriggerOpTypes.ADD */), |
|
set: createReadonlyMethod("set" /* TriggerOpTypes.SET */), |
|
delete: createReadonlyMethod("delete" /* TriggerOpTypes.DELETE */), |
|
clear: createReadonlyMethod("clear" /* TriggerOpTypes.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 |
|
? shallowReadonlyInstrumentations |
|
: shallowInstrumentations |
|
: isReadonly |
|
? readonlyInstrumentations |
|
: mutableInstrumentations; |
|
return (target, key, receiver) => { |
|
if (key === "__v_isReactive" /* ReactiveFlags.IS_REACTIVE */) { |
|
return !isReadonly; |
|
} |
|
else if (key === "__v_isReadonly" /* ReactiveFlags.IS_READONLY */) { |
|
return isReadonly; |
|
} |
|
else if (key === "__v_raw" /* ReactiveFlags.RAW */) { |
|
return target; |
|
} |
|
return Reflect.get(hasOwn(instrumentations, key) && key in target |
|
? instrumentations |
|
: target, key, receiver); |
|
}; |
|
} |
|
const mutableCollectionHandlers = { |
|
get: /*#__PURE__*/ createInstrumentationGetter(false, false) |
|
}; |
|
const shallowCollectionHandlers = { |
|
get: /*#__PURE__*/ createInstrumentationGetter(false, true) |
|
}; |
|
const readonlyCollectionHandlers = { |
|
get: /*#__PURE__*/ createInstrumentationGetter(true, false) |
|
}; |
|
const shallowReadonlyCollectionHandlers = { |
|
get: /*#__PURE__*/ createInstrumentationGetter(true, true) |
|
}; |
|
function checkIdentityKeys(target, has, key) { |
|
const rawKey = toRaw(key); |
|
if (rawKey !== key && has.call(target, rawKey)) { |
|
const type = toRawType(target); |
|
console.warn(`Reactive ${type} contains both the raw and reactive ` + |
|
`versions of the same object${type === `Map` ? ` as keys` : ``}, ` + |
|
`which can lead to inconsistencies. ` + |
|
`Avoid differentiating between the raw and reactive versions ` + |
|
`of an object and only use the reactive version if possible.`); |
|
} |
|
} |
|
|
|
const reactiveMap = new WeakMap(); |
|
const shallowReactiveMap = new WeakMap(); |
|
const readonlyMap = new WeakMap(); |
|
const shallowReadonlyMap = new WeakMap(); |
|
function targetTypeMap(rawType) { |
|
switch (rawType) { |
|
case 'Object': |
|
case 'Array': |
|
return 1 /* TargetType.COMMON */; |
|
case 'Map': |
|
case 'Set': |
|
case 'WeakMap': |
|
case 'WeakSet': |
|
return 2 /* TargetType.COLLECTION */; |
|
default: |
|
return 0 /* TargetType.INVALID */; |
|
} |
|
} |
|
function getTargetType(value) { |
|
return value["__v_skip" /* ReactiveFlags.SKIP */] || !Object.isExtensible(value) |
|
? 0 /* TargetType.INVALID */ |
|
: targetTypeMap(toRawType(value)); |
|
} |
|
function reactive(target) { |
|
// if trying to observe a readonly proxy, return the readonly version. |
|
if (isReadonly(target)) { |
|
return target; |
|
} |
|
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap); |
|
} |
|
/** |
|
* Return a shallowly-reactive copy of the original object, where only the root |
|
* level properties are reactive. It also does not auto-unwrap refs (even at the |
|
* root level). |
|
*/ |
|
function shallowReactive(target) { |
|
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap); |
|
} |
|
/** |
|
* Creates a readonly copy of the original object. Note the returned copy is not |
|
* made reactive, but `readonly` can be called on an already reactive object. |
|
*/ |
|
function readonly(target) { |
|
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap); |
|
} |
|
/** |
|
* Returns a reactive-copy of the original object, where only the root level |
|
* properties are readonly, and does NOT unwrap refs nor recursively convert |
|
* returned properties. |
|
* This is used for creating the props proxy object for stateful components. |
|
*/ |
|
function shallowReadonly(target) { |
|
return createReactiveObject(target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap); |
|
} |
|
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) { |
|
if (!isObject(target)) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
console.warn(`value cannot be made reactive: ${String(target)}`); |
|
} |
|
return target; |
|
} |
|
// target is already a Proxy, return it. |
|
// exception: calling readonly() on a reactive object |
|
if (target["__v_raw" /* ReactiveFlags.RAW */] && |
|
!(isReadonly && target["__v_isReactive" /* ReactiveFlags.IS_REACTIVE */])) { |
|
return target; |
|
} |
|
// target already has corresponding Proxy |
|
const existingProxy = proxyMap.get(target); |
|
if (existingProxy) { |
|
return existingProxy; |
|
} |
|
// only specific value types can be observed. |
|
const targetType = getTargetType(target); |
|
if (targetType === 0 /* TargetType.INVALID */) { |
|
return target; |
|
} |
|
const proxy = new Proxy(target, targetType === 2 /* TargetType.COLLECTION */ ? collectionHandlers : baseHandlers); |
|
proxyMap.set(target, proxy); |
|
return proxy; |
|
} |
|
function isReactive(value) { |
|
if (isReadonly(value)) { |
|
return isReactive(value["__v_raw" /* ReactiveFlags.RAW */]); |
|
} |
|
return !!(value && value["__v_isReactive" /* ReactiveFlags.IS_REACTIVE */]); |
|
} |
|
function isReadonly(value) { |
|
return !!(value && value["__v_isReadonly" /* ReactiveFlags.IS_READONLY */]); |
|
} |
|
function isShallow(value) { |
|
return !!(value && value["__v_isShallow" /* ReactiveFlags.IS_SHALLOW */]); |
|
} |
|
function isProxy(value) { |
|
return isReactive(value) || isReadonly(value); |
|
} |
|
function toRaw(observed) { |
|
const raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */]; |
|
return raw ? toRaw(raw) : observed; |
|
} |
|
function markRaw(value) { |
|
def(value, "__v_skip" /* ReactiveFlags.SKIP */, true); |
|
return value; |
|
} |
|
const toReactive = (value) => isObject(value) ? reactive(value) : value; |
|
const toReadonly = (value) => isObject(value) ? readonly(value) : value; |
|
|
|
function trackRefValue(ref) { |
|
if (shouldTrack && activeEffect) { |
|
ref = toRaw(ref); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
trackEffects(ref.dep || (ref.dep = createDep()), { |
|
target: ref, |
|
type: "get" /* TrackOpTypes.GET */, |
|
key: 'value' |
|
}); |
|
} |
|
else { |
|
trackEffects(ref.dep || (ref.dep = createDep())); |
|
} |
|
} |
|
} |
|
function triggerRefValue(ref, newVal) { |
|
ref = toRaw(ref); |
|
const dep = ref.dep; |
|
if (dep) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
triggerEffects(dep, { |
|
target: ref, |
|
type: "set" /* TriggerOpTypes.SET */, |
|
key: 'value', |
|
newValue: newVal |
|
}); |
|
} |
|
else { |
|
triggerEffects(dep); |
|
} |
|
} |
|
} |
|
function isRef(r) { |
|
return !!(r && r.__v_isRef === true); |
|
} |
|
function ref(value) { |
|
return createRef(value, false); |
|
} |
|
function shallowRef(value) { |
|
return createRef(value, true); |
|
} |
|
function createRef(rawValue, shallow) { |
|
if (isRef(rawValue)) { |
|
return rawValue; |
|
} |
|
return new RefImpl(rawValue, shallow); |
|
} |
|
class RefImpl { |
|
constructor(value, __v_isShallow) { |
|
this.__v_isShallow = __v_isShallow; |
|
this.dep = undefined; |
|
this.__v_isRef = true; |
|
this._rawValue = __v_isShallow ? value : toRaw(value); |
|
this._value = __v_isShallow ? value : toReactive(value); |
|
} |
|
get value() { |
|
trackRefValue(this); |
|
return this._value; |
|
} |
|
set value(newVal) { |
|
const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal); |
|
newVal = useDirectValue ? newVal : toRaw(newVal); |
|
if (hasChanged(newVal, this._rawValue)) { |
|
this._rawValue = newVal; |
|
this._value = useDirectValue ? newVal : toReactive(newVal); |
|
triggerRefValue(this, newVal); |
|
} |
|
} |
|
} |
|
function triggerRef(ref) { |
|
triggerRefValue(ref, (process.env.NODE_ENV !== 'production') ? ref.value : void 0); |
|
} |
|
function unref(ref) { |
|
return isRef(ref) ? ref.value : ref; |
|
} |
|
const shallowUnwrapHandlers = { |
|
get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)), |
|
set: (target, key, value, receiver) => { |
|
const oldValue = target[key]; |
|
if (isRef(oldValue) && !isRef(value)) { |
|
oldValue.value = value; |
|
return true; |
|
} |
|
else { |
|
return Reflect.set(target, key, value, receiver); |
|
} |
|
} |
|
}; |
|
function proxyRefs(objectWithRefs) { |
|
return isReactive(objectWithRefs) |
|
? objectWithRefs |
|
: new Proxy(objectWithRefs, shallowUnwrapHandlers); |
|
} |
|
class CustomRefImpl { |
|
constructor(factory) { |
|
this.dep = undefined; |
|
this.__v_isRef = true; |
|
const { get, set } = factory(() => trackRefValue(this), () => triggerRefValue(this)); |
|
this._get = get; |
|
this._set = set; |
|
} |
|
get value() { |
|
return this._get(); |
|
} |
|
set value(newVal) { |
|
this._set(newVal); |
|
} |
|
} |
|
function customRef(factory) { |
|
return new CustomRefImpl(factory); |
|
} |
|
function toRefs(object) { |
|
if ((process.env.NODE_ENV !== 'production') && !isProxy(object)) { |
|
console.warn(`toRefs() expects a reactive object but received a plain one.`); |
|
} |
|
const ret = isArray(object) ? new Array(object.length) : {}; |
|
for (const key in object) { |
|
ret[key] = toRef(object, key); |
|
} |
|
return ret; |
|
} |
|
class ObjectRefImpl { |
|
constructor(_object, _key, _defaultValue) { |
|
this._object = _object; |
|
this._key = _key; |
|
this._defaultValue = _defaultValue; |
|
this.__v_isRef = true; |
|
} |
|
get value() { |
|
const val = this._object[this._key]; |
|
return val === undefined ? this._defaultValue : val; |
|
} |
|
set value(newVal) { |
|
this._object[this._key] = newVal; |
|
} |
|
get dep() { |
|
return getDepFromReactive(toRaw(this._object), this._key); |
|
} |
|
} |
|
function toRef(object, key, defaultValue) { |
|
const val = object[key]; |
|
return isRef(val) |
|
? val |
|
: new ObjectRefImpl(object, key, defaultValue); |
|
} |
|
|
|
var _a; |
|
class ComputedRefImpl { |
|
constructor(getter, _setter, isReadonly, isSSR) { |
|
this._setter = _setter; |
|
this.dep = undefined; |
|
this.__v_isRef = true; |
|
this[_a] = false; |
|
this._dirty = true; |
|
this.effect = new ReactiveEffect(getter, () => { |
|
if (!this._dirty) { |
|
this._dirty = true; |
|
triggerRefValue(this); |
|
} |
|
}); |
|
this.effect.computed = this; |
|
this.effect.active = this._cacheable = !isSSR; |
|
this["__v_isReadonly" /* ReactiveFlags.IS_READONLY */] = isReadonly; |
|
} |
|
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._cacheable) { |
|
self._dirty = false; |
|
self._value = self.effect.run(); |
|
} |
|
return self._value; |
|
} |
|
set value(newValue) { |
|
this._setter(newValue); |
|
} |
|
} |
|
_a = "__v_isReadonly" /* ReactiveFlags.IS_READONLY */; |
|
function computed$1(getterOrOptions, debugOptions, isSSR = false) { |
|
let getter; |
|
let setter; |
|
const onlyGetter = isFunction(getterOrOptions); |
|
if (onlyGetter) { |
|
getter = getterOrOptions; |
|
setter = (process.env.NODE_ENV !== 'production') |
|
? () => { |
|
console.warn('Write operation failed: computed value is readonly'); |
|
} |
|
: NOOP; |
|
} |
|
else { |
|
getter = getterOrOptions.get; |
|
setter = getterOrOptions.set; |
|
} |
|
const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR); |
|
if ((process.env.NODE_ENV !== 'production') && debugOptions && !isSSR) { |
|
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) { |
|
if (!(process.env.NODE_ENV !== 'production')) |
|
return; |
|
// 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 /* ErrorCodes.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)); |
|
} |
|
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++; |
|
} |
|
else { |
|
normalizedStack.push({ |
|
vnode: currentVNode, |
|
recurseCount: 0 |
|
}); |
|
} |
|
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(` ...`); |
|
} |
|
return res; |
|
} |
|
/* istanbul ignore next */ |
|
function formatProp(key, value, raw) { |
|
if (isString(value)) { |
|
value = JSON.stringify(value); |
|
return raw ? value : [`${key}=${value}`]; |
|
} |
|
else if (typeof value === 'number' || |
|
typeof value === 'boolean' || |
|
value == null) { |
|
return raw ? value : [`${key}=${value}`]; |
|
} |
|
else if (isRef(value)) { |
|
value = formatProp(key, toRaw(value.value), true); |
|
return raw ? value : [`${key}=Ref<`, value, `>`]; |
|
} |
|
else if (isFunction(value)) { |
|
return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; |
|
} |
|
else { |
|
value = toRaw(value); |
|
return raw ? value : [`${key}=`, value]; |
|
} |
|
} |
|
|
|
const ErrorTypeStrings = { |
|
["sp" /* LifecycleHooks.SERVER_PREFETCH */]: 'serverPrefetch hook', |
|
["bc" /* LifecycleHooks.BEFORE_CREATE */]: 'beforeCreate hook', |
|
["c" /* LifecycleHooks.CREATED */]: 'created hook', |
|
["bm" /* LifecycleHooks.BEFORE_MOUNT */]: 'beforeMount hook', |
|
["m" /* LifecycleHooks.MOUNTED */]: 'mounted hook', |
|
["bu" /* LifecycleHooks.BEFORE_UPDATE */]: 'beforeUpdate hook', |
|
["u" /* LifecycleHooks.UPDATED */]: 'updated', |
|
["bum" /* LifecycleHooks.BEFORE_UNMOUNT */]: 'beforeUnmount hook', |
|
["um" /* LifecycleHooks.UNMOUNTED */]: 'unmounted hook', |
|
["a" /* LifecycleHooks.ACTIVATED */]: 'activated hook', |
|
["da" /* LifecycleHooks.DEACTIVATED */]: 'deactivated hook', |
|
["ec" /* LifecycleHooks.ERROR_CAPTURED */]: 'errorCaptured hook', |
|
["rtc" /* LifecycleHooks.RENDER_TRACKED */]: 'renderTracked hook', |
|
["rtg" /* LifecycleHooks.RENDER_TRIGGERED */]: 'renderTriggered hook', |
|
[0 /* ErrorCodes.SETUP_FUNCTION */]: 'setup function', |
|
[1 /* ErrorCodes.RENDER_FUNCTION */]: 'render function', |
|
[2 /* ErrorCodes.WATCH_GETTER */]: 'watcher getter', |
|
[3 /* ErrorCodes.WATCH_CALLBACK */]: 'watcher callback', |
|
[4 /* ErrorCodes.WATCH_CLEANUP */]: 'watcher cleanup function', |
|
[5 /* ErrorCodes.NATIVE_EVENT_HANDLER */]: 'native event handler', |
|
[6 /* ErrorCodes.COMPONENT_EVENT_HANDLER */]: 'component event handler', |
|
[7 /* ErrorCodes.VNODE_HOOK */]: 'vnode hook', |
|
[8 /* ErrorCodes.DIRECTIVE_HOOK */]: 'directive hook', |
|
[9 /* ErrorCodes.TRANSITION_HOOK */]: 'transition hook', |
|
[10 /* ErrorCodes.APP_ERROR_HANDLER */]: 'app errorHandler', |
|
[11 /* ErrorCodes.APP_WARN_HANDLER */]: 'app warnHandler', |
|
[12 /* ErrorCodes.FUNCTION_REF */]: 'ref function', |
|
[13 /* ErrorCodes.ASYNC_COMPONENT_LOADER */]: 'async component loader', |
|
[14 /* ErrorCodes.SCHEDULER */]: 'scheduler flush. This is likely a Vue internals bug. ' + |
|
'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core' |
|
}; |
|
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); |
|
}); |
|
} |
|
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 /* ErrorCodes.APP_ERROR_HANDLER */, [err, exposedInstance, errorInfo]); |
|
return; |
|
} |
|
} |
|
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(); |
|
} |
|
// crash in dev by default so it's more noticeable |
|
if (throwInDev) { |
|
// throw err fixed by xxxxxx 避免 error 导致 小程序 端不可用(比如跳转时报错) |
|
console.error(err); |
|
} |
|
else { |
|
console.error(err); |
|
} |
|
} |
|
else { |
|
// recover in prod to reduce the impact on end-user |
|
console.error(err); |
|
} |
|
} |
|
|
|
let isFlushing = false; |
|
let isFlushPending = false; |
|
// fixed by xxxxxx |
|
const queue = []; |
|
let flushIndex = 0; |
|
const pendingPostFlushCbs = []; |
|
let activePostFlushCbs = null; |
|
let postFlushIndex = 0; |
|
const resolvedPromise = /*#__PURE__*/ Promise.resolve(); |
|
let currentFlushPromise = null; |
|
const RECURSION_LIMIT = 100; |
|
function nextTick$1(fn) { |
|
const p = currentFlushPromise || resolvedPromise; |
|
return fn ? p.then(this ? fn.bind(this) : fn) : p; |
|
} |
|
// #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(id) { |
|
// the start index should be `flushIndex + 1` |
|
let start = flushIndex + 1; |
|
let end = queue.length; |
|
while (start < end) { |
|
const middle = (start + end) >>> 1; |
|
const middleJobId = getId(queue[middle]); |
|
middleJobId < id ? (start = middle + 1) : (end = middle); |
|
} |
|
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)) { |
|
if (job.id == null) { |
|
queue.push(job); |
|
} |
|
else { |
|
queue.splice(findInsertionIndex(job.id), 0, job); |
|
} |
|
queueFlush(); |
|
} |
|
} |
|
function queueFlush() { |
|
if (!isFlushing && !isFlushPending) { |
|
isFlushPending = true; |
|
currentFlushPromise = resolvedPromise.then(flushJobs); |
|
} |
|
} |
|
function hasQueueJob(job) { |
|
return queue.indexOf(job) > -1; |
|
} |
|
function invalidateJob(job) { |
|
const i = queue.indexOf(job); |
|
if (i > flushIndex) { |
|
queue.splice(i, 1); |
|
} |
|
} |
|
function queuePostFlushCb(cb) { |
|
if (!isArray(cb)) { |
|
if (!activePostFlushCbs || |
|
!activePostFlushCbs.includes(cb, cb.allowRecurse ? postFlushIndex + 1 : postFlushIndex)) { |
|
pendingPostFlushCbs.push(cb); |
|
} |
|
} |
|
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 |
|
pendingPostFlushCbs.push(...cb); |
|
} |
|
queueFlush(); |
|
} |
|
function flushPreFlushCbs(seen, |
|
// if currently flushing, skip the current job itself |
|
i = isFlushing ? flushIndex + 1 : 0) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
seen = seen || new Map(); |
|
} |
|
for (; i < queue.length; i++) { |
|
const cb = queue[i]; |
|
if (cb && cb.pre) { |
|
if ((process.env.NODE_ENV !== 'production') && checkRecursiveUpdates(seen, cb)) { |
|
continue; |
|
} |
|
queue.splice(i, 1); |
|
i--; |
|
cb(); |
|
} |
|
} |
|
} |
|
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; |
|
} |
|
activePostFlushCbs = deduped; |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
seen = seen || new Map(); |
|
} |
|
activePostFlushCbs.sort((a, b) => getId(a) - getId(b)); |
|
for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { |
|
if ((process.env.NODE_ENV !== 'production') && |
|
checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex])) { |
|
continue; |
|
} |
|
activePostFlushCbs[postFlushIndex](); |
|
} |
|
activePostFlushCbs = null; |
|
postFlushIndex = 0; |
|
} |
|
} |
|
const getId = (job) => job.id == null ? Infinity : job.id; |
|
const comparator = (a, b) => { |
|
const diff = getId(a) - getId(b); |
|
if (diff === 0) { |
|
if (a.pre && !b.pre) |
|
return -1; |
|
if (b.pre && !a.pre) |
|
return 1; |
|
} |
|
return diff; |
|
}; |
|
function flushJobs(seen) { |
|
isFlushPending = false; |
|
isFlushing = true; |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
seen = seen || new Map(); |
|
} |
|
// 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(comparator); |
|
// conditional usage of checkRecursiveUpdate must be determined out of |
|
// try ... catch block since Rollup by default de-optimizes treeshaking |
|
// inside try-catch. This can leave all warning code unshaked. Although |
|
// they would get eventually shaken by a minifier like terser, some minifiers |
|
// would fail to do that (e.g. https://github.com/evanw/esbuild/issues/1610) |
|
const check = (process.env.NODE_ENV !== 'production') |
|
? (job) => checkRecursiveUpdates(seen, job) |
|
: NOOP; |
|
try { |
|
for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { |
|
const job = queue[flushIndex]; |
|
if (job && job.active !== false) { |
|
if ((process.env.NODE_ENV !== 'production') && check(job)) { |
|
continue; |
|
} |
|
// console.log(`running:`, job.id) |
|
callWithErrorHandling(job, null, 14 /* ErrorCodes.SCHEDULER */); |
|
} |
|
} |
|
} |
|
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); |
|
} |
|
} |
|
} |
|
function checkRecursiveUpdates(seen, fn) { |
|
if (!seen.has(fn)) { |
|
seen.set(fn, 1); |
|
} |
|
else { |
|
const count = seen.get(fn); |
|
if (count > RECURSION_LIMIT) { |
|
const instance = fn.ownerInstance; |
|
const componentName = instance && getComponentName(instance.type); |
|
warn(`Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. ` + |
|
`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.`); |
|
return true; |
|
} |
|
else { |
|
seen.set(fn, count + 1); |
|
} |
|
} |
|
} |
|
|
|
let devtools; |
|
let buffer = []; |
|
let devtoolsNotInstalled = false; |
|
function emit$1(event, ...args) { |
|
if (devtools) { |
|
devtools.emit(event, ...args); |
|
} |
|
else if (!devtoolsNotInstalled) { |
|
buffer.push({ event, args }); |
|
} |
|
} |
|
function setDevtoolsHook(hook, target) { |
|
var _a, _b; |
|
devtools = hook; |
|
if (devtools) { |
|
devtools.enabled = true; |
|
buffer.forEach(({ event, args }) => devtools.emit(event, ...args)); |
|
buffer = []; |
|
} |
|
else if ( |
|
// handle late devtools injection - only do this if we are in an actual |
|
// browser environment to avoid the timer handle stalling test runner exit |
|
// (#4815) |
|
typeof window !== 'undefined' && |
|
// some envs mock window but not fully |
|
// eslint-disable-next-line no-restricted-globals |
|
window.HTMLElement && |
|
// also exclude jsdom |
|
// eslint-disable-next-line no-restricted-globals |
|
!((_b = (_a = window.navigator) === null || _a === void 0 ? void 0 : _a.userAgent) === null || _b === void 0 ? void 0 : _b.includes('jsdom'))) { |
|
const replay = (target.__VUE_DEVTOOLS_HOOK_REPLAY__ = |
|
target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []); |
|
replay.push((newHook) => { |
|
setDevtoolsHook(newHook, target); |
|
}); |
|
// clear buffer after 3s - the user probably doesn't have devtools installed |
|
// at all, and keeping the buffer will cause memory leaks (#4738) |
|
setTimeout(() => { |
|
if (!devtools) { |
|
target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; |
|
devtoolsNotInstalled = true; |
|
buffer = []; |
|
} |
|
}, 3000); |
|
} |
|
else { |
|
// non-browser env, assume not installed |
|
devtoolsNotInstalled = true; |
|
buffer = []; |
|
} |
|
} |
|
function devtoolsInitApp(app, version) { |
|
emit$1("app:init" /* DevtoolsHooks.APP_INIT */, app, version, { |
|
Fragment, |
|
Text, |
|
Comment, |
|
Static |
|
}); |
|
} |
|
const devtoolsComponentAdded = /*#__PURE__*/ createDevtoolsComponentHook("component:added" /* DevtoolsHooks.COMPONENT_ADDED */); |
|
const devtoolsComponentUpdated = |
|
/*#__PURE__*/ createDevtoolsComponentHook("component:updated" /* DevtoolsHooks.COMPONENT_UPDATED */); |
|
const _devtoolsComponentRemoved = /*#__PURE__*/ createDevtoolsComponentHook("component:removed" /* DevtoolsHooks.COMPONENT_REMOVED */); |
|
const devtoolsComponentRemoved = (component) => { |
|
if (devtools && |
|
typeof devtools.cleanupBuffer === 'function' && |
|
// remove the component if it wasn't buffered |
|
!devtools.cleanupBuffer(component)) { |
|
_devtoolsComponentRemoved(component); |
|
} |
|
}; |
|
function createDevtoolsComponentHook(hook) { |
|
return (component) => { |
|
emit$1(hook, component.appContext.app, component.uid, |
|
// fixed by xxxxxx |
|
// 为 0 是 App,无 parent 是 Page 指向 App |
|
component.uid === 0 |
|
? undefined |
|
: component.parent |
|
? component.parent.uid |
|
: 0, component); |
|
}; |
|
} |
|
const devtoolsPerfStart = /*#__PURE__*/ createDevtoolsPerformanceHook("perf:start" /* DevtoolsHooks.PERFORMANCE_START */); |
|
const devtoolsPerfEnd = /*#__PURE__*/ createDevtoolsPerformanceHook("perf:end" /* DevtoolsHooks.PERFORMANCE_END */); |
|
function createDevtoolsPerformanceHook(hook) { |
|
return (component, type, time) => { |
|
emit$1(hook, component.appContext.app, component.uid, component, type, time); |
|
}; |
|
} |
|
function devtoolsComponentEmit(component, event, params) { |
|
emit$1("component:emit" /* DevtoolsHooks.COMPONENT_EMIT */, component.appContext.app, component, event, params); |
|
} |
|
|
|
function emit(instance, event, ...rawArgs) { |
|
if (instance.isUnmounted) |
|
return; |
|
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(`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(`Invalid event arguments: event validation failed for event "${event}".`); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
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 => (isString(a) ? a.trim() : a)); |
|
} |
|
if (number) { |
|
args = rawArgs.map(looseToNumber); |
|
} |
|
} |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsComponentEmit(instance, event, args); |
|
} |
|
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}".`); |
|
} |
|
} |
|
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 /* ErrorCodes.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 /* ErrorCodes.COMPONENT_EVENT_HANDLER */, args); |
|
} |
|
} |
|
function normalizeEmitsOptions(comp, appContext, asMixin = false) { |
|
const cache = appContext.emitsCache; |
|
const cached = cache.get(comp); |
|
if (cached !== undefined) { |
|
return cached; |
|
} |
|
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); |
|
} |
|
} |
|
if (!raw && !hasExtends) { |
|
if (isObject(comp)) { |
|
cache.set(comp, null); |
|
} |
|
return null; |
|
} |
|
if (isArray(raw)) { |
|
raw.forEach(key => (normalized[key] = null)); |
|
} |
|
else { |
|
extend(normalized, raw); |
|
} |
|
if (isObject(comp)) { |
|
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)); |
|
} |
|
|
|
/** |
|
* mark the current rendering instance for asset resolution (e.g. |
|
* resolveComponent, resolveDirective) during render |
|
*/ |
|
let currentRenderingInstance = null; |
|
let currentScopeId = null; |
|
/** |
|
* Note: rendering calls maybe nested. The function returns the parent rendering |
|
* instance if present, which should be restored after the render is done: |
|
* |
|
* ```js |
|
* const prev = setCurrentRenderingInstance(i) |
|
* // ...render |
|
* setCurrentRenderingInstance(prev) |
|
* ``` |
|
*/ |
|
function setCurrentRenderingInstance(instance) { |
|
const prev = currentRenderingInstance; |
|
currentRenderingInstance = instance; |
|
currentScopeId = (instance && instance.type.__scopeId) || null; |
|
return prev; |
|
} |
|
/** |
|
* Only for backwards compat |
|
* @private |
|
*/ |
|
const withScopeId = (_id) => withCtx; |
|
/** |
|
* Wrap a slot function to memoize current rendering instance |
|
* @private compiler helper |
|
*/ |
|
function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot // false only |
|
) { |
|
if (!ctx) |
|
return fn; |
|
// already normalized |
|
if (fn._n) { |
|
return fn; |
|
} |
|
const renderFnWithContext = (...args) => { |
|
// If a user calls a compiled slot inside a template expression (#1745), it |
|
// can mess up block tracking, so by default we disable block tracking and |
|
// force bail out when invoking a compiled slot (indicated by the ._d flag). |
|
// This isn't necessary if rendering a compiled `<slot>`, so we flip the |
|
// ._d flag off when invoking the wrapped fn inside `renderSlot`. |
|
if (renderFnWithContext._d) { |
|
setBlockTracking(-1); |
|
} |
|
const prevInstance = setCurrentRenderingInstance(ctx); |
|
let res; |
|
try { |
|
res = fn(...args); |
|
} |
|
finally { |
|
setCurrentRenderingInstance(prevInstance); |
|
if (renderFnWithContext._d) { |
|
setBlockTracking(1); |
|
} |
|
} |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsComponentUpdated(ctx); |
|
} |
|
return res; |
|
}; |
|
// mark normalized to avoid duplicated wrapping |
|
renderFnWithContext._n = true; |
|
// mark this as compiled by default |
|
// this is used in vnode.ts -> normalizeChildren() to set the slot |
|
// rendering flag. |
|
renderFnWithContext._c = true; |
|
// disable block tracking by default |
|
renderFnWithContext._d = true; |
|
return renderFnWithContext; |
|
} |
|
function markAttrsAccessed() { |
|
} |
|
|
|
function provide(key, value) { |
|
if (!currentInstance) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`provide() can only be used inside setup().`); |
|
} |
|
} |
|
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; |
|
// 当实例为 App 时,同步到全局 provide |
|
if (currentInstance.type.mpType === 'app') { |
|
currentInstance.appContext.app.provide(key, value); |
|
} |
|
} |
|
} |
|
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 instance 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]; |
|
} |
|
else if (arguments.length > 1) { |
|
return treatDefaultAsFactory && isFunction(defaultValue) |
|
? defaultValue.call(instance.proxy) |
|
: defaultValue; |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`injection "${String(key)}" not found.`); |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`inject() can only be used inside setup() or functional components.`); |
|
} |
|
} |
|
|
|
// Simple effect. |
|
function watchEffect(effect, options) { |
|
return doWatch(effect, null, options); |
|
} |
|
function watchPostEffect(effect, options) { |
|
return doWatch(effect, null, (process.env.NODE_ENV !== 'production') ? Object.assign(Object.assign({}, options), { flush: 'post' }) : { flush: 'post' }); |
|
} |
|
function watchSyncEffect(effect, options) { |
|
return doWatch(effect, null, (process.env.NODE_ENV !== 'production') ? Object.assign(Object.assign({}, options), { flush: 'sync' }) : { flush: 'sync' }); |
|
} |
|
// 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) { |
|
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.`); |
|
} |
|
if (deep !== undefined) { |
|
warn(`watch() "deep" option is only respected when using the ` + |
|
`watch(source, callback, options?) signature.`); |
|
} |
|
} |
|
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.`); |
|
}; |
|
const instance = getCurrentScope() === (currentInstance === null || currentInstance === void 0 ? void 0 : currentInstance.scope) ? currentInstance : null; |
|
// const instance = currentInstance |
|
let getter; |
|
let forceTrigger = false; |
|
let isMultiSource = false; |
|
if (isRef(source)) { |
|
getter = () => source.value; |
|
forceTrigger = isShallow(source); |
|
} |
|
else if (isReactive(source)) { |
|
getter = () => source; |
|
deep = true; |
|
} |
|
else if (isArray(source)) { |
|
isMultiSource = true; |
|
forceTrigger = source.some(s => isReactive(s) || isShallow(s)); |
|
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 /* ErrorCodes.WATCH_GETTER */); |
|
} |
|
else { |
|
(process.env.NODE_ENV !== 'production') && warnInvalidSource(s); |
|
} |
|
}); |
|
} |
|
else if (isFunction(source)) { |
|
if (cb) { |
|
// getter with cb |
|
getter = () => callWithErrorHandling(source, instance, 2 /* ErrorCodes.WATCH_GETTER */); |
|
} |
|
else { |
|
// no cb -> simple effect |
|
getter = () => { |
|
if (instance && instance.isUnmounted) { |
|
return; |
|
} |
|
if (cleanup) { |
|
cleanup(); |
|
} |
|
return callWithAsyncErrorHandling(source, instance, 3 /* ErrorCodes.WATCH_CALLBACK */, [onCleanup]); |
|
}; |
|
} |
|
} |
|
else { |
|
getter = NOOP; |
|
(process.env.NODE_ENV !== 'production') && warnInvalidSource(source); |
|
} |
|
if (cb && deep) { |
|
const baseGetter = getter; |
|
getter = () => traverse(baseGetter()); |
|
} |
|
let cleanup; |
|
let onCleanup = (fn) => { |
|
cleanup = effect.onStop = () => { |
|
callWithErrorHandling(fn, instance, 4 /* ErrorCodes.WATCH_CLEANUP */); |
|
}; |
|
}; |
|
let oldValue = isMultiSource |
|
? new Array(source.length).fill(INITIAL_WATCHER_VALUE) |
|
: INITIAL_WATCHER_VALUE; |
|
const job = () => { |
|
if (!effect.active) { |
|
return; |
|
} |
|
if (cb) { |
|
// watch(source, cb) |
|
const newValue = effect.run(); |
|
if (deep || |
|
forceTrigger || |
|
(isMultiSource |
|
? newValue.some((v, i) => hasChanged(v, oldValue[i])) |
|
: hasChanged(newValue, oldValue)) || |
|
(false )) { |
|
// cleanup before running cb again |
|
if (cleanup) { |
|
cleanup(); |
|
} |
|
callWithAsyncErrorHandling(cb, instance, 3 /* ErrorCodes.WATCH_CALLBACK */, [ |
|
newValue, |
|
// pass undefined as the old value when it's changed for the first time |
|
oldValue === INITIAL_WATCHER_VALUE |
|
? undefined |
|
: isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE |
|
? [] |
|
: oldValue, |
|
onCleanup |
|
]); |
|
oldValue = newValue; |
|
} |
|
} |
|
else { |
|
// watchEffect |
|
effect.run(); |
|
} |
|
}; |
|
// 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; // the scheduler function gets called directly |
|
} |
|
else if (flush === 'post') { |
|
scheduler = () => queuePostRenderEffect$1(job, instance && instance.suspense); |
|
} |
|
else { |
|
// default: 'pre' |
|
job.pre = true; |
|
if (instance) |
|
job.id = instance.uid; |
|
scheduler = () => queueJob(job); |
|
} |
|
const effect = new ReactiveEffect(getter, scheduler); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
effect.onTrack = onTrack; |
|
effect.onTrigger = onTrigger; |
|
} |
|
// initial run |
|
if (cb) { |
|
if (immediate) { |
|
job(); |
|
} |
|
else { |
|
oldValue = effect.run(); |
|
} |
|
} |
|
else if (flush === 'post') { |
|
queuePostRenderEffect$1(effect.run.bind(effect), instance && instance.suspense); |
|
} |
|
else { |
|
effect.run(); |
|
} |
|
const unwatch = () => { |
|
effect.stop(); |
|
if (instance && instance.scope) { |
|
remove(instance.scope.effects, effect); |
|
} |
|
}; |
|
return unwatch; |
|
} |
|
// this.$watch |
|
function instanceWatch(source, value, options) { |
|
const publicThis = this.proxy; |
|
const getter = isString(source) |
|
? source.includes('.') |
|
? createPathGetter(publicThis, source) |
|
: () => publicThis[source] |
|
: source.bind(publicThis, publicThis); |
|
let cb; |
|
if (isFunction(value)) { |
|
cb = value; |
|
} |
|
else { |
|
cb = value.handler; |
|
options = value; |
|
} |
|
const cur = currentInstance; |
|
setCurrentInstance(this); |
|
const res = doWatch(getter, cb.bind(publicThis), options); |
|
if (cur) { |
|
setCurrentInstance(cur); |
|
} |
|
else { |
|
unsetCurrentInstance(); |
|
} |
|
return res; |
|
} |
|
function createPathGetter(ctx, path) { |
|
const segments = path.split('.'); |
|
return () => { |
|
let cur = ctx; |
|
for (let i = 0; i < segments.length && cur; i++) { |
|
cur = cur[segments[i]]; |
|
} |
|
return cur; |
|
}; |
|
} |
|
function traverse(value, seen) { |
|
if (!isObject(value) || value["__v_skip" /* ReactiveFlags.SKIP */]) { |
|
return value; |
|
} |
|
seen = seen || new Set(); |
|
if (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); |
|
} |
|
} |
|
else if (isSet(value) || isMap(value)) { |
|
value.forEach((v) => { |
|
traverse(v, seen); |
|
}); |
|
} |
|
else if (isPlainObject(value)) { |
|
for (const key in value) { |
|
traverse(value[key], seen); |
|
} |
|
} |
|
return value; |
|
} |
|
|
|
// 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" /* LifecycleHooks.ACTIVATED */, target); |
|
} |
|
function onDeactivated(hook, target) { |
|
registerKeepAliveHook(hook, "da" /* LifecycleHooks.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; |
|
} |
|
return 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 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) { |
|
// fixed by xxxxxx |
|
if (isRootHook(type)) { |
|
target = target.root; |
|
} |
|
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); // fixed by xxxxxx |
|
const res = callWithAsyncErrorHandling(hook, target, type, args); |
|
unsetCurrentInstance(); |
|
resetTracking(); |
|
return res; |
|
}); |
|
if (prepend) { |
|
hooks.unshift(wrappedHook); |
|
} |
|
else { |
|
hooks.push(wrappedHook); |
|
} |
|
return wrappedHook; |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
// fixed by xxxxxx |
|
const apiName = toHandlerKey((ErrorTypeStrings[type] || type.replace(/^on/, '')).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().` + |
|
(``)); |
|
} |
|
} |
|
const createHook = (lifecycle) => (hook, target = currentInstance) => |
|
// post-create lifecycle registrations are noops during SSR (except for serverPrefetch) |
|
(!isInSSRComponentSetup || lifecycle === "sp" /* LifecycleHooks.SERVER_PREFETCH */) && |
|
injectHook(lifecycle, (...args) => hook(...args), target); |
|
const onBeforeMount = createHook("bm" /* LifecycleHooks.BEFORE_MOUNT */); |
|
const onMounted = createHook("m" /* LifecycleHooks.MOUNTED */); |
|
const onBeforeUpdate = createHook("bu" /* LifecycleHooks.BEFORE_UPDATE */); |
|
const onUpdated = createHook("u" /* LifecycleHooks.UPDATED */); |
|
const onBeforeUnmount = createHook("bum" /* LifecycleHooks.BEFORE_UNMOUNT */); |
|
const onUnmounted = createHook("um" /* LifecycleHooks.UNMOUNTED */); |
|
const onServerPrefetch = createHook("sp" /* LifecycleHooks.SERVER_PREFETCH */); |
|
const onRenderTriggered = createHook("rtg" /* LifecycleHooks.RENDER_TRIGGERED */); |
|
const onRenderTracked = createHook("rtc" /* LifecycleHooks.RENDER_TRACKED */); |
|
function onErrorCaptured(hook, target = currentInstance) { |
|
injectHook("ec" /* LifecycleHooks.ERROR_CAPTURED */, hook, 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] |
|
]) |
|
*/ |
|
function validateDirectiveName(name) { |
|
if (isBuiltInDirective(name)) { |
|
warn('Do not use built-in directive ids as custom directive id: ' + name); |
|
} |
|
} |
|
/** |
|
* Adds directives to a VNode. |
|
*/ |
|
function withDirectives(vnode, directives) { |
|
const internalInstance = currentRenderingInstance; |
|
if (internalInstance === null) { |
|
(process.env.NODE_ENV !== 'production') && warn(`withDirectives can only be used inside render functions.`); |
|
return vnode; |
|
} |
|
const instance = getExposeProxy(internalInstance) || |
|
internalInstance.proxy; |
|
const bindings = vnode.dirs || (vnode.dirs = []); |
|
for (let i = 0; i < directives.length; i++) { |
|
let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]; |
|
if (dir) { |
|
if (isFunction(dir)) { |
|
dir = { |
|
mounted: dir, |
|
updated: dir |
|
}; |
|
} |
|
if (dir.deep) { |
|
traverse(value); |
|
} |
|
bindings.push({ |
|
dir, |
|
instance, |
|
value, |
|
oldValue: void 0, |
|
arg, |
|
modifiers |
|
}); |
|
} |
|
} |
|
return vnode; |
|
} |
|
|
|
const COMPONENTS = 'components'; |
|
const DIRECTIVES = 'directives'; |
|
/** |
|
* @private |
|
*/ |
|
function resolveComponent(name, maybeSelfReference) { |
|
return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name; |
|
} |
|
const NULL_DYNAMIC_COMPONENT = Symbol(); |
|
/** |
|
* @private |
|
*/ |
|
function resolveDirective(name) { |
|
return resolveAsset(DIRECTIVES, name); |
|
} |
|
// implementation |
|
function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { |
|
const instance = currentRenderingInstance || currentInstance; |
|
if (instance) { |
|
const Component = instance.type; |
|
// explicit self name has highest priority |
|
if (type === COMPONENTS) { |
|
const selfName = getComponentName(Component, false /* do not include inferred name to avoid breaking existing code */); |
|
if (selfName && |
|
(selfName === name || |
|
selfName === camelize(name) || |
|
selfName === capitalize(camelize(name)))) { |
|
return Component; |
|
} |
|
} |
|
const res = |
|
// local registration |
|
// check instance[type] first which is resolved for options API |
|
resolve(instance[type] || Component[type], name) || |
|
// global registration |
|
resolve(instance.appContext[type], name); |
|
if (!res && maybeSelfReference) { |
|
// fallback to implicit self-reference |
|
return Component; |
|
} |
|
if ((process.env.NODE_ENV !== 'production') && warnMissing && !res) { |
|
const extra = type === COMPONENTS |
|
? `\nIf this is a native custom element, make sure to exclude it from ` + |
|
`component resolution via compilerOptions.isCustomElement.` |
|
: ``; |
|
warn(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); |
|
} |
|
return res; |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`resolve${capitalize(type.slice(0, -1))} ` + |
|
`can only be used in render() or setup().`); |
|
} |
|
} |
|
function resolve(registry, name) { |
|
return (registry && |
|
(registry[name] || |
|
registry[camelize(name)] || |
|
registry[capitalize(camelize(name))])); |
|
} |
|
|
|
/** |
|
* For prefixing keys in v-on="obj" with "on" |
|
* @private |
|
*/ |
|
function toHandlers(obj, preserveCaseIfNecessary) { |
|
const ret = {}; |
|
if ((process.env.NODE_ENV !== 'production') && !isObject(obj)) { |
|
warn(`v-on with no argument expects an object value.`); |
|
return ret; |
|
} |
|
for (const key in obj) { |
|
ret[preserveCaseIfNecessary && /[A-Z]/.test(key) |
|
? `on:${key}` |
|
: toHandlerKey(key)] = obj[key]; |
|
} |
|
return ret; |
|
} |
|
|
|
/** |
|
* #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. |
|
*/ |
|
const getPublicInstance = (i) => { |
|
if (!i) |
|
return null; |
|
if (isStatefulComponent(i)) |
|
return getExposeProxy(i) || i.proxy; |
|
return getPublicInstance(i.parent); |
|
}; |
|
const publicPropertiesMap = |
|
// Move PURE marker to new line to workaround compiler discarding it |
|
// due to type annotation |
|
/*#__PURE__*/ extend(Object.create(null), { |
|
$: i => i, |
|
// fixed by xxxxxx vue-i18n 在 dev 模式,访问了 $el,故模拟一个假的 |
|
// $el: i => i.vnode.el, |
|
$el: i => i.__$el || (i.__$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 => i.f || (i.f = () => queueJob(i.update)), |
|
// $nextTick: i => i.n || (i.n = nextTick.bind(i.proxy!)),// fixed by xxxxxx |
|
$watch: i => (__VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP) |
|
}); |
|
const isReservedPrefix = (key) => key === '_' || key === '$'; |
|
const hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); |
|
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; |
|
} |
|
// data / props / ctx |
|
// This getter gets called for every property access on the render context |
|
// during render and is a major hotspot. The most expensive part of this |
|
// is the multiple hasOwn() calls. It's much faster to do a simple property |
|
// access on a plain object, so we use an accessCache object (with null |
|
// prototype) to memoize what access type a key corresponds to. |
|
let normalizedProps; |
|
if (key[0] !== '$') { |
|
const n = accessCache[key]; |
|
if (n !== undefined) { |
|
switch (n) { |
|
case 1 /* AccessTypes.SETUP */: |
|
return setupState[key]; |
|
case 2 /* AccessTypes.DATA */: |
|
return data[key]; |
|
case 4 /* AccessTypes.CONTEXT */: |
|
return ctx[key]; |
|
case 3 /* AccessTypes.PROPS */: |
|
return props[key]; |
|
// default: just fallthrough |
|
} |
|
} |
|
else if (hasSetupBinding(setupState, key)) { |
|
accessCache[key] = 1 /* AccessTypes.SETUP */; |
|
return setupState[key]; |
|
} |
|
else if (data !== EMPTY_OBJ && hasOwn(data, key)) { |
|
accessCache[key] = 2 /* AccessTypes.DATA */; |
|
return data[key]; |
|
} |
|
else if ( |
|
// only cache other properties when instance has declared (thus stable) |
|
// props |
|
(normalizedProps = instance.propsOptions[0]) && |
|
hasOwn(normalizedProps, key)) { |
|
accessCache[key] = 3 /* AccessTypes.PROPS */; |
|
return props[key]; |
|
} |
|
else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { |
|
accessCache[key] = 4 /* AccessTypes.CONTEXT */; |
|
return ctx[key]; |
|
} |
|
else if (!__VUE_OPTIONS_API__ || shouldCacheAccess) { |
|
accessCache[key] = 0 /* AccessTypes.OTHER */; |
|
} |
|
} |
|
const publicGetter = publicPropertiesMap[key]; |
|
let cssModule, globalProperties; |
|
// public $xxx properties |
|
if (publicGetter) { |
|
if (key === '$attrs') { |
|
track(instance, "get" /* TrackOpTypes.GET */, key); |
|
(process.env.NODE_ENV !== 'production') && markAttrsAccessed(); |
|
} |
|
return publicGetter(instance); |
|
} |
|
else if ( |
|
// css module (injected by vue-loader) |
|
(cssModule = type.__cssModules) && |
|
(cssModule = cssModule[key])) { |
|
return cssModule; |
|
} |
|
else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { |
|
// user may set custom properties to `this` that start with `$` |
|
accessCache[key] = 4 /* AccessTypes.CONTEXT */; |
|
return ctx[key]; |
|
} |
|
else if ( |
|
// global properties |
|
((globalProperties = appContext.config.globalProperties), |
|
hasOwn(globalProperties, key))) { |
|
{ |
|
return globalProperties[key]; |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production') && |
|
currentRenderingInstance && |
|
(!isString(key) || |
|
// #1091 avoid internal isRef/isVNode checks on component instance leading |
|
// to infinite warning loop |
|
key.indexOf('__v') !== 0)) { |
|
if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { |
|
warn(`Property ${JSON.stringify(key)} must be accessed via $data because it starts with a reserved ` + |
|
`character ("$" or "_") and is not proxied on the render context.`); |
|
} |
|
else if (instance === currentRenderingInstance) { |
|
warn(`Property ${JSON.stringify(key)} was accessed during render ` + |
|
`but is not defined on instance.`); |
|
} |
|
} |
|
}, |
|
set({ _: instance }, key, value) { |
|
const { data, setupState, ctx } = instance; |
|
if (hasSetupBinding(setupState, key)) { |
|
setupState[key] = value; |
|
return true; |
|
} |
|
else if ((process.env.NODE_ENV !== 'production') && |
|
setupState.__isScriptSetup && |
|
hasOwn(setupState, key)) { |
|
warn(`Cannot mutate <script setup> binding "${key}" from Options API.`); |
|
return false; |
|
} |
|
else if (data !== EMPTY_OBJ && hasOwn(data, key)) { |
|
data[key] = value; |
|
return true; |
|
} |
|
else if (hasOwn(instance.props, key)) { |
|
(process.env.NODE_ENV !== 'production') && warn(`Attempting to mutate prop "${key}". Props are readonly.`); |
|
return false; |
|
} |
|
if (key[0] === '$' && key.slice(1) in instance) { |
|
(process.env.NODE_ENV !== 'production') && |
|
warn(`Attempting to mutate public property "${key}". ` + |
|
`Properties starting with $ are reserved and readonly.`); |
|
return false; |
|
} |
|
else { |
|
if ((process.env.NODE_ENV !== 'production') && key in instance.appContext.config.globalProperties) { |
|
Object.defineProperty(ctx, key, { |
|
enumerable: true, |
|
configurable: true, |
|
value |
|
}); |
|
} |
|
else { |
|
ctx[key] = value; |
|
} |
|
} |
|
return true; |
|
}, |
|
has({ _: { data, setupState, accessCache, ctx, appContext, propsOptions } }, key) { |
|
let normalizedProps; |
|
return (!!accessCache[key] || |
|
(data !== EMPTY_OBJ && hasOwn(data, key)) || |
|
hasSetupBinding(setupState, key) || |
|
((normalizedProps = propsOptions[0]) && hasOwn(normalizedProps, key)) || |
|
hasOwn(ctx, key) || |
|
hasOwn(publicPropertiesMap, key) || |
|
hasOwn(appContext.config.globalProperties, key)); |
|
}, |
|
defineProperty(target, key, descriptor) { |
|
if (descriptor.get != null) { |
|
// invalidate key cache of a getter based property #5417 |
|
target._.accessCache[key] = 0; |
|
} |
|
else if (hasOwn(descriptor, 'value')) { |
|
this.set(target, key, descriptor.value, null); |
|
} |
|
return Reflect.defineProperty(target, key, descriptor); |
|
} |
|
}; |
|
if ((process.env.NODE_ENV !== 'production') && !false) { |
|
PublicInstanceProxyHandlers.ownKeys = (target) => { |
|
warn(`Avoid app logic that relies on enumerating keys on a component instance. ` + |
|
`The keys will be empty in production mode to avoid performance overhead.`); |
|
return Reflect.ownKeys(target); |
|
}; |
|
} |
|
// dev only |
|
// In dev mode, the proxy target exposes the same properties as seen on `this` |
|
// for easier console inspection. In prod mode it will be an empty object so |
|
// these properties definitions can be skipped. |
|
function createDevRenderContext(instance) { |
|
const target = {}; |
|
// expose internal instance for proxy handlers |
|
Object.defineProperty(target, `_`, { |
|
configurable: true, |
|
enumerable: false, |
|
get: () => instance |
|
}); |
|
// expose public properties |
|
Object.keys(publicPropertiesMap).forEach(key => { |
|
Object.defineProperty(target, key, { |
|
configurable: true, |
|
enumerable: false, |
|
get: () => publicPropertiesMap[key](instance), |
|
// intercepted by the proxy so no need for implementation, |
|
// but needed to prevent set errors |
|
set: NOOP |
|
}); |
|
}); |
|
return target; |
|
} |
|
// dev only |
|
function exposePropsOnRenderContext(instance) { |
|
const { ctx, propsOptions: [propsOptions] } = instance; |
|
if (propsOptions) { |
|
Object.keys(propsOptions).forEach(key => { |
|
Object.defineProperty(ctx, key, { |
|
enumerable: true, |
|
configurable: true, |
|
get: () => instance.props[key], |
|
set: NOOP |
|
}); |
|
}); |
|
} |
|
} |
|
// dev only |
|
function exposeSetupStateOnRenderContext(instance) { |
|
const { ctx, setupState } = instance; |
|
Object.keys(toRaw(setupState)).forEach(key => { |
|
if (!setupState.__isScriptSetup) { |
|
if (isReservedPrefix(key[0])) { |
|
warn(`setup() return property ${JSON.stringify(key)} should not start with "$" or "_" ` + |
|
`which are reserved prefixes for Vue internals.`); |
|
return; |
|
} |
|
Object.defineProperty(ctx, key, { |
|
enumerable: true, |
|
configurable: true, |
|
get: () => setupState[key], |
|
set: NOOP |
|
}); |
|
} |
|
}); |
|
} |
|
|
|
function createDuplicateChecker() { |
|
const cache = Object.create(null); |
|
return (type, key) => { |
|
if (cache[key]) { |
|
warn(`${type} property "${key}" is already defined in ${cache[key]}.`); |
|
} |
|
else { |
|
cache[key] = type; |
|
} |
|
}; |
|
} |
|
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" /* LifecycleHooks.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" /* OptionTypes.PROPS */, key); |
|
} |
|
} |
|
} |
|
// 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" /* OptionTypes.METHODS */, key); |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`Method "${key}" has type "${typeof methodHandler}" in the component definition. ` + |
|
`Did you reference the function correctly?`); |
|
} |
|
} |
|
} |
|
if (dataOptions) { |
|
if ((process.env.NODE_ENV !== 'production') && !isFunction(dataOptions)) { |
|
warn(`The data option must be a function. ` + |
|
`Plain object usage is no longer supported.`); |
|
} |
|
const data = dataOptions.call(publicThis, publicThis); |
|
if ((process.env.NODE_ENV !== 'production') && isPromise(data)) { |
|
warn(`data() returned a Promise - note data() cannot be async; If you ` + |
|
`intend to perform data fetching before component renders, use ` + |
|
`async setup() + <Suspense>.`); |
|
} |
|
if (!isObject(data)) { |
|
(process.env.NODE_ENV !== 'production') && warn(`data() should return an object.`); |
|
} |
|
else { |
|
instance.data = reactive(data); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
for (const key in data) { |
|
checkDuplicateProperties("Data" /* OptionTypes.DATA */, key); |
|
// expose data on ctx during dev |
|
if (!isReservedPrefix(key[0])) { |
|
Object.defineProperty(ctx, key, { |
|
configurable: true, |
|
enumerable: true, |
|
get: () => data[key], |
|
set: NOOP |
|
}); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
// 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(`Computed property "${key}" has no getter.`); |
|
} |
|
const set = !isFunction(opt) && isFunction(opt.set) |
|
? opt.set.bind(publicThis) |
|
: (process.env.NODE_ENV !== 'production') |
|
? () => { |
|
warn(`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" /* OptionTypes.COMPUTED */, key); |
|
} |
|
} |
|
} |
|
if (watchOptions) { |
|
for (const key in watchOptions) { |
|
createWatcher(watchOptions[key], ctx, publicThis, key); |
|
} |
|
} |
|
// 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" /* LifecycleHooks.CREATED */); |
|
} |
|
}; |
|
} |
|
else { |
|
if (created) { |
|
callHook(created, instance, "c" /* LifecycleHooks.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 if (!instance.exposed) { |
|
instance.exposed = {}; |
|
} |
|
} |
|
// 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 { |
|
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(`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; |
|
} |
|
} |
|
else { |
|
ctx[key] = injected; |
|
} |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
checkDuplicateProperties("Inject" /* OptionTypes.INJECT */, key); |
|
} |
|
} |
|
} |
|
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(`Invalid watch handler specified by key "${raw}"`, handler); |
|
} |
|
} |
|
else if (isFunction(raw)) { |
|
watch(getter, raw.bind(publicThis)); |
|
} |
|
else if (isObject(raw)) { |
|
if (isArray(raw)) { |
|
raw.forEach(r => createWatcher(r, ctx, publicThis, key)); |
|
} |
|
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(`Invalid watch handler specified by key "${raw.handler}"`, handler); |
|
} |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`Invalid watch option: "${key}"`, raw); |
|
} |
|
} |
|
/** |
|
* 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; |
|
} |
|
} |
|
else { |
|
resolved = {}; |
|
if (globalMixins.length) { |
|
globalMixins.forEach(m => mergeOptions(resolved, m, optionMergeStrategies, true)); |
|
} |
|
mergeOptions(resolved, base, optionMergeStrategies); |
|
} |
|
if (isObject(base)) { |
|
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(`"expose" option is ignored when declared in mixins or extends. ` + |
|
`It should only be declared in the base component itself.`); |
|
} |
|
else { |
|
const strat = internalOptionMergeStrats[key] || (strats && strats[key]); |
|
to[key] = strat ? strat(to[key], from[key]) : from[key]; |
|
} |
|
} |
|
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 (!to) { |
|
return from; |
|
} |
|
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 raw; |
|
} |
|
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]); |
|
} |
|
return merged; |
|
} |
|
|
|
function initProps(instance, rawProps, isStateful, // result of bitwise flag comparison |
|
isSSR = false) { |
|
const props = {}; |
|
const attrs = {}; |
|
// def(attrs, InternalObjectKey, 1) // fixed by xxxxxx |
|
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); |
|
} |
|
if (isStateful) { |
|
// stateful |
|
instance.props = isSSR ? props : shallowReactive(props); |
|
} |
|
else { |
|
if (!instance.type.props) { |
|
// functional w/ optional props, props === attrs |
|
instance.props = attrs; |
|
} |
|
else { |
|
// functional w/ declared props |
|
instance.props = props; |
|
} |
|
} |
|
instance.attrs = attrs; |
|
} |
|
function isInHmrContext(instance) { |
|
while (instance) { |
|
if (instance.type.__hmrId) |
|
return true; |
|
instance = instance.parent; |
|
} |
|
} |
|
function updateProps(instance, rawProps, rawPrevProps, optimized) { |
|
const { props, attrs, vnode: { patchFlag } } = instance; |
|
const rawCurrentProps = toRaw(props); |
|
const [options] = instance.propsOptions; |
|
let hasAttrsChanged = false; |
|
if ( |
|
// always force full diff in dev |
|
// - #1942 if hmr is enabled with sfc component |
|
// - vite#872 non-sfc component used by sfc component |
|
!((process.env.NODE_ENV !== 'production') && isInHmrContext(instance)) && |
|
(optimized || patchFlag > 0) && |
|
!(patchFlag & 16 /* PatchFlags.FULL_PROPS */)) { |
|
if (patchFlag & 8 /* PatchFlags.PROPS */) { |
|
// Compiler-generated props & no keys change, just set the updated |
|
// the props. |
|
const propsToUpdate = instance.vnode.dynamicProps; |
|
for (let i = 0; i < propsToUpdate.length; i++) { |
|
let key = propsToUpdate[i]; |
|
// skip if the prop key is a declared emit event listener |
|
if (isEmitListener(instance.emitsOptions, key)) { |
|
continue; |
|
} |
|
// PROPS flag guarantees rawProps to be non-null |
|
const value = rawProps[key]; |
|
if (options) { |
|
// attr / props separation was done on init and will be consistent |
|
// in this code path, so just check if attrs have it. |
|
if (hasOwn(attrs, key)) { |
|
if (value !== attrs[key]) { |
|
attrs[key] = value; |
|
hasAttrsChanged = true; |
|
} |
|
} |
|
else { |
|
const camelizedKey = camelize(key); |
|
props[camelizedKey] = resolvePropValue(options, rawCurrentProps, camelizedKey, value, instance, false /* isAbsent */); |
|
} |
|
} |
|
else { |
|
if (value !== attrs[key]) { |
|
attrs[key] = value; |
|
hasAttrsChanged = true; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else { |
|
// full props update. |
|
if (setFullProps(instance, rawProps, props, attrs)) { |
|
hasAttrsChanged = true; |
|
} |
|
// in case of dynamic props, check if we need to delete keys from |
|
// the props object |
|
let kebabKey; |
|
for (const key in rawCurrentProps) { |
|
if (!rawProps || |
|
// for camelCase |
|
(!hasOwn(rawProps, key) && |
|
// it's possible the original props was passed in as kebab-case |
|
// and converted to camelCase (#955) |
|
((kebabKey = hyphenate(key)) === key || !hasOwn(rawProps, kebabKey)))) { |
|
if (options) { |
|
if (rawPrevProps && |
|
// for camelCase |
|
(rawPrevProps[key] !== undefined || |
|
// for kebab-case |
|
rawPrevProps[kebabKey] !== undefined)) { |
|
props[key] = resolvePropValue(options, rawCurrentProps, key, undefined, instance, true /* isAbsent */); |
|
} |
|
} |
|
else { |
|
delete props[key]; |
|
} |
|
} |
|
} |
|
// in the case of functional component w/o props declaration, props and |
|
// attrs point to the same object so it should already have been updated. |
|
if (attrs !== rawCurrentProps) { |
|
for (const key in attrs) { |
|
if (!rawProps || |
|
(!hasOwn(rawProps, key) && |
|
(!false ))) { |
|
delete attrs[key]; |
|
hasAttrsChanged = true; |
|
} |
|
} |
|
} |
|
} |
|
// trigger updates for $attrs in case it's used in component slots |
|
if (hasAttrsChanged) { |
|
trigger(instance, "set" /* TriggerOpTypes.SET */, '$attrs'); |
|
} |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
validateProps(rawProps || {}, props, instance); |
|
} |
|
} |
|
function setFullProps(instance, rawProps, props, attrs) { |
|
const [options, needCastKeys] = instance.propsOptions; |
|
let hasAttrsChanged = false; |
|
let rawCastValues; |
|
if (rawProps) { |
|
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)))) { |
|
if (!needCastKeys || !needCastKeys.includes(camelKey)) { |
|
props[camelKey] = value; |
|
} |
|
else { |
|
(rawCastValues || (rawCastValues = {}))[camelKey] = value; |
|
} |
|
} |
|
else if (!isEmitListener(instance.emitsOptions, key)) { |
|
if (!(key in attrs) || 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, castValues[key], instance, !hasOwn(castValues, key)); |
|
} |
|
} |
|
return hasAttrsChanged; |
|
} |
|
function resolvePropValue(options, props, key, value, instance, isAbsent) { |
|
const opt = options[key]; |
|
if (opt != null) { |
|
const hasDefault = hasOwn(opt, 'default'); |
|
// default values |
|
if (hasDefault && value === undefined) { |
|
const defaultValue = opt.default; |
|
if (opt.type !== Function && isFunction(defaultValue)) { |
|
const { propsDefaults } = instance; |
|
if (key in propsDefaults) { |
|
value = propsDefaults[key]; |
|
} |
|
else { |
|
setCurrentInstance(instance); |
|
value = propsDefaults[key] = defaultValue.call(null, props); |
|
unsetCurrentInstance(); |
|
} |
|
} |
|
else { |
|
value = defaultValue; |
|
} |
|
} |
|
// boolean casting |
|
if (opt[0 /* BooleanFlags.shouldCast */]) { |
|
if (isAbsent && !hasDefault) { |
|
value = false; |
|
} |
|
else if (opt[1 /* BooleanFlags.shouldCastTrue */] && |
|
(value === '' || value === hyphenate(key))) { |
|
value = true; |
|
} |
|
} |
|
} |
|
return value; |
|
} |
|
function normalizePropsOptions(comp, appContext, asMixin = false) { |
|
const cache = appContext.propsCache; |
|
const cached = cache.get(comp); |
|
if (cached) { |
|
return cached; |
|
} |
|
const raw = comp.props; |
|
const normalized = {}; |
|
const needCastKeys = []; |
|
// apply mixin/extends props |
|
let hasExtends = false; |
|
if (__VUE_OPTIONS_API__ && !isFunction(comp)) { |
|
const extendProps = (raw) => { |
|
hasExtends = true; |
|
const [props, keys] = normalizePropsOptions(raw, appContext, true); |
|
extend(normalized, props); |
|
if (keys) |
|
needCastKeys.push(...keys); |
|
}; |
|
if (!asMixin && appContext.mixins.length) { |
|
appContext.mixins.forEach(extendProps); |
|
} |
|
if (comp.extends) { |
|
extendProps(comp.extends); |
|
} |
|
if (comp.mixins) { |
|
comp.mixins.forEach(extendProps); |
|
} |
|
} |
|
if (!raw && !hasExtends) { |
|
if (isObject(comp)) { |
|
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]); |
|
} |
|
const normalizedKey = camelize(raw[i]); |
|
if (validatePropName(normalizedKey)) { |
|
normalized[normalizedKey] = EMPTY_OBJ; |
|
} |
|
} |
|
} |
|
else if (raw) { |
|
if ((process.env.NODE_ENV !== 'production') && !isObject(raw)) { |
|
warn(`invalid props options`, raw); |
|
} |
|
for (const key in raw) { |
|
const normalizedKey = camelize(key); |
|
if (validatePropName(normalizedKey)) { |
|
const opt = raw[key]; |
|
const prop = (normalized[normalizedKey] = |
|
isArray(opt) || isFunction(opt) ? { type: opt } : Object.assign({}, opt)); |
|
if (prop) { |
|
const booleanIndex = getTypeIndex(Boolean, prop.type); |
|
const stringIndex = getTypeIndex(String, prop.type); |
|
prop[0 /* BooleanFlags.shouldCast */] = booleanIndex > -1; |
|
prop[1 /* BooleanFlags.shouldCastTrue */] = |
|
stringIndex < 0 || booleanIndex < stringIndex; |
|
// if the prop needs boolean casting or default value |
|
if (booleanIndex > -1 || hasOwn(prop, 'default')) { |
|
needCastKeys.push(normalizedKey); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
const res = [normalized, needCastKeys]; |
|
if (isObject(comp)) { |
|
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.`); |
|
} |
|
return false; |
|
} |
|
// use function string name to check type constructors |
|
// so that it works across vms / iframes. |
|
function getType(ctor) { |
|
const match = ctor && ctor.toString().match(/^\s*(function|class) (\w+)/); |
|
return match ? match[2] : ctor === null ? 'null' : ''; |
|
} |
|
function isSameType(a, b) { |
|
return getType(a) === getType(b); |
|
} |
|
function getTypeIndex(type, expectedTypes) { |
|
if (isArray(expectedTypes)) { |
|
return expectedTypes.findIndex(t => isSameType(t, type)); |
|
} |
|
else if (isFunction(expectedTypes)) { |
|
return isSameType(expectedTypes, type) ? 0 : -1; |
|
} |
|
return -1; |
|
} |
|
/** |
|
* dev only |
|
*/ |
|
function validateProps(rawProps, props, instance) { |
|
const resolvedValues = toRaw(props); |
|
const options = instance.propsOptions[0]; |
|
for (const key in options) { |
|
let opt = options[key]; |
|
if (opt == null) |
|
continue; |
|
validateProp(key, resolvedValues[key], opt, !hasOwn(rawProps, key) && !hasOwn(rawProps, hyphenate(key))); |
|
} |
|
} |
|
/** |
|
* dev only |
|
*/ |
|
function validateProp(name, value, prop, isAbsent) { |
|
const { type, required, validator } = prop; |
|
// required! |
|
if (required && isAbsent) { |
|
warn('Missing required prop: "' + name + '"'); |
|
return; |
|
} |
|
// missing but optional |
|
if (value == null && !prop.required) { |
|
return; |
|
} |
|
// type check |
|
if (type != null && type !== true) { |
|
let isValid = false; |
|
const types = isArray(type) ? type : [type]; |
|
const expectedTypes = []; |
|
// value is valid as long as one of the specified types match |
|
for (let i = 0; i < types.length && !isValid; i++) { |
|
const { valid, expectedType } = assertType(value, types[i]); |
|
expectedTypes.push(expectedType || ''); |
|
isValid = valid; |
|
} |
|
if (!isValid) { |
|
warn(getInvalidTypeMessage(name, value, expectedTypes)); |
|
return; |
|
} |
|
} |
|
// custom validator |
|
if (validator && !validator(value)) { |
|
warn('Invalid prop: custom validator check failed for prop "' + name + '".'); |
|
} |
|
} |
|
const isSimpleType = /*#__PURE__*/ makeMap('String,Number,Boolean,Function,Symbol,BigInt'); |
|
/** |
|
* dev only |
|
*/ |
|
function assertType(value, type) { |
|
let valid; |
|
const expectedType = getType(type); |
|
if (isSimpleType(expectedType)) { |
|
const t = typeof value; |
|
valid = t === expectedType.toLowerCase(); |
|
// for primitive wrapper objects |
|
if (!valid && t === 'object') { |
|
valid = value instanceof type; |
|
} |
|
} |
|
else if (expectedType === 'Object') { |
|
valid = isObject(value); |
|
} |
|
else if (expectedType === 'Array') { |
|
valid = isArray(value); |
|
} |
|
else if (expectedType === 'null') { |
|
valid = value === null; |
|
} |
|
else { |
|
valid = value instanceof type; |
|
} |
|
return { |
|
valid, |
|
expectedType |
|
}; |
|
} |
|
/** |
|
* dev only |
|
*/ |
|
function getInvalidTypeMessage(name, value, expectedTypes) { |
|
let message = `Invalid prop: type check failed for prop "${name}".` + |
|
` Expected ${expectedTypes.map(capitalize).join(' | ')}`; |
|
const expectedType = expectedTypes[0]; |
|
const receivedType = toRawType(value); |
|
const expectedValue = styleValue(value, expectedType); |
|
const receivedValue = styleValue(value, receivedType); |
|
// check if we need to specify expected value |
|
if (expectedTypes.length === 1 && |
|
isExplicable(expectedType) && |
|
!isBoolean(expectedType, receivedType)) { |
|
message += ` with value ${expectedValue}`; |
|
} |
|
message += `, got ${receivedType} `; |
|
// check if we need to specify received value |
|
if (isExplicable(receivedType)) { |
|
message += `with value ${receivedValue}.`; |
|
} |
|
return message; |
|
} |
|
/** |
|
* dev only |
|
*/ |
|
function styleValue(value, type) { |
|
if (type === 'String') { |
|
return `"${value}"`; |
|
} |
|
else if (type === 'Number') { |
|
return `${Number(value)}`; |
|
} |
|
else { |
|
return `${value}`; |
|
} |
|
} |
|
/** |
|
* dev only |
|
*/ |
|
function isExplicable(type) { |
|
const explicitTypes = ['string', 'number', 'boolean']; |
|
return explicitTypes.some(elem => type.toLowerCase() === elem); |
|
} |
|
/** |
|
* dev only |
|
*/ |
|
function isBoolean(...args) { |
|
return args.some(elem => elem.toLowerCase() === 'boolean'); |
|
} |
|
|
|
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() |
|
}; |
|
} |
|
let uid$1 = 0; |
|
function createAppAPI(render, // fixed by xxxxxx |
|
hydrate) { |
|
return function createApp(rootComponent, rootProps = null) { |
|
if (!isFunction(rootComponent)) { |
|
rootComponent = Object.assign({}, rootComponent); |
|
} |
|
if (rootProps != null && !isObject(rootProps)) { |
|
(process.env.NODE_ENV !== 'production') && warn(`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$1++, |
|
_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(`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); |
|
} |
|
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]; |
|
} |
|
if ((process.env.NODE_ENV !== 'production') && context.directives[name]) { |
|
warn(`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(`App already provides property with key "${String(key)}". ` + |
|
`It will be overwritten with the new value.`); |
|
} |
|
context.provides[key] = value; |
|
return app; |
|
} |
|
}); |
|
// fixed by xxxxxx |
|
// if (false) { |
|
// installAppCompatProperties(app, context, render) |
|
// } |
|
return app; |
|
}; |
|
} |
|
|
|
/* eslint-disable no-restricted-globals */ |
|
let supported; |
|
let perf; |
|
function startMeasure(instance, type) { |
|
if (instance.appContext.config.performance && isSupported()) { |
|
perf.mark(`vue-${type}-${instance.uid}`); |
|
} |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsPerfStart(instance, type, isSupported() ? perf.now() : Date.now()); |
|
} |
|
} |
|
function endMeasure(instance, type) { |
|
if (instance.appContext.config.performance && isSupported()) { |
|
const startTag = `vue-${type}-${instance.uid}`; |
|
const endTag = startTag + `:end`; |
|
perf.mark(endTag); |
|
perf.measure(`<${formatComponentName(instance, instance.type)}> ${type}`, startTag, endTag); |
|
perf.clearMarks(startTag); |
|
perf.clearMarks(endTag); |
|
} |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsPerfEnd(instance, type, isSupported() ? perf.now() : Date.now()); |
|
} |
|
} |
|
function isSupported() { |
|
if (supported !== undefined) { |
|
return supported; |
|
} |
|
if (typeof window !== 'undefined' && window.performance) { |
|
supported = true; |
|
perf = window.performance; |
|
} |
|
else { |
|
supported = false; |
|
} |
|
return supported; |
|
} |
|
|
|
const queuePostRenderEffect$1 = queuePostFlushCb; |
|
|
|
const isTeleport = (type) => type.__isTeleport; |
|
|
|
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); |
|
const Static = Symbol((process.env.NODE_ENV !== 'production') ? 'Static' : undefined); |
|
let currentBlock = null; |
|
// Whether we should be tracking dynamic child nodes inside a block. |
|
// Only tracks when this value is > 0 |
|
// We are not using a simple boolean because this value may need to be |
|
// incremented/decremented by nested usage of v-once (see below) |
|
let isBlockTreeEnabled = 1; |
|
/** |
|
* Block tracking sometimes needs to be disabled, for example during the |
|
* creation of a tree that needs to be cached by v-once. The compiler generates |
|
* code like this: |
|
* |
|
* ``` js |
|
* _cache[1] || ( |
|
* setBlockTracking(-1), |
|
* _cache[1] = createVNode(...), |
|
* setBlockTracking(1), |
|
* _cache[1] |
|
* ) |
|
* ``` |
|
* |
|
* @private |
|
*/ |
|
function setBlockTracking(value) { |
|
isBlockTreeEnabled += value; |
|
} |
|
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, ref_key, ref_for }) => { |
|
return (ref != null |
|
? isString(ref) || isRef(ref) || isFunction(ref) |
|
? { i: currentRenderingInstance, r: ref, k: ref_key, f: !!ref_for } |
|
: ref |
|
: null); |
|
}; |
|
function createBaseVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, shapeFlag = type === Fragment ? 0 : 1 /* ShapeFlags.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, |
|
ctx: currentRenderingInstance |
|
}; |
|
if (needFullChildrenNormalization) { |
|
normalizeChildren(vnode, children); |
|
} |
|
else if (children) { |
|
// compiled element vnode - if children is passed, only possible types are |
|
// string or Array. |
|
vnode.shapeFlag |= isString(children) |
|
? 8 /* ShapeFlags.TEXT_CHILDREN */ |
|
: 16 /* ShapeFlags.ARRAY_CHILDREN */; |
|
} |
|
// validate key |
|
if ((process.env.NODE_ENV !== 'production') && vnode.key !== vnode.key) { |
|
warn(`VNode created with invalid key (NaN). VNode type:`, vnode.type); |
|
} |
|
// track vnode for block tree |
|
if (isBlockTreeEnabled > 0 && |
|
// 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 /* ShapeFlags.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 /* PatchFlags.HYDRATE_EVENTS */) { |
|
currentBlock.push(vnode); |
|
} |
|
return vnode; |
|
} |
|
const createVNode$1 = ((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(`Invalid vnode type when creating vnode: ${type}.`); |
|
} |
|
type = Comment; |
|
} |
|
if (isVNode(type)) { |
|
// createVNode receiving an existing vnode. This happens in cases like |
|
// <component :is="vnode"/> |
|
// #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); |
|
} |
|
if (isBlockTreeEnabled > 0 && !isBlockNode && currentBlock) { |
|
if (cloned.shapeFlag & 6 /* ShapeFlags.COMPONENT */) { |
|
currentBlock[currentBlock.indexOf(type)] = cloned; |
|
} |
|
else { |
|
currentBlock.push(cloned); |
|
} |
|
} |
|
cloned.patchFlag |= -2 /* PatchFlags.BAIL */; |
|
return cloned; |
|
} |
|
// class component normalization. |
|
if (isClassComponent(type)) { |
|
type = type.__vccOpts; |
|
} |
|
// 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); |
|
} |
|
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); |
|
} |
|
} |
|
// encode the vnode type information into a bitmap |
|
const shapeFlag = isString(type) |
|
? 1 /* ShapeFlags.ELEMENT */ |
|
: isTeleport(type) |
|
? 64 /* ShapeFlags.TELEPORT */ |
|
: isObject(type) |
|
? 4 /* ShapeFlags.STATEFUL_COMPONENT */ |
|
: isFunction(type) |
|
? 2 /* ShapeFlags.FUNCTIONAL_COMPONENT */ |
|
: 0; |
|
if ((process.env.NODE_ENV !== 'production') && shapeFlag & 4 /* ShapeFlags.STATEFUL_COMPONENT */ && isProxy(type)) { |
|
type = toRaw(type); |
|
warn(`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 createBaseVNode(type, props, children, patchFlag, dynamicProps, shapeFlag, isBlockNode, true); |
|
} |
|
function guardReactiveProps(props) { |
|
if (!props) |
|
return null; |
|
return isProxy(props) || InternalObjectKey in props |
|
? extend({}, props) |
|
: props; |
|
} |
|
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 <component :is="vnode" ref="extra"/> |
|
// 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 /* PatchFlags.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: preserve flag for fragments since they use the flag for children |
|
// fast paths only. |
|
patchFlag: extraProps && vnode.type !== Fragment |
|
? patchFlag === -1 // hoisted node |
|
? 16 /* PatchFlags.FULL_PROPS */ |
|
: patchFlag | 16 /* PatchFlags.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, |
|
ctx: vnode.ctx, |
|
ce: vnode.ce |
|
}; |
|
return cloned; |
|
} |
|
/** |
|
* 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; |
|
} |
|
/** |
|
* @private |
|
*/ |
|
function createTextVNode(text = ' ', flag = 0) { |
|
return createVNode$1(Text, null, text, flag); |
|
} |
|
function normalizeChildren(vnode, children) { |
|
let type = 0; |
|
const { shapeFlag } = vnode; |
|
if (children == null) { |
|
children = null; |
|
} |
|
else if (isArray(children)) { |
|
type = 16 /* ShapeFlags.ARRAY_CHILDREN */; |
|
} |
|
else if (typeof children === 'object') { |
|
if (shapeFlag & (1 /* ShapeFlags.ELEMENT */ | 64 /* ShapeFlags.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; |
|
} |
|
else { |
|
type = 32 /* ShapeFlags.SLOTS_CHILDREN */; |
|
const slotFlag = children._; |
|
if (!slotFlag && !(InternalObjectKey in children)) { |
|
children._ctx = currentRenderingInstance; |
|
} |
|
else if (slotFlag === 3 /* SlotFlags.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 /* SlotFlags.STABLE */) { |
|
children._ = 1 /* SlotFlags.STABLE */; |
|
} |
|
else { |
|
children._ = 2 /* SlotFlags.DYNAMIC */; |
|
vnode.patchFlag |= 1024 /* PatchFlags.DYNAMIC_SLOTS */; |
|
} |
|
} |
|
} |
|
} |
|
else if (isFunction(children)) { |
|
children = { default: children, _ctx: currentRenderingInstance }; |
|
type = 32 /* ShapeFlags.SLOTS_CHILDREN */; |
|
} |
|
else { |
|
children = String(children); |
|
// force teleport children to array so it can be moved around |
|
if (shapeFlag & 64 /* ShapeFlags.TELEPORT */) { |
|
type = 16 /* ShapeFlags.ARRAY_CHILDREN */; |
|
children = [createTextVNode(children)]; |
|
} |
|
else { |
|
type = 8 /* ShapeFlags.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]); |
|
} |
|
} |
|
else if (key === 'style') { |
|
ret.style = normalizeStyle([ret.style, toMerge.style]); |
|
} |
|
else if (isOn(key)) { |
|
const existing = ret[key]; |
|
const incoming = toMerge[key]; |
|
if (incoming && |
|
existing !== incoming && |
|
!(isArray(existing) && existing.includes(incoming))) { |
|
ret[key] = existing |
|
? [].concat(existing, incoming) |
|
: incoming; |
|
} |
|
} |
|
else if (key !== '') { |
|
ret[key] = toMerge[key]; |
|
} |
|
} |
|
} |
|
return ret; |
|
} |
|
|
|
const emptyAppContext = createAppContext(); |
|
let uid = 0; |
|
function createComponentInstance(vnode, parent, suspense) { |
|
const type = vnode.type; |
|
// inherit parent app context - or - if root, adopt from root vnode |
|
const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext; |
|
const instance = { |
|
uid: uid++, |
|
vnode, |
|
type, |
|
parent, |
|
appContext, |
|
root: null, |
|
next: null, |
|
subTree: null, |
|
effect: null, |
|
update: null, |
|
scope: new EffectScope(true /* detached */), |
|
render: null, |
|
proxy: null, |
|
exposed: null, |
|
exposeProxy: null, |
|
withProxy: null, |
|
provides: parent ? parent.provides : Object.create(appContext.provides), |
|
accessCache: null, |
|
renderCache: [], |
|
// local resolved assets |
|
components: null, |
|
directives: null, |
|
// resolved props and emits options |
|
propsOptions: normalizePropsOptions(type, appContext), |
|
emitsOptions: normalizeEmitsOptions(type, appContext), |
|
// emit |
|
emit: null, |
|
emitted: null, |
|
// props default value |
|
propsDefaults: EMPTY_OBJ, |
|
// inheritAttrs |
|
inheritAttrs: type.inheritAttrs, |
|
// state |
|
ctx: EMPTY_OBJ, |
|
data: EMPTY_OBJ, |
|
props: EMPTY_OBJ, |
|
attrs: EMPTY_OBJ, |
|
slots: EMPTY_OBJ, |
|
refs: EMPTY_OBJ, |
|
setupState: EMPTY_OBJ, |
|
setupContext: null, |
|
// suspense related |
|
suspense, |
|
suspenseId: suspense ? suspense.pendingId : 0, |
|
asyncDep: null, |
|
asyncResolved: false, |
|
// lifecycle hooks |
|
// not using enums here because it results in computed properties |
|
isMounted: false, |
|
isUnmounted: false, |
|
isDeactivated: false, |
|
bc: null, |
|
c: null, |
|
bm: null, |
|
m: null, |
|
bu: null, |
|
u: null, |
|
um: null, |
|
bum: null, |
|
da: null, |
|
a: null, |
|
rtg: null, |
|
rtc: null, |
|
ec: null, |
|
sp: null |
|
}; |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
instance.ctx = createDevRenderContext(instance); |
|
} |
|
else { |
|
instance.ctx = { _: instance }; |
|
} |
|
instance.root = parent ? parent.root : instance; |
|
instance.emit = emit.bind(null, instance); |
|
// apply custom element special handling |
|
if (vnode.ce) { |
|
vnode.ce(instance); |
|
} |
|
return instance; |
|
} |
|
let currentInstance = null; |
|
const getCurrentInstance = () => currentInstance || currentRenderingInstance; |
|
const setCurrentInstance = (instance) => { |
|
currentInstance = instance; |
|
instance.scope.on(); |
|
}; |
|
const unsetCurrentInstance = () => { |
|
currentInstance && currentInstance.scope.off(); |
|
currentInstance = null; |
|
}; |
|
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component'); |
|
function validateComponentName(name, config) { |
|
const appIsNativeTag = config.isNativeTag || NO; |
|
if (isBuiltInTag(name) || appIsNativeTag(name)) { |
|
warn('Do not use built-in or reserved HTML elements as component id: ' + name); |
|
} |
|
} |
|
function isStatefulComponent(instance) { |
|
return instance.vnode.shapeFlag & 4 /* ShapeFlags.STATEFUL_COMPONENT */; |
|
} |
|
let isInSSRComponentSetup = false; |
|
function setupComponent(instance, isSSR = false) { |
|
isInSSRComponentSetup = isSSR; |
|
// fixed by xxxxxx |
|
const { props /*, children*/ } = instance.vnode; |
|
const isStateful = isStatefulComponent(instance); |
|
initProps(instance, props, isStateful, isSSR); |
|
// initSlots(instance, children) // fixed by xxxxxx |
|
const setupResult = isStateful |
|
? setupStatefulComponent(instance, isSSR) |
|
: undefined; |
|
isInSSRComponentSetup = false; |
|
return setupResult; |
|
} |
|
function setupStatefulComponent(instance, isSSR) { |
|
const Component = instance.type; |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
if (Component.name) { |
|
validateComponentName(Component.name, instance.appContext.config); |
|
} |
|
if (Component.components) { |
|
const names = Object.keys(Component.components); |
|
for (let i = 0; i < names.length; i++) { |
|
validateComponentName(names[i], instance.appContext.config); |
|
} |
|
} |
|
if (Component.directives) { |
|
const names = Object.keys(Component.directives); |
|
for (let i = 0; i < names.length; i++) { |
|
validateDirectiveName(names[i]); |
|
} |
|
} |
|
if (Component.compilerOptions && isRuntimeOnly()) { |
|
warn(`"compilerOptions" is only supported when using a build of Vue that ` + |
|
`includes the runtime compiler. Since you are using a runtime-only ` + |
|
`build, the options should be passed via your build tool config instead.`); |
|
} |
|
} |
|
// 0. create render proxy property access cache |
|
instance.accessCache = Object.create(null); |
|
// 1. create public instance / render proxy |
|
// also mark it raw so it's never observed |
|
instance.proxy = markRaw(new Proxy(instance.ctx, PublicInstanceProxyHandlers)); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
exposePropsOnRenderContext(instance); |
|
} |
|
// 2. call setup() |
|
const { setup } = Component; |
|
if (setup) { |
|
const setupContext = (instance.setupContext = |
|
setup.length > 1 ? createSetupContext(instance) : null); |
|
setCurrentInstance(instance); |
|
pauseTracking(); |
|
const setupResult = callWithErrorHandling(setup, instance, 0 /* ErrorCodes.SETUP_FUNCTION */, [(process.env.NODE_ENV !== 'production') ? shallowReadonly(instance.props) : instance.props, setupContext]); |
|
resetTracking(); |
|
unsetCurrentInstance(); |
|
if (isPromise(setupResult)) { |
|
setupResult.then(unsetCurrentInstance, unsetCurrentInstance); |
|
// fixed by xxxxxx |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`setup() returned a Promise, but the version of Vue you are using ` + |
|
`does not support it yet.`); |
|
} |
|
} |
|
else { |
|
handleSetupResult(instance, setupResult, isSSR); |
|
} |
|
} |
|
else { |
|
finishComponentSetup(instance, isSSR); |
|
} |
|
} |
|
function handleSetupResult(instance, setupResult, isSSR) { |
|
if (isFunction(setupResult)) { |
|
// setup returned an inline render function |
|
{ |
|
instance.render = setupResult; |
|
} |
|
} |
|
else if (isObject(setupResult)) { |
|
if ((process.env.NODE_ENV !== 'production') && isVNode(setupResult)) { |
|
warn(`setup() should not return VNodes directly - ` + |
|
`return a render function instead.`); |
|
} |
|
// setup returned bindings. |
|
// assuming a render function compiled from template is present. |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
instance.devtoolsRawSetupState = setupResult; |
|
} |
|
instance.setupState = proxyRefs(setupResult); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
exposeSetupStateOnRenderContext(instance); |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production') && setupResult !== undefined) { |
|
warn(`setup() should return an object. Received: ${setupResult === null ? 'null' : typeof setupResult}`); |
|
} |
|
finishComponentSetup(instance, isSSR); |
|
} |
|
let compile; |
|
// dev only |
|
const isRuntimeOnly = () => !compile; |
|
function finishComponentSetup(instance, isSSR, skipOptions) { |
|
const Component = instance.type; |
|
// template / render function normalization |
|
// could be already set when returned from setup() |
|
if (!instance.render) { |
|
instance.render = (Component.render || NOOP); |
|
} |
|
// support for 2.x options |
|
if (__VUE_OPTIONS_API__ && !(false )) { |
|
setCurrentInstance(instance); |
|
pauseTracking(); |
|
applyOptions$1(instance); |
|
resetTracking(); |
|
unsetCurrentInstance(); |
|
} |
|
// warn missing template/render |
|
// the runtime compilation of template in SSR is done by server-render |
|
if ((process.env.NODE_ENV !== 'production') && !Component.render && instance.render === NOOP && !isSSR) { |
|
/* istanbul ignore if */ |
|
if (Component.template) { |
|
warn(`Component provided template option but ` + |
|
`runtime compilation is not supported in this build of Vue.` + |
|
(` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".` |
|
) /* should not happen */); |
|
} |
|
else { |
|
warn(`Component is missing template or render function.`); |
|
} |
|
} |
|
} |
|
function createAttrsProxy(instance) { |
|
return new Proxy(instance.attrs, (process.env.NODE_ENV !== 'production') |
|
? { |
|
get(target, key) { |
|
track(instance, "get" /* TrackOpTypes.GET */, '$attrs'); |
|
return target[key]; |
|
}, |
|
set() { |
|
warn(`setupContext.attrs is readonly.`); |
|
return false; |
|
}, |
|
deleteProperty() { |
|
warn(`setupContext.attrs is readonly.`); |
|
return false; |
|
} |
|
} |
|
: { |
|
get(target, key) { |
|
track(instance, "get" /* TrackOpTypes.GET */, '$attrs'); |
|
return target[key]; |
|
} |
|
}); |
|
} |
|
function createSetupContext(instance) { |
|
const expose = exposed => { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
if (instance.exposed) { |
|
warn(`expose() should be called only once per setup().`); |
|
} |
|
if (exposed != null) { |
|
let exposedType = typeof exposed; |
|
if (exposedType === 'object') { |
|
if (isArray(exposed)) { |
|
exposedType = 'array'; |
|
} |
|
else if (isRef(exposed)) { |
|
exposedType = 'ref'; |
|
} |
|
} |
|
if (exposedType !== 'object') { |
|
warn(`expose() should be passed a plain object, received ${exposedType}.`); |
|
} |
|
} |
|
} |
|
instance.exposed = exposed || {}; |
|
}; |
|
let attrs; |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
// We use getters in dev in case libs like test-utils overwrite instance |
|
// properties (overwrites should not be done in prod) |
|
return Object.freeze({ |
|
get attrs() { |
|
return attrs || (attrs = createAttrsProxy(instance)); |
|
}, |
|
get slots() { |
|
return shallowReadonly(instance.slots); |
|
}, |
|
get emit() { |
|
return (event, ...args) => instance.emit(event, ...args); |
|
}, |
|
expose |
|
}); |
|
} |
|
else { |
|
return { |
|
get attrs() { |
|
return attrs || (attrs = createAttrsProxy(instance)); |
|
}, |
|
slots: instance.slots, |
|
emit: instance.emit, |
|
expose |
|
}; |
|
} |
|
} |
|
function getExposeProxy(instance) { |
|
if (instance.exposed) { |
|
return (instance.exposeProxy || |
|
(instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), { |
|
get(target, key) { |
|
if (key in target) { |
|
return target[key]; |
|
} |
|
// fixed by xxxxxx 框架内部需要访问很多非 public 属性,暂不做限制 |
|
return instance.proxy[key]; |
|
// else if (key in publicPropertiesMap) { |
|
// return publicPropertiesMap[key](instance) |
|
// } |
|
}, |
|
has(target, key) { |
|
return key in target || key in publicPropertiesMap; |
|
} |
|
}))); |
|
} |
|
} |
|
const classifyRE = /(?:^|[-_])(\w)/g; |
|
const classify = (str) => str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, ''); |
|
function getComponentName(Component, includeInferred = true) { |
|
return isFunction(Component) |
|
? Component.displayName || Component.name |
|
: Component.name || (includeInferred && Component.__name); |
|
} |
|
/* istanbul ignore next */ |
|
function formatComponentName(instance, Component, isRoot = false) { |
|
let name = getComponentName(Component); |
|
if (!name && Component.__file) { |
|
const match = Component.__file.match(/([^/\\]+)\.\w+$/); |
|
if (match) { |
|
name = match[1]; |
|
} |
|
} |
|
if (!name && instance && instance.parent) { |
|
// try to infer the name based on reverse resolution |
|
const inferFromRegistry = (registry) => { |
|
for (const key in registry) { |
|
if (registry[key] === Component) { |
|
return key; |
|
} |
|
} |
|
}; |
|
name = |
|
inferFromRegistry(instance.components || |
|
instance.parent.type.components) || inferFromRegistry(instance.appContext.components); |
|
} |
|
return name ? classify(name) : isRoot ? `App` : `Anonymous`; |
|
} |
|
function isClassComponent(value) { |
|
return isFunction(value) && '__vccOpts' in value; |
|
} |
|
|
|
const computed = ((getterOrOptions, debugOptions) => { |
|
// @ts-ignore |
|
return computed$1(getterOrOptions, debugOptions, isInSSRComponentSetup); |
|
}); |
|
|
|
// dev only |
|
const warnRuntimeUsage = (method) => warn(`${method}() is a compiler-hint helper that is only usable inside ` + |
|
`<script setup> of a single file component. Its arguments should be ` + |
|
`compiled away and passing it at runtime has no effect.`); |
|
// implementation |
|
function defineProps() { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warnRuntimeUsage(`defineProps`); |
|
} |
|
return null; |
|
} |
|
// implementation |
|
function defineEmits() { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warnRuntimeUsage(`defineEmits`); |
|
} |
|
return null; |
|
} |
|
/** |
|
* Vue `<script setup>` compiler macro for declaring a component's exposed |
|
* instance properties when it is accessed by a parent component via template |
|
* refs. |
|
* |
|
* `<script setup>` components are closed by default - i.e. variables inside |
|
* the `<script setup>` scope is not exposed to parent unless explicitly exposed |
|
* via `defineExpose`. |
|
* |
|
* This is only usable inside `<script setup>`, is compiled away in the |
|
* output and should **not** be actually called at runtime. |
|
*/ |
|
function defineExpose(exposed) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warnRuntimeUsage(`defineExpose`); |
|
} |
|
} |
|
/** |
|
* Vue `<script setup>` compiler macro for providing props default values when |
|
* using type-based `defineProps` declaration. |
|
* |
|
* Example usage: |
|
* ```ts |
|
* withDefaults(defineProps<{ |
|
* size?: number |
|
* labels?: string[] |
|
* }>(), { |
|
* size: 3, |
|
* labels: () => ['default label'] |
|
* }) |
|
* ``` |
|
* |
|
* This is only usable inside `<script setup>`, is compiled away in the output |
|
* and should **not** be actually called at runtime. |
|
*/ |
|
function withDefaults(props, defaults) { |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
warnRuntimeUsage(`withDefaults`); |
|
} |
|
return null; |
|
} |
|
function useSlots() { |
|
return getContext().slots; |
|
} |
|
function useAttrs() { |
|
return getContext().attrs; |
|
} |
|
function getContext() { |
|
const i = getCurrentInstance(); |
|
if ((process.env.NODE_ENV !== 'production') && !i) { |
|
warn(`useContext() called without active instance.`); |
|
} |
|
return i.setupContext || (i.setupContext = createSetupContext(i)); |
|
} |
|
/** |
|
* Runtime helper for merging default declarations. Imported by compiled code |
|
* only. |
|
* @internal |
|
*/ |
|
function mergeDefaults(raw, defaults) { |
|
const props = isArray(raw) |
|
? raw.reduce((normalized, p) => ((normalized[p] = {}), normalized), {}) |
|
: raw; |
|
for (const key in defaults) { |
|
const opt = props[key]; |
|
if (opt) { |
|
if (isArray(opt) || isFunction(opt)) { |
|
props[key] = { type: opt, default: defaults[key] }; |
|
} |
|
else { |
|
opt.default = defaults[key]; |
|
} |
|
} |
|
else if (opt === null) { |
|
props[key] = { default: defaults[key] }; |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warn(`props default key "${key}" has no corresponding declaration.`); |
|
} |
|
} |
|
return props; |
|
} |
|
/** |
|
* `<script setup>` helper for persisting the current instance context over |
|
* async/await flows. |
|
* |
|
* `@vue/compiler-sfc` converts the following: |
|
* |
|
* ```ts |
|
* const x = await foo() |
|
* ``` |
|
* |
|
* into: |
|
* |
|
* ```ts |
|
* let __temp, __restore |
|
* const x = (([__temp, __restore] = withAsyncContext(() => foo())),__temp=await __temp,__restore(),__temp) |
|
* ``` |
|
* @internal |
|
*/ |
|
function withAsyncContext(getAwaitable) { |
|
const ctx = getCurrentInstance(); |
|
if ((process.env.NODE_ENV !== 'production') && !ctx) { |
|
warn(`withAsyncContext called without active current instance. ` + |
|
`This is likely a bug.`); |
|
} |
|
let awaitable = getAwaitable(); |
|
unsetCurrentInstance(); |
|
if (isPromise(awaitable)) { |
|
awaitable = awaitable.catch(e => { |
|
setCurrentInstance(ctx); |
|
throw e; |
|
}); |
|
} |
|
return [awaitable, () => setCurrentInstance(ctx)]; |
|
} |
|
|
|
const ssrContextKey = Symbol((process.env.NODE_ENV !== 'production') ? `ssrContext` : ``); |
|
const useSSRContext = () => { |
|
{ |
|
const ctx = inject(ssrContextKey); |
|
if (!ctx) { |
|
(process.env.NODE_ENV !== 'production') && |
|
warn(`Server rendering context not provided. Make sure to only call ` + |
|
`useSSRContext() conditionally in the server build.`); |
|
} |
|
return ctx; |
|
} |
|
}; |
|
|
|
// Core API ------------------------------------------------------------------ |
|
const version = "3.2.47"; |
|
/** |
|
* @internal only exposed in compat builds |
|
*/ |
|
const resolveFilter = null; |
|
|
|
function unwrapper(target) { |
|
return unref(target); |
|
} |
|
function defineAsyncComponent(source) { |
|
console.error('defineAsyncComponent is unsupported'); |
|
} |
|
|
|
// import deepCopy from './deepCopy' |
|
/** |
|
* https://raw.githubusercontent.com/Tencent/westore/master/packages/westore/utils/diff.js |
|
*/ |
|
const ARRAYTYPE = '[object Array]'; |
|
const OBJECTTYPE = '[object Object]'; |
|
// const FUNCTIONTYPE = '[object Function]' |
|
function diff(current, pre) { |
|
const result = {}; |
|
syncKeys(current, pre); |
|
_diff(current, pre, '', result); |
|
return result; |
|
} |
|
function syncKeys(current, pre) { |
|
current = unwrapper(current); |
|
if (current === pre) |
|
return; |
|
const rootCurrentType = toTypeString(current); |
|
const rootPreType = toTypeString(pre); |
|
if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) { |
|
for (let key in pre) { |
|
const currentValue = current[key]; |
|
if (currentValue === undefined) { |
|
current[key] = null; |
|
} |
|
else { |
|
syncKeys(currentValue, pre[key]); |
|
} |
|
} |
|
} |
|
else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) { |
|
if (current.length >= pre.length) { |
|
pre.forEach((item, index) => { |
|
syncKeys(current[index], item); |
|
}); |
|
} |
|
} |
|
} |
|
function _diff(current, pre, path, result) { |
|
current = unwrapper(current); |
|
if (current === pre) |
|
return; |
|
const rootCurrentType = toTypeString(current); |
|
const rootPreType = toTypeString(pre); |
|
if (rootCurrentType == OBJECTTYPE) { |
|
if (rootPreType != OBJECTTYPE || |
|
Object.keys(current).length < Object.keys(pre).length) { |
|
setResult(result, path, current); |
|
} |
|
else { |
|
for (let key in current) { |
|
const currentValue = unwrapper(current[key]); |
|
const preValue = pre[key]; |
|
const currentType = toTypeString(currentValue); |
|
const preType = toTypeString(preValue); |
|
if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) { |
|
if (currentValue != preValue) { |
|
setResult(result, (path == '' ? '' : path + '.') + key, currentValue); |
|
} |
|
} |
|
else if (currentType == ARRAYTYPE) { |
|
if (preType != ARRAYTYPE) { |
|
setResult(result, (path == '' ? '' : path + '.') + key, currentValue); |
|
} |
|
else { |
|
if (currentValue.length < preValue.length) { |
|
setResult(result, (path == '' ? '' : path + '.') + key, currentValue); |
|
} |
|
else { |
|
currentValue.forEach((item, index) => { |
|
_diff(item, preValue[index], (path == '' ? '' : path + '.') + key + '[' + index + ']', result); |
|
}); |
|
} |
|
} |
|
} |
|
else if (currentType == OBJECTTYPE) { |
|
if (preType != OBJECTTYPE || |
|
Object.keys(currentValue).length < Object.keys(preValue).length) { |
|
setResult(result, (path == '' ? '' : path + '.') + key, currentValue); |
|
} |
|
else { |
|
for (let subKey in currentValue) { |
|
_diff(currentValue[subKey], preValue[subKey], (path == '' ? '' : path + '.') + key + '.' + subKey, result); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else if (rootCurrentType == ARRAYTYPE) { |
|
if (rootPreType != ARRAYTYPE) { |
|
setResult(result, path, current); |
|
} |
|
else { |
|
if (current.length < pre.length) { |
|
setResult(result, path, current); |
|
} |
|
else { |
|
current.forEach((item, index) => { |
|
_diff(item, pre[index], path + '[' + index + ']', result); |
|
}); |
|
} |
|
} |
|
} |
|
else { |
|
setResult(result, path, current); |
|
} |
|
} |
|
function setResult(result, k, v) { |
|
result[k] = v; //deepCopy(v) |
|
} |
|
|
|
function hasComponentEffect(instance) { |
|
return queue.includes(instance.update); |
|
} |
|
function flushCallbacks(instance) { |
|
const ctx = instance.ctx; |
|
const callbacks = ctx.__next_tick_callbacks; |
|
if (callbacks && callbacks.length) { |
|
if (process.env.UNI_DEBUG) { |
|
const mpInstance = ctx.$scope; |
|
console.log('[' + |
|
+new Date() + |
|
'][' + |
|
(mpInstance.is || mpInstance.route) + |
|
'][' + |
|
instance.uid + |
|
']:flushCallbacks[' + |
|
callbacks.length + |
|
']'); |
|
} |
|
const copies = callbacks.slice(0); |
|
callbacks.length = 0; |
|
for (let i = 0; i < copies.length; i++) { |
|
copies[i](); |
|
} |
|
} |
|
} |
|
function nextTick(instance, fn) { |
|
const ctx = instance.ctx; |
|
if (!ctx.__next_tick_pending && !hasComponentEffect(instance)) { |
|
if (process.env.UNI_DEBUG) { |
|
const mpInstance = ctx.$scope; |
|
console.log('[' + |
|
+new Date() + |
|
'][' + |
|
(mpInstance.is || mpInstance.route) + |
|
'][' + |
|
instance.uid + |
|
']:nextVueTick'); |
|
} |
|
return nextTick$1(fn && fn.bind(instance.proxy)); |
|
} |
|
if (process.env.UNI_DEBUG) { |
|
const mpInstance = ctx.$scope; |
|
console.log('[' + |
|
+new Date() + |
|
'][' + |
|
(mpInstance.is || mpInstance.route) + |
|
'][' + |
|
instance.uid + |
|
']:nextMPTick'); |
|
} |
|
let _resolve; |
|
if (!ctx.__next_tick_callbacks) { |
|
ctx.__next_tick_callbacks = []; |
|
} |
|
ctx.__next_tick_callbacks.push(() => { |
|
if (fn) { |
|
callWithErrorHandling(fn.bind(instance.proxy), instance, 14 /* ErrorCodes.SCHEDULER */); |
|
} |
|
else if (_resolve) { |
|
_resolve(instance.proxy); |
|
} |
|
}); |
|
return new Promise(resolve => { |
|
_resolve = resolve; |
|
}); |
|
} |
|
|
|
function clone(src, seen) { |
|
src = unwrapper(src); |
|
const type = typeof src; |
|
if (type === 'object' && src !== null) { |
|
let copy = seen.get(src); |
|
if (typeof copy !== 'undefined') { |
|
// (circular refs) |
|
return copy; |
|
} |
|
if (isArray(src)) { |
|
const len = src.length; |
|
copy = new Array(len); |
|
seen.set(src, copy); |
|
for (let i = 0; i < len; i++) { |
|
copy[i] = clone(src[i], seen); |
|
} |
|
} |
|
else { |
|
copy = {}; |
|
seen.set(src, copy); |
|
for (const name in src) { |
|
if (hasOwn(src, name)) { |
|
copy[name] = clone(src[name], seen); |
|
} |
|
} |
|
} |
|
return copy; |
|
} |
|
if (type !== 'symbol') { |
|
return src; |
|
} |
|
} |
|
/** |
|
* 与微信小程序保持一致的深度克隆 |
|
* @param src |
|
* @returns |
|
*/ |
|
function deepCopy(src) { |
|
return clone(src, typeof WeakMap !== 'undefined' ? new WeakMap() : new Map()); |
|
} |
|
|
|
function getMPInstanceData(instance, keys) { |
|
const data = instance.data; |
|
const ret = Object.create(null); |
|
//仅同步 data 中有的数据 |
|
keys.forEach(key => { |
|
ret[key] = data[key]; |
|
}); |
|
return ret; |
|
} |
|
function patch(instance, data, oldData) { |
|
if (!data) { |
|
return; |
|
} |
|
// TODO 微信小程序会对 props 序列化,目前通过序列化再次触发数据响应式收集,因为 render 中收集的数据可能不全面(也不能仅仅这里收集,render 中也要收集),导致子组件无法局部响应式更新 |
|
// 举例: |
|
// uni-indexed-list 组件传递 item 给 uni-indexed-list-item 组件,uni-indexed-list-item 发送点击到 uni-indexed-list 组件中修改 item.checked |
|
// uni-indexed-list 组件 render 中并未访问 item.checked(在 uni-indexed-list-item 中访问了,但被小程序序列化了,无法响应式),故无法收集依赖 |
|
data = deepCopy(data); |
|
// data = JSON.parse(JSON.stringify(data)) |
|
const ctx = instance.ctx; |
|
const mpType = ctx.mpType; |
|
if (mpType === 'page' || mpType === 'component') { |
|
data.r0 = 1; // ready |
|
const start = Date.now(); |
|
const mpInstance = ctx.$scope; |
|
const keys = Object.keys(data); |
|
// data.__webviewId__ = mpInstance.data.__webviewId__ |
|
const diffData = diff(data, oldData || getMPInstanceData(mpInstance, keys)); |
|
if (Object.keys(diffData).length) { |
|
if (process.env.UNI_DEBUG) { |
|
console.log('[' + |
|
+new Date() + |
|
'][' + |
|
(mpInstance.is || mpInstance.route) + |
|
'][' + |
|
instance.uid + |
|
'][耗时' + |
|
(Date.now() - start) + |
|
']差量更新', JSON.stringify(diffData)); |
|
} |
|
ctx.__next_tick_pending = true; |
|
mpInstance.setData(diffData, () => { |
|
ctx.__next_tick_pending = false; |
|
flushCallbacks(instance); |
|
}); |
|
// props update may have triggered pre-flush watchers. |
|
flushPreFlushCbs(); |
|
} |
|
else { |
|
flushCallbacks(instance); |
|
} |
|
} |
|
} |
|
|
|
function initAppConfig(appConfig) { |
|
appConfig.globalProperties.$nextTick = function $nextTick(fn) { |
|
return nextTick(this.$, fn); |
|
}; |
|
} |
|
|
|
function onApplyOptions(options, instance, publicThis) { |
|
instance.appContext.config.globalProperties.$applyOptions(options, instance, publicThis); |
|
const computedOptions = options.computed; |
|
if (computedOptions) { |
|
const keys = Object.keys(computedOptions); |
|
if (keys.length) { |
|
const ctx = instance.ctx; |
|
if (!ctx.$computedKeys) { |
|
ctx.$computedKeys = []; |
|
} |
|
ctx.$computedKeys.push(...keys); |
|
} |
|
} |
|
// remove |
|
delete instance.ctx.$onApplyOptions; |
|
} |
|
|
|
/** |
|
* Function for handling a template ref |
|
*/ |
|
function setRef$1(instance, isUnmount = false) { |
|
const { setupState, $templateRefs, ctx: { $scope, $mpPlatform } } = instance; |
|
if ($mpPlatform === 'mp-alipay') { |
|
return; |
|
} |
|
if (!$templateRefs || !$scope) { |
|
return; |
|
} |
|
if (isUnmount) { |
|
return $templateRefs.forEach(templateRef => setTemplateRef(templateRef, null, setupState)); |
|
} |
|
const check = $mpPlatform === 'mp-baidu' || $mpPlatform === 'mp-toutiao'; |
|
const doSetByRefs = (refs) => { |
|
const mpComponents = |
|
// 字节小程序 selectAllComponents 可能返回 null |
|
// https://github.com/dcloudio/uni-app/issues/3954 |
|
($scope.selectAllComponents('.r') || []).concat($scope.selectAllComponents('.r-i-f') || []); |
|
return refs.filter(templateRef => { |
|
const refValue = findComponentPublicInstance(mpComponents, templateRef.i); |
|
// 部分平台,在一些 if 条件下,部分 slot 组件初始化会被延迟到下一次渲染,需要二次检测 |
|
if (check && refValue === null) { |
|
return true; |
|
} |
|
setTemplateRef(templateRef, refValue, setupState); |
|
return false; |
|
}); |
|
}; |
|
const doSet = () => { |
|
const refs = doSetByRefs($templateRefs); |
|
if (refs.length && instance.proxy && instance.proxy.$scope) { |
|
instance.proxy.$scope.setData({ r1: 1 }, () => { |
|
doSetByRefs(refs); |
|
}); |
|
} |
|
}; |
|
if ($scope._$setRef) { |
|
$scope._$setRef(doSet); |
|
} |
|
else { |
|
nextTick(instance, doSet); |
|
} |
|
} |
|
function toSkip(value) { |
|
if (isObject(value)) { |
|
markRaw(value); |
|
} |
|
return value; |
|
} |
|
function findComponentPublicInstance(mpComponents, id) { |
|
const mpInstance = mpComponents.find(com => com && (com.properties || com.props).uI === id); |
|
if (mpInstance) { |
|
const vm = mpInstance.$vm; |
|
if (vm) { |
|
return getExposeProxy(vm.$) || vm; |
|
} |
|
// 可能是原生组件 |
|
return toSkip(mpInstance); |
|
} |
|
return null; |
|
} |
|
function setTemplateRef({ r, f }, refValue, setupState) { |
|
if (isFunction(r)) { |
|
r(refValue, {}); |
|
} |
|
else { |
|
const _isString = isString(r); |
|
const _isRef = isRef(r); |
|
if (_isString || _isRef) { |
|
if (f) { |
|
if (!_isRef) { |
|
return; |
|
} |
|
if (!isArray(r.value)) { |
|
r.value = []; |
|
} |
|
const existing = r.value; |
|
if (existing.indexOf(refValue) === -1) { |
|
existing.push(refValue); |
|
if (!refValue) { |
|
return; |
|
} |
|
// 实例销毁时,移除 |
|
onBeforeUnmount(() => remove(existing, refValue), refValue.$); |
|
} |
|
} |
|
else if (_isString) { |
|
if (hasOwn(setupState, r)) { |
|
setupState[r] = refValue; |
|
} |
|
} |
|
else if (isRef(r)) { |
|
r.value = refValue; |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warnRef(r); |
|
} |
|
} |
|
else if ((process.env.NODE_ENV !== 'production')) { |
|
warnRef(r); |
|
} |
|
} |
|
} |
|
function warnRef(ref) { |
|
warn('Invalid template ref type:', ref, `(${typeof ref})`); |
|
} |
|
|
|
var MPType; |
|
(function (MPType) { |
|
MPType["APP"] = "app"; |
|
MPType["PAGE"] = "page"; |
|
MPType["COMPONENT"] = "component"; |
|
})(MPType || (MPType = {})); |
|
const queuePostRenderEffect = queuePostFlushCb; |
|
function mountComponent(initialVNode, options) { |
|
const instance = (initialVNode.component = |
|
createComponentInstance(initialVNode, options.parentComponent, null)); |
|
if (__VUE_OPTIONS_API__) { |
|
instance.ctx.$onApplyOptions = onApplyOptions; |
|
instance.ctx.$children = []; |
|
} |
|
if (options.mpType === 'app') { |
|
instance.render = NOOP; |
|
} |
|
if (options.onBeforeSetup) { |
|
options.onBeforeSetup(instance, options); |
|
} |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
pushWarningContext(initialVNode); |
|
startMeasure(instance, `mount`); |
|
} |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
startMeasure(instance, `init`); |
|
} |
|
setupComponent(instance); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
endMeasure(instance, `init`); |
|
} |
|
if (__VUE_OPTIONS_API__) { |
|
// $children |
|
if (options.parentComponent && instance.proxy) { |
|
options.parentComponent.ctx.$children.push(getExposeProxy(instance) || instance.proxy); |
|
} |
|
} |
|
setupRenderEffect(instance); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
popWarningContext(); |
|
endMeasure(instance, `mount`); |
|
} |
|
return instance.proxy; |
|
} |
|
const getFunctionalFallthrough = (attrs) => { |
|
let res; |
|
for (const key in attrs) { |
|
if (key === 'class' || key === 'style' || isOn(key)) { |
|
(res || (res = {}))[key] = attrs[key]; |
|
} |
|
} |
|
return res; |
|
}; |
|
function renderComponentRoot(instance) { |
|
const { type: Component, vnode, proxy, withProxy, props, propsOptions: [propsOptions], slots, attrs, emit, render, renderCache, data, setupState, ctx, uid, appContext: { app: { config: { globalProperties: { pruneComponentPropsCache } } } }, inheritAttrs } = instance; |
|
instance.$templateRefs = []; |
|
instance.$ei = 0; |
|
// props |
|
pruneComponentPropsCache(uid); |
|
instance.__counter = |
|
instance.__counter === 0 ? 1 : 0; |
|
let result; |
|
const prev = setCurrentRenderingInstance(instance); |
|
try { |
|
if (vnode.shapeFlag & 4 /* ShapeFlags.STATEFUL_COMPONENT */) { |
|
fallthroughAttrs(inheritAttrs, props, propsOptions, attrs); |
|
// withProxy is a proxy with a different `has` trap only for |
|
// runtime-compiled render functions using `with` block. |
|
const proxyToUse = withProxy || proxy; |
|
result = render.call(proxyToUse, proxyToUse, renderCache, props, setupState, data, ctx); |
|
} |
|
else { |
|
fallthroughAttrs(inheritAttrs, props, propsOptions, Component.props ? attrs : getFunctionalFallthrough(attrs)); |
|
// functional |
|
const render = Component; |
|
result = |
|
render.length > 1 |
|
? render(props, { attrs, slots, emit }) |
|
: render(props, null /* we know it doesn't need it */); |
|
} |
|
} |
|
catch (err) { |
|
handleError(err, instance, 1 /* ErrorCodes.RENDER_FUNCTION */); |
|
result = false; |
|
} |
|
setRef$1(instance); |
|
setCurrentRenderingInstance(prev); |
|
return result; |
|
} |
|
function fallthroughAttrs(inheritAttrs, props, propsOptions, fallthroughAttrs) { |
|
if (props && fallthroughAttrs && inheritAttrs !== false) { |
|
const keys = Object.keys(fallthroughAttrs).filter(key => key !== 'class' && key !== 'style'); |
|
if (!keys.length) { |
|
return; |
|
} |
|
if (propsOptions && keys.some(isModelListener)) { |
|
keys.forEach(key => { |
|
if (!isModelListener(key) || !(key.slice(9) in propsOptions)) { |
|
props[key] = fallthroughAttrs[key]; |
|
} |
|
}); |
|
} |
|
else { |
|
keys.forEach(key => (props[key] = fallthroughAttrs[key])); |
|
} |
|
} |
|
} |
|
const updateComponentPreRender = (instance) => { |
|
pauseTracking(); |
|
// props update may have triggered pre-flush watchers. |
|
// flush them before the render update. |
|
flushPreFlushCbs(); |
|
resetTracking(); |
|
}; |
|
function componentUpdateScopedSlotsFn() { |
|
const scopedSlotsData = this.$scopedSlotsData; |
|
if (!scopedSlotsData || scopedSlotsData.length === 0) { |
|
return; |
|
} |
|
const start = Date.now(); |
|
const mpInstance = this.ctx.$scope; |
|
const oldData = mpInstance.data; |
|
const diffData = Object.create(null); |
|
scopedSlotsData.forEach(({ path, index, data }) => { |
|
const oldScopedSlotData = getValueByDataPath(oldData, path); |
|
const diffPath = isString(index) ? `${path}.${index}` : `${path}[${index}]`; |
|
if (typeof oldScopedSlotData === 'undefined' || |
|
typeof oldScopedSlotData[index] === 'undefined') { |
|
diffData[diffPath] = data; |
|
} |
|
else { |
|
const diffScopedSlotData = diff(data, oldScopedSlotData[index]); |
|
Object.keys(diffScopedSlotData).forEach(name => { |
|
diffData[diffPath + '.' + name] = diffScopedSlotData[name]; |
|
}); |
|
} |
|
}); |
|
scopedSlotsData.length = 0; |
|
if (Object.keys(diffData).length) { |
|
if (process.env.UNI_DEBUG) { |
|
console.log('[' + |
|
+new Date() + |
|
'][' + |
|
(mpInstance.is || mpInstance.route) + |
|
'][' + |
|
this.uid + |
|
'][耗时' + |
|
(Date.now() - start) + |
|
']作用域插槽差量更新', JSON.stringify(diffData)); |
|
} |
|
mpInstance.setData(diffData); |
|
} |
|
} |
|
function toggleRecurse({ effect, update }, allowed) { |
|
effect.allowRecurse = update.allowRecurse = allowed; |
|
} |
|
function setupRenderEffect(instance) { |
|
const updateScopedSlots = componentUpdateScopedSlotsFn.bind(instance); |
|
instance.$updateScopedSlots = () => nextTick$1(() => queueJob(updateScopedSlots)); |
|
const componentUpdateFn = () => { |
|
if (!instance.isMounted) { |
|
onBeforeUnmount(() => { |
|
setRef$1(instance, true); |
|
}, instance); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
startMeasure(instance, `patch`); |
|
} |
|
patch(instance, renderComponentRoot(instance)); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
endMeasure(instance, `patch`); |
|
} |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsComponentAdded(instance); |
|
} |
|
} |
|
else { |
|
// updateComponent |
|
const { next, bu, u } = instance; |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
pushWarningContext(next || instance.vnode); |
|
} |
|
// Disallow component effect recursion during pre-lifecycle hooks. |
|
toggleRecurse(instance, false); |
|
updateComponentPreRender(); |
|
// beforeUpdate hook |
|
if (bu) { |
|
invokeArrayFns(bu); |
|
} |
|
toggleRecurse(instance, true); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
startMeasure(instance, `patch`); |
|
} |
|
patch(instance, renderComponentRoot(instance)); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
endMeasure(instance, `patch`); |
|
} |
|
// updated hook |
|
if (u) { |
|
queuePostRenderEffect(u); |
|
} |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsComponentUpdated(instance); |
|
} |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
popWarningContext(); |
|
} |
|
} |
|
}; |
|
// create reactive effect for rendering |
|
const effect = (instance.effect = new ReactiveEffect(componentUpdateFn, () => queueJob(instance.update), instance.scope // track it in component's effect scope |
|
)); |
|
const update = (instance.update = effect.run.bind(effect)); |
|
update.id = instance.uid; |
|
// allowRecurse |
|
// #1801, #2043 component render effects should allow recursive updates |
|
toggleRecurse(instance, true); |
|
if ((process.env.NODE_ENV !== 'production')) { |
|
effect.onTrack = instance.rtc |
|
? e => invokeArrayFns(instance.rtc, e) |
|
: void 0; |
|
effect.onTrigger = instance.rtg |
|
? e => invokeArrayFns(instance.rtg, e) |
|
: void 0; |
|
// @ts-ignore (for scheduler) |
|
update.ownerInstance = instance; |
|
} |
|
update(); |
|
} |
|
function unmountComponent(instance) { |
|
const { bum, scope, update, um } = instance; |
|
// beforeUnmount hook |
|
if (bum) { |
|
invokeArrayFns(bum); |
|
} |
|
// stop effects in component scope |
|
scope.stop(); |
|
// update may be null if a component is unmounted before its async |
|
// setup has resolved. |
|
if (update) { |
|
update.active = false; |
|
} |
|
// unmounted hook |
|
if (um) { |
|
queuePostRenderEffect(um); |
|
} |
|
queuePostRenderEffect(() => { |
|
instance.isUnmounted = true; |
|
}); |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsComponentRemoved(instance); |
|
} |
|
} |
|
const oldCreateApp = createAppAPI(); |
|
function getTarget() { |
|
if (typeof window !== 'undefined') { |
|
return window; |
|
} |
|
if (typeof globalThis !== 'undefined') { |
|
return globalThis; |
|
} |
|
if (typeof global !== 'undefined') { |
|
return global; |
|
} |
|
if (typeof my !== 'undefined') { |
|
return my; |
|
} |
|
} |
|
function createVueApp(rootComponent, rootProps = null) { |
|
const target = getTarget(); |
|
target.__VUE__ = true; |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__, target); |
|
} |
|
const app = oldCreateApp(rootComponent, rootProps); |
|
const appContext = app._context; |
|
initAppConfig(appContext.config); |
|
const createVNode = initialVNode => { |
|
initialVNode.appContext = appContext; |
|
initialVNode.shapeFlag = 6 /* ShapeFlags.COMPONENT */; |
|
return initialVNode; |
|
}; |
|
const createComponent = function createComponent(initialVNode, options) { |
|
return mountComponent(createVNode(initialVNode), options); |
|
}; |
|
const destroyComponent = function destroyComponent(component) { |
|
return component && unmountComponent(component.$); |
|
}; |
|
app.mount = function mount() { |
|
rootComponent.render = NOOP; |
|
const instance = mountComponent(createVNode({ type: rootComponent }), { |
|
mpType: MPType.APP, |
|
mpInstance: null, |
|
parentComponent: null, |
|
slots: [], |
|
props: null |
|
}); |
|
app._instance = instance.$; |
|
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) { |
|
devtoolsInitApp(app, version); |
|
} |
|
instance.$app = app; |
|
instance.$createComponent = createComponent; |
|
instance.$destroyComponent = destroyComponent; |
|
appContext.$appInstance = instance; |
|
return instance; |
|
}; |
|
app.unmount = function unmount() { |
|
warn(`Cannot unmount an app.`); |
|
}; |
|
return app; |
|
} |
|
|
|
function useCssModule(name = '$style') { |
|
/* istanbul ignore else */ |
|
{ |
|
const instance = getCurrentInstance(); |
|
if (!instance) { |
|
(process.env.NODE_ENV !== 'production') && warn(`useCssModule must be called inside setup()`); |
|
return EMPTY_OBJ; |
|
} |
|
const modules = instance.type.__cssModules; |
|
if (!modules) { |
|
(process.env.NODE_ENV !== 'production') && warn(`Current instance does not have CSS modules injected.`); |
|
return EMPTY_OBJ; |
|
} |
|
const mod = modules[name]; |
|
if (!mod) { |
|
(process.env.NODE_ENV !== 'production') && |
|
warn(`Current instance does not have CSS module named "${name}".`); |
|
return EMPTY_OBJ; |
|
} |
|
return mod; |
|
} |
|
} |
|
|
|
/** |
|
* Runtime helper for SFC's CSS variable injection feature. |
|
* @private |
|
*/ |
|
function useCssVars(getter) { |
|
const instance = getCurrentInstance(); |
|
/* istanbul ignore next */ |
|
if (!instance) { |
|
(process.env.NODE_ENV !== 'production') && |
|
warn(`useCssVars is called without current active component instance.`); |
|
return; |
|
} |
|
initCssVarsRender(instance, getter); |
|
} |
|
function initCssVarsRender(instance, getter) { |
|
instance.ctx.__cssVars = () => { |
|
const vars = getter(instance.proxy); |
|
const cssVars = {}; |
|
for (const key in vars) { |
|
cssVars[`--${key}`] = vars[key]; |
|
} |
|
return cssVars; |
|
}; |
|
} |
|
|
|
function withModifiers() { } |
|
function createVNode() { } |
|
|
|
function injectLifecycleHook(name, hook, publicThis, instance) { |
|
if (isFunction(hook)) { |
|
injectHook(name, hook.bind(publicThis), instance); |
|
} |
|
} |
|
function initHooks(options, instance, publicThis) { |
|
const mpType = options.mpType || publicThis.$mpType; |
|
if (!mpType || mpType === 'component') { |
|
// 仅 App,Page 类型支持在 options 中配置 on 生命周期,组件可以使用组合式 API 定义页面生命周期 |
|
return; |
|
} |
|
Object.keys(options).forEach((name) => { |
|
if (isUniLifecycleHook(name, options[name], false)) { |
|
const hooks = options[name]; |
|
if (isArray(hooks)) { |
|
hooks.forEach((hook) => injectLifecycleHook(name, hook, publicThis, instance)); |
|
} |
|
else { |
|
injectLifecycleHook(name, hooks, publicThis, instance); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
function applyOptions(options, instance, publicThis) { |
|
initHooks(options, instance, publicThis); |
|
} |
|
|
|
function set(target, key, val) { |
|
return (target[key] = val); |
|
} |
|
|
|
function createErrorHandler(app) { |
|
return function errorHandler(err, instance, _info) { |
|
if (!instance) { |
|
throw err; |
|
} |
|
const appInstance = app._instance; |
|
if (!appInstance || !appInstance.proxy) { |
|
throw err; |
|
} |
|
{ |
|
appInstance.proxy.$callHook(ON_ERROR, err); |
|
} |
|
}; |
|
} |
|
function mergeAsArray(to, from) { |
|
return to ? [...new Set([].concat(to, from))] : from; |
|
} |
|
function initOptionMergeStrategies(optionMergeStrategies) { |
|
UniLifecycleHooks.forEach((name) => { |
|
optionMergeStrategies[name] = mergeAsArray; |
|
}); |
|
} |
|
|
|
let realAtob; |
|
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; |
|
const b64re = /^(?:[A-Za-z\d+/]{4})*?(?:[A-Za-z\d+/]{2}(?:==)?|[A-Za-z\d+/]{3}=?)?$/; |
|
if (typeof atob !== 'function') { |
|
realAtob = function (str) { |
|
str = String(str).replace(/[\t\n\f\r ]+/g, ''); |
|
if (!b64re.test(str)) { |
|
throw new Error("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); |
|
} |
|
// Adding the padding if missing, for semplicity |
|
str += '=='.slice(2 - (str.length & 3)); |
|
var bitmap; |
|
var result = ''; |
|
var r1; |
|
var r2; |
|
var i = 0; |
|
for (; i < str.length;) { |
|
bitmap = |
|
(b64.indexOf(str.charAt(i++)) << 18) | |
|
(b64.indexOf(str.charAt(i++)) << 12) | |
|
((r1 = b64.indexOf(str.charAt(i++))) << 6) | |
|
(r2 = b64.indexOf(str.charAt(i++))); |
|
result += |
|
r1 === 64 |
|
? String.fromCharCode((bitmap >> 16) & 255) |
|
: r2 === 64 |
|
? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255) |
|
: String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255); |
|
} |
|
return result; |
|
}; |
|
} |
|
else { |
|
// 注意atob只能在全局对象上调用,例如:`const Base64 = {atob};Base64.atob('xxxx')`是错误的用法 |
|
realAtob = atob; |
|
} |
|
function b64DecodeUnicode(str) { |
|
return decodeURIComponent(realAtob(str) |
|
.split('') |
|
.map(function (c) { |
|
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); |
|
}) |
|
.join('')); |
|
} |
|
function getCurrentUserInfo() { |
|
const token = uni.getStorageSync('uni_id_token') || ''; |
|
const tokenArr = token.split('.'); |
|
if (!token || tokenArr.length !== 3) { |
|
return { |
|
uid: null, |
|
role: [], |
|
permission: [], |
|
tokenExpired: 0, |
|
}; |
|
} |
|
let userInfo; |
|
try { |
|
userInfo = JSON.parse(b64DecodeUnicode(tokenArr[1])); |
|
} |
|
catch (error) { |
|
throw new Error('获取当前用户信息出错,详细错误信息为:' + error.message); |
|
} |
|
userInfo.tokenExpired = userInfo.exp * 1000; |
|
delete userInfo.exp; |
|
delete userInfo.iat; |
|
return userInfo; |
|
} |
|
function uniIdMixin(globalProperties) { |
|
globalProperties.uniIDHasRole = function (roleId) { |
|
const { role } = getCurrentUserInfo(); |
|
return role.indexOf(roleId) > -1; |
|
}; |
|
globalProperties.uniIDHasPermission = function (permissionId) { |
|
const { permission } = getCurrentUserInfo(); |
|
return this.uniIDHasRole('admin') || permission.indexOf(permissionId) > -1; |
|
}; |
|
globalProperties.uniIDTokenValid = function () { |
|
const { tokenExpired } = getCurrentUserInfo(); |
|
return tokenExpired > Date.now(); |
|
}; |
|
} |
|
|
|
function initApp(app) { |
|
const appConfig = app._context.config; |
|
appConfig.errorHandler = invokeCreateErrorHandler(app, createErrorHandler); |
|
initOptionMergeStrategies(appConfig.optionMergeStrategies); |
|
const globalProperties = appConfig.globalProperties; |
|
{ |
|
uniIdMixin(globalProperties); |
|
} |
|
if (__VUE_OPTIONS_API__) { |
|
globalProperties.$set = set; |
|
globalProperties.$applyOptions = applyOptions; |
|
} |
|
{ |
|
uni.invokeCreateVueAppHook(app); |
|
} |
|
} |
|
|
|
const propsCaches = Object.create(null); |
|
function renderProps(props) { |
|
const { uid, __counter } = getCurrentInstance(); |
|
const propsId = (propsCaches[uid] || (propsCaches[uid] = [])).push(guardReactiveProps(props)) - 1; |
|
// 强制每次更新 |
|
return uid + ',' + propsId + ',' + __counter; |
|
} |
|
function pruneComponentPropsCache(uid) { |
|
delete propsCaches[uid]; |
|
} |
|
function findComponentPropsData(up) { |
|
if (!up) { |
|
return; |
|
} |
|
const [uid, propsId] = up.split(','); |
|
if (!propsCaches[uid]) { |
|
return; |
|
} |
|
return propsCaches[uid][parseInt(propsId)]; |
|
} |
|
|
|
var plugin = { |
|
install(app) { |
|
initApp(app); |
|
app.config.globalProperties.pruneComponentPropsCache = |
|
pruneComponentPropsCache; |
|
const oldMount = app.mount; |
|
app.mount = function mount(rootContainer) { |
|
const instance = oldMount.call(app, rootContainer); |
|
const createApp = getCreateApp(); |
|
if (createApp) { |
|
createApp(instance); |
|
} |
|
else { |
|
// @ts-ignore 旧编译器 |
|
if (typeof createMiniProgramApp !== 'undefined') { |
|
// @ts-ignore |
|
createMiniProgramApp(instance); |
|
} |
|
} |
|
return instance; |
|
}; |
|
}, |
|
}; |
|
function getCreateApp() { |
|
const method = process.env.UNI_MP_PLUGIN |
|
? 'createPluginApp' |
|
: process.env.UNI_SUBPACKAGE |
|
? 'createSubpackageApp' |
|
: 'createApp'; |
|
if (typeof global !== 'undefined') { |
|
return global[method]; |
|
} |
|
else if (typeof my !== 'undefined') { |
|
// 支付宝小程序没有global |
|
return my[method]; |
|
} |
|
} |
|
|
|
function vOn(value, key) { |
|
const instance = getCurrentInstance(); |
|
const ctx = instance.ctx; |
|
// 微信小程序,QQ小程序,当 setData diff 的时候,若事件不主动同步过去,会导致事件绑定不更新,(question/137217) |
|
const extraKey = typeof key !== 'undefined' && |
|
(ctx.$mpPlatform === 'mp-weixin' || ctx.$mpPlatform === 'mp-qq') && |
|
(isString(key) || typeof key === 'number') |
|
? '_' + key |
|
: ''; |
|
const name = 'e' + instance.$ei++ + extraKey; |
|
const mpInstance = ctx.$scope; |
|
if (!value) { |
|
// remove |
|
delete mpInstance[name]; |
|
return name; |
|
} |
|
const existingInvoker = mpInstance[name]; |
|
if (existingInvoker) { |
|
// patch |
|
existingInvoker.value = value; |
|
} |
|
else { |
|
// add |
|
mpInstance[name] = createInvoker(value, instance); |
|
} |
|
return name; |
|
} |
|
function createInvoker(initialValue, instance) { |
|
const invoker = (e) => { |
|
patchMPEvent(e); |
|
let args = [e]; |
|
if (e.detail && e.detail.__args__) { |
|
args = e.detail.__args__; |
|
} |
|
const eventValue = invoker.value; |
|
const invoke = () => callWithAsyncErrorHandling(patchStopImmediatePropagation(e, eventValue), instance, 5 /* ErrorCodes.NATIVE_EVENT_HANDLER */, args); |
|
// 冒泡事件触发时,启用延迟策略,避免同一批次的事件执行时机不正确,对性能可能有略微影响 https://github.com/dcloudio/uni-app/issues/3228 |
|
const eventTarget = e.target; |
|
const eventSync = eventTarget |
|
? eventTarget.dataset |
|
? String(eventTarget.dataset.eventsync) === 'true' |
|
: false |
|
: false; |
|
if (bubbles.includes(e.type) && !eventSync) { |
|
setTimeout(invoke); |
|
} |
|
else { |
|
const res = invoke(); |
|
if (e.type === 'input' && (isArray(res) || isPromise(res))) { |
|
return; |
|
} |
|
return res; |
|
} |
|
}; |
|
invoker.value = initialValue; |
|
return invoker; |
|
} |
|
// 冒泡事件列表 |
|
const bubbles = [ |
|
// touch事件暂不做延迟,否则在 Android 上会影响性能,比如一些拖拽跟手手势等 |
|
// 'touchstart', |
|
// 'touchmove', |
|
// 'touchcancel', |
|
// 'touchend', |
|
'tap', |
|
'longpress', |
|
'longtap', |
|
'transitionend', |
|
'animationstart', |
|
'animationiteration', |
|
'animationend', |
|
'touchforcechange', |
|
]; |
|
function patchMPEvent(event) { |
|
if (event.type && event.target) { |
|
event.preventDefault = NOOP; |
|
event.stopPropagation = NOOP; |
|
event.stopImmediatePropagation = NOOP; |
|
if (!hasOwn(event, 'detail')) { |
|
event.detail = {}; |
|
} |
|
if (hasOwn(event, 'markerId')) { |
|
event.detail = typeof event.detail === 'object' ? event.detail : {}; |
|
event.detail.markerId = event.markerId; |
|
} |
|
// mp-baidu,checked=>value |
|
if (isPlainObject(event.detail) && |
|
hasOwn(event.detail, 'checked') && |
|
!hasOwn(event.detail, 'value')) { |
|
event.detail.value = event.detail.checked; |
|
} |
|
if (isPlainObject(event.detail)) { |
|
event.target = extend({}, event.target, event.detail); |
|
} |
|
} |
|
} |
|
function patchStopImmediatePropagation(e, value) { |
|
if (isArray(value)) { |
|
const originalStop = e.stopImmediatePropagation; |
|
e.stopImmediatePropagation = () => { |
|
originalStop && originalStop.call(e); |
|
e._stopped = true; |
|
}; |
|
return value.map((fn) => (e) => !e._stopped && fn(e)); |
|
} |
|
else { |
|
return value; |
|
} |
|
} |
|
|
|
/** |
|
* Actual implementation |
|
*/ |
|
function vFor(source, renderItem) { |
|
let ret; |
|
if (isArray(source) || isString(source)) { |
|
ret = new Array(source.length); |
|
for (let i = 0, l = source.length; i < l; i++) { |
|
ret[i] = renderItem(source[i], i, i); |
|
} |
|
} |
|
else if (typeof source === 'number') { |
|
if ((process.env.NODE_ENV !== 'production') && !Number.isInteger(source)) { |
|
warn(`The v-for range expect an integer value but got ${source}.`); |
|
return []; |
|
} |
|
ret = new Array(source); |
|
for (let i = 0; i < source; i++) { |
|
ret[i] = renderItem(i + 1, i, i); |
|
} |
|
} |
|
else if (isObject(source)) { |
|
if (source[Symbol.iterator]) { |
|
ret = Array.from(source, (item, i) => renderItem(item, i, i)); |
|
} |
|
else { |
|
const keys = Object.keys(source); |
|
ret = new Array(keys.length); |
|
for (let i = 0, l = keys.length; i < l; i++) { |
|
const key = keys[i]; |
|
ret[i] = renderItem(source[key], key, i); |
|
} |
|
} |
|
} |
|
else { |
|
ret = []; |
|
} |
|
return ret; |
|
} |
|
|
|
function renderSlot(name, props = {}, key) { |
|
const instance = getCurrentInstance(); |
|
const { parent, isMounted, ctx: { $scope }, } = instance; |
|
// mp-alipay 为 props |
|
const vueIds = ($scope.properties || $scope.props).uI; |
|
if (!vueIds) { |
|
return; |
|
} |
|
if (!parent && !isMounted) { |
|
// 头条小程序首次 render 时,还没有 parent |
|
onMounted(() => { |
|
renderSlot(name, props, key); |
|
}, instance); |
|
return; |
|
} |
|
const invoker = findScopedSlotInvoker(vueIds, instance); |
|
// 可能不存在,因为插槽不是必需的 |
|
if (invoker) { |
|
invoker(name, props, key); |
|
} |
|
} |
|
function findScopedSlotInvoker(vueId, instance) { |
|
let parent = instance.parent; |
|
while (parent) { |
|
const invokers = parent.$ssi; |
|
if (invokers && invokers[vueId]) { |
|
return invokers[vueId]; |
|
} |
|
parent = parent.parent; |
|
} |
|
} |
|
|
|
function withScopedSlot(fn, { name, path, vueId, }) { |
|
const instance = getCurrentInstance(); |
|
fn.path = path; |
|
const scopedSlots = (instance.$ssi || |
|
(instance.$ssi = {})); |
|
const invoker = scopedSlots[vueId] || |
|
(scopedSlots[vueId] = createScopedSlotInvoker(instance)); |
|
if (!invoker.slots[name]) { |
|
invoker.slots[name] = { |
|
fn, |
|
}; |
|
} |
|
else { |
|
invoker.slots[name].fn = fn; |
|
} |
|
return getValueByDataPath(instance.ctx.$scope.data, path); |
|
} |
|
function createScopedSlotInvoker(instance) { |
|
const invoker = (slotName, args, index) => { |
|
const slot = invoker.slots[slotName]; |
|
if (!slot) { |
|
// slot 可能不存在 https://github.com/dcloudio/uni-app/issues/3346 |
|
return; |
|
} |
|
const hasIndex = typeof index !== 'undefined'; |
|
index = index || 0; |
|
// 确保当前 slot 的上下文,类似 withCtx |
|
const prevInstance = setCurrentRenderingInstance(instance); |
|
const data = slot.fn(args, slotName + (hasIndex ? '-' + index : ''), index); |
|
const path = slot.fn.path; |
|
setCurrentRenderingInstance(prevInstance); |
|
(instance.$scopedSlotsData || (instance.$scopedSlotsData = [])).push({ |
|
path, |
|
index, |
|
data, |
|
}); |
|
instance.$updateScopedSlots(); |
|
}; |
|
invoker.slots = {}; |
|
return invoker; |
|
} |
|
|
|
function stringifyStyle(value) { |
|
if (isString(value)) { |
|
return value; |
|
} |
|
return stringify(normalizeStyle(value)); |
|
} |
|
function stringify(styles) { |
|
let ret = ''; |
|
if (!styles || isString(styles)) { |
|
return ret; |
|
} |
|
for (const key in styles) { |
|
ret += `${key.startsWith(`--`) ? key : hyphenate(key)}:${styles[key]};`; |
|
} |
|
return ret; |
|
} |
|
|
|
/** |
|
* quickapp-webview 不能使用 default 作为插槽名称,故统一转换 default 为 d |
|
* @param names |
|
* @returns |
|
*/ |
|
function dynamicSlot(names) { |
|
if (isString(names)) { |
|
return dynamicSlotName(names); |
|
} |
|
return names.map((name) => dynamicSlotName(name)); |
|
} |
|
|
|
function setRef(ref, id, opts = {}) { |
|
const { $templateRefs } = getCurrentInstance(); |
|
$templateRefs.push({ i: id, r: ref, k: opts.k, f: opts.f }); |
|
} |
|
|
|
function withModelModifiers(fn, { number, trim }, isComponent = false) { |
|
if (isComponent) { |
|
return (...args) => { |
|
if (trim) { |
|
args = args.map((a) => a.trim()); |
|
} |
|
else if (number) { |
|
args = args.map(toNumber); |
|
} |
|
return fn(...args); |
|
}; |
|
} |
|
return (event) => { |
|
const value = event.detail.value; |
|
if (trim) { |
|
event.detail.value = value.trim(); |
|
} |
|
else if (number) { |
|
event.detail.value = toNumber(value); |
|
} |
|
return fn(event); |
|
}; |
|
} |
|
|
|
function setupDevtoolsPlugin() { |
|
// noop |
|
} |
|
|
|
const o = (value, key) => vOn(value, key); |
|
const f = (source, renderItem) => vFor(source, renderItem); |
|
const d = (names) => dynamicSlot(names); |
|
const r = (name, props, key) => renderSlot(name, props, key); |
|
const w = (fn, options) => withScopedSlot(fn, options); |
|
const s = (value) => stringifyStyle(value); |
|
const c = (str) => camelize(str); |
|
const e = (target, ...sources) => extend(target, ...sources); |
|
const h = (str) => hyphenate(str); |
|
const n = (value) => normalizeClass(value); |
|
const t = (val) => toDisplayString(val); |
|
const p = (props) => renderProps(props); |
|
const sr = (ref, id, opts) => setRef(ref, id, opts); |
|
const m = (fn, modifiers, isComponent = false) => withModelModifiers(fn, modifiers, isComponent); |
|
const j = (obj) => JSON.stringify(obj); |
|
|
|
function createApp(rootComponent, rootProps = null) { |
|
rootComponent && (rootComponent.mpType = 'app'); |
|
return createVueApp(rootComponent, rootProps).use(plugin); |
|
} |
|
const createSSRApp = createApp; |
|
|
|
export { EffectScope, Fragment, ReactiveEffect, Text, c, callWithAsyncErrorHandling, callWithErrorHandling, computed, createApp, createSSRApp, createVNode, createVueApp, customRef, d, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, devtoolsComponentAdded, devtoolsComponentRemoved, devtoolsComponentUpdated, diff, e, effect, effectScope, f, findComponentPropsData, getCurrentInstance, getCurrentScope, getExposeProxy, guardReactiveProps, h, hasQueueJob, inject, injectHook, invalidateJob, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, j, logError, m, markRaw, mergeDefaults, mergeProps, n, nextTick$1 as nextTick, o, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, p, patch, provide, proxyRefs, pruneComponentPropsCache, queuePostFlushCb, r, reactive, readonly, ref, resolveComponent, resolveDirective, resolveFilter, s, setCurrentRenderingInstance, setTemplateRef, setupDevtoolsPlugin, shallowReactive, shallowReadonly, shallowRef, sr, stop, t, toHandlers, toRaw, toRef, toRefs, triggerRef, unref, updateProps, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, version, w, warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withModifiers, withScopeId };
|
|
|