Skip to content

fix(fetch): implement Request.text()/.json()/.arrayBuffer() (#1688) - #1690

Merged
proggeramlug merged 1 commit into
mainfrom
worktree-fix-1688-request-body-methods
May 24, 2026
Merged

fix(fetch): implement Request.text()/.json()/.arrayBuffer() (#1688)#1690
proggeramlug merged 1 commit into
mainfrom
worktree-fix-1688-request-body-methods

Conversation

@proggeramlug

@proggeramlug proggeramlug commented May 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Request.text() / .json() / .arrayBuffer() under Perry-native compile. Closes #1688.

Before this change, new Request(url, { body }).text() / .json() / .arrayBuffer() returned 0 instead of the request body. req.method / req.url / req.headers already worked (#1649); only the body-consuming methods were unimplemented — the typed module=="Request" codegen arm in lower_call/options/fetch.rs handled the property getters but had no body-method dispatch, so req.text() fell through to a generic path that yielded 0.

Changes

  • Runtime (perry-stdlib): add js_request_text / js_request_json / js_request_array_buffer, mirroring the existing Response js_fetch_response_text / js_fetch_response_json / js_response_array_buffer path. Body is in-memory, so the promise resolves synchronously (the LLVM await loop doesn't drain the deferred pump). A bodiless request reads as "".
  • Runtime (perry-ext-fetch): same three FFIs for the well-known-flip path, matching that crate's conventions, plus a data-path unit test.
  • Codegen: route text / json / arrayBuffer in the Request arm to the new FFIs (Promise pointer NaN-boxed as POINTER_TAG); declare them in runtime_decls.
  • Test: extend test_gap_fetch_response.ts with the three body methods.

Validation

Byte-for-byte identical to node --experimental-strip-types on the full test_gap_fetch_response.ts gap test (including the new request text / request json data / request arrayBuffer byteLength lines). cargo test -p perry-ext-fetch green (7 tests). cargo fmt --all -- --check clean.

Both code paths were exercised: the well-known flip routed fetchperry-ext-fetch and linked cleanly, confirming the ext-fetch additions are also reached.

Note (out of scope)

Using new Request(...) inline (e.g. await new Request(...).text()) doesn't set the uses_fetch feature flag, so the auto-optimize build omits the fetch module and the link fails — a pre-existing feature-detection limitation that affects all inline-Request method calls (and js_request_new itself), not just the new ones. Assigning to a variable first (const r = new Request(...), as in the #1688 repro) works. Tracked separately in #1691.

`new Request(url, { body }).text()` / `.json()` / `.arrayBuffer()` returned
`0` instead of the request body. `req.method` / `req.url` / `req.headers`
already worked (#1649); only the body-consuming methods were unimplemented.

The typed `module=="Request"` codegen arm in `lower_call/options/fetch.rs`
handled the url/method/body/headers property getters but had no body-method
dispatch, so `req.text()` fell through to a generic path that yielded `0`.

- Runtime (perry-stdlib): add `js_request_text` / `js_request_json` /
  `js_request_array_buffer`, mirroring the Response `js_fetch_response_text`
  / `js_fetch_response_json` / `js_response_array_buffer` path. The body is
  in-memory so the promise resolves synchronously (the LLVM await loop
  doesn't drain the deferred pump). A bodiless request reads as "".
- Runtime (perry-ext-fetch): same three FFIs for the well-known-flip path,
  matching that crate's conventions + a data-path unit test.
- Codegen: route `text`/`json`/`arrayBuffer` in the Request arm to the new
  FFIs (Promise pointer NaN-boxed as POINTER_TAG); declare them in
  runtime_decls.
- Extend test_gap_fetch_response.ts with the three body methods (verified
  byte-for-byte against `node --experimental-strip-types`).
@proggeramlug
proggeramlug merged commit 666786a into main May 24, 2026
9 checks passed
@proggeramlug
proggeramlug deleted the worktree-fix-1688-request-body-methods branch May 24, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web Fetch: Request.text() / Request.json() / Request.arrayBuffer() return 0 instead of the body

1 participant