-
Notifications
You must be signed in to change notification settings - Fork 4.7k
fix(bun:test): constructing a mock function must return an object #31381
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟣 Not blocking, and pre-existing, but worth a follow-up:
mock.instancesis still never populated —fn->instancesis only declared, cleared, lazily created empty, and GC-visited, never written to — so even with the new construct path,new fn(); fn.mock.instancesis[]where Jest gives[<instance>]. Since this PR now creates the verythisObjectthatmock.instancesis meant to record, it'd be a natural place to push it (and, to fully match Jest, pushthisValueon every call alongside thecontextspush injsMockFunctionCallImpl).Extended reasoning...
What this is
JSMockFunctionhas aninstancesfield (line 271) that backsmockFn.mock.instances, but nothing in the file ever writes to it. Grepping confirms it appears only at:WriteBarrier<JSArray>declaration,clear()clears it,getInstances()lazily creates an empty array,"instances"slot in the mock object structure.There is no
instances->push(...)orinitializeIndexcall anywhere, sofn.mock.instancesis always an empty array — both before and after this PR. In Jest,mock.instancesrecords thethisvalue for every invocation (parallel tomock.contexts), and is most useful exactly for thenew fn()case this PR is adding.Why mention it on this PR
This is a pre-existing gap —
instanceshas never been populated in Bun, and this PR does not regress it. The refutation correctly notes that the PR's stated scope is theisCell()crash fix and that "matching Jest's behavior" in the description refers to the primitive-return-replaced-by-thissemantics, not fullmock.instancesparity. That's all fair, and this should not block the PR.It is still worth a non-blocking note because the new
jsMockFunctionConstructis the first place in this file that actually creates the instance object thatmock.instancesis supposed to hold. Before this PR there was no obvious hook; now there is, and it's two lines away from where the value would be pushed. Flagging it as a "while you're here" follow-up is reasonable; landing it separately is equally fine.Step-by-step proof
const fn = jest.fn();const inst = new fn();— entersjsMockFunctionConstruct(line 989), allocatesthisObject(lines 1003–1005), callsjsMockFunctionCallImplwiththisValue = thisObject.jsMockFunctionCallImplpushes ontofn->calls,fn->contexts,fn->invocationCallOrder, andfn->returnValues(lines 854–910). It never touchesfn->instances.jsMockFunctionConstructreturnsthisObject(line 1015).fn->instancesis still unset.fn.mock.instancestriggersgetInstances()(line 420), which lazily creates an empty array. Result:[].[inst].Suggested follow-up fix
In
jsMockFunctionCallImpl, right next to the existingcontextspush (lines 868–880), add an analogous block that pushesthisValueontofn->instances. That matches Jest exactly: Jest recordsthisintomock.instanceson every call (for plain calls it's the receiver, fornewit's the freshly created instance), so doing it only injsMockFunctionConstructwould still diverge for non-construct calls. Doing it in the shared impl covers both, and the new construct path already threads the rightthisObjectthrough asthisValue.