mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
remove non-null assertion operator from std (part1) (#3900)
This commit is contained in:
parent
ea6179f7dc
commit
c2986891f6
26 changed files with 147 additions and 89 deletions
|
@ -1,8 +1,14 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
import { pad } from "../strings/pad.ts";
|
import { pad } from "../strings/pad.ts";
|
||||||
|
import { assert } from "../testing/mod.ts";
|
||||||
|
|
||||||
export type DateFormat = "mm-dd-yyyy" | "dd-mm-yyyy" | "yyyy-mm-dd";
|
export type DateFormat = "mm-dd-yyyy" | "dd-mm-yyyy" | "yyyy-mm-dd";
|
||||||
|
|
||||||
|
function execForce(reg: RegExp, pat: string): RegExpExecArray {
|
||||||
|
const v = reg.exec(pat);
|
||||||
|
assert(v != null);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Parse date from string using format string
|
* Parse date from string using format string
|
||||||
* @param dateStr Date string
|
* @param dateStr Date string
|
||||||
|
@ -16,15 +22,15 @@ export function parseDate(dateStr: string, format: DateFormat): Date {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case "mm-dd-yyyy":
|
case "mm-dd-yyyy":
|
||||||
datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
|
datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
|
||||||
[, m, d, y] = datePattern.exec(dateStr)!;
|
[, m, d, y] = execForce(datePattern, dateStr);
|
||||||
break;
|
break;
|
||||||
case "dd-mm-yyyy":
|
case "dd-mm-yyyy":
|
||||||
datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
|
datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
|
||||||
[, d, m, y] = datePattern.exec(dateStr)!;
|
[, d, m, y] = execForce(datePattern, dateStr);
|
||||||
break;
|
break;
|
||||||
case "yyyy-mm-dd":
|
case "yyyy-mm-dd":
|
||||||
datePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
|
datePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||||
[, y, m, d] = datePattern.exec(dateStr)!;
|
[, y, m, d] = execForce(datePattern, dateStr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Invalid date format!");
|
throw new Error("Invalid date format!");
|
||||||
|
@ -57,27 +63,27 @@ export function parseDateTime(
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case "mm-dd-yyyy hh:mm":
|
case "mm-dd-yyyy hh:mm":
|
||||||
datePattern = /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2})$/;
|
datePattern = /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2})$/;
|
||||||
[, m, d, y, ho, mi] = datePattern.exec(datetimeStr)!;
|
[, m, d, y, ho, mi] = execForce(datePattern, datetimeStr);
|
||||||
break;
|
break;
|
||||||
case "dd-mm-yyyy hh:mm":
|
case "dd-mm-yyyy hh:mm":
|
||||||
datePattern = /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2})$/;
|
datePattern = /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2})$/;
|
||||||
[, d, m, y, ho, mi] = datePattern.exec(datetimeStr)!;
|
[, d, m, y, ho, mi] = execForce(datePattern, datetimeStr);
|
||||||
break;
|
break;
|
||||||
case "yyyy-mm-dd hh:mm":
|
case "yyyy-mm-dd hh:mm":
|
||||||
datePattern = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})$/;
|
datePattern = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})$/;
|
||||||
[, y, m, d, ho, mi] = datePattern.exec(datetimeStr)!;
|
[, y, m, d, ho, mi] = execForce(datePattern, datetimeStr);
|
||||||
break;
|
break;
|
||||||
case "hh:mm mm-dd-yyyy":
|
case "hh:mm mm-dd-yyyy":
|
||||||
datePattern = /^(\d{2}):(\d{2}) (\d{2})-(\d{2})-(\d{4})$/;
|
datePattern = /^(\d{2}):(\d{2}) (\d{2})-(\d{2})-(\d{4})$/;
|
||||||
[, ho, mi, m, d, y] = datePattern.exec(datetimeStr)!;
|
[, ho, mi, m, d, y] = execForce(datePattern, datetimeStr);
|
||||||
break;
|
break;
|
||||||
case "hh:mm dd-mm-yyyy":
|
case "hh:mm dd-mm-yyyy":
|
||||||
datePattern = /^(\d{2}):(\d{2}) (\d{2})-(\d{2})-(\d{4})$/;
|
datePattern = /^(\d{2}):(\d{2}) (\d{2})-(\d{2})-(\d{4})$/;
|
||||||
[, ho, mi, d, m, y] = datePattern.exec(datetimeStr)!;
|
[, ho, mi, d, m, y] = execForce(datePattern, datetimeStr);
|
||||||
break;
|
break;
|
||||||
case "hh:mm yyyy-mm-dd":
|
case "hh:mm yyyy-mm-dd":
|
||||||
datePattern = /^(\d{2}):(\d{2}) (\d{4})-(\d{2})-(\d{2})$/;
|
datePattern = /^(\d{2}):(\d{2}) (\d{4})-(\d{2})-(\d{2})$/;
|
||||||
[, ho, mi, y, m, d] = datePattern.exec(datetimeStr)!;
|
[, ho, mi, y, m, d] = execForce(datePattern, datetimeStr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Invalid datetime format!");
|
throw new Error("Invalid datetime format!");
|
||||||
|
|
|
@ -14,10 +14,10 @@ for (let i = 0, len = code.length; i < len; ++i) {
|
||||||
const placeHolderPadLookup = [0, 1, , 2, 3, , 4];
|
const placeHolderPadLookup = [0, 1, , 2, 3, , 4];
|
||||||
function _getPadLen(placeHoldersLen: number): number {
|
function _getPadLen(placeHoldersLen: number): number {
|
||||||
const maybeLen = placeHolderPadLookup[placeHoldersLen];
|
const maybeLen = placeHolderPadLookup[placeHoldersLen];
|
||||||
if (maybeLen === undefined) {
|
if (typeof maybeLen !== "number") {
|
||||||
throw new Error("Invalid pad length");
|
throw new Error("Invalid pad length");
|
||||||
}
|
}
|
||||||
return maybeLen!;
|
return maybeLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLens(b32: string): [number, number] {
|
function getLens(b32: string): [number, number] {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { xeval } from "../xeval.ts";
|
import { xeval } from "../xeval.ts";
|
||||||
import { stringsReader } from "../../io/util.ts";
|
import { stringsReader } from "../../io/util.ts";
|
||||||
import { decode, encode } from "../../strings/mod.ts";
|
import { decode, encode } from "../../strings/mod.ts";
|
||||||
import { assertEquals, assertStrContains } from "../../testing/asserts.ts";
|
import {
|
||||||
|
assertEquals,
|
||||||
|
assertStrContains,
|
||||||
|
assert
|
||||||
|
} from "../../testing/asserts.ts";
|
||||||
import { test } from "../../testing/mod.ts";
|
import { test } from "../../testing/mod.ts";
|
||||||
const { execPath, run } = Deno;
|
const { execPath, run } = Deno;
|
||||||
|
|
||||||
|
@ -29,8 +33,9 @@ test(async function xevalCliReplvar(): Promise<void> {
|
||||||
stdout: "piped",
|
stdout: "piped",
|
||||||
stderr: "null"
|
stderr: "null"
|
||||||
});
|
});
|
||||||
await p.stdin!.write(encode("hello"));
|
assert(p.stdin != null);
|
||||||
await p.stdin!.close();
|
await p.stdin.write(encode("hello"));
|
||||||
|
await p.stdin.close();
|
||||||
assertEquals(await p.status(), { code: 0, success: true });
|
assertEquals(await p.status(), { code: 0, success: true });
|
||||||
assertEquals(decode(await p.output()).trimEnd(), "hello");
|
assertEquals(decode(await p.output()).trimEnd(), "hello");
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
normalize
|
normalize
|
||||||
} from "../path/mod.ts";
|
} from "../path/mod.ts";
|
||||||
import { WalkInfo, walk, walkSync } from "./walk.ts";
|
import { WalkInfo, walk, walkSync } from "./walk.ts";
|
||||||
|
import { assert } from "../testing/mod.ts";
|
||||||
const { ErrorKind, cwd, stat, statSync } = Deno;
|
const { ErrorKind, cwd, stat, statSync } = Deno;
|
||||||
type ErrorKind = Deno.ErrorKind;
|
type ErrorKind = Deno.ErrorKind;
|
||||||
type DenoError = Deno.DenoError<ErrorKind>;
|
type DenoError = Deno.DenoError<ErrorKind>;
|
||||||
|
@ -80,7 +81,9 @@ export async function* expandGlob(
|
||||||
|
|
||||||
let fixedRoot = winRoot != undefined ? winRoot : "/";
|
let fixedRoot = winRoot != undefined ? winRoot : "/";
|
||||||
while (segments.length > 0 && !isGlob(segments[0])) {
|
while (segments.length > 0 && !isGlob(segments[0])) {
|
||||||
fixedRoot = joinGlobs([fixedRoot, segments.shift()!], globOptions);
|
const seg = segments.shift();
|
||||||
|
assert(seg != null);
|
||||||
|
fixedRoot = joinGlobs([fixedRoot, seg], globOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fixedRootInfo: WalkInfo;
|
let fixedRootInfo: WalkInfo;
|
||||||
|
@ -182,7 +185,9 @@ export function* expandGlobSync(
|
||||||
|
|
||||||
let fixedRoot = winRoot != undefined ? winRoot : "/";
|
let fixedRoot = winRoot != undefined ? winRoot : "/";
|
||||||
while (segments.length > 0 && !isGlob(segments[0])) {
|
while (segments.length > 0 && !isGlob(segments[0])) {
|
||||||
fixedRoot = joinGlobs([fixedRoot, segments.shift()!], globOptions);
|
const seg = segments.shift();
|
||||||
|
assert(seg != null);
|
||||||
|
fixedRoot = joinGlobs([fixedRoot, seg], globOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fixedRootInfo: WalkInfo;
|
let fixedRootInfo: WalkInfo;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Documentation and interface for walk were adapted from Go
|
// Documentation and interface for walk were adapted from Go
|
||||||
// https://golang.org/pkg/path/filepath/#Walk
|
// https://golang.org/pkg/path/filepath/#Walk
|
||||||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||||
import { unimplemented } from "../testing/asserts.ts";
|
import { unimplemented, assert } from "../testing/asserts.ts";
|
||||||
import { join } from "../path/mod.ts";
|
import { join } from "../path/mod.ts";
|
||||||
const { readDir, readDirSync, stat, statSync } = Deno;
|
const { readDir, readDirSync, stat, statSync } = Deno;
|
||||||
type FileInfo = Deno.FileInfo;
|
type FileInfo = Deno.FileInfo;
|
||||||
|
@ -90,7 +90,8 @@ export async function* walk(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const filename = join(root, info.name!);
|
assert(info.name != null);
|
||||||
|
const filename = join(root, info.name);
|
||||||
|
|
||||||
if (info.isFile()) {
|
if (info.isFile()) {
|
||||||
if (includeFiles && include(filename, exts, match, skip)) {
|
if (includeFiles && include(filename, exts, match, skip)) {
|
||||||
|
@ -142,7 +143,8 @@ export function* walkSync(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const filename = join(root, info.name!);
|
assert(info.name != null);
|
||||||
|
const filename = join(root, info.name);
|
||||||
|
|
||||||
if (info.isFile()) {
|
if (info.isFile()) {
|
||||||
if (includeFiles && include(filename, exts, match, skip)) {
|
if (includeFiles && include(filename, exts, match, skip)) {
|
||||||
|
|
|
@ -45,8 +45,8 @@ function toString(cookie: Cookie): string {
|
||||||
if (cookie.httpOnly) {
|
if (cookie.httpOnly) {
|
||||||
out.push("HttpOnly");
|
out.push("HttpOnly");
|
||||||
}
|
}
|
||||||
if (Number.isInteger(cookie.maxAge!)) {
|
if (Number.isInteger(cookie.maxAge)) {
|
||||||
assert(cookie.maxAge! > 0, "Max-Age must be an integer superior to 0");
|
assert(cookie.maxAge > 0, "Max-Age must be an integer superior to 0");
|
||||||
out.push(`Max-Age=${cookie.maxAge}`);
|
out.push(`Max-Age=${cookie.maxAge}`);
|
||||||
}
|
}
|
||||||
if (cookie.domain) {
|
if (cookie.domain) {
|
||||||
|
@ -73,12 +73,14 @@ function toString(cookie: Cookie): string {
|
||||||
* @param req Server Request
|
* @param req Server Request
|
||||||
*/
|
*/
|
||||||
export function getCookies(req: ServerRequest): Cookies {
|
export function getCookies(req: ServerRequest): Cookies {
|
||||||
if (req.headers.has("Cookie")) {
|
const cookie = req.headers.get("Cookie");
|
||||||
|
if (cookie != null) {
|
||||||
const out: Cookies = {};
|
const out: Cookies = {};
|
||||||
const c = req.headers.get("Cookie")!.split(";");
|
const c = cookie.split(";");
|
||||||
for (const kv of c) {
|
for (const kv of c) {
|
||||||
const cookieVal = kv.split("=");
|
const [cookieKey, ...cookieVal] = kv.split("=");
|
||||||
const key = cookieVal.shift()!.trim();
|
assert(cookieKey != null);
|
||||||
|
const key = cookieKey.trim();
|
||||||
out[key] = cookieVal.join("=");
|
out[key] = cookieVal.join("=");
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -38,7 +38,7 @@ test({
|
||||||
const res: Response = {};
|
const res: Response = {};
|
||||||
delCookie(res, "deno");
|
delCookie(res, "deno");
|
||||||
assertEquals(
|
assertEquals(
|
||||||
res.headers!.get("Set-Cookie"),
|
res.headers?.get("Set-Cookie"),
|
||||||
"deno=; Expires=Thu, 01 Jan 1970 00:00:00 GMT"
|
"deno=; Expires=Thu, 01 Jan 1970 00:00:00 GMT"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ function modeToString(isDir: boolean, maybeMode: number | null): string {
|
||||||
if (maybeMode === null) {
|
if (maybeMode === null) {
|
||||||
return "(unknown mode)";
|
return "(unknown mode)";
|
||||||
}
|
}
|
||||||
const mode = maybeMode!.toString(8);
|
const mode = maybeMode.toString(8);
|
||||||
if (mode.length < 3) {
|
if (mode.length < 3) {
|
||||||
return "(unknown mode)";
|
return "(unknown mode)";
|
||||||
}
|
}
|
||||||
|
@ -186,8 +186,8 @@ function setCORS(res: Response): void {
|
||||||
if (!res.headers) {
|
if (!res.headers) {
|
||||||
res.headers = new Headers();
|
res.headers = new Headers();
|
||||||
}
|
}
|
||||||
res.headers!.append("access-control-allow-origin", "*");
|
res.headers.append("access-control-allow-origin", "*");
|
||||||
res.headers!.append(
|
res.headers.append(
|
||||||
"access-control-allow-headers",
|
"access-control-allow-headers",
|
||||||
"Origin, X-Requested-With, Content-Type, Accept, Range"
|
"Origin, X-Requested-With, Content-Type, Accept, Range"
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,14 +20,15 @@ async function startFileServer(): Promise<void> {
|
||||||
stdout: "piped"
|
stdout: "piped"
|
||||||
});
|
});
|
||||||
// Once fileServer is ready it will write to its stdout.
|
// Once fileServer is ready it will write to its stdout.
|
||||||
const r = new TextProtoReader(new BufReader(fileServer.stdout!));
|
assert(fileServer.stdout != null);
|
||||||
|
const r = new TextProtoReader(new BufReader(fileServer.stdout));
|
||||||
const s = await r.readLine();
|
const s = await r.readLine();
|
||||||
assert(s !== Deno.EOF && s.includes("server listening"));
|
assert(s !== Deno.EOF && s.includes("server listening"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function killFileServer(): void {
|
function killFileServer(): void {
|
||||||
fileServer.close();
|
fileServer.close();
|
||||||
fileServer.stdout!.close();
|
fileServer.stdout?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
test(async function serveFile(): Promise<void> {
|
test(async function serveFile(): Promise<void> {
|
||||||
|
@ -102,8 +103,10 @@ test(async function servePermissionDenied(): Promise<void> {
|
||||||
stdout: "piped",
|
stdout: "piped",
|
||||||
stderr: "piped"
|
stderr: "piped"
|
||||||
});
|
});
|
||||||
const reader = new TextProtoReader(new BufReader(deniedServer.stdout!));
|
assert(deniedServer.stdout != null);
|
||||||
const errReader = new TextProtoReader(new BufReader(deniedServer.stderr!));
|
const reader = new TextProtoReader(new BufReader(deniedServer.stdout));
|
||||||
|
assert(deniedServer.stderr != null);
|
||||||
|
const errReader = new TextProtoReader(new BufReader(deniedServer.stderr));
|
||||||
const s = await reader.readLine();
|
const s = await reader.readLine();
|
||||||
assert(s !== Deno.EOF && s.includes("server listening"));
|
assert(s !== Deno.EOF && s.includes("server listening"));
|
||||||
|
|
||||||
|
@ -115,8 +118,8 @@ test(async function servePermissionDenied(): Promise<void> {
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
deniedServer.close();
|
deniedServer.close();
|
||||||
deniedServer.stdout!.close();
|
deniedServer.stdout.close();
|
||||||
deniedServer.stderr!.close();
|
deniedServer.stderr.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -125,9 +128,10 @@ test(async function printHelp(): Promise<void> {
|
||||||
args: [Deno.execPath(), "run", "http/file_server.ts", "--help"],
|
args: [Deno.execPath(), "run", "http/file_server.ts", "--help"],
|
||||||
stdout: "piped"
|
stdout: "piped"
|
||||||
});
|
});
|
||||||
const r = new TextProtoReader(new BufReader(helpProcess.stdout!));
|
assert(helpProcess.stdout != null);
|
||||||
|
const r = new TextProtoReader(new BufReader(helpProcess.stdout));
|
||||||
const s = await r.readLine();
|
const s = await r.readLine();
|
||||||
assert(s !== Deno.EOF && s.includes("Deno File Server"));
|
assert(s !== Deno.EOF && s.includes("Deno File Server"));
|
||||||
helpProcess.close();
|
helpProcess.close();
|
||||||
helpProcess.stdout!.close();
|
helpProcess.stdout.close();
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,13 +12,14 @@ async function startServer(): Promise<void> {
|
||||||
stdout: "piped"
|
stdout: "piped"
|
||||||
});
|
});
|
||||||
// Once racing server is ready it will write to its stdout.
|
// Once racing server is ready it will write to its stdout.
|
||||||
const r = new TextProtoReader(new BufReader(server.stdout!));
|
assert(server.stdout != null);
|
||||||
|
const r = new TextProtoReader(new BufReader(server.stdout));
|
||||||
const s = await r.readLine();
|
const s = await r.readLine();
|
||||||
assert(s !== Deno.EOF && s.includes("Racing server listening..."));
|
assert(s !== Deno.EOF && s.includes("Racing server listening..."));
|
||||||
}
|
}
|
||||||
function killServer(): void {
|
function killServer(): void {
|
||||||
server.close();
|
server.close();
|
||||||
server.stdout!.close();
|
server.stdout?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
const input = `GET / HTTP/1.1
|
const input = `GET / HTTP/1.1
|
||||||
|
|
|
@ -73,9 +73,10 @@ export async function writeResponse(w: Writer, r: Response): Promise<void> {
|
||||||
let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`;
|
let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`;
|
||||||
|
|
||||||
setContentLength(r);
|
setContentLength(r);
|
||||||
const headers = r.headers!;
|
assert(r.headers != null);
|
||||||
|
const headers = r.headers;
|
||||||
|
|
||||||
for (const [key, value] of headers!) {
|
for (const [key, value] of headers) {
|
||||||
out += `${key}: ${value}\r\n`;
|
out += `${key}: ${value}\r\n`;
|
||||||
}
|
}
|
||||||
out += "\r\n";
|
out += "\r\n";
|
||||||
|
@ -88,7 +89,9 @@ export async function writeResponse(w: Writer, r: Response): Promise<void> {
|
||||||
const n = await writer.write(r.body);
|
const n = await writer.write(r.body);
|
||||||
assert(n === r.body.byteLength);
|
assert(n === r.body.byteLength);
|
||||||
} else if (headers.has("content-length")) {
|
} else if (headers.has("content-length")) {
|
||||||
const bodyLength = parseInt(headers.get("content-length")!);
|
const contentLength = headers.get("content-length");
|
||||||
|
assert(contentLength != null);
|
||||||
|
const bodyLength = parseInt(contentLength);
|
||||||
const n = await copy(writer, r.body);
|
const n = await copy(writer, r.body);
|
||||||
assert(n === bodyLength);
|
assert(n === bodyLength);
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,8 +132,9 @@ export class ServerRequest {
|
||||||
// undefined means not cached.
|
// undefined means not cached.
|
||||||
// null means invalid or not provided.
|
// null means invalid or not provided.
|
||||||
if (this._contentLength === undefined) {
|
if (this._contentLength === undefined) {
|
||||||
if (this.headers.has("content-length")) {
|
const cl = this.headers.get("content-length");
|
||||||
this._contentLength = +this.headers.get("content-length")!;
|
if (cl) {
|
||||||
|
this._contentLength = parseInt(cl);
|
||||||
// Convert NaN to null (as NaN harder to test)
|
// Convert NaN to null (as NaN harder to test)
|
||||||
if (Number.isNaN(this._contentLength)) {
|
if (Number.isNaN(this._contentLength)) {
|
||||||
this._contentLength = null;
|
this._contentLength = null;
|
||||||
|
@ -190,12 +194,12 @@ export class ServerRequest {
|
||||||
}
|
}
|
||||||
yield nread;
|
yield nread;
|
||||||
} else {
|
} else {
|
||||||
if (this.headers.has("transfer-encoding")) {
|
const transferEncoding = this.headers.get("transfer-encoding");
|
||||||
const transferEncodings = this.headers
|
if (transferEncoding) {
|
||||||
.get("transfer-encoding")!
|
const parts = transferEncoding
|
||||||
.split(",")
|
.split(",")
|
||||||
.map((e): string => e.trim().toLowerCase());
|
.map((e): string => e.trim().toLowerCase());
|
||||||
if (transferEncodings.includes("chunked")) {
|
if (parts.includes("chunked")) {
|
||||||
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
|
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
|
||||||
const tp = new TextProtoReader(this.r);
|
const tp = new TextProtoReader(this.r);
|
||||||
let line = await tp.readLine();
|
let line = await tp.readLine();
|
||||||
|
@ -413,7 +417,7 @@ export class Server implements AsyncIterable<ServerRequest> {
|
||||||
|
|
||||||
// Wait for the request to be processed before we accept a new request on
|
// Wait for the request to be processed before we accept a new request on
|
||||||
// this connection.
|
// this connection.
|
||||||
const procError = await req!.done;
|
const procError = await req.done;
|
||||||
if (procError) {
|
if (procError) {
|
||||||
// Something bad happened during response.
|
// Something bad happened during response.
|
||||||
// (likely other side closed during pipelined req)
|
// (likely other side closed during pipelined req)
|
||||||
|
@ -422,12 +426,12 @@ export class Server implements AsyncIterable<ServerRequest> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req! === Deno.EOF) {
|
if (req === Deno.EOF) {
|
||||||
// The connection was gracefully closed.
|
// The connection was gracefully closed.
|
||||||
} else if (err) {
|
} else if (err && req) {
|
||||||
// An error was thrown while parsing request headers.
|
// An error was thrown while parsing request headers.
|
||||||
try {
|
try {
|
||||||
await writeResponse(req!.w, {
|
await writeResponse(req.w, {
|
||||||
status: 400,
|
status: 400,
|
||||||
body: encoder.encode(`${err.message}\r\n\r\n`)
|
body: encoder.encode(`${err.message}\r\n\r\n`)
|
||||||
});
|
});
|
||||||
|
|
|
@ -506,8 +506,7 @@ test(async function testReadRequestError(): Promise<void> {
|
||||||
for (const test of testCases) {
|
for (const test of testCases) {
|
||||||
const reader = new BufReader(new StringReader(test.in));
|
const reader = new BufReader(new StringReader(test.in));
|
||||||
let err;
|
let err;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
let req: ServerRequest | Deno.EOF;
|
||||||
let req: any;
|
|
||||||
try {
|
try {
|
||||||
req = await readRequest(mockConn as Deno.Conn, reader);
|
req = await readRequest(mockConn as Deno.Conn, reader);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -520,10 +519,12 @@ test(async function testReadRequestError(): Promise<void> {
|
||||||
} else if (test.err) {
|
} else if (test.err) {
|
||||||
assert(err instanceof (test.err as typeof UnexpectedEOFError));
|
assert(err instanceof (test.err as typeof UnexpectedEOFError));
|
||||||
} else {
|
} else {
|
||||||
|
assert(req instanceof ServerRequest);
|
||||||
|
assert(test.headers != null);
|
||||||
assertEquals(err, undefined);
|
assertEquals(err, undefined);
|
||||||
assertNotEquals(req, Deno.EOF);
|
assertNotEquals(req, Deno.EOF);
|
||||||
for (const h of test.headers!) {
|
for (const h of test.headers) {
|
||||||
assertEquals((req! as ServerRequest).headers.get(h.key), h.value);
|
assertEquals(req.headers.get(h.key), h.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,6 @@ export class StringWriter implements Writer {
|
||||||
offs += chunk.byteLength;
|
offs += chunk.byteLength;
|
||||||
}
|
}
|
||||||
this.cache = decode(buf);
|
this.cache = decode(buf);
|
||||||
return this.cache!;
|
return this.cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
WriterHandler,
|
WriterHandler,
|
||||||
FileHandler
|
FileHandler
|
||||||
} from "./handlers.ts";
|
} from "./handlers.ts";
|
||||||
|
import { assert } from "../testing/mod.ts";
|
||||||
|
|
||||||
export class LoggerConfig {
|
export class LoggerConfig {
|
||||||
level?: string;
|
level?: string;
|
||||||
|
@ -50,16 +51,20 @@ export const handlers = {
|
||||||
|
|
||||||
export function getLogger(name?: string): Logger {
|
export function getLogger(name?: string): Logger {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return state.loggers.get("default")!;
|
const d = state.loggers.get("default");
|
||||||
|
assert(
|
||||||
|
d != null,
|
||||||
|
`"default" logger must be set for getting logger without name`
|
||||||
|
);
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
const result = state.loggers.get(name);
|
||||||
if (!state.loggers.has(name)) {
|
if (!result) {
|
||||||
const logger = new Logger("NOTSET", []);
|
const logger = new Logger("NOTSET", []);
|
||||||
state.loggers.set(name, logger);
|
state.loggers.set(name, logger);
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
return state.loggers.get(name)!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const debug = (msg: string, ...args: unknown[]): void =>
|
export const debug = (msg: string, ...args: unknown[]): void =>
|
||||||
|
@ -105,8 +110,9 @@ export async function setup(config: LogConfig): Promise<void> {
|
||||||
const handlers: BaseHandler[] = [];
|
const handlers: BaseHandler[] = [];
|
||||||
|
|
||||||
handlerNames.forEach((handlerName): void => {
|
handlerNames.forEach((handlerName): void => {
|
||||||
if (state.handlers.has(handlerName)) {
|
const handler = state.handlers.get(handlerName);
|
||||||
handlers.push(state.handlers.get(handlerName)!);
|
if (handler) {
|
||||||
|
handlers.push(handler);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ function populateMaps(
|
||||||
extensions.set(type, exts);
|
extensions.set(type, exts);
|
||||||
|
|
||||||
for (const ext of exts) {
|
for (const ext of exts) {
|
||||||
if (types.has(ext)) {
|
const current = types.get(ext);
|
||||||
const current = types.get(ext)!;
|
if (current) {
|
||||||
const from = preference.indexOf(db[current].source);
|
const from = preference.indexOf(db[current].source);
|
||||||
const to = preference.indexOf(mime.source);
|
const to = preference.indexOf(mime.source);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { extname } from "../path/mod.ts";
|
||||||
import { tempFile } from "../io/util.ts";
|
import { tempFile } from "../io/util.ts";
|
||||||
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
|
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
|
||||||
import { encoder } from "../strings/mod.ts";
|
import { encoder } from "../strings/mod.ts";
|
||||||
import { assertStrictEq } from "../testing/asserts.ts";
|
import { assertStrictEq, assert } from "../testing/asserts.ts";
|
||||||
import { TextProtoReader } from "../textproto/mod.ts";
|
import { TextProtoReader } from "../textproto/mod.ts";
|
||||||
import { hasOwnProperty } from "../util/has_own_property.ts";
|
import { hasOwnProperty } from "../util/has_own_property.ts";
|
||||||
|
|
||||||
|
@ -205,7 +205,8 @@ class PartReader implements Reader, Closer {
|
||||||
if (this.contentDispositionParams) return this.contentDispositionParams;
|
if (this.contentDispositionParams) return this.contentDispositionParams;
|
||||||
const cd = this.headers.get("content-disposition");
|
const cd = this.headers.get("content-disposition");
|
||||||
const params: { [key: string]: string } = {};
|
const params: { [key: string]: string } = {};
|
||||||
const comps = cd!.split(";");
|
assert(cd != null, "content-disposition must be set");
|
||||||
|
const comps = cd.split(";");
|
||||||
this.contentDisposition = comps[0];
|
this.contentDisposition = comps[0];
|
||||||
comps
|
comps
|
||||||
.slice(1)
|
.slice(1)
|
||||||
|
@ -265,10 +266,12 @@ export class MultipartReader {
|
||||||
/** Read all form data from stream.
|
/** Read all form data from stream.
|
||||||
* If total size of stored data in memory exceed maxMemory,
|
* If total size of stored data in memory exceed maxMemory,
|
||||||
* overflowed file data will be written to temporal files.
|
* overflowed file data will be written to temporal files.
|
||||||
* String field values are never written to files */
|
* String field values are never written to files.
|
||||||
|
* null value means parsing or writing to file was failed in some reason.
|
||||||
|
* */
|
||||||
async readForm(
|
async readForm(
|
||||||
maxMemory: number
|
maxMemory: number
|
||||||
): Promise<{ [key: string]: string | FormFile }> {
|
): Promise<{ [key: string]: null | string | FormFile }> {
|
||||||
const result = Object.create(null);
|
const result = Object.create(null);
|
||||||
let maxValueBytes = maxMemory + (10 << 20);
|
let maxValueBytes = maxMemory + (10 << 20);
|
||||||
const buf = new Buffer(new Uint8Array(maxValueBytes));
|
const buf = new Buffer(new Uint8Array(maxValueBytes));
|
||||||
|
@ -293,8 +296,10 @@ export class MultipartReader {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// file
|
// file
|
||||||
let formFile: FormFile;
|
let formFile: FormFile | null = null;
|
||||||
const n = await copy(buf, p);
|
const n = await copy(buf, p);
|
||||||
|
const contentType = p.headers.get("content-type");
|
||||||
|
assert(contentType != null, "content-type must be set");
|
||||||
if (n > maxMemory) {
|
if (n > maxMemory) {
|
||||||
// too big, write to disk and flush buffer
|
// too big, write to disk and flush buffer
|
||||||
const ext = extname(p.fileName);
|
const ext = extname(p.fileName);
|
||||||
|
@ -311,7 +316,7 @@ export class MultipartReader {
|
||||||
file.close();
|
file.close();
|
||||||
formFile = {
|
formFile = {
|
||||||
filename: p.fileName,
|
filename: p.fileName,
|
||||||
type: p.headers.get("content-type")!,
|
type: contentType,
|
||||||
tempfile: filepath,
|
tempfile: filepath,
|
||||||
size
|
size
|
||||||
};
|
};
|
||||||
|
@ -321,14 +326,14 @@ export class MultipartReader {
|
||||||
} else {
|
} else {
|
||||||
formFile = {
|
formFile = {
|
||||||
filename: p.fileName,
|
filename: p.fileName,
|
||||||
type: p.headers.get("content-type")!,
|
type: contentType,
|
||||||
content: buf.bytes(),
|
content: buf.bytes(),
|
||||||
size: buf.length
|
size: buf.length
|
||||||
};
|
};
|
||||||
maxMemory -= n;
|
maxMemory -= n;
|
||||||
maxValueBytes -= n;
|
maxValueBytes -= n;
|
||||||
}
|
}
|
||||||
result[p.formName] = formFile!;
|
result[p.formName] = formFile;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,8 @@ test(async function multipartMultipartReader2(): Promise<void> {
|
||||||
assertEquals(form["bar"], "bar");
|
assertEquals(form["bar"], "bar");
|
||||||
const file = form["file"] as FormFile;
|
const file = form["file"] as FormFile;
|
||||||
assertEquals(file.type, "application/octet-stream");
|
assertEquals(file.type, "application/octet-stream");
|
||||||
const f = await open(file.tempfile!);
|
assert(file.tempfile != null);
|
||||||
|
const f = await open(file.tempfile);
|
||||||
const w = new StringWriter();
|
const w = new StringWriter();
|
||||||
await copy(w, f);
|
await copy(w, f);
|
||||||
const json = JSON.parse(w.toString());
|
const json = JSON.parse(w.toString());
|
||||||
|
@ -207,7 +208,9 @@ test(async function multipartMultipartReader2(): Promise<void> {
|
||||||
f.close();
|
f.close();
|
||||||
} finally {
|
} finally {
|
||||||
const file = form["file"] as FormFile;
|
const file = form["file"] as FormFile;
|
||||||
await remove(file.tempfile!);
|
if (file.tempfile) {
|
||||||
|
await remove(file.tempfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { SEP, SEP_PATTERN } from "./constants.ts";
|
import { SEP, SEP_PATTERN } from "./constants.ts";
|
||||||
import { globrex } from "./globrex.ts";
|
import { globrex } from "./globrex.ts";
|
||||||
import { join, normalize } from "./mod.ts";
|
import { join, normalize } from "./mod.ts";
|
||||||
|
import { assert } from "../testing/asserts.ts";
|
||||||
|
|
||||||
const { DenoError, ErrorKind } = Deno;
|
const { DenoError, ErrorKind } = Deno;
|
||||||
|
|
||||||
export interface GlobOptions {
|
export interface GlobOptions {
|
||||||
|
@ -46,7 +48,8 @@ export function globToRegExp(
|
||||||
strict: false,
|
strict: false,
|
||||||
filepath: true
|
filepath: true
|
||||||
});
|
});
|
||||||
return result.path!.regex;
|
assert(result.path != null);
|
||||||
|
return result.path.regex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test whether the given string is a glob */
|
/** Test whether the given string is a glob */
|
||||||
|
|
|
@ -49,7 +49,7 @@ export function normalizeString(
|
||||||
let code: number;
|
let code: number;
|
||||||
for (let i = 0, len = path.length; i <= len; ++i) {
|
for (let i = 0, len = path.length; i <= len; ++i) {
|
||||||
if (i < len) code = path.charCodeAt(i);
|
if (i < len) code = path.charCodeAt(i);
|
||||||
else if (isPathSeparator(code!)) break;
|
else if (isPathSeparator(code)) break;
|
||||||
else code = CHAR_FORWARD_SLASH;
|
else code = CHAR_FORWARD_SLASH;
|
||||||
|
|
||||||
if (isPathSeparator(code)) {
|
if (isPathSeparator(code)) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
normalizeString,
|
normalizeString,
|
||||||
_format
|
_format
|
||||||
} from "./utils.ts";
|
} from "./utils.ts";
|
||||||
|
import { assert } from "../testing/asserts.ts";
|
||||||
|
|
||||||
export const sep = "\\";
|
export const sep = "\\";
|
||||||
export const delimiter = ";";
|
export const delimiter = ";";
|
||||||
|
@ -329,7 +330,7 @@ export function join(...paths: string[]): string {
|
||||||
// path.join('//server', 'share') -> '\\\\server\\share\\')
|
// path.join('//server', 'share') -> '\\\\server\\share\\')
|
||||||
let needsReplace = true;
|
let needsReplace = true;
|
||||||
let slashCount = 0;
|
let slashCount = 0;
|
||||||
firstPart = firstPart!;
|
assert(firstPart != null);
|
||||||
if (isPathSeparator(firstPart.charCodeAt(0))) {
|
if (isPathSeparator(firstPart.charCodeAt(0))) {
|
||||||
++slashCount;
|
++slashCount;
|
||||||
const firstLen = firstPart.length;
|
const firstLen = firstPart.length;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { assert } from "./asserts.ts";
|
||||||
|
|
||||||
// This file is ported from pretty-format@24.0.0
|
// This file is ported from pretty-format@24.0.0
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||||
|
@ -361,7 +363,9 @@ const getKeysOfEnumerableProperties = (object: {}): Array<string | symbol> => {
|
||||||
|
|
||||||
if (Object.getOwnPropertySymbols) {
|
if (Object.getOwnPropertySymbols) {
|
||||||
Object.getOwnPropertySymbols(object).forEach((symbol): void => {
|
Object.getOwnPropertySymbols(object).forEach((symbol): void => {
|
||||||
if (Object.getOwnPropertyDescriptor(object, symbol)!.enumerable) {
|
const d = Object.getOwnPropertyDescriptor(object, symbol);
|
||||||
|
assert(d != null);
|
||||||
|
if (d.enumerable) {
|
||||||
keys.push(symbol);
|
keys.push(symbol);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -261,11 +261,14 @@ function printResults(
|
||||||
}
|
}
|
||||||
|
|
||||||
function previousPrinted(name: string, results: TestResults): boolean {
|
function previousPrinted(name: string, results: TestResults): boolean {
|
||||||
const curIndex: number = results.keys.get(name)!;
|
const curIndex = results.keys.get(name);
|
||||||
|
assert(curIndex != null);
|
||||||
if (curIndex === 0) {
|
if (curIndex === 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return results.cases.get(curIndex - 1)!.printed;
|
const prev = results.cases.get(curIndex - 1);
|
||||||
|
assert(prev != null);
|
||||||
|
return prev.printed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTestCase(
|
async function createTestCase(
|
||||||
|
@ -274,7 +277,10 @@ async function createTestCase(
|
||||||
exitOnFail: boolean,
|
exitOnFail: boolean,
|
||||||
{ fn, name }: TestDefinition
|
{ fn, name }: TestDefinition
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const result: TestResult = results.cases.get(results.keys.get(name)!)!;
|
const i = results.keys.get(name);
|
||||||
|
assert(i != null);
|
||||||
|
const result = results.cases.get(i);
|
||||||
|
assert(result != null);
|
||||||
try {
|
try {
|
||||||
const start = performance.now();
|
const start = performance.now();
|
||||||
await fn();
|
await fn();
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { BufReader, UnexpectedEOFError } from "../io/bufio.ts";
|
||||||
import { charCode } from "../io/util.ts";
|
import { charCode } from "../io/util.ts";
|
||||||
|
|
||||||
const asciiDecoder = new TextDecoder();
|
const asciiDecoder = new TextDecoder();
|
||||||
function str(buf: Uint8Array): string {
|
function str(buf: Uint8Array | null | undefined): string {
|
||||||
if (buf == null) {
|
if (buf == null) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +82,7 @@ export class TextProtoReader {
|
||||||
throw new UnexpectedEOFError();
|
throw new UnexpectedEOFError();
|
||||||
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
||||||
throw new ProtocolError(
|
throw new ProtocolError(
|
||||||
`malformed MIME header initial line: ${str(line!)}`
|
`malformed MIME header initial line: ${str(line)}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ export class TextProtoReader {
|
||||||
const { line: l, more } = r;
|
const { line: l, more } = r;
|
||||||
|
|
||||||
// Avoid the copy if the first call produced a full line.
|
// Avoid the copy if the first call produced a full line.
|
||||||
if (!line! && !more) {
|
if (!line && !more) {
|
||||||
// TODO(ry):
|
// TODO(ry):
|
||||||
// This skipSpace() is definitely misplaced, but I don't know where it
|
// This skipSpace() is definitely misplaced, but I don't know where it
|
||||||
// comes from nor how to fix it.
|
// comes from nor how to fix it.
|
||||||
|
|
|
@ -23,7 +23,7 @@ export function deferred<T>(): Deferred<T> {
|
||||||
const promise = new Promise<T>((resolve, reject): void => {
|
const promise = new Promise<T>((resolve, reject): void => {
|
||||||
methods = { resolve, reject };
|
methods = { resolve, reject };
|
||||||
});
|
});
|
||||||
return Object.assign(promise, methods)! as Deferred<T>;
|
return Object.assign(promise, methods) as Deferred<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TaggedYieldedValue<T> {
|
interface TaggedYieldedValue<T> {
|
||||||
|
|
|
@ -24,7 +24,7 @@ export function deepAssign(
|
||||||
if (typeof target[key] !== `object` || !target[key]) {
|
if (typeof target[key] !== `object` || !target[key]) {
|
||||||
target[key] = {};
|
target[key] = {};
|
||||||
}
|
}
|
||||||
deepAssign(target[key] as Record<string, unknown>, value!);
|
deepAssign(target[key] as Record<string, unknown>, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
|
|
|
@ -97,7 +97,7 @@ export interface WebSocket {
|
||||||
export function unmask(payload: Uint8Array, mask?: Uint8Array): void {
|
export function unmask(payload: Uint8Array, mask?: Uint8Array): void {
|
||||||
if (mask) {
|
if (mask) {
|
||||||
for (let i = 0, len = payload.length; i < len; i++) {
|
for (let i = 0, len = payload.length; i < len; i++) {
|
||||||
payload[i] ^= mask![i & 3];
|
payload[i] ^= mask[i & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue