Skip to content

bun-types: SharedArrayBuffer.prototype.grow returns void - #36505

Closed
robobun wants to merge 1 commit into
mainfrom
farm/8ed91e50/bun-types-batch-fixes
Closed

robobun wants to merge 1 commit into
mainfrom
farm/8ed91e50/bun-types-batch-fixes

Conversation

@robobun

@robobun robobun commented Jul 31, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • packages/bun-types/globals.d.ts declares SharedArrayBuffer.prototype.grow() as returning the SharedArrayBuffer (globals.d.ts:1083). Per the spec it returns undefined (sec-sharedarraybuffer.prototype.grow, last step), and bun -e 'const b = new SharedArrayBuffer(1, { maxByteLength: 8 }); console.log(b.grow(4))' prints undefined.
  • bun-types merges its own interface SharedArrayBuffer into the lib one, and the merged-in signature is the one a grow(n) call resolves to, so code that chains off the result (sab.grow(n).byteLength) type-checks and then throws at runtime.

Fix

  • grow(size: number): SharedArrayBuffer becomes grow(size: number): void, matching the spec, the runtime, and TypeScript's own lib.es2024.sharedmemory.d.ts.
  • This is the same correction fix(types): ArrayBuffer.prototype.resize returns void #32484 makes for ArrayBuffer.prototype.resize(); that PR stays as is, and the two merge independently in either order (checked locally).
  • Verified with bun test test/integration/bun-types/bun-types.test.ts (types-only change, so it runs with the released bun): with only the fixture line, every lib configuration fails with array-buffer.ts(14,31): error TS2344: Type 'void' does not satisfy the constraint 'SharedArrayBuffer'.; with the declaration change, 14 pass.

Background

  • bun-types declares some globals that also exist in TypeScript's lib files. TypeScript merges same-named interfaces, and when both declare a method the signatures become overloads, with the later-merged declaration (bun-types) tried first. A wrong return type in bun-types therefore wins over the correct one in lib, which is why this shows up even with lib.dom/es2024 enabled.
History: this PR used to be a batch of seven type fixes

The earlier revision of this PR bundled YAML.stringify, ArrayBuffer.resize, the FormData iterator types, jest.now(), jest.setSystemTime() chaining, toHaveBeenCalledOnce() and the return-matcher aliases. Each of those already has a focused PR from its original author, and all seven still merge cleanly on current main with the types test passing, so this PR was cut down to the one line that none of them covers. The focused PRs are the ones to merge:

Fix PR
Bun.YAML.stringify() returns string | undefined #34162
ArrayBuffer.prototype.resize() returns void #32484
FormData values() / entries() / [Symbol.iterator]() yield FormDataEntryValue (#27194) #34264
toHaveBeenCalledOnce() declaration (#32332) #32333
toReturn() / lastReturnedWith() / nthReturnedWith() declarations (#32334) #32335
jest.now() declaration #32455
jest.setSystemTime() returns typeof jest #33923

Note for whoever merges the four bun:test ones (#32333, #32335, #32455, #33923): they all append to test/integration/bun-types/fixture/mocks.ts, so after the first one lands the other three need a trivial rebase (keep both sides). #32455 and #33923 additionally touch adjacent lines of the jest namespace in test.d.ts. The combined result of all seven plus this PR was checked locally and passes the types test.

@robobun
robobun requested a review from alii as a code owner July 31, 2026 04:17
@coderabbitai

coderabbitai Bot commented Jul 31, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: de63997a-0875-4ae5-81ec-58f3baabb3eb

📥 Commits

Reviewing files that changed from the base of the PR and between 74c2457 and f50af7b.

📒 Files selected for processing (2)
  • packages/bun-types/globals.d.ts
  • test/integration/bun-types/fixture/array-buffer.ts

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Found 4 issues this PR may fix:

  1. Incorrect Iterable FormData types in bun-types #27194 - PR fixes FormData iterator types (values(), entries(), [Symbol.iterator]()) to use FormDataEntryValue instead of string
  2. bun:test: expect(fn).toHaveBeenCalledOnce() works at runtime but is missing from types #32332 - PR adds missing toHaveBeenCalledOnce() type declaration to jest matchers
  3. bun:test: return-matcher aliases (toReturn, lastReturnedWith, nthReturnedWith) missing from types #32334 - PR adds missing toReturn(), lastReturnedWith(), nthReturnedWith() type declarations
  4. types: Conflicts with core-js-types #26868 - PR fixes ArrayBuffer.resize() return type from ArrayBuffer to void, resolving core-js-types conflict

If this is helpful, copy the block below into the PR description to auto-close these issues on merge.

Fixes #27194
Fixes #32332
Fixes #32334
Fixes #26868

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

This PR may be a duplicate of:

  1. types: fix YAML.stringify return type #34162 - Fixes the same YAML.stringify return type that this PR consolidates
  2. fix(types): ArrayBuffer.prototype.resize returns void #32484 - Fixes the same ArrayBuffer.prototype.resize return type that this PR consolidates
  3. fix(types): correct FormData values()/entries() iterator types #34264 - Fixes the same FormData values()/entries() iterator types that this PR consolidates
  4. fix(types): correct FormData iterator return types to include File #27195 - Fixes the same FormData iterator return types that this PR consolidates
  5. fix(types): add jest.now() to jest namespace in bun:test #32455 - Adds the same jest.now() type that this PR consolidates
  6. fix(types): return jest from setSystemTime #33923 - Fixes the same setSystemTime return type that this PR consolidates
  7. fix(types): add toHaveBeenCalledOnce matcher to bun:test types #32333 - Adds the same toHaveBeenCalledOnce matcher type that this PR consolidates
  8. fix(types): add jest return-matcher aliases to bun:test types #32335 - Adds the same jest return-matcher alias types that this PR consolidates

🤖 Generated with Claude Code

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM — type-declaration-only fixes, each verified against runtime.

What was reviewed:

  • Confirmed jest.now is wired at jest.rs:435 and JSMock__jsSetSystemTime returns callframe->thisValue(); toHaveBeenCalledOnce/toReturn/lastReturnedWith/nthReturnedWith exist in jest.classes.ts.
  • resize()/grow() → void matches the ES spec and TS's own lib.es2024; FormDataEntryValue iterators now match get()/forEach() and lib.dom.
  • Line-offset bump in bun-types.test.ts (307→311) matches the 4 lines added to the globals.ts fixture.
Extended reasoning...

Overview

This PR touches only packages/bun-types/{bun,globals,test}.d.ts plus four fixture files under test/integration/bun-types/fixture/ and a single expected-diagnostic line offset in bun-types.test.ts. No runtime code is modified. Each change corrects a type declaration to match already-shipped runtime behavior: YAML.stringify returning undefined for undefined/symbol/function (mirroring JSON.stringify), ArrayBuffer.resize/SharedArrayBuffer.grow returning void per ES spec, FormData iterators yielding FormDataEntryValue, and the addition of jest.now(), chainable jest.setSystemTime(), and four jest-extended matcher aliases.

Security risks

None. Pure .d.ts edits — no compiled code, no auth/crypto/permission surfaces, no data handling.

Level of scrutiny

Low. Per CLAUDE.md, .d.ts edits don't require a native build, and the bun-types.test.ts integration suite type-checks the fixtures against the packed tarball with skipLibCheck: false. I spot-checked every runtime claim in the PR table against source: JSMock__jsNow returns jsNumber(globalObject->jsDateNow()) and is registered on the jest object at jest.rs:435; JSMock__jsSetSystemTime returns callframe->thisValue(); the four matcher names appear in jest.classes.ts:308,342,358,366; Bun.FormDataEntryValue is File | string so the satisfies clauses in the fixture are exact.

Other factors

Each fix has a corresponding fixture assertion (expectType(...).is<...>() or satisfies) that would fail without the .d.ts change, satisfying the repo rule that tests must fail on the unfixed build. The 307→311 offset bump in the lib.dom diagnostic list correctly accounts for the 4-line for...of block added to the FormData fixture. No CODEOWNERS on packages/bun-types/, no outstanding reviewer comments, and no prior review from me on this PR.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Additional findings (outside current diff — PR may have been updated during review):

  • 🔴 packages/bun-types/package.json:35-37 — This change to packages/bun-types/package.json (adding "version": "1.4.0" and stripping the trailing newline) is an accidentally-committed test artifact — it's byte-for-byte what an interrupted run of bun-types.test.ts / scripts/build.ts leaves behind, and is unrelated to the .d.ts fixes in this PR. Please revert this file to its pre-PR state (no version field, trailing newline restored).

    Extended reasoning...

    What the bug is

    The PR modifies packages/bun-types/package.json to add a hardcoded "version": "1.4.0" field at the end of the object and strips the file's trailing newline. Prior to this PR (at base commit 468dac3c), this file had no version field and did end with a trailing newline — verified via git show 468dac3c:packages/bun-types/package.json.

    How it manifests / the code path that produces it

    This diff is not an intentional edit — it is byte-for-byte the residue of the bun-types build/test flow:

    1. packages/bun-types/scripts/build.ts:7 does:
      await Bun.write(join(import.meta.dir, "../package.json"), JSON.stringify({ ...pkg, version: BUN_VERSION }, null, 2));
      The spread places version last in the object, and JSON.stringify emits no trailing newline — exactly matching this diff.
    2. test/integration/bun-types/bun-types.test.ts (in beforeAll) runs cp package.json package.json.backup, then writes the same JSON.stringify({ ...pkg, version: BUN_VERSION }, null, 2), then runs bun run build / bun pm pack, then restores via mv package.json.backup package.json.
    3. If either the test or a manual bun run build in packages/bun-types is interrupted between the write and the restore, the working tree is left with precisely this diff.

    Why existing code doesn't prevent it

    The backup/restore in bun-types.test.ts exists specifically so this artifact is never committed — but it only works if the process reaches the mv package.json.backup package.json step. An interrupted local run (Ctrl-C, crash, timeout) leaves the modified package.json in place, and it was then staged alongside the real .d.ts changes.

    Step-by-step proof

    • Base state (468dac3c): od -c on the file ends with ... ] \n } \n and json.load(...) reports 'version' in d → False.
    • PR state: the diff shows + "version": "1.4.0" appended after keywords, and \ No newline at end of file.
    • Fingerprint match: JSON.stringify({...pkg, version: "1.4.0"}, null, 2) on the base file produces the PR's exact bytes — spread order puts injected keys last, and JSON.stringify never appends a trailing newline.
    • PR intent: the PR description and title mention only .d.ts fixes (YAML.stringify, ArrayBuffer.resize, FormData iterators, jest matchers). package.json is never mentioned. There is no reason a types-only PR would hardcode a package version.

    Impact

    Functionally, publishing is unaffected — scripts/build.ts overwrites version at pack time via { ...pkg, version: BUN_VERSION }. But committing this residue:

    • Checks a stale, meaningless 1.4.0 into the source of a published package's manifest.
    • Defeats the purpose of the test's backup/restore dance (which exists precisely to keep this file version-free in git).
    • Introduces unrelated churn in a PR that is otherwise pure .d.ts edits; per the repo's own review rules on scope, unrelated accidental changes get reverted before merge.

    Fix

    Revert packages/bun-types/package.json to its pre-PR state:

    git checkout 468dac3c -- packages/bun-types/package.json

    (i.e., drop the "version" field and restore the trailing newline.)

@robobun

robobun commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Already reverted in f676896; the current diff no longer touches packages/bun-types/package.json. (It was the residue of an interrupted bun-types.test.ts beforeAll, exactly as described.)

@robobun

robobun commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

CI: the bun-types.test.ts suite this PR changes is green across all lanes. The remaining reds are unrelated to .d.ts edits:

  • worker-transfer-terminate-stress.test.ts (SIGABRT, JSC !exception() assertion on debian x64-asan): runtime assertion in worker termination; this PR touches no compiled code. Reported for main-break triage.
  • Everything else is tagged [flaky] by the build annotator and passed on retry or in isolation (DNS IP mismatch on google.com, napi finalizer timing, webview/spawn/fetch lane flakes).

Ready for review.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM — pure .d.ts corrections aligning types with runtime behavior, each covered by a fixture assertion.

What was reviewed:

  • Verified each runtime claim: JSMock__jsSetSystemTime returns callframe->thisValue(), JSMock__jsNow returns jsNumber, and toHaveBeenCalledOnce/toReturn/lastReturnedWith/nthReturnedWith all exist in jest.classes.ts.
  • Checked FormData iterator changes for lib.dom merge conflicts — FormDataIterator<T> (via IteratorObject) is structurally assignable to IterableIterator<T>, so the new satisfies fixtures hold under both configs.
  • Confirmed the globals.ts:307→311 diagnostic offset matches the net +4 fixture lines, and packages/bun-types/package.json is no longer touched.
Extended reasoning...

Overview

This PR batches seven small .d.ts corrections in packages/bun-types/{bun,globals,test}.d.ts: YAML.stringify → string | undefined, ArrayBuffer#resize/SharedArrayBuffer#grow → void, FormData iterators yield FormDataEntryValue, jest.now() added, jest.setSystemTime() → typeof jest, and four missing jest matcher declarations. Each change is exercised by a fixture in test/integration/bun-types/fixture/, and one hard-coded diagnostic line number in bun-types.test.ts is bumped to account for the +4 lines added to globals.ts.

Security risks

None. Type declarations only; no compiled code, no runtime logic, no I/O, no auth/crypto surface.

Level of scrutiny

Low. These are documentation-grade edits to ambient declarations. The correctness bar is "matches runtime", and I spot-checked every claim against source: JSMockFunction.cpp:1437,1460 confirm jest.now() and setSystemTime() return values; jest.classes.ts:308,342,358,366 confirm the four matcher aliases exist; resize/grow returning void is per ES spec and matches lib.es2024; Bun.FormDataEntryValue = File | string already backs get()/forEach() so extending it to the iterators is consistent with lib.dom.

Other factors

  • The lib.dom interface-merge case was the only non-obvious risk: adding [Symbol.iterator]() and changing iterator return types could conflict with lib.dom.iterable's FormDataIterator<T>. Since FormDataIterator extends IteratorObject (a superset of IterableIterator), the fixture's satisfies IterableIterator<string | File> holds regardless of which merged overload resolves, and no new diagnostic appears in the lib.dom test case.
  • Fixture chain jest.setSystemTime(...).useRealTimers() type-checks because typeof jest includes useRealTimers.
  • The accidental package.json version bump was already reverted in f676896; the current diff is clean.
  • No prior human review comments to address.

grow() resizes the buffer in place and returns undefined
(https://tc39.es/ecma262/#sec-sharedarraybuffer.prototype.grow), but
bun-types declared it as returning the SharedArrayBuffer. Because
bun-types merges its own SharedArrayBuffer interface into the lib
declaration, its signature is the one a grow(n) call resolves to, so
chaining off the result type-checked even though it is undefined at
runtime.

Companion to the same correction for ArrayBuffer.prototype.resize in
#32484; the two merge independently.
@robobun
robobun force-pushed the farm/8ed91e50/bun-types-batch-fixes branch from f676896 to f50af7b Compare August 13, 2026 00:25
@robobun

robobun commented Aug 13, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 10:59 PM PT - Aug 12th, 2026

❌ Your commit f50af7bc has 1 failures in Build #93745 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 36505

That installs a local version of the PR into your bun-36505 executable, so you can run:

bun-36505 --bun

@robobun

robobun commented Aug 13, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: this PR has been cut down from the seven-fix batch to the single SharedArrayBuffer.prototype.grow() line (f50af7b), as part of deduplicating the open bun-types PRs.

Comment thread packages/bun-types/globals.d.ts
alii pushed a commit that referenced this pull request Aug 13, 2026
…ckages/bun-types; raise the file's timeout (#37990)

### Problem
- `bun test test/integration/bun-types/bun-types.test.ts` (the
invocation CLAUDE.md documents, and the one
`.github/workflows/bun-types.yml` uses) runs the file under bun's 5s
default timeout. On a slow or busy machine `beforeAll` is cut off with
`a beforeEach/afterEach hook timed out for this test.` and nothing runs.
Buildkite never sees this because `scripts/runner.node.mjs` passes
`--timeout=150000` for integration files.
- The hook does not fit in 5s: `bun install --no-cache` inside
`packages/bun-types` is a full workspace install that re-fetches
manifests (0.7s to 6.2s in this container depending on the registry),
then `bun run build`, `bun pm pack` and a `bun add` from the registry.
The type-checking cases are in the same situation: a plain run here had
the tsgo case at 5.1s and several LanguageService cases at 5 to 7s
(those only pass today because the check is synchronous, so the timer
cannot fire before the test resolves).
- `beforeAll` built the package in place (`bun-types.test.ts:41-61` on
main): it rewrote the tracked `packages/bun-types/package.json`, and
`bun run build` writes `CLAUDE.md` and `docs/` next to it. The restore
was the `mv package.json.backup package.json` at the end of a shell
chain, so a timed out hook (bun abandons the hook's promise and moves on
to `afterAll`) or a failing `bun pm pack` left the checkout with a
modified `package.json` plus `package.json.backup`. That residue has
already been committed by accident once (#36505, caught in review and
reverted there).

### Fix
- `packages/bun-types/scripts/build.ts` takes an optional output
directory for the files it generates (`package.json` with the version
filled in, `CLAUDE.md`, `docs/`). With no argument it still writes into
the package itself, which is what `release.yml` runs and publishes, so
the release flow is unchanged.
- The test copies `packages/bun-types` (minus `node_modules`) into its
temp dir, runs `bun run build <copy>` and `bun pm pack` inside the copy,
and installs the tarball from there. Nothing under `packages/` is
written anymore, so there is no restore step that an interrupted hook
can skip. `bun pm pack` only needs a lockfile for
`workspace:`/`catalog:` specifiers and `build.ts` imports nothing, so
the `bun install --no-cache` step is dropped rather than moved.
- The setup commands are now separate `&&` chains: a newline-separated
Bun Shell script keeps going after a failing command and only throws if
the last one fails, so a `build`/`pack` failure used to surface as a
cascade of four errors instead of the first one.
- The file calls `setDefaultTimeout(2 minutes)` before registering
anything (the runner captures the default when each hook/test is
declared). Every entry in the file installs from the registry or
type-checks for several seconds, so a per-test override would just
repeat the value 15 times. 2 minutes is 15 to 25x the slowest entry
measured here (the whole hook is 1 to 5s on a release build, about 4s
under the debug build) and stays under the 150s the CI runner gives
integration files, so a hang in CI is still attributed to a specific
test rather than to the file.
- A new case, `building and packing bun-types leaves packages/bun-types
untouched`, compares `package.json`'s text and the presence of
`CLAUDE.md`/`docs/` in the checkout before the module's setup and after
it. With the old `build.ts` it fails in setup (`bun pm pack` on the
versionless copy reports `package.json must have name and version
fields`) and the run leaves `package.json` modified plus `CLAUDE.md` and
`docs/` behind, which is the bug; with the new one the tree stays clean.
- Verified: `bun test test/integration/bun-types/bun-types.test.ts`
(release, no `--timeout`): 15 pass, `git status` clean afterwards. `bun
bd test test/integration/bun-types/bun-types.test.ts`: 3 pass, 12 skip
(the LanguageService cases are `skipIf(isDebug)` already), tree clean.
`bun run build` with no argument in `packages/bun-types` still builds in
place. The tarball packed from the copy has the same 367 files as one
packed in place (`files` in package.json selects them either way).

### Background
- `beforeAll` / test timeouts in `bun:test`: each hook and test gets a
deadline when it starts, resolved at declaration time as explicit
argument, then `setDefaultTimeout()`, then `--timeout` (default 5000ms).
A `setDefaultTimeout()` call therefore has to come before the
declarations it should apply to, and it overrides the CLI value. When a
`beforeAll` times out its promise is abandoned (nothing is cancelled),
the tests in its scope are skipped and `afterAll` still runs.
- `packages/bun-types/scripts/build.ts` is the `bun run build` script
the release workflow runs before `npm publish` from inside
`packages/bun-types`: it stamps the Bun version into `package.json`,
copies `src/cli/init/rule.md` to `CLAUDE.md` and copies
`docs/**/*.md(x)` in. `package.json` is tracked; `CLAUDE.md` and `docs/`
are gitignored in that directory.
- This integration test packs the package with `bun pm pack`, installs
the tarball into a fixture project together with a stub `@types/bun`,
and type-checks the fixture with TypeScript's compiler API, so it needs
the real build output (it is how the missing `CLAUDE.md` in #33940 was
caught), just not inside the checkout.
@robobun

robobun commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #39608, which aligns the whole block of ECMAScript declarations in globals.d.ts with the TypeScript lib files (#26868), grow() included.

@robobun robobun closed this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant