fix: Use Deno.errors where possible. (denoland/deno#4356)

This commit is contained in:
Oliver Lenehan 2020-03-14 12:40:13 +11:00 committed by denobot
parent 0f3300ba8f
commit 9986475ca1
13 changed files with 71 additions and 86 deletions

View File

@ -1,7 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { UnexpectedEOFError } from "../io/bufio.ts";
type RawBaseTypes = "int8" | "int16" | "int32" | "uint8" | "uint16" | "uint32";
type RawNumberTypes = RawBaseTypes | "float32" | "float64";
type RawBigTypes = RawBaseTypes | "int64" | "uint64";
@ -46,14 +44,14 @@ export function sizeof(dataType: RawTypes): number {
/** Reads `n` bytes from `r`.
*
* Returns it in a `Uint8Array`, or throws `UnexpectedEOFError` if `n` bytes cannot be read. */
* Returns it in a `Uint8Array`, or throws `Deno.errors.UnexpectedEof` if `n` bytes cannot be read. */
export async function getNBytes(
r: Deno.Reader,
n: number
): Promise<Uint8Array> {
const scratch = new Uint8Array(n);
const nRead = await r.read(scratch);
if (nRead === Deno.EOF || nRead < n) throw new UnexpectedEOFError();
if (nRead === Deno.EOF || nRead < n) throw new Deno.errors.UnexpectedEof();
return scratch;
}
@ -199,7 +197,7 @@ export function putVarbig(
/** Reads a number from `r`, comsuming `sizeof(o.dataType)` bytes. Data-type defaults to `int32`.
*
* Returns it as `number`, or throws `UnexpectedEOFError` if not enough bytes can be read. */
* Returns it as `number`, or throws `Deno.errors.UnexpectedEof` if not enough bytes can be read. */
export async function readVarnum(
r: Deno.Reader,
o: VarnumOptions = {}
@ -211,7 +209,7 @@ export async function readVarnum(
/** Reads an integer from `r`, comsuming `sizeof(o.dataType)` bytes. Data-type defaults to `int64`.
*
* Returns it as `bigint`, or throws `UnexpectedEOFError` if not enough bytes can be read. */
* Returns it as `bigint`, or throws `Deno.errors.UnexpectedEof` if not enough bytes can be read. */
export async function readVarbig(
r: Deno.Reader,
o: VarbigOptions = {}

View File

@ -1,7 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assertEquals, assertThrowsAsync } from "../testing/asserts.ts";
import { UnexpectedEOFError } from "../io/bufio.ts";
import {
getNBytes,
putVarbig,
@ -27,7 +26,7 @@ Deno.test(async function testGetNBytesThrows(): Promise<void> {
const buff = new Deno.Buffer(data.buffer);
assertThrowsAsync(async () => {
await getNBytes(buff, 8);
}, UnexpectedEOFError);
}, Deno.errors.UnexpectedEof);
});
Deno.test(async function testPutVarbig(): Promise<void> {

View File

@ -1,4 +1,4 @@
import { BufReader, UnexpectedEOFError, BufWriter } from "../io/bufio.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { assert } from "../testing/asserts.ts";
import { encoder } from "../strings/mod.ts";
@ -57,13 +57,13 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
chunks.shift();
// Consume \r\n;
if ((await tp.readLine()) === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
}
return readLength;
}
const line = await tp.readLine();
if (line === Deno.EOF) throw new UnexpectedEOFError();
if (line === Deno.EOF) throw new Deno.errors.UnexpectedEof();
// TODO: handle chunk extension
const [chunkSizeString] = line.split(";");
const chunkSize = parseInt(chunkSizeString, 16);
@ -74,12 +74,12 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
if (chunkSize > buf.byteLength) {
let eof = await r.readFull(buf);
if (eof === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
const restChunk = new Uint8Array(chunkSize - buf.byteLength);
eof = await r.readFull(restChunk);
if (eof === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
} else {
chunks.push({
offset: 0,
@ -91,11 +91,11 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
const bufToFill = buf.subarray(0, chunkSize);
const eof = await r.readFull(bufToFill);
if (eof === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
// Consume \r\n
if ((await tp.readLine()) === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
return chunkSize;
}
@ -103,7 +103,7 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
assert(chunkSize === 0);
// Consume \r\n
if ((await r.readLine()) === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
await readTrailers(h, r);
finished = true;
@ -348,7 +348,7 @@ export async function readRequest(
const firstLine = await tp.readLine(); // e.g. GET /index.html HTTP/1.0
if (firstLine === Deno.EOF) return Deno.EOF;
const headers = await tp.readMIMEHeader();
if (headers === Deno.EOF) throw new UnexpectedEOFError();
if (headers === Deno.EOF) throw new Deno.errors.UnexpectedEof();
const req = new ServerRequest();
req.conn = conn;

View File

@ -15,7 +15,7 @@ import {
writeResponse
} from "./io.ts";
import { encode, decode } from "../strings/mod.ts";
import { BufReader, UnexpectedEOFError, ReadLineResult } from "../io/bufio.ts";
import { BufReader, ReadLineResult } from "../io/bufio.ts";
import { chunkedBodyReader } from "./io.ts";
import { ServerRequest, Response } from "./server.ts";
import { StringReader } from "../io/readers.ts";
@ -369,7 +369,7 @@ test(async function testReadRequestError(): Promise<void> {
},
{
in: "GET / HTTP/1.1\r\nheader:foo\r\n",
err: UnexpectedEOFError
err: Deno.errors.UnexpectedEof
},
{ in: "", err: Deno.EOF },
{
@ -437,7 +437,7 @@ test(async function testReadRequestError(): Promise<void> {
} else if (typeof test.err === "string") {
assertEquals(err.message, test.err);
} else if (test.err) {
assert(err instanceof (test.err as typeof UnexpectedEOFError));
assert(err instanceof (test.err as typeof Deno.errors.UnexpectedEof));
} else {
assert(req instanceof ServerRequest);
assert(test.headers);

View File

@ -21,11 +21,11 @@ export class BufferFullError extends Error {
}
}
export class UnexpectedEOFError extends Error {
name = "UnexpectedEOFError";
export class PartialReadError extends Deno.errors.UnexpectedEof {
name = "PartialReadError";
partial?: Uint8Array;
constructor() {
super("Unexpected EOF");
super("Encountered UnexpectedEof, data only partially read");
}
}
@ -178,7 +178,7 @@ export class BufReader implements Reader {
if (bytesRead === 0) {
return Deno.EOF;
} else {
throw new UnexpectedEOFError();
throw new PartialReadError();
}
}
bytesRead += rr;

View File

@ -15,7 +15,7 @@ import {
BufReader,
BufWriter,
BufferFullError,
UnexpectedEOFError,
PartialReadError,
readStringDelim,
readLines
} from "./bufio.ts";
@ -369,9 +369,9 @@ Deno.test(async function bufReaderReadFull(): Promise<void> {
const buf = new Uint8Array(6);
try {
await bufr.readFull(buf);
fail("readFull() should throw");
fail("readFull() should throw PartialReadError");
} catch (err) {
assert(err instanceof UnexpectedEOFError);
assert(err instanceof PartialReadError);
assert(err.partial instanceof Uint8Array);
assertEquals(err.partial.length, 5);
assertEquals(dec.decode(buf.subarray(0, 5)), "World");

View File

@ -36,14 +36,7 @@ export class HalfReader implements Reader {
}
}
export class ErrTimeout extends Error {
constructor() {
super("timeout");
this.name = "ErrTimeout";
}
}
/** TimeoutReader returns ErrTimeout on the second read
/** TimeoutReader returns `Deno.errors.TimedOut` on the second read
* with no data. Subsequent calls to read succeed.
*/
export class TimeoutReader implements Reader {
@ -53,7 +46,7 @@ export class TimeoutReader implements Reader {
async read(p: Uint8Array): Promise<number | Deno.EOF> {
this.count++;
if (this.count === 2) {
throw new ErrTimeout();
throw new Deno.errors.TimedOut();
}
return this.r.read(p);
}

View File

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { BufReader, UnexpectedEOFError } from "./bufio.ts";
import { BufReader } from "./bufio.ts";
type Reader = Deno.Reader;
type Writer = Deno.Writer;
import { assert } from "../testing/asserts.ts";
@ -37,7 +37,7 @@ export async function readShort(buf: BufReader): Promise<number | Deno.EOF> {
const high = await buf.readByte();
if (high === Deno.EOF) return Deno.EOF;
const low = await buf.readByte();
if (low === Deno.EOF) throw new UnexpectedEOFError();
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
return (high << 8) | low;
}
@ -46,7 +46,7 @@ export async function readInt(buf: BufReader): Promise<number | Deno.EOF> {
const high = await readShort(buf);
if (high === Deno.EOF) return Deno.EOF;
const low = await readShort(buf);
if (low === Deno.EOF) throw new UnexpectedEOFError();
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
return (high << 16) | low;
}
@ -57,7 +57,7 @@ export async function readLong(buf: BufReader): Promise<number | Deno.EOF> {
const high = await readInt(buf);
if (high === Deno.EOF) return Deno.EOF;
const low = await readInt(buf);
if (low === Deno.EOF) throw new UnexpectedEOFError();
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
const big = (BigInt(high) << 32n) | BigInt(low);
// We probably should provide a similar API that returns BigInt values.
if (big > MAX_SAFE_INTEGER) {

View File

@ -10,7 +10,7 @@ import { copyN } from "../io/ioutil.ts";
import { MultiReader } from "../io/readers.ts";
import { extname } from "../path/mod.ts";
import { tempFile } from "../io/util.ts";
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { encoder } from "../strings/mod.ts";
import { assertStrictEq, assert } from "../testing/asserts.ts";
import { TextProtoReader } from "../textproto/mod.ts";
@ -166,7 +166,7 @@ class PartReader implements Reader, Closer {
peekLength = max(peekLength, br.buffered());
const peekBuf = await br.peek(peekLength);
if (peekBuf === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
const eof = peekBuf.length < peekLength;
this.n = scanUntilBoundary(
@ -352,14 +352,14 @@ export class MultipartReader {
for (;;) {
const line = await this.bufReader.readSlice("\n".charCodeAt(0));
if (line === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
if (this.isBoundaryDelimiterLine(line)) {
this.partsRead++;
const r = new TextProtoReader(this.bufReader);
const headers = await r.readMIMEHeader();
if (headers === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
const np = new PartReader(this, headers);
this.currentPart = np;

View File

@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import { BufReader, UnexpectedEOFError } from "../io/bufio.ts";
import { BufReader } from "../io/bufio.ts";
import { charCode } from "../io/util.ts";
const asciiDecoder = new TextDecoder();
@ -15,13 +15,6 @@ function str(buf: Uint8Array | null | undefined): string {
}
}
export class ProtocolError extends Error {
constructor(msg: string) {
super(msg);
this.name = "ProtocolError";
}
}
export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
if (a == null) {
return b;
@ -79,16 +72,16 @@ export class TextProtoReader {
buf = await this.r.peek(1);
if (buf === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
throw new ProtocolError(
throw new Deno.errors.InvalidData(
`malformed MIME header initial line: ${str(line)}`
);
}
while (true) {
const kv = await this.readLineSlice(); // readContinuedLineSlice
if (kv === Deno.EOF) throw new UnexpectedEOFError();
if (kv === Deno.EOF) throw new Deno.errors.UnexpectedEof();
if (kv.byteLength === 0) return m;
// Key ends at first colon; should not have trailing spaces
@ -96,7 +89,9 @@ export class TextProtoReader {
// them if present.
let i = kv.indexOf(charCode(":"));
if (i < 0) {
throw new ProtocolError(`malformed MIME header line: ${str(kv)}`);
throw new Deno.errors.InvalidData(
`malformed MIME header line: ${str(kv)}`
);
}
let endKey = i;
while (endKey > 0 && kv[endKey - 1] == charCode(" ")) {
@ -108,7 +103,7 @@ export class TextProtoReader {
// As per RFC 7230 field-name is a token,
// tokens consist of one or more chars.
// We could return a ProtocolError here,
// 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 == "") {

View File

@ -4,7 +4,7 @@
// license that can be found in the LICENSE file.
import { BufReader } from "../io/bufio.ts";
import { TextProtoReader, ProtocolError } from "./mod.ts";
import { TextProtoReader } from "./mod.ts";
import { stringsReader } from "../io/util.ts";
import {
assert,
@ -134,7 +134,7 @@ test({
} catch (e) {
err = e;
}
assert(err instanceof ProtocolError);
assert(err instanceof Deno.errors.InvalidData);
}
});
@ -156,7 +156,7 @@ test({
} catch (e) {
err = e;
}
assert(err instanceof ProtocolError);
assert(err instanceof Deno.errors.InvalidData);
}
});

View File

@ -2,7 +2,7 @@
import { decode, encode } from "../strings/mod.ts";
import { hasOwnProperty } from "../util/has_own_property.ts";
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { readLong, readShort, sliceLongToBytes } from "../io/ioutil.ts";
import { Sha1 } from "./sha1.ts";
import { writeResponse } from "../http/io.ts";
@ -71,12 +71,6 @@ export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
return output;
}
export class SocketClosedError extends Error {
constructor(msg = "Socket has already been closed") {
super(msg);
}
}
export interface WebSocketFrame {
isLastFrame: boolean;
opcode: OpCode;
@ -91,20 +85,20 @@ export interface WebSocket {
receive(): AsyncIterableIterator<WebSocketEvent>;
/**
* @throws SocketClosedError
* @throws `Deno.errors.ConnectionReset`
*/
send(data: WebSocketMessage): Promise<void>;
/**
* @param data
* @throws SocketClosedError
* @throws `Deno.errors.ConnectionReset`
*/
ping(data?: WebSocketMessage): Promise<void>;
/** Close connection after sending close frame to peer.
* This is canonical way of disconnection but it may hang because of peer's response delay.
* Default close code is 1000 (Normal Closure)
* @throws SocketClosedError
* @throws `Deno.errors.ConnectionReset`
*/
close(): Promise<void>;
close(code: number): Promise<void>;
@ -164,8 +158,8 @@ export async function writeFrame(
}
/** Read websocket frame from given BufReader
* @throws UnexpectedEOFError When peer closed connection without close frame
* @throws Error Frame is invalid
* @throws `Deno.errors.UnexpectedEof` When peer closed connection without close frame
* @throws `Error` Frame is invalid
*/
export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
let b = assertNotEOF(await buf.readByte());
@ -318,7 +312,7 @@ class WebSocketImpl implements WebSocket {
private enqueue(frame: WebSocketFrame): Promise<void> {
if (this._isClosed) {
throw new SocketClosedError();
throw new Deno.errors.ConnectionReset("Socket has already been closed");
}
const d = deferred<void>();
this.sendQueue.push({ d, frame });
@ -397,7 +391,11 @@ class WebSocketImpl implements WebSocket {
this._isClosed = true;
const rest = this.sendQueue;
this.sendQueue = [];
rest.forEach(e => e.d.reject(new SocketClosedError()));
rest.forEach(e =>
e.d.reject(
new Deno.errors.ConnectionReset("Socket has already been closed")
)
);
}
}
}
@ -495,7 +493,7 @@ export async function handshake(
const tpReader = new TextProtoReader(bufReader);
const statusLine = await tpReader.readLine();
if (statusLine === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
const m = statusLine.match(/^(?<version>\S+) (?<statusCode>\S+) /);
if (!m) {
@ -513,7 +511,7 @@ export async function handshake(
const responseHeaders = await tpReader.readMIMEHeader();
if (responseHeaders === Deno.EOF) {
throw new UnexpectedEOFError();
throw new Deno.errors.UnexpectedEof();
}
const expectedSecAccept = createSecAccept(key);

View File

@ -14,8 +14,7 @@ import {
readFrame,
unmask,
writeFrame,
createWebSocket,
SocketClosedError
createWebSocket
} from "./mod.ts";
import { encode, decode } from "../strings/mod.ts";
import Writer = Deno.Writer;
@ -331,7 +330,7 @@ test("[ws] createSecKeyHasCorrectLength", () => {
assertEquals(atob(secKey).length, 16);
});
test("[ws] WebSocket should throw SocketClosedError when peer closed connection without close frame", async () => {
test("[ws] WebSocket should throw `Deno.errors.ConnectionReset` when peer closed connection without close frame", async () => {
const buf = new Buffer();
const eofReader: Deno.Reader = {
async read(_: Uint8Array): Promise<number | Deno.EOF> {
@ -341,12 +340,15 @@ test("[ws] WebSocket should throw SocketClosedError when peer closed connection
const conn = dummyConn(eofReader, buf);
const sock = createWebSocket({ conn });
sock.closeForce();
await assertThrowsAsync(() => sock.send("hello"), SocketClosedError);
await assertThrowsAsync(() => sock.ping(), SocketClosedError);
await assertThrowsAsync(() => sock.close(0), SocketClosedError);
await assertThrowsAsync(
() => sock.send("hello"),
Deno.errors.ConnectionReset
);
await assertThrowsAsync(() => sock.ping(), Deno.errors.ConnectionReset);
await assertThrowsAsync(() => sock.close(0), Deno.errors.ConnectionReset);
});
test("[ws] WebSocket shouldn't throw UnexpectedEOFError on recive()", async () => {
test("[ws] WebSocket shouldn't throw `Deno.errors.UnexpectedEof` on recive()", async () => {
const buf = new Buffer();
const eofReader: Deno.Reader = {
async read(_: Uint8Array): Promise<number | Deno.EOF> {
@ -382,8 +384,8 @@ test("[ws] WebSocket should reject sending promise when connection reset forcely
sock.closeForce();
assertEquals(sock.isClosed, true);
const [a, b, c] = await p;
assert(a instanceof SocketClosedError);
assert(b instanceof SocketClosedError);
assert(c instanceof SocketClosedError);
assert(a instanceof Deno.errors.ConnectionReset);
assert(b instanceof Deno.errors.ConnectionReset);
assert(c instanceof Deno.errors.ConnectionReset);
clearTimeout(timer);
});