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.
3287 lines
113 KiB
3287 lines
113 KiB
import { EMPTY_OBJ, isArray, isSymbol, extend, hasOwn, isObject, hasChanged, capitalize, toRawType, def, makeMap, isFunction, NOOP, isString, isPromise, hyphenate, isOn, isReservedProp, camelize, EMPTY_ARR, remove, NO, isGloballyWhitelisted, toTypeString, invokeArrayFns } from '@vue/shared';
|
|
export { camelize } from '@vue/shared';
|
|
|
|
const targetMap = new WeakMap();
|
|
const effectStack = [];
|
|
let activeEffect;
|
|
const ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'iterate' : '');
|
|
const MAP_KEY_ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'Map key iterate' : '');
|
|
function isEffect(fn) {
|
|
return fn && fn._isEffect === true;
|
|
}
|
|
function effect(fn, options = EMPTY_OBJ) {
|
|
if (isEffect(fn)) {
|
|
fn = fn.raw;
|
|
}
|
|
const effect = createReactiveEffect(fn, options);
|
|
if (!options.lazy) {
|
|
effect();
|
|
}
|
|
return effect;
|
|
}
|
|
function stop(effect) {
|
|
if (effect.active) {
|
|
cleanup(effect);
|
|
if (effect.options.onStop) {
|
|
effect.options.onStop();
|
|
}
|
|
effect.active = false;
|
|
}
|
|
}
|
|
let uid = 0;
|
|
function createReactiveEffect(fn, options) {
|
|
const effect = function reactiveEffect() {
|
|
if (!effect.active) {
|
|
return options.scheduler ? undefined : fn();
|
|
}
|
|
if (!effectStack.includes(effect)) {
|
|
cleanup(effect);
|
|
try {
|
|
enableTracking();
|
|
effectStack.push(effect);
|
|
activeEffect = effect;
|
|
return fn();
|
|
}
|
|
finally {
|
|
effectStack.pop();
|
|
resetTracking();
|
|
activeEffect = effectStack[effectStack.length - 1];
|
|
}
|
|
}
|
|
};
|
|
effect.id = uid++;
|
|
effect._isEffect = true;
|
|
effect.active = true;
|
|
effect.raw = fn;
|
|
effect.deps = [];
|
|
effect.options = options;
|
|
return effect;
|
|
}
|
|
function cleanup(effect) {
|
|
const { deps } = effect;
|
|
if (deps.length) {
|
|
for (let i = 0; i < deps.length; i++) {
|
|
deps[i].delete(effect);
|
|
}
|
|
deps.length = 0;
|
|
}
|
|
}
|
|
let shouldTrack = true;
|
|
const trackStack = [];
|
|
function pauseTracking() {
|
|
trackStack.push(shouldTrack);
|
|
shouldTrack = false;
|
|
}
|
|
function enableTracking() {
|
|
trackStack.push(shouldTrack);
|
|
shouldTrack = true;
|
|
}
|
|
function resetTracking() {
|
|
const last = trackStack.pop();
|
|
shouldTrack = last === undefined ? true : last;
|
|
}
|
|
function track(target, type, key) {
|
|
if (!shouldTrack || activeEffect === undefined) {
|
|
return;
|
|
}
|
|
let depsMap = targetMap.get(target);
|
|
if (!depsMap) {
|
|
targetMap.set(target, (depsMap = new Map()));
|
|
}
|
|
let dep = depsMap.get(key);
|
|
if (!dep) {
|
|
depsMap.set(key, (dep = new Set()));
|
|
}
|
|
if (!dep.has(activeEffect)) {
|
|
dep.add(activeEffect);
|
|
activeEffect.deps.push(dep);
|
|
if ((process.env.NODE_ENV !== 'production') && activeEffect.options.onTrack) {
|
|
activeEffect.options.onTrack({
|
|
effect: activeEffect,
|
|
target,
|
|
type,
|
|
key
|
|
});
|
|
}
|
|
}
|
|
}
|
|
function trigger(target, type, key, newValue, oldValue, oldTarget) {
|
|
const depsMap = targetMap.get(target);
|
|
if (!depsMap) {
|
|
// never been tracked
|
|
return;
|
|
}
|
|
const effects = new Set();
|
|
const add = (effectsToAdd) => {
|
|
if (effectsToAdd) {
|
|
effectsToAdd.forEach(effect => {
|
|
if (effect !== activeEffect || !shouldTrack) {
|
|
effects.add(effect);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
if (type === "clear" /* CLEAR */) {
|
|
// collection being cleared
|
|
// trigger all effects for target
|
|
depsMap.forEach(add);
|
|
}
|
|
else if (key === 'length' && isArray(target)) {
|
|
depsMap.forEach((dep, key) => {
|
|
if (key === 'length' || key >= newValue) {
|
|
add(dep);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
// schedule runs for SET | ADD | DELETE
|
|
if (key !== void 0) {
|
|
add(depsMap.get(key));
|
|
}
|
|
// also run for iteration key on ADD | DELETE | Map.SET
|
|
const isAddOrDelete = type === "add" /* ADD */ ||
|
|
(type === "delete" /* DELETE */ && !isArray(target));
|
|
if (isAddOrDelete ||
|
|
(type === "set" /* SET */ && target instanceof Map)) {
|
|
add(depsMap.get(isArray(target) ? 'length' : ITERATE_KEY));
|
|
}
|
|
if (isAddOrDelete && target instanceof Map) {
|
|
add(depsMap.get(MAP_KEY_ITERATE_KEY));
|
|
}
|
|
}
|
|
const run = (effect) => {
|
|
if ((process.env.NODE_ENV !== 'production') && effect.options.onTrigger) {
|
|
effect.options.onTrigger({
|
|
effect,
|
|
target,
|
|
key,
|
|
type,
|
|
newValue,
|
|
oldValue,
|
|
oldTarget
|
|
});
|
|
}
|
|
if (effect.options.scheduler) {
|
|
effect.options.scheduler(effect);
|
|
}
|
|
else {
|
|
effect();
|
|
}
|
|
};
|
|
effects.forEach(run);
|
|
}
|
|
|
|
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
|
|
.map(key => Symbol[key])
|
|
.filter(isSymbol));
|
|
const get = /*#__PURE__*/ createGetter();
|
|
const shallowGet = /*#__PURE__*/ createGetter(false, true);
|
|
const readonlyGet = /*#__PURE__*/ createGetter(true);
|
|
const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
|
|
const arrayInstrumentations = {};
|
|
['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
|
|
arrayInstrumentations[key] = function (...args) {
|
|
const arr = toRaw(this);
|
|
for (let i = 0, l = this.length; i < l; i++) {
|
|
track(arr, "get" /* GET */, i + '');
|
|
}
|
|
// we run the method using the original args first (which may be reactive)
|
|
const res = 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;
|
|
}
|
|
};
|
|
});
|
|
function createGetter(isReadonly = false, shallow = false) {
|
|
return function get(target, key, receiver) {
|
|
if (key === "__v_isReactive" /* IS_REACTIVE */) {
|
|
return !isReadonly;
|
|
}
|
|
else if (key === "__v_isReadonly" /* IS_READONLY */) {
|
|
return isReadonly;
|
|
}
|
|
else if (key === "__v_raw" /* RAW */ &&
|
|
receiver ===
|
|
(isReadonly
|
|
? target["__v_readonly" /* READONLY */]
|
|
: target["__v_reactive" /* REACTIVE */])) {
|
|
return target;
|
|
}
|
|
const targetIsArray = isArray(target);
|
|
if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
|
|
return Reflect.get(arrayInstrumentations, key, receiver);
|
|
}
|
|
const res = Reflect.get(target, key, receiver);
|
|
if (isSymbol(key)
|
|
? builtInSymbols.has(key)
|
|
: key === `__proto__` || key === `__v_isRef`) {
|
|
return res;
|
|
}
|
|
if (!isReadonly) {
|
|
track(target, "get" /* GET */, key);
|
|
}
|
|
if (shallow) {
|
|
return res;
|
|
}
|
|
if (isRef(res)) {
|
|
// ref unwrapping, only for Objects, not for Arrays.
|
|
return targetIsArray ? 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 = /*#__PURE__*/ createSetter();
|
|
const shallowSet = /*#__PURE__*/ createSetter(true);
|
|
function createSetter(shallow = false) {
|
|
return function set(target, key, value, receiver) {
|
|
const oldValue = target[key];
|
|
if (!shallow) {
|
|
value = toRaw(value);
|
|
if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
|
|
oldValue.value = value;
|
|
return true;
|
|
}
|
|
}
|
|
const hadKey = 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" /* ADD */, key, value);
|
|
}
|
|
else if (hasChanged(value, oldValue)) {
|
|
trigger(target, "set" /* 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" /* DELETE */, key, undefined, oldValue);
|
|
}
|
|
return result;
|
|
}
|
|
function has(target, key) {
|
|
const result = Reflect.has(target, key);
|
|
if (!isSymbol(key) || !builtInSymbols.has(key)) {
|
|
track(target, "has" /* HAS */, key);
|
|
}
|
|
return result;
|
|
}
|
|
function ownKeys(target) {
|
|
track(target, "iterate" /* ITERATE */, ITERATE_KEY);
|
|
return Reflect.ownKeys(target);
|
|
}
|
|
const mutableHandlers = {
|
|
get,
|
|
set,
|
|
deleteProperty,
|
|
has,
|
|
ownKeys
|
|
};
|
|
const readonlyHandlers = {
|
|
get: readonlyGet,
|
|
has,
|
|
ownKeys,
|
|
set(target, key) {
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
|
|
}
|
|
return true;
|
|
},
|
|
deleteProperty(target, key) {
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
const shallowReactiveHandlers = extend({}, mutableHandlers, {
|
|
get: shallowGet,
|
|
set: shallowSet
|
|
});
|
|
// Props handlers are special in the sense that it should not unwrap top-level
|
|
// refs (in order to allow refs to be explicitly passed down), but should
|
|
// retain the reactivity of the normal readonly object.
|
|
const shallowReadonlyHandlers = extend({}, readonlyHandlers, {
|
|
get: shallowReadonlyGet
|
|
});
|
|
|
|
const toReactive = (value) => isObject(value) ? reactive(value) : value;
|
|
const toReadonly = (value) => isObject(value) ? readonly(value) : value;
|
|
const toShallow = (value) => value;
|
|
const getProto = (v) => Reflect.getPrototypeOf(v);
|
|
function get$1(target, key, wrap) {
|
|
target = toRaw(target);
|
|
const rawKey = toRaw(key);
|
|
if (key !== rawKey) {
|
|
track(target, "get" /* GET */, key);
|
|
}
|
|
track(target, "get" /* GET */, rawKey);
|
|
const { has, get } = getProto(target);
|
|
if (has.call(target, key)) {
|
|
return wrap(get.call(target, key));
|
|
}
|
|
else if (has.call(target, rawKey)) {
|
|
return wrap(get.call(target, rawKey));
|
|
}
|
|
}
|
|
function has$1(key) {
|
|
const target = toRaw(this);
|
|
const rawKey = toRaw(key);
|
|
if (key !== rawKey) {
|
|
track(target, "has" /* HAS */, key);
|
|
}
|
|
track(target, "has" /* HAS */, rawKey);
|
|
const has = getProto(target).has;
|
|
return has.call(target, key) || has.call(target, rawKey);
|
|
}
|
|
function size(target) {
|
|
target = toRaw(target);
|
|
track(target, "iterate" /* ITERATE */, ITERATE_KEY);
|
|
return Reflect.get(getProto(target), 'size', target);
|
|
}
|
|
function add(value) {
|
|
value = toRaw(value);
|
|
const target = toRaw(this);
|
|
const proto = getProto(target);
|
|
const hadKey = proto.has.call(target, value);
|
|
const result = proto.add.call(target, value);
|
|
if (!hadKey) {
|
|
trigger(target, "add" /* ADD */, value, value);
|
|
}
|
|
return result;
|
|
}
|
|
function set$1(key, value) {
|
|
value = toRaw(value);
|
|
const target = toRaw(this);
|
|
const { has, get, set } = 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);
|
|
const result = set.call(target, key, value);
|
|
if (!hadKey) {
|
|
trigger(target, "add" /* ADD */, key, value);
|
|
}
|
|
else if (hasChanged(value, oldValue)) {
|
|
trigger(target, "set" /* SET */, key, value, oldValue);
|
|
}
|
|
return result;
|
|
}
|
|
function deleteEntry(key) {
|
|
const target = toRaw(this);
|
|
const { has, get, delete: del } = 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 = del.call(target, key);
|
|
if (hadKey) {
|
|
trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
|
|
}
|
|
return result;
|
|
}
|
|
function clear() {
|
|
const target = toRaw(this);
|
|
const hadItems = target.size !== 0;
|
|
const oldTarget = (process.env.NODE_ENV !== 'production')
|
|
? target instanceof Map
|
|
? new Map(target)
|
|
: new Set(target)
|
|
: undefined;
|
|
// forward the operation before queueing reactions
|
|
const result = getProto(target).clear.call(target);
|
|
if (hadItems) {
|
|
trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
|
|
}
|
|
return result;
|
|
}
|
|
function createForEach(isReadonly, shallow) {
|
|
return function forEach(callback, thisArg) {
|
|
const observed = this;
|
|
const target = toRaw(observed);
|
|
const wrap = isReadonly ? toReadonly : shallow ? toShallow : toReactive;
|
|
!isReadonly && track(target, "iterate" /* ITERATE */, ITERATE_KEY);
|
|
// important: create 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.
|
|
function wrappedCallback(value, key) {
|
|
return callback.call(thisArg, wrap(value), wrap(key), observed);
|
|
}
|
|
return getProto(target).forEach.call(target, wrappedCallback);
|
|
};
|
|
}
|
|
function createIterableMethod(method, isReadonly, shallow) {
|
|
return function (...args) {
|
|
const target = toRaw(this);
|
|
const isMap = target instanceof Map;
|
|
const isPair = method === 'entries' || (method === Symbol.iterator && isMap);
|
|
const isKeyOnly = method === 'keys' && isMap;
|
|
const innerIterator = getProto(target)[method].apply(target, args);
|
|
const wrap = isReadonly ? toReadonly : shallow ? toShallow : toReactive;
|
|
!isReadonly &&
|
|
track(target, "iterate" /* 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" /* DELETE */ ? false : this;
|
|
};
|
|
}
|
|
const mutableInstrumentations = {
|
|
get(key) {
|
|
return get$1(this, key, toReactive);
|
|
},
|
|
get size() {
|
|
return size(this);
|
|
},
|
|
has: has$1,
|
|
add,
|
|
set: set$1,
|
|
delete: deleteEntry,
|
|
clear,
|
|
forEach: createForEach(false, false)
|
|
};
|
|
const shallowInstrumentations = {
|
|
get(key) {
|
|
return get$1(this, key, toShallow);
|
|
},
|
|
get size() {
|
|
return size(this);
|
|
},
|
|
has: has$1,
|
|
add,
|
|
set: set$1,
|
|
delete: deleteEntry,
|
|
clear,
|
|
forEach: createForEach(false, true)
|
|
};
|
|
const readonlyInstrumentations = {
|
|
get(key) {
|
|
return get$1(this, key, toReadonly);
|
|
},
|
|
get size() {
|
|
return size(this);
|
|
},
|
|
has: has$1,
|
|
add: createReadonlyMethod("add" /* ADD */),
|
|
set: createReadonlyMethod("set" /* SET */),
|
|
delete: createReadonlyMethod("delete" /* DELETE */),
|
|
clear: createReadonlyMethod("clear" /* CLEAR */),
|
|
forEach: createForEach(true, false)
|
|
};
|
|
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);
|
|
});
|
|
function createInstrumentationGetter(isReadonly, shallow) {
|
|
const instrumentations = shallow
|
|
? shallowInstrumentations
|
|
: isReadonly
|
|
? readonlyInstrumentations
|
|
: mutableInstrumentations;
|
|
return (target, key, receiver) => {
|
|
if (key === "__v_isReactive" /* IS_REACTIVE */) {
|
|
return !isReadonly;
|
|
}
|
|
else if (key === "__v_isReadonly" /* IS_READONLY */) {
|
|
return isReadonly;
|
|
}
|
|
else if (key === "__v_raw" /* RAW */) {
|
|
return target;
|
|
}
|
|
return Reflect.get(hasOwn(instrumentations, key) && key in target
|
|
? instrumentations
|
|
: target, key, receiver);
|
|
};
|
|
}
|
|
const mutableCollectionHandlers = {
|
|
get: createInstrumentationGetter(false, false)
|
|
};
|
|
const shallowCollectionHandlers = {
|
|
get: createInstrumentationGetter(false, true)
|
|
};
|
|
const readonlyCollectionHandlers = {
|
|
get: createInstrumentationGetter(true, false)
|
|
};
|
|
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 collectionTypes = new Set([Set, Map, WeakMap, WeakSet]);
|
|
const isObservableType = /*#__PURE__*/ makeMap('Object,Array,Map,Set,WeakMap,WeakSet');
|
|
const canObserve = (value) => {
|
|
return (!value["__v_skip" /* SKIP */] &&
|
|
isObservableType(toRawType(value)) &&
|
|
!Object.isFrozen(value));
|
|
};
|
|
function reactive(target) {
|
|
// if trying to observe a readonly proxy, return the readonly version.
|
|
if (target && target["__v_isReadonly" /* IS_READONLY */]) {
|
|
return target;
|
|
}
|
|
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers);
|
|
}
|
|
// Return a reactive-copy of the original object, where only the root level
|
|
// properties are reactive, and does NOT unwrap refs nor recursively convert
|
|
// returned properties.
|
|
function shallowReactive(target) {
|
|
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers);
|
|
}
|
|
function readonly(target) {
|
|
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers);
|
|
}
|
|
// Return 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, readonlyCollectionHandlers);
|
|
}
|
|
function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers) {
|
|
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" /* RAW */] &&
|
|
!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
|
|
return target;
|
|
}
|
|
// target already has corresponding Proxy
|
|
const reactiveFlag = isReadonly
|
|
? "__v_readonly" /* READONLY */
|
|
: "__v_reactive" /* REACTIVE */;
|
|
if (hasOwn(target, reactiveFlag)) {
|
|
return target[reactiveFlag];
|
|
}
|
|
// only a whitelist of value types can be observed.
|
|
if (!canObserve(target)) {
|
|
return target;
|
|
}
|
|
const observed = new Proxy(target, collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers);
|
|
def(target, reactiveFlag, observed);
|
|
return observed;
|
|
}
|
|
function isReactive(value) {
|
|
if (isReadonly(value)) {
|
|
return isReactive(value["__v_raw" /* RAW */]);
|
|
}
|
|
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
|
|
}
|
|
function isReadonly(value) {
|
|
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
|
|
}
|
|
function isProxy(value) {
|
|
return isReactive(value) || isReadonly(value);
|
|
}
|
|
function toRaw(observed) {
|
|
return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
|
|
}
|
|
function markRaw(value) {
|
|
def(value, "__v_skip" /* SKIP */, true);
|
|
return value;
|
|
}
|
|
|
|
const convert = (val) => isObject(val) ? reactive(val) : val;
|
|
function isRef(r) {
|
|
return r ? r.__v_isRef === true : false;
|
|
}
|
|
function ref(value) {
|
|
return createRef(value);
|
|
}
|
|
function shallowRef(value) {
|
|
return createRef(value, true);
|
|
}
|
|
function createRef(rawValue, shallow = false) {
|
|
if (isRef(rawValue)) {
|
|
return rawValue;
|
|
}
|
|
let value = shallow ? rawValue : convert(rawValue);
|
|
const r = {
|
|
__v_isRef: true,
|
|
get value() {
|
|
track(r, "get" /* GET */, 'value');
|
|
return value;
|
|
},
|
|
set value(newVal) {
|
|
if (hasChanged(toRaw(newVal), rawValue)) {
|
|
rawValue = newVal;
|
|
value = shallow ? newVal : convert(newVal);
|
|
trigger(r, "set" /* SET */, 'value', (process.env.NODE_ENV !== 'production') ? { newValue: newVal } : void 0);
|
|
}
|
|
}
|
|
};
|
|
return r;
|
|
}
|
|
function triggerRef(ref) {
|
|
trigger(ref, "set" /* SET */, 'value', (process.env.NODE_ENV !== 'production') ? { newValue: ref.value } : void 0);
|
|
}
|
|
function unref(ref) {
|
|
return isRef(ref) ? ref.value : ref;
|
|
}
|
|
function customRef(factory) {
|
|
const { get, set } = factory(() => track(r, "get" /* GET */, 'value'), () => trigger(r, "set" /* SET */, 'value'));
|
|
const r = {
|
|
__v_isRef: true,
|
|
get value() {
|
|
return get();
|
|
},
|
|
set value(v) {
|
|
set(v);
|
|
}
|
|
};
|
|
return r;
|
|
}
|
|
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 = {};
|
|
for (const key in object) {
|
|
ret[key] = toRef(object, key);
|
|
}
|
|
return ret;
|
|
}
|
|
function toRef(object, key) {
|
|
return {
|
|
__v_isRef: true,
|
|
get value() {
|
|
return object[key];
|
|
},
|
|
set value(newVal) {
|
|
object[key] = newVal;
|
|
}
|
|
};
|
|
}
|
|
|
|
function computed(getterOrOptions) {
|
|
let getter;
|
|
let setter;
|
|
if (isFunction(getterOrOptions)) {
|
|
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;
|
|
}
|
|
let dirty = true;
|
|
let value;
|
|
let computed;
|
|
const runner = effect(getter, {
|
|
lazy: true,
|
|
scheduler: () => {
|
|
if (!dirty) {
|
|
dirty = true;
|
|
trigger(computed, "set" /* SET */, 'value');
|
|
}
|
|
}
|
|
});
|
|
computed = {
|
|
__v_isRef: true,
|
|
["__v_isReadonly" /* IS_READONLY */]: isFunction(getterOrOptions) || !getterOrOptions.set,
|
|
// expose effect so computed can be stopped
|
|
effect: runner,
|
|
get value() {
|
|
if (dirty) {
|
|
value = runner();
|
|
dirty = false;
|
|
}
|
|
track(computed, "get" /* GET */, 'value');
|
|
return value;
|
|
},
|
|
set value(newValue) {
|
|
setter(newValue);
|
|
}
|
|
};
|
|
return computed;
|
|
}
|
|
|
|
const stack = [];
|
|
function pushWarningContext(vnode) {
|
|
stack.push(vnode);
|
|
}
|
|
function popWarningContext() {
|
|
stack.pop();
|
|
}
|
|
function warn(msg, ...args) {
|
|
// avoid props formatting or warn handler tracking deps that might be mutated
|
|
// during patch, leading to infinite recursion.
|
|
pauseTracking();
|
|
const instance = stack.length ? stack[stack.length - 1].component : null;
|
|
const appWarnHandler = instance && instance.appContext.config.warnHandler;
|
|
const trace = getComponentTrace();
|
|
if (appWarnHandler) {
|
|
callWithErrorHandling(appWarnHandler, instance, 11 /* APP_WARN_HANDLER */, [
|
|
msg + args.join(''),
|
|
instance && instance.proxy,
|
|
trace
|
|
.map(({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`)
|
|
.join('\n'),
|
|
trace
|
|
]);
|
|
}
|
|
else {
|
|
const warnArgs = [`[Vue warn]: ${msg}`, ...args];
|
|
/* istanbul ignore if */
|
|
if (trace.length &&
|
|
// avoid spamming console during tests
|
|
!false) {
|
|
warnArgs.push(`\n`, ...formatTrace(trace));
|
|
}
|
|
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 = {
|
|
["bc" /* BEFORE_CREATE */]: 'beforeCreate hook',
|
|
["c" /* CREATED */]: 'created hook',
|
|
["bm" /* BEFORE_MOUNT */]: 'beforeMount hook',
|
|
["m" /* MOUNTED */]: 'mounted hook',
|
|
["bu" /* BEFORE_UPDATE */]: 'beforeUpdate hook',
|
|
["u" /* UPDATED */]: 'updated',
|
|
["bum" /* BEFORE_UNMOUNT */]: 'beforeUnmount hook',
|
|
["um" /* UNMOUNTED */]: 'unmounted hook',
|
|
["a" /* ACTIVATED */]: 'activated hook',
|
|
["da" /* DEACTIVATED */]: 'deactivated hook',
|
|
["ec" /* ERROR_CAPTURED */]: 'errorCaptured hook',
|
|
["rtc" /* RENDER_TRACKED */]: 'renderTracked hook',
|
|
["rtg" /* RENDER_TRIGGERED */]: 'renderTriggered hook',
|
|
[0 /* SETUP_FUNCTION */]: 'setup function',
|
|
[1 /* RENDER_FUNCTION */]: 'render function',
|
|
[2 /* WATCH_GETTER */]: 'watcher getter',
|
|
[3 /* WATCH_CALLBACK */]: 'watcher callback',
|
|
[4 /* WATCH_CLEANUP */]: 'watcher cleanup function',
|
|
[5 /* NATIVE_EVENT_HANDLER */]: 'native event handler',
|
|
[6 /* COMPONENT_EVENT_HANDLER */]: 'component event handler',
|
|
[7 /* VNODE_HOOK */]: 'vnode hook',
|
|
[8 /* DIRECTIVE_HOOK */]: 'directive hook',
|
|
[9 /* TRANSITION_HOOK */]: 'transition hook',
|
|
[10 /* APP_ERROR_HANDLER */]: 'app errorHandler',
|
|
[11 /* APP_WARN_HANDLER */]: 'app warnHandler',
|
|
[12 /* FUNCTION_REF */]: 'ref function',
|
|
[13 /* ASYNC_COMPONENT_LOADER */]: 'async component loader',
|
|
[14 /* SCHEDULER */]: 'scheduler flush. This is likely a Vue internals bug. ' +
|
|
'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next'
|
|
};
|
|
function callWithErrorHandling(fn, instance, type, args) {
|
|
let res;
|
|
try {
|
|
res = args ? fn(...args) : fn();
|
|
}
|
|
catch (err) {
|
|
handleError(err, instance, type);
|
|
}
|
|
return res;
|
|
}
|
|
function callWithAsyncErrorHandling(fn, instance, type, args) {
|
|
if (isFunction(fn)) {
|
|
const res = callWithErrorHandling(fn, instance, type, args);
|
|
if (res && isPromise(res)) {
|
|
res.catch(err => {
|
|
handleError(err, instance, type);
|
|
});
|
|
}
|
|
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) {
|
|
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 xxxxxx
|
|
while (cur) {
|
|
const errorCapturedHooks = cur.ec;
|
|
if (errorCapturedHooks) {
|
|
for (let i = 0; i < errorCapturedHooks.length; i++) {
|
|
if (errorCapturedHooks[i](err, exposedInstance, errorInfo)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
cur = cur.parent;
|
|
}
|
|
// app-level handling
|
|
const appErrorHandler = instance.appContext.config.errorHandler;
|
|
if (appErrorHandler) {
|
|
callWithErrorHandling(appErrorHandler, null, 10 /* APP_ERROR_HANDLER */, [err, exposedInstance, errorInfo]);
|
|
return;
|
|
}
|
|
}
|
|
logError(err, type, contextVNode);
|
|
}
|
|
// fixed by xxxxxx
|
|
function logError(err, type, contextVNode) {
|
|
// default behavior is crash in prod & test, recover in dev.
|
|
if ((process.env.NODE_ENV !== 'production') && ( !false)) {
|
|
const info = ErrorTypeStrings[type] || type; // fixed by xxxxxx
|
|
if (contextVNode) {
|
|
pushWarningContext(contextVNode);
|
|
}
|
|
warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`);
|
|
console.error(err);
|
|
if (contextVNode) {
|
|
popWarningContext();
|
|
}
|
|
}
|
|
else {
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// fixed by xxxxxx
|
|
const queue = [];
|
|
const postFlushCbs = [];
|
|
const p = Promise.resolve();
|
|
let isFlushing = false;
|
|
let isFlushPending = false;
|
|
let flushIndex = 0;
|
|
let pendingPostFlushCbs = null;
|
|
let pendingPostFlushIndex = 0;
|
|
const RECURSION_LIMIT = 100;
|
|
function nextTick(fn) {
|
|
return fn ? p.then(fn) : p;
|
|
}
|
|
function queueJob(job) {
|
|
if (!queue.includes(job, flushIndex)) {
|
|
queue.push(job);
|
|
queueFlush();
|
|
}
|
|
}
|
|
function queuePostFlushCb(cb) {
|
|
if (!isArray(cb)) {
|
|
if (!pendingPostFlushCbs ||
|
|
!pendingPostFlushCbs.includes(cb, pendingPostFlushIndex)) {
|
|
postFlushCbs.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 dupicate check here to improve perf
|
|
postFlushCbs.push(...cb);
|
|
}
|
|
queueFlush();
|
|
}
|
|
function queueFlush() {
|
|
if (!isFlushing && !isFlushPending) {
|
|
isFlushPending = true;
|
|
nextTick(flushJobs);
|
|
}
|
|
}
|
|
function flushPostFlushCbs(seen) {
|
|
if (postFlushCbs.length) {
|
|
pendingPostFlushCbs = [...new Set(postFlushCbs)];
|
|
postFlushCbs.length = 0;
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
seen = seen || new Map();
|
|
}
|
|
for (pendingPostFlushIndex = 0; pendingPostFlushIndex < pendingPostFlushCbs.length; pendingPostFlushIndex++) {
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
checkRecursiveUpdates(seen, pendingPostFlushCbs[pendingPostFlushIndex]);
|
|
}
|
|
pendingPostFlushCbs[pendingPostFlushIndex]();
|
|
}
|
|
pendingPostFlushCbs = null;
|
|
pendingPostFlushIndex = 0;
|
|
}
|
|
}
|
|
const getId = (job) => (job.id == null ? Infinity : job.id);
|
|
function flushJobs(seen) {
|
|
isFlushPending = false;
|
|
isFlushing = true;
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
seen = seen || new Map();
|
|
}
|
|
// 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.
|
|
// Jobs can never be null before flush starts, since they are only invalidated
|
|
// during execution of another flushed job.
|
|
queue.sort((a, b) => getId(a) - getId(b));
|
|
for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
|
|
const job = queue[flushIndex];
|
|
if (job) {
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
checkRecursiveUpdates(seen, job);
|
|
}
|
|
callWithErrorHandling(job, null, 14 /* SCHEDULER */);
|
|
}
|
|
}
|
|
flushIndex = 0;
|
|
queue.length = 0;
|
|
flushPostFlushCbs(seen);
|
|
isFlushing = false;
|
|
// some postFlushCb queued jobs!
|
|
// keep flushing until it drains.
|
|
if (queue.length || postFlushCbs.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) {
|
|
throw new Error('Maximum recursive updates exceeded. ' +
|
|
"You may have code that is mutating state in your component's " +
|
|
'render function or updated hook or watcher source function.');
|
|
}
|
|
else {
|
|
seen.set(fn, count + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// mark the current rendering instance for asset resolution (e.g.
|
|
// resolveComponent, resolveDirective) during render
|
|
let currentRenderingInstance = null;
|
|
function markAttrsAccessed() {
|
|
}
|
|
|
|
function emit(instance, event, ...args) {
|
|
const props = instance.vnode.props || EMPTY_OBJ;
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
const options = normalizeEmitsOptions(instance.type);
|
|
if (options) {
|
|
if (!(event in options)) {
|
|
const propsOptions = normalizePropsOptions(instance.type)[0];
|
|
if (!propsOptions || !(`on` + capitalize(event) in propsOptions)) {
|
|
warn(`Component emitted event "${event}" but it is neither declared in ` +
|
|
`the emits option nor as an "on${capitalize(event)}" prop.`);
|
|
}
|
|
}
|
|
else {
|
|
const validator = options[event];
|
|
if (isFunction(validator)) {
|
|
const isValid = validator(...args);
|
|
if (!isValid) {
|
|
warn(`Invalid event arguments: event validation failed for event "${event}".`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let handlerName = `on${capitalize(event)}`;
|
|
let handler = props[handlerName];
|
|
// for v-model update:xxx events, also trigger kebab-case equivalent
|
|
// for props passed via kebab-case
|
|
if (!handler && event.startsWith('update:')) {
|
|
handlerName = `on${capitalize(hyphenate(event))}`;
|
|
handler = props[handlerName];
|
|
}
|
|
if (!handler) {
|
|
handler = props[handlerName + `Once`];
|
|
if (!instance.emitted) {
|
|
(instance.emitted = {})[handlerName] = true;
|
|
}
|
|
else if (instance.emitted[handlerName]) {
|
|
return;
|
|
}
|
|
}
|
|
if (handler) {
|
|
callWithAsyncErrorHandling(handler, instance, 6 /* COMPONENT_EVENT_HANDLER */, args);
|
|
}
|
|
}
|
|
function normalizeEmitsOptions(comp) {
|
|
if (hasOwn(comp, '__emits')) {
|
|
return comp.__emits;
|
|
}
|
|
const raw = comp.emits;
|
|
let normalized = {};
|
|
// apply mixin/extends props
|
|
let hasExtends = false;
|
|
if (__VUE_OPTIONS_API__ && !isFunction(comp)) {
|
|
if (comp.extends) {
|
|
hasExtends = true;
|
|
extend(normalized, normalizeEmitsOptions(comp.extends));
|
|
}
|
|
if (comp.mixins) {
|
|
hasExtends = true;
|
|
comp.mixins.forEach(m => extend(normalized, normalizeEmitsOptions(m)));
|
|
}
|
|
}
|
|
if (!raw && !hasExtends) {
|
|
return (comp.__emits = undefined);
|
|
}
|
|
if (isArray(raw)) {
|
|
raw.forEach(key => (normalized[key] = null));
|
|
}
|
|
else {
|
|
extend(normalized, raw);
|
|
}
|
|
return (comp.__emits = 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(comp, key) {
|
|
let emits;
|
|
if (!isOn(key) || !(emits = normalizeEmitsOptions(comp))) {
|
|
return false;
|
|
}
|
|
key = key.replace(/Once$/, '');
|
|
return (hasOwn(emits, key[2].toLowerCase() + key.slice(3)) ||
|
|
hasOwn(emits, key.slice(2)));
|
|
}
|
|
|
|
function initProps(instance, rawProps, isStateful, // result of bitwise flag comparison
|
|
isSSR = false) {
|
|
const props = {};
|
|
const attrs = {};
|
|
// def(attrs, InternalObjectKey, 1) // fixed by xxxxx
|
|
def(attrs, '__vInternal', 1);
|
|
setFullProps(instance, rawProps, props, attrs);
|
|
// validation
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
validateProps(props, instance.type);
|
|
}
|
|
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 setFullProps(instance, rawProps, props, attrs) {
|
|
const [options, needCastKeys] = normalizePropsOptions(instance.type);
|
|
if (rawProps) {
|
|
for (const key in rawProps) {
|
|
const value = rawProps[key];
|
|
// key, ref are reserved and never passed down
|
|
if (isReservedProp(key)) {
|
|
continue;
|
|
}
|
|
// prop option names are camelized during normalization, so to support
|
|
// kebab -> camel conversion here we need to camelize the key.
|
|
let camelKey;
|
|
if (options && hasOwn(options, (camelKey = camelize(key)))) {
|
|
props[camelKey] = value;
|
|
}
|
|
else if (!isEmitListener(instance.type, key)) {
|
|
// Any non-declared (either as a prop or an emitted event) props are put
|
|
// into a separate `attrs` object for spreading. Make sure to preserve
|
|
// original key casing
|
|
attrs[key] = value;
|
|
}
|
|
}
|
|
}
|
|
if (needCastKeys) {
|
|
const rawCurrentProps = toRaw(props);
|
|
for (let i = 0; i < needCastKeys.length; i++) {
|
|
const key = needCastKeys[i];
|
|
props[key] = resolvePropValue(options, rawCurrentProps, key, rawCurrentProps[key]);
|
|
}
|
|
}
|
|
}
|
|
function resolvePropValue(options, props, key, value) {
|
|
const opt = options[key];
|
|
if (opt != null) {
|
|
const hasDefault = hasOwn(opt, 'default');
|
|
// default values
|
|
if (hasDefault && value === undefined) {
|
|
const defaultValue = opt.default;
|
|
value =
|
|
opt.type !== Function && isFunction(defaultValue)
|
|
? defaultValue()
|
|
: defaultValue;
|
|
}
|
|
// boolean casting
|
|
if (opt[0 /* shouldCast */]) {
|
|
if (!hasOwn(props, key) && !hasDefault) {
|
|
value = false;
|
|
}
|
|
else if (opt[1 /* shouldCastTrue */] &&
|
|
(value === '' || value === hyphenate(key))) {
|
|
value = true;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
function normalizePropsOptions(comp) {
|
|
if (comp.__props) {
|
|
return comp.__props;
|
|
}
|
|
const raw = comp.props;
|
|
const normalized = {};
|
|
const needCastKeys = [];
|
|
// apply mixin/extends props
|
|
let hasExtends = false;
|
|
if (__VUE_OPTIONS_API__ && !isFunction(comp)) {
|
|
const extendProps = (raw) => {
|
|
const [props, keys] = normalizePropsOptions(raw);
|
|
extend(normalized, props);
|
|
if (keys)
|
|
needCastKeys.push(...keys);
|
|
};
|
|
if (comp.extends) {
|
|
hasExtends = true;
|
|
extendProps(comp.extends);
|
|
}
|
|
if (comp.mixins) {
|
|
hasExtends = true;
|
|
comp.mixins.forEach(extendProps);
|
|
}
|
|
}
|
|
if (!raw && !hasExtends) {
|
|
return (comp.__props = 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 } : opt);
|
|
if (prop) {
|
|
const booleanIndex = getTypeIndex(Boolean, prop.type);
|
|
const stringIndex = getTypeIndex(String, prop.type);
|
|
prop[0 /* shouldCast */] = booleanIndex > -1;
|
|
prop[1 /* shouldCastTrue */] =
|
|
stringIndex < 0 || booleanIndex < stringIndex;
|
|
// if the prop needs boolean casting or default value
|
|
if (booleanIndex > -1 || hasOwn(prop, 'default')) {
|
|
needCastKeys.push(normalizedKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const normalizedEntry = [normalized, needCastKeys];
|
|
comp.__props = normalizedEntry;
|
|
return normalizedEntry;
|
|
}
|
|
// 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 (\w+)/);
|
|
return match ? match[1] : '';
|
|
}
|
|
function isSameType(a, b) {
|
|
return getType(a) === getType(b);
|
|
}
|
|
function getTypeIndex(type, expectedTypes) {
|
|
if (isArray(expectedTypes)) {
|
|
for (let i = 0, len = expectedTypes.length; i < len; i++) {
|
|
if (isSameType(expectedTypes[i], type)) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
else if (isFunction(expectedTypes)) {
|
|
return isSameType(expectedTypes, type) ? 0 : -1;
|
|
}
|
|
return -1;
|
|
}
|
|
/**
|
|
* dev only
|
|
*/
|
|
function validateProps(props, comp) {
|
|
const rawValues = toRaw(props);
|
|
const options = normalizePropsOptions(comp)[0];
|
|
for (const key in options) {
|
|
let opt = options[key];
|
|
if (opt == null)
|
|
continue;
|
|
validateProp(key, rawValues[key], opt, !hasOwn(rawValues, key));
|
|
}
|
|
}
|
|
/**
|
|
* dev only
|
|
*/
|
|
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;
|
|
}
|
|
/**
|
|
* 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');
|
|
/**
|
|
* 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 = toRawType(value) === 'Object';
|
|
}
|
|
else if (expectedType === 'Array') {
|
|
valid = isArray(value);
|
|
}
|
|
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 injectHook(type, hook, target = currentInstance, prepend = false) {
|
|
if (target) {
|
|
const hooks = target[type] || (target[type] = []);
|
|
// cache the error handling wrapper for injected hooks so the same hook
|
|
// can be properly deduped by the scheduler. "__weh" stands for "with error
|
|
// handling".
|
|
const wrappedHook = hook.__weh ||
|
|
(hook.__weh = (...args) => {
|
|
if (target.isUnmounted) {
|
|
return;
|
|
}
|
|
// disable tracking inside all lifecycle hooks
|
|
// since they can potentially be called inside effects.
|
|
pauseTracking();
|
|
// Set currentInstance during hook invocation.
|
|
// This assumes the hook does not synchronously trigger other hooks, which
|
|
// can only be false when the user does something really funky.
|
|
setCurrentInstance(target);
|
|
const res = callWithAsyncErrorHandling(hook, target, type, args);
|
|
setCurrentInstance(null);
|
|
resetTracking();
|
|
return res;
|
|
});
|
|
if (prepend) {
|
|
hooks.unshift(wrappedHook);
|
|
}
|
|
else {
|
|
hooks.push(wrappedHook);
|
|
}
|
|
}
|
|
else if ((process.env.NODE_ENV !== 'production')) {
|
|
const apiName = `on${capitalize(ErrorTypeStrings[type].replace(/ hook$/, ''))}`;
|
|
warn(`${apiName} is called when there is no active component instance to be ` +
|
|
`associated with. ` +
|
|
`Lifecycle injection APIs can only be used during execution of setup().` +
|
|
( ``));
|
|
}
|
|
}
|
|
const createHook = (lifecycle) => (hook, target = currentInstance) =>
|
|
// post-create lifecycle registrations are noops during SSR
|
|
!isInSSRComponentSetup && injectHook(lifecycle, hook, target);
|
|
const onBeforeMount = createHook("bm" /* BEFORE_MOUNT */);
|
|
const onMounted = createHook("m" /* MOUNTED */);
|
|
const onBeforeUpdate = createHook("bu" /* BEFORE_UPDATE */);
|
|
const onUpdated = createHook("u" /* UPDATED */);
|
|
const onBeforeUnmount = createHook("bum" /* BEFORE_UNMOUNT */);
|
|
const onUnmounted = createHook("um" /* UNMOUNTED */);
|
|
const onRenderTriggered = createHook("rtg" /* RENDER_TRIGGERED */);
|
|
const onRenderTracked = createHook("rtc" /* RENDER_TRACKED */);
|
|
const onErrorCaptured = (hook, target = currentInstance) => {
|
|
injectHook("ec" /* ERROR_CAPTURED */, hook, target);
|
|
};
|
|
|
|
const isKeepAlive = (vnode) => vnode.type.__isKeepAlive;
|
|
function onActivated(hook, target) {
|
|
registerKeepAliveHook(hook, "a" /* ACTIVATED */, target);
|
|
}
|
|
function onDeactivated(hook, target) {
|
|
registerKeepAliveHook(hook, "da" /* DEACTIVATED */, target);
|
|
}
|
|
function registerKeepAliveHook(hook, type, target = currentInstance) {
|
|
// cache the deactivate branch check wrapper for injected hooks so the same
|
|
// hook can be properly deduped by the scheduler. "__wdc" stands for "with
|
|
// deactivation check".
|
|
const wrappedHook = hook.__wdc ||
|
|
(hook.__wdc = () => {
|
|
// only fire the hook if the target instance is NOT in a deactivated branch.
|
|
let current = target;
|
|
while (current) {
|
|
if (current.isDeactivated) {
|
|
return;
|
|
}
|
|
current = current.parent;
|
|
}
|
|
hook();
|
|
});
|
|
injectHook(type, wrappedHook, target);
|
|
// In addition to registering it on the target instance, we walk up the parent
|
|
// chain and register it on all ancestor instances that are keep-alive roots.
|
|
// This avoids the need to walk the entire component tree when invoking these
|
|
// hooks, and more importantly, avoids the need to track child components in
|
|
// arrays.
|
|
if (target) {
|
|
let current = target.parent;
|
|
while (current && current.parent) {
|
|
if (isKeepAlive(current.parent.vnode)) {
|
|
injectToKeepAliveRoot(wrappedHook, type, target, current);
|
|
}
|
|
current = current.parent;
|
|
}
|
|
}
|
|
}
|
|
function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) {
|
|
injectHook(type, hook, keepAliveRoot, true /* prepend */);
|
|
onUnmounted(() => {
|
|
remove(keepAliveRoot[type], 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]
|
|
])
|
|
*/
|
|
const isBuiltInDirective = /*#__PURE__*/ makeMap('bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text');
|
|
function validateDirectiveName(name) {
|
|
if (isBuiltInDirective(name)) {
|
|
warn('Do not use built-in directive ids as custom directive id: ' + name);
|
|
}
|
|
}
|
|
|
|
function createAppContext() {
|
|
return {
|
|
app: null,
|
|
config: {
|
|
isNativeTag: NO,
|
|
performance: false,
|
|
globalProperties: {},
|
|
optionMergeStrategies: {},
|
|
isCustomElement: NO,
|
|
errorHandler: undefined,
|
|
warnHandler: undefined
|
|
},
|
|
mixins: [],
|
|
components: {},
|
|
directives: {},
|
|
provides: Object.create(null)
|
|
};
|
|
}
|
|
// fixed by xxxxxx
|
|
function createAppAPI() {
|
|
return function createApp(rootComponent, rootProps = null) {
|
|
if (rootProps != null && !isObject(rootProps)) {
|
|
(process.env.NODE_ENV !== 'production') && warn(`root props passed to app.mount() must be an object.`);
|
|
rootProps = null;
|
|
}
|
|
const context = createAppContext();
|
|
const installedPlugins = new Set();
|
|
// fixed by xxxxxx
|
|
// let isMounted = false
|
|
const app = (context.app = {
|
|
_component: rootComponent,
|
|
_props: rootProps,
|
|
_container: null,
|
|
_context: context,
|
|
version,
|
|
get config() {
|
|
return context.config;
|
|
},
|
|
set config(v) {
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
warn(`app.config cannot be replaced. Modify individual options instead.`);
|
|
}
|
|
},
|
|
use(plugin, ...options) {
|
|
if (installedPlugins.has(plugin)) {
|
|
(process.env.NODE_ENV !== 'production') && warn(`Plugin has already been applied to target app.`);
|
|
}
|
|
else if (plugin && isFunction(plugin.install)) {
|
|
installedPlugins.add(plugin);
|
|
plugin.install(app, ...options);
|
|
}
|
|
else if (isFunction(plugin)) {
|
|
installedPlugins.add(plugin);
|
|
plugin(app, ...options);
|
|
}
|
|
else if ((process.env.NODE_ENV !== 'production')) {
|
|
warn(`A plugin must either be a function or an object with an "install" ` +
|
|
`function.`);
|
|
}
|
|
return app;
|
|
},
|
|
mixin(mixin) {
|
|
if (__VUE_OPTIONS_API__) {
|
|
if (!context.mixins.includes(mixin)) {
|
|
context.mixins.push(mixin);
|
|
}
|
|
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.`);
|
|
}
|
|
// TypeScript doesn't allow symbols as index type
|
|
// https://github.com/Microsoft/TypeScript/issues/24587
|
|
context.provides[key] = value;
|
|
return app;
|
|
}
|
|
});
|
|
return app;
|
|
};
|
|
}
|
|
|
|
const queuePostRenderEffect = queuePostFlushCb;
|
|
|
|
// Simple effect.
|
|
function watchEffect(effect, options) {
|
|
return doWatch(effect, null, options);
|
|
}
|
|
// initial value for watchers to trigger on undefined initial values
|
|
const INITIAL_WATCHER_VALUE = {};
|
|
// implementation
|
|
function watch(source, cb, options) {
|
|
if ((process.env.NODE_ENV !== 'production') && !isFunction(cb)) {
|
|
warn(`\`watch(fn, options?)\` signature has been moved to a separate API. ` +
|
|
`Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
|
|
`supports \`watch(source, cb, options?) signature.`);
|
|
}
|
|
return doWatch(source, cb, options);
|
|
}
|
|
function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ, instance = currentInstance) {
|
|
if ((process.env.NODE_ENV !== 'production') && !cb) {
|
|
if (immediate !== undefined) {
|
|
warn(`watch() "immediate" option is only respected when using the ` +
|
|
`watch(source, callback, options?) signature.`);
|
|
}
|
|
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.`);
|
|
};
|
|
let getter;
|
|
if (isRef(source)) {
|
|
getter = () => source.value;
|
|
}
|
|
else if (isReactive(source)) {
|
|
getter = () => source;
|
|
deep = true;
|
|
}
|
|
else if (isArray(source)) {
|
|
getter = () => source.map(s => {
|
|
if (isRef(s)) {
|
|
return s.value;
|
|
}
|
|
else if (isReactive(s)) {
|
|
return traverse(s);
|
|
}
|
|
else if (isFunction(s)) {
|
|
return callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */);
|
|
}
|
|
else {
|
|
(process.env.NODE_ENV !== 'production') && warnInvalidSource(s);
|
|
}
|
|
});
|
|
}
|
|
else if (isFunction(source)) {
|
|
if (cb) {
|
|
// getter with cb
|
|
getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */);
|
|
}
|
|
else {
|
|
// no cb -> simple effect
|
|
getter = () => {
|
|
if (instance && instance.isUnmounted) {
|
|
return;
|
|
}
|
|
if (cleanup) {
|
|
cleanup();
|
|
}
|
|
return callWithErrorHandling(source, instance, 3 /* WATCH_CALLBACK */, [onInvalidate]);
|
|
};
|
|
}
|
|
}
|
|
else {
|
|
getter = NOOP;
|
|
(process.env.NODE_ENV !== 'production') && warnInvalidSource(source);
|
|
}
|
|
if (cb && deep) {
|
|
const baseGetter = getter;
|
|
getter = () => traverse(baseGetter());
|
|
}
|
|
let cleanup;
|
|
const onInvalidate = (fn) => {
|
|
cleanup = runner.options.onStop = () => {
|
|
callWithErrorHandling(fn, instance, 4 /* WATCH_CLEANUP */);
|
|
};
|
|
};
|
|
let oldValue = isArray(source) ? [] : INITIAL_WATCHER_VALUE;
|
|
const job = () => {
|
|
if (!runner.active) {
|
|
return;
|
|
}
|
|
if (cb) {
|
|
// watch(source, cb)
|
|
const newValue = runner();
|
|
if (deep || hasChanged(newValue, oldValue)) {
|
|
// cleanup before running cb again
|
|
if (cleanup) {
|
|
cleanup();
|
|
}
|
|
callWithAsyncErrorHandling(cb, instance, 3 /* WATCH_CALLBACK */, [
|
|
newValue,
|
|
// pass undefined as the old value when it's changed for the first time
|
|
oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
|
|
onInvalidate
|
|
]);
|
|
oldValue = newValue;
|
|
}
|
|
}
|
|
else {
|
|
// watchEffect
|
|
runner();
|
|
}
|
|
};
|
|
let scheduler;
|
|
if (flush === 'sync') {
|
|
scheduler = job;
|
|
}
|
|
else if (flush === 'pre') {
|
|
// ensure it's queued before component updates (which have positive ids)
|
|
job.id = -1;
|
|
scheduler = () => {
|
|
if (!instance || instance.isMounted) {
|
|
queueJob(job);
|
|
}
|
|
else {
|
|
// with 'pre' option, the first call must happen before
|
|
// the component is mounted so it is called synchronously.
|
|
job();
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
scheduler = () => queuePostRenderEffect(job, instance && instance.suspense);
|
|
}
|
|
const runner = effect(getter, {
|
|
lazy: true,
|
|
onTrack,
|
|
onTrigger,
|
|
scheduler
|
|
});
|
|
recordInstanceBoundEffect(runner);
|
|
// initial run
|
|
if (cb) {
|
|
if (immediate) {
|
|
job();
|
|
}
|
|
else {
|
|
oldValue = runner();
|
|
}
|
|
}
|
|
else {
|
|
runner();
|
|
}
|
|
return () => {
|
|
stop(runner);
|
|
if (instance) {
|
|
remove(instance.effects, runner);
|
|
}
|
|
};
|
|
}
|
|
// this.$watch
|
|
function instanceWatch(source, cb, options) {
|
|
const publicThis = this.proxy;
|
|
const getter = isString(source)
|
|
? () => publicThis[source]
|
|
: source.bind(publicThis);
|
|
return doWatch(getter, cb.bind(publicThis), options, this);
|
|
}
|
|
function traverse(value, seen = new Set()) {
|
|
if (!isObject(value) || seen.has(value)) {
|
|
return value;
|
|
}
|
|
seen.add(value);
|
|
if (isArray(value)) {
|
|
for (let i = 0; i < value.length; i++) {
|
|
traverse(value[i], seen);
|
|
}
|
|
}
|
|
else if (value instanceof Map) {
|
|
value.forEach((v, key) => {
|
|
// to register mutation dep for existing keys
|
|
traverse(value.get(key), seen);
|
|
});
|
|
}
|
|
else if (value instanceof Set) {
|
|
value.forEach(v => {
|
|
traverse(v, seen);
|
|
});
|
|
}
|
|
else {
|
|
for (const key in value) {
|
|
traverse(value[key], seen);
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
function inject(key, defaultValue) {
|
|
// fallback to `currentRenderingInstance` so that this can be called in
|
|
// a functional component
|
|
const instance = currentInstance || currentRenderingInstance;
|
|
if (instance) {
|
|
const provides = instance.provides;
|
|
if (key in provides) {
|
|
// TS doesn't allow symbol as index type
|
|
return provides[key];
|
|
}
|
|
else if (arguments.length > 1) {
|
|
return 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.`);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
};
|
|
}
|
|
function applyOptions(instance, options, deferredData = [], deferredWatch = [], asMixin = false) {
|
|
const {
|
|
// composition
|
|
mixins, extends: extendsOptions,
|
|
// state
|
|
data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions,
|
|
// lifecycle
|
|
beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeUnmount, unmounted, renderTracked, renderTriggered, errorCaptured } = options;
|
|
const publicThis = instance.proxy;
|
|
const ctx = instance.ctx;
|
|
const globalMixins = instance.appContext.mixins;
|
|
// call it only during dev
|
|
// applyOptions is called non-as-mixin once per instance
|
|
if (!asMixin) {
|
|
callSyncHook('beforeCreate', options, publicThis, globalMixins);
|
|
// global mixins are applied first
|
|
applyMixins(instance, globalMixins, deferredData, deferredWatch);
|
|
}
|
|
// extending a base component...
|
|
if (extendsOptions) {
|
|
applyOptions(instance, extendsOptions, deferredData, deferredWatch, true);
|
|
}
|
|
// local mixins
|
|
if (mixins) {
|
|
applyMixins(instance, mixins, deferredData, deferredWatch);
|
|
}
|
|
const checkDuplicateProperties = (process.env.NODE_ENV !== 'production') ? createDuplicateChecker() : null;
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
const propsOptions = normalizePropsOptions(options)[0];
|
|
if (propsOptions) {
|
|
for (const key in propsOptions) {
|
|
checkDuplicateProperties("Props" /* 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) {
|
|
if (isArray(injectOptions)) {
|
|
for (let i = 0; i < injectOptions.length; i++) {
|
|
const key = injectOptions[i];
|
|
ctx[key] = inject(key);
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
checkDuplicateProperties("Inject" /* INJECT */, key);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (const key in injectOptions) {
|
|
const opt = injectOptions[key];
|
|
if (isObject(opt)) {
|
|
ctx[key] = inject(opt.from, opt.default);
|
|
}
|
|
else {
|
|
ctx[key] = inject(opt);
|
|
}
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
checkDuplicateProperties("Inject" /* INJECT */, key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (methods) {
|
|
for (const key in methods) {
|
|
const methodHandler = methods[key];
|
|
if (isFunction(methodHandler)) {
|
|
ctx[key] = methodHandler.bind(publicThis);
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
checkDuplicateProperties("Methods" /* 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.`);
|
|
}
|
|
if (asMixin) {
|
|
deferredData.push(dataOptions);
|
|
}
|
|
else {
|
|
resolveData(instance, dataOptions, publicThis);
|
|
}
|
|
}
|
|
if (!asMixin) {
|
|
if (deferredData.length) {
|
|
deferredData.forEach(dataFn => resolveData(instance, dataFn, publicThis));
|
|
}
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
const rawData = toRaw(instance.data);
|
|
for (const key in rawData) {
|
|
checkDuplicateProperties("Data" /* DATA */, key);
|
|
// expose data on ctx during dev
|
|
if (key[0] !== '$' && key[0] !== '_') {
|
|
Object.defineProperty(ctx, key, {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get: () => rawData[key],
|
|
set: NOOP
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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$1({
|
|
get,
|
|
set
|
|
});
|
|
Object.defineProperty(ctx, key, {
|
|
enumerable: true,
|
|
configurable: true,
|
|
get: () => c.value,
|
|
set: v => (c.value = v)
|
|
});
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
checkDuplicateProperties("Computed" /* COMPUTED */, key);
|
|
}
|
|
}
|
|
}
|
|
if (watchOptions) {
|
|
deferredWatch.push(watchOptions);
|
|
}
|
|
if (!asMixin && deferredWatch.length) {
|
|
deferredWatch.forEach(watchOptions => {
|
|
for (const key in watchOptions) {
|
|
createWatcher(watchOptions[key], ctx, publicThis, key);
|
|
}
|
|
});
|
|
}
|
|
// fixed by xxxxxx
|
|
if (!__VUE_CREATED_DEFERRED__ && provideOptions) {
|
|
const provides = isFunction(provideOptions)
|
|
? provideOptions.call(publicThis)
|
|
: provideOptions;
|
|
for (const key in provides) {
|
|
provide(key, provides[key]);
|
|
}
|
|
}
|
|
// fixed by xxxxxx
|
|
// lifecycle options
|
|
if (__VUE_CREATED_DEFERRED__) {
|
|
ctx.$callSyncHook = function (name) {
|
|
return callSyncHook(name, options, publicThis, globalMixins);
|
|
};
|
|
}
|
|
else if (!asMixin) {
|
|
callSyncHook('created', options, publicThis, globalMixins);
|
|
}
|
|
if (beforeMount) {
|
|
onBeforeMount(beforeMount.bind(publicThis));
|
|
}
|
|
if (mounted) {
|
|
onMounted(mounted.bind(publicThis));
|
|
}
|
|
if (beforeUpdate) {
|
|
onBeforeUpdate(beforeUpdate.bind(publicThis));
|
|
}
|
|
if (updated) {
|
|
onUpdated(updated.bind(publicThis));
|
|
}
|
|
if (activated) {
|
|
onActivated(activated.bind(publicThis));
|
|
}
|
|
if (deactivated) {
|
|
onDeactivated(deactivated.bind(publicThis));
|
|
}
|
|
if (errorCaptured) {
|
|
onErrorCaptured(errorCaptured.bind(publicThis));
|
|
}
|
|
if (renderTracked) {
|
|
onRenderTracked(renderTracked.bind(publicThis));
|
|
}
|
|
if (renderTriggered) {
|
|
onRenderTriggered(renderTriggered.bind(publicThis));
|
|
}
|
|
if (beforeUnmount) {
|
|
onBeforeUnmount(beforeUnmount.bind(publicThis));
|
|
}
|
|
if (unmounted) {
|
|
onUnmounted(unmounted.bind(publicThis));
|
|
}
|
|
// fixed by xxxxxx
|
|
if (instance.ctx.$onApplyOptions) {
|
|
instance.ctx.$onApplyOptions(options, instance, publicThis);
|
|
}
|
|
}
|
|
function callSyncHook(name, options, ctx, globalMixins) {
|
|
callHookFromMixins(name, globalMixins, ctx);
|
|
const baseHook = options.extends && options.extends[name];
|
|
if (baseHook) {
|
|
baseHook.call(ctx);
|
|
}
|
|
const mixins = options.mixins;
|
|
if (mixins) {
|
|
callHookFromMixins(name, mixins, ctx);
|
|
}
|
|
const selfHook = options[name];
|
|
if (selfHook) {
|
|
selfHook.call(ctx);
|
|
}
|
|
}
|
|
function callHookFromMixins(name, mixins, ctx) {
|
|
for (let i = 0; i < mixins.length; i++) {
|
|
const fn = mixins[i][name];
|
|
if (fn) {
|
|
fn.call(ctx);
|
|
}
|
|
}
|
|
}
|
|
function applyMixins(instance, mixins, deferredData, deferredWatch) {
|
|
for (let i = 0; i < mixins.length; i++) {
|
|
applyOptions(instance, mixins[i], deferredData, deferredWatch, true);
|
|
}
|
|
}
|
|
function resolveData(instance, dataFn, publicThis) {
|
|
const data = dataFn.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 if (instance.data === EMPTY_OBJ) {
|
|
instance.data = reactive(data);
|
|
}
|
|
else {
|
|
// existing data: this is a mixin or extends.
|
|
extend(instance.data, data);
|
|
}
|
|
}
|
|
function createWatcher(raw, ctx, publicThis, key) {
|
|
const getter = () => 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 {
|
|
watch(getter, raw.handler.bind(publicThis), raw);
|
|
}
|
|
}
|
|
else if ((process.env.NODE_ENV !== 'production')) {
|
|
warn(`Invalid watch option: "${key}"`);
|
|
}
|
|
}
|
|
function resolveMergedOptions(instance) {
|
|
const raw = instance.type;
|
|
const { __merged, mixins, extends: extendsOptions } = raw;
|
|
if (__merged)
|
|
return __merged;
|
|
const globalMixins = instance.appContext.mixins;
|
|
if (!globalMixins.length && !mixins && !extendsOptions)
|
|
return raw;
|
|
const options = {};
|
|
globalMixins.forEach(m => mergeOptions(options, m, instance));
|
|
extendsOptions && mergeOptions(options, extendsOptions, instance);
|
|
mixins && mixins.forEach(m => mergeOptions(options, m, instance));
|
|
mergeOptions(options, raw, instance);
|
|
return (raw.__merged = options);
|
|
}
|
|
function mergeOptions(to, from, instance) {
|
|
const strats = instance.appContext.config.optionMergeStrategies;
|
|
for (const key in from) {
|
|
if (strats && hasOwn(strats, key)) {
|
|
to[key] = strats[key](to[key], from[key], instance.proxy, key);
|
|
}
|
|
else if (!hasOwn(to, key)) {
|
|
to[key] = from[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
const publicPropertiesMap = extend(Object.create(null), {
|
|
$: i => i,
|
|
$el: i => i.vnode.el,
|
|
$data: i => i.data,
|
|
$props: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.props) : i.props),
|
|
$attrs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.attrs) : i.attrs),
|
|
$slots: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.slots) : i.slots),
|
|
$refs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.refs) : i.refs),
|
|
$parent: i => i.parent && i.parent.proxy,
|
|
$root: i => i.root && i.root.proxy,
|
|
$emit: i => i.emit,
|
|
$options: i => (__VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),
|
|
$forceUpdate: i => () => queueJob(i.update),
|
|
// $nextTick: () => nextTick, // fixed by xxxxxx
|
|
$watch: i => (__VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP)
|
|
});
|
|
const PublicInstanceProxyHandlers = {
|
|
get({ _: instance }, key) {
|
|
const { ctx, setupState, data, props, accessCache, type, appContext } = instance;
|
|
// let @vue/reactivity know it should never observe Vue public instances.
|
|
if (key === "__v_skip" /* SKIP */) {
|
|
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 0 /* SETUP */:
|
|
return setupState[key];
|
|
case 1 /* DATA */:
|
|
return data[key];
|
|
case 3 /* CONTEXT */:
|
|
return ctx[key];
|
|
case 2 /* PROPS */:
|
|
return props[key];
|
|
// default: just fallthrough
|
|
}
|
|
}
|
|
else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
|
|
accessCache[key] = 0 /* SETUP */;
|
|
return setupState[key];
|
|
}
|
|
else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
|
|
accessCache[key] = 1 /* DATA */;
|
|
return data[key];
|
|
}
|
|
else if (
|
|
// only cache other properties when instance has declared (thus stable)
|
|
// props
|
|
(normalizedProps = normalizePropsOptions(type)[0]) &&
|
|
hasOwn(normalizedProps, key)) {
|
|
accessCache[key] = 2 /* PROPS */;
|
|
return props[key];
|
|
}
|
|
else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {
|
|
accessCache[key] = 3 /* CONTEXT */;
|
|
return ctx[key];
|
|
}
|
|
else {
|
|
accessCache[key] = 4 /* OTHER */;
|
|
}
|
|
}
|
|
const publicGetter = publicPropertiesMap[key];
|
|
let cssModule, globalProperties;
|
|
// public $xxx properties
|
|
if (publicGetter) {
|
|
if (key === '$attrs') {
|
|
track(instance, "get" /* 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] = 3 /* 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 &&
|
|
// #1091 avoid internal isRef/isVNode checks on component instance leading
|
|
// to infinite warning loop
|
|
key.indexOf('__v') !== 0) {
|
|
if (data !== EMPTY_OBJ && key[0] === '$' && hasOwn(data, key)) {
|
|
warn(`Property ${JSON.stringify(key)} must be accessed via $data because it starts with a reserved ` +
|
|
`character and is not proxied on the render context.`);
|
|
}
|
|
else {
|
|
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 (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
|
|
setupState[key] = value;
|
|
}
|
|
else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
|
|
data[key] = value;
|
|
}
|
|
else if (key in instance.props) {
|
|
(process.env.NODE_ENV !== 'production') &&
|
|
warn(`Attempting to mutate prop "${key}". Props are readonly.`, instance);
|
|
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.`, instance);
|
|
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, type, appContext } }, key) {
|
|
let normalizedProps;
|
|
return (accessCache[key] !== undefined ||
|
|
(data !== EMPTY_OBJ && hasOwn(data, key)) ||
|
|
(setupState !== EMPTY_OBJ && hasOwn(setupState, key)) ||
|
|
((normalizedProps = normalizePropsOptions(type)[0]) &&
|
|
hasOwn(normalizedProps, key)) ||
|
|
hasOwn(ctx, key) ||
|
|
hasOwn(publicPropertiesMap, key) ||
|
|
hasOwn(appContext.config.globalProperties, key));
|
|
}
|
|
};
|
|
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);
|
|
};
|
|
}
|
|
const RuntimeCompiledPublicInstanceProxyHandlers = extend({}, PublicInstanceProxyHandlers, {
|
|
get(target, key) {
|
|
// fast path for unscopables when using `with` block
|
|
if (key === Symbol.unscopables) {
|
|
return;
|
|
}
|
|
return PublicInstanceProxyHandlers.get(target, key, target);
|
|
},
|
|
has(_, key) {
|
|
const has = key[0] !== '_' && !isGloballyWhitelisted(key);
|
|
if ((process.env.NODE_ENV !== 'production') && !has && PublicInstanceProxyHandlers.has(_, key)) {
|
|
warn(`Property ${JSON.stringify(key)} should not start with _ which is a reserved prefix for Vue internals.`);
|
|
}
|
|
return has;
|
|
}
|
|
});
|
|
// 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 createRenderContext(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
|
|
});
|
|
});
|
|
// expose global properties
|
|
const { globalProperties } = instance.appContext.config;
|
|
Object.keys(globalProperties).forEach(key => {
|
|
Object.defineProperty(target, key, {
|
|
configurable: true,
|
|
enumerable: false,
|
|
get: () => globalProperties[key],
|
|
set: NOOP
|
|
});
|
|
});
|
|
return target;
|
|
}
|
|
// dev only
|
|
function exposePropsOnRenderContext(instance) {
|
|
const { ctx, type } = instance;
|
|
const propsOptions = normalizePropsOptions(type)[0];
|
|
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 => {
|
|
Object.defineProperty(ctx, key, {
|
|
enumerable: true,
|
|
configurable: true,
|
|
get: () => setupState[key],
|
|
set: NOOP
|
|
});
|
|
});
|
|
}
|
|
|
|
const emptyAppContext = createAppContext();
|
|
let uid$1 = 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$1++,
|
|
vnode,
|
|
type,
|
|
parent,
|
|
appContext,
|
|
root: null,
|
|
next: null,
|
|
subTree: null,
|
|
update: null,
|
|
render: null,
|
|
proxy: null,
|
|
withProxy: null,
|
|
effects: null,
|
|
provides: parent ? parent.provides : Object.create(appContext.provides),
|
|
accessCache: null,
|
|
renderCache: [],
|
|
// 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,
|
|
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,
|
|
emit: null,
|
|
emitted: null
|
|
};
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
instance.ctx = createRenderContext(instance);
|
|
}
|
|
else {
|
|
instance.ctx = { _: instance };
|
|
}
|
|
instance.root = parent ? parent.root : instance;
|
|
instance.emit = emit.bind(null, instance);
|
|
if ((process.env.NODE_ENV !== 'production') || false) ;
|
|
return instance;
|
|
}
|
|
let currentInstance = null;
|
|
const setCurrentInstance = (instance) => {
|
|
currentInstance = instance;
|
|
};
|
|
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);
|
|
}
|
|
}
|
|
let isInSSRComponentSetup = false;
|
|
function setupComponent(instance, isSSR = false) {
|
|
isInSSRComponentSetup = isSSR;
|
|
const { props, /* children, */ shapeFlag } = instance.vnode;
|
|
const isStateful = shapeFlag & 4 /* STATEFUL_COMPONENT */;
|
|
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]);
|
|
}
|
|
}
|
|
}
|
|
// 0. create render proxy property access cache
|
|
instance.accessCache = {};
|
|
// 1. create public instance / render proxy
|
|
// also mark it raw so it's never observed
|
|
instance.proxy = 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);
|
|
currentInstance = instance;
|
|
pauseTracking();
|
|
const setupResult = callWithErrorHandling(setup, instance, 0 /* SETUP_FUNCTION */, [(process.env.NODE_ENV !== 'production') ? shallowReadonly(instance.props) : instance.props, setupContext]);
|
|
resetTracking();
|
|
currentInstance = null;
|
|
if (isPromise(setupResult)) {
|
|
if (isSSR) {
|
|
// return the promise so server-renderer can wait on it
|
|
return setupResult.then((resolvedResult) => {
|
|
handleSetupResult(instance, resolvedResult);
|
|
});
|
|
}
|
|
else 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);
|
|
}
|
|
}
|
|
else {
|
|
finishComponentSetup(instance);
|
|
}
|
|
}
|
|
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.
|
|
instance.setupState = reactive(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);
|
|
}
|
|
function finishComponentSetup(instance, isSSR) {
|
|
const Component = instance.type;
|
|
// template / render function normalization
|
|
if (!instance.render) {
|
|
if ((process.env.NODE_ENV !== 'production') && !Component.render) {
|
|
/* 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.`);
|
|
}
|
|
}
|
|
instance.render = (Component.render || NOOP);
|
|
// for runtime-compiled render functions using `with` blocks, the render
|
|
// proxy used needs a different `has` handler which is more performant and
|
|
// also only allows a whitelist of globals to fallthrough.
|
|
if (instance.render._rc) {
|
|
instance.withProxy = new Proxy(instance.ctx, RuntimeCompiledPublicInstanceProxyHandlers);
|
|
}
|
|
}
|
|
// support for 2.x options
|
|
if (__VUE_OPTIONS_API__) {
|
|
currentInstance = instance;
|
|
applyOptions(instance, Component);
|
|
currentInstance = null;
|
|
}
|
|
}
|
|
const attrHandlers = {
|
|
get: (target, key) => {
|
|
if ((process.env.NODE_ENV !== 'production')) ;
|
|
return target[key];
|
|
},
|
|
set: () => {
|
|
warn(`setupContext.attrs is readonly.`);
|
|
return false;
|
|
},
|
|
deleteProperty: () => {
|
|
warn(`setupContext.attrs is readonly.`);
|
|
return false;
|
|
}
|
|
};
|
|
function createSetupContext(instance) {
|
|
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 new Proxy(instance.attrs, attrHandlers);
|
|
},
|
|
get slots() {
|
|
return shallowReadonly(instance.slots);
|
|
},
|
|
get emit() {
|
|
return (event, ...args) => instance.emit(event, ...args);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
return {
|
|
attrs: instance.attrs,
|
|
slots: instance.slots,
|
|
emit: instance.emit
|
|
};
|
|
}
|
|
}
|
|
// record effects created during a component's setup() so that they can be
|
|
// stopped when the component unmounts
|
|
function recordInstanceBoundEffect(effect) {
|
|
if (currentInstance) {
|
|
(currentInstance.effects || (currentInstance.effects = [])).push(effect);
|
|
}
|
|
}
|
|
const classifyRE = /(?:^|[-_])(\w)/g;
|
|
const classify = (str) => str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '');
|
|
/* istanbul ignore next */
|
|
function formatComponentName(instance, Component, isRoot = false) {
|
|
let name = isFunction(Component)
|
|
? Component.displayName || Component.name
|
|
: Component.name;
|
|
if (!name && Component.__file) {
|
|
const match = Component.__file.match(/([^/\\]+)\.vue$/);
|
|
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.parent.type.components) || inferFromRegistry(instance.appContext.components);
|
|
}
|
|
return name ? classify(name) : isRoot ? `App` : `Anonymous`;
|
|
}
|
|
|
|
function computed$1(getterOrOptions) {
|
|
const c = computed(getterOrOptions);
|
|
recordInstanceBoundEffect(c.effect);
|
|
return c;
|
|
}
|
|
|
|
// Core API ------------------------------------------------------------------
|
|
const version = "3.0.0-rc.4";
|
|
|
|
// 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 = unref(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 = unref(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 = unref(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.VUE_APP_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$1(instance, fn) {
|
|
const ctx = instance.ctx;
|
|
if (!ctx.__next_tick_pending && !hasComponentEffect(instance)) {
|
|
if (process.env.VUE_APP_DEBUG) {
|
|
const mpInstance = ctx.$scope;
|
|
console.log('[' +
|
|
+new Date() +
|
|
'][' +
|
|
(mpInstance.is || mpInstance.route) +
|
|
'][' +
|
|
instance.uid +
|
|
']:nextVueTick');
|
|
}
|
|
return nextTick(fn && fn.bind(instance.proxy));
|
|
}
|
|
if (process.env.VUE_APP_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 /* SCHEDULER */);
|
|
}
|
|
else if (_resolve) {
|
|
_resolve(instance.proxy);
|
|
}
|
|
});
|
|
return new Promise(resolve => {
|
|
_resolve = resolve;
|
|
});
|
|
}
|
|
|
|
function getMPInstanceData(instance, keys) {
|
|
const data = instance.data;
|
|
const ret = Object.create(null);
|
|
//仅同步 data 中有的数据
|
|
keys.forEach(key => {
|
|
ret[key] = data[key];
|
|
});
|
|
return ret;
|
|
}
|
|
function getVueInstanceData(instance) {
|
|
const { data, setupState, ctx } = instance;
|
|
const keys = new Set();
|
|
const ret = Object.create(null);
|
|
Object.keys(setupState).forEach(key => {
|
|
keys.add(key);
|
|
ret[key] = setupState[key];
|
|
});
|
|
if (data) {
|
|
Object.keys(data).forEach(key => {
|
|
if (!keys.has(key)) {
|
|
keys.add(key);
|
|
ret[key] = data[key];
|
|
}
|
|
});
|
|
}
|
|
if (__VUE_OPTIONS_API__) {
|
|
if (ctx.$computedKeys) {
|
|
ctx.$computedKeys.forEach((key) => {
|
|
if (!keys.has(key)) {
|
|
keys.add(key);
|
|
ret[key] = ctx[key];
|
|
}
|
|
});
|
|
}
|
|
}
|
|
if (ctx.$mp) {
|
|
// TODO
|
|
extend(ret, ctx.$mp.data || {});
|
|
}
|
|
// TODO form-field
|
|
// track
|
|
return { keys, data: JSON.parse(JSON.stringify(ret)) };
|
|
}
|
|
function patch(instance) {
|
|
const ctx = instance.ctx;
|
|
const mpType = ctx.mpType;
|
|
if (mpType === 'page' || mpType === 'component') {
|
|
const start = Date.now();
|
|
const mpInstance = ctx.$scope;
|
|
const { keys, data } = getVueInstanceData(instance);
|
|
// data.__webviewId__ = mpInstance.data.__webviewId__
|
|
const diffData = diff(data, getMPInstanceData(mpInstance, keys));
|
|
if (Object.keys(diffData).length) {
|
|
if (process.env.VUE_APP_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);
|
|
});
|
|
}
|
|
else {
|
|
flushCallbacks(instance);
|
|
}
|
|
}
|
|
}
|
|
|
|
function errorHandler(err, instance, info) {
|
|
let hasOnError = false;
|
|
if (instance) {
|
|
const appInstance = instance.$.appContext.$appInstance;
|
|
hasOnError = appInstance && appInstance.$hasHook("onError" /* ON_ERROR */);
|
|
hasOnError && appInstance.$callHook("onError" /* ON_ERROR */, err);
|
|
}
|
|
logError(err, info, instance ? instance.$.vnode : null);
|
|
}
|
|
function initAppConfig(appConfig) {
|
|
appConfig.errorHandler = errorHandler;
|
|
appConfig.globalProperties.$nextTick = function $nextTick(fn) {
|
|
return nextTick$1(this.$, fn);
|
|
};
|
|
}
|
|
|
|
function onApplyOptions(options, instance, publicThis) {
|
|
Object.keys(options).forEach(name => {
|
|
if (name.indexOf('on') === 0) {
|
|
const hook = options[name];
|
|
if (isFunction(hook)) {
|
|
injectHook(name, hook.bind(publicThis), instance);
|
|
}
|
|
}
|
|
});
|
|
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;
|
|
}
|
|
|
|
var MPType;
|
|
(function (MPType) {
|
|
MPType["APP"] = "app";
|
|
MPType["PAGE"] = "page";
|
|
MPType["COMPONENT"] = "component";
|
|
})(MPType || (MPType = {}));
|
|
const queuePostRenderEffect$1 = 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);
|
|
}
|
|
setupComponent(instance);
|
|
if (__VUE_OPTIONS_API__) {
|
|
// $children
|
|
if (options.parentComponent && instance.proxy) {
|
|
options.parentComponent.ctx
|
|
.$children.push(instance.proxy);
|
|
}
|
|
}
|
|
setupRenderEffect(instance);
|
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
popWarningContext();
|
|
}
|
|
return instance.proxy;
|
|
}
|
|
const prodEffectOptions = {
|
|
scheduler: queueJob
|
|
};
|
|
function createDevEffectOptions(instance) {
|
|
return {
|
|
scheduler: queueJob,
|
|
onTrack: instance.rtc ? e => invokeArrayFns(instance.rtc, e) : void 0,
|
|
onTrigger: instance.rtg ? e => invokeArrayFns(instance.rtg, e) : void 0
|
|
};
|
|
}
|
|
function setupRenderEffect(instance) {
|
|
// create reactive effect for rendering
|
|
instance.update = effect(function componentEffect() {
|
|
if (!instance.isMounted) {
|
|
instance.render && instance.render.call(instance.proxy);
|
|
patch(instance);
|
|
}
|
|
else {
|
|
instance.render && instance.render.call(instance.proxy);
|
|
// updateComponent
|
|
const { bu, u } = instance;
|
|
// beforeUpdate hook
|
|
if (bu) {
|
|
invokeArrayFns(bu);
|
|
}
|
|
patch(instance);
|
|
// updated hook
|
|
if (u) {
|
|
queuePostRenderEffect$1(u);
|
|
}
|
|
}
|
|
}, (process.env.NODE_ENV !== 'production') ? createDevEffectOptions(instance) : prodEffectOptions);
|
|
}
|
|
function unmountComponent(instance) {
|
|
const { bum, effects, update, um } = instance;
|
|
// beforeUnmount hook
|
|
if (bum) {
|
|
invokeArrayFns(bum);
|
|
}
|
|
if (effects) {
|
|
for (let i = 0; i < effects.length; i++) {
|
|
stop(effects[i]);
|
|
}
|
|
}
|
|
// update may be null if a component is unmounted before its async
|
|
// setup has resolved.
|
|
if (update) {
|
|
stop(update);
|
|
}
|
|
// unmounted hook
|
|
if (um) {
|
|
queuePostRenderEffect$1(um);
|
|
}
|
|
queuePostRenderEffect$1(() => {
|
|
instance.isUnmounted = true;
|
|
});
|
|
}
|
|
const oldCreateApp = createAppAPI();
|
|
function createApp(rootComponent, rootProps = null) {
|
|
const app = oldCreateApp(rootComponent, rootProps);
|
|
const appContext = app._context;
|
|
initAppConfig(appContext.config);
|
|
const createVNode = initialVNode => {
|
|
initialVNode.appContext = appContext;
|
|
initialVNode.shapeFlag = 6 /* 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() {
|
|
const instance = mountComponent(createVNode({ type: rootComponent }), {
|
|
mpType: MPType.APP,
|
|
mpInstance: null,
|
|
parentComponent: null,
|
|
slots: [],
|
|
props: null
|
|
});
|
|
instance.$app = app;
|
|
instance.$createComponent = createComponent;
|
|
instance.$destroyComponent = destroyComponent;
|
|
appContext.$appInstance = instance;
|
|
createMiniProgramApp(instance);
|
|
return instance;
|
|
};
|
|
app.unmount = function unmount() {
|
|
warn(`Cannot unmount an app.`);
|
|
};
|
|
return app;
|
|
}
|
|
|
|
const createHook$1 = (lifecycle) => (hook, target = currentInstance) =>
|
|
// post-create lifecycle registrations are noops during SSR
|
|
!isInSSRComponentSetup &&
|
|
injectHook(lifecycle, hook, target);
|
|
const onShow = /*#__PURE__*/ createHook$1("onShow" /* ON_SHOW */);
|
|
const onHide = /*#__PURE__*/ createHook$1("onHide" /* ON_HIDE */);
|
|
const onLaunch = /*#__PURE__*/ createHook$1("onLaunch" /* ON_LAUCH */);
|
|
const onError = /*#__PURE__*/ createHook$1("onError" /* ON_ERROR */);
|
|
const onThemeChange = /*#__PURE__*/ createHook$1("onThemeChange" /* ON_THEME_CHANGE */);
|
|
const onPageNotFound = /*#__PURE__*/ createHook$1("onPageNotFound" /* ON_PAGE_NOT_FOUND */);
|
|
const onUniNViewMessage = /*#__PURE__*/ createHook$1("onUniNViewMessage" /* ON_UNI_NVIEW_MESSAGE */);
|
|
const onUnhandledRejection = /*#__PURE__*/ createHook$1("onUnhandledRejection" /* ON_UNHANDLE_REJECTION */);
|
|
const onLoad = /*#__PURE__*/ createHook$1("onLoad" /* ON_LOAD */);
|
|
const onReady = /*#__PURE__*/ createHook$1("onReady" /* ON_READY */);
|
|
const onUnload = /*#__PURE__*/ createHook$1("onUnload" /* ON_UNLOAD */);
|
|
const onResize = /*#__PURE__*/ createHook$1("onResize" /* ON_RESIZE */);
|
|
const onBackPress = /*#__PURE__*/ createHook$1("onBackPress" /* ON_BACK_PRESS */);
|
|
const onPageScroll = /*#__PURE__*/ createHook$1("onPageScroll" /* ON_PAGE_SCROLL */);
|
|
const onTabItemTap = /*#__PURE__*/ createHook$1("onTabItemTap" /* ON_TAB_ITEM_TAP */);
|
|
const onReachBottom = /*#__PURE__*/ createHook$1("onReachBottom" /* ON_REACH_BOTTOM */);
|
|
const onPullDownRefresh = /*#__PURE__*/ createHook$1("onPullDownRefresh" /* ON_PULL_DOWN_REFRESH */);
|
|
const onShareTimeline = /*#__PURE__*/ createHook$1("onShareTimeline" /* ON_SHARE_TIMELINE */);
|
|
const onAddToFavorites = /*#__PURE__*/ createHook$1("onAddToFavorites" /* ON_ADD_TO_FAVORITES */);
|
|
const onShareAppMessage = /*#__PURE__*/ createHook$1("onShareAppMessage" /* ON_SHARE_APP_MESSAGE */);
|
|
const onNavigationBarButtonTap = /*#__PURE__*/ createHook$1("onNavigationBarButtonTap" /* ON_NAVIGATION_BAR_BUTTON_TAP */);
|
|
const onNavigationBarSearchInputChanged = /*#__PURE__*/ createHook$1("onNavigationBarSearchInputChanged" /* ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED */);
|
|
const onNavigationBarSearchInputClicked = /*#__PURE__*/ createHook$1("onNavigationBarSearchInputClicked" /* ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED */);
|
|
const onNavigationBarSearchInputConfirmed = /*#__PURE__*/ createHook$1("onNavigationBarSearchInputConfirmed" /* ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED */);
|
|
const onNavigationBarSearchInputFocusChanged = /*#__PURE__*/ createHook$1("onNavigationBarSearchInputFocusChanged" /* ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED */);
|
|
|
|
export { callWithAsyncErrorHandling, callWithErrorHandling, computed$1 as computed, createApp, createHook$1 as createHook, customRef, inject, isProxy, isReactive, isReadonly, isRef, markRaw, nextTick, onActivated, onAddToFavorites, onBackPress, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onError, onErrorCaptured, onHide, onLaunch, onLoad, onMounted, onNavigationBarButtonTap, onNavigationBarSearchInputChanged, onNavigationBarSearchInputClicked, onNavigationBarSearchInputConfirmed, onNavigationBarSearchInputFocusChanged, onPageNotFound, onPageScroll, onPullDownRefresh, onReachBottom, onReady, onRenderTracked, onRenderTriggered, onResize, onShareAppMessage, onShareTimeline, onShow, onTabItemTap, onThemeChange, onUnhandledRejection, onUniNViewMessage, onUnload, onUnmounted, onUpdated, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, version, warn, watch, watchEffect };
|
|
|