Improve unmasked context caching
Only store cached masked/unmasked contexts on context consumers. Move all references to __reactInternal* cached attributes inside of ReactFiberContext.
Brian Vaughn committed
Jan 9, 2017 at 13:51 UTC
e5a7b758469ad9b84d36c0f191f0b0cd8e6acc64
2 files changed
+25
-5
src/renderers/shared/fiber/ReactFiberClassComponent.js
+8
-3
@@ -16,8 +16,10 @@ import type { Fiber } from 'ReactFiber';
16
import type { PriorityLevel } from 'ReactPriorityLevel';
17
18
var {
19
+ cacheContext,
20
getMaskedContext,
21
getUnmaskedContext,
22
+ isContextConsumer,
23
} = require('ReactFiberContext');
24
var {
25
addUpdate,
@@ -28,6 +30,7 @@ var {
30
var { hasContextChanged } = require('ReactFiberContext');
31
var { getComponentName, isMounted } = require('ReactFiberTreeReflection');
32
var ReactInstanceMap = require('ReactInstanceMap');
33
+var emptyObject = require('emptyObject');
34
var shallowEqual = require('shallowEqual');
35
var warning = require('warning');
36
var invariant = require('invariant');
@@ -206,15 +209,17 @@ module.exports = function(
209
const ctor = workInProgress.type;
210
const props = workInProgress.pendingProps;
211
const unmaskedContext = getUnmaskedContext(workInProgress);
209
- const context = getMaskedContext(workInProgress, unmaskedContext);
212
+ const needsContext = isContextConsumer(workInProgress);
213
+ const context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject;
214
const instance = new ctor(props, context);
215
adoptClassInstance(workInProgress, instance);
216
checkClassInstance(workInProgress);
217
218
// Cache unmasked context so we can avoid recreating masked context unless necessary.
219
// ReactFiberContext usually updates this cache but can't for newly-created instances.
216
- instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
217
- instance.__reactInternalMemoizedMaskedChildContext = context;
220
+ if (needsContext) {
221
+ cacheContext(workInProgress, unmaskedContext, context);
222
+ }
223
224
return instance;
225
}
src/renderers/shared/fiber/ReactFiberContext.js
+17
-2
@@ -57,6 +57,13 @@ function getUnmaskedContext(workInProgress : Fiber) : Object {
57
}
58
exports.getUnmaskedContext = getUnmaskedContext;
59
60
+function cacheContext(workInProgress : Fiber, unmaskedContext : Object, maskedContext : Object) {
61
+ const instance = workInProgress.stateNode;
62
+ instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
63
+ instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
64
+}
65
+exports.cacheContext = cacheContext;
66
+
67
exports.getMaskedContext = function(workInProgress : Fiber, unmaskedContext : Object) {
68
const type = workInProgress.type;
69
const contextTypes = type.contextTypes;
@@ -86,9 +93,9 @@ exports.getMaskedContext = function(workInProgress : Fiber, unmaskedContext : Ob
93
}
94
95
// Cache unmasked context so we can avoid recreating masked context unless necessary.
96
+ // Context is created before the class component is instantiated so check for instance.
97
if (instance) {
90
- instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
91
- instance.__reactInternalMemoizedMaskedChildContext = context;
98
+ cacheContext(workInProgress, unmaskedContext, context);
99
}
100
101
return context;
@@ -98,6 +105,14 @@ exports.hasContextChanged = function() : boolean {
105
return didPerformWorkStackCursor.current;
106
};
107
108
+function isContextConsumer(fiber : Fiber) : boolean {
109
+ return (
110
+ fiber.tag === ClassComponent &&
111
+ fiber.type.contextTypes != null
112
+ );
113
+}
114
+exports.isContextConsumer = isContextConsumer;
115
+
116
function isContextProvider(fiber : Fiber) : boolean {
117
return (
118
fiber.tag === ClassComponent &&