Skip to content

Commit 9cf75e1

Browse files
committed
Add forked copies of reconciler modules
1 parent a48cf16 commit 9cf75e1

37 files changed

+22521
-10
lines changed

packages/react-reconciler/src/ReactChildFiber.new.js

Lines changed: 1490 additions & 0 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/ReactFiber.new.js

Lines changed: 964 additions & 0 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/ReactFiberBeginWork.new.js

Lines changed: 3494 additions & 0 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/ReactFiberClassComponent.new.js

Lines changed: 1182 additions & 0 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/ReactFiberCommitWork.new.js

Lines changed: 1827 additions & 0 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/ReactFiberCompleteWork.new.js

Lines changed: 1314 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its 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 {Fiber} from './ReactFiber.new';
11+
import type {StackCursor} from './ReactFiberStack.new';
12+
13+
import {isFiberMounted} from './ReactFiberTreeReflection';
14+
import {disableLegacyContext} from 'shared/ReactFeatureFlags';
15+
import {ClassComponent, HostRoot} from './ReactWorkTags';
16+
import getComponentName from 'shared/getComponentName';
17+
import invariant from 'shared/invariant';
18+
import checkPropTypes from 'shared/checkPropTypes';
19+
20+
import {createCursor, push, pop} from './ReactFiberStack.new';
21+
22+
let warnedAboutMissingGetChildContext;
23+
24+
if (__DEV__) {
25+
warnedAboutMissingGetChildContext = {};
26+
}
27+
28+
export const emptyContextObject = {};
29+
if (__DEV__) {
30+
Object.freeze(emptyContextObject);
31+
}
32+
33+
// A cursor to the current merged context object on the stack.
34+
const contextStackCursor: StackCursor<Object> = createCursor(
35+
emptyContextObject,
36+
);
37+
// A cursor to a boolean indicating whether the context has changed.
38+
const didPerformWorkStackCursor: StackCursor<boolean> = createCursor(false);
39+
// Keep track of the previous context object that was on the stack.
40+
// We use this to get access to the parent context after we have already
41+
// pushed the next context provider, and now need to merge their contexts.
42+
let previousContext: Object = emptyContextObject;
43+
44+
function getUnmaskedContext(
45+
workInProgress: Fiber,
46+
Component: Function,
47+
didPushOwnContextIfProvider: boolean,
48+
): Object {
49+
if (disableLegacyContext) {
50+
return emptyContextObject;
51+
} else {
52+
if (didPushOwnContextIfProvider && isContextProvider(Component)) {
53+
// If the fiber is a context provider itself, when we read its context
54+
// we may have already pushed its own child context on the stack. A context
55+
// provider should not "see" its own child context. Therefore we read the
56+
// previous (parent) context instead for a context provider.
57+
return previousContext;
58+
}
59+
return contextStackCursor.current;
60+
}
61+
}
62+
63+
function cacheContext(
64+
workInProgress: Fiber,
65+
unmaskedContext: Object,
66+
maskedContext: Object,
67+
): void {
68+
if (disableLegacyContext) {
69+
return;
70+
} else {
71+
const instance = workInProgress.stateNode;
72+
instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
73+
instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
74+
}
75+
}
76+
77+
function getMaskedContext(
78+
workInProgress: Fiber,
79+
unmaskedContext: Object,
80+
): Object {
81+
if (disableLegacyContext) {
82+
return emptyContextObject;
83+
} else {
84+
const type = workInProgress.type;
85+
const contextTypes = type.contextTypes;
86+
if (!contextTypes) {
87+
return emptyContextObject;
88+
}
89+
90+
// Avoid recreating masked context unless unmasked context has changed.
91+
// Failing to do this will result in unnecessary calls to componentWillReceiveProps.
92+
// This may trigger infinite loops if componentWillReceiveProps calls setState.
93+
const instance = workInProgress.stateNode;
94+
if (
95+
instance &&
96+
instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext
97+
) {
98+
return instance.__reactInternalMemoizedMaskedChildContext;
99+
}
100+
101+
const context = {};
102+
for (const key in contextTypes) {
103+
context[key] = unmaskedContext[key];
104+
}
105+
106+
if (__DEV__) {
107+
const name = getComponentName(type) || 'Unknown';
108+
checkPropTypes(contextTypes, context, 'context', name);
109+
}
110+
111+
// Cache unmasked context so we can avoid recreating masked context unless necessary.
112+
// Context is created before the class component is instantiated so check for instance.
113+
if (instance) {
114+
cacheContext(workInProgress, unmaskedContext, context);
115+
}
116+
117+
return context;
118+
}
119+
}
120+
121+
function hasContextChanged(): boolean {
122+
if (disableLegacyContext) {
123+
return false;
124+
} else {
125+
return didPerformWorkStackCursor.current;
126+
}
127+
}
128+
129+
function isContextProvider(type: Function): boolean {
130+
if (disableLegacyContext) {
131+
return false;
132+
} else {
133+
const childContextTypes = type.childContextTypes;
134+
return childContextTypes !== null && childContextTypes !== undefined;
135+
}
136+
}
137+
138+
function popContext(fiber: Fiber): void {
139+
if (disableLegacyContext) {
140+
return;
141+
} else {
142+
pop(didPerformWorkStackCursor, fiber);
143+
pop(contextStackCursor, fiber);
144+
}
145+
}
146+
147+
function popTopLevelContextObject(fiber: Fiber): void {
148+
if (disableLegacyContext) {
149+
return;
150+
} else {
151+
pop(didPerformWorkStackCursor, fiber);
152+
pop(contextStackCursor, fiber);
153+
}
154+
}
155+
156+
function pushTopLevelContextObject(
157+
fiber: Fiber,
158+
context: Object,
159+
didChange: boolean,
160+
): void {
161+
if (disableLegacyContext) {
162+
return;
163+
} else {
164+
invariant(
165+
contextStackCursor.current === emptyContextObject,
166+
'Unexpected context found on stack. ' +
167+
'This error is likely caused by a bug in React. Please file an issue.',
168+
);
169+
170+
push(contextStackCursor, context, fiber);
171+
push(didPerformWorkStackCursor, didChange, fiber);
172+
}
173+
}
174+
175+
function processChildContext(
176+
fiber: Fiber,
177+
type: any,
178+
parentContext: Object,
179+
): Object {
180+
if (disableLegacyContext) {
181+
return parentContext;
182+
} else {
183+
const instance = fiber.stateNode;
184+
const childContextTypes = type.childContextTypes;
185+
186+
// TODO (bvaughn) Replace this behavior with an invariant() in the future.
187+
// It has only been added in Fiber to match the (unintentional) behavior in Stack.
188+
if (typeof instance.getChildContext !== 'function') {
189+
if (__DEV__) {
190+
const componentName = getComponentName(type) || 'Unknown';
191+
192+
if (!warnedAboutMissingGetChildContext[componentName]) {
193+
warnedAboutMissingGetChildContext[componentName] = true;
194+
console.error(
195+
'%s.childContextTypes is specified but there is no getChildContext() method ' +
196+
'on the instance. You can either define getChildContext() on %s or remove ' +
197+
'childContextTypes from it.',
198+
componentName,
199+
componentName,
200+
);
201+
}
202+
}
203+
return parentContext;
204+
}
205+
206+
const childContext = instance.getChildContext();
207+
for (const contextKey in childContext) {
208+
invariant(
209+
contextKey in childContextTypes,
210+
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
211+
getComponentName(type) || 'Unknown',
212+
contextKey,
213+
);
214+
}
215+
if (__DEV__) {
216+
const name = getComponentName(type) || 'Unknown';
217+
checkPropTypes(childContextTypes, childContext, 'child context', name);
218+
}
219+
220+
return {...parentContext, ...childContext};
221+
}
222+
}
223+
224+
function pushContextProvider(workInProgress: Fiber): boolean {
225+
if (disableLegacyContext) {
226+
return false;
227+
} else {
228+
const instance = workInProgress.stateNode;
229+
// We push the context as early as possible to ensure stack integrity.
230+
// If the instance does not exist yet, we will push null at first,
231+
// and replace it on the stack later when invalidating the context.
232+
const memoizedMergedChildContext =
233+
(instance && instance.__reactInternalMemoizedMergedChildContext) ||
234+
emptyContextObject;
235+
236+
// Remember the parent context so we can merge with it later.
237+
// Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.
238+
previousContext = contextStackCursor.current;
239+
push(contextStackCursor, memoizedMergedChildContext, workInProgress);
240+
push(
241+
didPerformWorkStackCursor,
242+
didPerformWorkStackCursor.current,
243+
workInProgress,
244+
);
245+
246+
return true;
247+
}
248+
}
249+
250+
function invalidateContextProvider(
251+
workInProgress: Fiber,
252+
type: any,
253+
didChange: boolean,
254+
): void {
255+
if (disableLegacyContext) {
256+
return;
257+
} else {
258+
const instance = workInProgress.stateNode;
259+
invariant(
260+
instance,
261+
'Expected to have an instance by this point. ' +
262+
'This error is likely caused by a bug in React. Please file an issue.',
263+
);
264+
265+
if (didChange) {
266+
// Merge parent and own context.
267+
// Skip this if we're not updating due to sCU.
268+
// This avoids unnecessarily recomputing memoized values.
269+
const mergedContext = processChildContext(
270+
workInProgress,
271+
type,
272+
previousContext,
273+
);
274+
instance.__reactInternalMemoizedMergedChildContext = mergedContext;
275+
276+
// Replace the old (or empty) context with the new one.
277+
// It is important to unwind the context in the reverse order.
278+
pop(didPerformWorkStackCursor, workInProgress);
279+
pop(contextStackCursor, workInProgress);
280+
// Now push the new context and mark that it has changed.
281+
push(contextStackCursor, mergedContext, workInProgress);
282+
push(didPerformWorkStackCursor, didChange, workInProgress);
283+
} else {
284+
pop(didPerformWorkStackCursor, workInProgress);
285+
push(didPerformWorkStackCursor, didChange, workInProgress);
286+
}
287+
}
288+
}
289+
290+
function findCurrentUnmaskedContext(fiber: Fiber): Object {
291+
if (disableLegacyContext) {
292+
return emptyContextObject;
293+
} else {
294+
// Currently this is only used with renderSubtreeIntoContainer; not sure if it
295+
// makes sense elsewhere
296+
invariant(
297+
isFiberMounted(fiber) && fiber.tag === ClassComponent,
298+
'Expected subtree parent to be a mounted class component. ' +
299+
'This error is likely caused by a bug in React. Please file an issue.',
300+
);
301+
302+
let node = fiber;
303+
do {
304+
switch (node.tag) {
305+
case HostRoot:
306+
return node.stateNode.context;
307+
case ClassComponent: {
308+
const Component = node.type;
309+
if (isContextProvider(Component)) {
310+
return node.stateNode.__reactInternalMemoizedMergedChildContext;
311+
}
312+
break;
313+
}
314+
}
315+
node = node.return;
316+
} while (node !== null);
317+
invariant(
318+
false,
319+
'Found unexpected detached subtree parent. ' +
320+
'This error is likely caused by a bug in React. Please file an issue.',
321+
);
322+
}
323+
}
324+
325+
export {
326+
getUnmaskedContext,
327+
cacheContext,
328+
getMaskedContext,
329+
hasContextChanged,
330+
popContext,
331+
popTopLevelContextObject,
332+
pushTopLevelContextObject,
333+
processChildContext,
334+
isContextProvider,
335+
pushContextProvider,
336+
invalidateContextProvider,
337+
findCurrentUnmaskedContext,
338+
};

0 commit comments

Comments
 (0)