Add missing exception checks in expect matchers, mock functions and error construction
Merged
DY
2mo ago+257+257+012345678901234567890123456789-296-296-012345678901234567890123456789
What does this PR do?
Second batch from an audit of native code that performs another JSC operation (or returns) while a JS exception may be pending. This one covers bun:test matchers/mocks and error construction; every site is reachable from user JS.
- Asymmetric matchers (
bindings.cpp): check afterisArrayinexpect.any(Array); after eachgetIndexinexpect.arrayContaining(a throwing index getter previously reachedBun__deepEqualswith the exception pending); aftertoString/RegExp::matchinexpect.stringMatching; aftertoInt32inexpect.closeTo(its two numbers are validated at construction, so they are read withasNumber).Bun__deepMatchandtoHaveProperty(path)check afterisArray(revoked Proxy) before using the result. mockResolvedValue/mockResolvedValueOnce:JSPromise::resolvedPromisereads the value'sconstructorand can throw; that was stored as a null implementation. Now propagates.mockRestore/jest.restoreAllMocks: putting the original back (overrideExportValueon a module namespace,putDirectIndex) can throw;clearSpygets a scope and its callers propagate.createInvalidThisError→throwInvalidThisError(scope, …): describing the receiver readsconstructor.name. The old function handed the pending exception tocreateError, whose catch scope then adopted the thrown value as the ERR_INVALID_THIS error. It now propagates the getter's exception; all callers (Mock, BunRequest, MIMEType/MIMEParams accessors, node:sqlite) are switched.$ERR_OUT_OF_RANGE: check after building the message, same reason.- Test-runner diff output:
DiffFormatterformatted both values withJestPrettyFormat(runs getters / Proxy traps) insideDisplay::fmtand dropped the result; it now formats in a fallibleDiffFormatter::new(...)?andfmtonly prints. Snapshot matchers propagate the pretty-format error instead of throwing "Failed to pretty format value" over it.
How did you verify your code works?
New test for mockResolvedValue (fails on release). mock-fn, expect, mock-module, node-sqlite suites pass under BUN_JSC_validateExceptionChecks=1 on a debug build. The matcher cases (arrayContaining with a throwing index getter, revoked-Proxy receivers) already surfaced the right error in release; the missing checks there are what the validator flags.