Skip to content

Commit 2d01fb4

Browse files
author
Brian Vaughn
committed
Effects list rewrite
1 parent 1cbaf48 commit 2d01fb4

10 files changed

+381
-201
lines changed

packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,14 @@ describe('ReactDOMServerPartialHydration', () => {
367367
const span2 = container.getElementsByTagName('span')[0];
368368
// This is a new node.
369369
expect(span).not.toBe(span2);
370-
expect(ref.current).toBe(span2);
370+
371+
if (gate(flags => flags.new)) {
372+
// The effects list refactor causes this to be null because the Suspense Offscreen's child
373+
// is null. However, since we can't hydrate Suspense in legacy this change in behavior is ok
374+
expect(ref.current).toBe(null);
375+
} else {
376+
expect(ref.current).toBe(span2);
377+
}
371378

372379
// Resolving the promise should render the final content.
373380
suspend = false;

packages/react-native-renderer/src/__tests__/createReactNativeComponentClass-test.internal.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,12 @@ describe('createReactNativeComponentClass', () => {
4545

4646
expect(Text).not.toBe(View);
4747

48-
ReactNative.render(<Text />, 1);
49-
ReactNative.render(<View />, 1);
48+
ReactNative.render(
49+
<View>
50+
<Text />
51+
</View>,
52+
1,
53+
);
5054
});
5155

5256
it('should not allow viewConfigs with duplicate uiViewClassNames to be registered', () => {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,15 @@ function ChildReconciler(shouldTrackSideEffects) {
280280
// deletions, so we can just append the deletion to the list. The remaining
281281
// effects aren't added until the complete phase. Once we implement
282282
// resuming, this may not be true.
283+
// TODO (effects) Get rid of effects list update here.
283284
const last = returnFiber.lastEffect;
284285
if (last !== null) {
285286
last.nextEffect = childToDelete;
286287
returnFiber.lastEffect = childToDelete;
287288
} else {
288289
returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
289290
}
291+
returnFiber.deletions.push(childToDelete);
290292
childToDelete.nextEffect = null;
291293
childToDelete.effectTag = Deletion;
292294
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ function FiberNode(
144144

145145
// Effects
146146
this.effectTag = NoEffect;
147+
this.subtreeTag = NoEffect;
148+
this.deletions = [];
147149
this.nextEffect = null;
148150

149151
this.firstEffect = null;
@@ -287,6 +289,8 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
287289
// We already have an alternate.
288290
// Reset the effect tag.
289291
workInProgress.effectTag = NoEffect;
292+
workInProgress.subtreeTag = NoEffect;
293+
workInProgress.deletions = [];
290294

291295
// The effect list is no longer valid.
292296
workInProgress.nextEffect = null;
@@ -826,6 +830,8 @@ export function assignFiberPropertiesInDEV(
826830
target.dependencies = source.dependencies;
827831
target.mode = source.mode;
828832
target.effectTag = source.effectTag;
833+
target.subtreeTag = source.subtreeTag;
834+
target.deletions = source.deletions;
829835
target.nextEffect = source.nextEffect;
830836
target.firstEffect = source.firstEffect;
831837
target.lastEffect = source.lastEffect;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,7 @@ function updateSuspensePrimaryChildren(
20662066
currentFallbackChildFragment.nextEffect = null;
20672067
currentFallbackChildFragment.effectTag = Deletion;
20682068
workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment;
2069+
workInProgress.deletions.push(currentFallbackChildFragment);
20692070
}
20702071

20712072
workInProgress.child = primaryChildFragment;
@@ -2131,9 +2132,11 @@ function updateSuspenseFallbackChildren(
21312132
workInProgress.firstEffect = primaryChildFragment.firstEffect;
21322133
workInProgress.lastEffect = progressedLastEffect;
21332134
progressedLastEffect.nextEffect = null;
2135+
workInProgress.deletions = [];
21342136
} else {
21352137
// TODO: Reset this somewhere else? Lol legacy mode is so weird.
21362138
workInProgress.firstEffect = workInProgress.lastEffect = null;
2139+
workInProgress.deletions = [];
21372140
}
21382141
} else {
21392142
primaryChildFragment = createWorkInProgressOffscreenFiber(
@@ -3040,6 +3043,7 @@ function remountFiber(
30403043
} else {
30413044
returnFiber.firstEffect = returnFiber.lastEffect = current;
30423045
}
3046+
returnFiber.deletions.push(current);
30433047
current.nextEffect = null;
30443048
current.effectTag = Deletion;
30453049

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,15 @@ function completeWork(
10621062
// Reset the effect list before doing the second pass since that's now invalid.
10631063
if (renderState.lastEffect === null) {
10641064
workInProgress.firstEffect = null;
1065+
workInProgress.subtreeTag = NoEffect;
1066+
// TODO (effects) This probably isn't the best approach. Discuss with Brian
1067+
let child = workInProgress.child;
1068+
while (child !== null) {
1069+
if (child.deletions.length > 0) {
1070+
child.deletions = [];
1071+
}
1072+
child = child.sibling;
1073+
}
10651074
}
10661075
workInProgress.lastEffect = renderState.lastEffect;
10671076
// Reset the child fibers to their original state.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
HostRoot,
2525
SuspenseComponent,
2626
} from './ReactWorkTags';
27-
import {Deletion, Placement, Hydrating} from './ReactSideEffectTags';
27+
import {Deletion, Hydrating, Placement} from './ReactSideEffectTags';
2828
import invariant from 'shared/invariant';
2929

3030
import {
@@ -125,6 +125,7 @@ function deleteHydratableInstance(
125125
childToDelete.stateNode = instance;
126126
childToDelete.return = returnFiber;
127127
childToDelete.effectTag = Deletion;
128+
returnFiber.deletions.push(childToDelete);
128129

129130
// This might seem like it belongs on progressedFirstDeletion. However,
130131
// these children are not part of the reconciliation list of children.

0 commit comments

Comments
 (0)