Skip to content

s3: leave the size of an S3 blob unknown in resolve_size - #43934

Closed
robobun wants to merge 4 commits into
mainfrom
robobun/aba85555/s3-size-stays-unknown
Closed

robobun wants to merge 4 commits into
mainfrom
robobun/aba85555/s3-size-stays-unknown

Conversation

@robobun

@robobun robobun commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Related to #41593

Problem

  • After console.log(request), fetch(request) uploads 1 byte of an S3 file body and gets a 200. request.body and request.textStream() read 1 byte. Each sends Range: bytes=0-0.
  • Cause: the S3 arm of resolve_size (src/runtime/webcore/Blob.rs:2145) sets the size to 0. Each S3 reader turns a known size into a Range header.
  • Found in review of Leave a body stream unsized when the file's st_size is 0 #41593, no user report. s3file.text(), request.text() and fetch(url, { body: s3file }) are correct.

Fix

  • The S3 arm of resolve_size and of resolved_size keeps the size. No caller changes.
  • Correct: an S3 object has no size before the download, and a slice already holds its window.
  • Body::Value::size maps the unknown size of an S3 blob to 0, so the inspect header stays Request (0 KB).
  • Verified: 16 new tests in test/js/web/fetch/body.test.ts and test/js/bun/s3/s3.test.ts, 15 fail on main.

Background

Downsides

Notes

Repro. A local server plays the S3 endpoint. The object has 100 bytes.

1.4.2 and main This PR
new Request(url, { body: s3file }).body 1 byte, bytes=0-0 100 bytes, no Range
a body made from s3file.slice(10, 30) 1 byte, bytes=10-10 20 bytes, bytes=10-29
Bun.inspect(request), then fetch(request) uploads 1 byte, 200 uploads 100 bytes
s3file.stream() 100 bytes 100 bytes

Paths that read one byte before. .body, textStream(), clone(), new Request(request), HTMLRewriter.transform(), WebAssembly.compileStreaming(), and each read after Bun.inspect(), expect().toHaveLength(), expect().toBeEmpty(), structuredClone() or a FormData body. A Response reaches these paths through fetch() of a blob: URL. new Response(s3file) is a redirect and does not.

Cost for callers that do not use S3. Release builds of the merge base 4227e46 and of this PR, same toolchain.

  • Release .text: 80,829,819 B before and after (llvm-size).
  • Stat and open syscalls over 600 new Bun.file() bodies: 1000 before and after (gdb catch syscall).
  • Instructions executed inside each changed function, per call. Counted with gdb, callees excluded, 3 repetitions and 2 runs per build, no variance.
Function Body Before After
to_readable_stream (.body) in-memory Blob 135 134
to_readable_stream (.body) file 145 144
to_text_readable_stream (.textStream()) in-memory Blob 101 100
to_text_readable_stream (.textStream()) file 117 117
from_blob_copy_ref in-memory Blob 166 164
from_blob_copy_ref file 221 221
Body::Value::size (Bun.inspect) in-memory Blob 31 31
Body::Value::size (Bun.inspect) file 34 34
Body::Value::size (Bun.inspect) S3 file 55 63

The S3 row includes its one callee, resolve_size (19 before, 18 after). perf, valgrind and strace are not installed on the machine that ran this. A count of whole calls, callees included, varies between runs of one binary, so it is not used.

Lines left alone on purpose. The File arm of resolve_size still sets the size to 0 when stat fails (Blob.rs:2143, and :2186 in resolved_size). That 0 is the documented .size of a missing Bun.file(). #39763 changes it.

The resolved_size arm. Its one caller, ByteBlobLoader::setup, runs only for a bytes store, so no test reaches this arm today. It changes with resolve_size because #43897 makes resolve_size apply resolved_size. After that, this arm is the rule for S3 and the new tests cover it.

The Body::Value::size line. On the first commit alone, the two Bun.inspect() tests fail with Request (0.0 ZB). The mapping is for an S3 blob only, so the header of each other body is the same as on main.

