Skip to content

Commit cbbe866

Browse files
authored
fix value formatting of proxies of class instances (#30880)
For Hookstate Proxies of class instances, `data.constructor.name` returns `Proxy({})`, so use `Object.getPrototypeOf(data).constructor.name` instead, which works correctly from my testing. <!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary React DevTools immediately bricks itself if you inspect any component that has a prop that is a Hookstate that wraps a class instance ... because these are proxies where `data.constructor.name` returns some un-cloneable object, but `Object.getPrototypeOf(data)` doesn't return `Object` (it returns the prototype of the class inside). ## How did you test this change? This part of the code has no associated tests at all. Technically, `packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js` exists, but I tried `yarn test` and these tests aren't even executed anymore. I can't figure it out, so whatever. If you run this code: ```js class Class {} const instance = new Class(); const instanceProxy = new Proxy(instance, { get(target, key, receiver) { if (key === 'constructor') { return { name: new Proxy({}, {}) }; } return Reflect.get(target, key, receiver); }, }); ``` then `instanceProxy.constructor.name` returns some proxy that cannot be cloned, but `Object.getPrototypeOf(instanceProxy).constructor.name` returns the correct value. This PR fixes the devtools to use `Object.getPrototypeOf(instanceProxy).constructor.name`. I modified my local copy of devtools to use this method and it fixed the bricking that I experienced. Related #29954
1 parent e0131f1 commit cbbe866

File tree

1 file changed

+19
-1
lines changed
  • packages/react-devtools-shared/src

1 file changed

+19
-1
lines changed

packages/react-devtools-shared/src/utils.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,25 @@ export function formatDataForPreview(
915915
case 'date':
916916
return data.toString();
917917
case 'class_instance':
918-
return data.constructor.name;
918+
try {
919+
let resolvedConstructorName = data.constructor.name;
920+
if (typeof resolvedConstructorName === 'string') {
921+
return resolvedConstructorName;
922+
}
923+
924+
resolvedConstructorName = Object.getPrototypeOf(data).constructor.name;
925+
if (typeof resolvedConstructorName === 'string') {
926+
return resolvedConstructorName;
927+
}
928+
929+
try {
930+
return truncateForDisplay(String(data));
931+
} catch (error) {
932+
return 'unserializable';
933+
}
934+
} catch (error) {
935+
return 'unserializable';
936+
}
919937
case 'object':
920938
if (showFormattedValue) {
921939
const keys = Array.from(getAllEnumerableKeys(data)).sort(alphaSortKeys);

0 commit comments

Comments
 (0)