From 60cb32bf9331045819505a2d390080d67d06ce7a Mon Sep 17 00:00:00 2001 From: Mengdi Chen Date: Fri, 25 Mar 2022 14:09:13 -0400 Subject: [PATCH 1/3] [ReactDebugTools] add custom error type for future new hooks --- .../src/ReactDebugCustomErrors.js | 27 +++++++++++++++++++ .../react-debug-tools/src/ReactDebugHooks.js | 20 ++++++++++++-- .../react-debug-tools/src/ReactDebugTools.js | 3 ++- 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 packages/react-debug-tools/src/ReactDebugCustomErrors.js diff --git a/packages/react-debug-tools/src/ReactDebugCustomErrors.js b/packages/react-debug-tools/src/ReactDebugCustomErrors.js new file mode 100644 index 0000000000000..ae3a22446ac82 --- /dev/null +++ b/packages/react-debug-tools/src/ReactDebugCustomErrors.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +/** + * This file contains a list of custom Errors that ReactDebugTools can throw in + * special occasions. + * The names of the errors are exported so that other packages (such as DevTools) + * can use them to detect and handle them separately. + */ + +export const ErrorsNames = { + UNSUPPORTTED_FEATURE_ERROR: 'UnsupportedFeatureError', +}; + +// For now we just override the name. If we decide to move react-debug-tools to +// devtools package, we should use a real Error class instead. +export function createUnsupportedFeatureError(message: string = '') { + const error = new Error(message); + error.name = ErrorsNames.UNSUPPORTTED_FEATURE_ERROR; + return error; +} diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index b7159859060e7..9f1a9e24728f5 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -29,6 +29,7 @@ import { ContextProvider, ForwardRef, } from 'react-reconciler/src/ReactWorkTags'; +import {createUnsupportedFeatureError} from './ReactDebugCustomErrors'; type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher; @@ -356,6 +357,21 @@ const Dispatcher: DispatcherType = { useId, }; +// create a proxy to throw a custom error +// in case future versions of React adds more hooks +const DispatcherProxyHandler = { + get(target, prop, _receiver) { + if (target.hasOwnProperty(prop)) { + return Reflect.get(...arguments); + } + throw createUnsupportedFeatureError( + 'Missing method in Dispatcher: ' + prop, + ); + }, +}; + +const DispatcherProxy = new Proxy(Dispatcher, DispatcherProxyHandler); + // Inspect export type HookSource = { @@ -664,7 +680,7 @@ export function inspectHooks( const previousDispatcher = currentDispatcher.current; let readHookLog; - currentDispatcher.current = Dispatcher; + currentDispatcher.current = DispatcherProxy; let ancestorStackError; try { ancestorStackError = new Error(); @@ -708,7 +724,7 @@ function inspectHooksOfForwardRef( ): HooksTree { const previousDispatcher = currentDispatcher.current; let readHookLog; - currentDispatcher.current = Dispatcher; + currentDispatcher.current = DispatcherProxy; let ancestorStackError; try { ancestorStackError = new Error(); diff --git a/packages/react-debug-tools/src/ReactDebugTools.js b/packages/react-debug-tools/src/ReactDebugTools.js index 7f441e0d2fedc..ca19ce8a08f30 100644 --- a/packages/react-debug-tools/src/ReactDebugTools.js +++ b/packages/react-debug-tools/src/ReactDebugTools.js @@ -8,5 +8,6 @@ */ import {inspectHooks, inspectHooksOfFiber} from './ReactDebugHooks'; +import {ErrorsNames} from './ReactDebugCustomErrors'; -export {inspectHooks, inspectHooksOfFiber}; +export {inspectHooks, inspectHooksOfFiber, ErrorsNames}; From 12ecbea744b9a22ed79ee3cf4cc1263467db0378 Mon Sep 17 00:00:00 2001 From: Mengdi Chen Date: Tue, 29 Mar 2022 13:07:01 -0400 Subject: [PATCH 2/3] update per review comments --- .../src/ReactDebugCustomErrors.js | 27 ------------------- .../react-debug-tools/src/ReactDebugHooks.js | 11 ++++---- .../react-debug-tools/src/ReactDebugTools.js | 3 +-- 3 files changed, 7 insertions(+), 34 deletions(-) delete mode 100644 packages/react-debug-tools/src/ReactDebugCustomErrors.js diff --git a/packages/react-debug-tools/src/ReactDebugCustomErrors.js b/packages/react-debug-tools/src/ReactDebugCustomErrors.js deleted file mode 100644 index ae3a22446ac82..0000000000000 --- a/packages/react-debug-tools/src/ReactDebugCustomErrors.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -/** - * This file contains a list of custom Errors that ReactDebugTools can throw in - * special occasions. - * The names of the errors are exported so that other packages (such as DevTools) - * can use them to detect and handle them separately. - */ - -export const ErrorsNames = { - UNSUPPORTTED_FEATURE_ERROR: 'UnsupportedFeatureError', -}; - -// For now we just override the name. If we decide to move react-debug-tools to -// devtools package, we should use a real Error class instead. -export function createUnsupportedFeatureError(message: string = '') { - const error = new Error(message); - error.name = ErrorsNames.UNSUPPORTTED_FEATURE_ERROR; - return error; -} diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index 9f1a9e24728f5..c013d3488d6a5 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -29,7 +29,6 @@ import { ContextProvider, ForwardRef, } from 'react-reconciler/src/ReactWorkTags'; -import {createUnsupportedFeatureError} from './ReactDebugCustomErrors'; type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher; @@ -362,11 +361,13 @@ const Dispatcher: DispatcherType = { const DispatcherProxyHandler = { get(target, prop, _receiver) { if (target.hasOwnProperty(prop)) { - return Reflect.get(...arguments); + return target[prop]; } - throw createUnsupportedFeatureError( - 'Missing method in Dispatcher: ' + prop, - ); + const error = new Error('Missing method in Dispatcher: ' + prop); + // Note: This error name needs to stay in sync with react-devtools-shared + // TODO: refactor this if we ever combine the devtools and debug tools packages + error.name = 'UnsupportedFeatureError'; + throw error; }, }; diff --git a/packages/react-debug-tools/src/ReactDebugTools.js b/packages/react-debug-tools/src/ReactDebugTools.js index ca19ce8a08f30..7f441e0d2fedc 100644 --- a/packages/react-debug-tools/src/ReactDebugTools.js +++ b/packages/react-debug-tools/src/ReactDebugTools.js @@ -8,6 +8,5 @@ */ import {inspectHooks, inspectHooksOfFiber} from './ReactDebugHooks'; -import {ErrorsNames} from './ReactDebugCustomErrors'; -export {inspectHooks, inspectHooksOfFiber, ErrorsNames}; +export {inspectHooks, inspectHooksOfFiber}; From ed70bfab2fa4666cbc62c20af90bca88c7edea6e Mon Sep 17 00:00:00 2001 From: Mengdi Chen Date: Wed, 30 Mar 2022 10:46:43 -0400 Subject: [PATCH 3/3] remove unused argument --- packages/react-debug-tools/src/ReactDebugHooks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index c013d3488d6a5..49bf65e3136fa 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -359,7 +359,7 @@ const Dispatcher: DispatcherType = { // create a proxy to throw a custom error // in case future versions of React adds more hooks const DispatcherProxyHandler = { - get(target, prop, _receiver) { + get(target, prop) { if (target.hasOwnProperty(prop)) { return target[prop]; }