Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
b9c81b2
Report Node.js 26.3.0 (V8 14.6.202.34, ABI 147)
Jarred-Sumner Jun 4, 2026
a914c27
webstreams: settle pending BYOB reads when the reader is cancelled
Jarred-Sumner Jun 4, 2026
f950dce
node:stream, node:http: sync behavioral changes from Node 24.x to 26.x
Jarred-Sumner Jun 4, 2026
22df8d4
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 4, 2026
4decf80
Bump bootstrap image versions for Node.js 26.3.0 [build images]
Jarred-Sumner Jun 4, 2026
73d4931
Node 26: restore native upgrade pieces (V8 14.6 shim, ABI 147) [build…
Jarred-Sumner Jun 4, 2026
1474e49
http, streams: review fixes for the Node 26 sync [build images]
Jarred-Sumner Jun 4, 2026
40bf490
bootstrap: keep the xwin cache on the same filesystem as the splat ou…
Jarred-Sumner Jun 4, 2026
2bffbf7
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 4, 2026
1646e94
Rebuild CI images for the Node 26.3.0 toolchain [build images]
Jarred-Sumner Jun 4, 2026
4e86a1c
bootstrap: install musl Node.js from unofficial-builds.nodejs.org [bu…
Jarred-Sumner Jun 4, 2026
af1bac6
Fix node-gyp on Windows and stale cipher stream tests for Node 26 [bu…
Jarred-Sumner Jun 5, 2026
f8aec41
streams: let destroyed-flagged readables still flush to piped destina…
Jarred-Sumner Jun 5, 2026
e194e98
next-pages tests: skip puppeteer browser download when it can't be us…
Jarred-Sumner Jun 5, 2026
3771d7a
Address review feedback: escape-slot lifetime, set-cookie consistency…
Jarred-Sumner Jun 5, 2026
71e4ae0
http2: destroy streams on socket close; never RST a never-started req…
Jarred-Sumner Jun 6, 2026
f8c00f1
v8: restore HandleScopeData when a Bun handle scope pops [build images]
Jarred-Sumner Jun 6, 2026
694c0ff
http2: validate options.signal before the pre-aborted fast path
Jarred-Sumner Jun 6, 2026
2b5e85b
packer: switch the windows-x64 bake VM to Standard_D4as_v7
Jarred-Sumner Jun 6, 2026
e256d3d
bootstrap: bump image versions past stale v35 tags [build images]
Jarred-Sumner Jun 6, 2026
abd2649
http2: send GOAWAY on graceful close(); run test node-gyp builds unde…
Jarred-Sumner Jun 6, 2026
5f5c532
v8 tests: run the node-side fixture build under bun too [build images]
Jarred-Sumner Jun 6, 2026
537a29c
process.config: report clang=1 on macOS; surface exit codes in v8 har…
Jarred-Sumner Jun 6, 2026
326cf3b
complex-workspace test: skip lifecycle scripts on Windows [build images]
Jarred-Sumner Jun 6, 2026
5738163
bootstrap: install Chrome on x64 apt images; recognize google-chrome …
Jarred-Sumner Jun 6, 2026
b3f5e61
symbols.def: export Value::IsArray/IsBigInt/IsInt32/IsMap [build images]
Jarred-Sumner Jun 6, 2026
a6bc225
v8 fixture: add stderr step markers to the tests that die on Windows …
Jarred-Sumner Jun 7, 2026
0a144f1
v8: export the V8_INLINE members MSVC debug builds import [build images]
Jarred-Sumner Jun 7, 2026
ae74b31
http2: lastStreamId <= 0 in goaway means the actual last stream [buil…
Jarred-Sumner Jun 7, 2026
83a4ad0
Merge main into Node 26 upgrade branch
cirospaciari Jun 8, 2026
c512404
tests: tolerate machines whose Node or toolchain lags the reported AB…
cirospaciari Jun 8, 2026
3693c99
ci: rebuild bootstrap images for the Node 26 toolchain [build images]
cirospaciari Jun 8, 2026
a3b9f18
test harness: download the ABI-matching node with curl, cache in ~/.c…
cirospaciari Jun 8, 2026
c4fe0c9
DEBUG: instrument http2 serverrequest-pipe timeout on darwin-aarch64
cirospaciari Jun 8, 2026
ee0abaf
DEBUG: drop binary-size step on trimmed pipeline
cirospaciari Jun 8, 2026
0822855
DEBUG: bake host image for trimmed pipeline [build images]
cirospaciari Jun 8, 2026
55adb92
DEBUG: include linux-aarch64 platforms so host images get baked [buil…
cirospaciari Jun 8, 2026
7c3f545
DEBUG: loop the instrumented pipe scenario with 3-way concurrency
cirospaciari Jun 9, 2026
1bfde82
DEBUG: rerun with images [build images]
cirospaciari Jun 9, 2026
b3fda1e
DEBUG: run full http2 family; instrument the real pipe test in place …
cirospaciari Jun 9, 2026
f9c4521
DEBUG: instrument server socket/session lifecycle [build images]
cirospaciari Jun 9, 2026
886a1b6
http2: destroy the server session when its socket closes [build images]
cirospaciari Jun 9, 2026
a33c1fc
DEBUG: revert maybeReadMore kReading guard [build images]
cirospaciari Jun 9, 2026
59a4a87
DEBUG: capture client socket state; add plain-net EOF probe [build im…
cirospaciari Jun 9, 2026
d3f2ae4
DEBUG: stderr prints in socket teardown paths [build images]
cirospaciari Jun 9, 2026
52d77a1
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 9, 2026
971e41c
DEBUG: rerun after autofix [build images]
cirospaciari Jun 9, 2026
87ae012
DEBUG: null-safe teardown prints [build images]
cirospaciari Jun 9, 2026
3f89df4
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 9, 2026
c6efd6f
DEBUG: rerun after autofix [build images]
cirospaciari Jun 9, 2026
68f2d55
DEBUG: pause/resume + native on_data prints [build images]
cirospaciari Jun 9, 2026
63a86ef
DEBUG: per-poll and per-recv prints in loop.c [build images]
cirospaciari Jun 9, 2026
d2767d3
DEBUG: bake host image for trimmed pipeline [build images]
cirospaciari Jun 8, 2026
aac6c95
DEBUG: rerun with images [build images]
cirospaciari Jun 9, 2026
c4be3b1
DEBUG: rerun after autofix [build images]
cirospaciari Jun 9, 2026
469c227
DEBUG: rerun after autofix [build images]
cirospaciari Jun 9, 2026
ee8547c
DEBUG: stream end-of-life prints [build images]
cirospaciari Jun 9, 2026
d653ca4
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 9, 2026
eaa7f1e
DEBUG: rerun after autofix [build images]
cirospaciari Jun 9, 2026
bc0c717
DEBUG: strip prints; fix headers-only END_STREAM stream leak [build i…
cirospaciari Jun 10, 2026
71b8b76
DEBUG: drop leftover include [build images]
cirospaciari Jun 10, 2026
fb91e22
DEBUG: strip JS prints [build images]
cirospaciari Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions .buildkite/ci.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1380,8 +1380,19 @@ async function getPipelineOptions() {
dryRun: parseOption(/\[(dry run)\]/i),
publishImages: parseOption(/\[(publish (?:(?:windows|linux) )?images?)\]/i),
imageFilter: (commitMessage.match(/\[(?:build|publish) (windows|linux) images?\]/i) || [])[1]?.toLowerCase(),
buildPlatforms: Array.from(buildPlatformsMap.values()),
testPlatforms: Array.from(testPlatformsMap.values()),
// DEBUG BRANCH ONLY: darwin-aarch64 pipeline running a single test file.
// The two linux-aarch64 entries are kept because the darwin cross-build
// runs on their host images (amazonlinux-with-docker for cpp/link,
// alpine-musl for rust), and image steps are only generated from
// non-crossCompile linux platforms.
buildPlatforms: Array.from(buildPlatformsMap.values()).filter(
p =>
p.arch === "aarch64" &&
p.abi !== "android" &&
(p.os === "darwin" || (p.os === "linux" && (p.distro === "amazonlinux" || p.abi === "musl"))),
),
testPlatforms: Array.from(testPlatformsMap.values()).filter(p => p.os === "darwin" && p.arch === "aarch64"),
testFiles: ["js/node/test/parallel/test-http2-"],
};
}

Expand Down Expand Up @@ -1508,11 +1519,8 @@ async function getPipeline(options = {}) {
}
}

// Binary-size tracking covers the artifacts that ship.
const strippedPlatforms = buildPlatforms.filter(p => (p.profile ?? "release") === "release");
if (!buildId && strippedPlatforms.length) {
steps.push(getBinarySizeStep(strippedPlatforms, options, { recordOnly: isMainBranch() }));
}
// DEBUG BRANCH ONLY: binary-size depends on every build target; the trimmed
// platform list breaks its dependencies and cancels the whole build.

// Sign Windows builds on release (non-canary main) or when [sign windows]
// is in the commit message (for testing the sign step on a branch).
Expand Down
4 changes: 2 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
clang = pkgs.clang_21;
lld = pkgs.lld_21;

# Node.js 24 - matching the bootstrap script (targets 24.3.0, actual version from nixpkgs-unstable)
nodejs = pkgs.nodejs_24;
# Node.js 26 - matching the bootstrap script (targets 26.3.0, actual version from nixpkgs-unstable)
nodejs = pkgs.nodejs_26;
Comment on lines +34 to +35

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the nearby Node version comment to match the new pin.

After switching to pkgs.nodejs_26, the package-list comment still says “version pinned to 24”, which is now misleading.

Suggested patch
-          # Node.js - version pinned to 24
+          # Node.js - version pinned to 26
           nodejs
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@flake.nix` around lines 34 - 35, Update the misleading comment near the
nodejs assignment: change the text that says the Node version is "pinned to 24"
to reflect the new pin (nodejs_26) and, if relevant, mention the targeted actual
version (e.g., 26.x / 26.3.0) so the comment aligns with the nodejs =
pkgs.nodejs_26 setting and the bootstrap script target.


# Build tools and dependencies
packages = [
Expand Down
8 changes: 4 additions & 4 deletions scripts/bootstrap.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Version: 20
# Version: 21
# A script that installs the dependencies needed to build and test Bun on Windows.
# Supports both x64 and ARM64 using Scoop for package management.
# Used by Azure [build images] pipeline.
Expand Down Expand Up @@ -215,9 +215,9 @@ function Install-Git {
}

function Install-NodeJs {
# Pin to match the ABI version Bun expects (NODE_MODULE_VERSION 137).
# Latest Node (25.x) uses ABI 141 which breaks node-gyp tests.
$nodejsVersion = "24.3.0"
# Pin to match the ABI version Bun expects (NODE_MODULE_VERSION 147).
# A mismatched Node ABI breaks node-gyp tests.
$nodejsVersion = "26.3.0"
Install-Scoop-Package "nodejs@$nodejsVersion" -Command node

# Seed node-gyp's cache so napi tests don't re-download headers + node.lib
Expand Down
29 changes: 24 additions & 5 deletions scripts/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh
# Version: 34
# Version: 36

# A script that installs the dependencies needed to build and test Bun.
# This should work on macOS and Linux with a POSIX shell.
Expand Down Expand Up @@ -780,7 +780,7 @@ install_common_software() {
}

nodejs_version_exact() {
print "24.3.0"
print "26.3.0"
}

nodejs_version() {
Expand Down Expand Up @@ -819,7 +819,11 @@ install_nodejs() {

case "$abi" in
musl)
nodejs_mirror="https://bun-nodejs-release.s3.us-west-1.amazonaws.com"
# nodejs.org doesn't publish musl binaries; the unofficial-builds
# project (nodejs/unofficial-builds) ships both x64-musl and
# arm64-musl for current releases. (The old private S3 mirror at
# bun-nodejs-release predates arm64-musl being available there.)
nodejs_mirror="https://unofficial-builds.nodejs.org/download/release"
nodejs_foldername="node-v$nodejs_version-$nodejs_platform-$nodejs_arch-musl"
;;
*)
Expand Down Expand Up @@ -1450,21 +1454,27 @@ install_windows_sysroot() {

execute_sudo rm -rf "$sysroot"
execute_sudo mkdir -p "$sysroot"
# The cache must live on the same filesystem as the output: splat moves
# unpacked files with rename(2), which fails with EXDEV (cross-device
# link) when the download dir is on tmpfs and /opt is not.
xwin_cache="$sysroot.cache"
execute_sudo rm -rf "$xwin_cache"
execute_sudo mkdir -p "$xwin_cache"
# Both target arches in one splat; --include-debug-libs so /MTd (debug
# CRT) links work; --include-atl for <atlstr.h> (rescle.cpp);
# winsysroot-style + MS arch notation so clang-cl and lld-link resolve it
# with a single /winsysroot flag; symlinks stay ON (default) to fix
# include/lib casing on a case-sensitive filesystem.
# stdout is dropped: xwin draws progress bars there even without a TTY,
# which floods the image-build log. Errors stay on stderr.
execute_sudo "$xwin_dir/xwin" --accept-license --arch x86_64,aarch64 --sdk-version 10.0.26100 --crt-version 14.44.17.14 --include-atl --cache-dir "$xwin_dir/cache" \
execute_sudo "$xwin_dir/xwin" --accept-license --arch x86_64,aarch64 --sdk-version 10.0.26100 --crt-version 14.44.17.14 --include-atl --cache-dir "$xwin_cache" \
splat --use-winsysroot-style --preserve-ms-arch-notation --include-debug-libs \
--output "$sysroot" >/dev/null
# clang-cl/lld-link compose SDK paths as "Include"/"Lib" (title case);
# the winsysroot-style splat writes lowercase — alias both spellings.
execute_sudo ln -s include "$sysroot/Windows Kits/10/Include"
execute_sudo ln -s lib "$sysroot/Windows Kits/10/Lib"
execute_sudo rm -rf "$xwin_dir"
execute_sudo rm -rf "$xwin_dir" "$xwin_cache"
# No WINDOWS_SYSROOT export — detectWindowsSysroot() picks up
# /opt/winsysroot by well-known path.
}
Expand Down Expand Up @@ -1768,6 +1778,15 @@ install_chromium() {
else
install_packages libasound2
fi

# Install Chrome itself on x64 (no arm64 build exists): with a system
# browser present, puppeteer-based tests skip their per-run ~300MB
# Chrome for Testing download entirely (see
# test/harness.ts getPuppeteerInstallEnv).
if [ "$arch" = "x64" ]; then
chrome_deb=$(download_file "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb")
execute_sudo apt-get install -y "$chrome_deb" || execute_sudo dpkg -i "$chrome_deb" || true
fi
;;
dnf | yum)
install_packages \
Expand Down
6 changes: 5 additions & 1 deletion scripts/build/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,10 @@ function emitJsModules({ n, cfg, sources, o, dirStamp }: Ctx): void {

// InternalModuleRegistry.cpp is read by the script (for a sanity check).
const extraInput = resolve(cfg.cwd, "src", "jsc", "bindings", "InternalModuleRegistry.cpp");
// replacements.ts bakes ErrorCode.ts indices into every bundled module
// ($makeErrorWithCode(N, ...)); without this dep an ErrorCode.ts edit leaves
// stale error numbers in the JS bundles while the C++ enum regenerates.
const errorCodeInput = resolve(cfg.cwd, "src", "jsc", "bindings", "ErrorCode.ts");

// Written into src/ (not codegenDir) — see zigFilesGeneratedIntoSrc at top.
const js2nativeZig = resolve(cfg.cwd, zigFilesGeneratedIntoSrc[1]);
Expand Down Expand Up @@ -791,7 +795,7 @@ function emitJsModules({ n, cfg, sources, o, dirStamp }: Ctx): void {
n.build({
outputs,
rule: "codegen",
inputs: [script, ...sources.js, ...sources.jsCodegen, extraInput],
inputs: [script, ...sources.js, ...sources.jsCodegen, extraInput, errorCodeInput],
orderOnlyInputs: [dirStamp],
vars: {
cwd: cfg.cwd,
Expand Down
7 changes: 6 additions & 1 deletion scripts/build/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { execSync } from "node:child_process";
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, symlinkSync } from "node:fs";
import { homedir, arch as hostArch, platform as hostPlatform } from "node:os";
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
import { NODEJS_ABI_VERSION, NODEJS_VERSION } from "./deps/nodejs-headers.ts";
import { NODEJS_ABI_VERSION, NODEJS_V8_VERSION, NODEJS_VERSION } from "./deps/nodejs-headers.ts";
import { WEBKIT_VERSION } from "./deps/webkit.ts";
import { assert, BuildError } from "./error.ts";
import { resolveMacosSdkPath } from "./macos-sdk.ts";
Expand Down Expand Up @@ -61,6 +61,7 @@ export interface Host {
const versionDefaults = {
nodejsVersion: NODEJS_VERSION,
nodejsAbiVersion: NODEJS_ABI_VERSION,
nodejsV8Version: NODEJS_V8_VERSION,
webkitVersion: WEBKIT_VERSION,
};

Expand Down Expand Up @@ -307,6 +308,7 @@ export interface Config {
/** Node.js compat version. Default in versions.ts; override to test a bump. */
nodejsVersion: string;
nodejsAbiVersion: string;
nodejsV8Version: string;
/** WebKit commit. Default in versions.ts; override to test a WebKit branch. */
webkitVersion: string;
}
Expand Down Expand Up @@ -368,6 +370,7 @@ export interface PartialConfig {
// Version pins (defaults in versions.ts).
nodejsVersion?: string;
nodejsAbiVersion?: string;
nodejsV8Version?: string;
webkitVersion?: string;
}

Expand Down Expand Up @@ -1019,6 +1022,7 @@ export function resolveConfig(partial: PartialConfig, toolchain: Toolchain): Con
// to test a branch before bumping the pinned default.
const nodejsVersion = partial.nodejsVersion ?? versionDefaults.nodejsVersion;
const nodejsAbiVersion = partial.nodejsAbiVersion ?? versionDefaults.nodejsAbiVersion;
const nodejsV8Version = partial.nodejsV8Version ?? versionDefaults.nodejsV8Version;
const webkitVersion = partial.webkitVersion ?? versionDefaults.webkitVersion;

// ─── macOS SDK ───
Expand Down Expand Up @@ -1180,6 +1184,7 @@ export function resolveConfig(partial: PartialConfig, toolchain: Toolchain): Con
version,
revision,
nodejsVersion,
nodejsV8Version,
nodejsAbiVersion,
canaryRevision,
webkitVersion,
Expand Down
7 changes: 5 additions & 2 deletions scripts/build/deps/nodejs-headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import type { Dependency } from "../source.ts";
* download URL, and passed to zig as -Dreported_nodejs_version.
* Override via `--nodejs-version=X.Y.Z` to test a bump.
*/
export const NODEJS_VERSION = "24.3.0";
export const NODEJS_VERSION = "26.3.0";

/** Node.js NODE_MODULE_VERSION — for native addon ABI compat. */
export const NODEJS_ABI_VERSION = "137";
export const NODEJS_ABI_VERSION = "147";

/** V8 version reported by process.versions.v8 — must match the pinned Node.js version's. */
export const NODEJS_V8_VERSION = "14.6.202.34-node.20";

export const nodejsHeaders: Dependency = {
name: "nodejs",
Expand Down
6 changes: 5 additions & 1 deletion scripts/build/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,14 +742,18 @@ export const defines: Flag[] = [
},
{
// Shell-escaped quotes so clang receives literal quotes in the define
// (the preprocessor needs the string to be "24.3.0", not bare 24.3.0).
// (the preprocessor needs the string to be "26.3.0", not bare 26.3.0).
flag: c => `REPORTED_NODEJS_VERSION=\\"${c.nodejsVersion}\\"`,
desc: "Node.js version string reported by process.version",
},
{
flag: c => `REPORTED_NODEJS_ABI_VERSION=${c.nodejsAbiVersion}`,
desc: "Node.js ABI version (process.versions.modules)",
},
{
flag: c => `REPORTED_NODEJS_V8_VERSION=\\"${c.nodejsV8Version}\\"`,
desc: "V8 version string (process.versions.v8)",
},
{
// Hardcoded ON — experimental flag not exposed in config
flag: "USE_BUN_MIMALLOC=1",
Expand Down
6 changes: 5 additions & 1 deletion scripts/packer/windows-x64.pkr.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ source "azure-arm" "windows-x64" {

// Build VM — only used during image creation, not for CI runners.
// CI runner VM sizes are set in ci.mjs (azureVmSizes).
vm_size = "Standard_D4ds_v6"
// D4as_v7 (AMD): D4ds_v6 hit repeated AllocationFailed (no capacity for
// that size in the region); Azure's allocation-guidance suggested this
// size as an in-region alternative. Build-only VM, so the CPU vendor
// doesn't affect the produced image.
vm_size = "Standard_D4as_v7"

// Use existing resource group instead of creating a temp one
build_resource_group_name = var.resource_group
Expand Down
8 changes: 4 additions & 4 deletions src/js/builtins/CompressionStream.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export function initializeCompressionStream(this, format) {
const zlib = require("node:zlib");
const stream = require("node:stream");
const { newBufferSourceTransformPairFromDuplex } = require("internal/webstreams_adapters");

const builders = {
"deflate": zlib.createDeflate,
Expand All @@ -13,9 +13,9 @@ export function initializeCompressionStream(this, format) {
if (!(format in builders))
throw $ERR_INVALID_ARG_VALUE("format", format, "must be one of: " + Object.keys(builders).join(", "));

const handle = builders[format]();
$putByIdDirectPrivate(this, "readable", stream.Readable.toWeb(handle));
$putByIdDirectPrivate(this, "writable", stream.Writable.toWeb(handle));
const transform = newBufferSourceTransformPairFromDuplex(builders[format]());
$putByIdDirectPrivate(this, "readable", transform.readable);
$putByIdDirectPrivate(this, "writable", transform.writable);

return this;
}
Expand Down
8 changes: 4 additions & 4 deletions src/js/builtins/DecompressionStream.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export function initializeDecompressionStream(this, format) {
const zlib = require("node:zlib");
const stream = require("node:stream");
const { newBufferSourceTransformPairFromDuplex } = require("internal/webstreams_adapters");

const builders = {
"deflate": zlib.createInflate,
Expand All @@ -13,9 +13,9 @@ export function initializeDecompressionStream(this, format) {
if (!(format in builders))
throw $ERR_INVALID_ARG_VALUE("format", format, "must be one of: " + Object.keys(builders).join(", "));

const handle = builders[format]();
$putByIdDirectPrivate(this, "readable", stream.Readable.toWeb(handle));
$putByIdDirectPrivate(this, "writable", stream.Writable.toWeb(handle));
const transform = newBufferSourceTransformPairFromDuplex(builders[format]());
$putByIdDirectPrivate(this, "readable", transform.readable);
$putByIdDirectPrivate(this, "writable", transform.writable);

return this;
}
Expand Down
13 changes: 13 additions & 0 deletions src/js/builtins/ReadableStreamInternals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,19 @@ export function readableStreamCancel(stream: ReadableStream, reason: any) {
if (state === $streamErrored) return Promise.$reject($getByIdDirectPrivate(stream, "storedError"));
$readableStreamClose(stream);

// https://streams.spec.whatwg.org/#readable-stream-cancel step 5: a BYOB
// reader's pending read requests are closed with undefined ($readableStreamClose
// only settles default-reader read requests; respond(0) is not coming after cancel).
const reader = $getByIdDirectPrivate(stream, "reader");
if (reader && $isReadableStreamBYOBReader(reader)) {
const requests = $getByIdDirectPrivate(reader, "readIntoRequests");
if (requests.isNotEmpty()) {
$putByIdDirectPrivate(reader, "readIntoRequests", $createFIFO());
for (var request = requests.shift(); request; request = requests.shift())
$fulfillPromise(request, { value: undefined, done: true });
}
}

const controller = $getByIdDirectPrivate(stream, "readableStreamController");
if (controller === null) return Promise.$resolve();

Expand Down
4 changes: 4 additions & 0 deletions src/js/internal/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ function emitErrorNt(msg, err, callback) {
const setMaxHTTPHeaderSize = $newZigFunction("node_http_binding.zig", "setMaxHTTPHeaderSize", 1);
const getMaxHTTPHeaderSize = $newZigFunction("node_http_binding.zig", "getMaxHTTPHeaderSize", 0);
const kOutHeaders = Symbol("kOutHeaders");
const kProxyConfig = Symbol("kProxyConfig");
const kWaitForProxyTunnel = Symbol("kWaitForProxyTunnel");

function ipToInt(ip) {
const octets = ip.split(".");
Expand Down Expand Up @@ -532,6 +534,7 @@ export {
kPendingCallbacks,
kPort,
kProtocol,
kProxyConfig,
kRealListen,
kRequest,
kRes,
Expand All @@ -542,6 +545,7 @@ export {
kTls,
kUpgradeOrConnect,
kUseDefaultPort,
kWaitForProxyTunnel,
noBodySymbol,
optionsSymbol,
parseProxyConfigFromEnv,
Expand Down
19 changes: 13 additions & 6 deletions src/js/internal/primordials.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,27 +96,33 @@ const arrayToSafePromiseIterable = (promises, mapFn) =>
const PromiseAll = Promise.all;
const PromiseResolve = Promise.$resolve.bind(Promise);
const SafePromiseAll = (promises, mapFn) => PromiseAll(arrayToSafePromiseIterable(promises, mapFn));
const SafePromiseAllReturnArrayLike = (promises, mapFn) =>
// Shared scheduler for SafePromiseAllReturnVoid/ReturnArrayLike: `returnVal`
// is null for the void variant (no result bookkeeping, resolves with nothing).
const safePromiseAllCollect = (promises, mapFn, returnVal) =>
new Promise((resolve, reject) => {
const { length } = promises;

const returnVal = Array(length);
ObjectSetPrototypeOf(returnVal, null);
if (length === 0) resolve(returnVal);
if (length === 0) resolve(returnVal ?? undefined);

let pendingPromises = length;
for (let i = 0; i < length; i++) {
const promise = mapFn != null ? mapFn(promises[i], i) : promises[i];
PromisePrototypeThen.$call(
PromiseResolve(promise),
result => {
returnVal[i] = result;
if (--pendingPromises === 0) resolve(returnVal);
if (returnVal !== null) returnVal[i] = result;
if (--pendingPromises === 0) resolve(returnVal ?? undefined);
},
reject,
);
}
});
const SafePromiseAllReturnVoid = (promises, mapFn) => safePromiseAllCollect(promises, mapFn, null);
const SafePromiseAllReturnArrayLike = (promises, mapFn) => {
const returnVal = Array(promises.length);
ObjectSetPrototypeOf(returnVal, null);
return safePromiseAllCollect(promises, mapFn, returnVal);
};

export default {
Array,
Expand All @@ -136,6 +142,7 @@ export default {
),
SafePromiseAll,
SafePromiseAllReturnArrayLike,
SafePromiseAllReturnVoid,
SafeSet: makeSafe(
Set,
class SafeSet extends Set {
Expand Down
Loading