Best JavaScript code snippet using playwright-internal
ReactFiberBeginWork.old.js
Source:ReactFiberBeginWork.old.js
...580 // Schedule this fiber to re-render at offscreen priority. Then bailout.581 if (enableSchedulerTracing) {582 markSpawnedWork((OffscreenLane: Lane));583 }584 workInProgress.lanes = workInProgress.childLanes = laneToLanes(585 OffscreenLane,586 );587 const nextState: OffscreenState = {588 baseLanes: nextBaseLanes,589 };590 workInProgress.memoizedState = nextState;591 // We're about to bail out, but we need to push this to the stack anyway592 // to avoid a push/pop misalignment.593 pushRenderLanes(workInProgress, nextBaseLanes);594 return null;595 } else {596 // Rendering at offscreen, so we can clear the base lanes.597 const nextState: OffscreenState = {598 baseLanes: NoLanes,599 };600 workInProgress.memoizedState = nextState;601 // Push the lanes that were skipped when we bailed out.602 const subtreeRenderLanes =603 prevState !== null ? prevState.baseLanes : renderLanes;604 pushRenderLanes(workInProgress, subtreeRenderLanes);605 }606 } else {607 let subtreeRenderLanes;608 if (prevState !== null) {609 subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes);610 // Since we're not hidden anymore, reset the state611 workInProgress.memoizedState = null;612 } else {613 // We weren't previously hidden, and we still aren't, so there's nothing614 // special to do. Need to push to the stack regardless, though, to avoid615 // a push/pop misalignment.616 subtreeRenderLanes = renderLanes;617 }618 pushRenderLanes(workInProgress, subtreeRenderLanes);619 }620 reconcileChildren(current, workInProgress, nextChildren, renderLanes);621 return workInProgress.child;622}623// Note: These happen to have identical begin phases, for now. We shouldn't hold624// ourselves to this constraint, though. If the behavior diverges, we should625// fork the function.626const updateLegacyHiddenComponent = updateOffscreenComponent;627function updateFragment(628 current: Fiber | null,629 workInProgress: Fiber,630 renderLanes: Lanes,631) {632 const nextChildren = workInProgress.pendingProps;633 reconcileChildren(current, workInProgress, nextChildren, renderLanes);634 return workInProgress.child;635}636function updateMode(637 current: Fiber | null,638 workInProgress: Fiber,639 renderLanes: Lanes,640) {641 const nextChildren = workInProgress.pendingProps.children;642 reconcileChildren(current, workInProgress, nextChildren, renderLanes);643 return workInProgress.child;644}645function updateProfiler(646 current: Fiber | null,647 workInProgress: Fiber,648 renderLanes: Lanes,649) {650 if (enableProfilerTimer) {651 workInProgress.flags |= Update;652 // Reset effect durations for the next eventual effect phase.653 // These are reset during render to allow the DevTools commit hook a chance to read them,654 const stateNode = workInProgress.stateNode;655 stateNode.effectDuration = 0;656 stateNode.passiveEffectDuration = 0;657 }658 const nextProps = workInProgress.pendingProps;659 const nextChildren = nextProps.children;660 reconcileChildren(current, workInProgress, nextChildren, renderLanes);661 return workInProgress.child;662}663function markRef(current: Fiber | null, workInProgress: Fiber) {664 const ref = workInProgress.ref;665 if (666 (current === null && ref !== null) ||667 (current !== null && current.ref !== ref)668 ) {669 // Schedule a Ref effect670 workInProgress.flags |= Ref;671 }672}673// function Componenté没æçå½å¨æ674// function A () {675// return <B></B>676// }677function updateFunctionComponent(678 current,679 workInProgress,680 Component,681 nextProps: any,682 renderLanes,683) {684 if (__DEV__) {685 if (workInProgress.type !== workInProgress.elementType) {686 // Lazy component props can't be validated in createElement687 // because they're only guaranteed to be resolved here.688 const innerPropTypes = Component.propTypes;689 if (innerPropTypes) {690 checkPropTypes(691 innerPropTypes,692 nextProps, // Resolved props693 'prop',694 getComponentName(Component),695 );696 }697 }698 }699 let context;700 if (!disableLegacyContext) {701 const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);702 context = getMaskedContext(workInProgress, unmaskedContext);703 }704 let nextChildren;705 prepareToReadContext(workInProgress, renderLanes);706 if (__DEV__) {707 ReactCurrentOwner.current = workInProgress;708 setIsRendering(true);709 // 注å
¥hooks710 nextChildren = renderWithHooks(711 current,712 workInProgress,713 Component,714 nextProps,715 context,716 renderLanes,717 );718 if (719 debugRenderPhaseSideEffectsForStrictMode &&720 workInProgress.mode & StrictMode721 ) {722 disableLogs();723 try {724 nextChildren = renderWithHooks(725 current,726 workInProgress,727 Component,728 nextProps,729 context,730 renderLanes,731 );732 } finally {733 reenableLogs();734 }735 }736 setIsRendering(false);737 } else {738 // render()739 nextChildren = renderWithHooks(740 current,741 workInProgress,742 Component,743 nextProps,744 context,745 renderLanes,746 );747 }748 // å¯ä»¥å¤ç¨749 if (current !== null && !didReceiveUpdate) {750 bailoutHooks(current, workInProgress, renderLanes);751 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);752 }753 // React DevTools reads this flag.754 workInProgress.flags |= PerformedWork;755 reconcileChildren(current, workInProgress, nextChildren, renderLanes);756 return workInProgress.child;757}758function updateBlock<Props, Data>(759 current: Fiber | null,760 workInProgress: Fiber,761 block: BlockComponent<Props, Data>,762 nextProps: any,763 renderLanes: Lanes,764) {765 // TODO: current can be non-null here even if the component766 // hasn't yet mounted. This happens after the first render suspends.767 // We'll need to figure out if this is fine or can cause issues.768 const render = block._render;769 const data = block._data;770 // The rest is a fork of updateFunctionComponent771 let nextChildren;772 prepareToReadContext(workInProgress, renderLanes);773 if (__DEV__) {774 ReactCurrentOwner.current = workInProgress;775 setIsRendering(true);776 nextChildren = renderWithHooks(777 current,778 workInProgress,779 render,780 nextProps,781 data,782 renderLanes,783 );784 if (785 debugRenderPhaseSideEffectsForStrictMode &&786 workInProgress.mode & StrictMode787 ) {788 disableLogs();789 try {790 nextChildren = renderWithHooks(791 current,792 workInProgress,793 render,794 nextProps,795 data,796 renderLanes,797 );798 } finally {799 reenableLogs();800 }801 }802 setIsRendering(false);803 } else {804 nextChildren = renderWithHooks(805 current,806 workInProgress,807 render,808 nextProps,809 data,810 renderLanes,811 );812 }813 if (current !== null && !didReceiveUpdate) {814 bailoutHooks(current, workInProgress, renderLanes);815 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);816 }817 // React DevTools reads this flag.818 workInProgress.flags |= PerformedWork;819 reconcileChildren(current, workInProgress, nextChildren, renderLanes);820 return workInProgress.child;821}822function updateClassComponent(823 current: Fiber | null,824 workInProgress: Fiber,825 Component: any,826 nextProps: any,827 renderLanes: Lanes,828) {829 if (__DEV__) {830 if (workInProgress.type !== workInProgress.elementType) {831 // Lazy component props can't be validated in createElement832 // because they're only guaranteed to be resolved here.833 const innerPropTypes = Component.propTypes;834 if (innerPropTypes) {835 checkPropTypes(836 innerPropTypes,837 nextProps, // Resolved props838 'prop',839 getComponentName(Component),840 );841 }842 }843 }844 // Push context providers early to prevent context stack mismatches.845 // During mounting we don't know the child context yet as the instance doesn't exist.846 // We will invalidate the child context in finishClassComponent() right after rendering.847 // context è·¨ç»ä»¶ä¼ éæ°æ®ã848 let hasContext;849 if (isLegacyContextProvider(Component)) {850 hasContext = true;851 pushLegacyContextProvider(workInProgress);852 } else {853 hasContext = false;854 }855 prepareToReadContext(workInProgress, renderLanes);856 // stateNode éåå¨çæ¯çæ£çDomå
ç´ 857 const instance = workInProgress.stateNode;858 let shouldUpdate;859 // 第ä¸æ¬¡æ§è¡860 if (instance === null) {861 if (current !== null) {862 // è¿ä¸ªèç¹ä¹åä»æªåå¨è¿ï¼flags设置为Placementï¼ä¹å°±æ¯æ°å¢863 // A class component without an instance only mounts if it suspended864 // inside a non-concurrent tree, in an inconsistent state. We want to865 // treat it like a new mount, even though an empty version of it already866 // committed. Disconnect the alternate pointers.867 current.alternate = null;868 workInProgress.alternate = null;869 // Since this is conceptually a new fiber, schedule a Placement effect870 workInProgress.flags |= Placement;871 }872 // In the initial pass we might need to construct the instance.873 // æ§è¡constructor çå½å¨æ874 // class A extends Component {875 // constructor(){876 // }877 // }878 constructClassInstance(workInProgress, Component, nextProps);879 // 1. è°ç¨getDerivedStateFromProps880 // 2. è°ç¨UNSAFE_componentWillMount881 mountClassInstance(workInProgress, Component, nextProps, renderLanes);882 shouldUpdate = true;883 } else if (current === null) {884 // ä¸æ¯ç¬¬ä¸æ¬¡æ§è¡ä½current === nullï¼èµ°ç¹æ®çå¤ç¨æ¹å¼885 // In a resume, we'll already have an instance we can reuse.886 // ä¼æ§è¡willMountï¼shouldComponentUpdateçççå½å¨æ887 shouldUpdate = resumeMountClassInstance(888 workInProgress,889 Component,890 nextProps,891 renderLanes,892 );893 } else {894 // ä¸æ¯ç¬¬ä¸æ¬¡æ§è¡ä½current !== null, æ´æ°é¶æ®µ895 // æ§è¡ä¸é¢ççå½å¨æ896 // æ§è¡componentWillReceivePropsãç¶çº§ä¼ éçpropsååäºï¼componentWillReceivePropsä¼æ§è¡897 // å¦æcomponentDidUpdateåå¨ï¼æä¸Flagsï¼ `workInProgress.flags |= Update //æä½æï¼æä¸updateæ è®°`898 // æ§è¡getDerivedStateFromProps899 // æ§è¡shouldComponentUpdate900 // æ§è¡componentWillUpdate901 shouldUpdate = updateClassInstance(902 current,903 workInProgress,904 Component,905 nextProps,906 renderLanes,907 );908 }909 // æ§è¡ render() çå½å¨æãåFiberä»Renderå¾æ¥910 const nextUnitOfWork = finishClassComponent(911 current,912 workInProgress,913 Component,914 shouldUpdate,915 hasContext,916 renderLanes,917 );918 if (__DEV__) {919 const inst = workInProgress.stateNode;920 if (shouldUpdate && inst.props !== nextProps) {921 if (!didWarnAboutReassigningProps) {922 console.error(923 'It looks like %s is reassigning its own `this.props` while rendering. ' +924 'This is not supported and can lead to confusing bugs.',925 getComponentName(workInProgress.type) || 'a component',926 );927 }928 didWarnAboutReassigningProps = true;929 }930 }931 return nextUnitOfWork;932}933function finishClassComponent(934 current: Fiber | null,935 workInProgress: Fiber,936 Component: any,937 shouldUpdate: boolean,938 hasContext: boolean,939 renderLanes: Lanes,940) {941 // Refs should update even if shouldComponentUpdate returns false942 markRef(current, workInProgress);943 const didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags;944 if (!shouldUpdate && !didCaptureError) {945 // Context providers should defer to sCU for rendering946 if (hasContext) {947 invalidateContextProvider(workInProgress, Component, false);948 }949 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);950 }951 const instance = workInProgress.stateNode;952 // Rerender953 ReactCurrentOwner.current = workInProgress;954 let nextChildren;955 if (956 didCaptureError &&957 typeof Component.getDerivedStateFromError !== 'function'958 ) {959 // If we captured an error, but getDerivedStateFromError is not defined,960 // unmount all the children. componentDidCatch will schedule an update to961 // re-render a fallback. This is temporary until we migrate everyone to962 // the new API.963 // TODO: Warn in a future release.964 nextChildren = null;965 if (enableProfilerTimer) {966 stopProfilerTimerIfRunning(workInProgress);967 }968 } else {969 if (__DEV__) {970 setIsRendering(true);971 nextChildren = instance.render();972 if (973 debugRenderPhaseSideEffectsForStrictMode &&974 workInProgress.mode & StrictMode975 ) {976 disableLogs();977 try {978 instance.render();979 } finally {980 reenableLogs();981 }982 }983 setIsRendering(false);984 } else {985 nextChildren = instance.render();986 }987 }988 // React DevTools reads this flag.989 workInProgress.flags |= PerformedWork;990 if (current !== null && didCaptureError) {991 // If we're recovering from an error, reconcile without reusing any of992 // the existing children. Conceptually, the normal children and the children993 // that are shown on error are two different sets, so we shouldn't reuse994 // normal children even if their identities match.995 forceUnmountCurrentAndReconcile(996 current,997 workInProgress,998 nextChildren,999 renderLanes,1000 );1001 } else {1002 reconcileChildren(current, workInProgress, nextChildren, renderLanes);1003 }1004 // Memoize state using the values we just used to render.1005 // TODO: Restructure so we never read values from the instance.1006 workInProgress.memoizedState = instance.state;1007 // The context might have changed so we need to recalculate it.1008 if (hasContext) {1009 invalidateContextProvider(workInProgress, Component, true);1010 }1011 return workInProgress.child;1012}1013function pushHostRootContext(workInProgress) {1014 const root = (workInProgress.stateNode: FiberRoot);1015 if (root.pendingContext) {1016 pushTopLevelContextObject(1017 workInProgress,1018 root.pendingContext,1019 root.pendingContext !== root.context,1020 );1021 } else if (root.context) {1022 // Should always be set1023 pushTopLevelContextObject(workInProgress, root.context, false);1024 }1025 pushHostContainer(workInProgress, root.containerInfo);1026}1027function updateHostRoot(current, workInProgress, renderLanes) {1028 pushHostRootContext(workInProgress);1029 const updateQueue = workInProgress.updateQueue;1030 invariant(1031 current !== null && updateQueue !== null,1032 'If the root does not have an updateQueue, we should have already ' +1033 'bailed out. This error is likely caused by a bug in React. Please ' +1034 'file an issue.',1035 );1036 const nextProps = workInProgress.pendingProps;1037 const prevState = workInProgress.memoizedState;1038 const prevChildren = prevState !== null ? prevState.element : null;1039 cloneUpdateQueue(current, workInProgress);1040 processUpdateQueue(workInProgress, nextProps, null, renderLanes);1041 const nextState = workInProgress.memoizedState;1042 // Caution: React DevTools currently depends on this property1043 // being called "element".1044 const nextChildren = nextState.element;1045 if (nextChildren === prevChildren) {1046 resetHydrationState();1047 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);1048 }1049 const root: FiberRoot = workInProgress.stateNode;1050 if (root.hydrate && enterHydrationState(workInProgress)) {1051 // If we don't have any current children this might be the first pass.1052 // We always try to hydrate. If this isn't a hydration pass there won't1053 // be any children to hydrate which is effectively the same thing as1054 // not hydrating.1055 if (supportsHydration) {1056 const mutableSourceEagerHydrationData =1057 root.mutableSourceEagerHydrationData;1058 if (mutableSourceEagerHydrationData != null) {1059 for (let i = 0; i < mutableSourceEagerHydrationData.length; i += 2) {1060 const mutableSource = ((mutableSourceEagerHydrationData[1061 i1062 ]: any): MutableSource<any>);1063 const version = mutableSourceEagerHydrationData[i + 1];1064 setWorkInProgressVersion(mutableSource, version);1065 }1066 }1067 }1068 const child = mountChildFibers(1069 workInProgress,1070 null,1071 nextChildren,1072 renderLanes,1073 );1074 workInProgress.child = child;1075 let node = child;1076 while (node) {1077 // Mark each child as hydrating. This is a fast path to know whether this1078 // tree is part of a hydrating tree. This is used to determine if a child1079 // node has fully mounted yet, and for scheduling event replaying.1080 // Conceptually this is similar to Placement in that a new subtree is1081 // inserted into the React tree here. It just happens to not need DOM1082 // mutations because it already exists.1083 node.flags = (node.flags & ~Placement) | Hydrating;1084 node = node.sibling;1085 }1086 } else {1087 // Otherwise reset hydration state in case we aborted and resumed another1088 // root.1089 reconcileChildren(current, workInProgress, nextChildren, renderLanes);1090 resetHydrationState();1091 }1092 return workInProgress.child;1093}1094function updateHostComponent(1095 current: Fiber | null,1096 workInProgress: Fiber,1097 renderLanes: Lanes,1098) {1099 pushHostContext(workInProgress);1100 if (current === null) {1101 tryToClaimNextHydratableInstance(workInProgress);1102 }1103 const type = workInProgress.type;1104 const nextProps = workInProgress.pendingProps;1105 const prevProps = current !== null ? current.memoizedProps : null;1106 let nextChildren = nextProps.children;1107 const isDirectTextChild = shouldSetTextContent(type, nextProps);1108 if (isDirectTextChild) {1109 // We special case a direct text child of a host node. This is a common1110 // case. We won't handle it as a reified child. We will instead handle1111 // this in the host environment that also has access to this prop. That1112 // avoids allocating another HostText fiber and traversing it.1113 nextChildren = null;1114 } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {1115 // If we're switching from a direct text child to a normal child, or to1116 // empty, we need to schedule the text content to be reset.1117 workInProgress.flags |= ContentReset;1118 }1119 markRef(current, workInProgress);1120 reconcileChildren(current, workInProgress, nextChildren, renderLanes);1121 return workInProgress.child;1122}1123function updateHostText(current, workInProgress) {1124 if (current === null) {1125 tryToClaimNextHydratableInstance(workInProgress);1126 }1127 // Nothing to do here. This is terminal. We'll do the completion step1128 // immediately after.1129 return null;1130}1131function mountLazyComponent(1132 _current,1133 workInProgress,1134 elementType,1135 updateLanes,1136 renderLanes,1137) {1138 if (_current !== null) {1139 // A lazy component only mounts if it suspended inside a non-1140 // concurrent tree, in an inconsistent state. We want to treat it like1141 // a new mount, even though an empty version of it already committed.1142 // Disconnect the alternate pointers.1143 _current.alternate = null;1144 workInProgress.alternate = null;1145 // Since this is conceptually a new fiber, schedule a Placement effect1146 workInProgress.flags |= Placement;1147 }1148 const props = workInProgress.pendingProps;1149 const lazyComponent: LazyComponentType<any, any> = elementType;1150 const payload = lazyComponent._payload;1151 const init = lazyComponent._init;1152 let Component = init(payload);1153 // Store the unwrapped component in the type.1154 workInProgress.type = Component;1155 const resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component));1156 const resolvedProps = resolveDefaultProps(Component, props);1157 let child;1158 switch (resolvedTag) {1159 case FunctionComponent: {1160 if (__DEV__) {1161 validateFunctionComponentInDev(workInProgress, Component);1162 workInProgress.type = Component = resolveFunctionForHotReloading(1163 Component,1164 );1165 }1166 child = updateFunctionComponent(1167 null,1168 workInProgress,1169 Component,1170 resolvedProps,1171 renderLanes,1172 );1173 return child;1174 }1175 case ClassComponent: {1176 if (__DEV__) {1177 workInProgress.type = Component = resolveClassForHotReloading(1178 Component,1179 );1180 }1181 child = updateClassComponent(1182 null,1183 workInProgress,1184 Component,1185 resolvedProps,1186 renderLanes,1187 );1188 return child;1189 }1190 case ForwardRef: {1191 if (__DEV__) {1192 workInProgress.type = Component = resolveForwardRefForHotReloading(1193 Component,1194 );1195 }1196 child = updateForwardRef(1197 null,1198 workInProgress,1199 Component,1200 resolvedProps,1201 renderLanes,1202 );1203 return child;1204 }1205 case MemoComponent: {1206 if (__DEV__) {1207 if (workInProgress.type !== workInProgress.elementType) {1208 const outerPropTypes = Component.propTypes;1209 if (outerPropTypes) {1210 checkPropTypes(1211 outerPropTypes,1212 resolvedProps, // Resolved for outer only1213 'prop',1214 getComponentName(Component),1215 );1216 }1217 }1218 }1219 child = updateMemoComponent(1220 null,1221 workInProgress,1222 Component,1223 resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too1224 updateLanes,1225 renderLanes,1226 );1227 return child;1228 }1229 case Block: {1230 if (enableBlocksAPI) {1231 // TODO: Resolve for Hot Reloading.1232 child = updateBlock(1233 null,1234 workInProgress,1235 Component,1236 props,1237 renderLanes,1238 );1239 return child;1240 }1241 break;1242 }1243 }1244 let hint = '';1245 if (__DEV__) {1246 if (1247 Component !== null &&1248 typeof Component === 'object' &&1249 Component.$$typeof === REACT_LAZY_TYPE1250 ) {1251 hint = ' Did you wrap a component in React.lazy() more than once?';1252 }1253 }1254 // This message intentionally doesn't mention ForwardRef or MemoComponent1255 // because the fact that it's a separate type of work is an1256 // implementation detail.1257 invariant(1258 false,1259 'Element type is invalid. Received a promise that resolves to: %s. ' +1260 'Lazy element type must resolve to a class or function.%s',1261 Component,1262 hint,1263 );1264}1265function mountIncompleteClassComponent(1266 _current,1267 workInProgress,1268 Component,1269 nextProps,1270 renderLanes,1271) {1272 if (_current !== null) {1273 // An incomplete component only mounts if it suspended inside a non-1274 // concurrent tree, in an inconsistent state. We want to treat it like1275 // a new mount, even though an empty version of it already committed.1276 // Disconnect the alternate pointers.1277 _current.alternate = null;1278 workInProgress.alternate = null;1279 // Since this is conceptually a new fiber, schedule a Placement effect1280 workInProgress.flags |= Placement;1281 }1282 // Promote the fiber to a class and try rendering again.1283 workInProgress.tag = ClassComponent;1284 // The rest of this function is a fork of `updateClassComponent`1285 // Push context providers early to prevent context stack mismatches.1286 // During mounting we don't know the child context yet as the instance doesn't exist.1287 // We will invalidate the child context in finishClassComponent() right after rendering.1288 let hasContext;1289 if (isLegacyContextProvider(Component)) {1290 hasContext = true;1291 pushLegacyContextProvider(workInProgress);1292 } else {1293 hasContext = false;1294 }1295 prepareToReadContext(workInProgress, renderLanes);1296 constructClassInstance(workInProgress, Component, nextProps);1297 mountClassInstance(workInProgress, Component, nextProps, renderLanes);1298 return finishClassComponent(1299 null,1300 workInProgress,1301 Component,1302 true,1303 hasContext,1304 renderLanes,1305 );1306}1307function mountIndeterminateComponent(1308 _current,1309 workInProgress,1310 Component,1311 renderLanes,1312) {1313 if (_current !== null) {1314 // An indeterminate component only mounts if it suspended inside a non-1315 // concurrent tree, in an inconsistent state. We want to treat it like1316 // a new mount, even though an empty version of it already committed.1317 // Disconnect the alternate pointers.1318 _current.alternate = null;1319 workInProgress.alternate = null;1320 // Since this is conceptually a new fiber, schedule a Placement effect1321 workInProgress.flags |= Placement;1322 }1323 const props = workInProgress.pendingProps;1324 let context;1325 if (!disableLegacyContext) {1326 const unmaskedContext = getUnmaskedContext(1327 workInProgress,1328 Component,1329 false,1330 );1331 context = getMaskedContext(workInProgress, unmaskedContext);1332 }1333 prepareToReadContext(workInProgress, renderLanes);1334 let value;1335 if (__DEV__) {1336 if (1337 Component.prototype &&1338 typeof Component.prototype.render === 'function'1339 ) {1340 const componentName = getComponentName(Component) || 'Unknown';1341 if (!didWarnAboutBadClass[componentName]) {1342 console.error(1343 "The <%s /> component appears to have a render method, but doesn't extend React.Component. " +1344 'This is likely to cause errors. Change %s to extend React.Component instead.',1345 componentName,1346 componentName,1347 );1348 didWarnAboutBadClass[componentName] = true;1349 }1350 }1351 if (workInProgress.mode & StrictMode) {1352 ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);1353 }1354 setIsRendering(true);1355 ReactCurrentOwner.current = workInProgress;1356 value = renderWithHooks(1357 null,1358 workInProgress,1359 Component,1360 props,1361 context,1362 renderLanes,1363 );1364 setIsRendering(false);1365 } else {1366 value = renderWithHooks(1367 null,1368 workInProgress,1369 Component,1370 props,1371 context,1372 renderLanes,1373 );1374 }1375 // React DevTools reads this flag.1376 workInProgress.flags |= PerformedWork;1377 if (__DEV__) {1378 // Support for module components is deprecated and is removed behind a flag.1379 // Whether or not it would crash later, we want to show a good message in DEV first.1380 if (1381 typeof value === 'object' &&1382 value !== null &&1383 typeof value.render === 'function' &&1384 value.$$typeof === undefined1385 ) {1386 const componentName = getComponentName(Component) || 'Unknown';1387 if (!didWarnAboutModulePatternComponent[componentName]) {1388 console.error(1389 'The <%s /> component appears to be a function component that returns a class instance. ' +1390 'Change %s to a class that extends React.Component instead. ' +1391 "If you can't use a class try assigning the prototype on the function as a workaround. " +1392 "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " +1393 'cannot be called with `new` by React.',1394 componentName,1395 componentName,1396 componentName,1397 );1398 didWarnAboutModulePatternComponent[componentName] = true;1399 }1400 }1401 }1402 if (1403 // Run these checks in production only if the flag is off.1404 // Eventually we'll delete this branch altogether.1405 !disableModulePatternComponents &&1406 typeof value === 'object' &&1407 value !== null &&1408 typeof value.render === 'function' &&1409 value.$$typeof === undefined1410 ) {1411 if (__DEV__) {1412 const componentName = getComponentName(Component) || 'Unknown';1413 if (!didWarnAboutModulePatternComponent[componentName]) {1414 console.error(1415 'The <%s /> component appears to be a function component that returns a class instance. ' +1416 'Change %s to a class that extends React.Component instead. ' +1417 "If you can't use a class try assigning the prototype on the function as a workaround. " +1418 "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " +1419 'cannot be called with `new` by React.',1420 componentName,1421 componentName,1422 componentName,1423 );1424 didWarnAboutModulePatternComponent[componentName] = true;1425 }1426 }1427 // Proceed under the assumption that this is a class instance1428 workInProgress.tag = ClassComponent;1429 // Throw out any hooks that were used.1430 workInProgress.memoizedState = null;1431 workInProgress.updateQueue = null;1432 // Push context providers early to prevent context stack mismatches.1433 // During mounting we don't know the child context yet as the instance doesn't exist.1434 // We will invalidate the child context in finishClassComponent() right after rendering.1435 let hasContext = false;1436 if (isLegacyContextProvider(Component)) {1437 hasContext = true;1438 pushLegacyContextProvider(workInProgress);1439 } else {1440 hasContext = false;1441 }1442 workInProgress.memoizedState =1443 value.state !== null && value.state !== undefined ? value.state : null;1444 initializeUpdateQueue(workInProgress);1445 const getDerivedStateFromProps = Component.getDerivedStateFromProps;1446 if (typeof getDerivedStateFromProps === 'function') {1447 applyDerivedStateFromProps(1448 workInProgress,1449 Component,1450 getDerivedStateFromProps,1451 props,1452 );1453 }1454 adoptClassInstance(workInProgress, value);1455 mountClassInstance(workInProgress, Component, props, renderLanes);1456 return finishClassComponent(1457 null,1458 workInProgress,1459 Component,1460 true,1461 hasContext,1462 renderLanes,1463 );1464 } else {1465 // Proceed under the assumption that this is a function component1466 workInProgress.tag = FunctionComponent;1467 if (__DEV__) {1468 if (disableLegacyContext && Component.contextTypes) {1469 console.error(1470 '%s uses the legacy contextTypes API which is no longer supported. ' +1471 'Use React.createContext() with React.useContext() instead.',1472 getComponentName(Component) || 'Unknown',1473 );1474 }1475 if (1476 debugRenderPhaseSideEffectsForStrictMode &&1477 workInProgress.mode & StrictMode1478 ) {1479 disableLogs();1480 try {1481 value = renderWithHooks(1482 null,1483 workInProgress,1484 Component,1485 props,1486 context,1487 renderLanes,1488 );1489 } finally {1490 reenableLogs();1491 }1492 }1493 }1494 reconcileChildren(null, workInProgress, value, renderLanes);1495 if (__DEV__) {1496 validateFunctionComponentInDev(workInProgress, Component);1497 }1498 return workInProgress.child;1499 }1500}1501function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {1502 if (__DEV__) {1503 if (Component) {1504 if (Component.childContextTypes) {1505 console.error(1506 '%s(...): childContextTypes cannot be defined on a function component.',1507 Component.displayName || Component.name || 'Component',1508 );1509 }1510 }1511 if (workInProgress.ref !== null) {1512 let info = '';1513 const ownerName = getCurrentFiberOwnerNameInDevOrNull();1514 if (ownerName) {1515 info += '\n\nCheck the render method of `' + ownerName + '`.';1516 }1517 let warningKey = ownerName || workInProgress._debugID || '';1518 const debugSource = workInProgress._debugSource;1519 if (debugSource) {1520 warningKey = debugSource.fileName + ':' + debugSource.lineNumber;1521 }1522 if (!didWarnAboutFunctionRefs[warningKey]) {1523 didWarnAboutFunctionRefs[warningKey] = true;1524 console.error(1525 'Function components cannot be given refs. ' +1526 'Attempts to access this ref will fail. ' +1527 'Did you mean to use React.forwardRef()?%s',1528 info,1529 );1530 }1531 }1532 if (1533 warnAboutDefaultPropsOnFunctionComponents &&1534 Component.defaultProps !== undefined1535 ) {1536 const componentName = getComponentName(Component) || 'Unknown';1537 if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) {1538 console.error(1539 '%s: Support for defaultProps will be removed from function components ' +1540 'in a future major release. Use JavaScript default parameters instead.',1541 componentName,1542 );1543 didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true;1544 }1545 }1546 if (typeof Component.getDerivedStateFromProps === 'function') {1547 const componentName = getComponentName(Component) || 'Unknown';1548 if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {1549 console.error(1550 '%s: Function components do not support getDerivedStateFromProps.',1551 componentName,1552 );1553 didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;1554 }1555 }1556 if (1557 typeof Component.contextType === 'object' &&1558 Component.contextType !== null1559 ) {1560 const componentName = getComponentName(Component) || 'Unknown';1561 if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {1562 console.error(1563 '%s: Function components do not support contextType.',1564 componentName,1565 );1566 didWarnAboutContextTypeOnFunctionComponent[componentName] = true;1567 }1568 }1569 }1570}1571const SUSPENDED_MARKER: SuspenseState = {1572 dehydrated: null,1573 retryLane: NoLane,1574};1575function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {1576 return {1577 baseLanes: renderLanes,1578 };1579}1580function updateSuspenseOffscreenState(1581 prevOffscreenState: OffscreenState,1582 renderLanes: Lanes,1583): OffscreenState {1584 return {1585 baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes),1586 };1587}1588// TODO: Probably should inline this back1589function shouldRemainOnFallback(1590 suspenseContext: SuspenseContext,1591 current: null | Fiber,1592 workInProgress: Fiber,1593 renderLanes: Lanes,1594) {1595 // If we're already showing a fallback, there are cases where we need to1596 // remain on that fallback regardless of whether the content has resolved.1597 // For example, SuspenseList coordinates when nested content appears.1598 if (current !== null) {1599 const suspenseState: SuspenseState = current.memoizedState;1600 if (suspenseState === null) {1601 // Currently showing content. Don't hide it, even if ForceSuspenseFallack1602 // is true. More precise name might be "ForceRemainSuspenseFallback".1603 // Note: This is a factoring smell. Can't remain on a fallback if there's1604 // no fallback to remain on.1605 return false;1606 }1607 }1608 // Not currently showing content. Consult the Suspense context.1609 return hasSuspenseContext(1610 suspenseContext,1611 (ForceSuspenseFallback: SuspenseContext),1612 );1613}1614function getRemainingWorkInPrimaryTree(current: Fiber, renderLanes) {1615 // TODO: Should not remove render lanes that were pinged during this render1616 return removeLanes(current.childLanes, renderLanes);1617}1618function updateSuspenseComponent(current, workInProgress, renderLanes) {1619 const nextProps = workInProgress.pendingProps;1620 // This is used by DevTools to force a boundary to suspend.1621 if (__DEV__) {1622 if (shouldSuspend(workInProgress)) {1623 workInProgress.flags |= DidCapture;1624 }1625 }1626 let suspenseContext: SuspenseContext = suspenseStackCursor.current;1627 let showFallback = false;1628 const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;1629 if (1630 didSuspend ||1631 shouldRemainOnFallback(1632 suspenseContext,1633 current,1634 workInProgress,1635 renderLanes,1636 )1637 ) {1638 // Something in this boundary's subtree already suspended. Switch to1639 // rendering the fallback children.1640 showFallback = true;1641 workInProgress.flags &= ~DidCapture;1642 } else {1643 // Attempting the main content1644 if (1645 current === null ||1646 (current.memoizedState: null | SuspenseState) !== null1647 ) {1648 // This is a new mount or this boundary is already showing a fallback state.1649 // Mark this subtree context as having at least one invisible parent that could1650 // handle the fallback state.1651 // Boundaries without fallbacks or should be avoided are not considered since1652 // they cannot handle preferred fallback states.1653 if (1654 nextProps.fallback !== undefined &&1655 nextProps.unstable_avoidThisFallback !== true1656 ) {1657 suspenseContext = addSubtreeSuspenseContext(1658 suspenseContext,1659 InvisibleParentSuspenseContext,1660 );1661 }1662 }1663 }1664 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);1665 pushSuspenseContext(workInProgress, suspenseContext);1666 // OK, the next part is confusing. We're about to reconcile the Suspense1667 // boundary's children. This involves some custom reconcilation logic. Two1668 // main reasons this is so complicated.1669 //1670 // First, Legacy Mode has different semantics for backwards compatibility. The1671 // primary tree will commit in an inconsistent state, so when we do the1672 // second pass to render the fallback, we do some exceedingly, uh, clever1673 // hacks to make that not totally break. Like transferring effects and1674 // deletions from hidden tree. In Concurrent Mode, it's much simpler,1675 // because we bailout on the primary tree completely and leave it in its old1676 // state, no effects. Same as what we do for Offscreen (except that1677 // Offscreen doesn't have the first render pass).1678 //1679 // Second is hydration. During hydration, the Suspense fiber has a slightly1680 // different layout, where the child points to a dehydrated fragment, which1681 // contains the DOM rendered by the server.1682 //1683 // Third, even if you set all that aside, Suspense is like error boundaries in1684 // that we first we try to render one tree, and if that fails, we render again1685 // and switch to a different tree. Like a try/catch block. So we have to track1686 // which branch we're currently rendering. Ideally we would model this using1687 // a stack.1688 if (current === null) {1689 // Initial mount1690 // If we're currently hydrating, try to hydrate this boundary.1691 // But only if this has a fallback.1692 if (nextProps.fallback !== undefined) {1693 tryToClaimNextHydratableInstance(workInProgress);1694 // This could've been a dehydrated suspense component.1695 if (enableSuspenseServerRenderer) {1696 const suspenseState: null | SuspenseState =1697 workInProgress.memoizedState;1698 if (suspenseState !== null) {1699 const dehydrated = suspenseState.dehydrated;1700 if (dehydrated !== null) {1701 return mountDehydratedSuspenseComponent(1702 workInProgress,1703 dehydrated,1704 renderLanes,1705 );1706 }1707 }1708 }1709 }1710 const nextPrimaryChildren = nextProps.children;1711 const nextFallbackChildren = nextProps.fallback;1712 if (showFallback) {1713 const fallbackFragment = mountSuspenseFallbackChildren(1714 workInProgress,1715 nextPrimaryChildren,1716 nextFallbackChildren,1717 renderLanes,1718 );1719 const primaryChildFragment: Fiber = (workInProgress.child: any);1720 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(1721 renderLanes,1722 );1723 workInProgress.memoizedState = SUSPENDED_MARKER;1724 return fallbackFragment;1725 } else if (typeof nextProps.unstable_expectedLoadTime === 'number') {1726 // This is a CPU-bound tree. Skip this tree and show a placeholder to1727 // unblock the surrounding content. Then immediately retry after the1728 // initial commit.1729 const fallbackFragment = mountSuspenseFallbackChildren(1730 workInProgress,1731 nextPrimaryChildren,1732 nextFallbackChildren,1733 renderLanes,1734 );1735 const primaryChildFragment: Fiber = (workInProgress.child: any);1736 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(1737 renderLanes,1738 );1739 workInProgress.memoizedState = SUSPENDED_MARKER;1740 // Since nothing actually suspended, there will nothing to ping this to1741 // get it started back up to attempt the next item. While in terms of1742 // priority this work has the same priority as this current render, it's1743 // not part of the same transition once the transition has committed. If1744 // it's sync, we still want to yield so that it can be painted.1745 // Conceptually, this is really the same as pinging. We can use any1746 // RetryLane even if it's the one currently rendering since we're leaving1747 // it behind on this node.1748 workInProgress.lanes = SomeRetryLane;1749 if (enableSchedulerTracing) {1750 markSpawnedWork(SomeRetryLane);1751 }1752 return fallbackFragment;1753 } else {1754 return mountSuspensePrimaryChildren(1755 workInProgress,1756 nextPrimaryChildren,1757 renderLanes,1758 );1759 }1760 } else {1761 // This is an update.1762 // If the current fiber has a SuspenseState, that means it's already showing1763 // a fallback.1764 const prevState: null | SuspenseState = current.memoizedState;1765 if (prevState !== null) {1766 // The current tree is already showing a fallback1767 // Special path for hydration1768 if (enableSuspenseServerRenderer) {1769 const dehydrated = prevState.dehydrated;1770 if (dehydrated !== null) {1771 if (!didSuspend) {1772 return updateDehydratedSuspenseComponent(1773 current,1774 workInProgress,1775 dehydrated,1776 prevState,1777 renderLanes,1778 );1779 } else if (1780 (workInProgress.memoizedState: null | SuspenseState) !== null1781 ) {1782 // Something suspended and we should still be in dehydrated mode.1783 // Leave the existing child in place.1784 workInProgress.child = current.child;1785 // The dehydrated completion pass expects this flag to be there1786 // but the normal suspense pass doesn't.1787 workInProgress.flags |= DidCapture;1788 return null;1789 } else {1790 // Suspended but we should no longer be in dehydrated mode.1791 // Therefore we now have to render the fallback.1792 const nextPrimaryChildren = nextProps.children;1793 const nextFallbackChildren = nextProps.fallback;1794 const fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(1795 current,1796 workInProgress,1797 nextPrimaryChildren,1798 nextFallbackChildren,1799 renderLanes,1800 );1801 const primaryChildFragment: Fiber = (workInProgress.child: any);1802 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(1803 renderLanes,1804 );1805 workInProgress.memoizedState = SUSPENDED_MARKER;1806 return fallbackChildFragment;1807 }1808 }1809 }1810 if (showFallback) {1811 const nextFallbackChildren = nextProps.fallback;1812 const nextPrimaryChildren = nextProps.children;1813 const fallbackChildFragment = updateSuspenseFallbackChildren(1814 current,1815 workInProgress,1816 nextPrimaryChildren,1817 nextFallbackChildren,1818 renderLanes,1819 );1820 const primaryChildFragment: Fiber = (workInProgress.child: any);1821 const prevOffscreenState: OffscreenState | null = (current.child: any)1822 .memoizedState;1823 primaryChildFragment.memoizedState =1824 prevOffscreenState === null1825 ? mountSuspenseOffscreenState(renderLanes)1826 : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);1827 primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(1828 current,1829 renderLanes,1830 );1831 workInProgress.memoizedState = SUSPENDED_MARKER;1832 return fallbackChildFragment;1833 } else {1834 const nextPrimaryChildren = nextProps.children;1835 const primaryChildFragment = updateSuspensePrimaryChildren(1836 current,1837 workInProgress,1838 nextPrimaryChildren,1839 renderLanes,1840 );1841 workInProgress.memoizedState = null;1842 return primaryChildFragment;1843 }1844 } else {1845 // The current tree is not already showing a fallback.1846 if (showFallback) {1847 // Timed out.1848 const nextFallbackChildren = nextProps.fallback;1849 const nextPrimaryChildren = nextProps.children;1850 const fallbackChildFragment = updateSuspenseFallbackChildren(1851 current,1852 workInProgress,1853 nextPrimaryChildren,1854 nextFallbackChildren,1855 renderLanes,1856 );1857 const primaryChildFragment: Fiber = (workInProgress.child: any);1858 const prevOffscreenState: OffscreenState | null = (current.child: any)1859 .memoizedState;1860 primaryChildFragment.memoizedState =1861 prevOffscreenState === null1862 ? mountSuspenseOffscreenState(renderLanes)1863 : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);1864 primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(1865 current,1866 renderLanes,1867 );1868 // Skip the primary children, and continue working on the1869 // fallback children.1870 workInProgress.memoizedState = SUSPENDED_MARKER;1871 return fallbackChildFragment;1872 } else {1873 // Still haven't timed out. Continue rendering the children, like we1874 // normally do.1875 const nextPrimaryChildren = nextProps.children;1876 const primaryChildFragment = updateSuspensePrimaryChildren(1877 current,1878 workInProgress,1879 nextPrimaryChildren,1880 renderLanes,1881 );1882 workInProgress.memoizedState = null;1883 return primaryChildFragment;1884 }1885 }1886 }1887}1888function mountSuspensePrimaryChildren(1889 workInProgress,1890 primaryChildren,1891 renderLanes,1892) {1893 const mode = workInProgress.mode;1894 const primaryChildProps: OffscreenProps = {1895 mode: 'visible',1896 children: primaryChildren,1897 };1898 const primaryChildFragment = createFiberFromOffscreen(1899 primaryChildProps,1900 mode,1901 renderLanes,1902 null,1903 );1904 primaryChildFragment.return = workInProgress;1905 workInProgress.child = primaryChildFragment;1906 return primaryChildFragment;1907}1908function mountSuspenseFallbackChildren(1909 workInProgress,1910 primaryChildren,1911 fallbackChildren,1912 renderLanes,1913) {1914 const mode = workInProgress.mode;1915 const progressedPrimaryFragment: Fiber | null = workInProgress.child;1916 const primaryChildProps: OffscreenProps = {1917 mode: 'hidden',1918 children: primaryChildren,1919 };1920 let primaryChildFragment;1921 let fallbackChildFragment;1922 if ((mode & BlockingMode) === NoMode && progressedPrimaryFragment !== null) {1923 // In legacy mode, we commit the primary tree as if it successfully1924 // completed, even though it's in an inconsistent state.1925 primaryChildFragment = progressedPrimaryFragment;1926 primaryChildFragment.childLanes = NoLanes;1927 primaryChildFragment.pendingProps = primaryChildProps;1928 if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1929 // Reset the durations from the first pass so they aren't included in the1930 // final amounts. This seems counterintuitive, since we're intentionally1931 // not measuring part of the render phase, but this makes it match what we1932 // do in Concurrent Mode.1933 primaryChildFragment.actualDuration = 0;1934 primaryChildFragment.actualStartTime = -1;1935 primaryChildFragment.selfBaseDuration = 0;1936 primaryChildFragment.treeBaseDuration = 0;1937 }1938 fallbackChildFragment = createFiberFromFragment(1939 fallbackChildren,1940 mode,1941 renderLanes,1942 null,1943 );1944 } else {1945 primaryChildFragment = createFiberFromOffscreen(1946 primaryChildProps,1947 mode,1948 NoLanes,1949 null,1950 );1951 fallbackChildFragment = createFiberFromFragment(1952 fallbackChildren,1953 mode,1954 renderLanes,1955 null,1956 );1957 }1958 primaryChildFragment.return = workInProgress;1959 fallbackChildFragment.return = workInProgress;1960 primaryChildFragment.sibling = fallbackChildFragment;1961 workInProgress.child = primaryChildFragment;1962 return fallbackChildFragment;1963}1964function createWorkInProgressOffscreenFiber(1965 current: Fiber,1966 offscreenProps: OffscreenProps,1967) {1968 // The props argument to `createWorkInProgress` is `any` typed, so we use this1969 // wrapper function to constrain it.1970 return createWorkInProgress(current, offscreenProps);1971}1972function updateSuspensePrimaryChildren(1973 current,1974 workInProgress,1975 primaryChildren,1976 renderLanes,1977) {1978 const currentPrimaryChildFragment: Fiber = (current.child: any);1979 const currentFallbackChildFragment: Fiber | null =1980 currentPrimaryChildFragment.sibling;1981 const primaryChildFragment = createWorkInProgressOffscreenFiber(1982 currentPrimaryChildFragment,1983 {1984 mode: 'visible',1985 children: primaryChildren,1986 },1987 );1988 if ((workInProgress.mode & BlockingMode) === NoMode) {1989 primaryChildFragment.lanes = renderLanes;1990 }1991 primaryChildFragment.return = workInProgress;1992 primaryChildFragment.sibling = null;1993 if (currentFallbackChildFragment !== null) {1994 // Delete the fallback child fragment1995 currentFallbackChildFragment.nextEffect = null;1996 currentFallbackChildFragment.flags = Deletion;1997 workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment;1998 }1999 workInProgress.child = primaryChildFragment;2000 return primaryChildFragment;2001}2002function updateSuspenseFallbackChildren(2003 current,2004 workInProgress,2005 primaryChildren,2006 fallbackChildren,2007 renderLanes,2008) {2009 const mode = workInProgress.mode;2010 const currentPrimaryChildFragment: Fiber = (current.child: any);2011 const currentFallbackChildFragment: Fiber | null =2012 currentPrimaryChildFragment.sibling;2013 const primaryChildProps: OffscreenProps = {2014 mode: 'hidden',2015 children: primaryChildren,2016 };2017 let primaryChildFragment;2018 if (2019 // In legacy mode, we commit the primary tree as if it successfully2020 // completed, even though it's in an inconsistent state.2021 (mode & BlockingMode) === NoMode &&2022 // Make sure we're on the second pass, i.e. the primary child fragment was2023 // already cloned. In legacy mode, the only case where this isn't true is2024 // when DevTools forces us to display a fallback; we skip the first render2025 // pass entirely and go straight to rendering the fallback. (In Concurrent2026 // Mode, SuspenseList can also trigger this scenario, but this is a legacy-2027 // only codepath.)2028 workInProgress.child !== currentPrimaryChildFragment2029 ) {2030 const progressedPrimaryFragment: Fiber = (workInProgress.child: any);2031 primaryChildFragment = progressedPrimaryFragment;2032 primaryChildFragment.childLanes = NoLanes;2033 primaryChildFragment.pendingProps = primaryChildProps;2034 if (enableProfilerTimer && workInProgress.mode & ProfileMode) {2035 // Reset the durations from the first pass so they aren't included in the2036 // final amounts. This seems counterintuitive, since we're intentionally2037 // not measuring part of the render phase, but this makes it match what we2038 // do in Concurrent Mode.2039 primaryChildFragment.actualDuration = 0;2040 primaryChildFragment.actualStartTime = -1;2041 primaryChildFragment.selfBaseDuration =2042 currentPrimaryChildFragment.selfBaseDuration;2043 primaryChildFragment.treeBaseDuration =2044 currentPrimaryChildFragment.treeBaseDuration;2045 }2046 // The fallback fiber was added as a deletion effect during the first pass.2047 // However, since we're going to remain on the fallback, we no longer want2048 // to delete it. So we need to remove it from the list. Deletions are stored2049 // on the same list as effects. We want to keep the effects from the primary2050 // tree. So we copy the primary child fragment's effect list, which does not2051 // include the fallback deletion effect.2052 const progressedLastEffect = primaryChildFragment.lastEffect;2053 if (progressedLastEffect !== null) {2054 workInProgress.firstEffect = primaryChildFragment.firstEffect;2055 workInProgress.lastEffect = progressedLastEffect;2056 progressedLastEffect.nextEffect = null;2057 } else {2058 // TODO: Reset this somewhere else? Lol legacy mode is so weird.2059 workInProgress.firstEffect = workInProgress.lastEffect = null;2060 }2061 } else {2062 primaryChildFragment = createWorkInProgressOffscreenFiber(2063 currentPrimaryChildFragment,2064 primaryChildProps,2065 );2066 }2067 let fallbackChildFragment;2068 if (currentFallbackChildFragment !== null) {2069 fallbackChildFragment = createWorkInProgress(2070 currentFallbackChildFragment,2071 fallbackChildren,2072 );2073 } else {2074 fallbackChildFragment = createFiberFromFragment(2075 fallbackChildren,2076 mode,2077 renderLanes,2078 null,2079 );2080 // Needs a placement effect because the parent (the Suspense boundary) already2081 // mounted but this is a new fiber.2082 fallbackChildFragment.flags |= Placement;2083 }2084 fallbackChildFragment.return = workInProgress;2085 primaryChildFragment.return = workInProgress;2086 primaryChildFragment.sibling = fallbackChildFragment;2087 workInProgress.child = primaryChildFragment;2088 return fallbackChildFragment;2089}2090function retrySuspenseComponentWithoutHydrating(2091 current: Fiber,2092 workInProgress: Fiber,2093 renderLanes: Lanes,2094) {2095 // This will add the old fiber to the deletion list2096 reconcileChildFibers(workInProgress, current.child, null, renderLanes);2097 // We're now not suspended nor dehydrated.2098 const nextProps = workInProgress.pendingProps;2099 const primaryChildren = nextProps.children;2100 const primaryChildFragment = mountSuspensePrimaryChildren(2101 workInProgress,2102 primaryChildren,2103 renderLanes,2104 );2105 // Needs a placement effect because the parent (the Suspense boundary) already2106 // mounted but this is a new fiber.2107 primaryChildFragment.flags |= Placement;2108 workInProgress.memoizedState = null;2109 return primaryChildFragment;2110}2111function mountSuspenseFallbackAfterRetryWithoutHydrating(2112 current,2113 workInProgress,2114 primaryChildren,2115 fallbackChildren,2116 renderLanes,2117) {2118 const mode = workInProgress.mode;2119 const primaryChildFragment = createFiberFromOffscreen(2120 primaryChildren,2121 mode,2122 NoLanes,2123 null,2124 );2125 const fallbackChildFragment = createFiberFromFragment(2126 fallbackChildren,2127 mode,2128 renderLanes,2129 null,2130 );2131 // Needs a placement effect because the parent (the Suspense2132 // boundary) already mounted but this is a new fiber.2133 fallbackChildFragment.flags |= Placement;2134 primaryChildFragment.return = workInProgress;2135 fallbackChildFragment.return = workInProgress;2136 primaryChildFragment.sibling = fallbackChildFragment;2137 workInProgress.child = primaryChildFragment;2138 if ((workInProgress.mode & BlockingMode) !== NoMode) {2139 // We will have dropped the effect list which contains the2140 // deletion. We need to reconcile to delete the current child.2141 reconcileChildFibers(workInProgress, current.child, null, renderLanes);2142 }2143 return fallbackChildFragment;2144}2145function mountDehydratedSuspenseComponent(2146 workInProgress: Fiber,2147 suspenseInstance: SuspenseInstance,2148 renderLanes: Lanes,2149): null | Fiber {2150 // During the first pass, we'll bail out and not drill into the children.2151 // Instead, we'll leave the content in place and try to hydrate it later.2152 if ((workInProgress.mode & BlockingMode) === NoMode) {2153 if (__DEV__) {2154 console.error(2155 'Cannot hydrate Suspense in legacy mode. Switch from ' +2156 'ReactDOM.hydrate(element, container) to ' +2157 'ReactDOM.createBlockingRoot(container, { hydrate: true })' +2158 '.render(element) or remove the Suspense components from ' +2159 'the server rendered components.',2160 );2161 }2162 workInProgress.lanes = laneToLanes(SyncLane);2163 } else if (isSuspenseInstanceFallback(suspenseInstance)) {2164 // This is a client-only boundary. Since we won't get any content from the server2165 // for this, we need to schedule that at a higher priority based on when it would2166 // have timed out. In theory we could render it in this pass but it would have the2167 // wrong priority associated with it and will prevent hydration of parent path.2168 // Instead, we'll leave work left on it to render it in a separate commit.2169 // TODO This time should be the time at which the server rendered response that is2170 // a parent to this boundary was displayed. However, since we currently don't have2171 // a protocol to transfer that time, we'll just estimate it by using the current2172 // time. This will mean that Suspense timeouts are slightly shifted to later than2173 // they should be.2174 // Schedule a normal pri update to render this content.2175 if (enableSchedulerTracing) {2176 markSpawnedWork(DefaultHydrationLane);2177 }2178 workInProgress.lanes = laneToLanes(DefaultHydrationLane);2179 } else {2180 // We'll continue hydrating the rest at offscreen priority since we'll already2181 // be showing the right content coming from the server, it is no rush.2182 workInProgress.lanes = laneToLanes(OffscreenLane);2183 if (enableSchedulerTracing) {2184 markSpawnedWork(OffscreenLane);2185 }2186 }2187 return null;2188}2189function updateDehydratedSuspenseComponent(2190 current: Fiber,2191 workInProgress: Fiber,2192 suspenseInstance: SuspenseInstance,2193 suspenseState: SuspenseState,2194 renderLanes: Lanes,2195): null | Fiber {2196 // We should never be hydrating at this point because it is the first pass,...
ReactFiberBeginWork.new.js
Source:ReactFiberBeginWork.new.js
...576 // Schedule this fiber to re-render at offscreen priority. Then bailout.577 if (enableSchedulerTracing) {578 markSpawnedWork((OffscreenLane: Lane));579 }580 workInProgress.lanes = workInProgress.childLanes = laneToLanes(581 OffscreenLane,582 );583 const nextState: OffscreenState = {584 baseLanes: nextBaseLanes,585 };586 workInProgress.memoizedState = nextState;587 // We're about to bail out, but we need to push this to the stack anyway588 // to avoid a push/pop misalignment.589 pushRenderLanes(workInProgress, nextBaseLanes);590 return null;591 } else {592 // Rendering at offscreen, so we can clear the base lanes.593 const nextState: OffscreenState = {594 baseLanes: NoLanes,595 };596 workInProgress.memoizedState = nextState;597 // Push the lanes that were skipped when we bailed out.598 const subtreeRenderLanes =599 prevState !== null ? prevState.baseLanes : renderLanes;600 pushRenderLanes(workInProgress, subtreeRenderLanes);601 }602 } else {603 let subtreeRenderLanes;604 if (prevState !== null) {605 subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes);606 // Since we're not hidden anymore, reset the state607 workInProgress.memoizedState = null;608 } else {609 // We weren't previously hidden, and we still aren't, so there's nothing610 // special to do. Need to push to the stack regardless, though, to avoid611 // a push/pop misalignment.612 subtreeRenderLanes = renderLanes;613 }614 pushRenderLanes(workInProgress, subtreeRenderLanes);615 }616 reconcileChildren(current, workInProgress, nextChildren, renderLanes);617 return workInProgress.child;618}619// Note: These happen to have identical begin phases, for now. We shouldn't hold620// ourselves to this constraint, though. If the behavior diverges, we should621// fork the function.622const updateLegacyHiddenComponent = updateOffscreenComponent;623function updateFragment(624 current: Fiber | null,625 workInProgress: Fiber,626 renderLanes: Lanes,627) {628 const nextChildren = workInProgress.pendingProps;629 reconcileChildren(current, workInProgress, nextChildren, renderLanes);630 return workInProgress.child;631}632function updateMode(633 current: Fiber | null,634 workInProgress: Fiber,635 renderLanes: Lanes,636) {637 const nextChildren = workInProgress.pendingProps.children;638 reconcileChildren(current, workInProgress, nextChildren, renderLanes);639 return workInProgress.child;640}641function updateProfiler(642 current: Fiber | null,643 workInProgress: Fiber,644 renderLanes: Lanes,645) {646 if (enableProfilerTimer) {647 // Reset effect durations for the next eventual effect phase.648 // These are reset during render to allow the DevTools commit hook a chance to read them,649 const stateNode = workInProgress.stateNode;650 stateNode.effectDuration = 0;651 stateNode.passiveEffectDuration = 0;652 }653 const nextProps = workInProgress.pendingProps;654 const nextChildren = nextProps.children;655 reconcileChildren(current, workInProgress, nextChildren, renderLanes);656 return workInProgress.child;657}658function markRef(current: Fiber | null, workInProgress: Fiber) {659 const ref = workInProgress.ref;660 if (661 (current === null && ref !== null) ||662 (current !== null && current.ref !== ref)663 ) {664 // Schedule a Ref effect665 workInProgress.flags |= Ref;666 }667}668function updateFunctionComponent(669 current,670 workInProgress,671 Component,672 nextProps: any,673 renderLanes,674) {675 if (__DEV__) {676 if (workInProgress.type !== workInProgress.elementType) {677 // Lazy component props can't be validated in createElement678 // because they're only guaranteed to be resolved here.679 const innerPropTypes = Component.propTypes;680 if (innerPropTypes) {681 checkPropTypes(682 innerPropTypes,683 nextProps, // Resolved props684 'prop',685 getComponentName(Component),686 );687 }688 }689 }690 let context;691 if (!disableLegacyContext) {692 const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);693 context = getMaskedContext(workInProgress, unmaskedContext);694 }695 let nextChildren;696 prepareToReadContext(workInProgress, renderLanes);697 if (__DEV__) {698 ReactCurrentOwner.current = workInProgress;699 setIsRendering(true);700 nextChildren = renderWithHooks(701 current,702 workInProgress,703 Component,704 nextProps,705 context,706 renderLanes,707 );708 if (709 debugRenderPhaseSideEffectsForStrictMode &&710 workInProgress.mode & StrictMode711 ) {712 disableLogs();713 try {714 nextChildren = renderWithHooks(715 current,716 workInProgress,717 Component,718 nextProps,719 context,720 renderLanes,721 );722 } finally {723 reenableLogs();724 }725 }726 setIsRendering(false);727 } else {728 nextChildren = renderWithHooks(729 current,730 workInProgress,731 Component,732 nextProps,733 context,734 renderLanes,735 );736 }737 if (current !== null && !didReceiveUpdate) {738 bailoutHooks(current, workInProgress, renderLanes);739 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);740 }741 // React DevTools reads this flag.742 workInProgress.flags |= PerformedWork;743 reconcileChildren(current, workInProgress, nextChildren, renderLanes);744 return workInProgress.child;745}746function updateBlock<Props, Data>(747 current: Fiber | null,748 workInProgress: Fiber,749 block: BlockComponent<Props, Data>,750 nextProps: any,751 renderLanes: Lanes,752) {753 // TODO: current can be non-null here even if the component754 // hasn't yet mounted. This happens after the first render suspends.755 // We'll need to figure out if this is fine or can cause issues.756 const render = block._render;757 const data = block._data;758 // The rest is a fork of updateFunctionComponent759 let nextChildren;760 prepareToReadContext(workInProgress, renderLanes);761 if (__DEV__) {762 ReactCurrentOwner.current = workInProgress;763 setIsRendering(true);764 nextChildren = renderWithHooks(765 current,766 workInProgress,767 render,768 nextProps,769 data,770 renderLanes,771 );772 if (773 debugRenderPhaseSideEffectsForStrictMode &&774 workInProgress.mode & StrictMode775 ) {776 disableLogs();777 try {778 nextChildren = renderWithHooks(779 current,780 workInProgress,781 render,782 nextProps,783 data,784 renderLanes,785 );786 } finally {787 reenableLogs();788 }789 }790 setIsRendering(false);791 } else {792 nextChildren = renderWithHooks(793 current,794 workInProgress,795 render,796 nextProps,797 data,798 renderLanes,799 );800 }801 if (current !== null && !didReceiveUpdate) {802 bailoutHooks(current, workInProgress, renderLanes);803 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);804 }805 // React DevTools reads this flag.806 workInProgress.flags |= PerformedWork;807 reconcileChildren(current, workInProgress, nextChildren, renderLanes);808 return workInProgress.child;809}810function updateClassComponent(811 current: Fiber | null,812 workInProgress: Fiber,813 Component: any,814 nextProps: any,815 renderLanes: Lanes,816) {817 if (__DEV__) {818 if (workInProgress.type !== workInProgress.elementType) {819 // Lazy component props can't be validated in createElement820 // because they're only guaranteed to be resolved here.821 const innerPropTypes = Component.propTypes;822 if (innerPropTypes) {823 checkPropTypes(824 innerPropTypes,825 nextProps, // Resolved props826 'prop',827 getComponentName(Component),828 );829 }830 }831 }832 // Push context providers early to prevent context stack mismatches.833 // During mounting we don't know the child context yet as the instance doesn't exist.834 // We will invalidate the child context in finishClassComponent() right after rendering.835 let hasContext;836 if (isLegacyContextProvider(Component)) {837 hasContext = true;838 pushLegacyContextProvider(workInProgress);839 } else {840 hasContext = false;841 }842 prepareToReadContext(workInProgress, renderLanes);843 const instance = workInProgress.stateNode;844 let shouldUpdate;845 if (instance === null) {846 if (current !== null) {847 // A class component without an instance only mounts if it suspended848 // inside a non-concurrent tree, in an inconsistent state. We want to849 // treat it like a new mount, even though an empty version of it already850 // committed. Disconnect the alternate pointers.851 current.alternate = null;852 workInProgress.alternate = null;853 // Since this is conceptually a new fiber, schedule a Placement effect854 workInProgress.flags |= Placement;855 }856 // In the initial pass we might need to construct the instance.857 constructClassInstance(workInProgress, Component, nextProps);858 mountClassInstance(workInProgress, Component, nextProps, renderLanes);859 shouldUpdate = true;860 } else if (current === null) {861 // In a resume, we'll already have an instance we can reuse.862 shouldUpdate = resumeMountClassInstance(863 workInProgress,864 Component,865 nextProps,866 renderLanes,867 );868 } else {869 shouldUpdate = updateClassInstance(870 current,871 workInProgress,872 Component,873 nextProps,874 renderLanes,875 );876 }877 const nextUnitOfWork = finishClassComponent(878 current,879 workInProgress,880 Component,881 shouldUpdate,882 hasContext,883 renderLanes,884 );885 if (__DEV__) {886 const inst = workInProgress.stateNode;887 if (shouldUpdate && inst.props !== nextProps) {888 if (!didWarnAboutReassigningProps) {889 console.error(890 'It looks like %s is reassigning its own `this.props` while rendering. ' +891 'This is not supported and can lead to confusing bugs.',892 getComponentName(workInProgress.type) || 'a component',893 );894 }895 didWarnAboutReassigningProps = true;896 }897 }898 return nextUnitOfWork;899}900function finishClassComponent(901 current: Fiber | null,902 workInProgress: Fiber,903 Component: any,904 shouldUpdate: boolean,905 hasContext: boolean,906 renderLanes: Lanes,907) {908 // Refs should update even if shouldComponentUpdate returns false909 markRef(current, workInProgress);910 const didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags;911 if (!shouldUpdate && !didCaptureError) {912 // Context providers should defer to sCU for rendering913 if (hasContext) {914 invalidateContextProvider(workInProgress, Component, false);915 }916 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);917 }918 const instance = workInProgress.stateNode;919 // Rerender920 ReactCurrentOwner.current = workInProgress;921 let nextChildren;922 if (923 didCaptureError &&924 typeof Component.getDerivedStateFromError !== 'function'925 ) {926 // If we captured an error, but getDerivedStateFromError is not defined,927 // unmount all the children. componentDidCatch will schedule an update to928 // re-render a fallback. This is temporary until we migrate everyone to929 // the new API.930 // TODO: Warn in a future release.931 nextChildren = null;932 if (enableProfilerTimer) {933 stopProfilerTimerIfRunning(workInProgress);934 }935 } else {936 if (__DEV__) {937 setIsRendering(true);938 nextChildren = instance.render();939 if (940 debugRenderPhaseSideEffectsForStrictMode &&941 workInProgress.mode & StrictMode942 ) {943 disableLogs();944 try {945 instance.render();946 } finally {947 reenableLogs();948 }949 }950 setIsRendering(false);951 } else {952 nextChildren = instance.render();953 }954 }955 // React DevTools reads this flag.956 workInProgress.flags |= PerformedWork;957 if (current !== null && didCaptureError) {958 // If we're recovering from an error, reconcile without reusing any of959 // the existing children. Conceptually, the normal children and the children960 // that are shown on error are two different sets, so we shouldn't reuse961 // normal children even if their identities match.962 forceUnmountCurrentAndReconcile(963 current,964 workInProgress,965 nextChildren,966 renderLanes,967 );968 } else {969 reconcileChildren(current, workInProgress, nextChildren, renderLanes);970 }971 // Memoize state using the values we just used to render.972 // TODO: Restructure so we never read values from the instance.973 workInProgress.memoizedState = instance.state;974 // The context might have changed so we need to recalculate it.975 if (hasContext) {976 invalidateContextProvider(workInProgress, Component, true);977 }978 return workInProgress.child;979}980function pushHostRootContext(workInProgress) {981 const root = (workInProgress.stateNode: FiberRoot);982 if (root.pendingContext) {983 pushTopLevelContextObject(984 workInProgress,985 root.pendingContext,986 root.pendingContext !== root.context,987 );988 } else if (root.context) {989 // Should always be set990 pushTopLevelContextObject(workInProgress, root.context, false);991 }992 pushHostContainer(workInProgress, root.containerInfo);993}994function updateHostRoot(current, workInProgress, renderLanes) {995 pushHostRootContext(workInProgress);996 const updateQueue = workInProgress.updateQueue;997 invariant(998 current !== null && updateQueue !== null,999 'If the root does not have an updateQueue, we should have already ' +1000 'bailed out. This error is likely caused by a bug in React. Please ' +1001 'file an issue.',1002 );1003 const nextProps = workInProgress.pendingProps;1004 const prevState = workInProgress.memoizedState;1005 const prevChildren = prevState !== null ? prevState.element : null;1006 cloneUpdateQueue(current, workInProgress);1007 processUpdateQueue(workInProgress, nextProps, null, renderLanes);1008 const nextState = workInProgress.memoizedState;1009 // Caution: React DevTools currently depends on this property1010 // being called "element".1011 const nextChildren = nextState.element;1012 if (nextChildren === prevChildren) {1013 resetHydrationState();1014 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);1015 }1016 const root: FiberRoot = workInProgress.stateNode;1017 if (root.hydrate && enterHydrationState(workInProgress)) {1018 // If we don't have any current children this might be the first pass.1019 // We always try to hydrate. If this isn't a hydration pass there won't1020 // be any children to hydrate which is effectively the same thing as1021 // not hydrating.1022 if (supportsHydration) {1023 const mutableSourceEagerHydrationData =1024 root.mutableSourceEagerHydrationData;1025 if (mutableSourceEagerHydrationData != null) {1026 for (let i = 0; i < mutableSourceEagerHydrationData.length; i += 2) {1027 const mutableSource = ((mutableSourceEagerHydrationData[1028 i1029 ]: any): MutableSource<any>);1030 const version = mutableSourceEagerHydrationData[i + 1];1031 setWorkInProgressVersion(mutableSource, version);1032 }1033 }1034 }1035 const child = mountChildFibers(1036 workInProgress,1037 null,1038 nextChildren,1039 renderLanes,1040 );1041 workInProgress.child = child;1042 let node = child;1043 while (node) {1044 // Mark each child as hydrating. This is a fast path to know whether this1045 // tree is part of a hydrating tree. This is used to determine if a child1046 // node has fully mounted yet, and for scheduling event replaying.1047 // Conceptually this is similar to Placement in that a new subtree is1048 // inserted into the React tree here. It just happens to not need DOM1049 // mutations because it already exists.1050 node.flags = (node.flags & ~Placement) | Hydrating;1051 node = node.sibling;1052 }1053 } else {1054 // Otherwise reset hydration state in case we aborted and resumed another1055 // root.1056 reconcileChildren(current, workInProgress, nextChildren, renderLanes);1057 resetHydrationState();1058 }1059 return workInProgress.child;1060}1061function updateHostComponent(1062 current: Fiber | null,1063 workInProgress: Fiber,1064 renderLanes: Lanes,1065) {1066 pushHostContext(workInProgress);1067 if (current === null) {1068 tryToClaimNextHydratableInstance(workInProgress);1069 }1070 const type = workInProgress.type;1071 const nextProps = workInProgress.pendingProps;1072 const prevProps = current !== null ? current.memoizedProps : null;1073 let nextChildren = nextProps.children;1074 const isDirectTextChild = shouldSetTextContent(type, nextProps);1075 if (isDirectTextChild) {1076 // We special case a direct text child of a host node. This is a common1077 // case. We won't handle it as a reified child. We will instead handle1078 // this in the host environment that also has access to this prop. That1079 // avoids allocating another HostText fiber and traversing it.1080 nextChildren = null;1081 } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {1082 // If we're switching from a direct text child to a normal child, or to1083 // empty, we need to schedule the text content to be reset.1084 workInProgress.flags |= ContentReset;1085 }1086 // React DevTools reads this flag.1087 workInProgress.flags |= PerformedWork;1088 markRef(current, workInProgress);1089 reconcileChildren(current, workInProgress, nextChildren, renderLanes);1090 return workInProgress.child;1091}1092function updateHostText(current, workInProgress) {1093 if (current === null) {1094 tryToClaimNextHydratableInstance(workInProgress);1095 }1096 // Nothing to do here. This is terminal. We'll do the completion step1097 // immediately after.1098 return null;1099}1100function mountLazyComponent(1101 _current,1102 workInProgress,1103 elementType,1104 updateLanes,1105 renderLanes,1106) {1107 if (_current !== null) {1108 // A lazy component only mounts if it suspended inside a non-1109 // concurrent tree, in an inconsistent state. We want to treat it like1110 // a new mount, even though an empty version of it already committed.1111 // Disconnect the alternate pointers.1112 _current.alternate = null;1113 workInProgress.alternate = null;1114 // Since this is conceptually a new fiber, schedule a Placement effect1115 workInProgress.flags |= Placement;1116 }1117 const props = workInProgress.pendingProps;1118 const lazyComponent: LazyComponentType<any, any> = elementType;1119 const payload = lazyComponent._payload;1120 const init = lazyComponent._init;1121 let Component = init(payload);1122 // Store the unwrapped component in the type.1123 workInProgress.type = Component;1124 const resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component));1125 const resolvedProps = resolveDefaultProps(Component, props);1126 let child;1127 switch (resolvedTag) {1128 case FunctionComponent: {1129 if (__DEV__) {1130 validateFunctionComponentInDev(workInProgress, Component);1131 workInProgress.type = Component = resolveFunctionForHotReloading(1132 Component,1133 );1134 }1135 child = updateFunctionComponent(1136 null,1137 workInProgress,1138 Component,1139 resolvedProps,1140 renderLanes,1141 );1142 return child;1143 }1144 case ClassComponent: {1145 if (__DEV__) {1146 workInProgress.type = Component = resolveClassForHotReloading(1147 Component,1148 );1149 }1150 child = updateClassComponent(1151 null,1152 workInProgress,1153 Component,1154 resolvedProps,1155 renderLanes,1156 );1157 return child;1158 }1159 case ForwardRef: {1160 if (__DEV__) {1161 workInProgress.type = Component = resolveForwardRefForHotReloading(1162 Component,1163 );1164 }1165 child = updateForwardRef(1166 null,1167 workInProgress,1168 Component,1169 resolvedProps,1170 renderLanes,1171 );1172 return child;1173 }1174 case MemoComponent: {1175 if (__DEV__) {1176 if (workInProgress.type !== workInProgress.elementType) {1177 const outerPropTypes = Component.propTypes;1178 if (outerPropTypes) {1179 checkPropTypes(1180 outerPropTypes,1181 resolvedProps, // Resolved for outer only1182 'prop',1183 getComponentName(Component),1184 );1185 }1186 }1187 }1188 child = updateMemoComponent(1189 null,1190 workInProgress,1191 Component,1192 resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too1193 updateLanes,1194 renderLanes,1195 );1196 return child;1197 }1198 case Block: {1199 if (enableBlocksAPI) {1200 // TODO: Resolve for Hot Reloading.1201 child = updateBlock(1202 null,1203 workInProgress,1204 Component,1205 props,1206 renderLanes,1207 );1208 return child;1209 }1210 break;1211 }1212 }1213 let hint = '';1214 if (__DEV__) {1215 if (1216 Component !== null &&1217 typeof Component === 'object' &&1218 Component.$$typeof === REACT_LAZY_TYPE1219 ) {1220 hint = ' Did you wrap a component in React.lazy() more than once?';1221 }1222 }1223 // This message intentionally doesn't mention ForwardRef or MemoComponent1224 // because the fact that it's a separate type of work is an1225 // implementation detail.1226 invariant(1227 false,1228 'Element type is invalid. Received a promise that resolves to: %s. ' +1229 'Lazy element type must resolve to a class or function.%s',1230 Component,1231 hint,1232 );1233}1234function mountIncompleteClassComponent(1235 _current,1236 workInProgress,1237 Component,1238 nextProps,1239 renderLanes,1240) {1241 if (_current !== null) {1242 // An incomplete component only mounts if it suspended inside a non-1243 // concurrent tree, in an inconsistent state. We want to treat it like1244 // a new mount, even though an empty version of it already committed.1245 // Disconnect the alternate pointers.1246 _current.alternate = null;1247 workInProgress.alternate = null;1248 // Since this is conceptually a new fiber, schedule a Placement effect1249 workInProgress.flags |= Placement;1250 }1251 // Promote the fiber to a class and try rendering again.1252 workInProgress.tag = ClassComponent;1253 // The rest of this function is a fork of `updateClassComponent`1254 // Push context providers early to prevent context stack mismatches.1255 // During mounting we don't know the child context yet as the instance doesn't exist.1256 // We will invalidate the child context in finishClassComponent() right after rendering.1257 let hasContext;1258 if (isLegacyContextProvider(Component)) {1259 hasContext = true;1260 pushLegacyContextProvider(workInProgress);1261 } else {1262 hasContext = false;1263 }1264 prepareToReadContext(workInProgress, renderLanes);1265 constructClassInstance(workInProgress, Component, nextProps);1266 mountClassInstance(workInProgress, Component, nextProps, renderLanes);1267 return finishClassComponent(1268 null,1269 workInProgress,1270 Component,1271 true,1272 hasContext,1273 renderLanes,1274 );1275}1276function mountIndeterminateComponent(1277 _current,1278 workInProgress,1279 Component,1280 renderLanes,1281) {1282 if (_current !== null) {1283 // An indeterminate component only mounts if it suspended inside a non-1284 // concurrent tree, in an inconsistent state. We want to treat it like1285 // a new mount, even though an empty version of it already committed.1286 // Disconnect the alternate pointers.1287 _current.alternate = null;1288 workInProgress.alternate = null;1289 // Since this is conceptually a new fiber, schedule a Placement effect1290 workInProgress.flags |= Placement;1291 }1292 const props = workInProgress.pendingProps;1293 let context;1294 if (!disableLegacyContext) {1295 const unmaskedContext = getUnmaskedContext(1296 workInProgress,1297 Component,1298 false,1299 );1300 context = getMaskedContext(workInProgress, unmaskedContext);1301 }1302 prepareToReadContext(workInProgress, renderLanes);1303 let value;1304 if (__DEV__) {1305 if (1306 Component.prototype &&1307 typeof Component.prototype.render === 'function'1308 ) {1309 const componentName = getComponentName(Component) || 'Unknown';1310 if (!didWarnAboutBadClass[componentName]) {1311 console.error(1312 "The <%s /> component appears to have a render method, but doesn't extend React.Component. " +1313 'This is likely to cause errors. Change %s to extend React.Component instead.',1314 componentName,1315 componentName,1316 );1317 didWarnAboutBadClass[componentName] = true;1318 }1319 }1320 if (workInProgress.mode & StrictMode) {1321 ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);1322 }1323 setIsRendering(true);1324 ReactCurrentOwner.current = workInProgress;1325 value = renderWithHooks(1326 null,1327 workInProgress,1328 Component,1329 props,1330 context,1331 renderLanes,1332 );1333 setIsRendering(false);1334 } else {1335 value = renderWithHooks(1336 null,1337 workInProgress,1338 Component,1339 props,1340 context,1341 renderLanes,1342 );1343 }1344 // React DevTools reads this flag.1345 workInProgress.flags |= PerformedWork;1346 if (__DEV__) {1347 // Support for module components is deprecated and is removed behind a flag.1348 // Whether or not it would crash later, we want to show a good message in DEV first.1349 if (1350 typeof value === 'object' &&1351 value !== null &&1352 typeof value.render === 'function' &&1353 value.$$typeof === undefined1354 ) {1355 const componentName = getComponentName(Component) || 'Unknown';1356 if (!didWarnAboutModulePatternComponent[componentName]) {1357 console.error(1358 'The <%s /> component appears to be a function component that returns a class instance. ' +1359 'Change %s to a class that extends React.Component instead. ' +1360 "If you can't use a class try assigning the prototype on the function as a workaround. " +1361 "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " +1362 'cannot be called with `new` by React.',1363 componentName,1364 componentName,1365 componentName,1366 );1367 didWarnAboutModulePatternComponent[componentName] = true;1368 }1369 }1370 }1371 if (1372 // Run these checks in production only if the flag is off.1373 // Eventually we'll delete this branch altogether.1374 !disableModulePatternComponents &&1375 typeof value === 'object' &&1376 value !== null &&1377 typeof value.render === 'function' &&1378 value.$$typeof === undefined1379 ) {1380 if (__DEV__) {1381 const componentName = getComponentName(Component) || 'Unknown';1382 if (!didWarnAboutModulePatternComponent[componentName]) {1383 console.error(1384 'The <%s /> component appears to be a function component that returns a class instance. ' +1385 'Change %s to a class that extends React.Component instead. ' +1386 "If you can't use a class try assigning the prototype on the function as a workaround. " +1387 "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " +1388 'cannot be called with `new` by React.',1389 componentName,1390 componentName,1391 componentName,1392 );1393 didWarnAboutModulePatternComponent[componentName] = true;1394 }1395 }1396 // Proceed under the assumption that this is a class instance1397 workInProgress.tag = ClassComponent;1398 // Throw out any hooks that were used.1399 workInProgress.memoizedState = null;1400 workInProgress.updateQueue = null;1401 // Push context providers early to prevent context stack mismatches.1402 // During mounting we don't know the child context yet as the instance doesn't exist.1403 // We will invalidate the child context in finishClassComponent() right after rendering.1404 let hasContext = false;1405 if (isLegacyContextProvider(Component)) {1406 hasContext = true;1407 pushLegacyContextProvider(workInProgress);1408 } else {1409 hasContext = false;1410 }1411 workInProgress.memoizedState =1412 value.state !== null && value.state !== undefined ? value.state : null;1413 initializeUpdateQueue(workInProgress);1414 const getDerivedStateFromProps = Component.getDerivedStateFromProps;1415 if (typeof getDerivedStateFromProps === 'function') {1416 applyDerivedStateFromProps(1417 workInProgress,1418 Component,1419 getDerivedStateFromProps,1420 props,1421 );1422 }1423 adoptClassInstance(workInProgress, value);1424 mountClassInstance(workInProgress, Component, props, renderLanes);1425 return finishClassComponent(1426 null,1427 workInProgress,1428 Component,1429 true,1430 hasContext,1431 renderLanes,1432 );1433 } else {1434 // Proceed under the assumption that this is a function component1435 workInProgress.tag = FunctionComponent;1436 if (__DEV__) {1437 if (disableLegacyContext && Component.contextTypes) {1438 console.error(1439 '%s uses the legacy contextTypes API which is no longer supported. ' +1440 'Use React.createContext() with React.useContext() instead.',1441 getComponentName(Component) || 'Unknown',1442 );1443 }1444 if (1445 debugRenderPhaseSideEffectsForStrictMode &&1446 workInProgress.mode & StrictMode1447 ) {1448 disableLogs();1449 try {1450 value = renderWithHooks(1451 null,1452 workInProgress,1453 Component,1454 props,1455 context,1456 renderLanes,1457 );1458 } finally {1459 reenableLogs();1460 }1461 }1462 }1463 reconcileChildren(null, workInProgress, value, renderLanes);1464 if (__DEV__) {1465 validateFunctionComponentInDev(workInProgress, Component);1466 }1467 return workInProgress.child;1468 }1469}1470function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {1471 if (__DEV__) {1472 if (Component) {1473 if (Component.childContextTypes) {1474 console.error(1475 '%s(...): childContextTypes cannot be defined on a function component.',1476 Component.displayName || Component.name || 'Component',1477 );1478 }1479 }1480 if (workInProgress.ref !== null) {1481 let info = '';1482 const ownerName = getCurrentFiberOwnerNameInDevOrNull();1483 if (ownerName) {1484 info += '\n\nCheck the render method of `' + ownerName + '`.';1485 }1486 let warningKey = ownerName || workInProgress._debugID || '';1487 const debugSource = workInProgress._debugSource;1488 if (debugSource) {1489 warningKey = debugSource.fileName + ':' + debugSource.lineNumber;1490 }1491 if (!didWarnAboutFunctionRefs[warningKey]) {1492 didWarnAboutFunctionRefs[warningKey] = true;1493 console.error(1494 'Function components cannot be given refs. ' +1495 'Attempts to access this ref will fail. ' +1496 'Did you mean to use React.forwardRef()?%s',1497 info,1498 );1499 }1500 }1501 if (1502 warnAboutDefaultPropsOnFunctionComponents &&1503 Component.defaultProps !== undefined1504 ) {1505 const componentName = getComponentName(Component) || 'Unknown';1506 if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) {1507 console.error(1508 '%s: Support for defaultProps will be removed from function components ' +1509 'in a future major release. Use JavaScript default parameters instead.',1510 componentName,1511 );1512 didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true;1513 }1514 }1515 if (typeof Component.getDerivedStateFromProps === 'function') {1516 const componentName = getComponentName(Component) || 'Unknown';1517 if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {1518 console.error(1519 '%s: Function components do not support getDerivedStateFromProps.',1520 componentName,1521 );1522 didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;1523 }1524 }1525 if (1526 typeof Component.contextType === 'object' &&1527 Component.contextType !== null1528 ) {1529 const componentName = getComponentName(Component) || 'Unknown';1530 if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {1531 console.error(1532 '%s: Function components do not support contextType.',1533 componentName,1534 );1535 didWarnAboutContextTypeOnFunctionComponent[componentName] = true;1536 }1537 }1538 }1539}1540const SUSPENDED_MARKER: SuspenseState = {1541 dehydrated: null,1542 retryLane: NoLane,1543};1544function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {1545 return {1546 baseLanes: renderLanes,1547 };1548}1549function updateSuspenseOffscreenState(1550 prevOffscreenState: OffscreenState,1551 renderLanes: Lanes,1552): OffscreenState {1553 return {1554 baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes),1555 };1556}1557// TODO: Probably should inline this back1558function shouldRemainOnFallback(1559 suspenseContext: SuspenseContext,1560 current: null | Fiber,1561 workInProgress: Fiber,1562 renderLanes: Lanes,1563) {1564 // If we're already showing a fallback, there are cases where we need to1565 // remain on that fallback regardless of whether the content has resolved.1566 // For example, SuspenseList coordinates when nested content appears.1567 if (current !== null) {1568 const suspenseState: SuspenseState = current.memoizedState;1569 if (suspenseState === null) {1570 // Currently showing content. Don't hide it, even if ForceSuspenseFallack1571 // is true. More precise name might be "ForceRemainSuspenseFallback".1572 // Note: This is a factoring smell. Can't remain on a fallback if there's1573 // no fallback to remain on.1574 return false;1575 }1576 }1577 // Not currently showing content. Consult the Suspense context.1578 return hasSuspenseContext(1579 suspenseContext,1580 (ForceSuspenseFallback: SuspenseContext),1581 );1582}1583function getRemainingWorkInPrimaryTree(current: Fiber, renderLanes) {1584 // TODO: Should not remove render lanes that were pinged during this render1585 return removeLanes(current.childLanes, renderLanes);1586}1587function updateSuspenseComponent(current, workInProgress, renderLanes) {1588 const nextProps = workInProgress.pendingProps;1589 // This is used by DevTools to force a boundary to suspend.1590 if (__DEV__) {1591 if (shouldSuspend(workInProgress)) {1592 workInProgress.flags |= DidCapture;1593 }1594 }1595 let suspenseContext: SuspenseContext = suspenseStackCursor.current;1596 let showFallback = false;1597 const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;1598 if (1599 didSuspend ||1600 shouldRemainOnFallback(1601 suspenseContext,1602 current,1603 workInProgress,1604 renderLanes,1605 )1606 ) {1607 // Something in this boundary's subtree already suspended. Switch to1608 // rendering the fallback children.1609 showFallback = true;1610 workInProgress.flags &= ~DidCapture;1611 } else {1612 // Attempting the main content1613 if (1614 current === null ||1615 (current.memoizedState: null | SuspenseState) !== null1616 ) {1617 // This is a new mount or this boundary is already showing a fallback state.1618 // Mark this subtree context as having at least one invisible parent that could1619 // handle the fallback state.1620 // Boundaries without fallbacks or should be avoided are not considered since1621 // they cannot handle preferred fallback states.1622 if (1623 nextProps.fallback !== undefined &&1624 nextProps.unstable_avoidThisFallback !== true1625 ) {1626 suspenseContext = addSubtreeSuspenseContext(1627 suspenseContext,1628 InvisibleParentSuspenseContext,1629 );1630 }1631 }1632 }1633 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);1634 pushSuspenseContext(workInProgress, suspenseContext);1635 // OK, the next part is confusing. We're about to reconcile the Suspense1636 // boundary's children. This involves some custom reconcilation logic. Two1637 // main reasons this is so complicated.1638 //1639 // First, Legacy Mode has different semantics for backwards compatibility. The1640 // primary tree will commit in an inconsistent state, so when we do the1641 // second pass to render the fallback, we do some exceedingly, uh, clever1642 // hacks to make that not totally break. Like transferring effects and1643 // deletions from hidden tree. In Concurrent Mode, it's much simpler,1644 // because we bailout on the primary tree completely and leave it in its old1645 // state, no effects. Same as what we do for Offscreen (except that1646 // Offscreen doesn't have the first render pass).1647 //1648 // Second is hydration. During hydration, the Suspense fiber has a slightly1649 // different layout, where the child points to a dehydrated fragment, which1650 // contains the DOM rendered by the server.1651 //1652 // Third, even if you set all that aside, Suspense is like error boundaries in1653 // that we first we try to render one tree, and if that fails, we render again1654 // and switch to a different tree. Like a try/catch block. So we have to track1655 // which branch we're currently rendering. Ideally we would model this using1656 // a stack.1657 if (current === null) {1658 // Initial mount1659 // If we're currently hydrating, try to hydrate this boundary.1660 // But only if this has a fallback.1661 if (nextProps.fallback !== undefined) {1662 tryToClaimNextHydratableInstance(workInProgress);1663 // This could've been a dehydrated suspense component.1664 if (enableSuspenseServerRenderer) {1665 const suspenseState: null | SuspenseState =1666 workInProgress.memoizedState;1667 if (suspenseState !== null) {1668 const dehydrated = suspenseState.dehydrated;1669 if (dehydrated !== null) {1670 return mountDehydratedSuspenseComponent(1671 workInProgress,1672 dehydrated,1673 renderLanes,1674 );1675 }1676 }1677 }1678 }1679 const nextPrimaryChildren = nextProps.children;1680 const nextFallbackChildren = nextProps.fallback;1681 if (showFallback) {1682 const fallbackFragment = mountSuspenseFallbackChildren(1683 workInProgress,1684 nextPrimaryChildren,1685 nextFallbackChildren,1686 renderLanes,1687 );1688 const primaryChildFragment: Fiber = (workInProgress.child: any);1689 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(1690 renderLanes,1691 );1692 workInProgress.memoizedState = SUSPENDED_MARKER;1693 return fallbackFragment;1694 } else if (typeof nextProps.unstable_expectedLoadTime === 'number') {1695 // This is a CPU-bound tree. Skip this tree and show a placeholder to1696 // unblock the surrounding content. Then immediately retry after the1697 // initial commit.1698 const fallbackFragment = mountSuspenseFallbackChildren(1699 workInProgress,1700 nextPrimaryChildren,1701 nextFallbackChildren,1702 renderLanes,1703 );1704 const primaryChildFragment: Fiber = (workInProgress.child: any);1705 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(1706 renderLanes,1707 );1708 workInProgress.memoizedState = SUSPENDED_MARKER;1709 // Since nothing actually suspended, there will nothing to ping this to1710 // get it started back up to attempt the next item. While in terms of1711 // priority this work has the same priority as this current render, it's1712 // not part of the same transition once the transition has committed. If1713 // it's sync, we still want to yield so that it can be painted.1714 // Conceptually, this is really the same as pinging. We can use any1715 // RetryLane even if it's the one currently rendering since we're leaving1716 // it behind on this node.1717 workInProgress.lanes = SomeRetryLane;1718 if (enableSchedulerTracing) {1719 markSpawnedWork(SomeRetryLane);1720 }1721 return fallbackFragment;1722 } else {1723 return mountSuspensePrimaryChildren(1724 workInProgress,1725 nextPrimaryChildren,1726 renderLanes,1727 );1728 }1729 } else {1730 // This is an update.1731 // If the current fiber has a SuspenseState, that means it's already showing1732 // a fallback.1733 const prevState: null | SuspenseState = current.memoizedState;1734 if (prevState !== null) {1735 // The current tree is already showing a fallback1736 // Special path for hydration1737 if (enableSuspenseServerRenderer) {1738 const dehydrated = prevState.dehydrated;1739 if (dehydrated !== null) {1740 if (!didSuspend) {1741 return updateDehydratedSuspenseComponent(1742 current,1743 workInProgress,1744 dehydrated,1745 prevState,1746 renderLanes,1747 );1748 } else if (1749 (workInProgress.memoizedState: null | SuspenseState) !== null1750 ) {1751 // Something suspended and we should still be in dehydrated mode.1752 // Leave the existing child in place.1753 workInProgress.child = current.child;1754 // The dehydrated completion pass expects this flag to be there1755 // but the normal suspense pass doesn't.1756 workInProgress.flags |= DidCapture;1757 return null;1758 } else {1759 // Suspended but we should no longer be in dehydrated mode.1760 // Therefore we now have to render the fallback.1761 const nextPrimaryChildren = nextProps.children;1762 const nextFallbackChildren = nextProps.fallback;1763 const fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(1764 current,1765 workInProgress,1766 nextPrimaryChildren,1767 nextFallbackChildren,1768 renderLanes,1769 );1770 const primaryChildFragment: Fiber = (workInProgress.child: any);1771 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(1772 renderLanes,1773 );1774 workInProgress.memoizedState = SUSPENDED_MARKER;1775 return fallbackChildFragment;1776 }1777 }1778 }1779 if (showFallback) {1780 const nextFallbackChildren = nextProps.fallback;1781 const nextPrimaryChildren = nextProps.children;1782 const fallbackChildFragment = updateSuspenseFallbackChildren(1783 current,1784 workInProgress,1785 nextPrimaryChildren,1786 nextFallbackChildren,1787 renderLanes,1788 );1789 const primaryChildFragment: Fiber = (workInProgress.child: any);1790 const prevOffscreenState: OffscreenState | null = (current.child: any)1791 .memoizedState;1792 primaryChildFragment.memoizedState =1793 prevOffscreenState === null1794 ? mountSuspenseOffscreenState(renderLanes)1795 : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);1796 primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(1797 current,1798 renderLanes,1799 );1800 workInProgress.memoizedState = SUSPENDED_MARKER;1801 return fallbackChildFragment;1802 } else {1803 const nextPrimaryChildren = nextProps.children;1804 const primaryChildFragment = updateSuspensePrimaryChildren(1805 current,1806 workInProgress,1807 nextPrimaryChildren,1808 renderLanes,1809 );1810 workInProgress.memoizedState = null;1811 return primaryChildFragment;1812 }1813 } else {1814 // The current tree is not already showing a fallback.1815 if (showFallback) {1816 // Timed out.1817 const nextFallbackChildren = nextProps.fallback;1818 const nextPrimaryChildren = nextProps.children;1819 const fallbackChildFragment = updateSuspenseFallbackChildren(1820 current,1821 workInProgress,1822 nextPrimaryChildren,1823 nextFallbackChildren,1824 renderLanes,1825 );1826 const primaryChildFragment: Fiber = (workInProgress.child: any);1827 const prevOffscreenState: OffscreenState | null = (current.child: any)1828 .memoizedState;1829 primaryChildFragment.memoizedState =1830 prevOffscreenState === null1831 ? mountSuspenseOffscreenState(renderLanes)1832 : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);1833 primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(1834 current,1835 renderLanes,1836 );1837 // Skip the primary children, and continue working on the1838 // fallback children.1839 workInProgress.memoizedState = SUSPENDED_MARKER;1840 return fallbackChildFragment;1841 } else {1842 // Still haven't timed out. Continue rendering the children, like we1843 // normally do.1844 const nextPrimaryChildren = nextProps.children;1845 const primaryChildFragment = updateSuspensePrimaryChildren(1846 current,1847 workInProgress,1848 nextPrimaryChildren,1849 renderLanes,1850 );1851 workInProgress.memoizedState = null;1852 return primaryChildFragment;1853 }1854 }1855 }1856}1857function mountSuspensePrimaryChildren(1858 workInProgress,1859 primaryChildren,1860 renderLanes,1861) {1862 const mode = workInProgress.mode;1863 const primaryChildProps: OffscreenProps = {1864 mode: 'visible',1865 children: primaryChildren,1866 };1867 const primaryChildFragment = createFiberFromOffscreen(1868 primaryChildProps,1869 mode,1870 renderLanes,1871 null,1872 );1873 primaryChildFragment.return = workInProgress;1874 workInProgress.child = primaryChildFragment;1875 return primaryChildFragment;1876}1877function mountSuspenseFallbackChildren(1878 workInProgress,1879 primaryChildren,1880 fallbackChildren,1881 renderLanes,1882) {1883 const mode = workInProgress.mode;1884 const progressedPrimaryFragment: Fiber | null = workInProgress.child;1885 const primaryChildProps: OffscreenProps = {1886 mode: 'hidden',1887 children: primaryChildren,1888 };1889 let primaryChildFragment;1890 let fallbackChildFragment;1891 if ((mode & BlockingMode) === NoMode && progressedPrimaryFragment !== null) {1892 // In legacy mode, we commit the primary tree as if it successfully1893 // completed, even though it's in an inconsistent state.1894 primaryChildFragment = progressedPrimaryFragment;1895 primaryChildFragment.childLanes = NoLanes;1896 primaryChildFragment.pendingProps = primaryChildProps;1897 if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1898 // Reset the durations from the first pass so they aren't included in the1899 // final amounts. This seems counterintuitive, since we're intentionally1900 // not measuring part of the render phase, but this makes it match what we1901 // do in Concurrent Mode.1902 primaryChildFragment.actualDuration = 0;1903 primaryChildFragment.actualStartTime = -1;1904 primaryChildFragment.selfBaseDuration = 0;1905 primaryChildFragment.treeBaseDuration = 0;1906 }1907 fallbackChildFragment = createFiberFromFragment(1908 fallbackChildren,1909 mode,1910 renderLanes,1911 null,1912 );1913 } else {1914 primaryChildFragment = createFiberFromOffscreen(1915 primaryChildProps,1916 mode,1917 NoLanes,1918 null,1919 );1920 fallbackChildFragment = createFiberFromFragment(1921 fallbackChildren,1922 mode,1923 renderLanes,1924 null,1925 );1926 }1927 primaryChildFragment.return = workInProgress;1928 fallbackChildFragment.return = workInProgress;1929 primaryChildFragment.sibling = fallbackChildFragment;1930 workInProgress.child = primaryChildFragment;1931 return fallbackChildFragment;1932}1933function createWorkInProgressOffscreenFiber(1934 current: Fiber,1935 offscreenProps: OffscreenProps,1936) {1937 // The props argument to `createWorkInProgress` is `any` typed, so we use this1938 // wrapper function to constrain it.1939 return createWorkInProgress(current, offscreenProps);1940}1941function updateSuspensePrimaryChildren(1942 current,1943 workInProgress,1944 primaryChildren,1945 renderLanes,1946) {1947 const currentPrimaryChildFragment: Fiber = (current.child: any);1948 const currentFallbackChildFragment: Fiber | null =1949 currentPrimaryChildFragment.sibling;1950 const primaryChildFragment = createWorkInProgressOffscreenFiber(1951 currentPrimaryChildFragment,1952 {1953 mode: 'visible',1954 children: primaryChildren,1955 },1956 );1957 if ((workInProgress.mode & BlockingMode) === NoMode) {1958 primaryChildFragment.lanes = renderLanes;1959 }1960 primaryChildFragment.return = workInProgress;1961 primaryChildFragment.sibling = null;1962 if (currentFallbackChildFragment !== null) {1963 // Delete the fallback child fragment1964 const deletions = workInProgress.deletions;1965 if (deletions === null) {1966 workInProgress.deletions = [currentFallbackChildFragment];1967 // TODO (effects) Rename this to better reflect its new usage (e.g. ChildDeletions)1968 workInProgress.flags |= Deletion;1969 } else {1970 deletions.push(currentFallbackChildFragment);1971 }1972 }1973 workInProgress.child = primaryChildFragment;1974 return primaryChildFragment;1975}1976function updateSuspenseFallbackChildren(1977 current,1978 workInProgress,1979 primaryChildren,1980 fallbackChildren,1981 renderLanes,1982) {1983 const mode = workInProgress.mode;1984 const currentPrimaryChildFragment: Fiber = (current.child: any);1985 const currentFallbackChildFragment: Fiber | null =1986 currentPrimaryChildFragment.sibling;1987 const primaryChildProps: OffscreenProps = {1988 mode: 'hidden',1989 children: primaryChildren,1990 };1991 let primaryChildFragment;1992 if (1993 // In legacy mode, we commit the primary tree as if it successfully1994 // completed, even though it's in an inconsistent state.1995 (mode & BlockingMode) === NoMode &&1996 // Make sure we're on the second pass, i.e. the primary child fragment was1997 // already cloned. In legacy mode, the only case where this isn't true is1998 // when DevTools forces us to display a fallback; we skip the first render1999 // pass entirely and go straight to rendering the fallback. (In Concurrent2000 // Mode, SuspenseList can also trigger this scenario, but this is a legacy-2001 // only codepath.)2002 workInProgress.child !== currentPrimaryChildFragment2003 ) {2004 const progressedPrimaryFragment: Fiber = (workInProgress.child: any);2005 primaryChildFragment = progressedPrimaryFragment;2006 primaryChildFragment.childLanes = NoLanes;2007 primaryChildFragment.pendingProps = primaryChildProps;2008 if (enableProfilerTimer && workInProgress.mode & ProfileMode) {2009 // Reset the durations from the first pass so they aren't included in the2010 // final amounts. This seems counterintuitive, since we're intentionally2011 // not measuring part of the render phase, but this makes it match what we2012 // do in Concurrent Mode.2013 primaryChildFragment.actualDuration = 0;2014 primaryChildFragment.actualStartTime = -1;2015 primaryChildFragment.selfBaseDuration =2016 currentPrimaryChildFragment.selfBaseDuration;2017 primaryChildFragment.treeBaseDuration =2018 currentPrimaryChildFragment.treeBaseDuration;2019 }2020 // The fallback fiber was added as a deletion effect during the first pass.2021 // However, since we're going to remain on the fallback, we no longer want2022 // to delete it.2023 workInProgress.deletions = null;2024 } else {2025 primaryChildFragment = createWorkInProgressOffscreenFiber(2026 currentPrimaryChildFragment,2027 primaryChildProps,2028 );2029 // Since we're reusing a current tree, we need to reuse the flags, too.2030 // (We don't do this in legacy mode, because in legacy mode we don't re-use2031 // the current tree; see previous branch.)2032 primaryChildFragment.subtreeFlags =2033 currentPrimaryChildFragment.subtreeFlags & StaticMask;2034 }2035 let fallbackChildFragment;2036 if (currentFallbackChildFragment !== null) {2037 fallbackChildFragment = createWorkInProgress(2038 currentFallbackChildFragment,2039 fallbackChildren,2040 );2041 } else {2042 fallbackChildFragment = createFiberFromFragment(2043 fallbackChildren,2044 mode,2045 renderLanes,2046 null,2047 );2048 // Needs a placement effect because the parent (the Suspense boundary) already2049 // mounted but this is a new fiber.2050 fallbackChildFragment.flags |= Placement;2051 }2052 fallbackChildFragment.return = workInProgress;2053 primaryChildFragment.return = workInProgress;2054 primaryChildFragment.sibling = fallbackChildFragment;2055 workInProgress.child = primaryChildFragment;2056 return fallbackChildFragment;2057}2058function retrySuspenseComponentWithoutHydrating(2059 current: Fiber,2060 workInProgress: Fiber,2061 renderLanes: Lanes,2062) {2063 // This will add the old fiber to the deletion list2064 reconcileChildFibers(workInProgress, current.child, null, renderLanes);2065 // We're now not suspended nor dehydrated.2066 const nextProps = workInProgress.pendingProps;2067 const primaryChildren = nextProps.children;2068 const primaryChildFragment = mountSuspensePrimaryChildren(2069 workInProgress,2070 primaryChildren,2071 renderLanes,2072 );2073 // Needs a placement effect because the parent (the Suspense boundary) already2074 // mounted but this is a new fiber.2075 primaryChildFragment.flags |= Placement;2076 workInProgress.memoizedState = null;2077 return primaryChildFragment;2078}2079function mountSuspenseFallbackAfterRetryWithoutHydrating(2080 current,2081 workInProgress,2082 primaryChildren,2083 fallbackChildren,2084 renderLanes,2085) {2086 const mode = workInProgress.mode;2087 const primaryChildFragment = createFiberFromOffscreen(2088 primaryChildren,2089 mode,2090 NoLanes,2091 null,2092 );2093 const fallbackChildFragment = createFiberFromFragment(2094 fallbackChildren,2095 mode,2096 renderLanes,2097 null,2098 );2099 // Needs a placement effect because the parent (the Suspense2100 // boundary) already mounted but this is a new fiber.2101 fallbackChildFragment.flags |= Placement;2102 primaryChildFragment.return = workInProgress;2103 fallbackChildFragment.return = workInProgress;2104 primaryChildFragment.sibling = fallbackChildFragment;2105 workInProgress.child = primaryChildFragment;2106 if ((workInProgress.mode & BlockingMode) !== NoMode) {2107 // We will have dropped the effect list which contains the2108 // deletion. We need to reconcile to delete the current child.2109 reconcileChildFibers(workInProgress, current.child, null, renderLanes);2110 }2111 return fallbackChildFragment;2112}2113function mountDehydratedSuspenseComponent(2114 workInProgress: Fiber,2115 suspenseInstance: SuspenseInstance,2116 renderLanes: Lanes,2117): null | Fiber {2118 // During the first pass, we'll bail out and not drill into the children.2119 // Instead, we'll leave the content in place and try to hydrate it later.2120 if ((workInProgress.mode & BlockingMode) === NoMode) {2121 if (__DEV__) {2122 console.error(2123 'Cannot hydrate Suspense in legacy mode. Switch from ' +2124 'ReactDOM.hydrate(element, container) to ' +2125 'ReactDOM.createBlockingRoot(container, { hydrate: true })' +2126 '.render(element) or remove the Suspense components from ' +2127 'the server rendered components.',2128 );2129 }2130 workInProgress.lanes = laneToLanes(SyncLane);2131 } else if (isSuspenseInstanceFallback(suspenseInstance)) {2132 // This is a client-only boundary. Since we won't get any content from the server2133 // for this, we need to schedule that at a higher priority based on when it would2134 // have timed out. In theory we could render it in this pass but it would have the2135 // wrong priority associated with it and will prevent hydration of parent path.2136 // Instead, we'll leave work left on it to render it in a separate commit.2137 // TODO This time should be the time at which the server rendered response that is2138 // a parent to this boundary was displayed. However, since we currently don't have2139 // a protocol to transfer that time, we'll just estimate it by using the current2140 // time. This will mean that Suspense timeouts are slightly shifted to later than2141 // they should be.2142 // Schedule a normal pri update to render this content.2143 if (enableSchedulerTracing) {2144 markSpawnedWork(DefaultHydrationLane);2145 }2146 workInProgress.lanes = laneToLanes(DefaultHydrationLane);2147 } else {2148 // We'll continue hydrating the rest at offscreen priority since we'll already2149 // be showing the right content coming from the server, it is no rush.2150 workInProgress.lanes = laneToLanes(OffscreenLane);2151 if (enableSchedulerTracing) {2152 markSpawnedWork(OffscreenLane);2153 }2154 }2155 return null;2156}2157function updateDehydratedSuspenseComponent(2158 current: Fiber,2159 workInProgress: Fiber,2160 suspenseInstance: SuspenseInstance,2161 suspenseState: SuspenseState,2162 renderLanes: Lanes,2163): null | Fiber {2164 // We should never be hydrating at this point because it is the first pass,...
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 lanes = await page._delegate.laneToLanes('default');7 console.log(lanes);8 await browser.close();9})();10[ Lane {11 _context: BrowserContext {12 },
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 lanes = await page._delegate.laneToLanes('1');7 console.log(lanes);8 await browser.close();9})();10 {11 }
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 const lanes = await page._delegate.laneToLanes('test');6 console.log(lanes);7 await browser.close();8})();9[ Lane {
Using AI Code Generation
1const { chromium } = require('playwright');2const { laneToLanes } = require('playwright/lib/server/frames');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const frames = await laneToLanes(page.mainFrame());8 console.log(frames.length);9 await browser.close();10})();
Using AI Code Generation
1const { chromium } = require('playwright');2const { pathToFileURL } = require('url');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 await page.waitForLoadState('networkidle');7 const frames = await page.mainFrame().childFrames();8 await frames[0].waitForLoadState('networkidle');9 const lanes = await frames[0].laneToLanes();10 console.log(lanes);11 await browser.close();12})();
Using AI Code Generation
1const playwright = require('playwright');2const { laneToLanes } = require('playwright/lib/server/browserContext');3(async () => {4 const browser = await playwright.chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();
Using AI Code Generation
1const {chromium} = require('playwright');2const browser = await chromium.launch({headless:false});3const context = await browser.newContext();4const page = await context.newPage();5const lanes = await page._delegate.laneToLanes('1');6console.log(lanes);7[ Lane {8 _page: Page {
Using AI Code Generation
1const { laneToLanes } = require('playwright/lib/utils/lanes.js');2const lanes = laneToLanes('1-2');3console.log(lanes);4const { laneToLanes } = require('playwright/lib/utils/lanes.js');5const lanes = laneToLanes('1-2, 3');6console.log(lanes);7const { laneToLanes } = require('playwright/lib/utils/lanes.js');8const lanes = laneToLanes('1-2, 3-4');9console.log(lanes);10const { laneToLanes } = require('playwright/lib/utils/lanes.js');11const lanes = laneToLanes('1-2, 3-4, 5');12console.log(lanes);13const { laneToLanes } = require('playwright/lib/utils/lanes.js');14const lanes = laneToLanes('1-2, 3-4, 5-6');15console.log(lanes);16const { laneToLanes } = require('playwright/lib/utils/lanes.js');17const lanes = laneToLanes('1-2, 3-4, 5-6, 7');18console.log(lanes);19const { laneToLanes } = require('play
Using AI Code Generation
1const { laneToLanes } = require('@playwright/test/lib/runner');2const lanes = laneToLanes('webkit,firefox', 3);3console.log('lanes', lanes);4const { laneToLanes } = require('@playwright/test/lib/runner');5const lanes = laneToLanes('webkit,firefox', 3);6console.log('lanes', lanes);7### `laneToLanes(lane: string, parallel: number): Lane[]`8[Apache License 2.0](
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!!