Best JavaScript code snippet using playwright-internal
createApp.js
Source:createApp.js  
...348                        hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);349                    }350                }351                if ((vnodeHook = props.onVnodeBeforeMount)) {352                    invokeVNodeHook(vnodeHook, parentComponent, vnode);353                }354            }355            // scopeId356            setScopeId(el, scopeId, vnode, parentComponent);357        }358        {359            Object.defineProperty(el, '__vnode', {360                value: vnode,361                enumerable: false362            });363            Object.defineProperty(el, '__vueParentComponent', {364                value: parentComponent,365                enumerable: false366            });367        }368        if (dirs) {369            invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount');370        }371        // #1583 For inside suspense + suspense not resolved case, enter hook should call when suspense resolved372        // #1689 For inside suspense + suspense resolved case, just call it373        const needCallTransitionHooks = (!parentSuspense || (parentSuspense && !parentSuspense.pendingBranch)) &&374            transition &&375            !transition.persisted;376        if (needCallTransitionHooks) {377            transition.beforeEnter(el);378        }379        hostInsert(el, container, anchor);380        if ((vnodeHook = props && props.onVnodeMounted) ||381            needCallTransitionHooks ||382            dirs) {383            queuePostRenderEffect(() => {384                vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);385                needCallTransitionHooks && transition.enter(el);386                dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted');387            }, parentSuspense);388        }389    };390    const setScopeId = (el, scopeId, vnode, parentComponent) => {391        if (scopeId) {392            hostSetScopeId(el, scopeId);393        }394        if (parentComponent) {395            const treeOwnerId = parentComponent.type.__scopeId;396            // vnode's own scopeId and the current patched component's scopeId is397            // different - this is a slot content node.398            if (treeOwnerId && treeOwnerId !== scopeId) {399                hostSetScopeId(el, treeOwnerId + '-s');400            }401            let subTree = parentComponent.subTree;402            if ( subTree.type === Fragment) {403                subTree =404                    filterSingleRoot(subTree.children) || subTree;405            }406            if (vnode === subTree) {407                setScopeId(el, parentComponent.vnode.scopeId, parentComponent.vnode, parentComponent.parent);408            }409        }410    };411    const mountChildren = (children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) => {412        for (let i = start; i < children.length; i++) {413            const child = (children[i] = optimized414                ? cloneIfMounted(children[i])415                : normalizeVNode(children[i]));416            patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);417        }418    };419    const patchElement = (n1, n2, parentComponent, parentSuspense, isSVG, optimized) => {420        const el = (n2.el = n1.el);421        let { patchFlag, dynamicChildren, dirs } = n2;422        // #1426 take the old vnode's patch flag into account since user may clone a423        // compiler-generated vnode, which de-opts to FULL_PROPS424        patchFlag |= n1.patchFlag & 16 /* FULL_PROPS */;425        const oldProps = n1.props || EMPTY_OBJ;426        const newProps = n2.props || EMPTY_OBJ;427        let vnodeHook;428        if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {429            invokeVNodeHook(vnodeHook, parentComponent, n2, n1);430        }431        if (dirs) {432            invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate');433        }434        if ( isHmrUpdating) {435            // HMR updated, force full diff436            patchFlag = 0;437            optimized = false;438            dynamicChildren = null;439        }440        if (patchFlag > 0) {441            // the presence of a patchFlag means this element's render code was442            // generated by the compiler and can take the fast path.443            // in this path old node and new node are guaranteed to have the same shape444            // (i.e. at the exact same position in the source template)445            if (patchFlag & 16 /* FULL_PROPS */) {446                // element props contain dynamic keys, full diff needed447                patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);448            }449            else {450                // class451                // this flag is matched when the element has dynamic class bindings.452                if (patchFlag & 2 /* CLASS */) {453                    if (oldProps.class !== newProps.class) {454                        hostPatchProp(el, 'class', null, newProps.class, isSVG);455                    }456                }457                // style458                // this flag is matched when the element has dynamic style bindings459                if (patchFlag & 4 /* STYLE */) {460                    hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG);461                }462                // props463                // This flag is matched when the element has dynamic prop/attr bindings464                // other than class and style. The keys of dynamic prop/attrs are saved for465                // faster iteration.466                // Note dynamic keys like :[foo]="bar" will cause this optimization to467                // bail out and go through a full diff because we need to unset the old key468                if (patchFlag & 8 /* PROPS */) {469                    // if the flag is present then dynamicProps must be non-null470                    const propsToUpdate = n2.dynamicProps;471                    for (let i = 0; i < propsToUpdate.length; i++) {472                        const key = propsToUpdate[i];473                        const prev = oldProps[key];474                        const next = newProps[key];475                        if (next !== prev ||476                            (hostForcePatchProp && hostForcePatchProp(el, key))) {477                            hostPatchProp(el, key, prev, next, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);478                        }479                    }480                }481            }482            // text483            // This flag is matched when the element has only dynamic text children.484            if (patchFlag & 1 /* TEXT */) {485                if (n1.children !== n2.children) {486                    hostSetElementText(el, n2.children);487                }488            }489        }490        else if (!optimized && dynamicChildren == null) {491            // unoptimized, full diff492            patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);493        }494        const areChildrenSVG = isSVG && n2.type !== 'foreignObject';495        if (dynamicChildren) {496            patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, areChildrenSVG);497            if ( parentComponent && parentComponent.type.__hmrId) {498                traverseStaticChildren(n1, n2);499            }500        }501        else if (!optimized) {502            // full diff503            patchChildren(n1, n2, el, null, parentComponent, parentSuspense, areChildrenSVG);504        }505        if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {506            queuePostRenderEffect(() => {507                vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1);508                dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated');509            }, parentSuspense);510        }511    };512    // The fast path for blocks.513    const patchBlockChildren = (oldChildren, newChildren, fallbackContainer, parentComponent, parentSuspense, isSVG) => {514        for (let i = 0; i < newChildren.length; i++) {515            const oldVNode = oldChildren[i];516            const newVNode = newChildren[i];517            // Determine the container (parent element) for the patch.518            const container = 519            // - In the case of a Fragment, we need to provide the actual parent520            // of the Fragment itself so it can move its children.521            oldVNode.type === Fragment ||522                // - In the case of different nodes, there is going to be a replacement523                // which also requires the correct parent container524                !isSameVNodeType(oldVNode, newVNode) ||525                // - In the case of a component, it could contain anything.526                oldVNode.shapeFlag & 6 /* COMPONENT */ ||527                oldVNode.shapeFlag & 64 /* TELEPORT */528                ? hostParentNode(oldVNode.el)529                : // In other cases, the parent container is not actually used so we530                    // just pass the block element here to avoid a DOM parentNode call.531                    fallbackContainer;532            patch(oldVNode, newVNode, container, null, parentComponent, parentSuspense, isSVG, true);533        }534    };535    const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {536        if (oldProps !== newProps) {537            for (const key in newProps) {538                if (isReservedProp(key))539                    continue;540                const next = newProps[key];541                const prev = oldProps[key];542                if (next !== prev ||543                    (hostForcePatchProp && hostForcePatchProp(el, key))) {544                    hostPatchProp(el, key, prev, next, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);545                }546            }547            if (oldProps !== EMPTY_OBJ) {548                for (const key in oldProps) {549                    if (!isReservedProp(key) && !(key in newProps)) {550                        hostPatchProp(el, key, oldProps[key], null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);551                    }552                }553            }554        }555    };556    const processFragment = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {557        const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''));558        const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''));559        let { patchFlag, dynamicChildren } = n2;560        if (patchFlag > 0) {561            optimized = true;562        }563        if ( isHmrUpdating) {564            // HMR updated, force full diff565            patchFlag = 0;566            optimized = false;567            dynamicChildren = null;568        }569        if (n1 == null) {570            hostInsert(fragmentStartAnchor, container, anchor);571            hostInsert(fragmentEndAnchor, container, anchor);572            // a fragment can only have array children573            // since they are either generated by the compiler, or implicitly created574            // from arrays.575            mountChildren(n2.children, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);576        }577        else {578            if (patchFlag > 0 &&579                patchFlag & 64 /* STABLE_FRAGMENT */ &&580                dynamicChildren) {581                // a stable fragment (template root or <template v-for>) doesn't need to582                // patch children order, but it may contain dynamicChildren.583                patchBlockChildren(n1.dynamicChildren, dynamicChildren, container, parentComponent, parentSuspense, isSVG);584                if ( parentComponent && parentComponent.type.__hmrId) {585                    traverseStaticChildren(n1, n2);586                }587                else if (588                // #2080 if the stable fragment has a key, it's a <template v-for> that may589                //  get moved around. Make sure all root level vnodes inherit el.590                // #2134 or if it's a component root, it may also get moved around591                // as the component is being moved.592                n2.key != null ||593                    (parentComponent && n2 === parentComponent.subTree)) {594                    traverseStaticChildren(n1, n2, true /* shallow */);595                }596            }597            else {598                // keyed / unkeyed, or manual fragments.599                // for keyed & unkeyed, since they are compiler generated from v-for,600                // each child is guaranteed to be a block so the fragment will never601                // have dynamicChildren.602                patchChildren(n1, n2, container, fragmentEndAnchor, parentComponent, parentSuspense, isSVG, optimized);603            }604        }605    };606    const processComponent = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {607        if (n1 == null) {608            if (n2.shapeFlag & 512 /* COMPONENT_KEPT_ALIVE */) {609                parentComponent.ctx.activate(n2, container, anchor, isSVG, optimized);610            }611            else {612                mountComponent(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);613            }614        }615        else {616            updateComponent(n1, n2, optimized);617        }618    };619    const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {620        const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent, parentSuspense));621        if ( instance.type.__hmrId) {622            registerHMR(instance);623        }624        {625            pushWarningContext(initialVNode);626            startMeasure(instance, `mount`);627        }628        // inject renderer internals for keepAlive629        if (isKeepAlive(initialVNode)) {630            instance.ctx.renderer = internals;631        }632        // resolve props and slots for setup context633        {634            startMeasure(instance, `init`);635        }636        setupComponent(instance);637        {638            endMeasure(instance, `init`);639        }640        // setup() is async. This component relies on async logic to be resolved641        // before proceeding642        if ( instance.asyncDep) {643            parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect);644            // Give it a placeholder if this is not hydration645            // TODO handle self-defined fallback646            if (!initialVNode.el) {647                const placeholder = (instance.subTree = createVNode(Comment));648                processCommentNode(null, placeholder, container, anchor);649            }650            return;651        }652        setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized);653        {654            popWarningContext();655            endMeasure(instance, `mount`);656        }657    };658    const updateComponent = (n1, n2, optimized) => {659        const instance = (n2.component = n1.component);660        if (shouldUpdateComponent(n1, n2, optimized)) {661            if (662                instance.asyncDep &&663                !instance.asyncResolved) {664                // async & still pending - just update props and slots665                // since the component's reactive effect for render isn't set-up yet666                {667                    pushWarningContext(n2);668                }669                updateComponentPreRender(instance, n2, optimized);670                {671                    popWarningContext();672                }673                return;674            }675            else {676                // normal update677                instance.next = n2;678                // in case the child component is also queued, remove it to avoid679                // double updating the same child component in the same flush.680                invalidateJob(instance.update);681                // instance.update is the reactive effect runner.682                instance.update();683            }684        }685        else {686            // no update needed. just copy over properties687            n2.component = n1.component;688            n2.el = n1.el;689            instance.vnode = n2;690        }691    };692    const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {693        // create reactive effect for rendering694        instance.update = effect(function componentEffect() {695            if (!instance.isMounted) {696                let vnodeHook;697                const { el, props } = initialVNode;698                const { bm, m, parent } = instance;699                // beforeMount hook700                if (bm) {701                    invokeArrayFns(bm);702                }703                // onVnodeBeforeMount704                if ((vnodeHook = props && props.onVnodeBeforeMount)) {705                    invokeVNodeHook(vnodeHook, parent, initialVNode);706                }707                // render708                {709                    startMeasure(instance, `render`);710                }711                const subTree = (instance.subTree = renderComponentRoot(instance));712                {713                    endMeasure(instance, `render`);714                }715                if (el && hydrateNode) {716                    {717                        startMeasure(instance, `hydrate`);718                    }719                    // vnode has adopted host node - perform hydration instead of mount.720                    hydrateNode(initialVNode.el, subTree, instance, parentSuspense);721                    {722                        endMeasure(instance, `hydrate`);723                    }724                }725                else {726                    {727                        startMeasure(instance, `patch`);728                    }729                    patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);730                    {731                        endMeasure(instance, `patch`);732                    }733                    initialVNode.el = subTree.el;734                }735                // mounted hook736                if (m) {737                    queuePostRenderEffect(m, parentSuspense);738                }739                // onVnodeMounted740                if ((vnodeHook = props && props.onVnodeMounted)) {741                    queuePostRenderEffect(() => {742                        invokeVNodeHook(vnodeHook, parent, initialVNode);743                    }, parentSuspense);744                }745                // activated hook for keep-alive roots.746                // #1742 activated hook must be accessed after first render747                // since the hook may be injected by a child keep-alive748                const { a } = instance;749                if (a &&750                    initialVNode.shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {751                    queuePostRenderEffect(a, parentSuspense);752                }753                instance.isMounted = true;754            }755            else {756                // updateComponent757                // This is triggered by mutation of component's own state (next: null)758                // OR parent calling processComponent (next: VNode)759                let { next, bu, u, parent, vnode } = instance;760                let originNext = next;761                let vnodeHook;762                {763                    pushWarningContext(next || instance.vnode);764                }765                if (next) {766                    updateComponentPreRender(instance, next, optimized);767                }768                else {769                    next = vnode;770                }771                next.el = vnode.el;772                // beforeUpdate hook773                if (bu) {774                    invokeArrayFns(bu);775                }776                // onVnodeBeforeUpdate777                if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {778                    invokeVNodeHook(vnodeHook, parent, next, vnode);779                }780                // render781                {782                    startMeasure(instance, `render`);783                }784                const nextTree = renderComponentRoot(instance);785                {786                    endMeasure(instance, `render`);787                }788                const prevTree = instance.subTree;789                instance.subTree = nextTree;790                // reset refs791                // only needed if previous patch had refs792                if (instance.refs !== EMPTY_OBJ) {793                    instance.refs = {};794                }795                {796                    startMeasure(instance, `patch`);797                }798                patch(prevTree, nextTree, 799                // parent may have changed if it's in a teleport800                hostParentNode(prevTree.el), 801                // anchor may have changed if it's in a fragment802                getNextHostNode(prevTree), instance, parentSuspense, isSVG);803                {804                    endMeasure(instance, `patch`);805                }806                next.el = nextTree.el;807                if (originNext === null) {808                    // self-triggered update. In case of HOC, update parent component809                    // vnode el. HOC is indicated by parent instance's subTree pointing810                    // to child component's vnode811                    updateHOCHostEl(instance, nextTree.el);812                }813                // updated hook814                if (u) {815                    queuePostRenderEffect(u, parentSuspense);816                }817                // onVnodeUpdated818                if ((vnodeHook = next.props && next.props.onVnodeUpdated)) {819                    queuePostRenderEffect(() => {820                        invokeVNodeHook(vnodeHook, parent, next, vnode);821                    }, parentSuspense);822                }823                {824                    devtoolsComponentUpdated(instance);825                }826                {827                    popWarningContext();828                }829            }830        },  createDevEffectOptions(instance) );831    };832    const updateComponentPreRender = (instance, nextVNode, optimized) => {833        nextVNode.component = instance;834        const prevProps = instance.vnode.props;835        instance.vnode = nextVNode;836        instance.next = null;837        updateProps(instance, nextVNode.props, prevProps, optimized);838        updateSlots(instance, nextVNode.children);839        // props update may have triggered pre-flush watchers.840        // flush them before the render update.841        flushPreFlushCbs(undefined, instance.update);842    };843    const patchChildren = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized = false) => {844        const c1 = n1 && n1.children;845        const prevShapeFlag = n1 ? n1.shapeFlag : 0;846        const c2 = n2.children;847        const { patchFlag, shapeFlag } = n2;848        // fast path849        if (patchFlag > 0) {850            if (patchFlag & 128 /* KEYED_FRAGMENT */) {851                // this could be either fully-keyed or mixed (some keyed some not)852                // presence of patchFlag means children are guaranteed to be arrays853                patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);854                return;855            }856            else if (patchFlag & 256 /* UNKEYED_FRAGMENT */) {857                // unkeyed858                patchUnkeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);859                return;860            }861        }862        // children has 3 possibilities: text, array or no children.863        if (shapeFlag & 8 /* TEXT_CHILDREN */) {864            // text children fast path865            if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {866                unmountChildren(c1, parentComponent, parentSuspense);867            }868            if (c2 !== c1) {869                hostSetElementText(container, c2);870            }871        }872        else {873            if (prevShapeFlag & 16 /* ARRAY_CHILDREN */) {874                // prev children was array875                if (shapeFlag & 16 /* ARRAY_CHILDREN */) {876                    // two arrays, cannot assume anything, do full diff877                    patchKeyedChildren(c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);878                }879                else {880                    // no new children, just unmount old881                    unmountChildren(c1, parentComponent, parentSuspense, true);882                }883            }884            else {885                // prev children was text OR null886                // new children is array OR null887                if (prevShapeFlag & 8 /* TEXT_CHILDREN */) {888                    hostSetElementText(container, '');889                }890                // mount new if array891                if (shapeFlag & 16 /* ARRAY_CHILDREN */) {892                    mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);893                }894            }895        }896    };897    const patchUnkeyedChildren = (c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {898        c1 = c1 || EMPTY_ARR;899        c2 = c2 || EMPTY_ARR;900        const oldLength = c1.length;901        const newLength = c2.length;902        const commonLength = Math.min(oldLength, newLength);903        let i;904        for (i = 0; i < commonLength; i++) {905            const nextChild = (c2[i] = optimized906                ? cloneIfMounted(c2[i])907                : normalizeVNode(c2[i]));908            patch(c1[i], nextChild, container, null, parentComponent, parentSuspense, isSVG, optimized);909        }910        if (oldLength > newLength) {911            // remove old912            unmountChildren(c1, parentComponent, parentSuspense, true, commonLength);913        }914        else {915            // mount new916            mountChildren(c2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, commonLength);917        }918    };919    // can be all-keyed or mixed920    const patchKeyedChildren = (c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, optimized) => {921        let i = 0;922        const l2 = c2.length;923        let e1 = c1.length - 1; // prev ending index924        let e2 = l2 - 1; // next ending index925        // 1. sync from start926        // (a b) c927        // (a b) d e928        while (i <= e1 && i <= e2) {929            const n1 = c1[i];930            const n2 = (c2[i] = optimized931                ? cloneIfMounted(c2[i])932                : normalizeVNode(c2[i]));933            if (isSameVNodeType(n1, n2)) {934                patch(n1, n2, container, null, parentComponent, parentSuspense, isSVG, optimized);935            }936            else {937                break;938            }939            i++;940        }941        // 2. sync from end942        // a (b c)943        // d e (b c)944        while (i <= e1 && i <= e2) {945            const n1 = c1[e1];946            const n2 = (c2[e2] = optimized947                ? cloneIfMounted(c2[e2])948                : normalizeVNode(c2[e2]));949            if (isSameVNodeType(n1, n2)) {950                patch(n1, n2, container, null, parentComponent, parentSuspense, isSVG, optimized);951            }952            else {953                break;954            }955            e1--;956            e2--;957        }958        // 3. common sequence + mount959        // (a b)960        // (a b) c961        // i = 2, e1 = 1, e2 = 2962        // (a b)963        // c (a b)964        // i = 0, e1 = -1, e2 = 0965        if (i > e1) {966            if (i <= e2) {967                const nextPos = e2 + 1;968                const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;969                while (i <= e2) {970                    patch(null, (c2[i] = optimized971                        ? cloneIfMounted(c2[i])972                        : normalizeVNode(c2[i])), container, anchor, parentComponent, parentSuspense, isSVG);973                    i++;974                }975            }976        }977        // 4. common sequence + unmount978        // (a b) c979        // (a b)980        // i = 2, e1 = 2, e2 = 1981        // a (b c)982        // (b c)983        // i = 0, e1 = 0, e2 = -1984        else if (i > e2) {985            while (i <= e1) {986                unmount(c1[i], parentComponent, parentSuspense, true);987                i++;988            }989        }990        // 5. unknown sequence991        // [i ... e1 + 1]: a b [c d e] f g992        // [i ... e2 + 1]: a b [e d c h] f g993        // i = 2, e1 = 4, e2 = 5994        else {995            const s1 = i; // prev starting index996            const s2 = i; // next starting index997            // 5.1 build key:index map for newChildren998            const keyToNewIndexMap = new Map();999            for (i = s2; i <= e2; i++) {1000                const nextChild = (c2[i] = optimized1001                    ? cloneIfMounted(c2[i])1002                    : normalizeVNode(c2[i]));1003                if (nextChild.key != null) {1004                    if ( keyToNewIndexMap.has(nextChild.key)) {1005                        warn(`Duplicate keys found during update:`, JSON.stringify(nextChild.key), `Make sure keys are unique.`);1006                    }1007                    keyToNewIndexMap.set(nextChild.key, i);1008                }1009            }1010            // 5.2 loop through old children left to be patched and try to patch1011            // matching nodes & remove nodes that are no longer present1012            let j;1013            let patched = 0;1014            const toBePatched = e2 - s2 + 1;1015            let moved = false;1016            // used to track whether any node has moved1017            let maxNewIndexSoFar = 0;1018            // works as Map<newIndex, oldIndex>1019            // Note that oldIndex is offset by +11020            // and oldIndex = 0 is a special value indicating the new node has1021            // no corresponding old node.1022            // used for determining longest stable subsequence1023            const newIndexToOldIndexMap = new Array(toBePatched);1024            for (i = 0; i < toBePatched; i++)1025                newIndexToOldIndexMap[i] = 0;1026            for (i = s1; i <= e1; i++) {1027                const prevChild = c1[i];1028                if (patched >= toBePatched) {1029                    // all new children have been patched so this can only be a removal1030                    unmount(prevChild, parentComponent, parentSuspense, true);1031                    continue;1032                }1033                let newIndex;1034                if (prevChild.key != null) {1035                    newIndex = keyToNewIndexMap.get(prevChild.key);1036                }1037                else {1038                    // key-less node, try to locate a key-less node of the same type1039                    for (j = s2; j <= e2; j++) {1040                        if (newIndexToOldIndexMap[j - s2] === 0 &&1041                            isSameVNodeType(prevChild, c2[j])) {1042                            newIndex = j;1043                            break;1044                        }1045                    }1046                }1047                if (newIndex === undefined) {1048                    unmount(prevChild, parentComponent, parentSuspense, true);1049                }1050                else {1051                    newIndexToOldIndexMap[newIndex - s2] = i + 1;1052                    if (newIndex >= maxNewIndexSoFar) {1053                        maxNewIndexSoFar = newIndex;1054                    }1055                    else {1056                        moved = true;1057                    }1058                    patch(prevChild, c2[newIndex], container, null, parentComponent, parentSuspense, isSVG, optimized);1059                    patched++;1060                }1061            }1062            // 5.3 move and mount1063            // generate longest stable subsequence only when nodes have moved1064            const increasingNewIndexSequence = moved1065                ? getSequence(newIndexToOldIndexMap)1066                : EMPTY_ARR;1067            j = increasingNewIndexSequence.length - 1;1068            // looping backwards so that we can use last patched node as anchor1069            for (i = toBePatched - 1; i >= 0; i--) {1070                const nextIndex = s2 + i;1071                const nextChild = c2[nextIndex];1072                const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : parentAnchor;1073                if (newIndexToOldIndexMap[i] === 0) {1074                    // mount new1075                    patch(null, nextChild, container, anchor, parentComponent, parentSuspense, isSVG);1076                }1077                else if (moved) {1078                    // move if:1079                    // There is no stable subsequence (e.g. a reverse)1080                    // OR current node is not among the stable sequence1081                    if (j < 0 || i !== increasingNewIndexSequence[j]) {1082                        move(nextChild, container, anchor, 2 /* REORDER */);1083                    }1084                    else {1085                        j--;1086                    }1087                }1088            }1089        }1090    };1091    const move = (vnode, container, anchor, moveType, parentSuspense = null) => {1092        const { el, type, transition, children, shapeFlag } = vnode;1093        if (shapeFlag & 6 /* COMPONENT */) {1094            move(vnode.component.subTree, container, anchor, moveType);1095            return;1096        }1097        if ( shapeFlag & 128 /* SUSPENSE */) {1098            vnode.suspense.move(container, anchor, moveType);1099            return;1100        }1101        if (shapeFlag & 64 /* TELEPORT */) {1102            type.move(vnode, container, anchor, internals);1103            return;1104        }1105        if (type === Fragment) {1106            hostInsert(el, container, anchor);1107            for (let i = 0; i < children.length; i++) {1108                move(children[i], container, anchor, moveType);1109            }1110            hostInsert(vnode.anchor, container, anchor);1111            return;1112        }1113        // static node move can only happen when force updating HMR1114        if ( type === Static) {1115            moveStaticNode(vnode, container, anchor);1116            return;1117        }1118        // single nodes1119        const needTransition = moveType !== 2 /* REORDER */ &&1120            shapeFlag & 1 /* ELEMENT */ &&1121            transition;1122        if (needTransition) {1123            if (moveType === 0 /* ENTER */) {1124                transition.beforeEnter(el);1125                hostInsert(el, container, anchor);1126                queuePostRenderEffect(() => transition.enter(el), parentSuspense);1127            }1128            else {1129                const { leave, delayLeave, afterLeave } = transition;1130                const remove = () => hostInsert(el, container, anchor);1131                const performLeave = () => {1132                    leave(el, () => {1133                        remove();1134                        afterLeave && afterLeave();1135                    });1136                };1137                if (delayLeave) {1138                    delayLeave(el, remove, performLeave);1139                }1140                else {1141                    performLeave();1142                }1143            }1144        }1145        else {1146            hostInsert(el, container, anchor);1147        }1148    };1149    const unmount = (vnode, parentComponent, parentSuspense, doRemove = false) => {1150        const { type, props, ref, children, dynamicChildren, shapeFlag, patchFlag, dirs } = vnode;1151        // unset ref1152        if (ref != null && parentComponent) {1153            setRef(ref, null, parentComponent, parentSuspense, null);1154        }1155        if (shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {1156            parentComponent.ctx.deactivate(vnode);1157            return;1158        }1159        const shouldInvokeDirs = shapeFlag & 1 /* ELEMENT */ && dirs;1160        let vnodeHook;1161        if ((vnodeHook = props && props.onVnodeBeforeUnmount)) {1162            invokeVNodeHook(vnodeHook, parentComponent, vnode);1163        }1164        if (shapeFlag & 6 /* COMPONENT */) {1165            unmountComponent(vnode.component, parentSuspense, doRemove);1166        }1167        else {1168            if ( shapeFlag & 128 /* SUSPENSE */) {1169                vnode.suspense.unmount(parentSuspense, doRemove);1170                return;1171            }1172            if (shouldInvokeDirs) {1173                invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount');1174            }1175            if (dynamicChildren &&1176                // #1153: fast path should not be taken for non-stable (v-for) fragments1177                (type !== Fragment ||1178                    (patchFlag > 0 && patchFlag & 64 /* STABLE_FRAGMENT */))) {1179                // fast path for block nodes: only need to unmount dynamic children.1180                unmountChildren(dynamicChildren, parentComponent, parentSuspense);1181            }1182            else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {1183                unmountChildren(children, parentComponent, parentSuspense);1184            }1185            // an unmounted teleport should always remove its children1186            if (shapeFlag & 64 /* TELEPORT */) {1187                vnode.type.remove(vnode, internals);1188            }1189            if (doRemove) {1190                remove(vnode);1191            }1192        }1193        if ((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) {1194            queuePostRenderEffect(() => {1195                vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);1196                shouldInvokeDirs &&1197                    invokeDirectiveHook(vnode, null, parentComponent, 'unmounted');1198            }, parentSuspense);1199        }1200    };1201    const remove = vnode => {1202        const { type, el, anchor, transition } = vnode;1203        if (type === Fragment) {1204            removeFragment(el, anchor);1205            return;1206        }1207        if ( type === Static) {1208            removeStaticNode(vnode);1209            return;...patch.js
Source:patch.js  
...404    }405    const shouldInvokeDirs = shapeFlag & 1 /* ELEMENT */ && dirs;406    let vnodeHook;407    if ((vnodeHook = props && props.onVnodeBeforeUnmount)) {408        invokeVNodeHook(vnodeHook, parentComponent, vnode);409    }410    if (shapeFlag & 6 /* COMPONENT */) {411        unmountComponent(vnode.component, parentSuspense, doRemove);412    }413    else {414        if ( shapeFlag & 128 /* SUSPENSE */) {415            vnode.suspense.unmount(parentSuspense, doRemove);416            return;417        }418        if (shouldInvokeDirs) {419            invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount');420        }421        if (dynamicChildren &&422            // #1153: fast path should not be taken for non-stable (v-for) fragments423            (type !== Fragment ||424                (patchFlag > 0 && patchFlag & 64 /* STABLE_FRAGMENT */))) {425            // fast path for block nodes: only need to unmount dynamic children.426            unmountChildren(dynamicChildren, parentComponent, parentSuspense);427        }428        else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {429            unmountChildren(children, parentComponent, parentSuspense);430        }431        // an unmounted teleport should always remove its children432        if (shapeFlag & 64 /* TELEPORT */) {433            vnode.type.remove(vnode, internals);434        }435        if (doRemove) {436            remove(vnode);437        }438    }439    if ((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) {440        queuePostRenderEffect(() => {441            vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);442            shouldInvokeDirs &&443                invokeDirectiveHook(vnode, null, parentComponent, 'unmounted');444        }, parentSuspense);445    }446};447const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, optimized = false) => {448    // patching & not same type, unmount old tree449    if (n1 && !isSameVNodeType(n1, n2)) {450        anchor = getNextHostNode(n1);451        unmount(n1, parentComponent, parentSuspense, true);452        n1 = null;453    }454    if (n2.patchFlag === -2 /* BAIL */) {455        optimized = false;456        n2.dynamicChildren = null;457    }458    const { type, ref, shapeFlag } = n2;459    switch (type) {460        case Text:461            processText(n1, n2, container, anchor);462            break;463        case Comment:464            processCommentNode(n1, n2, container, anchor);465            break;466        case Static:467            if (n1 == null) {468                mountStaticNode(n2, container, anchor, isSVG);469            }470            else {471                patchStaticNode(n1, n2, container, isSVG);472            }473            break;474        case Fragment:475            processFragment(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);476            break;477        default:478            if (shapeFlag & 1 /* ELEMENT */) {479                processElement(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);480            }481            else if (shapeFlag & 6 /* COMPONENT */) {482                processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);483            }484            else if (shapeFlag & 64 /* TELEPORT */) {485                type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);486            }487            else if ( shapeFlag & 128 /* SUSPENSE */) {488                type.process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized, internals);489            }490            else {491                warn('Invalid VNode type:', type, `(${typeof type})`);492            }493    }494    // set ref495    if (ref != null && parentComponent) {496        setRef(ref, n1 && n1.ref, parentComponent, parentSuspense, n2);497    }498};499const processText = (n1, n2, container, anchor) => {500    if (n1 == null) {501        hostInsert((n2.el = hostCreateText(n2.children)), container, anchor);502    }503    else {504        const el = (n2.el = n1.el);505        if (n2.children !== n1.children) {506            hostSetText(el, n2.children);507        }508    }509};510const processCommentNode = (n1, n2, container, anchor) => {511    if (n1 == null) {512        hostInsert((n2.el = hostCreateComment(n2.children || '')), container, anchor);513    }514    else {515        // there's no support for dynamic comments516        n2.el = n1.el;517    }518};519const processElement = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {520    isSVG = isSVG || n2.type === 'svg';521    if (n1 == null) {522        mountElement(n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized);523    }524    else {525        patchElement(n1, n2, parentComponent, parentSuspense, isSVG, optimized);526    }527};528    const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {529        let el;530        let vnodeHook;531        const { type, props, shapeFlag, transition, scopeId, patchFlag, dirs } = vnode;532        {533            el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is);534            // mount children first, since some props may rely on child content535            // being already rendered, e.g. `<select value>`536            if (shapeFlag & 8 /* TEXT_CHILDREN */) {537                hostSetElementText(el, vnode.children);538            }539            else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {540                mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', optimized || !!vnode.dynamicChildren);541            }542            if (dirs) {543                invokeDirectiveHook(vnode, null, parentComponent, 'created');544            }545            // props546            if (props) {547                for (const key in props) {548                    if (!isReservedProp(key)) {549                        hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);550                    }551                }552                if ((vnodeHook = props.onVnodeBeforeMount)) {553                    invokeVNodeHook(vnodeHook, parentComponent, vnode);554                }555            }556            // scopeId557            setScopeId(el, scopeId, vnode, parentComponent);558        }559        {560            Object.defineProperty(el, '__vnode', {561                value: vnode,562                enumerable: false563            });564            Object.defineProperty(el, '__vueParentComponent', {565                value: parentComponent,566                enumerable: false567            });568        }569        if (dirs) {570            invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount');571        }572        // #1583 For inside suspense + suspense not resolved case, enter hook should call when suspense resolved573        // #1689 For inside suspense + suspense resolved case, just call it574        const needCallTransitionHooks = (!parentSuspense || (parentSuspense && !parentSuspense.pendingBranch)) &&575            transition &&576            !transition.persisted;577        if (needCallTransitionHooks) {578            transition.beforeEnter(el);579        }580        hostInsert(el, container, anchor);581        if ((vnodeHook = props && props.onVnodeMounted) ||582            needCallTransitionHooks ||583            dirs) {584            queuePostRenderEffect(() => {585                vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);586                needCallTransitionHooks && transition.enter(el);587                dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted');588            }, parentSuspense);589        }590    };591        function invokeDirectiveHook(vnode, prevVNode, instance, name) {592            const bindings = vnode.dirs;593            const oldBindings = prevVNode && prevVNode.dirs;594            for (let i = 0; i < bindings.length; i++) {595                const binding = bindings[i];596                if (oldBindings) {597                    binding.oldValue = oldBindings[i].value;598                }599                const hook = binding.dir[name];600                if (hook) {601                    callWithAsyncErrorHandling(hook, instance, 8 /* DIRECTIVE_HOOK */, [602                        vnode.el,603                        binding,604                        vnode,605                        prevVNode606                    ]);607                }608            }609        }610        function callWithAsyncErrorHandling(fn, instance, type, args) {611            if (isFunction(fn)) {612                const res = callWithErrorHandling(fn, instance, type, args);613                if (res && isPromise(res)) {614                    res.catch(err => {615                        handleError(err, instance, type);616                    });617                }618                return res;619            }620            const values = [];621            for (let i = 0; i < fn.length; i++) {622                values.push(callWithAsyncErrorHandling(fn[i], instance, type, args));623            }624            return values;625        }626        const mountChildren = (children, container, anchor, parentComponent, parentSuspense, isSVG, optimized, start = 0) => {627            for (let i = start; i < children.length; i++) {628                const child = (children[i] = optimized629                    ? cloneIfMounted(children[i])630                    : normalizeVNode(children[i]));631                patch(null, child, container, anchor, parentComponent, parentSuspense, isSVG, optimized);632            }633        };634        const setScopeId = (el, scopeId, vnode, parentComponent) => {635            if (scopeId) {636                hostSetScopeId(el, scopeId);637            }638            if (parentComponent) {639                const treeOwnerId = parentComponent.type.__scopeId;640                // vnode's own scopeId and the current patched component's scopeId is641                // different - this is a slot content node.642                if (treeOwnerId && treeOwnerId !== scopeId) {643                    hostSetScopeId(el, treeOwnerId + '-s');644                }645                let subTree = parentComponent.subTree;646                if ( subTree.type === Fragment) {647                    subTree =648                        filterSingleRoot(subTree.children) || subTree;649                }650                if (vnode === subTree) {651                    setScopeId(el, parentComponent.vnode.scopeId, parentComponent.vnode, parentComponent.parent);652                }653            }654        };655        const queuePostRenderEffect =  queueEffectWithSuspense656        function queueEffectWithSuspense(fn, suspense) {657            if (suspense && suspense.pendingBranch) {658                if (isArray(fn)) {659                    suspense.effects.push(...fn);660                }661                else {662                    suspense.effects.push(fn);663                }664            }665            else {666                queuePostFlushCb(fn);667            }668        }669        function queuePostFlushCb(cb) {670            queueCb(cb, activePostFlushCbs, pendingPostFlushCbs, postFlushIndex);671        }672        function queueCb(cb, activeQueue, pendingQueue, index) {673            if (!isArray(cb)) {674                if (!activeQueue ||675                    !activeQueue.includes(cb, cb.allowRecurse ? index + 1 : index)) {676                    pendingQueue.push(cb);677                }678            }679            else {680                // if cb is an array, it is a component lifecycle hook which can only be681                // triggered by a job, which is already deduped in the main queue, so682                // we can skip duplicate check here to improve perf683                pendingQueue.push(...cb);684            }685            queueFlush();686        }687                function queueJob(job) {688                    // the dedupe search uses the startIndex argument of Array.includes()689                    // by default the search index includes the current job that is being run690                    // so it cannot recursively trigger itself again.691                    // if the job is a watch() callback, the search will start with a +1 index to692                    // allow it recursively trigger itself - it is the user's responsibility to693                    // ensure it doesn't end up in an infinite loop.694                    if ((!queue.length ||695                        !queue.includes(job, isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex)) &&696                        job !== currentPreFlushParentJob) {697                        queue.push(job);698                        queueFlush();699                    }700                }701                function queueFlush() {702                    if (!isFlushing && !isFlushPending) {703                        isFlushPending = true;704                        currentFlushPromise = resolvedPromise.then(flushJobs);705                    }706                }707                function flushJobs(seen) {708                    isFlushPending = false;709                    isFlushing = true;710                    {711                        seen = seen || new Map();712                    }713                    flushPreFlushCbs(seen);714                    // Sort queue before flush.715                    // This ensures that:716                    // 1. Components are updated from parent to child. (because parent is always717                    //    created before the child so its render effect will have smaller718                    //    priority number)719                    // 2. If a component is unmounted during a parent component's update,720                    //    its update can be skipped.721                    // Jobs can never be null before flush starts, since they are only invalidated722                    // during execution of another flushed job.723                    queue.sort((a, b) => getId(a) - getId(b));724                    try {725                        for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {726                            const job = queue[flushIndex];727                            if (job) {728                                if (true) {729                                    checkRecursiveUpdates(seen, job);730                                }731                                callWithErrorHandling(job, null, 14 /* SCHEDULER */);732                            }733                        }734                    }735                    finally {736                        flushIndex = 0;737                        queue.length = 0;738                        flushPostFlushCbs(seen);739                        isFlushing = false;740                        currentFlushPromise = null;741                        // some postFlushCb queued jobs!742                        // keep flushing until it drains.743                        if (queue.length || pendingPostFlushCbs.length) {744                            flushJobs(seen);745                        }746                    }747                }748                function checkRecursiveUpdates(seen, fn) {749                    if (!seen.has(fn)) {750                        seen.set(fn, 1);751                    }752                    else {753                        const count = seen.get(fn);754                        if (count > RECURSION_LIMIT) {755                            throw new Error(`Maximum recursive updates exceeded. ` +756                                `This means you have a reactive effect that is mutating its own ` +757                                `dependencies and thus recursively triggering itself. Possible sources ` +758                                `include component template, render function, updated hook or ` +759                                `watcher source function.`);760                        }761                        else {762                            seen.set(fn, count + 1);763                        }764                    }765                }766        function invokeVNodeHook(hook, instance, vnode, prevVNode = null) {767            callWithAsyncErrorHandling(hook, instance, 7 /* VNODE_HOOK */, [768                vnode,769                prevVNode770            ]);771        }772        function invokeDirectiveHook(vnode, prevVNode, instance, name) {773            const bindings = vnode.dirs;774            const oldBindings = prevVNode && prevVNode.dirs;775            for (let i = 0; i < bindings.length; i++) {776                const binding = bindings[i];777                if (oldBindings) {778                    binding.oldValue = oldBindings[i].value;779                }780                const hook = binding.dir[name];781                if (hook) {782                    callWithAsyncErrorHandling(hook, instance, 8 /* DIRECTIVE_HOOK */, [783                        vnode.el,784                        binding,785                        vnode,786                        prevVNode787                    ]);788                }789            }790        }791        const patchProp = (el, key, prevValue, nextValue, isSVG = false, prevChildren, parentComponent, parentSuspense, unmountChildren) => {792            switch (key) {793                // special794                case 'class':795                    patchClass(el, nextValue, isSVG);796                    break;797                case 'style':798                    patchStyle(el, prevValue, nextValue);799                    break;800                default:801                    if (isOn(key)) {802                        // ignore v-model listeners803                        if (!isModelListener(key)) {804                            patchEvent(el, key, prevValue, nextValue, parentComponent);805                        }806                    }807                    else if (shouldSetAsProp(el, key, nextValue, isSVG)) {808                        patchDOMProp(el, key, nextValue, prevChildren, parentComponent, parentSuspense, unmountChildren);809                    }810                    else {811                        // special case for <input v-model type="checkbox"> with812                        // :true-value & :false-value813                        // store value as dom properties since non-string values will be814                        // stringified.815                        if (key === 'true-value') {816                            el._trueValue = nextValue;817                        }818                        else if (key === 'false-value') {819                            el._falseValue = nextValue;820                        }821                        patchAttr(el, key, nextValue, isSVG);822                    }823                    break;824            }825        };826            // compiler should normalize class + :class bindings on the same element827            // into a single binding ['staticClass', dynamic]828            function patchClass(el, value, isSVG) {829                if (value == null) {830                    value = '';831                }832                if (isSVG) {833                    el.setAttribute('class', value);834                }835                else {836                    // directly setting className should be faster than setAttribute in theory837                    // if this is an element during a transition, take the temporary transition838                    // classes into account.839                    const transitionClasses = el._vtc;840                    if (transitionClasses) {841                        value = (value842                            ? [value, ...transitionClasses]843                            : [...transitionClasses]).join(' ');844                    }845                    el.className = value;846                }847            }848            function patchEvent(el, rawName, prevValue, nextValue, instance = null) {849                // vei = vue event invokers850                const invokers = el._vei || (el._vei = {});851                const existingInvoker = invokers[rawName];852                if (nextValue && existingInvoker) {853                    // patch854                    existingInvoker.value = nextValue;855                }856                else {857                    const [name, options] = parseName(rawName);858                    if (nextValue) {859                        // add860                        const invoker = (invokers[rawName] = createInvoker(nextValue, instance));861                        addEventListener(el, name, invoker, options);862                    }863                    else if (existingInvoker) {864                        // remove865                        removeEventListener(el, name, existingInvoker, options);866                        invokers[rawName] = undefined;867                    }868                }869            }870            function createInvoker(initialValue, instance) {871                const invoker = (e) => {872                    // async edge case #6566: inner click event triggers patch, event handler873                    // attached to outer element during patch, and triggered again. This874                    // happens because browsers fire microtask ticks between event propagation.875                    // the solution is simple: we save the timestamp when a handler is attached,876                    // and the handler would only fire if the event passed to it was fired877                    // AFTER it was attached.878                    const timeStamp = e.timeStamp || _getNow();879                    if (timeStamp >= invoker.attached - 1) {880                        callWithAsyncErrorHandling(patchStopImmediatePropagation(e, invoker.value), instance, 5 /* NATIVE_EVENT_HANDLER */, [e]);881                    }882                };883                invoker.value = initialValue;884                invoker.attached = getNow();885                return invoker;886            }887            function patchStopImmediatePropagation(e, value) {888                if (isArray(value)) {889                    const originalStop = e.stopImmediatePropagation;890                    e.stopImmediatePropagation = () => {891                        originalStop.call(e);892                        e._stopped = true;893                    };894                    return value.map(fn => (e) => !e._stopped && fn(e));895                }896                else {897                    return value;898                }899            }900            function shouldSetAsProp(el, key, value, isSVG) {901                if (isSVG) {902                    // most keys must be set as attribute on svg elements to work903                    // ...except innerHTML904                    if (key === 'innerHTML') {905                        return true;906                    }907                    // or native onclick with function values908                    if (key in el && nativeOnRE.test(key) && isFunction(value)) {909                        return true;910                    }911                    return false;912                }913                // spellcheck and draggable are numerated attrs, however their914                // corresponding DOM properties are actually booleans - this leads to915                // setting it with a string "false" value leading it to be coerced to916                // `true`, so we need to always treat them as attributes.917                // Note that `contentEditable` doesn't have this problem: its DOM918                // property is also enumerated string values.919                if (key === 'spellcheck' || key === 'draggable') {920                    return false;921                }922                // #1787 form as an attribute must be a string, while it accepts an Element as923                // a prop924                if (key === 'form' && typeof value === 'string') {925                    return false;926                }927                // #1526 <input list> must be set as attribute928                if (key === 'list' && el.tagName === 'INPUT') {929                    return false;930                }931                // native onclick with string value, must be set as attribute932                if (nativeOnRE.test(key) && isString(value)) {933                    return false;934                }935                return key in el;936            }937            function patchDOMProp(el, key, value, 938                // the following args are passed only due to potential innerHTML/textContent939                // overriding existing VNodes, in which case the old tree must be properly940                // unmounted.941                prevChildren, parentComponent, parentSuspense, unmountChildren) {942                    if (key === 'innerHTML' || key === 'textContent') {943                        if (prevChildren) {944                            unmountChildren(prevChildren, parentComponent, parentSuspense);945                        }946                        el[key] = value == null ? '' : value;947                        return;948                    }949                    if (key === 'value' && el.tagName !== 'PROGRESS') {950                        // store value as _value as well since951                        // non-string values will be stringified.952                        el._value = value;953                        const newValue = value == null ? '' : value;954                        if (el.value !== newValue) {955                            el.value = newValue;956                        }957                        return;958                    }959                    if (value === '' && typeof el[key] === 'boolean') {960                        // e.g. <select multiple> compiles to { multiple: '' }961                        el[key] = true;962                    }963                    else if (value == null && typeof el[key] === 'string') {964                        // e.g. <div :id="null">965                        el[key] = '';966                        el.removeAttribute(key);967                    }968                    else {969                        // some properties perform value validation and throw970                        try {971                            el[key] = value;972                        }973                        catch (e) {974                            {975                                warn(`Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` +976                                    `value ${value} is invalid.`, e);977                            }978                        }979                    }980                }981                function patchAttr(el, key, value, isSVG) {982                    if (isSVG && key.startsWith('xlink:')) {983                        if (value == null) {984                            el.removeAttributeNS(xlinkNS, key.slice(6, key.length));985                        }986                        else {987                            el.setAttributeNS(xlinkNS, key, value);988                        }989                    }990                    else {991                        // note we are only checking boolean attributes that don't have a992                        // corresponding dom prop of the same name here.993                        const isBoolean = isSpecialBooleanAttr(key);994                        if (value == null || (isBoolean && value === false)) {995                            el.removeAttribute(key);996                        }997                        else {998                            el.setAttribute(key, isBoolean ? '' : value);999                        }1000                    }1001                }1002                const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;1003            const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs);1004    /*1005    * å¯ä»¥æ ¹æ®shapeFlgæéæ©æ´æ°ï¼ç²åº¦æ´ç»1006    */1007    const patchElement = (n1, n2, parentComponent, parentSuspense, isSVG, optimized) => {1008        const el = (n2.el = n1.el);1009        let { patchFlag, dynamicChildren, dirs } = n2;1010        // #1426 take the old vnode's patch flag into account since user may clone a1011        // compiler-generated vnode, which de-opts to FULL_PROPS1012        patchFlag |= n1.patchFlag & 16 /* FULL_PROPS */;1013        const oldProps = n1.props || EMPTY_OBJ;1014        const newProps = n2.props || EMPTY_OBJ;1015        let vnodeHook;1016        if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {1017            invokeVNodeHook(vnodeHook, parentComponent, n2, n1);1018        }1019        if (dirs) {1020            invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate');1021        }1022        if ( isHmrUpdating) {1023            // HMR updated, force full diff1024            patchFlag = 0;1025            optimized = false;1026            dynamicChildren = null;1027        }1028        if (patchFlag > 0) {1029            // the presence of a patchFlag means this element's render code was1030            // generated by the compiler and can take the fast path.1031            // in this path old node and new node are guaranteed to have the same shape1032            // (i.e. at the exact same position in the source template)1033            if (patchFlag & 16 /* FULL_PROPS */) {1034                // element props contain dynamic keys, full diff needed1035                patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1036            }1037            else {1038                // class1039                // this flag is matched when the element has dynamic class bindings.1040                if (patchFlag & 2 /* CLASS */) {1041                    if (oldProps.class !== newProps.class) {1042                        hostPatchProp(el, 'class', null, newProps.class, isSVG);1043                    }1044                }1045                // style1046                // this flag is matched when the element has dynamic style bindings1047                if (patchFlag & 4 /* STYLE */) {1048                    hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG);1049                }1050                // props1051                // This flag is matched when the element has dynamic prop/attr bindings1052                // other than class and style. The keys of dynamic prop/attrs are saved for1053                // faster iteration.1054                // Note dynamic keys like :[foo]="bar" will cause this optimization to1055                // bail out and go through a full diff because we need to unset the old key1056                if (patchFlag & 8 /* PROPS */) {1057                    // if the flag is present then dynamicProps must be non-null1058                    const propsToUpdate = n2.dynamicProps;1059                    for (let i = 0; i < propsToUpdate.length; i++) {1060                        const key = propsToUpdate[i];1061                        const prev = oldProps[key];1062                        const next = newProps[key];1063                        if (next !== prev ||1064                            (hostForcePatchProp && hostForcePatchProp(el, key))) {1065                            hostPatchProp(el, key, prev, next, isSVG, n1.children, parentComponent, parentSuspense, unmountChildren);1066                        }1067                    }1068                }1069            }1070            // text1071            // This flag is matched when the element has only dynamic text children.1072            if (patchFlag & 1 /* TEXT */) {1073                if (n1.children !== n2.children) {1074                    hostSetElementText(el, n2.children);1075                }1076            }1077        }1078        else if (!optimized && dynamicChildren == null) {1079            // unoptimized, full diff1080            patchProps(el, n2, oldProps, newProps, parentComponent, parentSuspense, isSVG);1081        }1082        const areChildrenSVG = isSVG && n2.type !== 'foreignObject';1083        if (dynamicChildren) {1084            patchBlockChildren(n1.dynamicChildren, dynamicChildren, el, parentComponent, parentSuspense, areChildrenSVG);1085            if ( parentComponent && parentComponent.type.__hmrId) {1086                traverseStaticChildren(n1, n2);1087            }1088        }1089        else if (!optimized) {1090            // full diff1091            patchChildren(n1, n2, el, null, parentComponent, parentSuspense, areChildrenSVG);1092        }1093        if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {1094            queuePostRenderEffect(() => {1095                vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1);1096                dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated');1097            }, parentSuspense);1098        }1099    };1100            const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {1101                if (oldProps !== newProps) {1102                    for (const key in newProps) {1103                        if (isReservedProp(key))1104                            continue;1105                        const next = newProps[key];1106                        const prev = oldProps[key];1107                        if (next !== prev ||1108                            (hostForcePatchProp && hostForcePatchProp(el, key))) {1109                            hostPatchProp(el, key, prev, next, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);...renderer.js
Source:renderer.js  
...288      if ('value' in props) {289        hostPatchProp(el, 'value', null, props.value)290      }291      if ((vnodeHook = props.onVnodeBeforeMount)) {292        invokeVNodeHook(vnodeHook, parentComponent, vnode)293      }294    }295    setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent)296    if (dirs) {297      // console.log('æä»¤ï¼beforeMount')298      invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount')299    }300    const needCallTransitionHooks =301      (!parentSuspense || (parentSuspense && !parentSuspense.pendingBranch)) &&302      transition &&303      !transition.persisted304    if (needCallTransitionHooks) {305      transition.beforeEnter(el)306    }307    // æè½½å
ç´ 308    hostInsert(el, container, anchor)309    if (310      (vnodeHook = props && props.onVnodeMounted) ||311      needCallTransitionHooks ||312      dirs313    ) {314      queuePostRenderEffect(() => {315        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)316        needCallTransitionHooks && transition.enter(el)317        dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted')318      }, parentSuspense)319    }320  }321  const setScopeId = (el, vnode, scopeId, slotScopeIds, parentComponent) => {322    if (scopeId) {323      hostSetScopeId(el, scopeId)324    }325    if (slotScopeIds) {326      for (let i = 0; i < slotScopeIds.length; i++) {327        hostSetScopeId(el, slotScopeIds[i])328      }329    }330    if (parentComponent) {331      let subTree = parentComponent.subTree332      if (vnode === subTree) {333        const parentVNode = parentComponent.vnode334        setScopeId(335          el,336          parentVNode,337          parentVNode.scopeId,338          parentVNode.slotScopeIds,339          parentComponent.parent340        )341      }342    }343  }344  const mountChildren = (345    children,346    container,347    anchor,348    parentComponent,349    parentSuspense,350    isSVG,351    slotScopeIds,352    start = 0353  ) => {354    for (let i = start; i < children.length; i++) {355      const child = (children[i] = normalizeVNode(children[i]))356      patch(357        null,358        child,359        container,360        anchor,361        parentComponent,362        parentSuspense,363        isSVG,364        slotScopeIds365      )366    }367  }368  const patchElement = (369    n1,370    n2,371    parentComponent,372    parentSuspense,373    isSVG,374    slotScopeIds375  ) => {376    const el = (n2.el = n1.el)377    let { patchFlag, dynamicChildren, dirs } = n2378    patchFlag |= n1.patchFlag & 16379    const oldProps = n1.props || EMPTY_OBJ380    const newProps = n2.props || EMPTY_OBJ381    let vnodeHook382    parentComponent && toggleRecurse(parentComponent, false)383    if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {384      invokeVNodeHook(vnodeHook, parentComponent, n2, n1)385    }386    if (dirs) {387      // console.log('æä»¤ï¼beforeUpdate')388      invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')389    }390    parentComponent && toggleRecurse(parentComponent, true)391    const areChildrenSVG = isSVG && n2.type !== 'foreignObject'392    if (dynamicChildren) {393      patchBlockChildren(394        n1.dynamicChildren,395        dynamicChildren,396        el,397        parentComponent,398        parentSuspense,399        areChildrenSVG,400        slotScopeIds401      )402    } else {403      patchChildren(404        n1,405        n2,406        el,407        null,408        parentComponent,409        parentSuspense,410        areChildrenSVG,411        slotScopeIds,412        false413      )414    }415    if (patchFlag > 0) {416      if (patchFlag & 16) {417        patchProps(418          el,419          n2,420          oldProps,421          newProps,422          parentComponent,423          parentSuspense,424          isSVG425        )426      } else {427        if (patchFlag & 2) {428          if (oldProps.class !== newProps.class) {429            hostPatchProp(el, 'class', null, newProps.class, isSVG)430          }431        }432        if (patchFlag & 4) {433          hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG)434        }435        if (patchFlag & 8) {436          const propsToUpdate = n2.dynamicProps437          for (let i = 0; i < propsToUpdate.length; i++) {438            const key = propsToUpdate[i]439            const prev = oldProps[key]440            const next = newProps[key]441            if (next !== prev || key === 'value') {442              hostPatchProp(443                el,444                key,445                prev,446                next,447                isSVG,448                n1.children,449                parentComponent,450                parentSuspense,451                unmountChildren452              )453            }454          }455        }456      }457      if (patchFlag & 1) {458        if (n1.children !== n2.children) {459          hostSetElementText(el, n2.children)460        }461      }462    } else if (dynamicChildren == null) {463      patchProps(464        el,465        n2,466        oldProps,467        newProps,468        parentComponent,469        parentSuspense,470        isSVG471      )472    }473    if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {474      queuePostRenderEffect(() => {475        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1)476        dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated')477      }, parentSuspense)478    }479  }480  const patchBlockChildren = (481    oldChildren,482    newChildren,483    fallbackContainer,484    parentComponent,485    parentSuspense,486    isSVG,487    slotScopeIds488  ) => {489    for (let i = 0; i < newChildren.length; i++) {490      const oldVNode = oldChildren[i]491      const newVNode = newChildren[i]492      const container =493        oldVNode.el &&494        (oldVNode.type === Fragment ||495          !isSameVNodeType(oldVNode, newVNode) ||496          oldVNode.shapeFlag & (6 | 64))497          ? hostParentNode(oldVNode.el)498          : fallbackContainer499      patch(500        oldVNode,501        newVNode,502        container,503        null,504        parentComponent,505        parentSuspense,506        isSVG,507        slotScopeIds,508        true509      )510    }511  }512  const patchProps = (513    el,514    vnode,515    oldProps,516    newProps,517    parentComponent,518    parentSuspense,519    isSVG520  ) => {521    if (oldProps !== newProps) {522      for (const key in newProps) {523        if (isReservedProp(key)) continue524        const next = newProps[key]525        const prev = oldProps[key]526        if (next !== prev && key !== 'value') {527          hostPatchProp(528            el,529            key,530            prev,531            next,532            isSVG,533            vnode.children,534            parentComponent,535            parentSuspense,536            unmountChildren537          )538        }539      }540      if (oldProps !== EMPTY_OBJ) {541        for (const key in oldProps) {542          if (!isReservedProp(key) && !(key in newProps)) {543            hostPatchProp(544              el,545              key,546              oldProps[key],547              null,548              isSVG,549              vnode.children,550              parentComponent,551              parentSuspense,552              unmountChildren553            )554          }555        }556      }557      if ('value' in newProps) {558        hostPatchProp(el, 'value', oldProps.value, newProps.value)559      }560    }561  }562  const processFragment = (563    n1,564    n2,565    container,566    anchor,567    parentComponent,568    parentSuspense,569    isSVG,570    slotScopeIds571  ) => {572    const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''))573    const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''))574    let { patchFlag, dynamicChildren, slotScopeIds: fragmentSlotScopeIds } = n2575    if (fragmentSlotScopeIds) {576      slotScopeIds = slotScopeIds577        ? slotScopeIds.concat(fragmentSlotScopeIds)578        : fragmentSlotScopeIds579    }580    if (n1 == null) {581      hostInsert(fragmentStartAnchor, container, anchor)582      hostInsert(fragmentEndAnchor, container, anchor)583      mountChildren(584        n2.children,585        container,586        fragmentEndAnchor,587        parentComponent,588        parentSuspense,589        isSVG,590        slotScopeIds591      )592    } else {593      if (594        patchFlag > 0 &&595        patchFlag & 64 &&596        dynamicChildren &&597        n1.dynamicChildren598      ) {599        patchBlockChildren(600          n1.dynamicChildren,601          dynamicChildren,602          container,603          parentComponent,604          parentSuspense,605          isSVG,606          slotScopeIds607        )608        if (609          n2.key != null ||610          (parentComponent && n2 === parentComponent.subTree)611        ) {612          traverseStaticChildren(n1, n2, true)613        }614      } else {615        patchChildren(616          n1,617          n2,618          container,619          fragmentEndAnchor,620          parentComponent,621          parentSuspense,622          isSVG,623          slotScopeIds624        )625      }626    }627  }628  const processComponent = (629    n1,630    n2,631    container,632    anchor,633    parentComponent,634    parentSuspense,635    isSVG,636    slotScopeIds637  ) => {638    n2.slotScopeIds = slotScopeIds639    if (n1 == null) {640      if (n2.shapeFlag & 512) {641        parentComponent.ctx.activate(n2, container, anchor, isSVG)642      } else {643        mountComponent(644          n2,645          container,646          anchor,647          parentComponent,648          parentSuspense,649          isSVG650        )651      }652    } else {653      updateComponent(n1, n2)654    }655  }656  const mountComponent = (657    initialVNode,658    container,659    anchor,660    parentComponent,661    parentSuspense,662    isSVG663  ) => {664    // å建ç»ä»¶å®ä¾665    const instance = (initialVNode.component = createComponentInstance(666      initialVNode,667      parentComponent,668      parentSuspense669    ))670    if (isKeepAlive(initialVNode)) {671      instance.ctx.renderer = internals672    }673    setupComponent(instance)674    if (instance.asyncDep) {675      parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect)676      if (!initialVNode.el) {677        const placeholder = (instance.subTree = createVNode(Comment))678        processCommentNode(null, placeholder, container, anchor)679      }680      return681    }682    setupRenderEffect(683      instance,684      initialVNode,685      container,686      anchor,687      parentSuspense,688      isSVG689    )690  }691  const updateComponent = (n1, n2) => {692    const instance = (n2.component = n1.component)693    if (shouldUpdateComponent(n1, n2)) {694      if (instance.asyncDep && !instance.asyncResolved) {695        updateComponentPreRender(instance, n2)696        return697      } else {698        instance.next = n2699        invalidateJob(instance.update)700        instance.update()701      }702    } else {703      n2.component = n1.component704      n2.el = n1.el705      instance.vnode = n2706    }707  }708  const setupRenderEffect = (709    instance,710    initialVNode,711    container,712    anchor,713    parentSuspense,714    isSVG715  ) => {716    // ç»ä»¶æ´æ°å½æ°717    const componentUpdateFn = () => {718      // ç»ä»¶æ¯å¦æè½½719      if (!instance.isMounted) {720        // 忬¡æè½½721        let vnodeHook722        const { props } = initialVNode723        const { bm, m, parent } = instance724        const isAsyncWrapperVNode = isAsyncWrapper(initialVNode)725        toggleRecurse(instance, false)726        if (bm) {727          invokeArrayFns(bm)728        }729        if (730          !isAsyncWrapperVNode &&731          (vnodeHook = props && props.onVnodeBeforeMount)732        ) {733          invokeVNodeHook(vnodeHook, parent, initialVNode)734        }735        toggleRecurse(instance, true)736        const subTree = (instance.subTree = renderComponentRoot(instance))737        patch(null, subTree, container, anchor, instance, parentSuspense, isSVG)738        initialVNode.el = subTree.el739        if (m) {740          queuePostRenderEffect(m, parentSuspense)741        }742        if (743          !isAsyncWrapperVNode &&744          (vnodeHook = props && props.onVnodeMounted)745        ) {746          const scopedInitialVNode = initialVNode747          queuePostRenderEffect(748            () => invokeVNodeHook(vnodeHook, parent, scopedInitialVNode),749            parentSuspense750          )751        }752        if (initialVNode.shapeFlag & 256) {753          instance.a && queuePostRenderEffect(instance.a, parentSuspense)754        }755        instance.isMounted = true756        initialVNode = container = anchor = null757      } else {758        // ç»ä»¶æ´æ°759        let { next, bu, u, parent, vnode } = instance760        let originNext = next761        let vnodeHook762        toggleRecurse(instance, false)763        if (next) {764          next.el = vnode.el765          updateComponentPreRender(instance, next)766        } else {767          next = vnode768        }769        if (bu) {770          invokeArrayFns(bu)771        }772        if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {773          invokeVNodeHook(vnodeHook, parent, next, vnode)774        }775        toggleRecurse(instance, true)776        const nextTree = renderComponentRoot(instance)777        const prevTree = instance.subTree778        instance.subTree = nextTree779        patch(780          prevTree,781          nextTree,782          hostParentNode(prevTree.el),783          getNextHostNode(prevTree),784          instance,785          parentSuspense,786          isSVG787        )788        next.el = nextTree.el789        if (originNext === null) {790          updateHOCHostEl(instance, nextTree.el)791        }792        if (u) {793          queuePostRenderEffect(u, parentSuspense)794        }795        if ((vnodeHook = next.props && next.props.onVnodeUpdated)) {796          queuePostRenderEffect(797            () => invokeVNodeHook(vnodeHook, parent, next, vnode),798            parentSuspense799          )800        }801      }802    }803    const effect = (instance.effect = new ReactiveEffect(804      componentUpdateFn,805      () => queueJob(instance.update),806      instance.scope807    ))808    const update = (instance.update = effect.run.bind(effect))809    update.id = instance.uid810    toggleRecurse(instance, true)811    update()812  }813  const updateComponentPreRender = (instance, nextVNode) => {814    nextVNode.component = instance815    const prevProps = instance.vnode.props816    instance.vnode = nextVNode817    instance.next = null818    updateProps(instance, nextVNode.props, prevProps)819    updateSlots(instance, nextVNode.children)820    pauseTracking()821    flushPreFlushCbs(undefined, instance.update)822    resetTracking()823  }824  const patchChildren = (825    n1,826    n2,827    container,828    anchor,829    parentComponent,830    parentSuspense,831    isSVG,832    slotScopeIds833  ) => {834    const c1 = n1 && n1.children835    const prevShapeFlag = n1 ? n1.shapeFlag : 0836    const c2 = n2.children837    const { patchFlag, shapeFlag } = n2838    if (patchFlag > 0) {839      if (patchFlag & 128) {840        patchKeyedChildren(841          c1,842          c2,843          container,844          anchor,845          parentComponent,846          parentSuspense,847          isSVG,848          slotScopeIds849        )850        return851      } else if (patchFlag & 256) {852        patchUnkeyedChildren(853          c1,854          c2,855          container,856          anchor,857          parentComponent,858          parentSuspense,859          isSVG,860          slotScopeIds861        )862        return863      }864    }865    if (shapeFlag & 8) {866      if (prevShapeFlag & 16) {867        unmountChildren(c1, parentComponent, parentSuspense)868      }869      if (c2 !== c1) {870        hostSetElementText(container, c2)871      }872    } else {873      if (prevShapeFlag & 16) {874        if (shapeFlag & 16) {875          patchKeyedChildren(876            c1,877            c2,878            container,879            anchor,880            parentComponent,881            parentSuspense,882            isSVG,883            slotScopeIds884          )885        } else {886          unmountChildren(c1, parentComponent, parentSuspense, true)887        }888      } else {889        if (prevShapeFlag & 8) {890          hostSetElementText(container, '')891        }892        if (shapeFlag & 16) {893          mountChildren(894            c2,895            container,896            anchor,897            parentComponent,898            parentSuspense,899            isSVG,900            slotScopeIds901          )902        }903      }904    }905  }906  const patchUnkeyedChildren = (907    c1,908    c2,909    container,910    anchor,911    parentComponent,912    parentSuspense,913    isSVG,914    slotScopeIds915  ) => {916    c1 = c1 || EMPTY_ARR917    c2 = c2 || EMPTY_ARR918    const oldLength = c1.length919    const newLength = c2.length920    const commonLength = Math.min(oldLength, newLength)921    let i922    for (i = 0; i < commonLength; i++) {923      const nextChild = (c2[i] = normalizeVNode(c2[i]))924      patch(925        c1[i],926        nextChild,927        container,928        null,929        parentComponent,930        parentSuspense,931        isSVG,932        slotScopeIds933      )934    }935    if (oldLength > newLength) {936      unmountChildren(c1, parentComponent, parentSuspense, true, commonLength)937    } else {938      mountChildren(939        c2,940        container,941        anchor,942        parentComponent,943        parentSuspense,944        isSVG,945        slotScopeIds,946        commonLength947      )948    }949  }950  const patchKeyedChildren = (951    c1,952    c2,953    container,954    parentAnchor,955    parentComponent,956    parentSuspense,957    isSVG,958    slotScopeIds959  ) => {960    let i = 0961    const l2 = c2.length962    let e1 = c1.length - 1963    let e2 = l2 - 1964    while (i <= e1 && i <= e2) {965      const n1 = c1[i]966      const n2 = (c2[i] = normalizeVNode(c2[i]))967      if (isSameVNodeType(n1, n2)) {968        patch(969          n1,970          n2,971          container,972          null,973          parentComponent,974          parentSuspense,975          isSVG,976          slotScopeIds977        )978      } else {979        break980      }981      i++982    }983    while (i <= e1 && i <= e2) {984      const n1 = c1[e1]985      const n2 = (c2[e2] = normalizeVNode(c2[e2]))986      if (isSameVNodeType(n1, n2)) {987        patch(988          n1,989          n2,990          container,991          null,992          parentComponent,993          parentSuspense,994          isSVG,995          slotScopeIds996        )997      } else {998        break999      }1000      e1--1001      e2--1002    }1003    if (i > e1) {1004      if (i <= e2) {1005        const nextPos = e2 + 11006        const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor1007        while (i <= e2) {1008          patch(1009            null,1010            (c2[i] = normalizeVNode(c2[i])),1011            container,1012            anchor,1013            parentComponent,1014            parentSuspense,1015            isSVG,1016            slotScopeIds1017          )1018          i++1019        }1020      }1021    } else if (i > e2) {1022      while (i <= e1) {1023        unmount(c1[i], parentComponent, parentSuspense, true)1024        i++1025      }1026    } else {1027      const s1 = i1028      const s2 = i1029      const keyToNewIndexMap = new Map()1030      for (i = s2; i <= e2; i++) {1031        const nextChild = (c2[i] = normalizeVNode(c2[i]))1032        if (nextChild.key != null) {1033          keyToNewIndexMap.set(nextChild.key, i)1034        }1035      }1036      let j1037      let patched = 01038      const toBePatched = e2 - s2 + 11039      let moved = false1040      let maxNewIndexSoFar = 01041      const newIndexToOldIndexMap = new Array(toBePatched)1042      for (i = 0; i < toBePatched; i++) newIndexToOldIndexMap[i] = 01043      for (i = s1; i <= e1; i++) {1044        const prevChild = c1[i]1045        if (patched >= toBePatched) {1046          unmount(prevChild, parentComponent, parentSuspense, true)1047          continue1048        }1049        let newIndex1050        if (prevChild.key != null) {1051          newIndex = keyToNewIndexMap.get(prevChild.key)1052        } else {1053          for (j = s2; j <= e2; j++) {1054            if (1055              newIndexToOldIndexMap[j - s2] === 0 &&1056              isSameVNodeType(prevChild, c2[j])1057            ) {1058              newIndex = j1059              break1060            }1061          }1062        }1063        if (newIndex === undefined) {1064          unmount(prevChild, parentComponent, parentSuspense, true)1065        } else {1066          newIndexToOldIndexMap[newIndex - s2] = i + 11067          if (newIndex >= maxNewIndexSoFar) {1068            maxNewIndexSoFar = newIndex1069          } else {1070            moved = true1071          }1072          patch(1073            prevChild,1074            c2[newIndex],1075            container,1076            null,1077            parentComponent,1078            parentSuspense,1079            isSVG,1080            slotScopeIds1081          )1082          patched++1083        }1084      }1085      const increasingNewIndexSequence = moved1086        ? getSequence(newIndexToOldIndexMap)1087        : EMPTY_ARR1088      j = increasingNewIndexSequence.length - 11089      for (i = toBePatched - 1; i >= 0; i--) {1090        const nextIndex = s2 + i1091        const nextChild = c2[nextIndex]1092        const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : parentAnchor1093        if (newIndexToOldIndexMap[i] === 0) {1094          patch(1095            null,1096            nextChild,1097            container,1098            anchor,1099            parentComponent,1100            parentSuspense,1101            isSVG,1102            slotScopeIds1103          )1104        } else if (moved) {1105          if (j < 0 || i !== increasingNewIndexSequence[j]) {1106            move(nextChild, container, anchor, 2)1107          } else {1108            j--1109          }1110        }1111      }1112    }1113  }1114  const move = (vnode, container, anchor, moveType, parentSuspense = null) => {1115    const { el, type, transition, children, shapeFlag } = vnode1116    if (shapeFlag & 6) {1117      move(vnode.component.subTree, container, anchor, moveType)1118      return1119    }1120    if (shapeFlag & 128) {1121      vnode.suspense.move(container, anchor, moveType)1122      return1123    }1124    if (shapeFlag & 64) {1125      type.move(vnode, container, anchor, internals)1126      return1127    }1128    if (type === Fragment) {1129      hostInsert(el, container, anchor)1130      for (let i = 0; i < children.length; i++) {1131        move(children[i], container, anchor, moveType)1132      }1133      hostInsert(vnode.anchor, container, anchor)1134      return1135    }1136    if (type === Static) {1137      moveStaticNode(vnode, container, anchor)1138      return1139    }1140    const needTransition = moveType !== 2 && shapeFlag & 1 && transition1141    if (needTransition) {1142      if (moveType === 0) {1143        transition.beforeEnter(el)1144        hostInsert(el, container, anchor)1145        queuePostRenderEffect(() => transition.enter(el), parentSuspense)1146      } else {1147        const { leave, delayLeave, afterLeave } = transition1148        const remove = () => hostInsert(el, container, anchor)1149        const performLeave = () => {1150          leave(el, () => {1151            remove()1152            afterLeave && afterLeave()1153          })1154        }1155        if (delayLeave) {1156          delayLeave(el, remove, performLeave)1157        } else {1158          performLeave()1159        }1160      }1161    } else {1162      hostInsert(el, container, anchor)1163    }1164  }1165  const unmount = (1166    vnode,1167    parentComponent,1168    parentSuspense,1169    doRemove = false1170  ) => {1171    const {1172      type,1173      props,1174      ref,1175      children,1176      dynamicChildren,1177      shapeFlag,1178      patchFlag,1179      dirs1180    } = vnode1181    if (ref != null) {1182      setRef(ref, null, parentSuspense, vnode, true)1183    }1184    if (shapeFlag & 256) {1185      parentComponent.ctx.deactivate(vnode)1186      return1187    }1188    const shouldInvokeDirs = shapeFlag & 1 && dirs1189    const shouldInvokeVnodeHook = !isAsyncWrapper(vnode)1190    let vnodeHook1191    if (1192      shouldInvokeVnodeHook &&1193      (vnodeHook = props && props.onVnodeBeforeUnmount)1194    ) {1195      invokeVNodeHook(vnodeHook, parentComponent, vnode)1196    }1197    if (shapeFlag & 6) {1198      unmountComponent(vnode.component, parentSuspense, doRemove)1199    } else {1200      if (shapeFlag & 128) {1201        vnode.suspense.unmount(parentSuspense, doRemove)1202        return1203      }1204      if (shouldInvokeDirs) {1205        invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')1206      }1207      if (shapeFlag & 64) {1208        vnode.type.remove(1209          vnode,1210          parentComponent,1211          parentSuspense,1212          internals,1213          doRemove1214        )1215      } else if (1216        dynamicChildren &&1217        (type !== Fragment || (patchFlag > 0 && patchFlag & 64))1218      ) {1219        unmountChildren(dynamicChildren, parentComponent, parentSuspense, false)1220      } else if (1221        (type === Fragment && patchFlag & (128 | 256)) ||1222        shapeFlag & 161223      ) {1224        unmountChildren(children, parentComponent, parentSuspense)1225      }1226      if (doRemove) {1227        remove(vnode)1228      }1229    }1230    if (1231      (shouldInvokeVnodeHook &&1232        (vnodeHook = props && props.onVnodeUnmounted)) ||1233      shouldInvokeDirs1234    ) {1235      queuePostRenderEffect(() => {1236        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)1237        shouldInvokeDirs &&1238          invokeDirectiveHook(vnode, null, parentComponent, 'unmounted')1239      }, parentSuspense)1240    }1241  }1242  const remove = vnode => {1243    const { type, el, anchor, transition } = vnode1244    if (type === Fragment) {1245      removeFragment(el, anchor)1246      return1247    }1248    if (type === Static) {1249      removeStaticNode(vnode)1250      return...Navigation.js
Source:Navigation.js  
...39    else {40        queuePostFlushCb(fn);41    }42}43function invokeVNodeHook(hook, instance, vnode, prevVNode = null) {44    callWithAsyncErrorHandling(hook, instance, 7 /* VNODE_HOOK */, [45        vnode,46        prevVNode47    ]);48}49function createDevtoolsComponentHook(hook) {50    return (component) => {51        if (!devtools)52            return;53        devtools.emit(hook, component.appContext.app, component.uid, component.parent ? component.parent.uid : undefined, component);54    };55}56const devtoolsComponentAdded = /*#__PURE__*/ createDevtoolsComponentHook("component:added" /* COMPONENT_ADDED */);57const navigation = {58    name: `navigation`,59    // Marker for special handling inside the renderer. We are not using a ===60    // check directly on KeepAlive in the renderer, because importing it directly61    // would prevent it from being tree-shaken.62    __isKeepAlive: true,63    props: {64        include: [String, RegExp, Array],65        exclude: [String, RegExp, Array],66        max: [String, Number]67    },68    setup(props, { slots }) {69        const selfRouters = reactive(Routes)70        const instance = getCurrentInstance();71        // KeepAlive communicates with the instantiated renderer via the72        // ctx where the renderer passes in its internals,73        // and the KeepAlive instance exposes activate/deactivate implementations.74        // The whole point of this is to avoid importing KeepAlive directly in the75        // renderer to facilitate tree-shaking.76        const sharedContext = instance.ctx;77        // if the internal renderer is not registered, it indicates that this is server-side rendering,78        // for KeepAlive, we just need to render its children79        if (!sharedContext.renderer) {80            return slots.default;81        }82        const cache = new Map();83        const keys = new Set();84        let current = null;85        {86            instance.__v_cache = cache;87        }88        const parentSuspense = instance.suspense;89        const { renderer: { p: patch, m: move, um: _unmount, o: { createElement } } } = sharedContext;90        const storageContainer = createElement('div');91        sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {92            const instance = vnode.component;93            move(vnode, container, anchor, 0 /* ENTER */, parentSuspense);94            // in case props have changed95            patch(instance.vnode, vnode, container, anchor, instance, parentSuspense, isSVG, vnode.slotScopeIds, optimized);96            queuePostRenderEffect(() => {97                instance.isDeactivated = false;98                if (instance.a) {99                    invokeArrayFns(instance.a);100                }101                const vnodeHook = vnode.props && vnode.props.onVnodeMounted;102                if (vnodeHook) {103                    invokeVNodeHook(vnodeHook, instance.parent, vnode);104                }105            }, parentSuspense);106            {107                // Update components tree108                devtoolsComponentAdded(instance);109            }110        };111        sharedContext.deactivate = (vnode) => {112            const instance = vnode.component;113            move(vnode, storageContainer, null, 1 /* LEAVE */, parentSuspense);114            queuePostRenderEffect(() => {115                if (instance.da) {116                    invokeArrayFns(instance.da);117                }118                const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted;119                if (vnodeHook) {120                    invokeVNodeHook(vnodeHook, instance.parent, vnode);121                }122                instance.isDeactivated = true;123            }, parentSuspense);124            {125                // Update components tree126                devtoolsComponentAdded(instance);127            }128        };129        function unmount(vnode) {130            // reset the shapeFlag so it can be properly unmounted131            resetShapeFlag(vnode);132            _unmount(vnode, instance, parentSuspense);133        }134        function pruneCache(filter) {...keepAlive.js
Source:keepAlive.js  
...26          invokeArrayFns(instance.a)27        }28        const vnodeHook = vnode.props && vnode.props.onVnodeMounted29        if (vnodeHook) {30          invokeVNodeHook(vnodeHook, instance.parent, vnode)31        }32      }, parentSuspense)33    }34    sharedContext.deactivate = (vnode) => {35      const instance = vnode.component36      move(vnode, storageContainer, null, 1 /* LEAVE */, parentSuspense)37      queuePostRenderEffect(() => {38        if (instance.da) {39          invokeArrayFns(instance.da)40        }41        const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted42        if (vnodeHook) {43          invokeVNodeHook(vnodeHook, instance.parent, vnode)44        }45        instance.isDeactivated = true46      }, parentSuspense)47    }48    function unmount(vnode) {49      resetShapeFlag(vnode)50      _unmount(vnode, instance, parentSuspense)51    }52    function pruneCache(filter) {53      cache.forEach((vnode, key) => {54        const name = getName(vnode.type)55        if (name && (!filter || !filter(name))) {56          pruneCacheEntry(key)57        }58      })59    }60    function pruneCacheEntry(key) {61      const cached = cache.get(key)62      if (!current || cached.type !== current.type) {63        unmount(cached)64      }65      else if (current) {66        resetShapeFlag(current)67      }68      cache.delete(key)69      keys.delete(key)70    }71    watch(() => [props.include, props.exclude], ([include, exclude]) => {72      include && pruneCache(name => matches(include, name))73      exclude && !pruneCache(name => matches(exclude, name))74    })75    let pendingCacheKey = null76    const cacheSubtree = () => {77      if (pendingCacheKey != null) {78        cache.set(pendingCacheKey, instance.subTree)79      }80    }81    onBeforeMount(cacheSubtree)82    onBeforeUpdate(cacheSubtree)83    onBeforeUnmount(() => {84      cache.forEach(cached => {85        const { subTree, suspense } = instance86        if (cached.type === subTree.type) {87          resetShapeFlag(subTree)88          const da = subTree.component.da89          da && queuePostRenderEffect(da, suspense)90          return91        }92        unmount(cached)93      })94    })95    return () => {96      pendingCacheKey = null97      if (!slots.default) {98        return null99      }100      const children = slots.default()101      let vnode = children[0]102      if (children.length > 1) {103        if ((process.env.NODE_ENV !== 'production')) {104          warn(`KeepAlive should contain exactly one component child.`)105        }106        current = null107        return children108      }109      else if (!isVNode(vnode) ||110        !(vnode.shapeFlag & 4 /* STATEFUL_COMPONENT */)) {111        current = null112        return vnode113      }114      const comp = vnode.type115      const name = getName(comp)116      const { include, exclude, max } = props117      if ((include && (!name || !matches(include, name))) ||118        (exclude && name && matches(exclude, name))) {119        return (current = vnode)120      }121      const key = vnode.key == null ? comp : vnode.key122      const cachedVNode = cache.get(key)123      if (vnode.el) {124        vnode = cloneVNode(vnode)125      }126      pendingCacheKey = key127      if (cachedVNode) {128        vnode.el = cachedVNode.el129        vnode.component = cachedVNode.component130        vnode.shapeFlag |= 512 /* COMPONENT_KEPT_ALIVE */131        keys.delete(key)132        keys.add(key)133      }134      else {135        keys.add(key)136        if (max && keys.size > parseInt(max, 10)) {137          pruneCacheEntry(keys.values().next().value)138        }139      }140      vnode.shapeFlag |= 256 /* COMPONENT_SHOULD_KEEP_ALIVE */141      current = vnode142      return vnode143    }144  }145}146// ç»ä»¶ç渲æé¨å147return () => {148  pendingCacheKey = null149  if (!slots.default) {150    return null151  }152  const children = slots.default()153  let vnode = children[0]154  if (children.length > 1) {155    if ((process.env.NODE_ENV !== 'production')) {156      warn(`KeepAlive should contain exactly one component child.`)157    }158    current = null159    return children160  }161  else if (!isVNode(vnode) ||162    !(vnode.shapeFlag & 4 /* STATEFUL_COMPONENT */)) {163    current = null164    return vnode165  }166  const comp = vnode.type167  const name = getName(comp)168  const { include, exclude, max } = props169  if ((include && (!name || !matches(include, name))) ||170    (exclude && name && matches(exclude, name))) {171    return (current = vnode)172  }173  const key = vnode.key == null ? comp : vnode.key174  const cachedVNode = cache.get(key)175  if (vnode.el) {176    vnode = cloneVNode(vnode)177  }178  pendingCacheKey = key179  if (cachedVNode) {180    vnode.el = cachedVNode.el181    vnode.component = cachedVNode.component182    // é¿å
 vnode èç¹ä½ä¸ºæ°èç¹è¢«æè½½183    vnode.shapeFlag |= 512 /* COMPONENT_KEPT_ALIVE */184    // 让è¿ä¸ª key å§ç»æ°é²185    keys.delete(key)186    keys.add(key)187  }188  else {189    keys.add(key)190    // å é¤æä¹
