main
js 965 lines 28.2 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import type {ReactElement} from 'shared/ReactElementType';
11 import type {
12 ReactFragment,
13 ReactPortal,
14 ReactScope,
15 ViewTransitionProps,
16 ActivityProps,
17 ReactKey,
18 } from 'shared/ReactTypes';
19 import type {Fiber} from './ReactInternalTypes';
20 import type {RootTag} from './ReactRootTags';
21 import type {WorkTag} from './ReactWorkTags';
22 import type {TypeOfMode} from './ReactTypeOfMode';
23 import type {Lanes} from './ReactFiberLane';
24 import type {ActivityInstance, SuspenseInstance} from './ReactFiberConfig';
25 import type {
26 LegacyHiddenProps,
27 OffscreenProps,
28 } from './ReactFiberOffscreenComponent';
29 import type {ViewTransitionState} from './ReactFiberViewTransitionComponent';
30 import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';
31
32 import {
33 supportsResources,
34 supportsSingletons,
35 isHostHoistableType,
36 isHostSingletonType,
37 } from './ReactFiberConfig';
38 import {
39 enableProfilerTimer,
40 enableScopeAPI,
41 enableLegacyHidden,
42 enableTransitionTracing,
43 disableLegacyMode,
44 enableObjectFiber,
45 enableViewTransition,
46 enableSuspenseyImages,
47 enableOptimisticKey,
48 } from 'shared/ReactFeatureFlags';
49 import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
50 import {ConcurrentRoot} from './ReactRootTags';
51 import {
52 ClassComponent,
53 HostRoot,
54 HostComponent,
55 HostText,
56 HostPortal,
57 HostHoistable,
58 HostSingleton,
59 ForwardRef,
60 Fragment,
61 Mode,
62 ContextProvider,
63 ContextConsumer,
64 Profiler,
65 SuspenseComponent,
66 SuspenseListComponent,
67 DehydratedFragment,
68 FunctionComponent,
69 MemoComponent,
70 SimpleMemoComponent,
71 LazyComponent,
72 ScopeComponent,
73 OffscreenComponent,
74 LegacyHiddenComponent,
75 TracingMarkerComponent,
76 Throw,
77 ViewTransitionComponent,
78 ActivityComponent,
79 } from './ReactWorkTags';
80 import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';
81 import {isDevToolsPresent} from './ReactFiberDevToolsHook';
82 import {resolveTypeForHotReloading} from './ReactFiberHotReloading';
83 import {NoLanes} from './ReactFiberLane';
84 import {
85 NoMode,
86 ConcurrentMode,
87 ProfileMode,
88 StrictLegacyMode,
89 StrictEffectsMode,
90 SuspenseyImagesMode,
91 } from './ReactTypeOfMode';
92 import {
93 REACT_FORWARD_REF_TYPE,
94 REACT_FRAGMENT_TYPE,
95 REACT_STRICT_MODE_TYPE,
96 REACT_PROFILER_TYPE,
97 REACT_CONTEXT_TYPE,
98 REACT_CONSUMER_TYPE,
99 REACT_SUSPENSE_TYPE,
100 REACT_SUSPENSE_LIST_TYPE,
101 REACT_MEMO_TYPE,
102 REACT_LAZY_TYPE,
103 REACT_SCOPE_TYPE,
104 REACT_LEGACY_HIDDEN_TYPE,
105 REACT_TRACING_MARKER_TYPE,
106 REACT_ELEMENT_TYPE,
107 REACT_VIEW_TRANSITION_TYPE,
108 REACT_ACTIVITY_TYPE,
109 } from 'shared/ReactSymbols';
110 import {TransitionTracingMarker} from './ReactFiberTracingMarkerComponent';
111 import {getHostContext} from './ReactFiberHostContext';
112 import type {ReactComponentInfo} from '../../shared/ReactTypes';
113 import isArray from 'shared/isArray';
114 import getComponentNameFromType from 'shared/getComponentNameFromType';
115
116 export type {Fiber};
117
118 let hasBadMapPolyfill;
119
120 if (__DEV__) {
121 hasBadMapPolyfill = false;
122 try {
123 const nonExtensibleObject = Object.preventExtensions({});
124 // eslint-disable-next-line no-new
125 new Map([[nonExtensibleObject, null]]);
126 // eslint-disable-next-line no-new
127 new Set([nonExtensibleObject]);
128 } catch (e) {
129 // TODO: Consider warning about bad polyfills
130 hasBadMapPolyfill = true;
131 }
132 }
133
134 function FiberNode(
135 this: $FlowFixMe,
136 tag: WorkTag,
137 pendingProps: mixed,
138 key: ReactKey,
139 mode: TypeOfMode,
140 ) {
141 // Instance
142 this.tag = tag;
143 this.key = key;
144 this.elementType = null;
145 this.type = null;
146 this.stateNode = null;
147
148 // Fiber
149 this.return = null;
150 this.child = null;
151 this.sibling = null;
152 this.index = 0;
153
154 this.ref = null;
155 this.refCleanup = null;
156
157 this.pendingProps = pendingProps;
158 this.memoizedProps = null;
159 this.updateQueue = null;
160 this.memoizedState = null;
161 this.dependencies = null;
162
163 this.mode = mode;
164
165 // Effects
166 this.flags = NoFlags;
167 this.subtreeFlags = NoFlags;
168 this.deletions = null;
169
170 this.lanes = NoLanes;
171 this.childLanes = NoLanes;
172
173 this.alternate = null;
174
175 if (enableProfilerTimer) {
176 // Note: The following is done to avoid a v8 performance cliff.
177 //
178 // Initializing the fields below to smis and later updating them with
179 // double values will cause Fibers to end up having separate shapes.
180 // This behavior/bug has something to do with Object.preventExtension().
181 // Fortunately this only impacts DEV builds.
182 // Unfortunately it makes React unusably slow for some applications.
183 // To work around this, initialize the fields below with doubles.
184 //
185 // Learn more about this here:
186 // https://github.com/facebook/react/issues/14365
187 // https://bugs.chromium.org/p/v8/issues/detail?id=8538
188
189 this.actualDuration = -0;
190 this.actualStartTime = -1.1;
191 this.selfBaseDuration = -0;
192 this.treeBaseDuration = -0;
193 }
194
195 if (__DEV__) {
196 // This isn't directly used but is handy for debugging internals:
197 this._debugInfo = null;
198 this._debugOwner = null;
199 this._debugStack = null;
200 this._debugTask = null;
201 this._debugNeedsRemount = false;
202 this._debugHookTypes = null;
203 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
204 Object.preventExtensions(this);
205 }
206 }
207 }
208
209 // This is a constructor function, rather than a POJO constructor, still
210 // please ensure we do the following:
211 // 1) Nobody should add any instance methods on this. Instance methods can be
212 // more difficult to predict when they get optimized and they are almost
213 // never inlined properly in static compilers.
214 // 2) Nobody should rely on `instanceof Fiber` for type testing. We should
215 // always know when it is a fiber.
216 // 3) We might want to experiment with using numeric keys since they are easier
217 // to optimize in a non-JIT environment.
218 // 4) We can easily go from a constructor to a createFiber object literal if that
219 // is faster.
220 // 5) It should be easy to port this to a C struct and keep a C implementation
221 // compatible.
222 function createFiberImplClass(
223 tag: WorkTag,
224 pendingProps: mixed,
225 key: ReactKey,
226 mode: TypeOfMode,
227 ): Fiber {
228 // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
229 return new FiberNode(tag, pendingProps, key, mode);
230 }
231
232 function createFiberImplObject(
233 tag: WorkTag,
234 pendingProps: mixed,
235 key: ReactKey,
236 mode: TypeOfMode,
237 ): Fiber {
238 const fiber: Fiber = {
239 // Instance
240 // tag, key - defined at the bottom as dynamic properties
241 elementType: null,
242 type: null,
243 stateNode: null,
244
245 // Fiber
246 return: null,
247 child: null,
248 sibling: null,
249 index: 0,
250
251 ref: null,
252 refCleanup: null,
253
254 // pendingProps - defined at the bottom as dynamic properties
255 memoizedProps: null,
256 updateQueue: null,
257 memoizedState: null,
258 dependencies: null,
259
260 // Effects
261 flags: NoFlags,
262 subtreeFlags: NoFlags,
263 deletions: null,
264
265 lanes: NoLanes,
266 childLanes: NoLanes,
267
268 alternate: null,
269
270 // dynamic properties at the end for more efficient hermes bytecode
271 tag,
272 key,
273 pendingProps,
274 mode,
275 };
276
277 if (enableProfilerTimer) {
278 fiber.actualDuration = -0;
279 fiber.actualStartTime = -1.1;
280 fiber.selfBaseDuration = -0;
281 fiber.treeBaseDuration = -0;
282 }
283
284 if (__DEV__) {
285 // This isn't directly used but is handy for debugging internals:
286 fiber._debugInfo = null;
287 fiber._debugOwner = null;
288 fiber._debugStack = null;
289 fiber._debugTask = null;
290 fiber._debugNeedsRemount = false;
291 fiber._debugHookTypes = null;
292 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
293 Object.preventExtensions(fiber);
294 }
295 }
296 return fiber;
297 }
298
299 const createFiber = enableObjectFiber
300 ? createFiberImplObject
301 : createFiberImplClass;
302
303 function shouldConstruct(Component: Function) {
304 const prototype = Component.prototype;
305 return !!(prototype && prototype.isReactComponent);
306 }
307
308 export function isSimpleFunctionComponent(type: any): boolean {
309 return (
310 typeof type === 'function' &&
311 !shouldConstruct(type) &&
312 type.defaultProps === undefined
313 );
314 }
315
316 export function isFunctionClassComponent(
317 type: (...args: Array<any>) => mixed,
318 ): boolean {
319 return shouldConstruct(type);
320 }
321
322 // This is used to create an alternate fiber to do work on.
323 export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
324 let workInProgress = current.alternate;
325 if (workInProgress === null) {
326 // We use a double buffering pooling technique because we know that we'll
327 // only ever need at most two versions of a tree. We pool the "other" unused
328 // node that we're free to reuse. This is lazily created to avoid allocating
329 // extra objects for things that are never updated. It also allow us to
330 // reclaim the extra memory if needed.
331 workInProgress = createFiber(
332 current.tag,
333 pendingProps,
334 current.key,
335 current.mode,
336 );
337 workInProgress.elementType = current.elementType;
338 workInProgress.type = current.type;
339 workInProgress.stateNode = current.stateNode;
340
341 if (__DEV__) {
342 // DEV-only fields
343
344 workInProgress._debugOwner = current._debugOwner;
345 workInProgress._debugStack = current._debugStack;
346 workInProgress._debugTask = current._debugTask;
347 workInProgress._debugHookTypes = current._debugHookTypes;
348 }
349
350 workInProgress.alternate = current;
351 current.alternate = workInProgress;
352 } else {
353 workInProgress.pendingProps = pendingProps;
354 // Needed because Blocks store data on type.
355 workInProgress.type = current.type;
356
357 // We already have an alternate.
358 // Reset the effect tag.
359 workInProgress.flags = NoFlags;
360
361 // The effects are no longer valid.
362 workInProgress.subtreeFlags = NoFlags;
363 workInProgress.deletions = null;
364
365 if (enableOptimisticKey) {
366 // For optimistic keys, the Fibers can have different keys if one is optimistic
367 // and the other one is filled in.
368 workInProgress.key = current.key;
369 }
370
371 if (enableProfilerTimer) {
372 // We intentionally reset, rather than copy, actualDuration & actualStartTime.
373 // This prevents time from endlessly accumulating in new commits.
374 // This has the downside of resetting values for different priority renders,
375 // But works for yielding (the common case) and should support resuming.
376 workInProgress.actualDuration = -0;
377 workInProgress.actualStartTime = -1.1;
378 }
379 }
380
381 // Reset all effects except static ones.
382 // Static effects are not specific to a render.
383 workInProgress.flags = current.flags & StaticMask;
384 workInProgress.childLanes = current.childLanes;
385 workInProgress.lanes = current.lanes;
386
387 workInProgress.child = current.child;
388 workInProgress.memoizedProps = current.memoizedProps;
389 workInProgress.memoizedState = current.memoizedState;
390 workInProgress.updateQueue = current.updateQueue;
391
392 // Clone the dependencies object. This is mutated during the render phase, so
393 // it cannot be shared with the current fiber.
394 const currentDependencies = current.dependencies;
395 workInProgress.dependencies =
396 currentDependencies === null
397 ? null
398 : __DEV__
399 ? {
400 lanes: currentDependencies.lanes,
401 firstContext: currentDependencies.firstContext,
402 _debugThenableState: currentDependencies._debugThenableState,
403 }
404 : {
405 lanes: currentDependencies.lanes,
406 firstContext: currentDependencies.firstContext,
407 };
408
409 // These will be overridden during the parent's reconciliation
410 workInProgress.sibling = current.sibling;
411 workInProgress.index = current.index;
412 workInProgress.ref = current.ref;
413 workInProgress.refCleanup = current.refCleanup;
414
415 if (enableProfilerTimer) {
416 workInProgress.selfBaseDuration = current.selfBaseDuration;
417 workInProgress.treeBaseDuration = current.treeBaseDuration;
418 }
419
420 if (__DEV__) {
421 workInProgress._debugInfo = current._debugInfo;
422 workInProgress._debugNeedsRemount = current._debugNeedsRemount;
423 switch (workInProgress.tag) {
424 case FunctionComponent:
425 case SimpleMemoComponent:
426 case MemoComponent:
427 case ClassComponent:
428 case ForwardRef:
429 workInProgress.type = resolveTypeForHotReloading(current.type);
430 break;
431 default:
432 break;
433 }
434 }
435
436 return workInProgress;
437 }
438
439 // Used to reuse a Fiber for a second pass.
440 export function resetWorkInProgress(
441 workInProgress: Fiber,
442 renderLanes: Lanes,
443 ): Fiber {
444 // This resets the Fiber to what createFiber or createWorkInProgress would
445 // have set the values to before during the first pass. Ideally this wouldn't
446 // be necessary but unfortunately many code paths reads from the workInProgress
447 // when they should be reading from current and writing to workInProgress.
448
449 // We assume pendingProps, index, key, ref, return are still untouched to
450 // avoid doing another reconciliation.
451
452 // Reset the effect flags but keep any Placement tags, since that's something
453 // that child fiber is setting, not the reconciliation.
454 workInProgress.flags &= StaticMask | Placement;
455
456 // The effects are no longer valid.
457
458 const current = workInProgress.alternate;
459 if (current === null) {
460 // Reset to createFiber's initial values.
461 workInProgress.childLanes = NoLanes;
462 workInProgress.lanes = renderLanes;
463
464 workInProgress.child = null;
465 workInProgress.subtreeFlags = NoFlags;
466 workInProgress.memoizedProps = null;
467 workInProgress.memoizedState = null;
468 workInProgress.updateQueue = null;
469
470 workInProgress.dependencies = null;
471
472 workInProgress.stateNode = null;
473
474 if (enableProfilerTimer) {
475 // Note: We don't reset the actualTime counts. It's useful to accumulate
476 // actual time across multiple render passes.
477 workInProgress.selfBaseDuration = 0;
478 workInProgress.treeBaseDuration = 0;
479 }
480 } else {
481 // Reset to the cloned values that createWorkInProgress would've.
482 workInProgress.childLanes = current.childLanes;
483 workInProgress.lanes = current.lanes;
484
485 workInProgress.child = current.child;
486 workInProgress.subtreeFlags = NoFlags;
487 workInProgress.deletions = null;
488 workInProgress.memoizedProps = current.memoizedProps;
489 workInProgress.memoizedState = current.memoizedState;
490 workInProgress.updateQueue = current.updateQueue;
491 // Needed because Blocks store data on type.
492 // TODO: Blocks don't exist anymore. Do we still need this?
493 workInProgress.type = current.type;
494
495 if (enableOptimisticKey) {
496 // For optimistic keys, the Fibers can have different keys if one is optimistic
497 // and the other one is filled in.
498 workInProgress.key = current.key;
499 }
500
501 // Clone the dependencies object. This is mutated during the render phase, so
502 // it cannot be shared with the current fiber.
503 const currentDependencies = current.dependencies;
504 workInProgress.dependencies =
505 currentDependencies === null
506 ? null
507 : __DEV__
508 ? {
509 lanes: currentDependencies.lanes,
510 firstContext: currentDependencies.firstContext,
511 _debugThenableState: currentDependencies._debugThenableState,
512 }
513 : {
514 lanes: currentDependencies.lanes,
515 firstContext: currentDependencies.firstContext,
516 };
517
518 if (enableProfilerTimer) {
519 // Note: We don't reset the actualTime counts. It's useful to accumulate
520 // actual time across multiple render passes.
521 workInProgress.selfBaseDuration = current.selfBaseDuration;
522 workInProgress.treeBaseDuration = current.treeBaseDuration;
523 }
524 }
525
526 return workInProgress;
527 }
528
529 export function createHostRootFiber(
530 tag: RootTag,
531 isStrictMode: boolean,
532 ): Fiber {
533 let mode: number;
534 if (disableLegacyMode || tag === ConcurrentRoot) {
535 mode = ConcurrentMode;
536 if (isStrictMode === true) {
537 mode |= StrictLegacyMode | StrictEffectsMode;
538 }
539 } else {
540 mode = NoMode;
541 }
542
543 if (__DEV__ || (enableProfilerTimer && isDevToolsPresent)) {
544 // dev: Enable profiling instrumentation by default.
545 // profile: enabled if DevTools is present or subtree is wrapped in <Profiler>.
546 // production: disabled.
547 mode |= ProfileMode;
548 }
549
550 return createFiber(HostRoot, null, null, mode);
551 }
552
553 // TODO: Get rid of this helper. Only createFiberFromElement should exist.
554 export function createFiberFromTypeAndProps(
555 type: any, // React$ElementType
556 key: ReactKey,
557 pendingProps: any,
558 owner: null | ReactComponentInfo | Fiber,
559 mode: TypeOfMode,
560 lanes: Lanes,
561 ): Fiber {
562 let fiberTag: WorkTag = FunctionComponent;
563 // The resolved type is set if we know what the final type will be. I.e. it's not lazy.
564 let resolvedType = type;
565 if (__DEV__) {
566 resolvedType = resolveTypeForHotReloading(type);
567 }
568 if (typeof resolvedType === 'function') {
569 if (shouldConstruct(resolvedType)) {
570 fiberTag = ClassComponent;
571 }
572 } else if (typeof resolvedType === 'string') {
573 // $FlowFixMe[constant-condition]
574 if (supportsResources && supportsSingletons) {
575 const hostContext = getHostContext();
576 fiberTag = isHostHoistableType(type, pendingProps, hostContext)
577 ? HostHoistable
578 : isHostSingletonType(type)
579 ? HostSingleton
580 : HostComponent;
581 // $FlowFixMe[constant-condition]
582 } else if (supportsResources) {
583 const hostContext = getHostContext();
584 fiberTag = isHostHoistableType(type, pendingProps, hostContext)
585 ? HostHoistable
586 : HostComponent;
587 // $FlowFixMe[constant-condition]
588 } else if (supportsSingletons) {
589 fiberTag = isHostSingletonType(type) ? HostSingleton : HostComponent;
590 } else {
591 fiberTag = HostComponent;
592 }
593 } else {
594 getTag: switch (resolvedType) {
595 // $FlowFixMe[invalid-compare]
596 case REACT_ACTIVITY_TYPE:
597 return createFiberFromActivity(pendingProps, mode, lanes, key);
598 // $FlowFixMe[invalid-compare]
599 case REACT_FRAGMENT_TYPE:
600 return createFiberFromFragment(pendingProps.children, mode, lanes, key);
601 // $FlowFixMe[invalid-compare]
602 case REACT_STRICT_MODE_TYPE:
603 fiberTag = Mode;
604 mode |= StrictLegacyMode;
605 if (disableLegacyMode || (mode & ConcurrentMode) !== NoMode) {
606 // Strict effects should never run on legacy roots
607 mode |= StrictEffectsMode;
608 }
609 break;
610 // $FlowFixMe[invalid-compare]
611 case REACT_PROFILER_TYPE:
612 return createFiberFromProfiler(pendingProps, mode, lanes, key);
613 // $FlowFixMe[invalid-compare]
614 case REACT_SUSPENSE_TYPE:
615 return createFiberFromSuspense(pendingProps, mode, lanes, key);
616 // $FlowFixMe[invalid-compare]
617 case REACT_SUSPENSE_LIST_TYPE:
618 return createFiberFromSuspenseList(pendingProps, mode, lanes, key);
619 // $FlowFixMe[invalid-compare]
620 case REACT_LEGACY_HIDDEN_TYPE:
621 if (enableLegacyHidden) {
622 return createFiberFromLegacyHidden(pendingProps, mode, lanes, key);
623 }
624 // $FlowFixMe[invalid-compare] -- falls through
625 case REACT_VIEW_TRANSITION_TYPE:
626 if (enableViewTransition) {
627 return createFiberFromViewTransition(pendingProps, mode, lanes, key);
628 }
629 // $FlowFixMe[invalid-compare] -- falls through
630 case REACT_SCOPE_TYPE:
631 if (enableScopeAPI) {
632 return createFiberFromScope(type, pendingProps, mode, lanes, key);
633 }
634 // $FlowFixMe[invalid-compare] -- falls through
635 case REACT_TRACING_MARKER_TYPE:
636 if (enableTransitionTracing) {
637 return createFiberFromTracingMarker(pendingProps, mode, lanes, key);
638 }
639 // Fall through
640 default: {
641 // $FlowFixMe[invalid-compare]
642 if (typeof resolvedType === 'object' && resolvedType !== null) {
643 switch (resolvedType.$$typeof) {
644 // $FlowFixMe[invalid-compare]
645 case REACT_CONTEXT_TYPE:
646 fiberTag = ContextProvider;
647 break getTag;
648 // $FlowFixMe[invalid-compare]
649 case REACT_CONSUMER_TYPE:
650 fiberTag = ContextConsumer;
651 break getTag;
652 // Fall through
653 // $FlowFixMe[invalid-compare]
654 case REACT_FORWARD_REF_TYPE:
655 fiberTag = ForwardRef;
656 break getTag;
657 // $FlowFixMe[invalid-compare]
658 case REACT_MEMO_TYPE:
659 fiberTag = MemoComponent;
660 break getTag;
661 // $FlowFixMe[invalid-compare]
662 case REACT_LAZY_TYPE:
663 fiberTag = LazyComponent;
664 resolvedType = null;
665 break getTag;
666 }
667 }
668 let info = '';
669 let typeString;
670 if (__DEV__) {
671 if (
672 type === undefined ||
673 (typeof type === 'object' &&
674 // $FlowFixMe[invalid-compare]
675 type !== null &&
676 Object.keys(type).length === 0)
677 ) {
678 info +=
679 ' You likely forgot to export your component from the file ' +
680 "it's defined in, or you might have mixed up default and named imports.";
681 }
682
683 // $FlowFixMe[invalid-compare]
684 if (type === null) {
685 typeString = 'null';
686 } else if (isArray(type)) {
687 typeString = 'array';
688 } else if (
689 type !== undefined &&
690 // $FlowFixMe[invalid-compare]
691 type.$$typeof === REACT_ELEMENT_TYPE
692 ) {
693 typeString = `<${
694 getComponentNameFromType(type.type) || 'Unknown'
695 } />`;
696 info =
697 ' Did you accidentally export a JSX literal instead of a component?';
698 } else {
699 typeString = typeof type;
700 }
701
702 const ownerName = owner ? getComponentNameFromOwner(owner) : null;
703 if (ownerName) {
704 info += '\n\nCheck the render method of `' + ownerName + '`.';
705 }
706 } else {
707 // $FlowFixMe[invalid-compare]
708 typeString = type === null ? 'null' : typeof type;
709 }
710
711 // The type is invalid but it's conceptually a child that errored and not the
712 // current component itself so we create a virtual child that throws in its
713 // begin phase. This is the same thing we do in ReactChildFiber if we throw
714 // but we do it here so that we can assign the debug owner and stack from the
715 // element itself. That way the error stack will point to the JSX callsite.
716 fiberTag = Throw;
717 pendingProps = new Error(
718 'Element type is invalid: expected a string (for built-in ' +
719 'components) or a class/function (for composite components) ' +
720 `but got: ${typeString}.${info}`,
721 );
722 resolvedType = null;
723 }
724 }
725 }
726
727 const fiber = createFiber(fiberTag, pendingProps, key, mode);
728 fiber.elementType = type;
729 fiber.type = resolvedType;
730 fiber.lanes = lanes;
731
732 if (__DEV__) {
733 fiber._debugOwner = owner;
734 }
735
736 return fiber;
737 }
738
739 export function createFiberFromElement(
740 element: ReactElement,
741 mode: TypeOfMode,
742 lanes: Lanes,
743 ): Fiber {
744 let owner = null;
745 if (__DEV__) {
746 owner = element._owner;
747 }
748 const type = element.type;
749 const key = element.key;
750 const pendingProps = element.props;
751 const fiber = createFiberFromTypeAndProps(
752 type,
753 key,
754 pendingProps,
755 owner,
756 mode,
757 lanes,
758 );
759 if (__DEV__) {
760 fiber._debugOwner = element._owner;
761 fiber._debugStack = element._debugStack;
762 fiber._debugTask = element._debugTask;
763 }
764 return fiber;
765 }
766
767 export function createFiberFromFragment(
768 elements: ReactFragment,
769 mode: TypeOfMode,
770 lanes: Lanes,
771 key: ReactKey,
772 ): Fiber {
773 const fiber = createFiber(Fragment, elements, key, mode);
774 fiber.lanes = lanes;
775 return fiber;
776 }
777
778 function createFiberFromScope(
779 scope: ReactScope,
780 pendingProps: any,
781 mode: TypeOfMode,
782 lanes: Lanes,
783 key: ReactKey,
784 ) {
785 const fiber = createFiber(ScopeComponent, pendingProps, key, mode);
786 fiber.type = scope;
787 fiber.elementType = scope;
788 fiber.lanes = lanes;
789 return fiber;
790 }
791
792 function createFiberFromProfiler(
793 pendingProps: any,
794 mode: TypeOfMode,
795 lanes: Lanes,
796 key: ReactKey,
797 ): Fiber {
798 if (__DEV__) {
799 if (typeof pendingProps.id !== 'string') {
800 console.error(
801 'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.',
802 typeof pendingProps.id,
803 );
804 }
805 }
806
807 const fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode);
808 fiber.elementType = REACT_PROFILER_TYPE;
809 fiber.lanes = lanes;
810
811 if (enableProfilerTimer) {
812 fiber.stateNode = {
813 effectDuration: 0,
814 passiveEffectDuration: 0,
815 };
816 }
817
818 return fiber;
819 }
820
821 export function createFiberFromSuspense(
822 pendingProps: any,
823 mode: TypeOfMode,
824 lanes: Lanes,
825 key: ReactKey,
826 ): Fiber {
827 const fiber = createFiber(SuspenseComponent, pendingProps, key, mode);
828 fiber.elementType = REACT_SUSPENSE_TYPE;
829 fiber.lanes = lanes;
830 return fiber;
831 }
832
833 export function createFiberFromSuspenseList(
834 pendingProps: any,
835 mode: TypeOfMode,
836 lanes: Lanes,
837 key: ReactKey,
838 ): Fiber {
839 const fiber = createFiber(SuspenseListComponent, pendingProps, key, mode);
840 fiber.elementType = REACT_SUSPENSE_LIST_TYPE;
841 fiber.lanes = lanes;
842 return fiber;
843 }
844
845 export function createFiberFromOffscreen(
846 pendingProps: OffscreenProps,
847 mode: TypeOfMode,
848 lanes: Lanes,
849 key: ReactKey,
850 ): Fiber {
851 const fiber = createFiber(OffscreenComponent, pendingProps, key, mode);
852 fiber.lanes = lanes;
853 return fiber;
854 }
855 export function createFiberFromActivity(
856 pendingProps: ActivityProps,
857 mode: TypeOfMode,
858 lanes: Lanes,
859 key: ReactKey,
860 ): Fiber {
861 const fiber = createFiber(ActivityComponent, pendingProps, key, mode);
862 fiber.elementType = REACT_ACTIVITY_TYPE;
863 fiber.lanes = lanes;
864 return fiber;
865 }
866
867 export function createFiberFromViewTransition(
868 pendingProps: ViewTransitionProps,
869 mode: TypeOfMode,
870 lanes: Lanes,
871 key: ReactKey,
872 ): Fiber {
873 if (!enableSuspenseyImages) {
874 // Render a ViewTransition component opts into SuspenseyImages mode even
875 // when the flag is off.
876 mode |= SuspenseyImagesMode;
877 }
878 const fiber = createFiber(ViewTransitionComponent, pendingProps, key, mode);
879 fiber.elementType = REACT_VIEW_TRANSITION_TYPE;
880 fiber.lanes = lanes;
881 const instance: ViewTransitionState = {
882 autoName: null,
883 paired: null,
884 clones: null,
885 ref: null,
886 };
887 fiber.stateNode = instance;
888 return fiber;
889 }
890
891 export function createFiberFromLegacyHidden(
892 pendingProps: LegacyHiddenProps,
893 mode: TypeOfMode,
894 lanes: Lanes,
895 key: ReactKey,
896 ): Fiber {
897 const fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode);
898 fiber.elementType = REACT_LEGACY_HIDDEN_TYPE;
899 fiber.lanes = lanes;
900 return fiber;
901 }
902
903 export function createFiberFromTracingMarker(
904 pendingProps: any,
905 mode: TypeOfMode,
906 lanes: Lanes,
907 key: ReactKey,
908 ): Fiber {
909 const fiber = createFiber(TracingMarkerComponent, pendingProps, key, mode);
910 fiber.elementType = REACT_TRACING_MARKER_TYPE;
911 fiber.lanes = lanes;
912 const tracingMarkerInstance: TracingMarkerInstance = {
913 tag: TransitionTracingMarker,
914 transitions: null,
915 pendingBoundaries: null,
916 aborts: null,
917 name: pendingProps.name,
918 };
919 fiber.stateNode = tracingMarkerInstance;
920 return fiber;
921 }
922
923 export function createFiberFromText(
924 content: string,
925 mode: TypeOfMode,
926 lanes: Lanes,
927 ): Fiber {
928 const fiber = createFiber(HostText, content, null, mode);
929 fiber.lanes = lanes;
930 return fiber;
931 }
932
933 export function createFiberFromDehydratedFragment(
934 dehydratedNode: SuspenseInstance | ActivityInstance,
935 ): Fiber {
936 const fiber = createFiber(DehydratedFragment, null, null, NoMode);
937 fiber.stateNode = dehydratedNode;
938 return fiber;
939 }
940
941 export function createFiberFromPortal(
942 portal: ReactPortal,
943 mode: TypeOfMode,
944 lanes: Lanes,
945 ): Fiber {
946 const pendingProps = portal.children !== null ? portal.children : [];
947 const fiber = createFiber(HostPortal, pendingProps, portal.key, mode);
948 fiber.lanes = lanes;
949 fiber.stateNode = {
950 containerInfo: portal.containerInfo,
951 pendingChildren: null, // Used by persistent updates
952 implementation: portal.implementation,
953 };
954 return fiber;
955 }
956
957 export function createFiberFromThrow(
958 error: mixed,
959 mode: TypeOfMode,
960 lanes: Lanes,
961 ): Fiber {
962 const fiber = createFiber(Throw, error, null, mode);
963 fiber.lanes = lanes;
964 return fiber;
965 }