Other open PRs on these lines.

Other visible changes.

An open-ended slice as a body. A body made from s3file.slice(95) now sends bytes=95-4503599627370494. s3file.slice(95).text(), .stream() and request.text() send that header on main too. Before, the body stream sent bytes=95-95 and read 1 byte. #43938 tracks the header of an open-ended slice and of a negative index.

The inspect header of a file body. Not changed. A slice of a file and a missing file print 0.0 ZB, on main too. #43939 tracks it.

No user report. A search of the issues for an S3 body stream, bytes=0-0 and resolve_size found no report. #16398 and #27272 are closed reports about slices that were not empty.

Suites run with a debug build. body.test.ts and s3.test.ts: 811 pass, 290 skip (286 of them in s3.test.ts need S3 credentials or Docker). response.test.ts, wasm-streaming.test.ts, blob.test.ts, FormData.test.ts, FormData-multipart-serialization.test.ts, structured-clone-blob-file.test.ts, inspect.test.js, expect.test.js, html-rewriter.test.js and five S3 suites that use a local server: 1082 pass. In that run handle stack overflow in response.test.ts timed out once, at 5.5 s against a limit of 5 s. Alone it takes 4.8 s on the debug build and passes. It takes 60 ms on a release build of main and of this PR. It uses a Response with no body.


[human-review] gate passed · iteration 0 · 5 files touched

fails on main (without fix)
ASAN without fix: 15 failed, 290 skipped
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/pr_gate.xml" "test/js/bun/s3/s3.test.ts" test/js/web/fetch/body.test.ts
bun test v1.4.3 (367d939d9)

test/js/bun/s3/s3.test.ts:
failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory
(skip) R2 > s3 > fetch > bucket in path > should download file via fetch GET
(skip) R2 > s3 > fetch > bucket in path > should download range
(skip) R2 > s3 > fetch > bucket in path > should check if a key exists or content-length
(skip) R2 > s3 > fetch > bucket in path > should check if a key does not exist
(skip) R2 > s3 > fetch > bucket in path > should be able to set content-type
(skip) R2 > s3 > fetch > bucket in path > should be able to upload large files
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download file via Bun.s3().text()
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download range
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download range with 0 offset
(skip) R2 > s3 > Bun.S3Client > 
... (truncated)

release without fix: 290 skipped
bun test v1.4.3-canary.1 (d63112719)

test/js/bun/s3/s3.test.ts:
failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory
(skip) R2 > s3 > fetch > bucket in path > should download file via fetch GET
(skip) R2 > s3 > fetch > bucket in path > should download range
(skip) R2 > s3 > fetch > bucket in path > should check if a key exists or content-length
(skip) R2 > s3 > fetch > bucket in path > should check if a key does not exist
(skip) R2 > s3 > fetch > bucket in path > should be able to set content-type
(skip) R2 > s3 > fetch > bucket in path > should be able to upload large files
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download file via Bun.s3().text()
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download range
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download range with 0 offset
(skip) R2 > s3 > Bun.S3Client > bucket in path > should check if a key exists or content-length
(skip) R2 > s3 > Bun.S3Client > bucket in path > should check if a key does not exist
(skip) R2 > s3 > Bun.S3Client > 
... (truncated)
passes on PR (with fix)
ASAN with fix: 290 skipped
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/pr_gate.xml" "test/js/bun/s3/s3.test.ts" test/js/web/fetch/body.test.ts
bun test v1.4.3 (367d939d9)

