Skip to content

Commit

Permalink
Add on(Caught|Uncaught|Recoverable) opts to RN (#28836)
Browse files Browse the repository at this point in the history
## Overview

There's currently a bug in RN now that we no longer re-throw errors. The
`showErrorDialog` function in React Native only logs the errors as soft
errors, and never a fatal. RN was depending on the global handler for
the fatal error handling and logging.

Instead of fixing this in `ReactFiberErrorDialog`, we can implement the
new root options in RN to handle caught/uncaught/recoverable in the
respective functions, and delete ReactFiberErrorDialog. I'll follow up
with a RN PR to implement these options and fix the error handling.

DiffTrain build for commit 0347fcd.
  • Loading branch information
rickhanlonii committed Apr 15, 2024
1 parent 4cc7d27 commit 8017f27
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9defcd56bc3cd53ac2901ed93f29218007010434
0347fcd0073cf529f67a05be86a0545c3efab8e2
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<158d73c5518a6a28f53717610189a696>>
* @generated SignedSource<<bd640d85592d7d9b873f1a2f979ad51a>>
*/

"use strict";
Expand Down Expand Up @@ -30286,7 +30286,7 @@ to return true:wantsResponderID| |
return root;
}

var ReactVersion = "19.0.0-canary-5d6d8736";
var ReactVersion = "19.0.0-canary-9cace4d2";

/*
* The `'' + value` pattern (used in perf-sensitive code) throws for Symbol
Expand Down Expand Up @@ -31464,22 +31464,40 @@ to return true:wantsResponderID| |
defaultOnCaughtError(error, errorInfo);
}

function render(element, containerTag, callback, concurrentRoot) {
function render(element, containerTag, callback, concurrentRoot, options) {
var root = roots.get(containerTag);

if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// TODO: these defaults are for backwards compatibility.
// Once RN implements these options internally,
// we can remove the defaults and ReactFiberErrorDialog.
var onUncaughtError = nativeOnUncaughtError;
var onCaughtError = nativeOnCaughtError;
var onRecoverableError = defaultOnRecoverableError;

if (options && options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}

if (options && options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}

if (options && options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
} // TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.

root = createContainer(
containerTag,
concurrentRoot ? ConcurrentRoot : LegacyRoot,
null,
false,
null,
"",
nativeOnUncaughtError,
nativeOnCaughtError,
defaultOnRecoverableError,
onUncaughtError,
onCaughtError,
onRecoverableError,
null
);
roots.set(containerTag, root);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<0e4b40bc0587df35c50de0d0321f8af2>>
* @generated SignedSource<<34dfa97c1577841a85cbb93e6d1aa9b7>>
*/

