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.js
Using 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!!