Skip to content
3 changes: 0 additions & 3 deletions scripts/fiber/tests-failing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -554,9 +554,6 @@ src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponent-test.js
src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponentNestedState-test.js
* should provide up to date values for props

src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponentState-test.js
* should support setting state

src/renderers/shared/stack/reconciler/__tests__/ReactEmptyComponent-test.js
* should still throw when rendering to undefined
* should be able to switch between rendering null and a normal tag
Expand Down
2 changes: 2 additions & 0 deletions scripts/fiber/tests-passing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
* skips will/DidUpdate when bailing unless an update was already in progress
* performs batched updates at the end of the batch
* can nest batchedUpdates
* propagates an error from a noop error boundary

src/renderers/shared/fiber/__tests__/ReactIncrementalReflection-test.js
* handles isMounted even when the initial render is deferred
Expand Down Expand Up @@ -1016,6 +1017,7 @@ src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponentDOMMinima
* should not render extra nodes for non-interpolated text

src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponentState-test.js
* should support setting state
* should batch unmounts

src/renderers/shared/stack/reconciler/__tests__/ReactEmptyComponent-test.js
Expand Down
76 changes: 25 additions & 51 deletions src/renderers/shared/fiber/ReactFiberCommitWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

'use strict';

import type { TrappedError } from 'ReactFiberErrorBoundary';
import type { Fiber } from 'ReactFiber';
import type { FiberRoot } from 'ReactFiberRoot';
import type { HostConfig } from 'ReactFiberReconciler';
Expand All @@ -24,7 +23,6 @@ var {
HostComponent,
HostText,
} = ReactTypeOfWork;
var { trapError } = require('ReactFiberErrorBoundary');
var { callCallbacks } = require('ReactFiberUpdateQueue');

var {
Expand All @@ -33,7 +31,10 @@ var {
Callback,
} = require('ReactTypeOfSideEffect');

module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
module.exports = function<T, P, I, TI, C>(
config : HostConfig<T, P, I, TI, C>,
trapError : (fiber : Fiber, error: Error, isUnmounting : boolean) => void
) {

const updateContainer = config.updateContainer;
const commitUpdate = config.commitUpdate;
Expand Down Expand Up @@ -156,94 +157,71 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
}
}

function commitNestedUnmounts(root : Fiber): Array<TrappedError> | null {
// Since errors are rare, we allocate this array on demand.
let trappedErrors = null;

function commitNestedUnmounts(root : Fiber): void {
// While we're inside a removed host node we don't want to call
// removeChild on the inner nodes because they're removed by the top
// call anyway. We also want to call componentWillUnmount on all
// composites before this host node is removed from the tree. Therefore
// we do an inner loop while we're still inside the host node.
let node : Fiber = root;
while (true) {
const error = commitUnmount(node);
if (error) {
trappedErrors = trappedErrors || [];
trappedErrors.push(error);
}
commitUnmount(node);
if (node.child) {
// TODO: Coroutines need to visit the stateNode.
node = node.child;
continue;
}
if (node === root) {
return trappedErrors;
return;
}
while (!node.sibling) {
if (!node.return || node.return === root) {
return trappedErrors;
return;
}
node = node.return;
}
node = node.sibling;
}
return trappedErrors;
}

function unmountHostComponents(parent, current): Array<TrappedError> | null {
// Since errors are rare, we allocate this array on demand.
let trappedErrors = null;

function unmountHostComponents(parent, current): void {
// We only have the top Fiber that was inserted but we need recurse down its
// children to find all the terminal nodes.
let node : Fiber = current;
while (true) {
if (node.tag === HostComponent || node.tag === HostText) {
const errors = commitNestedUnmounts(node);
if (errors) {
if (!trappedErrors) {
trappedErrors = errors;
} else {
trappedErrors.push.apply(trappedErrors, errors);
}
}
commitNestedUnmounts(node);
// After all the children have unmounted, it is now safe to remove the
// node from the tree.
if (parent) {
removeChild(parent, node.stateNode);
}
} else {
const error = commitUnmount(node);
if (error) {
trappedErrors = trappedErrors || [];
trappedErrors.push(error);
}
commitUnmount(node);
if (node.child) {
// TODO: Coroutines need to visit the stateNode.
node = node.child;
continue;
}
}
if (node === current) {
return trappedErrors;
return;
}
while (!node.sibling) {
if (!node.return || node.return === current) {
return trappedErrors;
return;
}
node = node.return;
}
node = node.sibling;
}
return trappedErrors;
}

function commitDeletion(current : Fiber) : Array<TrappedError> | null {
function commitDeletion(current : Fiber) : void {
// Recursively delete all host nodes from the parent.
const parent = getHostParent(current);
// Detach refs and call componentWillUnmount() on the whole subtree.
const trappedErrors = unmountHostComponents(parent, current);
unmountHostComponents(parent, current);

// Cut off the return pointers to disconnect it from the tree. Ideally, we
// should clear the child pointer of the parent alternate to let this
Expand All @@ -256,29 +234,24 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
current.alternate.child = null;
current.alternate.return = null;
}

return trappedErrors;
}

function commitUnmount(current : Fiber) : TrappedError | null {
function commitUnmount(current : Fiber) : void {
switch (current.tag) {
case ClassComponent: {
detachRef(current);
const instance = current.stateNode;
if (typeof instance.componentWillUnmount === 'function') {
const error = tryCallComponentWillUnmount(instance);
if (error) {
return trapError(current, error);
trapError(current, error, true);
}
}
return null;
return;
}
case HostComponent: {
detachRef(current);
return null;
}
default: {
return null;
return;
}
}
}
Expand Down Expand Up @@ -323,7 +296,7 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
}
}

function commitLifeCycles(current : ?Fiber, finishedWork : Fiber) : TrappedError | null {
function commitLifeCycles(current : ?Fiber, finishedWork : Fiber) : void {
switch (finishedWork.tag) {
case ClassComponent: {
const instance = finishedWork.stateNode;
Expand Down Expand Up @@ -353,9 +326,9 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
}
}
if (error) {
return trapError(finishedWork, error);
trapError(finishedWork, error, false);
}
return null;
return;
}
case HostContainer: {
const rootFiber = finishedWork.stateNode;
Expand All @@ -364,15 +337,16 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
rootFiber.callbackList = null;
callCallbacks(callbackList, rootFiber.current.child.stateNode);
}
return;
}
case HostComponent: {
const instance : I = finishedWork.stateNode;
attachRef(current, finishedWork, instance);
return null;
return;
}
case HostText: {
// We have no life-cycles associated with text.
return null;
return;
}
default:
throw new Error('This unit of work tag should not have side-effects.');
Expand Down
53 changes: 0 additions & 53 deletions src/renderers/shared/fiber/ReactFiberErrorBoundary.js

This file was deleted.

Loading