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

fix(io): fix readAllSync for the case when read source is slow #6355

Merged
merged 3 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion async/unstable_wait_for.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// Copyright 2018-2025 the Deno authors. MIT license.
// This module is browser compatible.

import { deadline } from "./deadline.ts";
Expand Down
2 changes: 1 addition & 1 deletion async/unstable_wait_for_test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// Copyright 2018-2025 the Deno authors. MIT license.
import { assertAlmostEquals, assertEquals, assertRejects } from "@std/assert";
import { waitFor } from "./unstable_wait_for.ts";

Expand Down
5 changes: 2 additions & 3 deletions io/read_all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,13 @@ export async function readAll(reader: Reader): Promise<Uint8Array> {
export function readAllSync(reader: ReaderSync): Uint8Array {
const chunks: Uint8Array[] = [];
while (true) {
const chunk = new Uint8Array(DEFAULT_CHUNK_SIZE);
let chunk = new Uint8Array(DEFAULT_CHUNK_SIZE);
const n = reader.readSync(chunk);
if (n === null) {
break;
}
if (n < DEFAULT_CHUNK_SIZE) {
chunks.push(chunk.subarray(0, n));
break;
chunk = chunk.subarray(0, n);
}
chunks.push(chunk);
}
Expand Down
44 changes: 44 additions & 0 deletions io/read_all_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { assert, assertEquals } from "@std/assert";
import { readAll, readAllSync } from "./read_all.ts";
import { Buffer } from "./buffer.ts";
import { init } from "./_test_common.ts";
import type { Reader, ReaderSync } from "./types.ts";

Deno.test("readAll()", async () => {
const testBytes = init();
Expand All @@ -20,3 +21,46 @@ Deno.test("readAllSync()", () => {
const actualBytes = readAllSync(reader);
assertEquals(testBytes, actualBytes);
});

Deno.test("readAll() and readAllSync() can read slow buffer correctly", async () => {
class SlowBuffer implements Reader, ReaderSync {
#remaining: Uint8Array;

constructor(bytes: Uint8Array) {
this.#remaining = bytes;
}

// deno-lint-ignore require-await -- implementing `Reader` interface
async read(p: Uint8Array): Promise<number | null> {
return this.readSync(p);
}

readSync(p: Uint8Array): number | null {
if (p.length === 0) {
throw new TypeError("p is empty");
}
const remaining = this.#remaining;
if (remaining.length === 0) {
// no more bytes to read; signal end-of-stream
return null;
}
// read one byte at a time
p.set(remaining.subarray(0, 1));
this.#remaining = remaining.subarray(1);
return 1;
}
}

{
const testBytes = crypto.getRandomValues(new Uint8Array(20));
const reader = new SlowBuffer(testBytes);
const actualBytes = await readAll(reader);
assertEquals(actualBytes, testBytes);
}
{
const testBytes = crypto.getRandomValues(new Uint8Array(20));
const reader = new SlowBuffer(testBytes);
const actualBytes = readAllSync(reader);
assertEquals(actualBytes, testBytes);
}
});
Loading