0
0
Fork 0
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:
Yusuke Sakurai 2020-02-07 16:23:38 +09:00 committed by GitHub
parent ea6179f7dc
commit c2986891f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 147 additions and 89 deletions

View file

@ -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!");

View file

@ -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] {

View file

@ -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");
}); });

View file

@ -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;

View file

@ -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)) {

View file

@ -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;

View file

@ -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"
); );
} }

View file

@ -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"
); );

View file

@ -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();
}); });

View file

@ -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

View file

@ -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`)
}); });

View file

@ -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);
} }
} }
} }

View file

@ -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;
} }
} }

View file

@ -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);
} }
}); });

View file

@ -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);

View file

@ -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;
} }

View file

@ -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);
}
} }
}); });

View file

@ -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 */

View file

@ -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)) {

View file

@ -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;

View file

@ -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);
} }
}); });

View file

@ -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();

View file

@ -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.

View file

@ -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> {

View file

@ -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;

View file

@ -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];
} }
} }
} }