From 74be01273c16b83b1063da1750045b12e095f0c3 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 17 Oct 2022 18:57:31 -0400 Subject: [PATCH] chore: upgrade internal deno_std to 0.160 (#16333) --- cli/tests/testdata/run/textproto.ts | 173 +++++++++++++++++++++++ cli/tests/testdata/run/tls_connecttls.js | 6 +- cli/tests/testdata/run/tls_starttls.js | 6 +- cli/tests/unit/files_test.ts | 2 +- cli/tests/unit/flash_test.ts | 8 +- cli/tests/unit/http_test.ts | 10 +- cli/tests/unit/read_file_test.ts | 14 +- cli/tests/unit/read_text_file_test.ts | 14 +- cli/tests/unit/test_util.ts | 2 +- cli/tests/unit/tls_test.ts | 10 +- test_util/std | 2 +- 11 files changed, 206 insertions(+), 41 deletions(-) create mode 100644 cli/tests/testdata/run/textproto.ts diff --git a/cli/tests/testdata/run/textproto.ts b/cli/tests/testdata/run/textproto.ts new file mode 100644 index 0000000000..ff13bfe475 --- /dev/null +++ b/cli/tests/testdata/run/textproto.ts @@ -0,0 +1,173 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/** **Deprecated**. Use `TextLineStream` from `std/steams` for line-by-line text reading instead. + * + * A reader for dealing with low level text based protocols. + * + * Based on + * [net/textproto](https://github.com/golang/go/tree/master/src/net/textproto). + * + * @deprecated (will be removed after 0.159.0) Use `TextLineStream` from `std/steams` for line-by-line text reading instead. + * @module + */ + +import type { + BufReader, + ReadLineResult, +} from "../../../../test_util/std/io/buffer.ts"; +import { concat } from "../../../../test_util/std/bytes/mod.ts"; + +// Constants created for DRY +const CHAR_SPACE: number = " ".charCodeAt(0); +const CHAR_TAB: number = "\t".charCodeAt(0); +const CHAR_COLON: number = ":".charCodeAt(0); + +const WHITESPACES: Array = [CHAR_SPACE, CHAR_TAB]; + +const decoder = new TextDecoder(); + +// FROM https://github.com/denoland/deno/blob/b34628a26ab0187a827aa4ebe256e23178e25d39/cli/js/web/headers.ts#L9 +const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/g; + +function str(buf: Uint8Array | null | undefined): string { + return !buf ? "" : decoder.decode(buf); +} + +/** + * @deprecated (will be removed after 0.159.0) Use `TextLineStream` from `std/steams` for line-by-line text reading instead. + */ +export class TextProtoReader { + constructor(readonly r: BufReader) {} + + /** readLine() reads a single line from the TextProtoReader, + * eliding the final \n or \r\n from the returned string. + */ + async readLine(): Promise { + const s = await this.readLineSlice(); + return s === null ? null : str(s); + } + + /** ReadMimeHeader reads a MIME-style header from r. + * The header is a sequence of possibly continued Key: Value lines + * ending in a blank line. + * The returned map m maps CanonicalMIMEHeaderKey(key) to a + * sequence of values in the same order encountered in the input. + * + * For example, consider this input: + * + * My-Key: Value 1 + * Long-Key: Even + * Longer Value + * My-Key: Value 2 + * + * Given that input, ReadMIMEHeader returns the map: + * + * map[string][]string{ + * "My-Key": {"Value 1", "Value 2"}, + * "Long-Key": {"Even Longer Value"}, + * } + */ + async readMimeHeader(): Promise { + const m = new Headers(); + let line: Uint8Array | undefined; + + // The first line cannot start with a leading space. + let buf = await this.r.peek(1); + if (buf === null) { + return null; + } else if (WHITESPACES.includes(buf[0])) { + line = (await this.readLineSlice()) as Uint8Array; + } + + buf = await this.r.peek(1); + if (buf === null) { + throw new Deno.errors.UnexpectedEof(); + } else if (WHITESPACES.includes(buf[0])) { + throw new Deno.errors.InvalidData( + `malformed MIME header initial line: ${str(line)}`, + ); + } + + while (true) { + const kv = await this.readLineSlice(); // readContinuedLineSlice + if (kv === null) throw new Deno.errors.UnexpectedEof(); + if (kv.byteLength === 0) return m; + + // Key ends at first colon + let i = kv.indexOf(CHAR_COLON); + if (i < 0) { + throw new Deno.errors.InvalidData( + `malformed MIME header line: ${str(kv)}`, + ); + } + + //let key = canonicalMIMEHeaderKey(kv.subarray(0, endKey)); + const key = str(kv.subarray(0, i)); + + // As per RFC 7230 field-name is a token, + // tokens consist of one or more chars. + // We could throw `Deno.errors.InvalidData` here, + // but better to be liberal in what we + // accept, so if we get an empty key, skip it. + if (key == "") { + continue; + } + + // Skip initial spaces in value. + i++; // skip colon + while ( + i < kv.byteLength && + (WHITESPACES.includes(kv[i])) + ) { + i++; + } + const value = str(kv.subarray(i)).replace( + invalidHeaderCharRegex, + encodeURI, + ); + + // In case of invalid header we swallow the error + // example: "Audio Mode" => invalid due to space in the key + try { + m.append(key, value); + } catch { + // Pass + } + } + } + + async readLineSlice(): Promise { + let line = new Uint8Array(0); + let r: ReadLineResult | null = null; + + do { + r = await this.r.readLine(); + // TODO(ry): + // This skipSpace() is definitely misplaced, but I don't know where it + // comes from nor how to fix it. + + //TODO(SmashingQuasar): Kept skipSpace to preserve behavior but it should be looked into to check if it makes sense when this is used. + + if (r !== null && this.skipSpace(r.line) !== 0) { + line = concat(line, r.line); + } + } while (r !== null && r.more); + + return r === null ? null : line; + } + + skipSpace(l: Uint8Array): number { + let n = 0; + + for (const val of l) { + if (!WHITESPACES.includes(val)) { + n++; + } + } + + return n; + } +} diff --git a/cli/tests/testdata/run/tls_connecttls.js b/cli/tests/testdata/run/tls_connecttls.js index fb38399684..aea60151a7 100644 --- a/cli/tests/testdata/run/tls_connecttls.js +++ b/cli/tests/testdata/run/tls_connecttls.js @@ -3,8 +3,8 @@ import { assert, assertEquals, } from "../../../../test_util/std/testing/asserts.ts"; -import { BufReader, BufWriter } from "../../../../test_util/std/io/bufio.ts"; -import { TextProtoReader } from "../../../../test_util/std/textproto/mod.ts"; +import { BufReader, BufWriter } from "../../../../test_util/std/io/buffer.ts"; +import { TextProtoReader } from "./textproto.ts"; const encoder = new TextEncoder(); const decoder = new TextDecoder(); @@ -57,7 +57,7 @@ const [_, proto, status, ok] = m; assertEquals(proto, "HTTP/1.1"); assertEquals(status, "200"); assertEquals(ok, "OK"); -const headers = await tpr.readMIMEHeader(); +const headers = await tpr.readMimeHeader(); assert(headers !== null); const contentLength = parseInt(headers.get("content-length")); const bodyBuf = new Uint8Array(contentLength); diff --git a/cli/tests/testdata/run/tls_starttls.js b/cli/tests/testdata/run/tls_starttls.js index 7aa4365127..86bba7938f 100644 --- a/cli/tests/testdata/run/tls_starttls.js +++ b/cli/tests/testdata/run/tls_starttls.js @@ -3,8 +3,8 @@ import { assert, assertEquals, } from "../../../../test_util/std/testing/asserts.ts"; -import { BufReader, BufWriter } from "../../../../test_util/std/io/bufio.ts"; -import { TextProtoReader } from "../../../../test_util/std/textproto/mod.ts"; +import { BufReader, BufWriter } from "../../../../test_util/std/io/buffer.ts"; +import { TextProtoReader } from "./textproto.ts"; const encoder = new TextEncoder(); const decoder = new TextDecoder(); @@ -55,7 +55,7 @@ const [_, proto, status, ok] = m; assertEquals(proto, "HTTP/1.1"); assertEquals(status, "200"); assertEquals(ok, "OK"); -const headers = await tpr.readMIMEHeader(); +const headers = await tpr.readMimeHeader(); assert(headers !== null); const contentLength = parseInt(headers.get("content-length")); const bodyBuf = new Uint8Array(contentLength); diff --git a/cli/tests/unit/files_test.ts b/cli/tests/unit/files_test.ts index bb095072ce..e5d3a96a7e 100644 --- a/cli/tests/unit/files_test.ts +++ b/cli/tests/unit/files_test.ts @@ -8,7 +8,7 @@ import { assertRejects, assertThrows, } from "./test_util.ts"; -import { copy } from "../../../test_util/std/io/util.ts"; +import { copy } from "../../../test_util/std/streams/conversion.ts"; Deno.test(function filesStdioFileDescriptors() { assertEquals(Deno.stdin.rid, 0); diff --git a/cli/tests/unit/flash_test.ts b/cli/tests/unit/flash_test.ts index a5a31a136f..375fdb8f36 100644 --- a/cli/tests/unit/flash_test.ts +++ b/cli/tests/unit/flash_test.ts @@ -7,7 +7,7 @@ import { BufReader, BufWriter, } from "../../../test_util/std/io/buffer.ts"; -import { TextProtoReader } from "../../../test_util/std/textproto/mod.ts"; +import { TextProtoReader } from "../testdata/run/textproto.ts"; import { assert, assertEquals, @@ -763,7 +763,7 @@ Deno.test( const tpr = new TextProtoReader(r); const statusLine = await tpr.readLine(); assert(statusLine !== null); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); const chunkedReader = chunkedBodyReader(headers, r); @@ -920,7 +920,7 @@ Deno.test( assert(m !== null, "must be matched"); const [_, _proto, status, _ok] = m; assertEquals(status, "200"); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); } @@ -2342,7 +2342,7 @@ async function readTrailers( if (trailers == null) return; const trailerNames = [...trailers.keys()]; const tp = new TextProtoReader(r); - const result = await tp.readMIMEHeader(); + const result = await tp.readMimeHeader(); if (result == null) { throw new Deno.errors.InvalidData("Missing trailer header."); } diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index 7bb16aecc5..63eae3ace6 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -4,7 +4,7 @@ import { BufReader, BufWriter, } from "../../../test_util/std/io/buffer.ts"; -import { TextProtoReader } from "../../../test_util/std/textproto/mod.ts"; +import { TextProtoReader } from "../testdata/run/textproto.ts"; import { serve, serveTls } from "../../../test_util/std/http/server.ts"; import { assert, @@ -30,7 +30,7 @@ async function writeRequestAndReadResponse(conn: Deno.Conn): Promise { const tpr = new TextProtoReader(r); const statusLine = await tpr.readLine(); assert(statusLine !== null); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); const chunkedReader = chunkedBodyReader(headers, r); @@ -605,7 +605,7 @@ Deno.test( const tpr = new TextProtoReader(r); const statusLine = await tpr.readLine(); assert(statusLine !== null); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); const chunkedReader = chunkedBodyReader(headers, r); @@ -751,7 +751,7 @@ Deno.test( assert(m !== null, "must be matched"); const [_, _proto, status, _ok] = m; assertEquals(status, "200"); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); } @@ -2459,7 +2459,7 @@ async function readTrailers( if (trailers == null) return; const trailerNames = [...trailers.keys()]; const tp = new TextProtoReader(r); - const result = await tp.readMIMEHeader(); + const result = await tp.readMimeHeader(); if (result == null) { throw new Deno.errors.InvalidData("Missing trailer header."); } diff --git a/cli/tests/unit/read_file_test.ts b/cli/tests/unit/read_file_test.ts index c18cdf0590..888021edaa 100644 --- a/cli/tests/unit/read_file_test.ts +++ b/cli/tests/unit/read_file_test.ts @@ -95,17 +95,15 @@ Deno.test( async function readFileWithAbortSignal() { const ac = new AbortController(); queueMicrotask(() => ac.abort()); - await assertRejects( + const error = await assertRejects( async () => { await Deno.readFile("cli/tests/testdata/assets/fixture.json", { signal: ac.signal, }); }, - (error: Error) => { - assert(error instanceof DOMException); - assertEquals(error.name, "AbortError"); - }, ); + assert(error instanceof DOMException); + assertEquals(error.name, "AbortError"); }, ); @@ -115,16 +113,14 @@ Deno.test( const ac = new AbortController(); const abortReason = new Error(); queueMicrotask(() => ac.abort(abortReason)); - await assertRejects( + const error = await assertRejects( async () => { await Deno.readFile("cli/tests/testdata/assets/fixture.json", { signal: ac.signal, }); }, - (error: Error) => { - assertEquals(error, abortReason); - }, ); + assertEquals(error, abortReason); }, ); diff --git a/cli/tests/unit/read_text_file_test.ts b/cli/tests/unit/read_text_file_test.ts index 119c650b60..5e455c5832 100644 --- a/cli/tests/unit/read_text_file_test.ts +++ b/cli/tests/unit/read_text_file_test.ts @@ -91,17 +91,15 @@ Deno.test( async function readTextFileWithAbortSignal() { const ac = new AbortController(); queueMicrotask(() => ac.abort()); - await assertRejects( + const error = await assertRejects( async () => { await Deno.readFile("cli/tests/testdata/assets/fixture.json", { signal: ac.signal, }); }, - (error: Error) => { - assert(error instanceof DOMException); - assertEquals(error.name, "AbortError"); - }, ); + assert(error instanceof DOMException); + assertEquals(error.name, "AbortError"); }, ); @@ -111,16 +109,14 @@ Deno.test( const ac = new AbortController(); const abortReason = new Error(); queueMicrotask(() => ac.abort(abortReason)); - await assertRejects( + const error = await assertRejects( async () => { await Deno.readFile("cli/tests/testdata/assets/fixture.json", { signal: ac.signal, }); }, - (error: Error) => { - assertEquals(error, abortReason); - }, ); + assertEquals(error, abortReason); }, ); diff --git a/cli/tests/unit/test_util.ts b/cli/tests/unit/test_util.ts index 19cad092d1..c33da53388 100644 --- a/cli/tests/unit/test_util.ts +++ b/cli/tests/unit/test_util.ts @@ -20,7 +20,7 @@ export { export { deferred } from "../../../test_util/std/async/deferred.ts"; export type { Deferred } from "../../../test_util/std/async/deferred.ts"; export { delay } from "../../../test_util/std/async/delay.ts"; -export { readLines } from "../../../test_util/std/io/bufio.ts"; +export { readLines } from "../../../test_util/std/io/buffer.ts"; export { parse as parseArgs } from "../../../test_util/std/flags/mod.ts"; export function pathToAbsoluteFileUrl(path: string): URL { diff --git a/cli/tests/unit/tls_test.ts b/cli/tests/unit/tls_test.ts index a5b87239a6..cf335de499 100644 --- a/cli/tests/unit/tls_test.ts +++ b/cli/tests/unit/tls_test.ts @@ -9,9 +9,9 @@ import { Deferred, deferred, } from "./test_util.ts"; -import { BufReader, BufWriter } from "../../../test_util/std/io/bufio.ts"; -import { readAll } from "../../../test_util/std/io/util.ts"; -import { TextProtoReader } from "../../../test_util/std/textproto/mod.ts"; +import { BufReader, BufWriter } from "../../../test_util/std/io/buffer.ts"; +import { readAll } from "../../../test_util/std/streams/conversion.ts"; +import { TextProtoReader } from "../testdata/run/textproto.ts"; const encoder = new TextEncoder(); const decoder = new TextDecoder(); @@ -195,7 +195,7 @@ Deno.test( assertEquals(proto, "HTTP/1.1"); assertEquals(status, "200"); assertEquals(ok, "OK"); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); const contentLength = parseInt(headers.get("content-length")!); const bodyBuf = new Uint8Array(contentLength); @@ -248,7 +248,7 @@ Deno.test( assertEquals(proto, "HTTP/1.1"); assertEquals(status, "200"); assertEquals(ok, "OK"); - const headers = await tpr.readMIMEHeader(); + const headers = await tpr.readMimeHeader(); assert(headers !== null); const contentLength = parseInt(headers.get("content-length")!); const bodyBuf = new Uint8Array(contentLength); diff --git a/test_util/std b/test_util/std index 28956f7957..0ce558fec1 160000 --- a/test_util/std +++ b/test_util/std @@ -1 +1 @@ -Subproject commit 28956f795762e8dd9b6213687ce32665319fa98a +Subproject commit 0ce558fec1a1beeda3ed7710c6507b9e991829c9