@samitouri / QOS-React / commits / e5a7b75846

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 &&