ä¸ç¨ç keyï¼ç¬¦å LRU ææ³191    if (max && keys.size > parseInt(max, 10)) {192      pruneCacheEntry(keys.values().next().value)193    }194  }195  // é¿å
 vnode 被å¸è½½196  vnode.shapeFlag |= 256 /* COMPONENT_SHOULD_KEEP_ALIVE */197  current = vnode198  return vnode199}200sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {201  const instance = vnode.component202  move(vnode, container, anchor, 0 /* ENTER */, parentSuspense)203  patch(instance.vnode, vnode, container, anchor, instance, parentSuspense, isSVG, optimized)204  queuePostRenderEffect(() => {205    instance.isDeactivated = false206    if (instance.a) {207      invokeArrayFns(instance.a)208    }209    const vnodeHook = vnode.props && vnode.props.onVnodeMounted210    if (vnodeHook) {211      invokeVNodeHook(vnodeHook, instance.parent, vnode)212    }213  }, parentSuspense)214}215sharedContext.deactivate = (vnode) => {216  const instance = vnode.component217  move(vnode, storageContainer, null, 1 /* LEAVE */, parentSuspense)218  queuePostRenderEffect(() => {219    if (instance.da) {220      invokeArrayFns(instance.da)221    }222    const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted223    if (vnodeHook) {224      invokeVNodeHook(vnodeHook, instance.parent, vnode)225    }226    instance.isDeactivated = true227  }, parentSuspense)228}229onBeforeUnmount(() => {230  cache.forEach(cached => {231    const { subTree, suspense } = instance232    if (cached.type === subTree.type) {233      resetShapeFlag(subTree)234      const da = subTree.component.da235      da && queuePostRenderEffect(da, suspense)236      return237    }238    unmount(cached)...router-alive-ext.jsx
Source:router-alive-ext.jsx  
...92          invokeArrayFns(instance.a)93        }94        const vnodeHook = vnode.props && vnode.props.onVnodeMounted95        if (vnodeHook) {96          invokeVNodeHook(vnodeHook, instance.parent, vnode)97        }98      }, parentSuspense)99    }100    sharedContext.deactivate = (vnode) => {101      const instance = vnode.component102      move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)103      queuePostRenderEffect(() => {104        if (instance.da) {105          invokeArrayFns(instance.da)106        }107        const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted108        if (vnodeHook) {109          invokeVNodeHook(vnodeHook, instance.parent, vnode)110        }111        instance.isDeactivated = true112      }, parentSuspense)113    }114    function unmount(vnode) {115      // reset the shapeFlag so it can be properly unmounted116      resetShapeFlag(vnode)117      _unmount(vnode, instance, parentSuspense)118    }119    function pruneCache(filter) {120      cache.forEach((vnode, key) => { 121        const name = getComponentName(vnode.type, vnode.key)122        if (name && (!filter || !filter(name))) {123          pruneCacheEntry(key)124        }125      })126    }127    function pruneCacheEntry(key) {128      const cached = cache.get(key)129      // if (!current || cached.type !== current.type) {130      //   unmount(cached)131      // } else if (current) {132      //   resetShapeFlag(current)133      // }134      // å½tabåºåå卿¨¡å页é¢135      if (current){136        unmount(cached)137      }138      139      cache.delete(key)140      keys.delete(key)141    }142    watch(143      () => [props.include, props.exclude],144      ([include, exclude]) => {145        include && pruneCache(name => matches(include, name))146        exclude && pruneCache(name => !matches(exclude, name))147      },148      // prune post-render after `current` has been updated149      { flush: 'post', deep: true }150    )151    // cache sub tree after render152    let pendingCacheKey = null153    const cacheSubtree = () => {154      // fix #1621, the pendingCacheKey could be 0155      if (pendingCacheKey != null) {156        cache.set(pendingCacheKey, getInnerChild(instance.subTree))157      }158    }159    onMounted(cacheSubtree)160    onUpdated(cacheSubtree)161    onBeforeUnmount(() => {162      cache.forEach(cached => {163        const { subTree, suspense } = instance164        const vnode = getInnerChild(subTree)165        if (cached.type === vnode.type) {166          // current instance will be unmounted as part of keep-alive's unmount167          resetShapeFlag(vnode)168          // but invoke its deactivated hook here169          const da = vnode.component.da170          da && queuePostRenderEffect(da, suspense)171          return172        }173        unmount(cached)174      })175    })176    //render fn177    return () => {178      pendingCacheKey = null179      if (!slots.default) {180        return null181      }182      const children = slots.default()183      const rawVNode = children[0]184      if (children.length > 1) {185       current = null186        return children187      } else if (188        !isVNode(rawVNode) ||189        (!(rawVNode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) &&190          !(rawVNode.shapeFlag & ShapeFlags.SUSPENSE))191      ) {192        current = null193        return rawVNode194      }195      let vnode = getInnerChild(rawVNode)196      const comp = vnode.type197      const name = getComponentName(comp, vnode.key)198      const { include, exclude, max } = props199      if (200        (include && (!name || !matches(include, name))) ||201        (exclude && name && matches(exclude, name))202      ) {203        current = vnode204        return rawVNode205      }206      const key = vnode.key == null ? comp : vnode.key207      const cachedVNode = cache.get(key)208      if (vnode.el) {209        vnode = cloneVNode(vnode)210        if (rawVNode.shapeFlag & ShapeFlags.SUSPENSE) {211          rawVNode.ssContent = vnode212        }213      }214    215      pendingCacheKey = key216      if (cachedVNode) {217        vnode.el = cachedVNode.el218        vnode.component = cachedVNode.component219        if (vnode.transition) {220          setTransitionHooks(vnode, vnode.transition)221        }222        vnode.shapeFlag |= ShapeFlags.COMPONENT_KEPT_ALIVE223        keys.delete(key)224        keys.add(key)225      } else {226        keys.add(key)227        if (max && keys.size > parseInt(max, 10)) {228          pruneCacheEntry(keys.values().next().value)229        }230      }231      vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE232      current = vnode233      return rawVNode234    }235  }236}237function isFunction(val){238  return typeof val === 'function'239}240function getComponentName(241  Component,242  key243){244  if (key){245    return key246  }247  return isFunction(Component)248    ? Component.displayName || Component.name249    : Component.name250}251function resetShapeFlag(vnode) {252  let shapeFlag = vnode.shapeFlag253  if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {254    shapeFlag -= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE255  }256  if (shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {257    shapeFlag -= ShapeFlags.COMPONENT_KEPT_ALIVE258  }259  vnode.shapeFlag = shapeFlag260}261function getInnerChild(vnode) {262  return vnode.shapeFlag & ShapeFlags.SUSPENSE ? vnode.ssContent : vnode263}264function matches(pattern, name) {265  if (isArray(pattern)) {266    return pattern.some((p) => matches(p, name))267  } else if (isString(pattern)) {268    return pattern.split(',').indexOf(name) > -1269  } else if (pattern.test) {270    return pattern.test(name)271  }272  return false273}274function invokeVNodeHook(275  hook,276  instance,277  vnode,278  prevVNode = null279) {280  callWithAsyncErrorHandling(hook, instance, 7, [281    vnode,282    prevVNode283  ])...2.js
Source:2.js  
...10                invokeArrayFns(bm);11            }12            // onVnodeBeforeMount13            if ((vnodeHook = props && props.onVnodeBeforeMount)) {14                invokeVNodeHook(vnodeHook, parent, initialVNode);15            }16            effect.allowRecurse = true;17            if (el && hydrateNode) {18                // vnode has adopted host node - perform hydration instead of mount.19                const hydrateSubTree = () => {20                    {21                        startMeasure(instance, `render`);22                    }23                    instance.subTree = renderComponentRoot(instance);24                    {25                        endMeasure(instance, `render`);26                    }27                    {28                        startMeasure(instance, `hydrate`);29                    }30                    hydrateNode(el, instance.subTree, instance, parentSuspense, null);31                    {32                        endMeasure(instance, `hydrate`);33                    }34                };35                if (isAsyncWrapper(initialVNode)) {36                    initialVNode.type.__asyncLoader().then(37                        // note: we are moving the render call into an async callback,38                        // which means it won't track dependencies - but it's ok because39                        // a server-rendered async wrapper is already in resolved state40                        // and it will never need to change.41                        () => !instance.isUnmounted && hydrateSubTree());42                }43                else {44                    hydrateSubTree();45                }46            }47            else {48                {49                    startMeasure(instance, `render`);50                }51                const subTree = (instance.subTree = renderComponentRoot(instance));52                {53                    endMeasure(instance, `render`);54                }55                {56                    startMeasure(instance, `patch`);57                }58                patch(null, subTree, container, anchor, instance, parentSuspense, isSVG);59                {60                    endMeasure(instance, `patch`);61                }62                initialVNode.el = subTree.el;63            }64            // mounted hook65            if (m) {66                queuePostRenderEffect(m, parentSuspense);67            }68            // onVnodeMounted69            if ((vnodeHook = props && props.onVnodeMounted)) {70                const scopedInitialVNode = initialVNode;71                queuePostRenderEffect(() => invokeVNodeHook(vnodeHook, parent, scopedInitialVNode), parentSuspense);72            }73            // activated hook for keep-alive roots.74            // #1742 activated hook must be accessed after first render75            // since the hook may be injected by a child keep-alive76            if (initialVNode.shapeFlag & 256 /* COMPONENT_SHOULD_KEEP_ALIVE */) {77                instance.a && queuePostRenderEffect(instance.a, parentSuspense);78            }79            instance.isMounted = true;80            {81                devtoolsComponentAdded(instance);82            }83            // #2458: deference mount-only object parameters to prevent memleaks84            initialVNode = container = anchor = null;85        }86        else {87            // updateComponent88            // This is triggered by mutation of component's own state (next: null)89            // OR parent calling processComponent (next: VNode)90            let { next, bu, u, parent, vnode } = instance;91            let originNext = next;92            let vnodeHook;93            {94                pushWarningContext(next || instance.vnode);95            }96            if (next) {97                next.el = vnode.el;98                updateComponentPreRender(instance, next, optimized);99            }100            else {101                next = vnode;102            }103            // Disallow component effect recursion during pre-lifecycle hooks.104            effect.allowRecurse = false;105            // beforeUpdate hook106            if (bu) {107                invokeArrayFns(bu);108            }109            // onVnodeBeforeUpdate110            if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {111                invokeVNodeHook(vnodeHook, parent, next, vnode);112            }113            effect.allowRecurse = true;114            // render115            {116                startMeasure(instance, `render`);117            }118            const nextTree = renderComponentRoot(instance);119            {120                endMeasure(instance, `render`);121            }122            const prevTree = instance.subTree;123            instance.subTree = nextTree;124            {125                startMeasure(instance, `patch`);126            }127            patch(prevTree, nextTree,128                // parent may have changed if it's in a teleport129                hostParentNode(prevTree.el),130                // anchor may have changed if it's in a fragment131                getNextHostNode(prevTree), instance, parentSuspense, isSVG);132            {133                endMeasure(instance, `patch`);134            }135            next.el = nextTree.el;136            if (originNext === null) {137                // self-triggered update. In case of HOC, update parent component138                // vnode el. HOC is indicated by parent instance's subTree pointing139                // to child component's vnode140                updateHOCHostEl(instance, nextTree.el);141            }142            // updated hook143            if (u) {144                queuePostRenderEffect(u, parentSuspense);145            }146            // onVnodeUpdated147            if ((vnodeHook = next.props && next.props.onVnodeUpdated)) {148                queuePostRenderEffect(() => invokeVNodeHook(vnodeHook, parent, next, vnode), parentSuspense);149            }150            {151                devtoolsComponentUpdated(instance);152            }153            {154                popWarningContext();155            }156        }...vnode.js
Source:vnode.js  
1import { callWithAsyncErrorHandling } from 'Vue'2const VNODE_HOOK = 73export function invokeVNodeHook(4    hook,5    instance,6    vnode,7    prevVNode = null8  ) {9    callWithAsyncErrorHandling(hook, instance, VNODE_HOOK, [10      vnode,11      prevVNode12    ])13  }...Using AI Code Generation
1const { invokeVNodeHook } = require('playwright');2const { chromium } = require('playwright-chromium');3(async () => {4  const browser = await chromium.launch();5  const page = await browser.newPage();6  await invokeVNodeHook(page, 'a', 'click', () => {7    console.log('Link clicked');8  });9  await browser.close();10})();Using AI Code Generation
1const { invokeVNodeHook } = require('@playwright/test/lib/server/vnode');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4    await invokeVNodeHook('text=Get started', 'mounted', {});5});6const { invokeVNodeHook } = require('@playwright/test/lib/server/vnode');7const { test } = require('@playwright/test');8test('test', async ({ page }) => {9    await invokeVNodeHook('text=Get started', 'mounted', {});10});Using AI Code Generation
1const { invokeVNodeHook } = require('@playwright/test/lib/server/vscode/vscode');2const { VNode } = require('@playwright/test/lib/server/vscode/vnode');3const vnode = new VNode('my-vnode', 'my-vnode');4invokeVNodeHook(vnode, 'my-hook', 'my-arg');5{6    {7      "outFiles": ["${workspaceFolder}/lib/**/*.js"],8    }9}Using AI Code Generation
1const { invokeVNodeHook } = require('@playwright/test/lib/server/vscode/vscode');2const { test } = require('@playwright/test');3test.describe('My Test', () => {4    test('My Test', async ({ page }) => {5        await invokeVNodeHook(page, 'onDidClick', { selector: 'text=Get started' });6    });7});Using AI Code Generation
1const { invokeVNodeHook, VNode } = require('playwright-core/lib/server/trace/recorder/vnode');2const { Page } = require('playwright-core/lib/server/page');3const { ElementHandle } = require('playwright-core/lib/server/dom');4const { Frame } = require('playwright-core/lib/server/frames');5const { JSHandle } = require('playwright-core/lib/server/jsHandle');6const { v4: uuidv4 } = require('uuid');7const { createHash } = require('crypto');8class VNodeWrapper {9  constructor(vNode) {10    this.vNode = vNode;11  }12  async getAttribute(name) {13    return this.vNode.getAttribute(name);14  }15  async getAttributes() {16    return this.vNode.getAttributes();17  }18  async getInnerText() {19    return this.vNode.getInnerText();20  }21  async getInnerHTML() {22    return this.vNode.getInnerHTML();23  }24  async getInnerText() {25    return this.vNode.getInnerText();26  }27  async getVisible() {28    return this.vNode.getVisible();29  }30  async getVisibleCenter() {31    return this.vNode.getVisibleCenter();32  }33  async getVisibleBoundingBox() {34    return this.vNode.getVisibleBoundingBox();35  }36  async getBoundingRect() {37    return this.vNode.getBoundingRect();38  }39  async getComputedStyle() {40    return this.vNode.getComputedStyle();41  }42  async getOwnerFrame() {43    return this.vNode.getOwnerFrame();44  }45  async getOwnerPage() {46    return this.vNode.getOwnerPage();47  }48  async getOwnerElement() {49    return this.vNode.getOwnerElement();50  }51  async getChildren() {52    return this.vNode.getChildren();53  }54  async getSelector() {55    return this.vNode.getSelector();56  }57  async getSelectorList() {58    return this.vNode.getSelectorList();59  }60  async getSelectorListWithText() {61    return this.vNode.getSelectorListWithText();62  }63  async getSelectorListWithTextAndIndex() {Using AI Code Generation
1const { invokeVNodeHook } = require('playwright/lib/server/dom.js');2const { getTestState } = require('playwright/lib/server/state.js');3const testState = getTestState();4const page = testState.page;5const elementHandle = await page.$('button');6await invokeVNodeHook(elementHandle, 'onfocus');7[Apache 2.0](LICENSE.txt)Using AI Code Generation
1const { invokeVNodeHook } = require('@playwright/test/lib/server/vnode');2invokeVNodeHook(vnode, 'hookName');3import { invokeVNodeHook } from '@playwright/test/lib/server/vnode';4invokeVNodeHook(vnode, 'hookName');5const { page } = test;6const page = test.page;7const { browser } = test;8const browser = test.browser;9const { currentTestInfo } = require('@playwright/test/lib/server/test');10import { currentTestInfo } from '@playwright/test/lib/server/test';11const { testInfo } = test;12const testInfo = test.testInfo;13const { state } =Using AI Code Generation
1const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');2invokeVNodeHook(node, 'click');3const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');4invokeVNodeHook(node, 'mouseover');5const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');6invokeVNodeHook(node, 'mousedown');7const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');8invokeVNodeHook(node, 'mouseup');9const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');10invokeVNodeHook(node, 'focus');11const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');12invokeVNodeHook(node, 'blur');13const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');14invokeVNodeHook(node, 'change');15const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.js');16invokeVNodeHook(node, 'input');17const { invokeVNodeHook } = require('playwright/lib/server/supplements/recorder/recorderSupplement.jsUsing AI Code Generation
1const { invokeVNodeHook } = require('playwright/lib/server/dom.js');2const vnode = {3  props: {4    style: { color: 'red' },5  },6  attrs: {7  },8    {9      props: {10        style: { color: 'red' },11      },12      attrs: {13      },14    },15};16invokeVNodeHook(vnode, 'hook:mounted');17function invokeVNodeHook(vnode, hook) {18  const handlers = vnode.data && vnode.data.hook && vnode.data.hook[hook];19  if (handlers) for (const handler of handlers) handler();20}LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
