bailoutOnLowPriority correct pushes context for ClassComponents to mirror complete phase context pop
Brian Vaughn committed
Dec 16, 2016 at 15:04 UTC
441cc5c82b93dd2a7b75292cea5fdd745cc00999
3 files changed
+55
-2
scripts/fiber/tests-passing.txt
+1
@@ -1148,6 +1148,7 @@ src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
1148
* provides context when reusing work
1149
* reads context when setState is below the provider
1150
* reads context when setState is above the provider
1151
+* maintains the correct context index when context proviers are bailed out due to low priority
1152
1153
src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js
1154
* catches render error in a boundary during full deferred mounting
src/renderers/shared/fiber/ReactFiberBeginWork.js
+11
-2
@@ -462,8 +462,17 @@ module.exports = function<T, P, I, TI, C, CX>(
462
}
463
464
function bailoutOnLowPriority(current, workInProgress) {
465
- if (workInProgress.tag === HostPortal) {
466
- pushHostContainer(workInProgress.stateNode.containerInfo);
465
+ // TODO: Handle HostComponent tags here as well and call pushHostContext()?
466
+ // See PR 8590 discussion for context
467
+ switch (workInProgress.tag) {
468
+ case ClassComponent:
469
+ if (isContextProvider(workInProgress)) {
470
+ pushContextProvider(workInProgress, false);
471
+ }
472
+ break;
473
+ case HostPortal:
474
+ pushHostContainer(workInProgress.stateNode.containerInfo);
475
+ break;
476
}
477
// TODO: What if this is currently in progress?
478
// How can that happen? How is this not being cloned?
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+43
@@ -1932,4 +1932,47 @@ describe('ReactIncremental', () => {
1932
'ShowLocaleFn:read {"locale":"gr"}',
1933
]);
1934
});
1935
+
1936
+ it('maintains the correct context index when context proviers are bailed out due to low priority', () => {
1937
+ class Root extends React.Component {
1938
+ render() {
1939
+ return <Middle {...this.props} />;
1940
+ }
1941
+ }
1942
+
1943
+ let instance;
1944
+
1945
+ class Middle extends React.Component {
1946
+ constructor(props, context) {
1947
+ super(props, context);
1948
+ instance = this;
1949
+ }
1950
+ shouldComponentUpdate() {
1951
+ // Return false so that our child will get a NoWork priority (and get bailed out)
1952
+ return false;
1953
+ }
1954
+ render() {
1955
+ return <Child />;
1956
+ }
1957
+ }
1958
+
1959
+ // Child must be a context provider to trigger the bug
1960
+ class Child extends React.Component {
1961
+ static childContextTypes = {};
1962
+ getChildContext() {
1963
+ return {};
1964
+ }
1965
+ render() {
1966
+ return <div />;
1967
+ }
1968
+ }
1969
+
1970
+ // Init
1971
+ ReactNoop.render(<Root />);
1972
+ ReactNoop.flush();
1973
+
1974
+ // Trigger an update in the middle of the tree
1975
+ instance.setState({});
1976
+ ReactNoop.flush();
1977
+ });
1978
});