Files
Dylan ConwayandClaude 1917b1aaba Build with Bun 1.4.4, update Node.js to 26.12.1 (#46533)
### What does this PR do?

Three things, in one PR because each of them bakes the CI images again.

**1. Bun 1.4.2 → 1.4.4 for the repository's own tooling.** The CI
machine images (`pins.bun`), the macOS host setup script
(`scripts/darwin-ci/host.sh`), and the four GitHub workflows that pin a
version. Workflows on `canary` or `latest` are unchanged.

**2. Node.js 26.3.0 → 26.12.1, a security release. This one is visible
to users.** `pins.nodejs` is the Node.js on the CI machines, the headers
Bun compiles against, and the version Bun reports:

| | before | after |
|---|---|---|
| `process.version` | `v26.3.0` | `v26.12.1` |
| `process.versions.v8` | `14.6.202.34-node.20` | `14.6.202.34-node.40`
|
| `process.versions.modules` / `.napi` | `147` / `10` | unchanged |

In the new headers `node::ObjectWrap` calls `AddEnvironmentCleanupHook`
and `RemoveEnvironmentCleanupHook`. Bun already exports both on every
platform.

Five test files use the real `node` as a reference or as the server, and
failed once the CI machines had 26.12.1. Each was traced to the release
that changed the behavior, by running the test or reading the headers of
each release. (The commit message of 3c1e4e02 says 26.12 for the first
row. 26.9.0 is right.)

| Node.js | What changed | What this PR does |
|---|---|---|
| 26.9.0, [`51d094e2`](https://github.com/nodejs/node/commit/51d094e2) |
`node_api_create_object_with_properties` takes `const napi_value*` |
Bun's header and definition follow, so the three Node-API headers are
byte-identical to upstream again. The test addon stops declaring the
function itself |
| 26.11.0, [`7702a50e`](https://github.com/nodejs/node/commit/7702a50e)
| The `node:http2` server entry points check `strictSingleValueFields`
before `unknownProtocolTimeout`, a side effect of sharing the checks
with `connect()` | **Bun does too** |
| 26.10.0, [`d141ddb8`](https://github.com/nodejs/node/commit/d141ddb8)
| A `write()` made while OpenSSL is on the stack, as in a handshake
callback, waits for the next turn of the loop. `renegotiate()` does not,
so its request leaves first | The fixture waits for the write. `fetch`
was right to refuse |
| 26.3.1, [`d1be6304`](https://github.com/nodejs/node/commit/d1be6304)
(CVE-2026-48934) | A TLS session is only offered to the host it came
from | The fixture names the host on every path |
| 26.7.0, [`e26891ec`](https://github.com/nodejs/node/commit/e26891ec) |
`res.writableFinished` says whether `'finish'` was emitted | **Bun is
unchanged.** The test says where the two differ |

Following `writableFinished` was tried and dropped. It belongs to a
larger rewrite of `OutgoingMessage.end()`: with only the flag, the
vendored `test-http-outgoing-end-multiple.js` fails, as it does on
Node.js 26.7.0 and later. The same upstream commit changed that test,
`test-http-outgoing-writableFinished.js` and `test-stream-pipeline.js`.

**3. A failed Visual Studio install prints the end of its logs.** The
first build of this PR failed a Windows arm64 bake with `the Visual
Studio installer exited with code 5002`, which Microsoft does not
document. The reason was in the installer's logs, and the machine is
deleted when a bake fails.

A bake's output is public, so what is printed is limited:
- only `dd_<program>_<time>.log` and its `_errors.log`, never the log of
each package (an MSI's ends with every property of the machine and the
user)
- the last 100 lines of each
- no lines about telemetry, which have ids of the machine and the user
- no URL queries

The script puts no token or password on the machine before that step,
and the Azure credentials stay on the Buildkite agent.

Worth knowing before merging:
- **macOS test machines keep Bun 1.4.2 and Node.js 26.3.0** until
`scripts/darwin-ci` `bake` is re-run on each host. Nothing fails
meanwhile: the exact-version check runs at build configure, macOS builds
are cross-compiled on Linux, and the Node-API harness falls back to
node-gyp when the headers are not cached. The two reference runs whose
expected output changed are skipped below the release that changed it.
- **The release jobs** (sign, npm, S3) first run on Bun 1.4.4 at the
next scheduled canary release.

### How did you verify your code works?

- **Pins:** downloaded all 8 Bun zips and all 9 Node.js files from the
URLs in the generated scripts. Each matches its pinned sum.
- **Node.js:** a debug build on linux-x64 compiles against the new
headers and reports the values above. A real Node.js 26.12.1 reports the
same V8, ABI and Node-API versions.
- **Logging:** ran the generated lines in PowerShell 7.4 with a stand-in
installer, 5 logs that may be shown and 8 that may not. Nothing filtered
came through, and the script still ends with the installer's exit code,
also when a log cannot be read. Both `bootstrap.ps1` parse with no
errors. The new test fails for each of 5 ways of loosening the filters.
- `bun test test/internal/source-lints/` (183 pass), `tsc -p
scripts/build/tsconfig.json`, prettier.

- **The five test files:** ran each against Node.js 26.3.0 and 26.12.1,
and against the releases on both sides of each change. The original
addon source reproduces CI's error against the 26.12.1 headers, and the
new one compiles against both sets.
- Ran all 463 vendored `test-http*` and `test-https*` files while the
`writableFinished` change was in, which is how its regression was found.

Not verified: `test/napi` was only syntax-checked locally, not built and
run. The logging has not seen a real Visual Studio log, and a bake runs
it under Windows PowerShell 5.1, not 7.4. Nothing was run on macOS or
Windows.


---
_Generated by [Claude Code](https://claude.ai/code)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-22 17:45:02 -07:00
..
2025-07-10 00:10:43 -07:00