Skip to content

Commit

Permalink
fix(io): fix readAllSync for the case when read source is slow (#6355)
Browse files Browse the repository at this point in the history
  • Loading branch information
kt3k authored Jan 22, 2025
1 parent 5af091b commit 8e64d00
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
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);
}
});

0 comments on commit 8e64d00

Please sign in to comment.