fix(streams): strictly define toJson() and toText() input (#5517)

* fix(streams): strictly define `toJson()` and `toText()` input

* fix
This commit is contained in:
Asher Gomez 2024-07-23 13:23:35 +10:00 committed by GitHub
parent f1ee8ac2c6
commit a04a2ed798
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 60 additions and 40 deletions

View File

@ -4,14 +4,16 @@
import { toText } from "./to_text.ts";
/**
* Converts a JSON-formatted {@linkcode ReadableSteam} of strings or
* {@linkcode Uint8Array}s to an object. Works the same as
* {@linkcode Response.json}.
* Converts a
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON}-formatted
* {@linkcode ReadableSteam} of strings or {@linkcode Uint8Array}s to an object.
* Works the same as {@linkcode Response.json} and {@linkcode Request.json}, but
* also extends to support streams of strings.
*
* @param readableStream A `ReadableStream` whose chunks compose a JSON.
* @param stream A `ReadableStream` whose chunks compose a JSON.
* @returns A promise that resolves to the parsed JSON.
*
* @example Basic usage
* @example Usage with a stream of strings
* ```ts
* import { toJson } from "@std/streams/to-json";
* import { assertEquals } from "@std/assert";
@ -21,12 +23,24 @@ import { toText } from "./to_text.ts";
* ', [], {}, "hello',
* '", null]',
* ]);
* const json = await toJson(stream);
* assertEquals(json, [1, true, [], {}, "hello", null]);
* assertEquals(await toJson(stream), [1, true, [], {}, "hello", null]);
* ```
*
* @example Usage with a stream of `Uint8Array`s
* ```ts
* import { toJson } from "@std/streams/to-json";
* import { assertEquals } from "@std/assert";
*
* const stream = ReadableStream.from([
* "[1, true",
* ', [], {}, "hello',
* '", null]',
* ]).pipeThrough(new TextEncoderStream());
* assertEquals(await toJson(stream), [1, true, [], {}, "hello", null]);
* ```
*/
export function toJson(
readableStream: ReadableStream,
stream: ReadableStream<string> | ReadableStream<Uint8Array>,
): Promise<unknown> {
return toText(readableStream).then(JSON.parse);
return toText(stream).then(JSON.parse);
}

View File

@ -4,20 +4,24 @@ import { assertEquals } from "@std/assert";
import { toJson } from "./to_json.ts";
Deno.test("toJson()", async () => {
const byteStream = ReadableStream.from(["[", "1, 2, 3, 4", "]"])
.pipeThrough(new TextEncoderStream());
assertEquals(await toJson(byteStream), [1, 2, 3, 4]);
const stringStream = ReadableStream.from([
const strings = [
"[",
"1, 2, 3, 4,",
'{ "a": 2,',
' "b": 3,',
' "c": 4 }',
]);
assertEquals(await toJson(stringStream), {
"]",
];
const expected = [1, 2, 3, 4, {
a: 2,
b: 3,
c: 4,
});
}];
const byteStream = ReadableStream.from(strings)
.pipeThrough(new TextEncoderStream());
assertEquals(await toJson(byteStream), expected);
const stringStream = ReadableStream.from(strings);
assertEquals(await toJson(stringStream), expected);
});

View File

@ -3,12 +3,13 @@
/**
* Converts a {@linkcode ReadableSteam} of strings or {@linkcode Uint8Array}s
* to a single string. Works the same as {@linkcode Response.text}.
* to a single string. Works the same as {@linkcode Response.text} and
* {@linkcode Request.text}, but also extends to support streams of strings.
*
* @param readableStream A `ReadableStream` to convert into a `string`.
* @param stream A `ReadableStream` to convert into a `string`.
* @returns A `Promise` that resolves to the `string`.
*
* @example Basic usage
* @example Basic usage with a stream of strings
* ```ts
* import { toText } from "@std/streams/to-text";
* import { assertEquals } from "@std/assert";
@ -16,12 +17,22 @@
* const stream = ReadableStream.from(["Hello, ", "world!"]);
* assertEquals(await toText(stream), "Hello, world!");
* ```
*
* @example Basic usage with a stream of `Uint8Array`s
* ```ts
* import { toText } from "@std/streams/to-text";
* import { assertEquals } from "@std/assert";
*
* const stream = ReadableStream.from(["Hello, ", "world!"])
* .pipeThrough(new TextEncoderStream());
* assertEquals(await toText(stream), "Hello, world!");
* ```
*/
export async function toText(
readableStream: ReadableStream,
stream: ReadableStream<string> | ReadableStream<Uint8Array>,
): Promise<string> {
const textDecoder = new TextDecoder();
const reader = readableStream.getReader();
const reader = stream.getReader();
let result = "";
while (true) {

View File

@ -4,22 +4,13 @@ import { assertEquals } from "@std/assert";
import { toText } from "./to_text.ts";
Deno.test("toText()", async () => {
const byteStream = ReadableStream.from(["hello", " js ", "fans"])
const strings = ["hello", " js ", "fans", " 中文♥"];
const expected = "hello js fans 中文♥";
const byteStream = ReadableStream.from(strings)
.pipeThrough(new TextEncoderStream());
assertEquals(await toText(byteStream), expected);
assertEquals(await toText(byteStream), "hello js fans");
const stringStream = ReadableStream.from(["hello", " deno ", "world"]);
assertEquals(await toText(stringStream), "hello deno world");
const utf8ByteStream = new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array([228, 184, 173, 230, 150]));
controller.enqueue(new Uint8Array([135]));
controller.close();
},
});
assertEquals(await toText(utf8ByteStream), "中文");
const stringStream = ReadableStream.from(strings);
assertEquals(await toText(stringStream), expected);
});