Skip to content

fix(deepEqual): support objects with null prototypes #4752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

iamakulov
Copy link

While reviewing a project crash for a client, I discovered that the deepEqual function (invoked by getConnectors) crashes if some field inside a connector is an object without a prototype:

const a = Object.create(null)

if (a.valueOf !== Object.prototype.valueOf)
    return a.valueOf() === b.valueOf();
          // ↑ fails with “TypeError: a.valueOf is not a function” since an object
          // with no prototype will have `a.valueOf === undefined`

This PR fixes that.

Copy link

vercel bot commented Aug 4, 2025

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

Name Status Preview Comments Updated (UTC)
wagmi ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 4, 2025 2:42pm

Copy link

changeset-bot bot commented Aug 4, 2025

🦋 Changeset detected

Latest commit: 295babd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@wagmi/core Patch
@wagmi/connectors Patch
wagmi Patch
@wagmi/vue Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@iamakulov
Copy link
Author

Dug deeper into this. Another issue this deepEqual implementation has is it also crashes with Maximum call stack size exceeded if any passed object has circular references.

Critically, it’s pretty easy to end up that state. I still don’t have the full picture of how exactly it’s happening, but it appears that:

  • Wagmi adds an emitter (instance of eventemitter3) object onto every connector created through it. This object has both __proto__ === null and a circular reference to itself
  • Whenever you call getConnectors(), Wagmi deep-compares previous and new connectors
  • So if you ever recreate a connector from scratch (which can easily happen during SSR, where the React state gets reset on every request), Wagmi will end up deep-comparing the previous and the new connector – and crashing inside deepEqual when it tries to compare emitter objects

I guess the answer to this is “don’t store Wagmi connectors in your React state, duh”. But it would’ve been nice if Wagmi had a better DX around this (rather than just crashing with a.valueOf is not a function or Maximum call stack size exceeded).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant