@samitouri / QOS-React / commits / 9ea55516e6

Replace unstable_AsyncComponent with unstable_AsyncMode (#12117)

* Replace unstable_AsyncComponent with Unstable_AsyncMode Mirrors the StrictMode API and uses the new Mode type of work. * internalContextTag -> mode Change this now that we have a better name * Unstable_ -> unstable_

Andrew Clark committed Jan 29, 2018 at 19:11 UTC 9ea55516e674c2de63b9f7829e3c459f3cb3cf78
19 files changed +131 -145
packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js
+19 -20
@@ -14,7 +14,7 @@ let ReactFeatureFlags = require('shared/ReactFeatureFlags');
14
15 let ReactDOM;
16
17 -const AsyncComponent = React.unstable_AsyncComponent;
17 +const AsyncMode = React.unstable_AsyncMode;
18
19 describe('ReactDOMFiberAsync', () => {
20 let container;
@@ -40,23 +40,22 @@ describe('ReactDOMFiberAsync', () => {
40 jest.resetModules();
41 ReactFeatureFlags = require('shared/ReactFeatureFlags');
42 container = document.createElement('div');
43 - ReactFeatureFlags.enableAsyncSubtreeAPI = false;
43 ReactDOM = require('react-dom');
44 });
45
46 it('renders synchronously', () => {
47 ReactDOM.render(
49 - <AsyncComponent>
48 + <AsyncMode>
49 <div>Hi</div>
51 - </AsyncComponent>,
50 + </AsyncMode>,
51 container,
52 );
53 expect(container.textContent).toEqual('Hi');
54
55 ReactDOM.render(
57 - <AsyncComponent>
56 + <AsyncMode>
57 <div>Bye</div>
59 - </AsyncComponent>,
58 + </AsyncMode>,
59 container,
60 );
61 expect(container.textContent).toEqual('Bye');
@@ -68,7 +67,6 @@ describe('ReactDOMFiberAsync', () => {
67 jest.resetModules();
68 ReactFeatureFlags = require('shared/ReactFeatureFlags');
69 container = document.createElement('div');
71 - ReactFeatureFlags.enableAsyncSubtreeAPI = true;
70 ReactFeatureFlags.enableCreateRoot = true;
71 ReactDOM = require('react-dom');
72 });
@@ -108,9 +106,9 @@ describe('ReactDOMFiberAsync', () => {
106 expect(container.textContent).toEqual('1');
107 });
108
111 - it('AsyncComponent creates an async subtree', () => {
109 + it('AsyncMode creates an async subtree', () => {
110 let instance;
113 - class Component extends React.unstable_AsyncComponent {
111 + class Component extends React.Component {
112 state = {step: 0};
113 render() {
114 instance = this;
@@ -119,9 +117,9 @@ describe('ReactDOMFiberAsync', () => {
117 }
118
119 ReactDOM.render(
122 - <div>
120 + <AsyncMode>
121 <Component />
124 - </div>,
122 + </AsyncMode>,
123 container,
124 );
125 jest.runAllTimers();
@@ -133,12 +131,6 @@ describe('ReactDOMFiberAsync', () => {
131 });
132
133 it('updates inside an async subtree are async by default', () => {
136 - class Component extends React.unstable_AsyncComponent {
137 - render() {
138 - return <Child />;
139 - }
140 - }
141 -
134 let instance;
135 class Child extends React.Component {
136 state = {step: 0};
@@ -150,7 +142,9 @@ describe('ReactDOMFiberAsync', () => {
142
143 ReactDOM.render(
144 <div>
153 - <Component />
145 + <AsyncMode>
146 + <Child />
147 + </AsyncMode>
148 </div>,
149 container,
150 );
@@ -264,7 +258,7 @@ describe('ReactDOMFiberAsync', () => {
258 let ops = [];
259 let instance;
260
267 - class Component extends React.unstable_AsyncComponent {
261 + class Component extends React.Component {
262 state = {text: ''};
263 push(val) {
264 this.setState(state => ({text: state.text + val}));
@@ -278,7 +272,12 @@ describe('ReactDOMFiberAsync', () => {
272 }
273 }
274
281 - ReactDOM.render(<Component />, container);
275 + ReactDOM.render(
276 + <AsyncMode>
277 + <Component />
278 + </AsyncMode>,
279 + container,
280 + );
281 jest.runAllTimers();
282
283 // Updates are async by default
packages/react-dom/src/__tests__/ReactDOMRoot-test.internal.js
+6 -7
@@ -12,7 +12,7 @@
12 let React = require('react');
13 let ReactDOM = require('react-dom');
14 let ReactDOMServer = require('react-dom/server');
15 -let AsyncComponent = React.unstable_AsyncComponent;
15 +let AsyncMode = React.unstable_AsyncMode;
16
17 describe('ReactDOMRoot', () => {
18 let container;
@@ -70,7 +70,7 @@ describe('ReactDOMRoot', () => {
70 React = require('react');
71 ReactDOM = require('react-dom');
72 ReactDOMServer = require('react-dom/server');
73 - AsyncComponent = React.unstable_AsyncComponent;
73 + AsyncMode = React.unstable_AsyncMode;
74 });
75
76 it('renders children', () => {
@@ -92,7 +92,7 @@ describe('ReactDOMRoot', () => {
92
93 it('`root.render` returns a thenable work object', () => {
94 const root = ReactDOM.createRoot(container);
95 - const work = root.render(<AsyncComponent>Hi</AsyncComponent>);
95 + const work = root.render(<AsyncMode>Hi</AsyncMode>);
96 let ops = [];
97 work.then(() => {
98 ops.push('inside callback: ' + container.textContent);
@@ -110,7 +110,7 @@ describe('ReactDOMRoot', () => {
110
111 it('resolves `work.then` callback synchronously if the work already committed', () => {
112 const root = ReactDOM.createRoot(container);
113 - const work = root.render(<AsyncComponent>Hi</AsyncComponent>);
113 + const work = root.render(<AsyncMode>Hi</AsyncMode>);
114 flush();
115 let ops = [];
116 work.then(() => {
@@ -209,10 +209,9 @@ describe('ReactDOMRoot', () => {
209 });
210
211 it('can wait for a batch to finish', () => {
212 - const Async = React.unstable_AsyncComponent;
212 const root = ReactDOM.createRoot(container);
213 const batch = root.createBatch();
215 - batch.render(<Async>Foo</Async>);
214 + batch.render(<AsyncMode>Foo</AsyncMode>);
215
216 flush();
217
@@ -252,7 +251,7 @@ describe('ReactDOMRoot', () => {
251
252 it('can commit an empty batch', () => {
253 const root = ReactDOM.createRoot(container);
255 - root.render(<AsyncComponent>1</AsyncComponent>);
254 + root.render(<AsyncMode>1</AsyncMode>);
255
256 expire(2000);
257 // This batch has a later expiration time than the earlier update.
packages/react-reconciler/src/ReactChildFiber.js
+12 -12
@@ -318,7 +318,7 @@ function ChildReconciler(shouldTrackSideEffects) {
318 // Insert
319 const created = createFiberFromText(
320 textContent,
321 - returnFiber.internalContextTag,
321 + returnFiber.mode,
322 expirationTime,
323 );
324 created.return = returnFiber;
@@ -351,7 +351,7 @@ function ChildReconciler(shouldTrackSideEffects) {
351 // Insert
352 const created = createFiberFromElement(
353 element,
354 - returnFiber.internalContextTag,
354 + returnFiber.mode,
355 expirationTime,
356 );
357 created.ref = coerceRef(current, element);
@@ -375,7 +375,7 @@ function ChildReconciler(shouldTrackSideEffects) {
375 // Insert
376 const created = createFiberFromPortal(
377 portal,
378 - returnFiber.internalContextTag,
378 + returnFiber.mode,
379 expirationTime,
380 );
381 created.return = returnFiber;
@@ -399,7 +399,7 @@ function ChildReconciler(shouldTrackSideEffects) {
399 // Insert
400 const created = createFiberFromFragment(
401 fragment,
402 - returnFiber.internalContextTag,
402 + returnFiber.mode,
403 expirationTime,
404 key,
405 );
@@ -424,7 +424,7 @@ function ChildReconciler(shouldTrackSideEffects) {
424 // node.
425 const created = createFiberFromText(
426 '' + newChild,
427 - returnFiber.internalContextTag,
427 + returnFiber.mode,
428 expirationTime,
429 );
430 created.return = returnFiber;
@@ -436,7 +436,7 @@ function ChildReconciler(shouldTrackSideEffects) {
436 case REACT_ELEMENT_TYPE: {
437 const created = createFiberFromElement(
438 newChild,
439 - returnFiber.internalContextTag,
439 + returnFiber.mode,
440 expirationTime,
441 );
442 created.ref = coerceRef(null, newChild);
@@ -446,7 +446,7 @@ function ChildReconciler(shouldTrackSideEffects) {
446 case REACT_PORTAL_TYPE: {
447 const created = createFiberFromPortal(
448 newChild,
449 - returnFiber.internalContextTag,
449 + returnFiber.mode,
450 expirationTime,
451 );
452 created.return = returnFiber;
@@ -457,7 +457,7 @@ function ChildReconciler(shouldTrackSideEffects) {
457 if (isArray(newChild) || getIteratorFn(newChild)) {
458 const created = createFiberFromFragment(
459 newChild,
460 - returnFiber.internalContextTag,
460 + returnFiber.mode,
461 expirationTime,
462 null,
463 );
@@ -1045,7 +1045,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1045 deleteRemainingChildren(returnFiber, currentFirstChild);
1046 const created = createFiberFromText(
1047 textContent,
1048 - returnFiber.internalContextTag,
1048 + returnFiber.mode,
1049 expirationTime,
1050 );
1051 created.return = returnFiber;
@@ -1097,7 +1097,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1097 if (element.type === REACT_FRAGMENT_TYPE) {
1098 const created = createFiberFromFragment(
1099 element.props.children,
1100 - returnFiber.internalContextTag,
1100 + returnFiber.mode,
1101 expirationTime,
1102 element.key,
1103 );
@@ -1106,7 +1106,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1106 } else {
1107 const created = createFiberFromElement(
1108 element,
1109 - returnFiber.internalContextTag,
1109 + returnFiber.mode,
1110 expirationTime,
1111 );
1112 created.ref = coerceRef(currentFirstChild, element);
@@ -1152,7 +1152,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1152
1153 const created = createFiberFromPortal(
1154 portal,
1155 - returnFiber.internalContextTag,
1155 + returnFiber.mode,
1156 expirationTime,
1157 );
1158 created.return = returnFiber;
packages/react-reconciler/src/ReactFiber.js
+27 -31
@@ -9,7 +9,7 @@
9 import type {ReactElement, Source} from 'shared/ReactElementType';
10 import type {ReactPortal} from 'shared/ReactTypes';
11 import type {TypeOfWork} from 'shared/ReactTypeOfWork';
12 -import type {TypeOfInternalContext} from './ReactTypeOfInternalContext';
12 +import type {TypeOfMode} from './ReactTypeOfMode';
13 import type {TypeOfSideEffect} from 'shared/ReactTypeOfSideEffect';
14 import type {ExpirationTime} from './ReactFiberExpirationTime';
15 import type {UpdateQueue} from './ReactFiberUpdateQueue';
@@ -33,11 +33,7 @@ import {
33 import getComponentName from 'shared/getComponentName';
34
35 import {NoWork} from './ReactFiberExpirationTime';
36 -import {
37 - NoContext,
38 - AsyncUpdates,
39 - StrictMode,
40 -} from './ReactTypeOfInternalContext';
36 +import {NoContext, AsyncMode, StrictMode} from './ReactTypeOfMode';
37 import {
38 REACT_FRAGMENT_TYPE,
39 REACT_RETURN_TYPE,
@@ -45,6 +41,7 @@ import {
41 REACT_STRICT_MODE_TYPE,
42 REACT_PROVIDER_TYPE,
43 REACT_CONTEXT_TYPE,
44 + REACT_ASYNC_MODE_TYPE,
45 } from 'shared/ReactSymbols';
46
47 let hasBadMapPolyfill;
@@ -123,12 +120,12 @@ export type Fiber = {|
120 memoizedState: any,
121
122 // Bitfield that describes properties about the fiber and its subtree. E.g.
126 - // the AsyncUpdates flag indicates whether the subtree should be async-by-
127 - // default. When a fiber is created, it inherits the internalContextTag of its
123 + // the AsyncMode flag indicates whether the subtree should be async-by-
124 + // default. When a fiber is created, it inherits the mode of its
125 // parent. Additional flags can be set at creation time, but after than the
126 // value should remain unchanged throughout the fiber's lifetime, particularly
127 // before its child fibers are created.
131 - internalContextTag: TypeOfInternalContext,
128 + mode: TypeOfMode,
129
130 // Effect
131 effectTag: TypeOfSideEffect,
@@ -171,7 +168,7 @@ function FiberNode(
168 tag: TypeOfWork,
169 pendingProps: mixed,
170 key: null | string,
174 - internalContextTag: TypeOfInternalContext,
171 + mode: TypeOfMode,
172 ) {
173 // Instance
174 this.tag = tag;
@@ -192,7 +189,7 @@ function FiberNode(
189 this.updateQueue = null;
190 this.memoizedState = null;
191
195 - this.internalContextTag = internalContextTag;
192 + this.mode = mode;
193
194 // Effects
195 this.effectTag = NoEffect;
@@ -233,10 +230,10 @@ const createFiber = function(
230 tag: TypeOfWork,
231 pendingProps: mixed,
232 key: null | string,
236 - internalContextTag: TypeOfInternalContext,
233 + mode: TypeOfMode,
234 ): Fiber {
235 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
239 - return new FiberNode(tag, pendingProps, key, internalContextTag);
236 + return new FiberNode(tag, pendingProps, key, mode);
237 };
238
239 function shouldConstruct(Component) {
@@ -260,7 +257,7 @@ export function createWorkInProgress(
257 current.tag,
258 pendingProps,
259 current.key,
263 - current.internalContextTag,
260 + current.mode,
261 );
262 workInProgress.type = current.type;
263 workInProgress.stateNode = current.stateNode;
@@ -303,13 +300,13 @@ export function createWorkInProgress(
300 }
301
302 export function createHostRootFiber(isAsync): Fiber {
306 - const internalContextTag = isAsync ? AsyncUpdates | StrictMode : NoContext;
307 - return createFiber(HostRoot, null, null, internalContextTag);
303 + const mode = isAsync ? AsyncMode | StrictMode : NoContext;
304 + return createFiber(HostRoot, null, null, mode);
305 }
306
307 export function createFiberFromElement(
308 element: ReactElement,
312 - internalContextTag: TypeOfInternalContext,
309 + mode: TypeOfMode,
310 expirationTime: ExpirationTime,
311 ): Fiber {
312 let owner = null;
@@ -332,13 +329,17 @@ export function createFiberFromElement(
329 case REACT_FRAGMENT_TYPE:
330 return createFiberFromFragment(
331 pendingProps.children,
335 - internalContextTag,
332 + mode,
333 expirationTime,
334 key,
335 );
336 + case REACT_ASYNC_MODE_TYPE:
337 + fiberTag = Mode;
338 + mode |= AsyncMode | StrictMode;
339 + break;
340 case REACT_STRICT_MODE_TYPE:
341 fiberTag = Mode;
341 - internalContextTag |= StrictMode;
342 + mode |= StrictMode;
343 break;
344 case REACT_CALL_TYPE:
345 fiberTag = CallComponent;
@@ -382,7 +383,7 @@ export function createFiberFromElement(
383 }
384 }
385
385 - fiber = createFiber(fiberTag, pendingProps, key, internalContextTag);
386 + fiber = createFiber(fiberTag, pendingProps, key, mode);
387 fiber.type = type;
388 fiber.expirationTime = expirationTime;
389
@@ -425,21 +426,21 @@ function throwOnInvalidElementType(type, owner) {
426
427 export function createFiberFromFragment(
428 elements: ReactFragment,
428 - internalContextTag: TypeOfInternalContext,
429 + mode: TypeOfMode,
430 expirationTime: ExpirationTime,
431 key: null | string,
432 ): Fiber {
432 - const fiber = createFiber(Fragment, elements, key, internalContextTag);
433 + const fiber = createFiber(Fragment, elements, key, mode);
434 fiber.expirationTime = expirationTime;
435 return fiber;
436 }
437
438 export function createFiberFromText(
439 content: string,
439 - internalContextTag: TypeOfInternalContext,
440 + mode: TypeOfMode,
441 expirationTime: ExpirationTime,
442 ): Fiber {
442 - const fiber = createFiber(HostText, content, null, internalContextTag);
443 + const fiber = createFiber(HostText, content, null, mode);
444 fiber.expirationTime = expirationTime;
445 return fiber;
446 }
@@ -452,16 +453,11 @@ export function createFiberFromHostInstanceForDeletion(): Fiber {
453
454 export function createFiberFromPortal(
455 portal: ReactPortal,
455 - internalContextTag: TypeOfInternalContext,
456 + mode: TypeOfMode,
457 expirationTime: ExpirationTime,
458 ): Fiber {
459 const pendingProps = portal.children !== null ? portal.children : [];
459 - const fiber = createFiber(
460 - HostPortal,
461 - pendingProps,
462 - portal.key,
463 - internalContextTag,
464 - );
460 + const fiber = createFiber(HostPortal, pendingProps, portal.key, mode);
461 fiber.expirationTime = expirationTime;
462 fiber.stateNode = {
463 containerInfo: portal.containerInfo,
packages/react-reconciler/src/ReactFiberBeginWork.js
+4 -4
@@ -67,7 +67,7 @@ import {
67 } from './ReactFiberContext';
68 import {pushProvider} from './ReactFiberNewContext';
69 import {NoWork, Never} from './ReactFiberExpirationTime';
70 -import {AsyncUpdates, StrictMode} from './ReactTypeOfInternalContext';
70 +import {AsyncMode, StrictMode} from './ReactTypeOfMode';
71 import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';
72
73 let didWarnAboutBadClass;
@@ -293,7 +293,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
293 if (
294 debugRenderPhaseSideEffects ||
295 (debugRenderPhaseSideEffectsForStrictMode &&
296 - workInProgress.internalContextTag & StrictMode)
296 + workInProgress.mode & StrictMode)
297 ) {
298 instance.render();
299 }
@@ -302,7 +302,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
302 if (
303 debugRenderPhaseSideEffects ||
304 (debugRenderPhaseSideEffectsForStrictMode &&
305 - workInProgress.internalContextTag & StrictMode)
305 + workInProgress.mode & StrictMode)
306 ) {
307 instance.render();
308 }
@@ -438,7 +438,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
438 // Check the host config to see if the children are offscreen/hidden.
439 if (
440 renderExpirationTime !== Never &&
441 - workInProgress.internalContextTag & AsyncUpdates &&
441 + workInProgress.mode & AsyncMode &&
442 shouldDeprioritizeSubtree(type, nextProps)
443 ) {
444 // Down-prioritize the children.
packages/react-reconciler/src/ReactFiberClassComponent.js
+4 -16
@@ -14,7 +14,6 @@ import {Update} from 'shared/ReactTypeOfSideEffect';
14 import {
15 debugRenderPhaseSideEffects,
16 debugRenderPhaseSideEffectsForStrictMode,
17 - enableAsyncSubtreeAPI,
17 warnAboutDeprecatedLifecycles,
18 } from 'shared/ReactFeatureFlags';
19 import ReactStrictModeWarnings from './ReactStrictModeWarnings';
@@ -27,7 +26,7 @@ import invariant from 'fbjs/lib/invariant';
26 import warning from 'fbjs/lib/warning';
27
28 import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf';
30 -import {AsyncUpdates, StrictMode} from './ReactTypeOfInternalContext';
29 +import {StrictMode} from './ReactTypeOfMode';
30 import {
31 cacheContext,
32 getMaskedContext,
@@ -395,7 +394,7 @@ export default function(
394 if (
395 debugRenderPhaseSideEffects ||
396 (debugRenderPhaseSideEffectsForStrictMode &&
398 - workInProgress.internalContextTag & StrictMode)
397 + workInProgress.mode & StrictMode)
398 ) {
399 new ctor(props, context); // eslint-disable-line no-new
400 }
@@ -548,7 +547,7 @@ export default function(
547 if (
548 debugRenderPhaseSideEffects ||
549 (debugRenderPhaseSideEffectsForStrictMode &&
551 - workInProgress.internalContextTag & StrictMode)
550 + workInProgress.mode & StrictMode)
551 ) {
552 // Invoke method an extra time to help detect side-effects.
553 type.getDerivedStateFromProps.call(
@@ -603,19 +602,8 @@ export default function(
602 instance.refs = emptyObject;
603 instance.context = getMaskedContext(workInProgress, unmaskedContext);
604
606 - if (workInProgress.type != null && workInProgress.type.prototype != null) {
607 - const prototype = workInProgress.type.prototype;
608 -
609 - if (enableAsyncSubtreeAPI) {
610 - if (prototype.unstable_isAsyncReactComponent === true) {
611 - workInProgress.internalContextTag |= AsyncUpdates;
612 - workInProgress.internalContextTag |= StrictMode;
613 - }
614 - }
615 - }
616 -
605 if (__DEV__) {
618 - if (workInProgress.internalContextTag & StrictMode) {
606 + if (workInProgress.mode & StrictMode) {
607 ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(
608 workInProgress,
609 instance,
packages/react-reconciler/src/ReactFiberScheduler.js
+2 -2
@@ -81,7 +81,7 @@ import {
81 expirationTimeToMs,
82 computeExpirationBucket,
83 } from './ReactFiberExpirationTime';
84 -import {AsyncUpdates} from './ReactTypeOfInternalContext';
84 +import {AsyncMode} from './ReactTypeOfMode';
85 import {getUpdateExpirationTime} from './ReactFiberUpdateQueue';
86 import {resetContext as resetLegacyContext} from './ReactFiberContext';
87 import {resetProviderStack} from './ReactFiberNewContext';
@@ -1200,7 +1200,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
1200 } else {
1201 // No explicit expiration context was set, and we're not currently
1202 // performing work. Calculate a new expiration time.
1203 - if (fiber.internalContextTag & AsyncUpdates) {
1203 + if (fiber.mode & AsyncMode) {
1204 // This is an async update
1205 expirationTime = computeAsyncExpiration();
1206 } else {
packages/react-reconciler/src/ReactFiberUpdateQueue.js
+2 -2
@@ -18,7 +18,7 @@ import {Callback as CallbackEffect} from 'shared/ReactTypeOfSideEffect';
18 import {ClassComponent, HostRoot} from 'shared/ReactTypeOfWork';
19 import invariant from 'fbjs/lib/invariant';
20 import warning from 'fbjs/lib/warning';
21 -import {StrictMode} from './ReactTypeOfInternalContext';
21 +import {StrictMode} from './ReactTypeOfMode';
22
23 import {NoWork} from './ReactFiberExpirationTime';
24
@@ -278,7 +278,7 @@ export function processUpdateQueue<State>(
278 if (
279 debugRenderPhaseSideEffects ||
280 (debugRenderPhaseSideEffectsForStrictMode &&
281 - workInProgress.internalContextTag & StrictMode)
281 + workInProgress.mode & StrictMode)
282 ) {
283 getStateFromUpdate(update, instance, state, props);
284 }
packages/react-reconciler/src/ReactStrictModeWarnings.js
+2 -2
@@ -11,7 +11,7 @@ import type {Fiber} from './ReactFiber';
11
12 import getComponentName from 'shared/getComponentName';
13 import {getStackAddendumByWorkInProgressFiber} from 'shared/ReactFiberComponentTreeHook';
14 -import {StrictMode} from './ReactTypeOfInternalContext';
14 +import {StrictMode} from './ReactTypeOfMode';
15 import warning from 'fbjs/lib/warning';
16
17 type LIFECYCLE =
@@ -104,7 +104,7 @@ if (__DEV__) {
104 let maybeStrictRoot = null;
105
106 while (fiber !== null) {
107 - if (fiber.internalContextTag & StrictMode) {
107 + if (fiber.mode & StrictMode) {
108 maybeStrictRoot = fiber;
109 }
110
packages/react-reconciler/src/ReactTypeOfMode.js renamed
+4 -4
@@ -7,8 +7,8 @@
7 * @flow
8 */
9
10 -export type TypeOfInternalContext = number;
10 +export type TypeOfMode = number;
11
12 -export const NoContext = 0b00000000;
13 -export const AsyncUpdates = 0b00000001;
14 -export const StrictMode = 0b00000010;
12 +export const NoContext = 0b00;
13 +export const AsyncMode = 0b01;
14 +export const StrictMode = 0b10;
packages/react/src/React.js
+7 -3
@@ -7,9 +7,13 @@
7
8 import assign from 'object-assign';
9 import ReactVersion from 'shared/ReactVersion';
10 -import {REACT_FRAGMENT_TYPE, REACT_STRICT_MODE_TYPE} from 'shared/ReactSymbols';
10 +import {
11 + REACT_FRAGMENT_TYPE,
12 + REACT_STRICT_MODE_TYPE,
13 + REACT_ASYNC_MODE_TYPE,
14 +} from 'shared/ReactSymbols';
15
12 -import {AsyncComponent, Component, PureComponent} from './ReactBaseClasses';
16 +import {Component, PureComponent} from './ReactBaseClasses';
17 import {forEach, map, count, toArray, only} from './ReactChildren';
18 import ReactCurrentOwner from './ReactCurrentOwner';
19 import {
@@ -38,10 +42,10 @@ const React = {
42
43 Component,
44 PureComponent,
41 - unstable_AsyncComponent: AsyncComponent,
45
46 Fragment: REACT_FRAGMENT_TYPE,
47 StrictMode: REACT_STRICT_MODE_TYPE,
48 + unstable_AsyncMode: REACT_ASYNC_MODE_TYPE,
49
50 createElement: __DEV__ ? createElementWithValidation : createElement,
51 cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
packages/react/src/ReactBaseClasses.js
+1 -20
@@ -136,23 +136,4 @@ pureComponentPrototype.constructor = PureComponent;
136 Object.assign(pureComponentPrototype, Component.prototype);
137 pureComponentPrototype.isPureReactComponent = true;
138
139 -/**
140 - * Special component type that opts subtree into async rendering mode.
141 - */
142 -function AsyncComponent(props, context, updater) {
143 - this.props = props;
144 - this.context = context;
145 - this.refs = emptyObject;
146 - this.updater = updater || ReactNoopUpdateQueue;
147 -}
148 -
149 -const asyncComponentPrototype = (AsyncComponent.prototype = new ComponentDummy());
150 -asyncComponentPrototype.constructor = AsyncComponent;
151 -// Avoid an extra prototype jump for these methods.
152 -Object.assign(asyncComponentPrototype, Component.prototype);
153 -asyncComponentPrototype.unstable_isAsyncReactComponent = true;
154 -asyncComponentPrototype.render = function() {
155 - return this.props.children;
156 -};
157 -
158 -export {AsyncComponent, Component, PureComponent};
139 +export {Component, PureComponent};
packages/react/src/ReactElementValidator.js
+2
@@ -19,6 +19,7 @@ import {
19 getIteratorFn,
20 REACT_FRAGMENT_TYPE,
21 REACT_STRICT_MODE_TYPE,
22 + REACT_ASYNC_MODE_TYPE,
23 } from 'shared/ReactSymbols';
24 import checkPropTypes from 'prop-types/checkPropTypes';
25 import warning from 'fbjs/lib/warning';
@@ -287,6 +288,7 @@ export function createElementWithValidation(type, props, children) {
288 typeof type === 'function' ||
289 // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
290 type === REACT_FRAGMENT_TYPE ||
291 + type === REACT_ASYNC_MODE_TYPE ||
292 type === REACT_STRICT_MODE_TYPE;
293
294 // We warn in this case but don't throw. We expect the element creation to
packages/react/src/__tests__/ReactStrictMode-test.internal.js
+36 -18
@@ -285,10 +285,14 @@ describe('ReactStrictMode', () => {
285 UNSAFE_componentWillUpdate() {}
286 UNSAFE_componentWillReceiveProps() {}
287 render() {
288 - return <AsyncRoot />;
288 + return (
289 + <React.unstable_AsyncMode>
290 + <AsyncRoot />
291 + </React.unstable_AsyncMode>
292 + );
293 }
294 }
291 - class AsyncRoot extends React.unstable_AsyncComponent {
295 + class AsyncRoot extends React.Component {
296 UNSAFE_componentWillMount() {}
297 UNSAFE_componentWillUpdate() {}
298 render() {
@@ -326,7 +330,6 @@ describe('ReactStrictMode', () => {
330 rendered = ReactTestRenderer.create(<SyncRoot />);
331 }).toWarnDev(
332 'Unsafe lifecycle methods were found within a strict-mode tree:' +
329 - '\n in AsyncRoot (at **)' +
333 '\n in SyncRoot (at **)' +
334 '\n\ncomponentWillMount: Please update the following components ' +
335 'to use componentDidMount instead: AsyncRoot' +
@@ -349,10 +352,14 @@ describe('ReactStrictMode', () => {
352 UNSAFE_componentWillUpdate() {}
353 UNSAFE_componentWillReceiveProps() {}
354 render() {
352 - return <AsyncRoot />;
355 + return (
356 + <React.unstable_AsyncMode>
357 + <AsyncRoot />
358 + </React.unstable_AsyncMode>
359 + );
360 }
361 }
355 - class AsyncRoot extends React.unstable_AsyncComponent {
362 + class AsyncRoot extends React.Component {
363 UNSAFE_componentWillMount() {}
364 UNSAFE_componentWillUpdate() {}
365 render() {
@@ -380,7 +387,6 @@ describe('ReactStrictMode', () => {
387 () => (rendered = ReactTestRenderer.create(<SyncRoot />)),
388 ).toWarnDev(
389 'Unsafe lifecycle methods were found within a strict-mode tree:' +
383 - '\n in AsyncRoot (at **)' +
390 '\n in SyncRoot (at **)' +
391 '\n\ncomponentWillMount: Please update the following components ' +
392 'to use componentDidMount instead: AsyncRoot, Parent' +
@@ -411,21 +417,25 @@ describe('ReactStrictMode', () => {
417 );
418 }
419 }
414 - class AsyncRootOne extends React.unstable_AsyncComponent {
420 + class AsyncRootOne extends React.Component {
421 render() {
422 return (
417 - <Foo>
418 - <Bar />
419 - </Foo>
423 + <React.unstable_AsyncMode>
424 + <Foo>
425 + <Bar />
426 + </Foo>
427 + </React.unstable_AsyncMode>
428 );
429 }
430 }
423 - class AsyncRootTwo extends React.unstable_AsyncComponent {
431 + class AsyncRootTwo extends React.Component {
432 render() {
433 return (
426 - <Foo>
427 - <Baz />
428 - </Foo>
434 + <React.unstable_AsyncMode>
435 + <Foo>
436 + <Baz />
437 + </Foo>
438 + </React.unstable_AsyncMode>
439 );
440 }
441 }
@@ -473,9 +483,13 @@ describe('ReactStrictMode', () => {
483 });
484
485 it('should warn about components not present during the initial render', () => {
476 - class AsyncRoot extends React.unstable_AsyncComponent {
486 + class AsyncRoot extends React.Component {
487 render() {
478 - return this.props.foo ? <Foo /> : <Bar />;
488 + return (
489 + <React.unstable_AsyncMode>
490 + {this.props.foo ? <Foo /> : <Bar />}
491 + </React.unstable_AsyncMode>
492 + );
493 }
494 }
495 class Foo extends React.Component {
@@ -520,9 +534,13 @@ describe('ReactStrictMode', () => {
534 it('should not warn about uncommitted lifecycles in the event of an error', () => {
535 let caughtError;
536
523 - class AsyncRoot extends React.unstable_AsyncComponent {
537 + class AsyncRoot extends React.Component {
538 render() {
525 - return <ErrorBoundary />;
539 + return (
540 + <React.unstable_AsyncMode>
541 + <ErrorBoundary />
542 + </React.unstable_AsyncMode>
543 + );
544 }
545 }
546 class ErrorBoundary extends React.Component {
packages/shared/ReactFeatureFlags.js
-1
@@ -9,7 +9,6 @@
9
10 import invariant from 'fbjs/lib/invariant';
11
12 -export const enableAsyncSubtreeAPI = true;
12 // Exports ReactDOM.createRoot
13 export const enableCreateRoot = false;
14 export const enableUserTimingAPI = __DEV__;
packages/shared/ReactSymbols.js
+3
@@ -33,6 +33,9 @@ export const REACT_PROVIDER_TYPE = hasSymbol
33 export const REACT_CONTEXT_TYPE = hasSymbol
34 ? Symbol.for('react.context')
35 : 0xeace;
36 +export const REACT_ASYNC_MODE_TYPE = hasSymbol
37 + ? Symbol.for('react.async_mode')
38 + : 0xeacf;
39
40 const MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
41 const FAUX_ITERATOR_SYMBOL = '@@iterator';
packages/shared/forks/ReactFeatureFlags.native-fabric.js
-1
@@ -14,7 +14,6 @@ import typeof * as FabricFeatureFlagsType from './ReactFeatureFlags.native-fabri
14
15 export const debugRenderPhaseSideEffects = false;
16 export const debugRenderPhaseSideEffectsForStrictMode = false;
17 -export const enableAsyncSubtreeAPI = true;
17 export const enableCreateRoot = false;
18 export const enableUserTimingAPI = __DEV__;
19 export const warnAboutDeprecatedLifecycles = false;
packages/shared/forks/ReactFeatureFlags.native.js
-1
@@ -20,7 +20,6 @@ export const {
20 } = require('ReactFeatureFlags');
21
22 // The rest of the flags are static for better dead code elimination.
23 -export const enableAsyncSubtreeAPI = true;
23 export const enableCreateRoot = false;
24 export const enableUserTimingAPI = __DEV__;
25 export const enableMutatingReconciler = true;
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -18,7 +18,6 @@ export const {
18 } = require('ReactFeatureFlags');
19
20 // The rest of the flags are static for better dead code elimination.
21 -export const enableAsyncSubtreeAPI = true;
21 export const enableCreateRoot = true;
22 export const enableNewContextAPI = true;
23