Skip to content

Conversation

@LoganDark
Copy link
Contributor

@LoganDark LoganDark commented Sep 4, 2024

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.

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:

    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

@vercel
Copy link

vercel bot commented Sep 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 5, 2024 2:11am

Copy link

@anandfresh anandfresh left a comment

Choose a reason for hiding this comment

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

LGTM

return data.toString();
case 'class_instance':
return data.constructor.name;
return Object.getPrototypeOf(data).constructor.name;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would rather change it to something like this:

let resolvedConstructorName = data.constructor.name;
if (typeof resolvedConstructorName === 'string') {
  return resolvedConstructorName;
}

resolvedConstructorName =  Object.getPrototypeOf(data).constructor.name;
if (typeof resolvedConstructorName === 'string') {
  return resolvedConstructorName;
}

try {
  return truncateForDisplay(String(data));
} catch (error) {
  return 'unserializable';
}

What do you think?

Copy link
Contributor Author

@LoganDark LoganDark Nov 10, 2024

Choose a reason for hiding this comment

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

I have a feeling that other stuff should be inside the try block as well, but otherwise, that looks good to me :) Do you have push access to my branch ("Allow edits by maintainers" is checked) or would you like me to commit this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please push it? You can also wrap everything in try block, yeah

@github-actions
Copy link

github-actions bot commented Feb 9, 2025

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Feb 9, 2025
@LoganDark
Copy link
Contributor Author

github actions shut uppp ugh I will deal with this soon if I forgot something (I haven't yet checked if I did)

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Feb 9, 2025
@LoganDark LoganDark force-pushed the fix-class-instance-proxies branch from a15f204 to 69f5040 Compare February 12, 2025 17:53
For Hookstate Proxies of classes, `data.constructor.name` returns
`Proxy({})`, so use `Object.getPrototypeOf(data).constructor.name`
instead in that case.
@LoganDark LoganDark force-pushed the fix-class-instance-proxies branch from 69f5040 to f724a9f Compare February 12, 2025 17:55
@LoganDark
Copy link
Contributor Author

image okay I tried to make sure there were no merge commits in my branch but it still says this so I have no idea if this PR will work, but anyway...

Copy link
Contributor

@hoxyq hoxyq left a comment

Choose a reason for hiding this comment

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

Thanks!

@hoxyq hoxyq merged commit cbbe866 into facebook:main Feb 13, 2025
190 checks passed
@LoganDark LoganDark deleted the fix-class-instance-proxies branch February 13, 2025 14:00
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.

5 participants