Best JavaScript code snippet using playwright-internal
ReactFiberCommitWork.new.js
Source:ReactFiberCommitWork.new.js
...335 // Check to see if the focused element was inside of a hidden (Suspense) subtree.336 // TODO: Move this out of the hot path using a dedicated effect tag.337 if (338 finishedWork.tag === SuspenseComponent &&339 isSuspenseBoundaryBeingHidden(current, finishedWork) &&340 doesFiberContain(finishedWork, focusedInstanceHandle)341 ) {342 shouldFireAfterActiveInstanceBlur = true;343 beforeActiveInstanceBlur(finishedWork);344 }345 }346 if ((flags & Snapshot) !== NoFlags) {347 setCurrentDebugFiberInDEV(finishedWork);348 switch (finishedWork.tag) {349 case FunctionComponent:350 case ForwardRef:351 case SimpleMemoComponent: {352 break;353 }354 case ClassComponent: {355 if (current !== null) {356 const prevProps = current.memoizedProps;357 const prevState = current.memoizedState;358 const instance = finishedWork.stateNode;359 // We could update instance props and state here,360 // but instead we rely on them being set during last render.361 // TODO: revisit this when we implement resuming.362 if (__DEV__) {363 if (364 finishedWork.type === finishedWork.elementType &&365 !didWarnAboutReassigningProps366 ) {367 if (instance.props !== finishedWork.memoizedProps) {368 console.error(369 'Expected %s props to match memoized props before ' +370 'getSnapshotBeforeUpdate. ' +371 'This might either be because of a bug in React, or because ' +372 'a component reassigns its own `this.props`. ' +373 'Please file an issue.',374 getComponentName(finishedWork.type) || 'instance',375 );376 }377 if (instance.state !== finishedWork.memoizedState) {378 console.error(379 'Expected %s state to match memoized state before ' +380 'getSnapshotBeforeUpdate. ' +381 'This might either be because of a bug in React, or because ' +382 'a component reassigns its own `this.state`. ' +383 'Please file an issue.',384 getComponentName(finishedWork.type) || 'instance',385 );386 }387 }388 }389 const snapshot = instance.getSnapshotBeforeUpdate(390 finishedWork.elementType === finishedWork.type391 ? prevProps392 : resolveDefaultProps(finishedWork.type, prevProps),393 prevState,394 );395 if (__DEV__) {396 const didWarnSet = ((didWarnAboutUndefinedSnapshotBeforeUpdate: any): Set<mixed>);397 if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) {398 didWarnSet.add(finishedWork.type);399 console.error(400 '%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' +401 'must be returned. You have returned undefined.',402 getComponentName(finishedWork.type),403 );404 }405 }406 instance.__reactInternalSnapshotBeforeUpdate = snapshot;407 }408 break;409 }410 case HostRoot: {411 if (supportsMutation) {412 const root = finishedWork.stateNode;413 clearContainer(root.containerInfo);414 }415 break;416 }417 case HostComponent:418 case HostText:419 case HostPortal:420 case IncompleteClassComponent:421 // Nothing to do for these component types422 break;423 default: {424 invariant(425 false,426 'This unit of work tag should not have side-effects. This error is ' +427 'likely caused by a bug in React. Please file an issue.',428 );429 }430 }431 resetCurrentDebugFiberInDEV();432 }433}434function commitBeforeMutationEffectsDeletion(deletion: Fiber) {435 // TODO (effects) It would be nice to avoid calling doesFiberContain()436 // Maybe we can repurpose one of the subtreeFlags positions for this instead?437 // Use it to store which part of the tree the focused instance is in?438 // This assumes we can safely determine that instance during the "render" phase.439 if (doesFiberContain(deletion, ((focusedInstanceHandle: any): Fiber))) {440 shouldFireAfterActiveInstanceBlur = true;441 beforeActiveInstanceBlur(deletion);442 }443}444function commitHookEffectListUnmount(445 flags: HookFlags,446 finishedWork: Fiber,447 nearestMountedAncestor: Fiber | null,448) {449 const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any);450 const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;451 if (lastEffect !== null) {452 const firstEffect = lastEffect.next;453 let effect = firstEffect;454 do {455 if ((effect.tag & flags) === flags) {456 // Unmount457 const destroy = effect.destroy;458 effect.destroy = undefined;459 if (destroy !== undefined) {460 safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);461 }462 }463 effect = effect.next;464 } while (effect !== firstEffect);465 }466}467function commitHookEffectListMount(tag: number, finishedWork: Fiber) {468 const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any);469 const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;470 if (lastEffect !== null) {471 const firstEffect = lastEffect.next;472 let effect = firstEffect;473 do {474 if ((effect.tag & tag) === tag) {475 // Mount476 const create = effect.create;477 effect.destroy = create();478 if (__DEV__) {479 const destroy = effect.destroy;480 if (destroy !== undefined && typeof destroy !== 'function') {481 let addendum;482 if (destroy === null) {483 addendum =484 ' You returned null. If your effect does not require clean ' +485 'up, return undefined (or nothing).';486 } else if (typeof destroy.then === 'function') {487 addendum =488 '\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' +489 'Instead, write the async function inside your effect ' +490 'and call it immediately:\n\n' +491 'useEffect(() => {\n' +492 ' async function fetchData() {\n' +493 ' // You can await here\n' +494 ' const response = await MyAPI.getData(someId);\n' +495 ' // ...\n' +496 ' }\n' +497 ' fetchData();\n' +498 `}, [someId]); // Or [] if effect doesn't need props or state\n\n` +499 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching';500 } else {501 addendum = ' You returned: ' + destroy;502 }503 console.error(504 'An effect function must not return anything besides a function, ' +505 'which is used for clean-up.%s',506 addendum,507 );508 }509 }510 }511 effect = effect.next;512 } while (effect !== firstEffect);513 }514}515export function commitPassiveEffectDurations(516 finishedRoot: FiberRoot,517 finishedWork: Fiber,518): void {519 if (enableProfilerTimer && enableProfilerCommitHooks) {520 // Only Profilers with work in their subtree will have an Update effect scheduled.521 if ((finishedWork.flags & Update) !== NoFlags) {522 switch (finishedWork.tag) {523 case Profiler: {524 const {passiveEffectDuration} = finishedWork.stateNode;525 const {id, onPostCommit} = finishedWork.memoizedProps;526 // This value will still reflect the previous commit phase.527 // It does not get reset until the start of the next commit phase.528 const commitTime = getCommitTime();529 let phase = finishedWork.alternate === null ? 'mount' : 'update';530 if (enableProfilerNestedUpdatePhase) {531 if (isCurrentUpdateNested()) {532 phase = 'nested-update';533 }534 }535 if (typeof onPostCommit === 'function') {536 if (enableSchedulerTracing) {537 onPostCommit(538 id,539 phase,540 passiveEffectDuration,541 commitTime,542 finishedRoot.memoizedInteractions,543 );544 } else {545 onPostCommit(id, phase, passiveEffectDuration, commitTime);546 }547 }548 // Bubble times to the next nearest ancestor Profiler.549 // After we process that Profiler, we'll bubble further up.550 let parentFiber = finishedWork.return;551 while (parentFiber !== null) {552 if (parentFiber.tag === Profiler) {553 const parentStateNode = parentFiber.stateNode;554 parentStateNode.passiveEffectDuration += passiveEffectDuration;555 break;556 }557 parentFiber = parentFiber.return;558 }559 break;560 }561 default:562 break;563 }564 }565 }566}567function commitLayoutEffectOnFiber(568 finishedRoot: FiberRoot,569 current: Fiber | null,570 finishedWork: Fiber,571 committedLanes: Lanes,572): void {573 if ((finishedWork.flags & (Update | Callback)) !== NoFlags) {574 switch (finishedWork.tag) {575 case FunctionComponent:576 case ForwardRef:577 case SimpleMemoComponent: {578 // At this point layout effects have already been destroyed (during mutation phase).579 // This is done to prevent sibling component effects from interfering with each other,580 // e.g. a destroy function in one component should never override a ref set581 // by a create function in another component during the same commit.582 if (583 enableProfilerTimer &&584 enableProfilerCommitHooks &&585 finishedWork.mode & ProfileMode586 ) {587 try {588 startLayoutEffectTimer();589 commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);590 } finally {591 recordLayoutEffectDuration(finishedWork);592 }593 } else {594 commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);595 }596 break;597 }598 case ClassComponent: {599 const instance = finishedWork.stateNode;600 if (finishedWork.flags & Update) {601 if (current === null) {602 // We could update instance props and state here,603 // but instead we rely on them being set during last render.604 // TODO: revisit this when we implement resuming.605 if (__DEV__) {606 if (607 finishedWork.type === finishedWork.elementType &&608 !didWarnAboutReassigningProps609 ) {610 if (instance.props !== finishedWork.memoizedProps) {611 console.error(612 'Expected %s props to match memoized props before ' +613 'componentDidMount. ' +614 'This might either be because of a bug in React, or because ' +615 'a component reassigns its own `this.props`. ' +616 'Please file an issue.',617 getComponentName(finishedWork.type) || 'instance',618 );619 }620 if (instance.state !== finishedWork.memoizedState) {621 console.error(622 'Expected %s state to match memoized state before ' +623 'componentDidMount. ' +624 'This might either be because of a bug in React, or because ' +625 'a component reassigns its own `this.state`. ' +626 'Please file an issue.',627 getComponentName(finishedWork.type) || 'instance',628 );629 }630 }631 }632 if (633 enableProfilerTimer &&634 enableProfilerCommitHooks &&635 finishedWork.mode & ProfileMode636 ) {637 try {638 startLayoutEffectTimer();639 instance.componentDidMount();640 } finally {641 recordLayoutEffectDuration(finishedWork);642 }643 } else {644 instance.componentDidMount();645 }646 } else {647 const prevProps =648 finishedWork.elementType === finishedWork.type649 ? current.memoizedProps650 : resolveDefaultProps(finishedWork.type, current.memoizedProps);651 const prevState = current.memoizedState;652 // We could update instance props and state here,653 // but instead we rely on them being set during last render.654 // TODO: revisit this when we implement resuming.655 if (__DEV__) {656 if (657 finishedWork.type === finishedWork.elementType &&658 !didWarnAboutReassigningProps659 ) {660 if (instance.props !== finishedWork.memoizedProps) {661 console.error(662 'Expected %s props to match memoized props before ' +663 'componentDidUpdate. ' +664 'This might either be because of a bug in React, or because ' +665 'a component reassigns its own `this.props`. ' +666 'Please file an issue.',667 getComponentName(finishedWork.type) || 'instance',668 );669 }670 if (instance.state !== finishedWork.memoizedState) {671 console.error(672 'Expected %s state to match memoized state before ' +673 'componentDidUpdate. ' +674 'This might either be because of a bug in React, or because ' +675 'a component reassigns its own `this.state`. ' +676 'Please file an issue.',677 getComponentName(finishedWork.type) || 'instance',678 );679 }680 }681 }682 if (683 enableProfilerTimer &&684 enableProfilerCommitHooks &&685 finishedWork.mode & ProfileMode686 ) {687 try {688 startLayoutEffectTimer();689 instance.componentDidUpdate(690 prevProps,691 prevState,692 instance.__reactInternalSnapshotBeforeUpdate,693 );694 } finally {695 recordLayoutEffectDuration(finishedWork);696 }697 } else {698 instance.componentDidUpdate(699 prevProps,700 prevState,701 instance.__reactInternalSnapshotBeforeUpdate,702 );703 }704 }705 }706 // TODO: I think this is now always non-null by the time it reaches the707 // commit phase. Consider removing the type check.708 const updateQueue: UpdateQueue<709 *,710 > | null = (finishedWork.updateQueue: any);711 if (updateQueue !== null) {712 if (__DEV__) {713 if (714 finishedWork.type === finishedWork.elementType &&715 !didWarnAboutReassigningProps716 ) {717 if (instance.props !== finishedWork.memoizedProps) {718 console.error(719 'Expected %s props to match memoized props before ' +720 'processing the update queue. ' +721 'This might either be because of a bug in React, or because ' +722 'a component reassigns its own `this.props`. ' +723 'Please file an issue.',724 getComponentName(finishedWork.type) || 'instance',725 );726 }727 if (instance.state !== finishedWork.memoizedState) {728 console.error(729 'Expected %s state to match memoized state before ' +730 'processing the update queue. ' +731 'This might either be because of a bug in React, or because ' +732 'a component reassigns its own `this.state`. ' +733 'Please file an issue.',734 getComponentName(finishedWork.type) || 'instance',735 );736 }737 }738 }739 // We could update instance props and state here,740 // but instead we rely on them being set during last render.741 // TODO: revisit this when we implement resuming.742 commitUpdateQueue(finishedWork, updateQueue, instance);743 }744 break;745 }746 case HostRoot: {747 // TODO: I think this is now always non-null by the time it reaches the748 // commit phase. Consider removing the type check.749 const updateQueue: UpdateQueue<750 *,751 > | null = (finishedWork.updateQueue: any);752 if (updateQueue !== null) {753 let instance = null;754 if (finishedWork.child !== null) {755 switch (finishedWork.child.tag) {756 case HostComponent:757 instance = getPublicInstance(finishedWork.child.stateNode);758 break;759 case ClassComponent:760 instance = finishedWork.child.stateNode;761 break;762 }763 }764 commitUpdateQueue(finishedWork, updateQueue, instance);765 }766 break;767 }768 case HostComponent: {769 const instance: Instance = finishedWork.stateNode;770 // Renderers may schedule work to be done after host components are mounted771 // (eg DOM renderer may schedule auto-focus for inputs and form controls).772 // These effects should only be committed when components are first mounted,773 // aka when there is no current/alternate.774 if (current === null && finishedWork.flags & Update) {775 const type = finishedWork.type;776 const props = finishedWork.memoizedProps;777 commitMount(instance, type, props, finishedWork);778 }779 break;780 }781 case HostText: {782 // We have no life-cycles associated with text.783 break;784 }785 case HostPortal: {786 // We have no life-cycles associated with portals.787 break;788 }789 case Profiler: {790 if (enableProfilerTimer) {791 const {onCommit, onRender} = finishedWork.memoizedProps;792 const {effectDuration} = finishedWork.stateNode;793 const commitTime = getCommitTime();794 let phase = current === null ? 'mount' : 'update';795 if (enableProfilerNestedUpdatePhase) {796 if (isCurrentUpdateNested()) {797 phase = 'nested-update';798 }799 }800 if (typeof onRender === 'function') {801 if (enableSchedulerTracing) {802 onRender(803 finishedWork.memoizedProps.id,804 phase,805 finishedWork.actualDuration,806 finishedWork.treeBaseDuration,807 finishedWork.actualStartTime,808 commitTime,809 finishedRoot.memoizedInteractions,810 );811 } else {812 onRender(813 finishedWork.memoizedProps.id,814 phase,815 finishedWork.actualDuration,816 finishedWork.treeBaseDuration,817 finishedWork.actualStartTime,818 commitTime,819 );820 }821 }822 if (enableProfilerCommitHooks) {823 if (typeof onCommit === 'function') {824 if (enableSchedulerTracing) {825 onCommit(826 finishedWork.memoizedProps.id,827 phase,828 effectDuration,829 commitTime,830 finishedRoot.memoizedInteractions,831 );832 } else {833 onCommit(834 finishedWork.memoizedProps.id,835 phase,836 effectDuration,837 commitTime,838 );839 }840 }841 // Schedule a passive effect for this Profiler to call onPostCommit hooks.842 // This effect should be scheduled even if there is no onPostCommit callback for this Profiler,843 // because the effect is also where times bubble to parent Profilers.844 enqueuePendingPassiveProfilerEffect(finishedWork);845 // Propagate layout effect durations to the next nearest Profiler ancestor.846 // Do not reset these values until the next render so DevTools has a chance to read them first.847 let parentFiber = finishedWork.return;848 while (parentFiber !== null) {849 if (parentFiber.tag === Profiler) {850 const parentStateNode = parentFiber.stateNode;851 parentStateNode.effectDuration += effectDuration;852 break;853 }854 parentFiber = parentFiber.return;855 }856 }857 }858 break;859 }860 case SuspenseComponent: {861 commitSuspenseHydrationCallbacks(finishedRoot, finishedWork);862 break;863 }864 case SuspenseListComponent:865 case IncompleteClassComponent:866 case FundamentalComponent:867 case ScopeComponent:868 case OffscreenComponent:869 case LegacyHiddenComponent:870 break;871 default:872 invariant(873 false,874 'This unit of work tag should not have side-effects. This error is ' +875 'likely caused by a bug in React. Please file an issue.',876 );877 }878 }879 if (enableScopeAPI) {880 // TODO: This is a temporary solution that allowed us to transition away881 // from React Flare on www.882 if (finishedWork.flags & Ref && finishedWork.tag !== ScopeComponent) {883 commitAttachRef(finishedWork);884 }885 } else {886 if (finishedWork.flags & Ref) {887 commitAttachRef(finishedWork);888 }889 }890}891function hideOrUnhideAllChildren(finishedWork, isHidden) {892 if (supportsMutation) {893 // We only have the top Fiber that was inserted but we need to recurse down its894 // children to find all the terminal nodes.895 let node: Fiber = finishedWork;896 while (true) {897 if (node.tag === HostComponent) {898 const instance = node.stateNode;899 if (isHidden) {900 hideInstance(instance);901 } else {902 unhideInstance(node.stateNode, node.memoizedProps);903 }904 } else if (node.tag === HostText) {905 const instance = node.stateNode;906 if (isHidden) {907 hideTextInstance(instance);908 } else {909 unhideTextInstance(instance, node.memoizedProps);910 }911 } else if (912 (node.tag === OffscreenComponent ||913 node.tag === LegacyHiddenComponent) &&914 (node.memoizedState: OffscreenState) !== null &&915 node !== finishedWork916 ) {917 // Found a nested Offscreen component that is hidden. Don't search918 // any deeper. This tree should remain hidden.919 } else if (node.child !== null) {920 node.child.return = node;921 node = node.child;922 continue;923 }924 if (node === finishedWork) {925 return;926 }927 while (node.sibling === null) {928 if (node.return === null || node.return === finishedWork) {929 return;930 }931 node = node.return;932 }933 node.sibling.return = node.return;934 node = node.sibling;935 }936 }937}938function commitAttachRef(finishedWork: Fiber) {939 const ref = finishedWork.ref;940 if (ref !== null) {941 const instance = finishedWork.stateNode;942 let instanceToUse;943 switch (finishedWork.tag) {944 case HostComponent:945 instanceToUse = getPublicInstance(instance);946 break;947 default:948 instanceToUse = instance;949 }950 // Moved outside to ensure DCE works with this flag951 if (enableScopeAPI && finishedWork.tag === ScopeComponent) {952 instanceToUse = instance;953 }954 if (typeof ref === 'function') {955 if (956 enableProfilerTimer &&957 enableProfilerCommitHooks &&958 finishedWork.mode & ProfileMode959 ) {960 try {961 startLayoutEffectTimer();962 ref(instanceToUse);963 } finally {964 recordLayoutEffectDuration(finishedWork);965 }966 } else {967 ref(instanceToUse);968 }969 } else {970 if (__DEV__) {971 if (!ref.hasOwnProperty('current')) {972 console.error(973 'Unexpected ref object provided for %s. ' +974 'Use either a ref-setter function or React.createRef().',975 getComponentName(finishedWork.type),976 );977 }978 }979 ref.current = instanceToUse;980 }981 }982}983function commitDetachRef(current: Fiber) {984 const currentRef = current.ref;985 if (currentRef !== null) {986 if (typeof currentRef === 'function') {987 if (988 enableProfilerTimer &&989 enableProfilerCommitHooks &&990 current.mode & ProfileMode991 ) {992 try {993 startLayoutEffectTimer();994 currentRef(null);995 } finally {996 recordLayoutEffectDuration(current);997 }998 } else {999 currentRef(null);1000 }1001 } else {1002 currentRef.current = null;1003 }1004 }1005}1006// User-originating errors (lifecycles and refs) should not interrupt1007// deletion, so don't let them throw. Host-originating errors should1008// interrupt deletion, so it's okay1009function commitUnmount(1010 finishedRoot: FiberRoot,1011 current: Fiber,1012 nearestMountedAncestor: Fiber,1013 renderPriorityLevel: ReactPriorityLevel,1014): void {1015 onCommitUnmount(current);1016 switch (current.tag) {1017 case FunctionComponent:1018 case ForwardRef:1019 case MemoComponent:1020 case SimpleMemoComponent: {1021 const updateQueue: FunctionComponentUpdateQueue | null = (current.updateQueue: any);1022 if (updateQueue !== null) {1023 const lastEffect = updateQueue.lastEffect;1024 if (lastEffect !== null) {1025 const firstEffect = lastEffect.next;1026 let effect = firstEffect;1027 do {1028 const {destroy, tag} = effect;1029 if (destroy !== undefined) {1030 if ((tag & HookLayout) !== NoHookEffect) {1031 if (1032 enableProfilerTimer &&1033 enableProfilerCommitHooks &&1034 current.mode & ProfileMode1035 ) {1036 startLayoutEffectTimer();1037 safelyCallDestroy(current, nearestMountedAncestor, destroy);1038 recordLayoutEffectDuration(current);1039 } else {1040 safelyCallDestroy(current, nearestMountedAncestor, destroy);1041 }1042 }1043 }1044 effect = effect.next;1045 } while (effect !== firstEffect);1046 }1047 }1048 return;1049 }1050 case ClassComponent: {1051 safelyDetachRef(current, nearestMountedAncestor);1052 const instance = current.stateNode;1053 if (typeof instance.componentWillUnmount === 'function') {1054 safelyCallComponentWillUnmount(1055 current,1056 nearestMountedAncestor,1057 instance,1058 );1059 }1060 return;1061 }1062 case HostComponent: {1063 safelyDetachRef(current, nearestMountedAncestor);1064 return;1065 }1066 case HostPortal: {1067 // TODO: this is recursive.1068 // We are also not using this parent because1069 // the portal will get pushed immediately.1070 if (supportsMutation) {1071 unmountHostComponents(1072 finishedRoot,1073 current,1074 nearestMountedAncestor,1075 renderPriorityLevel,1076 );1077 } else if (supportsPersistence) {1078 emptyPortalContainer(current);1079 }1080 return;1081 }1082 case FundamentalComponent: {1083 if (enableFundamentalAPI) {1084 const fundamentalInstance = current.stateNode;1085 if (fundamentalInstance !== null) {1086 unmountFundamentalComponent(fundamentalInstance);1087 current.stateNode = null;1088 }1089 }1090 return;1091 }1092 case DehydratedFragment: {1093 if (enableSuspenseCallback) {1094 const hydrationCallbacks = finishedRoot.hydrationCallbacks;1095 if (hydrationCallbacks !== null) {1096 const onDeleted = hydrationCallbacks.onDeleted;1097 if (onDeleted) {1098 onDeleted((current.stateNode: SuspenseInstance));1099 }1100 }1101 }1102 return;1103 }1104 case ScopeComponent: {1105 if (enableScopeAPI) {1106 safelyDetachRef(current, nearestMountedAncestor);1107 }1108 return;1109 }1110 }1111}1112function commitNestedUnmounts(1113 finishedRoot: FiberRoot,1114 root: Fiber,1115 nearestMountedAncestor: Fiber,1116 renderPriorityLevel: ReactPriorityLevel,1117): void {1118 // While we're inside a removed host node we don't want to call1119 // removeChild on the inner nodes because they're removed by the top1120 // call anyway. We also want to call componentWillUnmount on all1121 // composites before this host node is removed from the tree. Therefore1122 // we do an inner loop while we're still inside the host node.1123 let node: Fiber = root;1124 while (true) {1125 commitUnmount(1126 finishedRoot,1127 node,1128 nearestMountedAncestor,1129 renderPriorityLevel,1130 );1131 // Visit children because they may contain more composite or host nodes.1132 // Skip portals because commitUnmount() currently visits them recursively.1133 if (1134 node.child !== null &&1135 // If we use mutation we drill down into portals using commitUnmount above.1136 // If we don't use mutation we drill down into portals here instead.1137 (!supportsMutation || node.tag !== HostPortal)1138 ) {1139 node.child.return = node;1140 node = node.child;1141 continue;1142 }1143 if (node === root) {1144 return;1145 }1146 while (node.sibling === null) {1147 if (node.return === null || node.return === root) {1148 return;1149 }1150 node = node.return;1151 }1152 node.sibling.return = node.return;1153 node = node.sibling;1154 }1155}1156function detachFiberMutation(fiber: Fiber) {1157 // Cut off the return pointer to disconnect it from the tree.1158 // This enables us to detect and warn against state updates on an unmounted component.1159 // It also prevents events from bubbling from within disconnected components.1160 //1161 // Ideally, we should also clear the child pointer of the parent alternate to let this1162 // get GC:ed but we don't know which for sure which parent is the current1163 // one so we'll settle for GC:ing the subtree of this child.1164 // This child itself will be GC:ed when the parent updates the next time.1165 //1166 // Note that we can't clear child or sibling pointers yet.1167 // They're needed for passive effects and for findDOMNode.1168 // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects).1169 //1170 // Don't reset the alternate yet, either. We need that so we can detach the1171 // alternate's fields in the passive phase. Clearing the return pointer is1172 // sufficient for findDOMNode semantics.1173 fiber.return = null;1174}1175export function detachFiberAfterEffects(fiber: Fiber): void {1176 // Null out fields to improve GC for references that may be lingering (e.g. DevTools).1177 // Note that we already cleared the return pointer in detachFiberMutation().1178 fiber.alternate = null;1179 fiber.child = null;1180 fiber.deletions = null;1181 fiber.dependencies = null;1182 fiber.memoizedProps = null;1183 fiber.memoizedState = null;1184 fiber.pendingProps = null;1185 fiber.sibling = null;1186 fiber.stateNode = null;1187 fiber.updateQueue = null;1188 if (__DEV__) {1189 fiber._debugOwner = null;1190 }1191}1192function emptyPortalContainer(current: Fiber) {1193 if (!supportsPersistence) {1194 return;1195 }1196 const portal: {1197 containerInfo: Container,1198 pendingChildren: ChildSet,1199 ...1200 } = current.stateNode;1201 const {containerInfo} = portal;1202 const emptyChildSet = createContainerChildSet(containerInfo);1203 replaceContainerChildren(containerInfo, emptyChildSet);1204}1205function commitContainer(finishedWork: Fiber) {1206 if (!supportsPersistence) {1207 return;1208 }1209 switch (finishedWork.tag) {1210 case ClassComponent:1211 case HostComponent:1212 case HostText:1213 case FundamentalComponent: {1214 return;1215 }1216 case HostRoot:1217 case HostPortal: {1218 const portalOrRoot: {1219 containerInfo: Container,1220 pendingChildren: ChildSet,1221 ...1222 } = finishedWork.stateNode;1223 const {containerInfo, pendingChildren} = portalOrRoot;1224 replaceContainerChildren(containerInfo, pendingChildren);1225 return;1226 }1227 }1228 invariant(1229 false,1230 'This unit of work tag should not have side-effects. This error is ' +1231 'likely caused by a bug in React. Please file an issue.',1232 );1233}1234function getHostParentFiber(fiber: Fiber): Fiber {1235 let parent = fiber.return;1236 while (parent !== null) {1237 if (isHostParent(parent)) {1238 return parent;1239 }1240 parent = parent.return;1241 }1242 invariant(1243 false,1244 'Expected to find a host parent. This error is likely caused by a bug ' +1245 'in React. Please file an issue.',1246 );1247}1248function isHostParent(fiber: Fiber): boolean {1249 return (1250 fiber.tag === HostComponent ||1251 fiber.tag === HostRoot ||1252 fiber.tag === HostPortal1253 );1254}1255function getHostSibling(fiber: Fiber): ?Instance {1256 // We're going to search forward into the tree until we find a sibling host1257 // node. Unfortunately, if multiple insertions are done in a row we have to1258 // search past them. This leads to exponential search for the next sibling.1259 // TODO: Find a more efficient way to do this.1260 let node: Fiber = fiber;1261 siblings: while (true) {1262 // If we didn't find anything, let's try the next sibling.1263 while (node.sibling === null) {1264 if (node.return === null || isHostParent(node.return)) {1265 // If we pop out of the root or hit the parent the fiber we are the1266 // last sibling.1267 return null;1268 }1269 node = node.return;1270 }1271 node.sibling.return = node.return;1272 node = node.sibling;1273 while (1274 node.tag !== HostComponent &&1275 node.tag !== HostText &&1276 node.tag !== DehydratedFragment1277 ) {1278 // If it is not host node and, we might have a host node inside it.1279 // Try to search down until we find one.1280 if (node.flags & Placement) {1281 // If we don't have a child, try the siblings instead.1282 continue siblings;1283 }1284 // If we don't have a child, try the siblings instead.1285 // We also skip portals because they are not part of this host tree.1286 if (node.child === null || node.tag === HostPortal) {1287 continue siblings;1288 } else {1289 node.child.return = node;1290 node = node.child;1291 }1292 }1293 // Check if this host node is stable or about to be placed.1294 if (!(node.flags & Placement)) {1295 // Found it!1296 return node.stateNode;1297 }1298 }1299}1300function commitPlacement(finishedWork: Fiber): void {1301 if (!supportsMutation) {1302 return;1303 }1304 // Recursively insert all host nodes into the parent.1305 const parentFiber = getHostParentFiber(finishedWork);1306 // Note: these two variables *must* always be updated together.1307 let parent;1308 let isContainer;1309 const parentStateNode = parentFiber.stateNode;1310 switch (parentFiber.tag) {1311 case HostComponent:1312 parent = parentStateNode;1313 isContainer = false;1314 break;1315 case HostRoot:1316 parent = parentStateNode.containerInfo;1317 isContainer = true;1318 break;1319 case HostPortal:1320 parent = parentStateNode.containerInfo;1321 isContainer = true;1322 break;1323 case FundamentalComponent:1324 if (enableFundamentalAPI) {1325 parent = parentStateNode.instance;1326 isContainer = false;1327 }1328 // eslint-disable-next-line-no-fallthrough1329 default:1330 invariant(1331 false,1332 'Invalid host parent fiber. This error is likely caused by a bug ' +1333 'in React. Please file an issue.',1334 );1335 }1336 if (parentFiber.flags & ContentReset) {1337 // Reset the text content of the parent before doing any insertions1338 resetTextContent(parent);1339 // Clear ContentReset from the effect tag1340 parentFiber.flags &= ~ContentReset;1341 }1342 const before = getHostSibling(finishedWork);1343 // We only have the top Fiber that was inserted but we need to recurse down its1344 // children to find all the terminal nodes.1345 if (isContainer) {1346 insertOrAppendPlacementNodeIntoContainer(finishedWork, before, parent);1347 } else {1348 insertOrAppendPlacementNode(finishedWork, before, parent);1349 }1350}1351function insertOrAppendPlacementNodeIntoContainer(1352 node: Fiber,1353 before: ?Instance,1354 parent: Container,1355): void {1356 const {tag} = node;1357 const isHost = tag === HostComponent || tag === HostText;1358 if (isHost || (enableFundamentalAPI && tag === FundamentalComponent)) {1359 const stateNode = isHost ? node.stateNode : node.stateNode.instance;1360 if (before) {1361 insertInContainerBefore(parent, stateNode, before);1362 } else {1363 appendChildToContainer(parent, stateNode);1364 }1365 } else if (tag === HostPortal) {1366 // If the insertion itself is a portal, then we don't want to traverse1367 // down its children. Instead, we'll get insertions from each child in1368 // the portal directly.1369 } else {1370 const child = node.child;1371 if (child !== null) {1372 insertOrAppendPlacementNodeIntoContainer(child, before, parent);1373 let sibling = child.sibling;1374 while (sibling !== null) {1375 insertOrAppendPlacementNodeIntoContainer(sibling, before, parent);1376 sibling = sibling.sibling;1377 }1378 }1379 }1380}1381function insertOrAppendPlacementNode(1382 node: Fiber,1383 before: ?Instance,1384 parent: Instance,1385): void {1386 const {tag} = node;1387 const isHost = tag === HostComponent || tag === HostText;1388 if (isHost || (enableFundamentalAPI && tag === FundamentalComponent)) {1389 const stateNode = isHost ? node.stateNode : node.stateNode.instance;1390 if (before) {1391 insertBefore(parent, stateNode, before);1392 } else {1393 appendChild(parent, stateNode);1394 }1395 } else if (tag === HostPortal) {1396 // If the insertion itself is a portal, then we don't want to traverse1397 // down its children. Instead, we'll get insertions from each child in1398 // the portal directly.1399 } else {1400 const child = node.child;1401 if (child !== null) {1402 insertOrAppendPlacementNode(child, before, parent);1403 let sibling = child.sibling;1404 while (sibling !== null) {1405 insertOrAppendPlacementNode(sibling, before, parent);1406 sibling = sibling.sibling;1407 }1408 }1409 }1410}1411function unmountHostComponents(1412 finishedRoot: FiberRoot,1413 current: Fiber,1414 nearestMountedAncestor: Fiber,1415 renderPriorityLevel: ReactPriorityLevel,1416): void {1417 // We only have the top Fiber that was deleted but we need to recurse down its1418 // children to find all the terminal nodes.1419 let node: Fiber = current;1420 // Each iteration, currentParent is populated with node's host parent if not1421 // currentParentIsValid.1422 let currentParentIsValid = false;1423 // Note: these two variables *must* always be updated together.1424 let currentParent;1425 let currentParentIsContainer;1426 while (true) {1427 if (!currentParentIsValid) {1428 let parent = node.return;1429 findParent: while (true) {1430 invariant(1431 parent !== null,1432 'Expected to find a host parent. This error is likely caused by ' +1433 'a bug in React. Please file an issue.',1434 );1435 const parentStateNode = parent.stateNode;1436 switch (parent.tag) {1437 case HostComponent:1438 currentParent = parentStateNode;1439 currentParentIsContainer = false;1440 break findParent;1441 case HostRoot:1442 currentParent = parentStateNode.containerInfo;1443 currentParentIsContainer = true;1444 break findParent;1445 case HostPortal:1446 currentParent = parentStateNode.containerInfo;1447 currentParentIsContainer = true;1448 break findParent;1449 case FundamentalComponent:1450 if (enableFundamentalAPI) {1451 currentParent = parentStateNode.instance;1452 currentParentIsContainer = false;1453 }1454 }1455 parent = parent.return;1456 }1457 currentParentIsValid = true;1458 }1459 if (node.tag === HostComponent || node.tag === HostText) {1460 commitNestedUnmounts(1461 finishedRoot,1462 node,1463 nearestMountedAncestor,1464 renderPriorityLevel,1465 );1466 // After all the children have unmounted, it is now safe to remove the1467 // node from the tree.1468 if (currentParentIsContainer) {1469 removeChildFromContainer(1470 ((currentParent: any): Container),1471 (node.stateNode: Instance | TextInstance),1472 );1473 } else {1474 removeChild(1475 ((currentParent: any): Instance),1476 (node.stateNode: Instance | TextInstance),1477 );1478 }1479 // Don't visit children because we already visited them.1480 } else if (enableFundamentalAPI && node.tag === FundamentalComponent) {1481 const fundamentalNode = node.stateNode.instance;1482 commitNestedUnmounts(1483 finishedRoot,1484 node,1485 nearestMountedAncestor,1486 renderPriorityLevel,1487 );1488 // After all the children have unmounted, it is now safe to remove the1489 // node from the tree.1490 if (currentParentIsContainer) {1491 removeChildFromContainer(1492 ((currentParent: any): Container),1493 (fundamentalNode: Instance),1494 );1495 } else {1496 removeChild(1497 ((currentParent: any): Instance),1498 (fundamentalNode: Instance),1499 );1500 }1501 } else if (1502 enableSuspenseServerRenderer &&1503 node.tag === DehydratedFragment1504 ) {1505 if (enableSuspenseCallback) {1506 const hydrationCallbacks = finishedRoot.hydrationCallbacks;1507 if (hydrationCallbacks !== null) {1508 const onDeleted = hydrationCallbacks.onDeleted;1509 if (onDeleted) {1510 onDeleted((node.stateNode: SuspenseInstance));1511 }1512 }1513 }1514 // Delete the dehydrated suspense boundary and all of its content.1515 if (currentParentIsContainer) {1516 clearSuspenseBoundaryFromContainer(1517 ((currentParent: any): Container),1518 (node.stateNode: SuspenseInstance),1519 );1520 } else {1521 clearSuspenseBoundary(1522 ((currentParent: any): Instance),1523 (node.stateNode: SuspenseInstance),1524 );1525 }1526 } else if (node.tag === HostPortal) {1527 if (node.child !== null) {1528 // When we go into a portal, it becomes the parent to remove from.1529 // We will reassign it back when we pop the portal on the way up.1530 currentParent = node.stateNode.containerInfo;1531 currentParentIsContainer = true;1532 // Visit children because portals might contain host components.1533 node.child.return = node;1534 node = node.child;1535 continue;1536 }1537 } else {1538 commitUnmount(1539 finishedRoot,1540 node,1541 nearestMountedAncestor,1542 renderPriorityLevel,1543 );1544 // Visit children because we may find more host components below.1545 if (node.child !== null) {1546 node.child.return = node;1547 node = node.child;1548 continue;1549 }1550 }1551 if (node === current) {1552 return;1553 }1554 while (node.sibling === null) {1555 if (node.return === null || node.return === current) {1556 return;1557 }1558 node = node.return;1559 if (node.tag === HostPortal) {1560 // When we go out of the portal, we need to restore the parent.1561 // Since we don't keep a stack of them, we will search for it.1562 currentParentIsValid = false;1563 }1564 }1565 node.sibling.return = node.return;1566 node = node.sibling;1567 }1568}1569function commitDeletion(1570 finishedRoot: FiberRoot,1571 current: Fiber,1572 nearestMountedAncestor: Fiber,1573 renderPriorityLevel: ReactPriorityLevel,1574): void {1575 if (supportsMutation) {1576 // Recursively delete all host nodes from the parent.1577 // Detach refs and call componentWillUnmount() on the whole subtree.1578 unmountHostComponents(1579 finishedRoot,1580 current,1581 nearestMountedAncestor,1582 renderPriorityLevel,1583 );1584 } else {1585 // Detach refs and call componentWillUnmount() on the whole subtree.1586 commitNestedUnmounts(1587 finishedRoot,1588 current,1589 nearestMountedAncestor,1590 renderPriorityLevel,1591 );1592 }1593 const alternate = current.alternate;1594 detachFiberMutation(current);1595 if (alternate !== null) {1596 detachFiberMutation(alternate);1597 }1598}1599function commitWork(current: Fiber | null, finishedWork: Fiber): void {1600 if (!supportsMutation) {1601 switch (finishedWork.tag) {1602 case FunctionComponent:1603 case ForwardRef:1604 case MemoComponent:1605 case SimpleMemoComponent: {1606 // Layout effects are destroyed during the mutation phase so that all1607 // destroy functions for all fibers are called before any create functions.1608 // This prevents sibling component effects from interfering with each other,1609 // e.g. a destroy function in one component should never override a ref set1610 // by a create function in another component during the same commit.1611 if (1612 enableProfilerTimer &&1613 enableProfilerCommitHooks &&1614 finishedWork.mode & ProfileMode1615 ) {1616 try {1617 startLayoutEffectTimer();1618 commitHookEffectListUnmount(1619 HookLayout | HookHasEffect,1620 finishedWork,1621 finishedWork.return,1622 );1623 } finally {1624 recordLayoutEffectDuration(finishedWork);1625 }1626 } else {1627 commitHookEffectListUnmount(1628 HookLayout | HookHasEffect,1629 finishedWork,1630 finishedWork.return,1631 );1632 }1633 return;1634 }1635 case Profiler: {1636 return;1637 }1638 case SuspenseComponent: {1639 commitSuspenseComponent(finishedWork);1640 attachSuspenseRetryListeners(finishedWork);1641 return;1642 }1643 case SuspenseListComponent: {1644 attachSuspenseRetryListeners(finishedWork);1645 return;1646 }1647 case HostRoot: {1648 if (supportsHydration) {1649 const root: FiberRoot = finishedWork.stateNode;1650 if (root.hydrate) {1651 // We've just hydrated. No need to hydrate again.1652 root.hydrate = false;1653 commitHydratedContainer(root.containerInfo);1654 }1655 }1656 break;1657 }1658 case OffscreenComponent:1659 case LegacyHiddenComponent: {1660 return;1661 }1662 }1663 commitContainer(finishedWork);1664 return;1665 }1666 switch (finishedWork.tag) {1667 case FunctionComponent:1668 case ForwardRef:1669 case MemoComponent:1670 case SimpleMemoComponent: {1671 // Layout effects are destroyed during the mutation phase so that all1672 // destroy functions for all fibers are called before any create functions.1673 // This prevents sibling component effects from interfering with each other,1674 // e.g. a destroy function in one component should never override a ref set1675 // by a create function in another component during the same commit.1676 if (1677 enableProfilerTimer &&1678 enableProfilerCommitHooks &&1679 finishedWork.mode & ProfileMode1680 ) {1681 try {1682 startLayoutEffectTimer();1683 commitHookEffectListUnmount(1684 HookLayout | HookHasEffect,1685 finishedWork,1686 finishedWork.return,1687 );1688 } finally {1689 recordLayoutEffectDuration(finishedWork);1690 }1691 } else {1692 commitHookEffectListUnmount(1693 HookLayout | HookHasEffect,1694 finishedWork,1695 finishedWork.return,1696 );1697 }1698 return;1699 }1700 case ClassComponent: {1701 return;1702 }1703 case HostComponent: {1704 const instance: Instance = finishedWork.stateNode;1705 if (instance != null) {1706 // Commit the work prepared earlier.1707 const newProps = finishedWork.memoizedProps;1708 // For hydration we reuse the update path but we treat the oldProps1709 // as the newProps. The updatePayload will contain the real change in1710 // this case.1711 const oldProps = current !== null ? current.memoizedProps : newProps;1712 const type = finishedWork.type;1713 // TODO: Type the updateQueue to be specific to host components.1714 const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any);1715 finishedWork.updateQueue = null;1716 if (updatePayload !== null) {1717 commitUpdate(1718 instance,1719 updatePayload,1720 type,1721 oldProps,1722 newProps,1723 finishedWork,1724 );1725 }1726 }1727 return;1728 }1729 case HostText: {1730 invariant(1731 finishedWork.stateNode !== null,1732 'This should have a text node initialized. This error is likely ' +1733 'caused by a bug in React. Please file an issue.',1734 );1735 const textInstance: TextInstance = finishedWork.stateNode;1736 const newText: string = finishedWork.memoizedProps;1737 // For hydration we reuse the update path but we treat the oldProps1738 // as the newProps. The updatePayload will contain the real change in1739 // this case.1740 const oldText: string =1741 current !== null ? current.memoizedProps : newText;1742 commitTextUpdate(textInstance, oldText, newText);1743 return;1744 }1745 case HostRoot: {1746 if (supportsHydration) {1747 const root: FiberRoot = finishedWork.stateNode;1748 if (root.hydrate) {1749 // We've just hydrated. No need to hydrate again.1750 root.hydrate = false;1751 commitHydratedContainer(root.containerInfo);1752 }1753 }1754 return;1755 }1756 case Profiler: {1757 return;1758 }1759 case SuspenseComponent: {1760 commitSuspenseComponent(finishedWork);1761 attachSuspenseRetryListeners(finishedWork);1762 return;1763 }1764 case SuspenseListComponent: {1765 attachSuspenseRetryListeners(finishedWork);1766 return;1767 }1768 case IncompleteClassComponent: {1769 return;1770 }1771 case FundamentalComponent: {1772 if (enableFundamentalAPI) {1773 const fundamentalInstance = finishedWork.stateNode;1774 updateFundamentalComponent(fundamentalInstance);1775 return;1776 }1777 break;1778 }1779 case ScopeComponent: {1780 if (enableScopeAPI) {1781 const scopeInstance = finishedWork.stateNode;1782 prepareScopeUpdate(scopeInstance, finishedWork);1783 return;1784 }1785 break;1786 }1787 case OffscreenComponent:1788 case LegacyHiddenComponent: {1789 const newState: OffscreenState | null = finishedWork.memoizedState;1790 const isHidden = newState !== null;1791 hideOrUnhideAllChildren(finishedWork, isHidden);1792 return;1793 }1794 }1795 invariant(1796 false,1797 'This unit of work tag should not have side-effects. This error is ' +1798 'likely caused by a bug in React. Please file an issue.',1799 );1800}1801function commitSuspenseComponent(finishedWork: Fiber) {1802 const newState: SuspenseState | null = finishedWork.memoizedState;1803 if (newState !== null) {1804 markCommitTimeOfFallback();1805 if (supportsMutation) {1806 // Hide the Offscreen component that contains the primary children. TODO:1807 // Ideally, this effect would have been scheduled on the Offscreen fiber1808 // itself. That's how unhiding works: the Offscreen component schedules an1809 // effect on itself. However, in this case, the component didn't complete,1810 // so the fiber was never added to the effect list in the normal path. We1811 // could have appended it to the effect list in the Suspense component's1812 // second pass, but doing it this way is less complicated. This would be1813 // simpler if we got rid of the effect list and traversed the tree, like1814 // we're planning to do.1815 const primaryChildParent: Fiber = (finishedWork.child: any);1816 hideOrUnhideAllChildren(primaryChildParent, true);1817 }1818 }1819 if (enableSuspenseCallback && newState !== null) {1820 const suspenseCallback = finishedWork.memoizedProps.suspenseCallback;1821 if (typeof suspenseCallback === 'function') {1822 const wakeables: Set<Wakeable> | null = (finishedWork.updateQueue: any);1823 if (wakeables !== null) {1824 suspenseCallback(new Set(wakeables));1825 }1826 } else if (__DEV__) {1827 if (suspenseCallback !== undefined) {1828 console.error('Unexpected type for suspenseCallback.');1829 }1830 }1831 }1832}1833function commitSuspenseHydrationCallbacks(1834 finishedRoot: FiberRoot,1835 finishedWork: Fiber,1836) {1837 if (!supportsHydration) {1838 return;1839 }1840 const newState: SuspenseState | null = finishedWork.memoizedState;1841 if (newState === null) {1842 const current = finishedWork.alternate;1843 if (current !== null) {1844 const prevState: SuspenseState | null = current.memoizedState;1845 if (prevState !== null) {1846 const suspenseInstance = prevState.dehydrated;1847 if (suspenseInstance !== null) {1848 commitHydratedSuspenseInstance(suspenseInstance);1849 if (enableSuspenseCallback) {1850 const hydrationCallbacks = finishedRoot.hydrationCallbacks;1851 if (hydrationCallbacks !== null) {1852 const onHydrated = hydrationCallbacks.onHydrated;1853 if (onHydrated) {1854 onHydrated(suspenseInstance);1855 }1856 }1857 }1858 }1859 }1860 }1861 }1862}1863function attachSuspenseRetryListeners(finishedWork: Fiber) {1864 // If this boundary just timed out, then it will have a set of wakeables.1865 // For each wakeable, attach a listener so that when it resolves, React1866 // attempts to re-render the boundary in the primary (pre-timeout) state.1867 const wakeables: Set<Wakeable> | null = (finishedWork.updateQueue: any);1868 if (wakeables !== null) {1869 finishedWork.updateQueue = null;1870 let retryCache = finishedWork.stateNode;1871 if (retryCache === null) {1872 retryCache = finishedWork.stateNode = new PossiblyWeakSet();1873 }1874 wakeables.forEach(wakeable => {1875 // Memoize using the boundary fiber to prevent redundant listeners.1876 let retry = resolveRetryWakeable.bind(null, finishedWork, wakeable);1877 if (!retryCache.has(wakeable)) {1878 if (enableSchedulerTracing) {1879 if (wakeable.__reactDoNotTraceInteractions !== true) {1880 retry = Schedule_tracing_wrap(retry);1881 }1882 }1883 retryCache.add(wakeable);1884 wakeable.then(retry, retry);1885 }1886 });1887 }1888}1889// This function detects when a Suspense boundary goes from visible to hidden.1890// It returns false if the boundary is already hidden.1891// TODO: Use an effect tag.1892export function isSuspenseBoundaryBeingHidden(1893 current: Fiber | null,1894 finishedWork: Fiber,1895): boolean {1896 if (current !== null) {1897 const oldState: SuspenseState | null = current.memoizedState;1898 if (oldState === null || oldState.dehydrated !== null) {1899 const newState: SuspenseState | null = finishedWork.memoizedState;1900 return newState !== null && newState.dehydrated === null;1901 }1902 }1903 return false;1904}1905function commitResetTextContent(current: Fiber) {1906 if (!supportsMutation) {...
ReactFiberCommitWork.old.js
Source:ReactFiberCommitWork.old.js
...944 }945 } // This function detects when a Suspense boundary goes from visible to hidden.946 // It returns false if the boundary is already hidden.947 // TODO: Use an effect tag.948 function isSuspenseBoundaryBeingHidden(current, finishedWork) {949 if (current !== null) {950 var oldState = current.memoizedState;951 if (oldState === null || oldState.dehydrated !== null) {952 var newState = finishedWork.memoizedState;953 return newState !== null && newState.dehydrated === null;954 }955 }956 return false;957 }958 function commitResetTextContent(current) {959 resetTextContent(current.stateNode);...
ReactFiberCommitWork.js
Source:ReactFiberCommitWork.js
1import {2 FunctionComponent,3 ForwardRef,4 ClassComponent,5 HostRoot,6 HostComponent,7 HostText,8 HostPortal,9 IncompleteClassComponent,10 SimpleMemoComponent,11 Block,12 FundamentalComponent,13 DehydratedFragment,14 MemoComponent,15 SuspenseComponent,16 OffscreenComponent,17 LegacyHiddenComponent,18} from './ReactWorkTags';19import { Snapshot, ContentReset, Placement } from './ReactFiberFlags';20import { resolveDefaultProps } from './ReactFiberLazyComponent';21import {22 clearContainer,23 resetTextContent,24 insertInContainerBefore,25 appendChildToContainer,26 commitUpdate,27 commitTextUpdate,28} from './ReactFiberHostConfig';29import {30 NoFlags as NoHookEffect,31 HasEffect as HookHasEffect,32 Layout as HookLayout,33 Passive as HookPassive,34} from './ReactHookEffectTags';35const invariant = require('invariant');36const isSuspenseBoundaryBeingHidden = (current, finishedWork) => {37 if (current !== null) {38 const oldState = current.memoizedState;39 if (oldState === null || oldState.dehydrated !== null) {40 const newState = finishedWork.memoizedState;41 return newState !== null && newState.dehydrated === null;42 }43 }44 return false;45};46const commitBeforeMutationLifeCycles = (current, finishedWork) => {47 switch (finishedWork.tag) {48 case FunctionComponent:49 case ForwardRef:50 case SimpleMemoComponent:51 case Block: {52 return;53 }54 case ClassComponent: {55 if (finishedWork.flags & Snapshot) {56 if (current !== null) {57 const prevProps = current.memoizedProps;58 const prevState = current.memoizedState;59 const instance = finishedWork.stateNode;60 const snapshot = instance.getSnapshotBeforeUpdate(61 finishedWork.elementType === finishedWork.type62 ? prevProps63 : resolveDefaultProps(finishedWork.type, prevProps),64 prevState65 );66 instance.__reactInternalSnapshotBeforeUpdate = snapshot;67 }68 }69 return;70 }71 case HostRoot: {72 if (finishedWork.flags & Snapshot) {73 const root = finishedWork.stateNode;74 clearContainer(root.containerInfo);75 }76 return;77 }78 case HostComponent:79 case HostText:80 case HostPortal:81 case IncompleteClassComponent:82 return;83 }84 invariant(85 false,86 'This unit of work tag should not have side-effects. This error is ' +87 'likely caused by a bug in React. Please file an issue.'88 );89};90const commitResetTextContent = (current) => {91 resetTextContent(current.stateNode);92};93const commitDetachRef = (current) => {94 const currentRef = current.ref;95 if (currentRef !== null) {96 if (typeof currentRef === 'function') {97 currentRef(null);98 } else {99 currentRef.current = null;100 }101 }102};103const isHostParent = (fiber) => {104 return (105 fiber.tag === HostComponent ||106 fiber.tag === HostRoot ||107 fiber.tag === HostPortal108 );109};110const getHostParentFiber = (fiber) => {111 let parent = fiber.return;112 while (parent !== null) {113 if (isHostParent(parent)) {114 return parent;115 }116 parent = parent.return;117 }118 invariant(119 false,120 'Expected to find a host parent. This error is likely caused by a bug ' +121 'in React. Please file an issue.'122 );123};124const getHostSibling = (fiber) => {125 let node = fiber;126 while (true) {127 while (node.sibling === null) {128 if (node.return === null || isHostParent(node.return)) return null;129 node = node.return;130 }131 node.sibling.return = node.return;132 node = node.sibling;133 let shouldRun = true;134 while (135 node.tag !== HostComponent &&136 node.tag !== HostText &&137 node.tag !== DehydratedFragment &&138 shouldRun139 ) {140 if (node.flags & Placement) {141 shouldRun = false;142 }143 if (node.child === null || node.tag === HostPortal) {144 shouldRun = false;145 } else {146 node.child.return = node;147 node = node.child;148 }149 }150 if (!(node.flags & Placement)) {151 return node.stateNode;152 }153 }154};155const insertOrAppendPlacementNodeIntoContainer = (node, before, parent) => {156 const { tag } = node;157 const isHost = tag === HostComponent || tag === HostText;158 if (isHost) {159 const stateNode = isHost ? node.stateNode : node.stateNode.instance;160 if (before) {161 insertInContainerBefore(parent, stateNode, before);162 } else {163 appendChildToContainer(parent, stateNode);164 }165 } else if (tag === HostPortal) {166 //167 } else {168 const child = node.child;169 if (child !== null) {170 insertOrAppendPlacementNodeIntoContainer(child, before, parent);171 let sibling = child.sibling;172 while (sibling !== null) {173 insertOrAppendPlacementNodeIntoContainer(sibling, before, parent);174 sibling = sibling.sibling;175 }176 }177 }178};179const insertOrAppendPlacementNode = (node, before, parent) => {180 const { tag } = node;181 const isHost = tag === HostComponent || tag === HostText;182 if (isHost) {183 const stateNode = isHost ? node.stateNode : node.stateNode.instance;184 if (before) {185 parent.insertBefore(stateNode, before);186 } else {187 parent.appendChild(stateNode);188 }189 } else if (tag === HostPortal) {190 // If the insertion itself is a portal, then we don't want to traverse191 // down its children. Instead, we'll get insertions from each child in192 // the portal directly.193 } else {194 const child = node.child;195 if (child !== null) {196 insertOrAppendPlacementNode(child, before, parent);197 let sibling = child.sibling;198 while (sibling !== null) {199 insertOrAppendPlacementNode(sibling, before, parent);200 sibling = sibling.sibling;201 }202 }203 }204};205const commitPlacement = (finishedWork) => {206 const parentFiber = getHostParentFiber(finishedWork);207 let parent;208 let isContainer;209 const parentStateNode = parentFiber.stateNode;210 switch (parentFiber.tag) {211 case HostComponent:212 parent = parentStateNode;213 isContainer = false;214 break;215 case HostRoot:216 parent = parentStateNode.containerInfo;217 isContainer = true;218 break;219 case HostPortal:220 parent = parentStateNode.containerInfo;221 isContainer = true;222 break;223 case FundamentalComponent:224 default:225 invariant(226 false,227 'Invalid host parent fiber. This error is likely caused by a bug ' +228 'in React. Please file an issue.'229 );230 }231 if (parentFiber.flags & ContentReset) {232 resetTextContent(parent);233 parentFiber.flags &= ~ContentReset;234 }235 const before = getHostSibling(finishedWork);236 if (isContainer) {237 insertOrAppendPlacementNodeIntoContainer(finishedWork, before, parent);238 } else {239 insertOrAppendPlacementNode(finishedWork, before, parent);240 }241};242const commitHookEffectListUnmount = (tag, finishedWork) => {243 const updateQueue = finishedWork.updateQueue;244 const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;245 if (lastEffect !== null) {246 const firstEffect = lastEffect.next;247 let effect = firstEffect;248 do {249 if ((effect.tag & tag) === tag) {250 const destroy = effect.destroy;251 effect.destroy = undefined;252 if (destroy !== undefined) {253 destroy();254 }255 }256 effect = effect.next;257 } while (effect !== firstEffect);258 }259};260const commitWork = (current, finishedWork) => {261 switch (finishedWork.tag) {262 case FunctionComponent:263 case ForwardRef:264 case MemoComponent:265 case SimpleMemoComponent:266 case Block: {267 commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);268 return;269 }270 case ClassComponent: {271 return;272 }273 case HostComponent: {274 const instance = finishedWork.stateNode;275 if (instance != null) {276 const newProps = finishedWork.memoizedProps;277 const oldProps = current !== null ? current.memoizedProps : newProps;278 const type = finishedWork.type;279 const updatePayload = finishedWork.updateQueue;280 finishedWork.updateQueue = null;281 if (updatePayload !== null) {282 commitUpdate(283 instance,284 updatePayload,285 type,286 oldProps,287 newProps,288 finishedWork289 );290 }291 }292 return;293 }294 case HostText: {295 invariant(296 finishedWork.stateNode !== null,297 'This should have a text node initialized. This error is likely ' +298 'caused by a bug in React. Please file an issue.'299 );300 const textInstance = finishedWork.stateNode;301 const newText = finishedWork.memoizedProps;302 const oldText = current !== null ? current.memoizedProps : newText;303 commitTextUpdate(textInstance, oldText, newText);304 return;305 }306 case HostRoot: {307 const root = finishedWork.stateNode;308 if (root.hydrate) {309 root.hydrate = false;310 commitHydratedContainer(root.containerInfo);311 }312 return;313 }314 // case SuspenseComponent: {315 // commitSuspenseComponent(finishedWork);316 // attachSuspenseRetryListeners(finishedWork);317 // return;318 // }319 // case IncompleteClassComponent: {320 // return;321 // }322 // case FundamentalComponent: {323 // break;324 // }325 // case OffscreenComponent:326 // case LegacyHiddenComponent: {327 // const newState = finishedWork.memoizedState;328 // const isHidden = newState !== null;329 // hideOrUnhideAllChildren(finishedWork, isHidden);330 // return;331 // }332 }333 invariant(334 false,335 'This unit of work tag should not have side-effects. This error is ' +336 'likely caused by a bug in React. Please file an issue.'337 );338};339const unmountHostComponents = (340 finishedRoot,341 current,342 renderPriorityLevel343) => {};344const detachFiberMutation = (fiber) => {345 fiber.alternate = null;346 fiber.child = null;347 fiber.dependencies = null;348 fiber.firstEffect = null;349 fiber.lastEffect = null;350 fiber.memoizedProps = null;351 fiber.memoizedState = null;352 fiber.pendingProps = null;353 fiber.return = null;354 fiber.updateQueue = null;355};356const commitDeletion = (finishedRoot, current, renderPriorityLevel) => {357 unmountHostComponents(finishedRoot, current, renderPriorityLevel);358 const alternate = current.alternate;359 detachFiberMutation(current);360 if (alternate !== null) {361 detachFiberMutation(alternate);362 }363};364export {365 isSuspenseBoundaryBeingHidden,366 commitBeforeMutationLifeCycles,367 commitResetTextContent,368 commitDetachRef,369 commitPlacement,370 commitWork,371 commitDeletion,...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const isHidden = await page.evaluate(() => window._playwrightInternals.isSuspenseBoundaryBeingHidden(document.getElementById('hplogo')));7 console.log(isHidden);8 await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const context = await browser.newContext();14 const page = await context.newPage();15 const isHidden = await page.evaluate(() => window._playwrightInternals.isSuspenseBoundaryBeingHidden(document.getElementById('hplogo')));16 console.log(isHidden);17 await browser.close();18})();19const { chromium } = require('playwright');20(async () => {21 const browser = await chromium.launch();22 const context = await browser.newContext();23 const page = await context.newPage();24 const isHidden = await page.evaluate(() => window._playwrightInternals.isSuspenseBoundaryBeingHidden(document.getElementById('hplogo')));25 console.log(isHidden);26 await browser.close();27})();28const { chromium } = require('playwright');29(async () => {30 const browser = await chromium.launch();31 const context = await browser.newContext();32 const page = await context.newPage();33 const isHidden = await page.evaluate(() => window._playwrightInternals.isSuspenseBoundaryBeingHidden(document.getElementById('hplogo')));34 console.log(isHidden);35 await browser.close();36})();37const { chromium } = require('playwright');38(async () => {39 const browser = await chromium.launch();40 const context = await browser.newContext();41 const page = await context.newPage();42 await page.goto('
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.waitForLoadState('load');7 await page.screenshot({ path: 'example.png' });8 await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const context = await browser.newContext();14 const page = await context.newPage();15 await page.waitForLoadState('load');16 const isHidden = await page.isSuspenseBoundaryBeingHidden();17 console.log(isHidden);18 await browser.close();19})();20const { chromium } = require('playwright');21(async () => {22 const browser = await chromium.launch();23 const context = await browser.newContext();24 const page = await context.newPage();25 await page.waitForLoadState('load');26 const isHidden = await page.isSuspenseBoundaryBeingHidden();27 console.log(isHidden);
Using AI Code Generation
1const { chromium } = require('playwright');2const { isSuspenseBoundaryBeingHidden } = require('playwright/lib/internal/api');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.waitForSelector('text=Loading...');8 const isHidden = await isSuspenseBoundaryBeingHidden(page, 'text=Loading...');9 console.log('isHidden', isHidden);10 await browser.close();11})();
Using AI Code Generation
1const { isSuspenseBoundaryBeingHidden } = require('@playwright/test/lib/internal/inspectorHelper');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 await page.waitForTimeout(2000);7 console.log(await isSuspenseBoundaryBeingHidden(page, 'main'));8 await browser.close();9})();10The test() method is used to write tests. The test() method takes two arguments:11const { test, expect } = require('@playwright/test');12test('text is displayed', async ({ page }) => {13 const text = await page.textContent('h1');14 expect(text).toBe('Hello, world!');15});16The describe() method is used to group tests. The describe() method takes two arguments:
Using AI Code Generation
1const { isSuspenseBoundaryBeingHidden } = require('playwright/lib/client/supplements/har/harTracer');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.click('text=Sign in');8 await page.waitForLoadState('networkidle');9 await page.screenshot({ path: `example.png` });10 console.log(isSuspenseBoundaryBeingHidden(page));11 await browser.close();12})();
Using AI Code Generation
1const { isSuspenseBoundaryBeingHidden } = require('@playwright/test/lib/server/supplements/recorderSupplement');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4 await page.click('text=Get started');5 await page.click('text=Docs');6 await page.click('text=API');7 await page.click('text=Page');8 await page.click('text=page.goto');9 console.log(await isSuspenseBoundaryBeingHidden(page, 'docs-ui'));10});11const { isSuspenseBoundaryBeingHidden } = require('@playwright/test/lib/server/supplements/recorderSupplement');12const { test } = require('@playwright/test');13test('test', async ({ page }) => {14 await page.click('text=Get started');15 await page.click('text=Docs');16 await page.click('text=API');17 await page.click('text=Page');18 await page.click('text=page.goto');19 console.log(await isSuspenseBoundaryBeingHidden(page, 'docs-ui'));20});
Using AI Code Generation
1const { isSuspenseBoundaryBeingHidden } = require("@playwright/test/lib/server/frames");2const { test } = require('@playwright/test');3test('should test isSuspenseBoundaryBeingHidden method', async ({ page }) => {4 const isHidden = await isSuspenseBoundaryBeingHidden(page.mainFrame(), 'text=Get started');5 console.log(isHidden);6});
Using AI Code Generation
1const { isSuspenseBoundaryBeingHidden } = require('playwright-core/lib/server/supplements/recorderSupplement/recorderSupplement.js');2const { page } = require('playwright-core/lib/server/supplements/recorderSupplement/recorderSupplement.js');3(async () => {4 await page.fill('input[type="text"]', 'Hello World');5 await page.click('input[type="submit"]');6 const isHidden = await isSuspenseBoundaryBeingHidden();7 console.log(isHidden);8})();
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!