How to use laneToLanes method in Playwright Internal

Best JavaScript code snippet using playwright-internal

ReactFiberBeginWork.old.js

Source:ReactFiberBeginWork.old.js Github

copy

Full Screen

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

Full Screen

Full Screen

ReactFiberBeginWork.new.js

Source:ReactFiberBeginWork.new.js Github

copy

Full Screen

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

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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 }

Full Screen

Using AI Code Generation

copy

Full Screen

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 {

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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 {

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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](

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

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

Run Playwright Internal automation tests on LambdaTest cloud grid

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

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful