How to use invokeVNodeHook method in Playwright Internal

Best JavaScript code snippet using playwright-internal

createApp.js

Source:createApp.js Github

copy

Full Screen

...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;...

Full Screen

Full Screen

patch.js

Source:patch.js Github

copy

Full Screen

...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);...

Full Screen

Full Screen

renderer.js

Source:renderer.js Github

copy

Full Screen

...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...

Full Screen

Full Screen

Navigation.js

Source:Navigation.js Github

copy

Full Screen

...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) {...

Full Screen

Full Screen

keepAlive.js

Source:keepAlive.js Github

copy

Full Screen

...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)...

Full Screen

Full Screen

router-alive-ext.jsx

Source:router-alive-ext.jsx Github

copy

Full Screen

...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 ])...

Full Screen

Full Screen

2.js

Source:2.js Github

copy

Full Screen

...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 }...

Full Screen

Full Screen

vnode.js

Source:vnode.js Github

copy

Full Screen

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 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

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})();

Full Screen

Using AI Code Generation

copy

Full Screen

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});

Full Screen

Using AI Code Generation

copy

Full Screen

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}

Full Screen

Using AI Code Generation

copy

Full Screen

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});

Full Screen

Using AI Code Generation

copy

Full Screen

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() {

Full Screen

Using AI Code Generation

copy

Full Screen

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)

Full Screen

Using AI Code Generation

copy

Full Screen

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 } =

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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}

Full Screen

Playwright tutorial

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.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful