Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 31 additions & 20 deletions packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ if (__DEV__) {

function FiberNode(
tag: TypeOfWork,
pendingProps: mixed,
key: null | string,
internalContextTag: TypeOfInternalContext,
) {
Expand All @@ -169,7 +170,7 @@ function FiberNode(

this.ref = null;

this.pendingProps = null;
this.pendingProps = pendingProps;
this.memoizedProps = null;
this.updateQueue = null;
this.memoizedState = null;
Expand Down Expand Up @@ -213,11 +214,12 @@ function FiberNode(
// compatible.
var createFiber = function(
tag: TypeOfWork,
pendingProps: mixed,
key: null | string,
internalContextTag: TypeOfInternalContext,
): Fiber {
// $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
return new FiberNode(tag, key, internalContextTag);
return new FiberNode(tag, pendingProps, key, internalContextTag);
};

function shouldConstruct(Component) {
Expand All @@ -239,6 +241,7 @@ export function createWorkInProgress(
// reclaim the extra memory if needed.
workInProgress = createFiber(
current.tag,
pendingProps,
current.key,
current.internalContextTag,
);
Expand All @@ -255,6 +258,8 @@ export function createWorkInProgress(
workInProgress.alternate = current;
current.alternate = workInProgress;
} else {
workInProgress.pendingProps = pendingProps;

// We already have an alternate.
// Reset the effect tag.
workInProgress.effectTag = NoEffect;
Expand All @@ -266,7 +271,6 @@ export function createWorkInProgress(
}

workInProgress.expirationTime = expirationTime;
workInProgress.pendingProps = pendingProps;

workInProgress.child = current.child;
workInProgress.memoizedProps = current.memoizedProps;
Expand Down Expand Up @@ -297,17 +301,22 @@ export function createFiberFromElement(
}

let fiber;
const {type, key} = element;
const type = element.type;
const key = element.key;
const pendingProps = element.props;
if (typeof type === 'function') {
fiber = shouldConstruct(type)
? createFiber(ClassComponent, key, internalContextTag)
: createFiber(IndeterminateComponent, key, internalContextTag);
? createFiber(ClassComponent, pendingProps, key, internalContextTag)
: createFiber(
IndeterminateComponent,
pendingProps,
key,
internalContextTag,
);
fiber.type = type;
fiber.pendingProps = element.props;
} else if (typeof type === 'string') {
fiber = createFiber(HostComponent, key, internalContextTag);
fiber = createFiber(HostComponent, pendingProps, key, internalContextTag);
fiber.type = type;
fiber.pendingProps = element.props;
} else if (
typeof type === 'object' &&
type !== null &&
Expand All @@ -320,7 +329,7 @@ export function createFiberFromElement(
// we don't know if we can reuse that fiber or if we need to clone it.
// There is probably a clever way to restructure this.
fiber = ((type: any): Fiber);
fiber.pendingProps = element.props;
fiber.pendingProps = pendingProps;
} else {
let info = '';
if (__DEV__) {
Expand Down Expand Up @@ -364,8 +373,7 @@ export function createFiberFromFragment(
expirationTime: ExpirationTime,
key: null | string,
): Fiber {
const fiber = createFiber(Fragment, key, internalContextTag);
fiber.pendingProps = elements;
const fiber = createFiber(Fragment, elements, key, internalContextTag);
fiber.expirationTime = expirationTime;
return fiber;
}
Expand All @@ -375,14 +383,13 @@ export function createFiberFromText(
internalContextTag: TypeOfInternalContext,
expirationTime: ExpirationTime,
): Fiber {
const fiber = createFiber(HostText, null, internalContextTag);
fiber.pendingProps = content;
const fiber = createFiber(HostText, content, null, internalContextTag);
fiber.expirationTime = expirationTime;
return fiber;
}

export function createFiberFromHostInstanceForDeletion(): Fiber {
const fiber = createFiber(HostComponent, null, NoContext);
const fiber = createFiber(HostComponent, null, null, NoContext);
fiber.type = 'DELETED';
return fiber;
}
Expand All @@ -392,9 +399,8 @@ export function createFiberFromCall(
internalContextTag: TypeOfInternalContext,
expirationTime: ExpirationTime,
): Fiber {
const fiber = createFiber(CallComponent, call.key, internalContextTag);
const fiber = createFiber(CallComponent, call, call.key, internalContextTag);
fiber.type = call.handler;
fiber.pendingProps = call;
fiber.expirationTime = expirationTime;
return fiber;
}
Expand All @@ -404,7 +410,7 @@ export function createFiberFromReturn(
internalContextTag: TypeOfInternalContext,
expirationTime: ExpirationTime,
): Fiber {
const fiber = createFiber(ReturnComponent, null, internalContextTag);
const fiber = createFiber(ReturnComponent, null, null, internalContextTag);
fiber.expirationTime = expirationTime;
return fiber;
}
Expand All @@ -414,8 +420,13 @@ export function createFiberFromPortal(
internalContextTag: TypeOfInternalContext,
expirationTime: ExpirationTime,
): Fiber {
const fiber = createFiber(HostPortal, portal.key, internalContextTag);
fiber.pendingProps = portal.children || [];
const pendingProps = portal.children !== null ? portal.children : [];
const fiber = createFiber(
HostPortal,
pendingProps,
portal.key,
internalContextTag,
);
fiber.expirationTime = expirationTime;
fiber.stateNode = {
containerInfo: portal.containerInfo,
Expand Down
59 changes: 11 additions & 48 deletions packages/react-reconciler/src/ReactFiberBeginWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,10 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
}

function updateFragment(current, workInProgress) {
var nextChildren = workInProgress.pendingProps;
const nextChildren = workInProgress.pendingProps;
if (hasContextChanged()) {
// Normally we can bail out on props equality but if context has changed
// we don't do the bailout and we have to reuse existing props instead.
if (nextChildren === null) {
nextChildren = workInProgress.memoizedProps;
}
} else if (
nextChildren === null ||
workInProgress.memoizedProps === nextChildren
Expand All @@ -168,18 +165,14 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
}

function updateFunctionalComponent(current, workInProgress) {
var fn = workInProgress.type;
var nextProps = workInProgress.pendingProps;
const fn = workInProgress.type;
const nextProps = workInProgress.pendingProps;

const memoizedProps = workInProgress.memoizedProps;
if (hasContextChanged()) {
// Normally we can bail out on props equality but if context has changed
// we don't do the bailout and we have to reuse existing props instead.
if (nextProps === null) {
nextProps = memoizedProps;
}
} else {
if (nextProps === null || memoizedProps === nextProps) {
if (workInProgress.memoizedProps === nextProps) {
return bailoutOnAlreadyFinishedWork(current, workInProgress);
}
// TODO: consider bringing fn.shouldComponentUpdate() back.
Expand Down Expand Up @@ -373,21 +366,13 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(

const type = workInProgress.type;
const memoizedProps = workInProgress.memoizedProps;
let nextProps = workInProgress.pendingProps;
if (nextProps === null) {
nextProps = memoizedProps;
invariant(
nextProps !== null,
'We should always have pending or current props. This error is ' +
'likely caused by a bug in React. Please file an issue.',
);
}
const nextProps = workInProgress.pendingProps;
const prevProps = current !== null ? current.memoizedProps : null;

if (hasContextChanged()) {
// Normally we can bail out on props equality but if context has changed
// we don't do the bailout and we have to reuse existing props instead.
} else if (nextProps === null || memoizedProps === nextProps) {
} else if (memoizedProps === nextProps) {
return bailoutOnAlreadyFinishedWork(current, workInProgress);
}

Expand Down Expand Up @@ -429,10 +414,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
if (current === null) {
tryToClaimNextHydratableInstance(workInProgress);
}
let nextProps = workInProgress.pendingProps;
if (nextProps === null) {
nextProps = workInProgress.memoizedProps;
}
const nextProps = workInProgress.pendingProps;
memoizeProps(workInProgress, nextProps);
// Nothing to do here. This is terminal. We'll do the completion step
// immediately after.
Expand Down Expand Up @@ -534,19 +516,11 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
}

function updateCallComponent(current, workInProgress, renderExpirationTime) {
var nextCall = (workInProgress.pendingProps: null | ReactCall);
var nextCall = (workInProgress.pendingProps: ReactCall);
if (hasContextChanged()) {
// Normally we can bail out on props equality but if context has changed
// we don't do the bailout and we have to reuse existing props instead.
if (nextCall === null) {
nextCall = current && current.memoizedProps;
invariant(
nextCall !== null,
'We should always have pending or current props. This error is ' +
'likely caused by a bug in React. Please file an issue.',
);
}
} else if (nextCall === null || workInProgress.memoizedProps === nextCall) {
} else if (workInProgress.memoizedProps === nextCall) {
nextCall = workInProgress.memoizedProps;
// TODO: When bailing out, we might need to return the stateNode instead
// of the child. To check it for work.
Expand Down Expand Up @@ -585,22 +559,11 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
renderExpirationTime,
) {
pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
let nextChildren = workInProgress.pendingProps;
const nextChildren = workInProgress.pendingProps;
if (hasContextChanged()) {
// Normally we can bail out on props equality but if context has changed
// we don't do the bailout and we have to reuse existing props instead.
if (nextChildren === null) {
nextChildren = current && current.memoizedProps;
invariant(
nextChildren != null,
'We should always have pending or current props. This error is ' +
'likely caused by a bug in React. Please file an issue.',
);
}
} else if (
nextChildren === null ||
workInProgress.memoizedProps === nextChildren
) {
} else if (workInProgress.memoizedProps === nextChildren) {
return bailoutOnAlreadyFinishedWork(current, workInProgress);
}

Expand Down
21 changes: 2 additions & 19 deletions packages/react-reconciler/src/ReactFiberClassComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,7 @@ export default function(

const instance = workInProgress.stateNode;
const state = instance.state || null;

let props = workInProgress.pendingProps;
invariant(
props,
'There must be pending props for an initial mount. This error is ' +
'likely caused by a bug in React. Please file an issue.',
);

const props = workInProgress.pendingProps;
const unmaskedContext = getUnmaskedContext(workInProgress);

instance.props = props;
Expand Down Expand Up @@ -593,17 +586,7 @@ export default function(
resetInputPointers(workInProgress, instance);

const oldProps = workInProgress.memoizedProps;
let newProps = workInProgress.pendingProps;
if (!newProps) {
// If there aren't any new props, then we'll reuse the memoized props.
// This could be from already completed work.
newProps = oldProps;
invariant(
newProps != null,
'There should always be pending or memoized props. This error is ' +
'likely caused by a bug in React. Please file an issue.',
);
}
const newProps = workInProgress.pendingProps;
const oldContext = instance.context;
const newUnmaskedContext = getUnmaskedContext(workInProgress);
const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
Expand Down
14 changes: 1 addition & 13 deletions packages/react-reconciler/src/ReactFiberCompleteWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import {
popContextProvider,
popTopLevelContextObject,
} from './ReactFiberContext';
import {Never} from './ReactFiberExpirationTime';

export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
Expand Down Expand Up @@ -392,18 +391,7 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
workInProgress: Fiber,
renderExpirationTime: ExpirationTime,
): Fiber | null {
// Get the latest props.
let newProps = workInProgress.pendingProps;
if (newProps === null) {
newProps = workInProgress.memoizedProps;
} else if (
workInProgress.expirationTime !== Never ||
renderExpirationTime === Never
) {
// Reset the pending props, unless this was a down-prioritization.
workInProgress.pendingProps = null;
}

const newProps = workInProgress.pendingProps;
switch (workInProgress.tag) {
case FunctionalComponent:
return null;
Expand Down