vue-next
Version:
## Status: Pre-Alpha.
1,419 lines (1,401 loc) • 168 kB
JavaScript
var VueTestRuntime = (function (exports) {
'use strict';
// Patch flags are optimization hints generated by the compiler.
// when a block with dynamicChildren is encountered during diff, the algorithm
// enters "optimized mode". In this mode, we know that the vdom is produced by
// a render function generated by the compiler, so the algorithm only needs to
// handle updates explicitly marked by these patch flags.
// runtime object for public consumption
const PublicPatchFlags = {
TEXT: 1 /* TEXT */,
CLASS: 2 /* CLASS */,
STYLE: 4 /* STYLE */,
PROPS: 8 /* PROPS */,
NEED_PATCH: 32 /* NEED_PATCH */,
FULL_PROPS: 16 /* FULL_PROPS */,
KEYED_FRAGMENT: 64 /* KEYED_FRAGMENT */,
UNKEYED_FRAGMENT: 128 /* UNKEYED_FRAGMENT */,
DYNAMIC_SLOTS: 256 /* DYNAMIC_SLOTS */,
BAIL: -1 /* BAIL */
};
// Make a map and return a function for checking if a key
// is in that map.
//
// IMPORTANT: all calls of this function must be prefixed with /*#__PURE__*/
// So that rollup can tree-shake them if necessary.
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
const EMPTY_OBJ = Object.freeze({})
;
const EMPTY_ARR = [];
const NOOP = () => { };
/**
* Always return false.
*/
const NO = () => false;
const isOn = (key) => key[0] === 'o' && key[1] === 'n';
const extend = (a, b) => {
for (const key in b) {
a[key] = b[key];
}
return a;
};
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const isArray = Array.isArray;
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isSymbol = (val) => typeof val === 'symbol';
const isObject = (val) => val !== null && typeof val === 'object';
function isPromise(val) {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
}
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
function toRawType(value) {
return toTypeString(value).slice(8, -1);
}
const isPlainObject = (val) => toTypeString(val) === '[object Object]';
const isReservedProp = (key) => key === 'key' || key === 'ref' || key.startsWith(`onVnode`);
const camelizeRE = /-(\w)/g;
const camelize = (str) => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
};
const hyphenateRE = /\B([A-Z])/g;
const hyphenate = (str) => {
return str.replace(hyphenateRE, '-$1').toLowerCase();
};
const capitalize = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
// implementation, close to no-op
function createComponent(options) {
return isFunction(options) ? { setup: options } : options;
}
// global immutability lock
let LOCKED = true;
function lock() {
LOCKED = true;
}
function unlock() {
LOCKED = false;
}
const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key])
.filter(isSymbol));
function createGetter(isReadonly) {
return function get(target, key, receiver) {
const res = Reflect.get(target, key, receiver);
if (isSymbol(key) && builtInSymbols.has(key)) {
return res;
}
if (isRef(res)) {
return res.value;
}
track(target, "get" /* GET */, key);
return isObject(res)
? isReadonly
? // need to lazy access readonly and reactive here to avoid
// circular dependency
readonly(res)
: reactive(res)
: res;
};
}
function set(target, key, value, receiver) {
value = toRaw(value);
const oldValue = target[key];
if (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)) {
/* istanbul ignore else */
{
const extraInfo = { oldValue, newValue: value };
if (!hadKey) {
trigger(target, "add" /* ADD */, key, extraInfo);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, extraInfo);
}
}
}
return result;
}
function deleteProperty(target, key) {
const hadKey = hasOwn(target, key);
const oldValue = target[key];
const result = Reflect.deleteProperty(target, key);
if (result && hadKey) {
/* istanbul ignore else */
{
trigger(target, "delete" /* DELETE */, key, { oldValue });
}
}
return result;
}
function has(target, key) {
const result = Reflect.has(target, key);
track(target, "has" /* HAS */, key);
return result;
}
function ownKeys(target) {
track(target, "iterate" /* ITERATE */);
return Reflect.ownKeys(target);
}
const mutableHandlers = {
get: createGetter(false),
set,
deleteProperty,
has,
ownKeys
};
const readonlyHandlers = {
get: createGetter(true),
set(target, key, value, receiver) {
if (LOCKED) {
{
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
}
else {
return set(target, key, value, receiver);
}
},
deleteProperty(target, key) {
if (LOCKED) {
{
console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
}
return true;
}
else {
return deleteProperty(target, key);
}
},
has,
ownKeys
};
const toReactive = (value) => isObject(value) ? reactive(value) : value;
const toReadonly = (value) => isObject(value) ? readonly(value) : value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get(target, key, wrap) {
target = toRaw(target);
key = toRaw(key);
track(target, "get" /* GET */, key);
return wrap(getProto(target).get.call(target, key));
}
function has$1(key) {
const target = toRaw(this);
key = toRaw(key);
track(target, "has" /* HAS */, key);
return getProto(target).has.call(target, key);
}
function size(target) {
target = toRaw(target);
track(target, "iterate" /* ITERATE */);
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) {
/* istanbul ignore else */
{
trigger(target, "add" /* ADD */, value, { newValue: value });
}
}
return result;
}
function set$1(key, value) {
value = toRaw(value);
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, key);
const oldValue = proto.get.call(target, key);
const result = proto.set.call(target, key, value);
/* istanbul ignore else */
{
const extraInfo = { oldValue, newValue: value };
if (!hadKey) {
trigger(target, "add" /* ADD */, key, extraInfo);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, extraInfo);
}
}
return result;
}
function deleteEntry(key) {
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, key);
const oldValue = proto.get ? proto.get.call(target, key) : undefined;
// forward the operation before queueing reactions
const result = proto.delete.call(target, key);
if (hadKey) {
/* istanbul ignore else */
{
trigger(target, "delete" /* DELETE */, key, { oldValue });
}
}
return result;
}
function clear() {
const target = toRaw(this);
const hadItems = target.size !== 0;
const oldTarget = target instanceof Map
? new Map(target)
: new Set(target)
;
// forward the operation before queueing reactions
const result = getProto(target).clear.call(target);
if (hadItems) {
/* istanbul ignore else */
{
trigger(target, "clear" /* CLEAR */, void 0, { oldTarget });
}
}
return result;
}
function createForEach(isReadonly) {
return function forEach(callback, thisArg) {
const observed = this;
const target = toRaw(observed);
const wrap = isReadonly ? toReadonly : toReactive;
track(target, "iterate" /* ITERATE */);
// 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(observed, wrap(value), wrap(key), observed);
}
return getProto(target).forEach.call(target, wrappedCallback, thisArg);
};
}
function createIterableMethod(method, isReadonly) {
return function (...args) {
const target = toRaw(this);
const isPair = method === 'entries' ||
(method === Symbol.iterator && target instanceof Map);
const innerIterator = getProto(target)[method].apply(target, args);
const wrap = isReadonly ? toReadonly : toReactive;
track(target, "iterate" /* ITERATE */);
// 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(method, type) {
return function (...args) {
if (LOCKED) {
{
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;
}
else {
return method.apply(this, args);
}
};
}
const mutableInstrumentations = {
get(key) {
return get(this, key, toReactive);
},
get size() {
return size(this);
},
has: has$1,
add,
set: set$1,
delete: deleteEntry,
clear,
forEach: createForEach(false)
};
const readonlyInstrumentations = {
get(key) {
return get(this, key, toReadonly);
},
get size() {
return size(this);
},
has: has$1,
add: createReadonlyMethod(add, "add" /* ADD */),
set: createReadonlyMethod(set$1, "set" /* SET */),
delete: createReadonlyMethod(deleteEntry, "delete" /* DELETE */),
clear: createReadonlyMethod(clear, "clear" /* CLEAR */),
forEach: createForEach(true)
};
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
iteratorMethods.forEach(method => {
mutableInstrumentations[method] = createIterableMethod(method, false);
readonlyInstrumentations[method] = createIterableMethod(method, true);
});
function createInstrumentationGetter(instrumentations) {
return (target, key, receiver) => Reflect.get(hasOwn(instrumentations, key) && key in target
? instrumentations
: target, key, receiver);
}
const mutableCollectionHandlers = {
get: createInstrumentationGetter(mutableInstrumentations)
};
const readonlyCollectionHandlers = {
get: createInstrumentationGetter(readonlyInstrumentations)
};
const targetMap = new WeakMap();
// WeakMaps that store {raw <-> observed} pairs.
const rawToReactive = new WeakMap();
const reactiveToRaw = new WeakMap();
const rawToReadonly = new WeakMap();
const readonlyToRaw = new WeakMap();
// WeakSets for values that are marked readonly or non-reactive during
// observable creation.
const readonlyValues = new WeakSet();
const nonReactiveValues = new WeakSet();
const collectionTypes = new Set([Set, Map, WeakMap, WeakSet]);
const isObservableType = /*#__PURE__*/ makeMap('Object,Array,Map,Set,WeakMap,WeakSet');
const canObserve = (value) => {
return (!value._isVue &&
!value._isVNode &&
isObservableType(toRawType(value)) &&
!nonReactiveValues.has(value));
};
function reactive(target) {
// if trying to observe a readonly proxy, return the readonly version.
if (readonlyToRaw.has(target)) {
return target;
}
// target is explicitly marked as readonly by user
if (readonlyValues.has(target)) {
return readonly(target);
}
return createReactiveObject(target, rawToReactive, reactiveToRaw, mutableHandlers, mutableCollectionHandlers);
}
function readonly(target) {
// value is a mutable observable, retrieve its original and return
// a readonly version.
if (reactiveToRaw.has(target)) {
target = reactiveToRaw.get(target);
}
return createReactiveObject(target, rawToReadonly, readonlyToRaw, readonlyHandlers, readonlyCollectionHandlers);
}
function createReactiveObject(target, toProxy, toRaw, baseHandlers, collectionHandlers) {
if (!isObject(target)) {
{
console.warn(`value cannot be made reactive: ${String(target)}`);
}
return target;
}
// target already has corresponding Proxy
let observed = toProxy.get(target);
if (observed !== void 0) {
return observed;
}
// target is already a Proxy
if (toRaw.has(target)) {
return target;
}
// only a whitelist of value types can be observed.
if (!canObserve(target)) {
return target;
}
const handlers = collectionTypes.has(target.constructor)
? collectionHandlers
: baseHandlers;
observed = new Proxy(target, handlers);
toProxy.set(target, observed);
toRaw.set(observed, target);
if (!targetMap.has(target)) {
targetMap.set(target, new Map());
}
return observed;
}
function isReactive(value) {
return reactiveToRaw.has(value) || readonlyToRaw.has(value);
}
function isReadonly(value) {
return readonlyToRaw.has(value);
}
function toRaw(observed) {
return reactiveToRaw.get(observed) || readonlyToRaw.get(observed) || observed;
}
function markReadonly(value) {
readonlyValues.add(value);
return value;
}
function markNonReactive(value) {
nonReactiveValues.add(value);
return value;
}
const effectStack = [];
const ITERATE_KEY = Symbol('iterate');
function isEffect(fn) {
return fn != null && 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.onStop) {
effect.onStop();
}
effect.active = false;
}
}
function createReactiveEffect(fn, options) {
const effect = function reactiveEffect(...args) {
return run(effect, fn, args);
};
effect._isEffect = true;
effect.active = true;
effect.raw = fn;
effect.scheduler = options.scheduler;
effect.onTrack = options.onTrack;
effect.onTrigger = options.onTrigger;
effect.onStop = options.onStop;
effect.computed = options.computed;
effect.deps = [];
return effect;
}
function run(effect, fn, args) {
if (!effect.active) {
return fn(...args);
}
if (!effectStack.includes(effect)) {
cleanup(effect);
try {
effectStack.push(effect);
return fn(...args);
}
finally {
effectStack.pop();
}
}
}
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;
function pauseTracking() {
shouldTrack = false;
}
function resumeTracking() {
shouldTrack = true;
}
function track(target, type, key) {
if (!shouldTrack || effectStack.length === 0) {
return;
}
const effect = effectStack[effectStack.length - 1];
if (type === "iterate" /* ITERATE */) {
key = ITERATE_KEY;
}
let depsMap = targetMap.get(target);
if (depsMap === void 0) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (dep === void 0) {
depsMap.set(key, (dep = new Set()));
}
if (!dep.has(effect)) {
dep.add(effect);
effect.deps.push(dep);
if ( effect.onTrack) {
effect.onTrack({
effect,
target,
type,
key
});
}
}
}
function trigger(target, type, key, extraInfo) {
const depsMap = targetMap.get(target);
if (depsMap === void 0) {
// never been tracked
return;
}
const effects = new Set();
const computedRunners = new Set();
if (type === "clear" /* CLEAR */) {
// collection being cleared, trigger all effects for target
depsMap.forEach(dep => {
addRunners(effects, computedRunners, dep);
});
}
else {
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
addRunners(effects, computedRunners, depsMap.get(key));
}
// also run for iteration key on ADD | DELETE
if (type === "add" /* ADD */ || type === "delete" /* DELETE */) {
const iterationKey = Array.isArray(target) ? 'length' : ITERATE_KEY;
addRunners(effects, computedRunners, depsMap.get(iterationKey));
}
}
const run = (effect) => {
scheduleRun(effect, target, type, key, extraInfo);
};
// Important: computed effects must be run first so that computed getters
// can be invalidated before any normal effects that depend on them are run.
computedRunners.forEach(run);
effects.forEach(run);
}
function addRunners(effects, computedRunners, effectsToAdd) {
if (effectsToAdd !== void 0) {
effectsToAdd.forEach(effect => {
if (effect.computed) {
computedRunners.add(effect);
}
else {
effects.add(effect);
}
});
}
}
function scheduleRun(effect, target, type, key, extraInfo) {
if ( effect.onTrigger) {
const event = {
effect,
target,
key,
type
};
effect.onTrigger(extraInfo ? extend(event, extraInfo) : event);
}
if (effect.scheduler !== void 0) {
effect.scheduler(effect);
}
else {
effect();
}
}
const convert = (val) => isObject(val) ? reactive(val) : val;
function ref(raw) {
if (isRef(raw)) {
return raw;
}
raw = convert(raw);
const r = {
_isRef: true,
get value() {
track(r, "get" /* GET */, '');
return raw;
},
set value(newVal) {
raw = convert(newVal);
trigger(r, "set" /* SET */, '');
}
};
return r;
}
function isRef(r) {
return r ? r._isRef === true : false;
}
function toRefs(object) {
const ret = {};
for (const key in object) {
ret[key] = toProxyRef(object, key);
}
return ret;
}
function toProxyRef(object, key) {
return {
_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 = () => {
console.warn('Write operation failed: computed value is readonly');
}
;
}
else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
let dirty = true;
let value;
const runner = effect(getter, {
lazy: true,
// mark effect as computed so that it gets priority during trigger
computed: true,
scheduler: () => {
dirty = true;
}
});
return {
_isRef: true,
// expose effect so computed can be stopped
effect: runner,
get value() {
if (dirty) {
value = runner();
dirty = false;
}
// When computed effects are accessed in a parent effect, the parent
// should track all the dependencies the computed property has tracked.
// This should also apply for chained computed properties.
trackChildRun(runner);
return value;
},
set value(newValue) {
setter(newValue);
}
};
}
function trackChildRun(childRunner) {
if (effectStack.length === 0) {
return;
}
const parentRunner = effectStack[effectStack.length - 1];
for (let i = 0; i < childRunner.deps.length; i++) {
const dep = childRunner.deps[i];
if (!dep.has(parentRunner)) {
dep.add(parentRunner);
parentRunner.deps.push(dep);
}
}
}
const stack = [];
function pushWarningContext(vnode) {
stack.push(vnode);
}
function popWarningContext() {
stack.pop();
}
function warn(msg, ...args) {
const instance = stack.length ? stack[stack.length - 1].component : null;
const appWarnHandler = instance && instance.appContext.config.warnHandler;
const trace = getComponentTrace();
if (appWarnHandler) {
appWarnHandler(msg + args.join(''), instance && instance.renderProxy, formatTrace(trace).join(''));
return;
}
console.warn(`[Vue warn]: ${msg}`, ...args);
// avoid spamming console during tests
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
return;
}
if (!trace.length) {
return;
}
if (trace.length > 1 && console.groupCollapsed) {
console.groupCollapsed('at', ...formatTraceEntry(trace[0]));
const logs = [];
trace.slice(1).forEach((entry, i) => {
if (i !== 0)
logs.push('\n');
logs.push(...formatTraceEntry(entry, i + 1));
});
console.log(...logs);
console.groupEnd();
}
else {
console.log(...formatTrace(trace));
}
}
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
.parent;
currentVNode = parentInstance && parentInstance.vnode;
}
return normalizedStack;
}
function formatTrace(trace) {
const logs = [];
trace.forEach((entry, i) => {
const formatted = formatTraceEntry(entry, i);
if (i === 0) {
logs.push('at', ...formatted);
}
else {
logs.push('\n', ...formatted);
}
});
return logs;
}
function formatTraceEntry({ vnode, recurseCount }, depth = 0) {
const padding = depth === 0 ? '' : ' '.repeat(depth * 2 + 1);
const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``;
const open = padding + `<${formatComponentName(vnode)}`;
const close = `>` + postfix;
const rootLabel = vnode.component.parent == null ? `(Root)` : ``;
return vnode.props
? [open, ...formatProps(vnode.props), close, rootLabel]
: [open + close, rootLabel];
}
const classifyRE = /(?:^|[-_])(\w)/g;
const classify = (str) => str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '');
function formatComponentName(vnode, file) {
const Component = vnode.type;
let name = isFunction(Component) ? Component.displayName : Component.name;
if (!name && file) {
const match = file.match(/([^/\\]+)\.vue$/);
if (match) {
name = match[1];
}
}
return name ? classify(name) : 'AnonymousComponent';
}
function formatProps(props) {
const res = [];
for (const key in props) {
const value = props[key];
if (isString(value)) {
res.push(`${key}=${JSON.stringify(value)}`);
}
else {
res.push(`${key}=`, String(toRaw(value)));
}
}
return res;
}
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 /* DIRECTIVE_HOOK */]: 'directive hook',
[8 /* APP_ERROR_HANDLER */]: 'app errorHandler',
[9 /* APP_WARN_HANDLER */]: 'app warnHandler',
[10 /* SCHEDULER */]: 'scheduler flush. This is likely a Vue internals bug. ' +
'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue'
};
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 != null && !res._isVue && isPromise(res)) {
res.catch((err) => {
handleError(err, instance, type);
});
}
return res;
}
for (let i = 0; i < fn.length; i++) {
callWithAsyncErrorHandling(fn[i], instance, type, args);
}
}
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.renderProxy;
// in production the hook receives only the error code
const errorInfo = ErrorTypeStrings[type] ;
while (cur) {
const errorCapturedHooks = cur.ec;
if (errorCapturedHooks !== null) {
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, 8 /* APP_ERROR_HANDLER */, [err, exposedInstance, errorInfo]);
return;
}
}
logError(err, type, contextVNode);
}
function logError(err, type, contextVNode) {
// default behavior is crash in prod & test, recover in dev.
if (
!(typeof process !== 'undefined' && process.env.NODE_ENV === 'test')) {
const info = ErrorTypeStrings[type];
if (contextVNode) {
pushWarningContext(contextVNode);
}
warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`);
console.error(err);
if (contextVNode) {
popWarningContext();
}
}
else {
throw err;
}
}
const queue = [];
const postFlushCbs = [];
const p = Promise.resolve();
let isFlushing = false;
function nextTick(fn) {
return fn ? p.then(fn) : p;
}
function queueJob(job) {
if (!queue.includes(job)) {
queue.push(job);
if (!isFlushing) {
nextTick(flushJobs);
}
}
}
function queuePostFlushCb(cb) {
if (!isArray(cb)) {
postFlushCbs.push(cb);
}
else {
postFlushCbs.push(...cb);
}
if (!isFlushing) {
nextTick(flushJobs);
}
}
const dedupe = (cbs) => [...new Set(cbs)];
function flushPostFlushCbs() {
if (postFlushCbs.length) {
const cbs = dedupe(postFlushCbs);
postFlushCbs.length = 0;
for (let i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
}
const RECURSION_LIMIT = 100;
function flushJobs(seenJobs) {
isFlushing = true;
let job;
{
seenJobs = seenJobs || new Map();
}
while ((job = queue.shift())) {
{
const seen = seenJobs;
if (!seen.has(job)) {
seen.set(job, 1);
}
else {
const count = seen.get(job);
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.');
}
else {
seen.set(job, count + 1);
}
}
}
callWithErrorHandling(job, null, 10 /* SCHEDULER */);
}
flushPostFlushCbs();
isFlushing = false;
// some postFlushCb queued jobs!
// keep flushing until it drains.
if (queue.length) {
flushJobs(seenJobs);
}
}
const Fragment = Symbol( 'Fragment' );
const Portal = Symbol( 'Portal' );
const Suspense = Symbol( 'Suspense' );
const Text = Symbol( 'Text' );
const Comment = Symbol( 'Comment' );
// Since v-if and v-for are the two possible ways node structure can dynamically
// change, once we consider v-if branches and each v-for fragment a block, we
// can divide a template into nested blocks, and within each block the node
// structure would be stable. This allows us to skip most children diffing
// and only worry about the dynamic nodes (indicated by patch flags).
const blockStack = [];
let currentBlock = null;
// Open a block.
// This must be called before `createBlock`. It cannot be part of `createBlock`
// because the children of the block are evaluated before `createBlock` itself
// is called. The generated code typically looks like this:
//
// function render() {
// return (openBlock(),createBlock('div', null, [...]))
// }
//
// disableTracking is true when creating a fragment block, since a fragment
// always diffs its children.
function openBlock(disableTracking) {
blockStack.push((currentBlock = disableTracking ? null : []));
}
// Whether we should be tracking dynamic child nodes inside a block.
// Only tracks when this value is > 0
// We are not using a simple boolean because this value may need to be
// incremented/decremented by nested usage of v-once (see below)
let shouldTrack$1 = 1;
// Block tracking sometimes needs to be disabled, for example during the
// creation of a tree that needs to be cached by v-once. The compiler generates
// code like this:
// _cache[1] || (
// setBlockTracking(-1),
// _cache[1] = createVNode(...),
// setBlockTracking(1),
// _cache[1]
// )
function setBlockTracking(value) {
shouldTrack$1 += value;
}
// Create a block root vnode. Takes the same exact arguments as `createVNode`.
// A block root keeps track of dynamic nodes within the block in the
// `dynamicChildren` array.
function createBlock(type, props, children, patchFlag, dynamicProps) {
// avoid a block with patchFlag tracking itself
shouldTrack$1--;
const vnode = createVNode(type, props, children, patchFlag, dynamicProps);
shouldTrack$1++;
// save current block children on the block vnode
vnode.dynamicChildren = currentBlock || EMPTY_ARR;
// close block
blockStack.pop();
currentBlock = blockStack[blockStack.length - 1] || null;
// a block is always going to be patched, so track it as a child of its
// parent block
if (currentBlock !== null) {
currentBlock.push(vnode);
}
return vnode;
}
function isVNode(value) {
return value ? value._isVNode === true : false;
}
function createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null) {
// class & style normalization.
if (props !== null) {
// for reactive or proxy objects, we need to clone it to enable mutation.
if (isReactive(props) || SetupProxySymbol in props) {
props = extend({}, props);
}
let { class: klass, style } = props;
if (klass != null && !isString(klass)) {
props.class = normalizeClass(klass);
}
if (style != null) {
// reactive state objects need to be cloned since they are likely to be
// mutated
if (isReactive(style) && !isArray(style)) {
style = extend({}, style);
}
props.style = normalizeStyle(style);
}
}
// encode the vnode type information into a bitmap
const shapeFlag = isString(type)
? 1 /* ELEMENT */
: isObject(type)
? 4 /* STATEFUL_COMPONENT */
: isFunction(type)
? 2 /* FUNCTIONAL_COMPONENT */
: 0;
const vnode = {
_isVNode: true,
type,
props,
key: (props !== null && props.key) || null,
ref: (props !== null && props.ref) || null,
children: null,
component: null,
suspense: null,
el: null,
anchor: null,
target: null,
shapeFlag,
patchFlag,
dynamicProps,
dynamicChildren: null,
appContext: null
};
normalizeChildren(vnode, children);
// presence of a patch flag indicates this node needs patching on updates.
// component nodes also should always be patched, because even if the
// component doesn't need to update, it needs to persist the instance on to
// the next vnode so that it can be properly unmounted later.
if (shouldTrack$1 > 0 &&
currentBlock !== null &&
(patchFlag > 0 ||
shapeFlag & 4 /* STATEFUL_COMPONENT */ ||
shapeFlag & 2 /* FUNCTIONAL_COMPONENT */)) {
currentBlock.push(vnode);
}
return vnode;
}
function cloneVNode(vnode, extraProps) {
return {
_isVNode: true,
type: vnode.type,
props: extraProps
? vnode.props
? mergeProps(vnode.props, extraProps)
: extraProps
: vnode.props,
key: vnode.key,
ref: vnode.ref,
children: vnode.children,
target: vnode.target,
shapeFlag: vnode.shapeFlag,
patchFlag: vnode.patchFlag,
dynamicProps: vnode.dynamicProps,
dynamicChildren: vnode.dynamicChildren,
appContext: vnode.appContext,
// these should be set to null since they should only be present on
// mounted VNodes. If they are somehow not null, this means we have
// encountered an already-mounted vnode being used again.
component: null,
suspense: null,
el: null,
anchor: null
};
}
function createTextVNode(text = ' ', flag = 0) {
return createVNode(Text, null, text, flag);
}
function createCommentVNode(text = '',
// when used as the v-else branch, the comment node must be created as a
// block to ensure correct updates.
asBlock = false) {
return asBlock
? createBlock(Comment, null, text)
: createVNode(Comment, null, text);
}
function normalizeVNode(child) {
if (child == null) {
// empty placeholder
return createVNode(Comment);
}
else if (isArray(child)) {
// fragment
return createVNode(Fragment, null, child);
}
else if (typeof child === 'object') {
// already vnode, this should be the most common since compiled templates
// always produce all-vnode children arrays
return child.el === null ? child : cloneVNode(child);
}
else {
// primitive types
return createVNode(Text, null, child + '');
}
}
function normalizeChildren(vnode, children) {
let type = 0;
if (children == null) {
children = null;
}
else if (isArray(children)) {
type = 16 /* ARRAY_CHILDREN */;
}
else if (typeof children === 'object') {
type = 32 /* SLOTS_CHILDREN */;
}
else if (isFunction(children)) {
children = { default: children };
type = 32 /* SLOTS_CHILDREN */;
}
else {
children = isString(children) ? children : children + '';
type = 8 /* TEXT_CHILDREN */;
}
vnode.children = children;
vnode.shapeFlag |= type;
}
function normalizeStyle(value) {
if (isArray(value)) {
const res = {};
for (let i = 0; i < value.length; i++) {
const normalized = normalizeStyle(value[i]);
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key];
}
}
}
return res;
}
else if (isObject(value)) {
return value;
}
}
function normalizeClass(value) {
let res = '';
if (isString(value)) {
res = value;
}
else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
res += normalizeClass(value[i]) + ' ';
}
}
else if (isObject(value)) {
for (const name in value) {
if (value[name]) {
res += name + ' ';
}
}
}
return res.trim();
}
const handlersRE = /^on|^vnode/;
function mergeProps(...args) {
const ret = {};
extend(ret, args[0]);
for (let i = 1; i < args.length; i++) {
const toMerge = args[i];
for (const key in toMerge) {
if (key === 'class') {
ret.class = normalizeClass([ret.class, toMerge.class]);
}
else if (key === 'style') {
ret.style = normalizeStyle([ret.style, toMerge.style]);
}
else if (handlersRE.test(key)) {
// on*, vnode*
const existing = ret[key];
ret[key] = existing
? [].concat(existing, toMerge[key])
: toMerge[key];
}
else {
ret[key] = toMerge[key];
}
}
}
return ret;
}
function injectHook(type, hook, target) {
if (target) {
(target[type] || (target[type] = [])).push((...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);
resumeTracking();
return res;
});
}
else {
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().` +
( ` If you are using async setup(), make sure to register lifecycle ` +
`hooks before the first await statement.`
));
}
}
const createHook = (lifecycle) => (hook, target = currentInstance) => 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 = createHook("ec" /* ERROR_CAPTURED */);
// mark the current rendering instance for asset resolution (e.g.
// resolveComponent, resolveDirective) during render
let currentRenderingInstance = null;
// dev only flag to track whether $attrs was used during render.
// If $attrs was used during render then the warning for failed attrs
// fallthrough can be suppressed.
let accessedAttrs = false;
function markAttrsAccessed() {
accessedAttrs = true;
}
function renderComponentRoot(instance) {
const { type: Component, vnode, renderProxy, props, slots, attrs, emit } = instance;
let result;
currentRenderingInstance = instance;
{
accessedAttrs = false;
}
try {
if (vnode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {
result = normalizeVNode(instance.render.call(renderProxy));
}
else {
// functional
const render = Component;
result = normalizeVNode(render.length > 1
? render(props, {
attrs,
slots,
emit
})
: render(props, null /* we know it doesn't need it */));
}
// attr merging
if (Component.props != null &&
Component.inheritAttrs !== false &&
attrs !== EMPTY_OBJ &&
Object.keys(attrs).length) {
if (result.shapeFlag & 1 /* ELEMENT */ ||
result.shapeFlag & 6 /* COMPONENT */) {
result = cloneVNode(result, attrs);
}
else if (true && !accessedAttrs) {
warn(`Extraneous non-props attributes (${Object.keys(attrs).join(',')}) ` +
`were passed to component but could not be automatically inhertied ` +
`because component renders fragment or text root nodes.`);
}
}
}
catch (err) {
handleError(err, instance, 1 /* RENDER_FUNCTION */);
result = createVNode(Comment);
}
currentRenderingInstance = null;
return result;
}
function shouldUpdateComponent(prevVNode, nextVNode, optimized) {
const { props: prevProps, children: prevChildren } = prevVNode;
const { props: nextProps, children: nextChildren, patchFlag } = nextVNode;
if (patchFlag > 0) {
if (patchFlag & 256 /* DYNAMIC_SLOTS */) {
// slot content that references values that might have changed,
// e.g. in a v-for
return true;
}
if (patchFlag & 16 /* FULL_PROPS */) {
// presence of this flag indicates props are always non-null
return hasPropsChanged(prevProps, nextProps);
}
else if (patchFlag & 8 /* PROPS */) {
const dynamicProps = nextVNode.dynamicProps;
for (let i = 0; i < dynamicProps.length; i++) {
const key = dynamicProps[i];
if (nextProps[key] !== prevProps[key]) {
return true;
}
}
}
}
else if (!optimized) {
// this path is only taken by manually written render functions
// so presence of any children leads to a forced update
if (prevChildren != null || nextChildren != null) {
return true;
}
if (prevProps === nextProps) {
return false;
}
if (prevProps === null) {
return nextProps !== null;
}
if (nextProps === null) {
return true;
}