vue-svg-loader
Version:
Use SVG files as Vue Components
1,278 lines (1,265 loc) • 204 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var reactivity = require('@vue/reactivity');
var shared = require('@vue/shared');
const stack = [];
function warn(msg, ...args) {
// avoid props formatting or warn handler tracking deps that might be mutated
// during patch, leading to infinite recursion.
reactivity.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);
}
reactivity.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 (shared.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 (reactivity.isRef(value)) {
value = formatProp(key, reactivity.toRaw(value.value), true);
return raw ? value : [`${key}=Ref<`, value, `>`];
}
else if (shared.isFunction(value)) {
return [`${key}=fn${value.name ? `<${value.name}>` : ``}`];
}
else {
value = reactivity.toRaw(value);
return raw ? value : [`${key}=`, value];
}
}
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 (shared.isFunction(fn)) {
const res = callWithErrorHandling(fn, instance, type, args);
if (res && shared.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 = type;
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);
}
function logError(err, type, contextVNode) {
{
// recover in prod to reduce the impact on end-user
console.error(err);
}
}
let isFlushing = false;
let isFlushPending = false;
const queue = [];
let flushIndex = 0;
const pendingPreFlushCbs = [];
let activePreFlushCbs = null;
let preFlushIndex = 0;
const pendingPostFlushCbs = [];
let activePostFlushCbs = null;
let postFlushIndex = 0;
const resolvedPromise = Promise.resolve();
let currentFlushPromise = null;
let currentPreFlushParentJob = null;
const RECURSION_LIMIT = 100;
function nextTick(fn) {
const p = currentFlushPromise || resolvedPromise;
return fn ? p.then(fn) : p;
}
function queueJob(job) {
// the dedupe search uses the startIndex argument of Array.includes()
// by default the search index includes the current job that is being run
// so it cannot recursively trigger itself again.
// if the job is a watch() callback, the search will start with a +1 index to
// allow it recursively trigger itself - it is the user's responsibility to
// ensure it doesn't end up in an infinite loop.
if ((!queue.length ||
!queue.includes(job, isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex)) &&
job !== currentPreFlushParentJob) {
queue.push(job);
queueFlush();
}
}
function queueFlush() {
if (!isFlushing && !isFlushPending) {
isFlushPending = true;
currentFlushPromise = resolvedPromise.then(flushJobs);
}
}
function invalidateJob(job) {
const i = queue.indexOf(job);
if (i > -1) {
queue[i] = null;
}
}
function queueCb(cb, activeQueue, pendingQueue, index) {
if (!shared.isArray(cb)) {
if (!activeQueue ||
!activeQueue.includes(cb, cb.allowRecurse ? index + 1 : index)) {
pendingQueue.push(cb);
}
}
else {
// if cb is an array, it is a component lifecycle hook which can only be
// triggered by a job, which is already deduped in the main queue, so
// we can skip duplicate check here to improve perf
pendingQueue.push(...cb);
}
queueFlush();
}
function queuePreFlushCb(cb) {
queueCb(cb, activePreFlushCbs, pendingPreFlushCbs, preFlushIndex);
}
function queuePostFlushCb(cb) {
queueCb(cb, activePostFlushCbs, pendingPostFlushCbs, postFlushIndex);
}
function flushPreFlushCbs(seen, parentJob = null) {
if (pendingPreFlushCbs.length) {
currentPreFlushParentJob = parentJob;
activePreFlushCbs = [...new Set(pendingPreFlushCbs)];
pendingPreFlushCbs.length = 0;
for (preFlushIndex = 0; preFlushIndex < activePreFlushCbs.length; preFlushIndex++) {
activePreFlushCbs[preFlushIndex]();
}
activePreFlushCbs = null;
preFlushIndex = 0;
currentPreFlushParentJob = null;
// recursively flush until it drains
flushPreFlushCbs(seen, parentJob);
}
}
function flushPostFlushCbs(seen) {
if (pendingPostFlushCbs.length) {
activePostFlushCbs = [...new Set(pendingPostFlushCbs)];
pendingPostFlushCbs.length = 0;
activePostFlushCbs.sort((a, b) => getId(a) - getId(b));
for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) {
activePostFlushCbs[postFlushIndex]();
}
activePostFlushCbs = null;
postFlushIndex = 0;
}
}
const getId = (job) => job.id == null ? Infinity : job.id;
function flushJobs(seen) {
isFlushPending = false;
isFlushing = true;
flushPreFlushCbs(seen);
// Sort queue before flush.
// This ensures that:
// 1. Components are updated from parent to child. (because parent is always
// created before the child so its render effect will have smaller
// priority number)
// 2. If a component is unmounted during a parent component's update,
// its update can be skipped.
// 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));
try {
for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
const job = queue[flushIndex];
if (job) {
if (false) {
checkRecursiveUpdates(seen, job);
}
callWithErrorHandling(job, null, 14 /* SCHEDULER */);
}
}
}
finally {
flushIndex = 0;
queue.length = 0;
flushPostFlushCbs();
isFlushing = false;
currentFlushPromise = null;
// some postFlushCb queued jobs!
// keep flushing until it drains.
if (queue.length || pendingPostFlushCbs.length) {
flushJobs(seen);
}
}
}
function checkRecursiveUpdates(seen, fn) {
if (!seen.has(fn)) {
seen.set(fn, 1);
}
else {
const count = seen.get(fn);
if (count > RECURSION_LIMIT) {
throw new Error(`Maximum recursive updates exceeded. ` +
`This means you have a reactive effect that is mutating its own ` +
`dependencies and thus recursively triggering itself. Possible sources ` +
`include component template, render function, updated hook or ` +
`watcher source function.`);
}
else {
seen.set(fn, count + 1);
}
}
}
// mark the current rendering instance for asset resolution (e.g.
// resolveComponent, resolveDirective) during render
let currentRenderingInstance = null;
function setCurrentRenderingInstance(instance) {
currentRenderingInstance = instance;
}
// 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, parent, vnode, proxy, withProxy, props, slots, attrs, emit, render, renderCache, data, setupState, ctx } = instance;
let result;
currentRenderingInstance = instance;
try {
let fallthroughAttrs;
if (vnode.shapeFlag & 4 /* STATEFUL_COMPONENT */) {
// withProxy is a proxy with a different `has` trap only for
// runtime-compiled render functions using `with` block.
const proxyToUse = withProxy || proxy;
result = normalizeVNode(render.call(proxyToUse, proxyToUse, renderCache, props, setupState, data, ctx));
fallthroughAttrs = attrs;
}
else {
// functional
const render = Component;
// in dev, mark attrs accessed if optional props (attrs === props)
if (false && attrs === props) {
markAttrsAccessed();
}
result = normalizeVNode(render.length > 1
? render(props, false
? {
get attrs() {
markAttrsAccessed();
return attrs;
},
slots,
emit
}
: { attrs, slots, emit })
: render(props, null /* we know it doesn't need it */));
fallthroughAttrs = Component.props
? attrs
: getFunctionalFallthrough(attrs);
}
// attr merging
// in dev mode, comments are preserved, and it's possible for a template
// to have comments along side the root element which makes it a fragment
let root = result;
let setRoot = undefined;
if (false) {
;
[root, setRoot] = getChildRoot(result);
}
if (Component.inheritAttrs !== false && fallthroughAttrs) {
const keys = Object.keys(fallthroughAttrs);
const { shapeFlag } = root;
if (keys.length) {
if (shapeFlag & 1 /* ELEMENT */ ||
shapeFlag & 6 /* COMPONENT */) {
if (shapeFlag & 1 /* ELEMENT */ && keys.some(shared.isModelListener)) {
// #1643, #1543
// component v-model listeners should only fallthrough for component
// HOCs
fallthroughAttrs = filterModelListeners(fallthroughAttrs);
}
root = cloneVNode(root, fallthroughAttrs);
}
else if (false && !accessedAttrs && root.type !== Comment) {
const allAttrs = Object.keys(attrs);
const eventAttrs = [];
const extraAttrs = [];
for (let i = 0, l = allAttrs.length; i < l; i++) {
const key = allAttrs[i];
if (shared.isOn(key)) {
// ignore v-model handlers when they fail to fallthrough
if (!shared.isModelListener(key)) {
// remove `on`, lowercase first letter to reflect event casing
// accurately
eventAttrs.push(key[2].toLowerCase() + key.slice(3));
}
}
else {
extraAttrs.push(key);
}
}
if (extraAttrs.length) {
warn(`Extraneous non-props attributes (` +
`${extraAttrs.join(', ')}) ` +
`were passed to component but could not be automatically inherited ` +
`because component renders fragment or text root nodes.`);
}
if (eventAttrs.length) {
warn(`Extraneous non-emits event listeners (` +
`${eventAttrs.join(', ')}) ` +
`were passed to component but could not be automatically inherited ` +
`because component renders fragment or text root nodes. ` +
`If the listener is intended to be a component custom event listener only, ` +
`declare it using the "emits" option.`);
}
}
}
}
// inherit scopeId
const scopeId = vnode.scopeId;
// vite#536: if subtree root is created from parent slot if would already
// have the correct scopeId, in this case adding the scopeId will cause
// it to be removed if the original slot vnode is reused.
const needScopeId = scopeId && root.scopeId !== scopeId;
const treeOwnerId = parent && parent.type.__scopeId;
const slotScopeId = treeOwnerId && treeOwnerId !== scopeId ? treeOwnerId + '-s' : null;
if (needScopeId || slotScopeId) {
const extras = {};
if (needScopeId)
extras[scopeId] = '';
if (slotScopeId)
extras[slotScopeId] = '';
root = cloneVNode(root, extras);
}
// inherit directives
if (vnode.dirs) {
if (false && !isElementRoot(root)) {
warn(`Runtime directive used on component with non-element root node. ` +
`The directives will not function as intended.`);
}
root.dirs = vnode.dirs;
}
// inherit transition data
if (vnode.transition) {
if (false && !isElementRoot(root)) {
warn(`Component inside <Transition> renders non-element root node ` +
`that cannot be animated.`);
}
root.transition = vnode.transition;
}
if (false && setRoot) {
setRoot(root);
}
else {
result = root;
}
}
catch (err) {
handleError(err, instance, 1 /* RENDER_FUNCTION */);
result = createVNode(Comment);
}
currentRenderingInstance = null;
return result;
}
/**
* dev only
*/
const getChildRoot = (vnode) => {
if (vnode.type !== Fragment) {
return [vnode, undefined];
}
const rawChildren = vnode.children;
const dynamicChildren = vnode.dynamicChildren;
const children = rawChildren.filter(child => {
return !(isVNode(child) &&
child.type === Comment &&
child.children !== 'v-if');
});
if (children.length !== 1) {
return [vnode, undefined];
}
const childRoot = children[0];
const index = rawChildren.indexOf(childRoot);
const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1;
const setRoot = (updatedRoot) => {
rawChildren[index] = updatedRoot;
if (dynamicIndex > -1) {
dynamicChildren[dynamicIndex] = updatedRoot;
}
else if (dynamicChildren && updatedRoot.patchFlag > 0) {
dynamicChildren.push(updatedRoot);
}
};
return [normalizeVNode(childRoot), setRoot];
};
const getFunctionalFallthrough = (attrs) => {
let res;
for (const key in attrs) {
if (key === 'class' || key === 'style' || shared.isOn(key)) {
(res || (res = {}))[key] = attrs[key];
}
}
return res;
};
const filterModelListeners = (attrs) => {
const res = {};
for (const key in attrs) {
if (!shared.isModelListener(key)) {
res[key] = attrs[key];
}
}
return res;
};
const isElementRoot = (vnode) => {
return (vnode.shapeFlag & 6 /* COMPONENT */ ||
vnode.shapeFlag & 1 /* ELEMENT */ ||
vnode.type === Comment // potential v-if branch switch
);
};
function shouldUpdateComponent(prevVNode, nextVNode, optimized) {
const { props: prevProps, children: prevChildren } = prevVNode;
const { props: nextProps, children: nextChildren, patchFlag } = nextVNode;
// force child update for runtime directive or transition on component vnode.
if (nextVNode.dirs || nextVNode.transition) {
return true;
}
if (optimized && patchFlag > 0) {
if (patchFlag & 1024 /* DYNAMIC_SLOTS */) {
// slot content that references values that might have changed,
// e.g. in a v-for
return true;
}
if (patchFlag & 16 /* FULL_PROPS */) {
if (!prevProps) {
return !!nextProps;
}
// 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 {
// this path is only taken by manually written render functions
// so presence of any children leads to a forced update
if (prevChildren || nextChildren) {
if (!nextChildren || !nextChildren.$stable) {
return true;
}
}
if (prevProps === nextProps) {
return false;
}
if (!prevProps) {
return !!nextProps;
}
if (!nextProps) {
return true;
}
return hasPropsChanged(prevProps, nextProps);
}
return false;
}
function hasPropsChanged(prevProps, nextProps) {
const nextKeys = Object.keys(nextProps);
if (nextKeys.length !== Object.keys(prevProps).length) {
return true;
}
for (let i = 0; i < nextKeys.length; i++) {
const key = nextKeys[i];
if (nextProps[key] !== prevProps[key]) {
return true;
}
}
return false;
}
function updateHOCHostEl({ vnode, parent }, el // HostNode
) {
while (parent && parent.subTree === vnode) {
(vnode = parent.vnode).el = el;
parent = parent.parent;
}
}
const isSuspense = (type) => type.__isSuspense;
// Suspense exposes a component-like API, and is treated like a component
// in the compiler, but internally it's a special built-in type that hooks
// directly into the renderer.
const SuspenseImpl = {
// In order to make Suspense tree-shakable, we need to avoid importing it
// directly in the renderer. The renderer checks for the __isSuspense flag
// on a vnode's type and calls the `process` method, passing in renderer
// internals.
__isSuspense: true,
process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized,
// platform-specific impl passed from renderer
rendererInternals) {
if (n1 == null) {
mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, rendererInternals);
}
else {
patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized, rendererInternals);
}
},
hydrate: hydrateSuspense
};
// Force-casted public typing for h and TSX props inference
const Suspense = ( SuspenseImpl
);
function mountSuspense(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, rendererInternals) {
const { p: patch, o: { createElement } } = rendererInternals;
const hiddenContainer = createElement('div');
const suspense = (n2.suspense = createSuspenseBoundary(n2, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, optimized, rendererInternals));
// start mounting the content subtree in an off-dom container
patch(null, suspense.subTree, hiddenContainer, null, parentComponent, suspense, isSVG, optimized);
// now check if we have encountered any async deps
if (suspense.deps > 0) {
// mount the fallback tree
patch(null, suspense.fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context
isSVG, optimized);
n2.el = suspense.fallbackTree.el;
}
else {
// Suspense has no async deps. Just resolve.
suspense.resolve();
}
}
function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, optimized, { p: patch }) {
const suspense = (n2.suspense = n1.suspense);
suspense.vnode = n2;
const { content, fallback } = normalizeSuspenseChildren(n2);
const oldSubTree = suspense.subTree;
const oldFallbackTree = suspense.fallbackTree;
if (!suspense.isResolved) {
patch(oldSubTree, content, suspense.hiddenContainer, null, parentComponent, suspense, isSVG, optimized);
if (suspense.deps > 0) {
// still pending. patch the fallback tree.
patch(oldFallbackTree, fallback, container, anchor, parentComponent, null, // fallback tree will not have suspense context
isSVG, optimized);
n2.el = fallback.el;
}
// If deps somehow becomes 0 after the patch it means the patch caused an
// async dep component to unmount and removed its dep. It will cause the
// suspense to resolve and we don't need to do anything here.
}
else {
// just normal patch inner content as a fragment
patch(oldSubTree, content, container, anchor, parentComponent, suspense, isSVG, optimized);
n2.el = content.el;
}
suspense.subTree = content;
suspense.fallbackTree = fallback;
}
function createSuspenseBoundary(vnode, parent, parentComponent, container, hiddenContainer, anchor, isSVG, optimized, rendererInternals, isHydrating = false) {
const { p: patch, m: move, um: unmount, n: next, o: { parentNode } } = rendererInternals;
const getCurrentTree = () => suspense.isResolved || suspense.isHydrating
? suspense.subTree
: suspense.fallbackTree;
const { content, fallback } = normalizeSuspenseChildren(vnode);
const suspense = {
vnode,
parent,
parentComponent,
isSVG,
optimized,
container,
hiddenContainer,
anchor,
deps: 0,
subTree: content,
fallbackTree: fallback,
isHydrating,
isResolved: false,
isUnmounted: false,
effects: [],
resolve() {
const { vnode, subTree, fallbackTree, effects, parentComponent, container } = suspense;
if (suspense.isHydrating) {
suspense.isHydrating = false;
}
else {
// this is initial anchor on mount
let { anchor } = suspense;
// unmount fallback tree
if (fallbackTree.el) {
// if the fallback tree was mounted, it may have been moved
// as part of a parent suspense. get the latest anchor for insertion
anchor = next(fallbackTree);
unmount(fallbackTree, parentComponent, suspense, true);
}
// move content from off-dom container to actual container
move(subTree, container, anchor, 0 /* ENTER */);
}
const el = (vnode.el = subTree.el);
// suspense as the root node of a component...
if (parentComponent && parentComponent.subTree === vnode) {
parentComponent.vnode.el = el;
updateHOCHostEl(parentComponent, el);
}
// check if there is a pending parent suspense
let parent = suspense.parent;
let hasUnresolvedAncestor = false;
while (parent) {
if (!parent.isResolved) {
// found a pending parent suspense, merge buffered post jobs
// into that parent
parent.effects.push(...effects);
hasUnresolvedAncestor = true;
break;
}
parent = parent.parent;
}
// no pending parent suspense, flush all jobs
if (!hasUnresolvedAncestor) {
queuePostFlushCb(effects);
}
suspense.isResolved = true;
suspense.effects = [];
// invoke @resolve event
const onResolve = vnode.props && vnode.props.onResolve;
if (shared.isFunction(onResolve)) {
onResolve();
}
},
recede() {
suspense.isResolved = false;
const { vnode, subTree, fallbackTree, parentComponent, container, hiddenContainer, isSVG, optimized } = suspense;
// move content tree back to the off-dom container
const anchor = next(subTree);
move(subTree, hiddenContainer, null, 1 /* LEAVE */);
// remount the fallback tree
patch(null, fallbackTree, container, anchor, parentComponent, null, // fallback tree will not have suspense context
isSVG, optimized);
const el = (vnode.el = fallbackTree.el);
// suspense as the root node of a component...
if (parentComponent && parentComponent.subTree === vnode) {
parentComponent.vnode.el = el;
updateHOCHostEl(parentComponent, el);
}
// invoke @recede event
const onRecede = vnode.props && vnode.props.onRecede;
if (shared.isFunction(onRecede)) {
onRecede();
}
},
move(container, anchor, type) {
move(getCurrentTree(), container, anchor, type);
suspense.container = container;
},
next() {
return next(getCurrentTree());
},
registerDep(instance, setupRenderEffect) {
// suspense is already resolved, need to recede.
// use queueJob so it's handled synchronously after patching the current
// suspense tree
if (suspense.isResolved) {
queueJob(() => {
suspense.recede();
});
}
const hydratedEl = instance.vnode.el;
suspense.deps++;
instance
.asyncDep.catch(err => {
handleError(err, instance, 0 /* SETUP_FUNCTION */);
})
.then(asyncSetupResult => {
// retry when the setup() promise resolves.
// component may have been unmounted before resolve.
if (instance.isUnmounted || suspense.isUnmounted) {
return;
}
suspense.deps--;
// retry from this component
instance.asyncResolved = true;
const { vnode } = instance;
handleSetupResult(instance, asyncSetupResult, false);
if (hydratedEl) {
// vnode may have been replaced if an update happened before the
// async dep is resolved.
vnode.el = hydratedEl;
}
setupRenderEffect(instance, vnode,
// component may have been moved before resolve.
// if this is not a hydration, instance.subTree will be the comment
// placeholder.
hydratedEl
? parentNode(hydratedEl)
: parentNode(instance.subTree.el),
// anchor will not be used if this is hydration, so only need to
// consider the comment placeholder case.
hydratedEl ? null : next(instance.subTree), suspense, isSVG, optimized);
updateHOCHostEl(instance, vnode.el);
if (suspense.deps === 0) {
suspense.resolve();
}
});
},
unmount(parentSuspense, doRemove) {
suspense.isUnmounted = true;
unmount(suspense.subTree, parentComponent, parentSuspense, doRemove);
if (!suspense.isResolved) {
unmount(suspense.fallbackTree, parentComponent, parentSuspense, doRemove);
}
}
};
return suspense;
}
function hydrateSuspense(node, vnode, parentComponent, parentSuspense, isSVG, optimized, rendererInternals, hydrateNode) {
/* eslint-disable no-restricted-globals */
const suspense = (vnode.suspense = createSuspenseBoundary(vnode, parentSuspense, parentComponent, node.parentNode, document.createElement('div'), null, isSVG, optimized, rendererInternals, true /* hydrating */));
// there are two possible scenarios for server-rendered suspense:
// - success: ssr content should be fully resolved
// - failure: ssr content should be the fallback branch.
// however, on the client we don't really know if it has failed or not
// attempt to hydrate the DOM assuming it has succeeded, but we still
// need to construct a suspense boundary first
const result = hydrateNode(node, suspense.subTree, parentComponent, suspense, optimized);
if (suspense.deps === 0) {
suspense.resolve();
}
return result;
/* eslint-enable no-restricted-globals */
}
function normalizeSuspenseChildren(vnode) {
const { shapeFlag, children } = vnode;
if (shapeFlag & 32 /* SLOTS_CHILDREN */) {
const { default: d, fallback } = children;
return {
content: normalizeVNode(shared.isFunction(d) ? d() : d),
fallback: normalizeVNode(shared.isFunction(fallback) ? fallback() : fallback)
};
}
else {
return {
content: normalizeVNode(children),
fallback: normalizeVNode(null)
};
}
}
function queueEffectWithSuspense(fn, suspense) {
if (suspense && !suspense.isResolved) {
if (shared.isArray(fn)) {
suspense.effects.push(...fn);
}
else {
suspense.effects.push(fn);
}
}
else {
queuePostFlushCb(fn);
}
}
let isRenderingCompiledSlot = 0;
/**
* Compiler runtime helper for rendering `<slot/>`
* @private
*/
function renderSlot(slots, name, props = {},
// this is not a user-facing function, so the fallback is always generated by
// the compiler and guaranteed to be a function returning an array
fallback) {
let slot = slots[name];
// a compiled slot disables block tracking by default to avoid manual
// invocation interfering with template-based block tracking, but in
// `renderSlot` we can be sure that it's template-based so we can force
// enable it.
isRenderingCompiledSlot++;
const rendered = (openBlock(),
createBlock(Fragment, { key: props.key }, slot ? slot(props) : fallback ? fallback() : [], slots._ === 1 /* STABLE */
? 64 /* STABLE_FRAGMENT */
: -2 /* BAIL */));
isRenderingCompiledSlot--;
return rendered;
}
/**
* Wrap a slot function to memoize current rendering instance
* @private
*/
function withCtx(fn, ctx = currentRenderingInstance) {
if (!ctx)
return fn;
return function renderFnWithContext() {
// If a user calls a compiled slot inside a template expression (#1745), it
// can mess up block tracking, so by default we need to push a null block to
// avoid that. This isn't necessary if rendering a compiled `<slot>`.
if (!isRenderingCompiledSlot) {
openBlock(true /* null block that disables tracking */);
}
const owner = currentRenderingInstance;
setCurrentRenderingInstance(ctx);
const res = fn.apply(null, arguments);
setCurrentRenderingInstance(owner);
if (!isRenderingCompiledSlot) {
closeBlock();
}
return res;
};
}
// SFC scoped style ID management.
let currentScopeId = null;
const scopeIdStack = [];
/**
* @private
*/
function pushScopeId(id) {
scopeIdStack.push((currentScopeId = id));
}
/**
* @private
*/
function popScopeId() {
scopeIdStack.pop();
currentScopeId = scopeIdStack[scopeIdStack.length - 1] || null;
}
/**
* @private
*/
function withScopeId(id) {
return ((fn) => withCtx(function () {
pushScopeId(id);
const res = fn.apply(this, arguments);
popScopeId();
return res;
}));
}
const isTeleport = (type) => type.__isTeleport;
const isTeleportDisabled = (props) => props && (props.disabled || props.disabled === '');
const resolveTarget = (props, select) => {
const targetSelector = props && props.to;
if (shared.isString(targetSelector)) {
if (!select) {
return null;
}
else {
const target = select(targetSelector);
return target;
}
}
else {
return targetSelector;
}
};
const TeleportImpl = {
__isTeleport: true,
process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals) {
const { mc: mountChildren, pc: patchChildren, pbc: patchBlockChildren, o: { insert, querySelector, createText, createComment } } = internals;
const disabled = isTeleportDisabled(n2.props);
const { shapeFlag, children } = n2;
if (n1 == null) {
// insert anchors in the main view
const placeholder = (n2.el = createText(''));
const mainAnchor = (n2.anchor = createText(''));
insert(placeholder, container, anchor);
insert(mainAnchor, container, anchor);
const target = (n2.target = resolveTarget(n2.props, querySelector));
const targetAnchor = (n2.targetAnchor = createText(''));
if (target) {
insert(targetAnchor, target);
}
const mount = (container, anchor) => {
// Teleport *always* has Array children. This is enforced in both the
// compiler and vnode children normalization.
if (shapeFlag & 16 /* ARRAY_CHILDREN */) {
mountChildren(children, container, anchor, parentComponent, parentSuspense, isSVG, optimized);
}
};
if (disabled) {
mount(container, mainAnchor);
}
else if (target) {
mount(target, targetAnchor);
}
}
else {
// update content
n2.el = n1.el;
const mainAnchor = (n2.anchor = n1.anchor);
const target = (n2.target = n1.target);
const targetAnchor = (n2.targetAnchor = n1.targetAnchor);
const wasDisabled = isTeleportDisabled(n1.props);
const currentContainer = wasDisabled ? container : target;
const currentAnchor = wasDisabled ? mainAnchor : targetAnchor;
if (n2.dynamicChildren) {
// fast path when the teleport happens to be a block root
patchBlockChildren(n1.dynamicChildren, n2.dynamicChildren, currentContainer, parentComponent, parentSuspense, isSVG);
// even in block tree mode we need to make sure all root-level nodes
// in the teleport inherit previous DOM references so that they can
// be moved in future patches.
if (n2.shapeFlag & 16 /* ARRAY_CHILDREN */) {
const oldChildren = n1.children;
const children = n2.children;
for (let i = 0; i < children.length; i++) {
// only inherit for non-patched nodes (i.e. static ones)
if (!children[i].el) {
children[i].el = oldChildren[i].el;
}
}
}
}
else if (!optimized) {
patchChildren(n1, n2, currentContainer, currentAnchor, parentComponent, parentSuspense, isSVG);
}
if (disabled) {
if (!wasDisabled) {
// enabled -> disabled
// move into main container
moveTeleport(n2, container, mainAnchor, internals, 1 /* TOGGLE */);
}
}
else {
// target changed
if ((n2.props && n2.props.to) !== (n1.props && n1.props.to)) {
const nextTarget = (n2.target = resolveTarget(n2.props, querySelector));
if (nextTarget) {
moveTeleport(n2, nextTarget, null, internals, 0 /* TARGET_CHANGE */);
}
}
else if (wasDisabled) {
// disabled -> enabled
// move into teleport target
moveTeleport(n2, target, targetAnchor, internals, 1 /* TOGGLE */);
}
}
}
},
remove(vnode, { r: remove, o: { remove: hostRemove } }) {
const { shapeFlag, children, anchor } = vnode;
hostRemove(anchor);
if (shapeFlag & 16 /* ARRAY_CHILDREN */) {
for (let i = 0; i < children.length; i++) {
remove(children[i]);
}
}
},
move: moveTeleport,
hydrate: hydrateTeleport
};
function moveTeleport(vnode, container, parentAnchor, { o: { insert }, m: move }, moveType = 2 /* REORDER */) {
// move target anchor if this is a target change.
if (moveType === 0 /* TARGET_CHANGE */) {
insert(vnode.targetAnchor, container, parentAnchor);
}
const { el, anchor, shapeFlag, children, props } = vnode;
const isReorder = moveType === 2 /* REORDER */;
// move main view anchor if this is a re-order.
if (isReorder) {
insert(el, container, parentAnchor);
}
// if this is a re-order and teleport is enabled (content is in target)
// do not move children. So the opposite is: only move children if this
// is not a reorder, or the teleport is disabled
if (!isReorder || isTeleportDisabled(props)) {
// Teleport has either Array children or no children.
if (shapeFlag & 16 /* ARRAY_CHILDREN */) {
for (let i = 0; i < children.length; i++) {
move(children[i], container, parentAnchor, 2 /* REORDER */);
}
}
}
// move main view anchor if this is a re-order.
if (isReorder) {
insert(anchor, container, parentAnchor);
}
}
function hydrateTeleport(node, vnode, parentComponent, parentSuspense, optimized, { o: { nextSibling, parentNode, querySelector } }, hydrateChildren) {
const target = (vnode.target = resolveTarget(vnode.props, querySelector));
if (target) {
// if multiple teleports rendered to the same target element, we need to
// pick up from where the last teleport finished instead of the first node
const targetNode = target._lpa || target.firstChild;
if (vnode.shapeFlag & 16 /* ARRAY_CHILDREN */) {
if (isTeleportDisabled(vnode.props)) {
vnode.anchor = hydrateChildren(nextSibling(node), vnode, parentNode(node), parentComponent, parentSuspense, optimized);
vnode.targetAnchor = targetNode;
}
else {
vnode.anchor = nextSibling(node);
vnode.targetAnchor = hydrateChildren(targetNode, vnode, target, parentComponent, parentSuspense, optimized);
}
target._lpa =
vnode.targetAnchor && nextSibling(vnode.targetAnchor);
}
}
return vnode.anchor && nextSibling(vnode.anchor);
}
// Force-casted public typing for h and TSX props inference
const Teleport = TeleportImpl;
const COMPONENTS = 'components';
const DIRECTIVES = 'directives';
/**
* @private
*/
function resolveComponent(name) {
return resolveAsset(COMPONENTS, name) || name;
}
const NULL_DYNAMIC_COMPONENT = Symbol();
/**
* @private
*/
function resolveDynamicComponent(component) {
if (shared.isString(component)) {
return resolveAsset(COMPONENTS, component, false) || component;
}
else {
// invalid types will fallthrough to createVNode and raise warning
return (component || NULL_DYNAMIC_COMPONENT);
}
}
/**
* @private
*/
function resolveDirective(name) {
return resolveAsset(DIRECTIVES, name);
}
// implementation
function resolveAsset(type, name, warnMissing = true) {
const instance = currentRenderingInstance || currentInstance;
if (instance) {
const Component = instance.type;
// self name has highest priority
if (type === COMPONENTS) {
const selfName = Component.displayName || Component.name;
if (selfName &&
(selfName === name ||
selfName === shared.camelize(name) ||
selfName === shared.capitalize(shared.camelize(name)))) {
return Component;
}
}
const res =
// local registration
resolve(Component[type], name) ||
// global registration
resolve(instance.appContext[type], name);
return res;
}
}
function resolve(registry, name) {
return (registry &&
(registry[name] ||
registry[shared.camelize(name)] ||
registry[shared.capitalize(shared.camelize(name))]));
}
const Fragment = Symbol( undefined);
const Text = Symbol( undefined);
const Comment = Symbol( undefined);
const Static = Symbol( undefined);
// 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:
*
* ```js
* function render() {
* return (openBlock(),createBlock('div', null, [...]))
* }
* ```
* disableTracking is true when creating a v-for fragment block, since a v-for
* fragment always diffs its children.
*
* @private
*/
function openBlock(disableTracking = false) {
blockStack.push((currentBlock = disableTracking ? null : []));
}
function closeBlock() {
blockStack.pop();
currentBlock = blockStack[blockStack.length - 1] || 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;
/**
* Block tracking sometimes needs to be disabled, for example during the
* creation of a tree that needs to be cached by v-once. The compiler generates
* code like this:
*
* ``` js
* _cache[1] || (
* setBlockTracking(-1),
* _cache[1] = createVNode(...),
* setBlockTracking(1),
* _cache[1]
* )
* ```
*
* @private
*/
function setBlockTracking(value) {
shouldTrack += 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.
*
* @private
*/
function createBlock(type, props, children, patchFlag, dynamicProps) {
const vnode = createVNode(type, props, children, patchFlag, dynamicProps, true /* isBlock: prevent a block from tracking itself */);
// save current block children on the block vnode
vnode.dynamicChildren = currentBlock || shared.EMPTY_ARR;
// close block
closeBlock();
// a block is always going to be patched, so track it as a child of its
// parent block
if (currentBlock) {
currentBlock.push(vnode);
}
return vnode;
}
function isVNode(value) {
return value ? value.__v_isVNode === true : false;
}
function isSameVNodeType(n1, n2) {
return n1.type === n2.type && n1.key === n2.key;
}
/**
* Internal API for registering an arguments transform for createVNode
* used for creating stubs in the test-utils
* It is *internal* but needs to be exposed for test-utils to pick up proper
* typings
*/
function transformVNodeArgs(transformer) {
}
const InternalObjectKey = `__vInternal`;
const normalizeKey = ({ key }) => key != null ? key : null;
const normalizeRef = ({ ref }) => {
return (ref != null
? shared.isArray(ref)
? ref
: [currentRenderingInstance, ref]
: null);
};
const createVNode = ( _createVNode);
function _createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, isBlockNode = false) {
if (!type || type === NULL_DYNAMIC_COMPONENT) {
type = Comment