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

[Fiber] Make error handling more resilient #8210

Merged
merged 3 commits into from
Nov 5, 2016

Conversation

gaearon
Copy link
Collaborator

@gaearon gaearon commented Nov 4, 2016

Supersedes #8166.

  • Create a separate test file for incremental error handling
  • Ensure that errors in one root don't prevent work on another root
  • Fix an issue where boundary state change would get ignored in incremental mode

* Ensure that errors in one root don't prevent work on another root
* Fix an issue where boundary state change would get ignored in incremental mode
@@ -1465,27 +1465,4 @@ describe('ReactIncremental', () => {
]);
expect(instance.state.n).toEqual(4);
});

it('propagates an error from a noop error boundary', () => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was just moved into another file.

@@ -561,47 +603,28 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
try {
performTaskWorkUnsafe();
} catch (error) {
isPerformingTaskWork = false;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I moved this one into a try/finally in performTaskWorkUnsafe so that it's only set there.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree it's easier to follow this way but I don't think it's worth a perf hit

scheduleCallbackAtPriority(nextPriorityLevel);
}
} finally {
isPerformingTaskWork = false;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Functions that contain a try-catch/finally can't be optimized in V8. Can we move this reset back to the catch in handleErrors?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Usual strategy is to split the try-catch/finally block into a separate function that does nothing but an unsafe function. We should do a pass at some point to do this across the codebase.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I know but we're completely moving this code around every week. I'm worried microoptimizations just make it hard to follow right now. Let's do a pass as soon as it stabilizes a little bit?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Haha good point

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe drop a TODO in there?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍 Could you please?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When we do it, we should do it consistently IMO, not in an ad hoc way. Use a tryCatch helper like Bluebird or something like this.

trapError(nextUnitOfWork, error, false);
}
}

// Unschedule the roots that fataled so that we can later schedule
// other updates to the same roots and potentially replace them.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you explain in more detail why it's necessary to unschedule failed roots?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I want to continue working on the other roots in the same frame even if some failed, and only throw errors after all work is done (or frame is over). If I don't unschedule failed roots, findNextUnitOfWork will find them again, and we'll get into an infinite loop handling their errors again, then finding them again, and so on.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I also don't want to get errors about a root I rendered once every time I schedule an update to another unrelated root. So I need it to be gone from the list until I explicitly retry it. You can see the desired behavior in the last test I added.

});
}

function unscheduleWork(unscheduledRoots : Set<FiberRoot>) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we had a way to only perform work on a specific root if we could avoid having to unschedule.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I suspect this might not be too challenging. Add the ability to pass a root to perform* functions. If so, they won't attempt to look for new work once they run out.

Copy link
Collaborator Author

@gaearon gaearon Nov 4, 2016

Choose a reason for hiding this comment

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

How would I know which root to work on? I only know which roots not to work on.

@acdlite
Copy link
Collaborator

acdlite commented Nov 5, 2016

Going to try to remove the need for unscheduling for a bit, otherwise I'll merge as-is

@gaearon
Copy link
Collaborator Author

gaearon commented Nov 5, 2016

👍 Leaving it to you.

We can use the existing unscheduling logic in findNextUnitOfWork.
@acdlite acdlite merged commit c0c2455 into facebook:master Nov 5, 2016
@gaearon gaearon deleted the fiber-error-boundaries-fatal branch November 8, 2016 18:25
@gaearon gaearon mentioned this pull request Nov 8, 2016
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants