Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fetch: avoid async iteration when request.body is null #1303

Merged
merged 2 commits into from Mar 28, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
97 changes: 49 additions & 48 deletions lib/fetch/index.js
Expand Up @@ -1664,61 +1664,62 @@ async function httpNetworkFetch (
// 2. Otherwise, return a network error.

// To transmit request’s body body, run these steps:
const requestBody = (async function * () {
// 1. If body is null and fetchParams’s process request end-of-body is
// non-null, then queue a fetch task given fetchParams’s process request
// end-of-body and fetchParams’s task destination.
if (request.body == null && fetchParams.processRequestEndOfBody) {
queueMicrotask(() => fetchParams.processRequestEndOfBody())
} else if (request.body != null) {
// 2. Otherwise, if body is non-null:

// 1. Let processBodyChunk given bytes be these steps:
const processBodyChunk = async function * (bytes) {
// 1. If the ongoing fetch is terminated, then abort these steps.
if (isCancelled(fetchParams)) {
return
}
let requestBody = null
// 1. If body is null and fetchParams’s process request end-of-body is
// non-null, then queue a fetch task given fetchParams’s process request
// end-of-body and fetchParams’s task destination.
if (request.body == null && fetchParams.processRequestEndOfBody) {
queueMicrotask(() => fetchParams.processRequestEndOfBody())
} else if (request.body != null) {
// 2. Otherwise, if body is non-null:

// 1. Let processBodyChunk given bytes be these steps:
const processBodyChunk = async function * (bytes) {
// 1. If the ongoing fetch is terminated, then abort these steps.
if (isCancelled(fetchParams)) {
return
}

// 2. Run this step in parallel: transmit bytes.
yield bytes
// 2. Run this step in parallel: transmit bytes.
yield bytes

// 3. If fetchParams’s process request body is non-null, then run
// fetchParams’s process request body given bytes’s length.
fetchParams.processRequestBodyChunkLength?.(bytes.byteLength)
}
// 3. If fetchParams’s process request body is non-null, then run
// fetchParams’s process request body given bytes’s length.
fetchParams.processRequestBodyChunkLength?.(bytes.byteLength)
}

// 2. Let processEndOfBody be these steps:
const processEndOfBody = () => {
// 1. If fetchParams is canceled, then abort these steps.
if (isCancelled(fetchParams)) {
return
}
// 2. Let processEndOfBody be these steps:
const processEndOfBody = () => {
// 1. If fetchParams is canceled, then abort these steps.
if (isCancelled(fetchParams)) {
return
}

// 2. If fetchParams’s process request end-of-body is non-null,
// then run fetchParams’s process request end-of-body.
if (fetchParams.processRequestEndOfBody) {
fetchParams.processRequestEndOfBody()
}
// 2. If fetchParams’s process request end-of-body is non-null,
// then run fetchParams’s process request end-of-body.
if (fetchParams.processRequestEndOfBody) {
fetchParams.processRequestEndOfBody()
}
}

// 3. Let processBodyError given e be these steps:
const processBodyError = (e) => {
// 1. If fetchParams is canceled, then abort these steps.
if (isCancelled(fetchParams)) {
return
}
// 3. Let processBodyError given e be these steps:
const processBodyError = (e) => {
// 1. If fetchParams is canceled, then abort these steps.
if (isCancelled(fetchParams)) {
return
}

// 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller.
if (e.name === 'AbortError') {
fetchParams.controller.abort()
} else {
fetchParams.controller.terminate(e)
}
// 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller.
if (e.name === 'AbortError') {
fetchParams.controller.abort()
} else {
fetchParams.controller.terminate(e)
}
}

// 4. Incrementally read request’s body given processBodyChunk, processEndOfBody,
// processBodyError, and fetchParams’s task destination.
// 4. Incrementally read request’s body given processBodyChunk, processEndOfBody,
// processBodyError, and fetchParams’s task destination.
requestBody = (async function * () {
try {
for await (const bytes of request.body.stream) {
yield * processBodyChunk(bytes)
Expand All @@ -1727,8 +1728,8 @@ async function httpNetworkFetch (
} catch (err) {
processBodyError(err)
}
}
})()
})()
}

try {
const { body, status, statusText, headersList } = await dispatch({ body: requestBody })
Expand Down