Skip to content

fix: support mock method names inherited from Object.prototype - #2785

Open
maxazure wants to merge 1 commit into
sinonjs:mainfrom
maxazure:fix/mock-expectation-property-names
Open

maxazure wants to merge 1 commit into
sinonjs:mainfrom
maxazure:fix/mock-expectation-property-names

Conversation

@maxazure

Copy link
Copy Markdown

Purpose (TL;DR) - mandatory

Allow mocks to expect methods named toString, hasOwnProperty, constructor, and __proto__. The expectation dictionary currently inherits these names from Object.prototype, so expects() treats inherited values as existing expectation lists instead of wrapping the method.

Use a dictionary without a prototype so all method names refer to actual expectation lists. Tests cover two argument-specific expectations per method, returned values, verification, and restoration of the original method.

How to verify - mandatory

  1. Check out this branch and run npm ci.
  2. Run npx mocha test/src/mock-test.js --grep 'method named' (4 passing). Against the unmodified source, the toString, hasOwnProperty, and constructor cases each fail with a TypeError; run baseline cases in separate processes because inherited values can be mutated.
  3. Run npm run test-node, npm run lint, npm run prettier:check, npm test, and npm run test-contract.

Verified locally on Node v25.2.1: mock suite 113 passing; Node suite 1564 passing / 12 pending; headless browser suite 1557 passing / 13 pending; WebWorker smoke 1 passing. Lint, formatting, and distribution/browser contract tests pass.

Checklist for author

  • npm run lint passes
  • References to standard library functions are cached.

Copilot AI balanced review requested due to automatic review settings October 13, 2026 00:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The one-line fix is correct and consistent with existing Object.create(null) usage in the codebase (e.g. walk.js:66), all expectations access occurs via the proxies array or bracket access without relying on prototype methods, and the added tests cover the fixed behavior.

0 open findings

What changed in this PR

This PR fixes a bug in Sinon's mock implementation where method names that collide with inherited Object.prototype members (toString, hasOwnProperty, constructor, __proto__) could not be mocked. The expectation dictionary was created with a plain object literal ({}), so expects() saw inherited values when checking this.expectations[method], mistaking them for existing expectation lists instead of wrapping the method. Using Object.create(null) removes the prototype chain so every key refers to an actual expectation list.

Changes:

  • Switch the expectations store in mock.expects from {} to Object.create(null).
  • Add a parameterized test covering mocking, invocation, verification, and restoration for the four prototype-colliding method names.
File Description
src/​sinon/​mock.js Create the expectations dictionary without a prototype so inherited names no longer shadow real expectation lists.
test/​src/​mock-test.js Add tests verifying mock/expect/verify/restore behavior for toString, hasOwnProperty, constructor, and __proto__.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

This branch has not been deployed

No deployments
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.

2 participants