"use strict";
Expand Down Expand Up @@ -10597,7 +10597,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1099 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "19.0.0-canary-8cc7c10c",
version: "19.0.0-canary-08aa6077",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand Down Expand Up @@ -10640,7 +10640,7 @@ var internals$jscomp$inline_1366 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-canary-8cc7c10c"
reconcilerVersion: "19.0.0-canary-08aa6077"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1367 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -10714,34 +10714,52 @@ exports.getPublicInstanceFromInternalInstanceHandle = function (
exports.isChildPublicInstance = function () {
throw Error("isChildPublicInstance() is not available in production.");
};
exports.render = function (element, containerTag, callback, concurrentRoot) {
exports.render = function (
element,
containerTag,
callback,
concurrentRoot,
options
) {
var root = roots.get(containerTag);
if (!root) {
root = concurrentRoot ? 1 : 0;
concurrentRoot = new FiberRootNode(
root = nativeOnUncaughtError;
var onCaughtError = nativeOnCaughtError,
onRecoverableError = defaultOnRecoverableError;
options &&
void 0 !== options.onUncaughtError &&
(root = options.onUncaughtError);
options &&
void 0 !== options.onCaughtError &&
(onCaughtError = options.onCaughtError);
options &&
void 0 !== options.onRecoverableError &&
(onRecoverableError = options.onRecoverableError);
concurrentRoot = concurrentRoot ? 1 : 0;
options = new FiberRootNode(
containerTag,
root,
concurrentRoot,
!1,
"",
nativeOnUncaughtError,
nativeOnCaughtError,
defaultOnRecoverableError,
root,
onCaughtError,
onRecoverableError,
null
);
root = createFiber(3, null, null, 1 === root ? 1 : 0);
concurrentRoot.current = root;
root.stateNode = concurrentRoot;
var initialCache = createCache();
initialCache.refCount++;
concurrentRoot.pooledCache = initialCache;
initialCache.refCount++;
root.memoizedState = {
concurrentRoot = createFiber(3, null, null, 1 === concurrentRoot ? 1 : 0);
options.current = concurrentRoot;
concurrentRoot.stateNode = options;
root = createCache();
root.refCount++;
options.pooledCache = root;
root.refCount++;
concurrentRoot.memoizedState = {
element: null,
isDehydrated: !1,
cache: initialCache
cache: root
};
initializeUpdateQueue(root);
root = concurrentRoot;
initializeUpdateQueue(concurrentRoot);
root = options;
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<7546478ab9f50ee5a66b895958b26b28>>
* @generated SignedSource<<d86bdae683e0b6b9649eb43c0d5548c4>>
*/

"use strict";
Expand Down Expand Up @@ -11302,7 +11302,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1179 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "19.0.0-canary-cae54ba1",
version: "19.0.0-canary-42633113",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand Down Expand Up @@ -11358,7 +11358,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-canary-cae54ba1"
reconcilerVersion: "19.0.0-canary-42633113"
});
exports.createPortal = function (children, containerTag) {
return createPortal$1(
Expand Down Expand Up @@ -11419,36 +11419,54 @@ exports.getPublicInstanceFromInternalInstanceHandle = function (
exports.isChildPublicInstance = function () {
throw Error("isChildPublicInstance() is not available in production.");
};
exports.render = function (element, containerTag, callback, concurrentRoot) {
exports.render = function (
element,
containerTag,
callback,
concurrentRoot,
options
) {
var root = roots.get(containerTag);
if (!root) {
root = concurrentRoot ? 1 : 0;
concurrentRoot = new FiberRootNode(
root = nativeOnUncaughtError;
var onCaughtError = nativeOnCaughtError,
onRecoverableError = defaultOnRecoverableError;
options &&
void 0 !== options.onUncaughtError &&
(root = options.onUncaughtError);
options &&
void 0 !== options.onCaughtError &&
(onCaughtError = options.onCaughtError);
options &&
void 0 !== options.onRecoverableError &&
(onRecoverableError = options.onRecoverableError);
concurrentRoot = concurrentRoot ? 1 : 0;
options = new FiberRootNode(
containerTag,
root,
concurrentRoot,
!1,
"",
nativeOnUncaughtError,
nativeOnCaughtError,
defaultOnRecoverableError,
root,
onCaughtError,
onRecoverableError,
null
);
root = 1 === root ? 1 : 0;
isDevToolsPresent && (root |= 2);
root = createFiber(3, null, null, root);
concurrentRoot.current = root;
root.stateNode = concurrentRoot;
var initialCache = createCache();
initialCache.refCount++;
concurrentRoot.pooledCache = initialCache;
initialCache.refCount++;
root.memoizedState = {
concurrentRoot = 1 === concurrentRoot ? 1 : 0;
isDevToolsPresent && (concurrentRoot |= 2);
concurrentRoot = createFiber(3, null, null, concurrentRoot);
options.current = concurrentRoot;
concurrentRoot.stateNode = options;
root = createCache();
root.refCount++;
options.pooledCache = root;
root.refCount++;
concurrentRoot.memoizedState = {
element: null,
isDehydrated: !1,
cache: initialCache
cache: root
};
initializeUpdateQueue(root);
root = concurrentRoot;
initializeUpdateQueue(concurrentRoot);
root = options;
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<a8095aaaeaf72137df4e00de44458ad8>>
* @generated SignedSource<<4c35df7e60d1b43bfa4dd44c80eb34bc>>
*/

"use strict";
Expand Down Expand Up @@ -30739,7 +30739,7 @@ to return true:wantsResponderID| |
return root;
}

var ReactVersion = "19.0.0-canary-1adfe2d5";
var ReactVersion = "19.0.0-canary-b604e595";

/*
* The `'' + value` pattern (used in perf-sensitive code) throws for Symbol
Expand Down Expand Up @@ -31911,22 +31911,40 @@ to return true:wantsResponderID| |
defaultOnCaughtError(error, errorInfo);
}

function render(element, containerTag, callback) {
function render(element, containerTag, callback, options) {
var root = roots.get(containerTag);

if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// TODO: these defaults are for backwards compatibility.
// Once RN implements these options internally,
// we can remove the defaults and ReactFiberErrorDialog.
var onUncaughtError = nativeOnUncaughtError;
var onCaughtError = nativeOnCaughtError;
var onRecoverableError = defaultOnRecoverableError;

if (options && options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}

if (options && options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}

if (options && options.onRecoverableError !== undefined) {
onRecoverableError = options.onRecoverableError;
} // TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.

root = createContainer(
containerTag,
LegacyRoot,
null,
false,
null,
"",
nativeOnUncaughtError,
nativeOnCaughtError,
defaultOnRecoverableError,
onUncaughtError,
onCaughtError,
onRecoverableError,
null
);
roots.set(containerTag, root);
Expand Down
Loading

0 comments on commit 8017f27

Please sign in to comment.