test/js/bun/s3/s3.test.ts:
failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory
(skip) R2 > s3 > fetch > bucket in path > should download file via fetch GET
(skip) R2 > s3 > fetch > bucket in path > should download range
(skip) R2 > s3 > fetch > bucket in path > should check if a key exists or content-length
(skip) R2 > s3 > fetch > bucket in path > should check if a key does not exist
(skip) R2 > s3 > fetch > bucket in path > should be able to set content-type
(skip) R2 > s3 > fetch > bucket in path > should be able to upload large files
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download file via Bun.s3().text()
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download range
(skip) R2 > s3 > Bun.S3Client > bucket in path > should download range with 0 offset
(skip) R2 > s3 > Bun.S3Client > 
... (truncated)

release with fix: 290 skipped
$ bun scripts/build.ts --profile=release
[configured] bun-profile → bun (stripped) in 1067ms (unchanged)
ninja: Entering directory `/workspace/bun/build/release'
[1/145] gen JSBuffer.lut.h
Generating /workspace/bun/build/release/codegen/JSBuffer.lut.h from /workspace/bun/src/jsc/bindings/JSBuffer.cpp
[2/145] gen generated_host_exports.rs
generated_host_exports.rs: 121 exports (host=5, lazy=10, generic=106, rust=0); 248 extern-C blocks audited
[3/145] gen cpp.rs (cppbind)
[4/145] gen JS modules (bundle-modules)
Preprocess modules (8873ms)
Bundle modules (145ms)
Postprocesss modules (158ms)
Bundle Functions (486ms)
Generate Code (43ms)

[9.71s] Bundled "src/js" for production
  2597 kb
  197 internal modules
  13 native modules
  50 internal functions across 16 files
[5/142] rustc bun_spawn 
[6/142] rustc bun_patch 
[7/142] pch pch/root-pch.h.hxx.pch
[8/142] cxx obj/unified/UnifiedSource-src_jsc_bindings-0.cpp.o
[9/142] cxx obj/unified/UnifiedSource-src_jsc_bindings-1.cpp.o
[10/142] cxx obj/unified/UnifiedSource-src_jsc_bindings_node_crypto-0.cpp.o
[11/142] cxx obj/unified/UnifiedSource-src_jsc_bindings_v8-0.cpp.o
[12/142] cxx obj/unified/UnifiedSource-packages_bun_
... (truncated)
diff hotspot
src/runtime/webcore/Blob.rs         |   5 +-
 src/runtime/webcore/Body.rs         |   6 +-
 test/js/bun/s3/s3-local-endpoint.ts |  33 +++++++++
 test/js/bun/s3/s3.test.ts           |  93 ++++++++++++++++++++++++
 test/js/web/fetch/body.test.ts      | 138 ++++++++++++++++++++++++++++++++++++
 5 files changed, 272 insertions(+), 3 deletions(-)

gate history · 1 passed · 0 rejected · iteration 0

evidence per changed file
file                                 reads  edits  tests
src/runtime/webcore/Blob.rs              7      3     41
src/runtime/webcore/Body.rs              4      2     40
test/js/bun/s3/s3-local-endpoint.ts      0      1     41
test/js/bun/s3/s3.test.ts                0      0     27
test/js/web/fetch/body.test.ts           2      0     28

resolve_size set the size of an S3-backed blob to 0. An S3 object has no
size before the download, and a slice already has its final window. Every
reader maps a size other than MAX_SIZE to a Range header, so a resolved
S3 blob requested `Range: bytes=N-N` and read one byte.

This broke the body stream of a Request or Response made from an S3 file
(.body, textStream(), HTMLRewriter, WebAssembly.compileStreaming), and
every read that came after Bun.inspect(request), expect().toHaveLength(),
structuredClone() or a FormData body.

The S3 arm of resolve_size and of resolved_size now keeps the size.
Body::Value::size feeds only the `Request (size)` and `Response (size)`
header of Bun.inspect. An S3 body printed `0 KB` because resolve_size had
set its size to 0. With the size left unknown, get_size_for_bindings
returns u64::MAX, which the size formatter prints as `0.0 ZB`.

Map the unknown size of an S3 blob to 0, the value a Locked body with no
size hint reports. The header of an S3 body does not change, and no other
body is affected.
@robobun

robobun commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: closed. #46653 replaces this PR.

How to reproduce. A local Bun.serve plays the S3 endpoint and records the Range header. The object has 100 bytes.

import { S3Client } from "bun";

const payload = Buffer.alloc(100, "0123456789").toString();
const ranges = [];
using server = Bun.serve({
  port: 0,
  fetch(req) {
    const range = req.headers.get("range");
    ranges.push(range);
    const m = /^bytes=(\d+)-(\d+)$/.exec(range ?? "");
    return m ? new Response(payload.slice(+m[1], +m[2] + 1), { status: 206 }) : new Response(payload);
  },
});
const s3 = new S3Client({ endpoint: server.url.href, accessKeyId: "x", secretAccessKey: "y", bucket: "b" });

const request = new Request("http://example.com/", { method: "POST", body: s3.file("key") });
console.log((await Bun.readableStreamToText(request.body)).length); // 1 on 1.4.2 and main, 100 with this PR
console.log(ranges); // [ "bytes=0-0" ] on 1.4.2 and main, [ null ] with this PR

The 16 new tests in test/js/web/fetch/body.test.ts and test/js/bun/s3/s3.test.ts run the same way. 15 fail on main (4227e46) and 16 pass on this branch.

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: oven-sh/bun/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Essentials

Run ID: 67cd333b-42a7-4614-b026-56cc19bbf956

📥 Commits

Reviewing files that changed from the base of the PR and between d631127 and e0df286.

📒 Files selected for processing (4)
  • src/runtime/webcore/Blob.rs
  • test/js/bun/s3/s3-local-endpoint.ts
  • test/js/bun/s3/s3.test.ts
  • test/js/web/fetch/body.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 3 remain after this review.


Walkthrough

S3 Blob size resolution now preserves offsets and sizes. Value::size reports an unknown S3 Blob size as zero. Tests cover inspection, cloning, slices, FormData, and S3-backed Request and Response bodies.

Changes

S3 Blob size and body reads

Layer / File(s) Summary
Preserve S3 Blob size values
src/runtime/webcore/Blob.rs, src/runtime/webcore/Body.rs
Blob size resolution retains S3 offsets and sizes. Value::size reports an S3 Blob with the unknown-size sentinel as zero.
S3 file inspection and slices
test/js/bun/s3/s3-local-endpoint.ts, test/js/bun/s3/s3.test.ts
A local endpoint records range requests. Tests check that inspection, cloning, and FormData use do not change an unknown file size, and that whole-file and slice reads return the expected content.
S3 files as web bodies
test/js/web/fetch/body.test.ts
Tests cover S3-backed Request and Response bodies, including body readers, clones, uploads, HTMLRewriter, and WebAssembly.compileStreaming().

Suggested reviewers: jarred-sumner

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to e0df2

S3-backed body reads retain the intended full-object behavior. No actionable issue remains before merging after normal checks.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving the unknown size of S3 blobs in resolve_size.
Description check ✅ Passed The description explains the problem, cause, fix, scope, downsides, and verification results. It does not use the exact template headings, but it contains the required information and is substantially…

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

@robobun

robobun commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 5:31 PM PT - Sep 24th, 2026

✅ @robobun, your commit e0df286e495429b6bb5e3df053d1ba8fbc1ca461 passed in Build #120474! 🎉


🧪   To try this PR locally:

bunx bun-pr 43934

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

bun-43934 --bun

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Additional findings (outside the current diff — GitHub can't attach inline comments there):

  • 🟣 src/runtime/webcore/Blob.rs — Users who structuredClone or postMessage an S3 file now get a DataClone error on every call, where the base returned a Blob on the second and later calls. The serializer at src/runtime/webcore/Blob.rs:728-736 tags an S3 store as SerializeTag::Bytes and then writes the u64 size at Blob.rs:753 before resolve_size; the Bytes deserializer at Blob.rs:3807 reads the low 32 bits of that size as a byte length, and MAX_SIZE yields 0xFFFFFFFF, which read_slice rejects with TooSmall. Fix: give S3 stores their own SerializeTag (or reuse File with the S3 path record) so serialize and deserialize agree, and add a round-trip test for structuredClone(s3file).

    Why this was flagged

    Trigger: structuredClone(s3file) or worker.postMessage(s3file); on_structured_clone_serialize at src/runtime/webcore/Blob.rs:728-736 selects SerializeTag::Bytes for an S3 store, writes the blob size at Blob.rs:753, and then Store::serialize (blob/Store.rs:199) writes the S3 path record. on_structured_clone_deserialize at Blob.rs:3806-3808 reads a u32 bytes_len from the first four bytes of the size. With MAX_SIZE = (1<<52)-1 the low u32 is 0xFFFFFFFF, so read_slice fails with Error::TooSmall and the call throws. On the base the first call throws the same way, but resolve_size (Blob.rs:754) then set the size to 0 so every later clone parsed a zero-length Bytes record and returned a Blob; after this change the size stays MAX_SIZE and every call throws. The new test at test/js/bun/s3/s3.test.ts:2248-2250 swallows this with an empty catch, so nothing asserts what structuredClone returns. Remedy: serialize an S3 store with a tag the deserializer understands, and assert the clone result in the test.

    Verification: pre-existing. Trigger: structuredClone(s3file) / postMessage(s3file) on any S3-backed Blob. Mechanism verified: /home/claude/bun/src/runtime/webcore/Blob.rs:728-736 tags every non-File store (including store::Data::S3) as SerializeTag::Bytes; the else-branch at :753 then writes self.size.get() as a u64 BEFORE self.resolve_size() (:754) and store.serialize (:755, the S3 arm in…

  • 🟣 src/runtime/webcore/Blob.rs — Anyone who sends a FormData containing an S3 file as a Request or Response body uploads an empty part, and the file contents are silently dropped. The S3 arm of the multipart serializer at src/runtime/webcore/Blob.rs:3677 is a TODO that writes no bytes after resolve_size at Blob.rs:3668, and nothing reports the omission to the caller. Fix: either read the S3 object into the part (async download like the File arm) or reject the body with an error naming the unsupported S3 entry, so a multipart upload never signals success with missing data.

    Why this was flagged

    Trigger: form.append("file", s3client.file(key)) then new Response(form).arrayBuffer() or fetch(url, { body: form }); the FormData entry reaches the multipart serializer at src/runtime/webcore/Blob.rs:3668 which calls resolve_size and then matches store::Data::S3 at Blob.rs:3677, an empty arm. Before this change the size was set to 0 and the part was empty; after it the size stays MAX_SIZE and the part is still empty, so the base and the change both produce a multipart body whose S3 part has headers and no payload, with no error. The new test at test/js/bun/s3/s3.test.ts:2258-2260 wraps this call in try {} catch {} and only asserts that the entry can still be read afterwards, so the silent drop is never asserted against. The dismissal treats the arm as out of scope, but the PR touches the size handling that feeds this arm and leaves a successful-looking upload with missing content. Remedy: fail loudly for an S3 entry until the async download is implemented.

    Verification: pre-existing. Trigger: a FormData holding an S3 blob (form.append("file", s3client.file(key))) is used as a Request/Response body and serialized. Mechanism verified at /home/claude/bun/src/runtime/webcore/Blob.rs:3666-3679: on_entry writes the part headers, calls blob.resolve_size() when size is MAX_SIZE (line 3668), then matches store::Data::S3(_) => { // TODO: s3 ... } (lines…

Comment thread test/js/bun/s3/s3.test.ts Outdated
Comment thread test/js/bun/s3/s3.test.ts
Comment thread test/js/web/fetch/body.test.ts
Comment thread test/js/web/fetch/body.test.ts Outdated
Comment thread src/runtime/webcore/Blob.rs
Comment thread src/runtime/webcore/Body.rs
Both test files had a copy of the server that plays the S3 endpoint. Move
it to test/js/bun/s3/s3-local-endpoint.ts.

The matcher assertions name the message of the length comparison, so a
throw for another reason does not pass. The bytes() reader is compared
with the payload, not with its length.
Comment thread src/runtime/webcore/Blob.rs Outdated
@robobun

robobun commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Reply to the two findings outside the diff. Both are present on 1.4.2 and on main, and this PR does not change them.

The inline comments have a reply in each thread. Three are done in 1394f42.

@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.

Re-reviewed after the two follow-up commits (shared s3-local-endpoint.ts, specific toThrow messages, bytes() now compared by content) and found no new bugs; a maintainer's look is still worthwhile because resolve_size is a shared helper whose S3 semantics this changes, and the same lines are touched by several open PRs named in the description.

What was reviewed:

  • Every resolve_size/resolved_size caller (serializer, get_exists_sync, get_size_for_bindings, get_size, FormData multipart, Body::to_readable_stream/to_text_readable_stream, HEAD response in RequestContext, wasm_streaming) for a consumer that relied on the S3 size being 0 — each already maps MAX_SIZE to "unknown" (None range in from_blob_copy_ref, content-length: 0 on HEAD, NaN in get_size).
  • Body::Value::size change is scoped to is_s3(); other bodies' inspect header is unchanged.
  • New tests: hermetic local Bun.serve({ port: 0 }), using disposal, exact byte and Range-header assertions, and they exercise the changed arm via .body, textStream(), clone(), Bun.inspect, structuredClone, FormData and slices.
Extended reasoning...

The diff is a three-line runtime change in src/runtime/webcore/Blob.rs (S3 arms of resolve_size and resolved_size keep the size instead of setting 0) and src/runtime/webcore/Body.rs (u64::MAX for an S3 blob maps to 0 in the inspect header), plus a new shared test helper and ~230 lines of tests in test/js/bun/s3/ and test/js/web/fetch/. It touches no security-sensitive surface (no auth, parsing of untrusted input, or credentials beyond placeholder test values). Since the prior review, commits 1394f42 and e0df286 addressed three of the six earlier nits; the remaining ones were marked optional or pre-existing and the author replied to each. Deferring rather than approving because the change alters observable behaviour of a shared Blob helper (matchers on S3 files now throw, structuredClone/FormData paths no longer collapse the slice window) and conflicts with open PRs #43897, #43910 and #36296 on the same lines, which is a landing-order decision for a maintainer; no CODEOWNERS entry covers the changed files.

@robobun

robobun commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

#38364 now contains the four commits of this PR, merged in without a change to the source. It needs them: it lets an empty slice of an S3 file through as an empty FormData part, and that is safe only when nothing else writes size 0 onto an S3 blob.

Two small edits to the tests came with the merge:

If #38364 lands first, this PR has nothing left to add. If this one lands first, #38364 keeps only its own part.

robobun added a commit that referenced this pull request Oct 24, 2026
#46653 replaces #43934. This branch now has the same three source hunks
as #46653, so the two merge without a conflict in either order. The
tests of #43934 and its S3 stand-in are gone from this branch. The
FormData tests use the S3 server in test/packages/s3-server.
@robobun

robobun commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator Author

Correction to my comment above. #38364 no longer contains the commits of this PR.

#38364 now contains #46653, which replaces this PR. The two resolve_size() arms are the same as here, and there is no case in Body::Value::size. The tests of this PR and s3-local-endpoint.ts are gone from #38364.

@robobun

robobun commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

#46653 replaces this PR, so I am closing this one. It makes the same two changes to resolve_size and resolved_size on current main, with more tests.

Not carried over:

If a maintainer prefers this version, reopen it.

@robobun robobun closed this Oct 24, 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.

2 participants