mirror of
https://github.com/denoland/deno.git
synced 2025-10-02 15:14:33 +00:00
Revert "feat(fetch): accept async iterables for body" (#25207)
Unfortunately this caused a regression: https://github.com/denoland/deno/issues/25203. Need to do some more upstream spec work to fix this before this can be re-landed. Reverts denoland/deno#24623
This commit is contained in:
parent
675539c7ab
commit
e53678fd58
9 changed files with 51 additions and 217 deletions
|
@ -458,8 +458,6 @@ function extractBody(object) {
|
||||||
if (object.locked || isReadableStreamDisturbed(object)) {
|
if (object.locked || isReadableStreamDisturbed(object)) {
|
||||||
throw new TypeError("ReadableStream is locked or disturbed");
|
throw new TypeError("ReadableStream is locked or disturbed");
|
||||||
}
|
}
|
||||||
} else if (object[webidl.AsyncIterable] === webidl.AsyncIterable) {
|
|
||||||
stream = ReadableStream.from(object.open());
|
|
||||||
}
|
}
|
||||||
if (typeof source === "string") {
|
if (typeof source === "string") {
|
||||||
// WARNING: this deviates from spec (expects length to be set)
|
// WARNING: this deviates from spec (expects length to be set)
|
||||||
|
@ -477,9 +475,6 @@ function extractBody(object) {
|
||||||
return { body, contentType };
|
return { body, contentType };
|
||||||
}
|
}
|
||||||
|
|
||||||
webidl.converters["async iterable<Uint8Array>"] = webidl
|
|
||||||
.createAsyncIterableConverter(webidl.converters.Uint8Array);
|
|
||||||
|
|
||||||
webidl.converters["BodyInit_DOMString"] = (V, prefix, context, opts) => {
|
webidl.converters["BodyInit_DOMString"] = (V, prefix, context, opts) => {
|
||||||
// Union for (ReadableStream or Blob or ArrayBufferView or ArrayBuffer or FormData or URLSearchParams or USVString)
|
// Union for (ReadableStream or Blob or ArrayBufferView or ArrayBuffer or FormData or URLSearchParams or USVString)
|
||||||
if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, V)) {
|
if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, V)) {
|
||||||
|
@ -498,14 +493,6 @@ webidl.converters["BodyInit_DOMString"] = (V, prefix, context, opts) => {
|
||||||
if (ArrayBufferIsView(V)) {
|
if (ArrayBufferIsView(V)) {
|
||||||
return webidl.converters["ArrayBufferView"](V, prefix, context, opts);
|
return webidl.converters["ArrayBufferView"](V, prefix, context, opts);
|
||||||
}
|
}
|
||||||
if (webidl.isAsyncIterator(V)) {
|
|
||||||
return webidl.converters["async iterable<Uint8Array>"](
|
|
||||||
V,
|
|
||||||
prefix,
|
|
||||||
context,
|
|
||||||
opts,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// BodyInit conversion is passed to extractBody(), which calls core.encode().
|
// BodyInit conversion is passed to extractBody(), which calls core.encode().
|
||||||
// core.encode() will UTF-8 encode strings with replacement, being equivalent to the USV normalization.
|
// core.encode() will UTF-8 encode strings with replacement, being equivalent to the USV normalization.
|
||||||
|
|
1
ext/fetch/lib.deno_fetch.d.ts
vendored
1
ext/fetch/lib.deno_fetch.d.ts
vendored
|
@ -163,7 +163,6 @@ declare type BodyInit =
|
||||||
| FormData
|
| FormData
|
||||||
| URLSearchParams
|
| URLSearchParams
|
||||||
| ReadableStream<Uint8Array>
|
| ReadableStream<Uint8Array>
|
||||||
| AsyncIterable<Uint8Array>
|
|
||||||
| string;
|
| string;
|
||||||
/** @category Fetch */
|
/** @category Fetch */
|
||||||
declare type RequestDestination =
|
declare type RequestDestination =
|
||||||
|
|
|
@ -70,6 +70,7 @@ const {
|
||||||
String,
|
String,
|
||||||
Symbol,
|
Symbol,
|
||||||
SymbolAsyncIterator,
|
SymbolAsyncIterator,
|
||||||
|
SymbolIterator,
|
||||||
SymbolFor,
|
SymbolFor,
|
||||||
TypeError,
|
TypeError,
|
||||||
TypedArrayPrototypeGetBuffer,
|
TypedArrayPrototypeGetBuffer,
|
||||||
|
@ -5083,6 +5084,34 @@ function initializeCountSizeFunction(globalObject) {
|
||||||
WeakMapPrototypeSet(countSizeFunctionWeakMap, globalObject, size);
|
WeakMapPrototypeSet(countSizeFunctionWeakMap, globalObject, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ref: https://tc39.es/ecma262/#sec-getiterator
|
||||||
|
function getAsyncOrSyncIterator(obj) {
|
||||||
|
let iterator;
|
||||||
|
if (obj[SymbolAsyncIterator] != null) {
|
||||||
|
iterator = obj[SymbolAsyncIterator]();
|
||||||
|
if (!isObject(iterator)) {
|
||||||
|
throw new TypeError(
|
||||||
|
"[Symbol.asyncIterator] returned a non-object value",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (obj[SymbolIterator] != null) {
|
||||||
|
iterator = obj[SymbolIterator]();
|
||||||
|
if (!isObject(iterator)) {
|
||||||
|
throw new TypeError("[Symbol.iterator] returned a non-object value");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new TypeError("No iterator found");
|
||||||
|
}
|
||||||
|
if (typeof iterator.next !== "function") {
|
||||||
|
throw new TypeError("iterator.next is not a function");
|
||||||
|
}
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isObject(x) {
|
||||||
|
return (typeof x === "object" && x != null) || typeof x === "function";
|
||||||
|
}
|
||||||
|
|
||||||
const _resourceBacking = Symbol("[[resourceBacking]]");
|
const _resourceBacking = Symbol("[[resourceBacking]]");
|
||||||
// This distinction exists to prevent unrefable streams being used in
|
// This distinction exists to prevent unrefable streams being used in
|
||||||
// regular fast streams that are unaware of refability
|
// regular fast streams that are unaware of refability
|
||||||
|
@ -5168,22 +5197,21 @@ class ReadableStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
static from(asyncIterable) {
|
static from(asyncIterable) {
|
||||||
const prefix = "Failed to execute 'ReadableStream.from'";
|
|
||||||
webidl.requiredArguments(
|
webidl.requiredArguments(
|
||||||
arguments.length,
|
arguments.length,
|
||||||
1,
|
1,
|
||||||
prefix,
|
"Failed to execute 'ReadableStream.from'",
|
||||||
);
|
);
|
||||||
asyncIterable = webidl.converters["async iterable<any>"](
|
asyncIterable = webidl.converters.any(asyncIterable);
|
||||||
asyncIterable,
|
|
||||||
prefix,
|
const iterator = getAsyncOrSyncIterator(asyncIterable);
|
||||||
"Argument 1",
|
|
||||||
);
|
|
||||||
const iter = asyncIterable.open();
|
|
||||||
|
|
||||||
const stream = createReadableStream(noop, async () => {
|
const stream = createReadableStream(noop, async () => {
|
||||||
// deno-lint-ignore prefer-primordials
|
// deno-lint-ignore prefer-primordials
|
||||||
const res = await iter.next();
|
const res = await iterator.next();
|
||||||
|
if (!isObject(res)) {
|
||||||
|
throw new TypeError("iterator.next value is not an object");
|
||||||
|
}
|
||||||
if (res.done) {
|
if (res.done) {
|
||||||
readableStreamDefaultControllerClose(stream[_controller]);
|
readableStreamDefaultControllerClose(stream[_controller]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5193,8 +5221,17 @@ class ReadableStream {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, async (reason) => {
|
}, async (reason) => {
|
||||||
// deno-lint-ignore prefer-primordials
|
if (iterator.return == null) {
|
||||||
await iter.return(reason);
|
return undefined;
|
||||||
|
} else {
|
||||||
|
// deno-lint-ignore prefer-primordials
|
||||||
|
const res = await iterator.return(reason);
|
||||||
|
if (!isObject(res)) {
|
||||||
|
throw new TypeError("iterator.return value is not an object");
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
@ -6854,10 +6891,6 @@ webidl.converters.StreamPipeOptions = webidl
|
||||||
{ key: "signal", converter: webidl.converters.AbortSignal },
|
{ key: "signal", converter: webidl.converters.AbortSignal },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
webidl.converters["async iterable<any>"] = webidl.createAsyncIterableConverter(
|
|
||||||
webidl.converters.any,
|
|
||||||
);
|
|
||||||
|
|
||||||
internals.resourceForReadableStream = resourceForReadableStream;
|
internals.resourceForReadableStream = resourceForReadableStream;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
@ -26,7 +26,6 @@ const {
|
||||||
Float32Array,
|
Float32Array,
|
||||||
Float64Array,
|
Float64Array,
|
||||||
FunctionPrototypeBind,
|
FunctionPrototypeBind,
|
||||||
FunctionPrototypeCall,
|
|
||||||
Int16Array,
|
Int16Array,
|
||||||
Int32Array,
|
Int32Array,
|
||||||
Int8Array,
|
Int8Array,
|
||||||
|
@ -78,7 +77,6 @@ const {
|
||||||
StringPrototypeToWellFormed,
|
StringPrototypeToWellFormed,
|
||||||
Symbol,
|
Symbol,
|
||||||
SymbolIterator,
|
SymbolIterator,
|
||||||
SymbolAsyncIterator,
|
|
||||||
SymbolToStringTag,
|
SymbolToStringTag,
|
||||||
TypedArrayPrototypeGetBuffer,
|
TypedArrayPrototypeGetBuffer,
|
||||||
TypedArrayPrototypeGetSymbolToStringTag,
|
TypedArrayPrototypeGetSymbolToStringTag,
|
||||||
|
@ -921,127 +919,6 @@ function createSequenceConverter(converter) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAsyncIterator(obj) {
|
|
||||||
if (obj[SymbolAsyncIterator] === undefined) {
|
|
||||||
if (obj[SymbolIterator] === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AsyncIterable = Symbol("[[asyncIterable]]");
|
|
||||||
|
|
||||||
function createAsyncIterableConverter(converter) {
|
|
||||||
return function (
|
|
||||||
V,
|
|
||||||
prefix = undefined,
|
|
||||||
context = undefined,
|
|
||||||
opts = { __proto__: null },
|
|
||||||
) {
|
|
||||||
if (type(V) !== "Object") {
|
|
||||||
throw makeException(
|
|
||||||
TypeError,
|
|
||||||
"can not be converted to async iterable.",
|
|
||||||
prefix,
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let isAsync = true;
|
|
||||||
let method = V[SymbolAsyncIterator];
|
|
||||||
if (method === undefined) {
|
|
||||||
method = V[SymbolIterator];
|
|
||||||
|
|
||||||
if (method === undefined) {
|
|
||||||
throw makeException(
|
|
||||||
TypeError,
|
|
||||||
"is not iterable.",
|
|
||||||
prefix,
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isAsync = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
value: V,
|
|
||||||
[AsyncIterable]: AsyncIterable,
|
|
||||||
open(context) {
|
|
||||||
const iter = FunctionPrototypeCall(method, V);
|
|
||||||
if (type(iter) !== "Object") {
|
|
||||||
throw new TypeError(
|
|
||||||
`${context} could not be iterated because iterator method did not return object, but ${
|
|
||||||
type(iter)
|
|
||||||
}.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let asyncIterator = iter;
|
|
||||||
|
|
||||||
if (!isAsync) {
|
|
||||||
asyncIterator = {
|
|
||||||
// deno-lint-ignore require-await
|
|
||||||
async next() {
|
|
||||||
// deno-lint-ignore prefer-primordials
|
|
||||||
return iter.next();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
async next() {
|
|
||||||
// deno-lint-ignore prefer-primordials
|
|
||||||
const iterResult = await asyncIterator.next();
|
|
||||||
if (type(iterResult) !== "Object") {
|
|
||||||
throw TypeError(
|
|
||||||
`${context} failed to iterate next value because the next() method did not return an object, but ${
|
|
||||||
type(iterResult)
|
|
||||||
}.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iterResult.done) {
|
|
||||||
return { done: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
const iterValue = converter(
|
|
||||||
iterResult.value,
|
|
||||||
`${context} failed to iterate next value`,
|
|
||||||
`The value returned from the next() method`,
|
|
||||||
opts,
|
|
||||||
);
|
|
||||||
|
|
||||||
return { done: false, value: iterValue };
|
|
||||||
},
|
|
||||||
async return(reason) {
|
|
||||||
if (asyncIterator.return === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// deno-lint-ignore prefer-primordials
|
|
||||||
const returnPromiseResult = await asyncIterator.return(reason);
|
|
||||||
if (type(returnPromiseResult) !== "Object") {
|
|
||||||
throw TypeError(
|
|
||||||
`${context} failed to close iterator because the return() method did not return an object, but ${
|
|
||||||
type(returnPromiseResult)
|
|
||||||
}.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
[SymbolAsyncIterator]() {
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createRecordConverter(keyConverter, valueConverter) {
|
function createRecordConverter(keyConverter, valueConverter) {
|
||||||
return (V, prefix, context, opts) => {
|
return (V, prefix, context, opts) => {
|
||||||
if (type(V) !== "Object") {
|
if (type(V) !== "Object") {
|
||||||
|
@ -1410,11 +1287,9 @@ function setlike(obj, objPrototype, readonly) {
|
||||||
|
|
||||||
export {
|
export {
|
||||||
assertBranded,
|
assertBranded,
|
||||||
AsyncIterable,
|
|
||||||
brand,
|
brand,
|
||||||
configureInterface,
|
configureInterface,
|
||||||
converters,
|
converters,
|
||||||
createAsyncIterableConverter,
|
|
||||||
createBranded,
|
createBranded,
|
||||||
createDictionaryConverter,
|
createDictionaryConverter,
|
||||||
createEnumConverter,
|
createEnumConverter,
|
||||||
|
@ -1425,7 +1300,6 @@ export {
|
||||||
createSequenceConverter,
|
createSequenceConverter,
|
||||||
illegalConstructor,
|
illegalConstructor,
|
||||||
invokeCallbackFunction,
|
invokeCallbackFunction,
|
||||||
isAsyncIterator,
|
|
||||||
makeException,
|
makeException,
|
||||||
mixinPairIterable,
|
mixinPairIterable,
|
||||||
requiredArguments,
|
requiredArguments,
|
||||||
|
|
21
ext/webidl/internal.d.ts
vendored
21
ext/webidl/internal.d.ts
vendored
|
@ -438,27 +438,6 @@ declare module "ext:deno_webidl/00_webidl.js" {
|
||||||
opts?: any,
|
opts?: any,
|
||||||
) => T[];
|
) => T[];
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a converter that converts an async iterable of the inner type.
|
|
||||||
*/
|
|
||||||
function createAsyncIterableConverter<V, T>(
|
|
||||||
converter: (
|
|
||||||
v: V,
|
|
||||||
prefix?: string,
|
|
||||||
context?: string,
|
|
||||||
opts?: any,
|
|
||||||
) => T,
|
|
||||||
): (
|
|
||||||
v: any,
|
|
||||||
prefix?: string,
|
|
||||||
context?: string,
|
|
||||||
opts?: any,
|
|
||||||
) => ConvertedAsyncIterable<V, T>;
|
|
||||||
|
|
||||||
interface ConvertedAsyncIterable<V, T> extends AsyncIterableIterator<T> {
|
|
||||||
value: V;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a converter that converts a Promise of the inner type.
|
* Create a converter that converts a Promise of the inner type.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -72,7 +72,6 @@ util::unit_test_factory!(
|
||||||
dgram_test,
|
dgram_test,
|
||||||
domain_test,
|
domain_test,
|
||||||
fs_test,
|
fs_test,
|
||||||
fetch_test,
|
|
||||||
http_test,
|
http_test,
|
||||||
http2_test,
|
http2_test,
|
||||||
inspector_test,
|
inspector_test,
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
import {
|
import { assertEquals, assertRejects, fail } from "./test_util.ts";
|
||||||
assertEquals,
|
|
||||||
assertRejects,
|
|
||||||
assertThrows,
|
|
||||||
fail,
|
|
||||||
} from "./test_util.ts";
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
core,
|
core,
|
||||||
|
@ -538,11 +533,3 @@ Deno.test(async function decompressionStreamInvalidGzipStillReported() {
|
||||||
"corrupt gzip stream does not have a matching checksum",
|
"corrupt gzip stream does not have a matching checksum",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test(function readableStreamFromWithStringThrows() {
|
|
||||||
assertThrows(
|
|
||||||
() => ReadableStream.from("string"),
|
|
||||||
TypeError,
|
|
||||||
"Failed to execute 'ReadableStream.from': Argument 1 can not be converted to async iterable.",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
import { assertEquals } from "@std/assert";
|
|
||||||
import { createReadStream } from "node:fs";
|
|
||||||
|
|
||||||
Deno.test("fetch node stream", async () => {
|
|
||||||
const file = createReadStream("tests/testdata/assets/fixture.json");
|
|
||||||
|
|
||||||
const response = await fetch("http://localhost:4545/echo_server", {
|
|
||||||
method: "POST",
|
|
||||||
body: file,
|
|
||||||
});
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
await response.text(),
|
|
||||||
await Deno.readTextFile("tests/testdata/assets/fixture.json"),
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -4007,14 +4007,8 @@
|
||||||
"owning-type-message-port.any.worker.html": false,
|
"owning-type-message-port.any.worker.html": false,
|
||||||
"owning-type.any.html": false,
|
"owning-type.any.html": false,
|
||||||
"owning-type.any.worker.html": false,
|
"owning-type.any.worker.html": false,
|
||||||
"from.any.html": [
|
"from.any.html": true,
|
||||||
"ReadableStream.from ignores a null @@asyncIterator",
|
"from.any.worker.html": true
|
||||||
"ReadableStream.from accepts a string"
|
|
||||||
],
|
|
||||||
"from.any.worker.html": [
|
|
||||||
"ReadableStream.from ignores a null @@asyncIterator",
|
|
||||||
"ReadableStream.from accepts a string"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"transform-streams": {
|
"transform-streams": {
|
||||||
"backpressure.any.html": true,
|
"backpressure.any.html": true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue