Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialize update queue object on mount #17560

Merged
merged 2 commits into from Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 24 additions & 11 deletions packages/react-noop-renderer/src/createReactNoop.js
Expand Up @@ -1142,20 +1142,33 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {

function logUpdateQueue(updateQueue: UpdateQueue<mixed>, depth) {
log(' '.repeat(depth + 1) + 'QUEUED UPDATES');
const firstUpdate = updateQueue.firstUpdate;
if (!firstUpdate) {
const last = updateQueue.baseQueue;
if (last === null) {
return;
}
const first = last.next;
let update = first;
if (update !== null) {
do {
log(
' '.repeat(depth + 1) + '~',
'[' + update.expirationTime + ']',
);
} while (update !== null && update !== first);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can update be changed while inside the loop? Do we need to additionally check for not null being inside if (update !== null)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. It's missing a update = update.next line at the end of the loop. Honestly I don't think anyone actually uses this method anymore, so I'll probably just remove it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I believe removal would be safe here and in the block below.

}

log(
' '.repeat(depth + 1) + '~',
'[' + firstUpdate.expirationTime + ']',
);
while (firstUpdate.next) {
log(
' '.repeat(depth + 1) + '~',
'[' + firstUpdate.expirationTime + ']',
);
const lastPending = updateQueue.shared.pending;
if (lastPending !== null) {
const firstPending = lastPending.next;
let pendingUpdate = firstPending;
if (pendingUpdate !== null) {
do {
log(
' '.repeat(depth + 1) + '~',
'[' + pendingUpdate.expirationTime + ']',
);
} while (pendingUpdate !== null && pendingUpdate !== firstPending);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question whether pendingUpdate needs to be checked for ! == null when already inside if check

}
}
}

Expand Down
19 changes: 10 additions & 9 deletions packages/react-reconciler/src/ReactFiberBeginWork.js
Expand Up @@ -90,7 +90,11 @@ import {
reconcileChildFibers,
cloneChildFibers,
} from './ReactChildFiber';
import {processUpdateQueue} from './ReactUpdateQueue';
import {
processUpdateQueue,
cloneUpdateQueue,
initializeUpdateQueue,
} from './ReactUpdateQueue';
import {
NoWork,
Never,
Expand Down Expand Up @@ -904,21 +908,16 @@ function updateHostRoot(current, workInProgress, renderExpirationTime) {
pushHostRootContext(workInProgress);
const updateQueue = workInProgress.updateQueue;
invariant(
updateQueue !== null,
current !== null && updateQueue !== null,
'If the root does not have an updateQueue, we should have already ' +
'bailed out. This error is likely caused by a bug in React. Please ' +
'file an issue.',
);
const nextProps = workInProgress.pendingProps;
const prevState = workInProgress.memoizedState;
const prevChildren = prevState !== null ? prevState.element : null;
processUpdateQueue(
workInProgress,
updateQueue,
nextProps,
null,
renderExpirationTime,
);
cloneUpdateQueue(current, workInProgress);
processUpdateQueue(workInProgress, nextProps, null, renderExpirationTime);
const nextState = workInProgress.memoizedState;
// Caution: React DevTools currently depends on this property
// being called "element".
Expand Down Expand Up @@ -1338,6 +1337,8 @@ function mountIndeterminateComponent(
workInProgress.memoizedState =
value.state !== null && value.state !== undefined ? value.state : null;

initializeUpdateQueue(workInProgress);

const getDerivedStateFromProps = Component.getDerivedStateFromProps;
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
Expand Down
69 changes: 23 additions & 46 deletions packages/react-reconciler/src/ReactFiberClassComponent.js
Expand Up @@ -9,6 +9,7 @@

import type {Fiber} from './ReactFiber';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {UpdateQueue} from './ReactUpdateQueue';

import React from 'react';
import {Update, Snapshot} from 'shared/ReactSideEffectTags';
Expand Down Expand Up @@ -38,6 +39,8 @@ import {
createUpdate,
ReplaceState,
ForceUpdate,
initializeUpdateQueue,
cloneUpdateQueue,
} from './ReactUpdateQueue';
import {NoWork} from './ReactFiberExpirationTime';
import {
Expand Down Expand Up @@ -171,8 +174,9 @@ export function applyDerivedStateFromProps(

// Once the update queue is empty, persist the derived state onto the
// base state.
const updateQueue = workInProgress.updateQueue;
if (updateQueue !== null && workInProgress.expirationTime === NoWork) {
if (workInProgress.expirationTime === NoWork) {
// Queue is always non-null for classes
const updateQueue: UpdateQueue<any> = (workInProgress.updateQueue: any);
updateQueue.baseState = memoizedState;
}
}
Expand Down Expand Up @@ -789,6 +793,8 @@ function mountClassInstance(
instance.state = workInProgress.memoizedState;
instance.refs = emptyRefsObject;

initializeUpdateQueue(workInProgress);

const contextType = ctor.contextType;
if (typeof contextType === 'object' && contextType !== null) {
instance.context = readContext(contextType);
Expand Down Expand Up @@ -829,17 +835,8 @@ function mountClassInstance(
}
}

let updateQueue = workInProgress.updateQueue;
if (updateQueue !== null) {
processUpdateQueue(
workInProgress,
updateQueue,
newProps,
instance,
renderExpirationTime,
);
instance.state = workInProgress.memoizedState;
}
processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime);
instance.state = workInProgress.memoizedState;

const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
if (typeof getDerivedStateFromProps === 'function') {
Expand All @@ -863,17 +860,13 @@ function mountClassInstance(
callComponentWillMount(workInProgress, instance);
// If we had additional state updates during this life-cycle, let's
// process them now.
updateQueue = workInProgress.updateQueue;
if (updateQueue !== null) {
processUpdateQueue(
workInProgress,
updateQueue,
newProps,
instance,
renderExpirationTime,
);
instance.state = workInProgress.memoizedState;
}
processUpdateQueue(
workInProgress,
newProps,
instance,
renderExpirationTime,
);
instance.state = workInProgress.memoizedState;
}

if (typeof instance.componentDidMount === 'function') {
Expand Down Expand Up @@ -936,17 +929,8 @@ function resumeMountClassInstance(

const oldState = workInProgress.memoizedState;
let newState = (instance.state = oldState);
let updateQueue = workInProgress.updateQueue;
if (updateQueue !== null) {
processUpdateQueue(
workInProgress,
updateQueue,
newProps,
instance,
renderExpirationTime,
);
newState = workInProgress.memoizedState;
}
processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime);
newState = workInProgress.memoizedState;
if (
oldProps === newProps &&
oldState === newState &&
Expand Down Expand Up @@ -1035,6 +1019,8 @@ function updateClassInstance(
): boolean {
const instance = workInProgress.stateNode;

cloneUpdateQueue(current, workInProgress);

const oldProps = workInProgress.memoizedProps;
instance.props =
workInProgress.type === workInProgress.elementType
Expand Down Expand Up @@ -1081,17 +1067,8 @@ function updateClassInstance(

const oldState = workInProgress.memoizedState;
let newState = (instance.state = oldState);
let updateQueue = workInProgress.updateQueue;
if (updateQueue !== null) {
processUpdateQueue(
workInProgress,
updateQueue,
newProps,
instance,
renderExpirationTime,
);
newState = workInProgress.memoizedState;
}
processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime);
newState = workInProgress.memoizedState;

if (
oldProps === newProps &&
Expand Down