mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
invokeGuardedCallback is a function we use in place of try-catch statement. It accepts a function, and if the function throws, it captures the error. In production, the implementation is a normal try- catch. In development, we swap out the prod implementation for a special version designed to preserve "Pause on all exceptions" behavior of the browser DevTools. invokeGuardedCallbackDev works by dispatching an event to a dummy DOM node and calling the provided function inside a handler for that event. We also attach an error event handler to the window object. If the function throws, the global event handler is called and we can access the error. The global event handler is added and removed right before and after the fake event is dispatched. But if invokeGuardedCallbackDev is nested -- that is, if it's invoked inside the body of another invokeGuardedCallbackDev -- multiple error event handlers will attached simultaneously. We only want the handler that corresponds to the deepest level to handle the error. So we keep track of a depth counter, and within the event handler, we only handle the error if the current depth matches the depth at the time the function was invoked. The problem that we discovered, and that this PR fixes, is that the depth counter is local to each renderer. So if you nest separate copies of invokeGuardedCallback from separate renderers, each renderer will have its own depth counter, and multiple error handlers will fire for a single, nested error.