feat: implement Response.clone()#312
Conversation
f11e19c to
1c3a6cf
Compare
90647e3 to
c28ec93
Compare
… tee Fix Headers cloning bug -- re: Immutable.
c28ec93 to
43436f3
Compare
|
Thank you! Looks good. It's a bit unfortunate that we cannot use SpiderMonkey's That said, I think those changes will break IIUC See the comment: Also, this has to be rebased to include: #313, because it will change wpt expectations. Is that correct? |
|
@tschneidereit did you want to have another look? If I'm not mistaken you're fresh out of the stream implementation 🙂 |
Good catch — fixed in the latest push. One-liner in maybe_stream_body: also gate the incoming fast-path on Impact: basically nil for normal apps — proxy / header-rewrite / fetch-and-return never reify I did look at gating on an explicit "was teed" flag to keep the fast-path for the bare .body-reify case, but that only helps "reify .body, never read it, return the same object" — which doesn't really happen — so I went with the simpler guard. All WPT + unit tests still green.
yes, WPT expectations will have some "FAIL" with this branch alone and rebasing #313 will make them all "PASS" |
Implement Response.clone() (WHATWG Fetch)
Implements
Response.clone()per the WHATWG Fetch spec. All 21 WPT tests infetch/api/response/response-clone.any.jspass.Approach
Response bodies are modelled as default (non-byte)
ReadableStreams, whose tee shares a singlechunk object between both branches. Fetch's "clone a body" requires the clone to receive independent
copies, so
Response::cloneimplements the WHATWGReadableStreamDefaultTeealgorithm withcloneForBranch2 = true:object identity, and a
JSAutoStructuredCloneBuffercopy is enqueued into branch2 (the clone'sbody).
lazy copy would be read-order dependent and would duplicate already-mutated bytes if the original
branch is read and mutated in place first.
Cancellation is tracked per branch (
canceled1/canceled2): a cancelled branch is dropped from theread loop while the other continues.
sc_callbacksis not needed — body chunks areTypedArray/ArrayBuffer/DataView, handled by thebuilt-in structured clone.
Design notes
count as the spec byte-stream tee.
highWaterMarkis 0 and chunks are pulled on demand, so thebody is never fully buffered.
this directly (
CloneAsUint8Array, no hand-rolled tee), but that is a large change across allbody I/O and is out of scope here.
Request::clonecurrently tees without copying branch2; aligning it is a reasonablefollow-up.
Changes
builtins/web/fetch/request-response.hResponse::clonedeclaration.builtins/web/fetch/request-response.cpp#include "js/StructuredClone.h".Request::bodyUsed_get/Response::bodyUsed_get: fall back toJS::ReadableStreamIsDisturbedwhen the
BodyUsedslot is false, sobodyUsedreportstrueafterbody.cancel()and otherexternal stream disturbances.
CloneTeeSlot(shared-state layout),clone_tee_pump,clone_tee_read_then_handler,clone_tee_read_catch_handler,clone_tee_cancel_algorithm,clone_tee_pull_algorithm.Response::clone: acquires a default reader on the body, creates twoNativeStreamSourcebranches over shared tee state, and assigns branch1 to the original responseand branch2 to the clone.
JS_FN("clone", Response::clone, 0, JSPROP_ENUMERATE).tests/wpt-harness/expectations/fetch/api/response/response-clone.any.js.jsonWPT results
fetch/api/response/response-clone.any.js— 21/21 pass.Side-effect fixes from the
ReadableStreamIsDisturbedfallback inbodyUsed_get:fetch/api/response/response-stream-disturbed-6.any.js— 5 FAIL → PASS (partially resolves Stream disturbed test failures #184)fetch/api/response/response-stream-disturbed-by-pipe.any.js— 2 FAIL → PASSfetch/api/request/request-disturbed.any.js— 1 FAIL → PASSfetch/api/abort/general.any.js— 2 FAIL → PASSfetch/api/body/mime-type.any.js— new expectations file (6 PASS, 14 FAIL). The file previouslyaborted during initialisation on a top-level
clone()that threwTypeError; it now loads, and the14 failures expose a pre-existing gap where
parse_body<Blob>does not populateblob.typefromthe
Content-Typeheader. Tracked in #311.Downstream testing: PASSING
https://github.com/G-Core/FastEdge-sdk-js/blob/main/integration-tests/test-application/handlers/response-clone.ts