diff --git a/archive/tar.ts b/archive/tar.ts index 5ef3aa2a7596..c72abc65988c 100644 --- a/archive/tar.ts +++ b/archive/tar.ts @@ -35,8 +35,10 @@ const ustar = "ustar\u000000"; * Simple file reader */ export class FileReader implements Deno.Reader { - private file: Deno.File; + private file?: Deno.File; + constructor(private filePath: string, private mode: Deno.OpenMode = "r") {} + public async read(p: Uint8Array): Promise { if (!this.file) { this.file = await Deno.open(this.filePath, this.mode); @@ -44,7 +46,7 @@ export class FileReader implements Deno.Reader { const res = await Deno.read(this.file.rid, p); if (res.eof) { await Deno.close(this.file.rid); - this.file = null; + this.file = undefined; } return res; } @@ -54,18 +56,21 @@ export class FileReader implements Deno.Reader { * Simple file writer (call FileWriter.dispose() after use) */ export class FileWriter implements Deno.Writer { - private file: Deno.File; + private file?: Deno.File; + constructor(private filePath: string, private mode: Deno.OpenMode = "w") {} + public async write(p: Uint8Array): Promise { if (!this.file) { this.file = await Deno.open(this.filePath, this.mode); } return Deno.write(this.file.rid, p); } + public dispose(): void { if (!this.file) return; Deno.close(this.file.rid); - this.file = null; + this.file = undefined; } } @@ -191,7 +196,7 @@ function formatHeader(data: TarData): Uint8Array { buffer = clean(512); let offset = 0; ustarStructure.forEach(function(value): void { - const entry = encoder.encode(data[value.field] || ""); + const entry = encoder.encode(data[value.field as keyof TarData] || ""); buffer.set(entry, offset); offset += value.length; // space it out with nulls }); @@ -307,12 +312,13 @@ export class Tar { } i--; } - if (i < 0 || fileName.length > 100 || fileNamePrefix.length > 155) { + if (i < 0 || fileName.length > 100 || fileNamePrefix!.length > 155) { throw new Error( "ustar format does not allow a long file name (length of [file name prefix] + / + [file name] must be shorter than 256 bytes)" ); } } + fileNamePrefix = fileNamePrefix!; opts = opts || {}; @@ -344,7 +350,7 @@ export class Tar { fileMode: pad(mode, 7), uid: pad(uid, 7), gid: pad(gid, 7), - fileSize: pad(info ? info.len : opts.contentSize, 11), + fileSize: pad((info ? info.len : opts.contentSize)!, 11), mtime: pad(mtime, 11), checksum: " ", type: "0", // just a file @@ -362,7 +368,7 @@ export class Tar { .filter((key): boolean => ["filePath", "reader"].indexOf(key) < 0) .forEach(function(key): void { checksum += encoder - .encode(tarData[key]) + .encode(tarData[key as keyof TarData]) .reduce((p, c): number => p + c, 0); }); @@ -381,7 +387,7 @@ export class Tar { headerArr = formatHeader(tarData); readers.push(new Deno.Buffer(headerArr)); if (!reader) { - reader = new FileReader(filePath); + reader = new FileReader(filePath!); } readers.push(reader); @@ -390,7 +396,7 @@ export class Tar { new Deno.Buffer( clean( recordSize - - (parseInt(tarData.fileSize, 8) % recordSize || recordSize) + (parseInt(tarData.fileSize!, 8) % recordSize || recordSize) ) ) ); @@ -451,7 +457,7 @@ export class Untar { (key): void => { const arr = trim(header[key]); if (arr.byteLength > 0) { - meta[key] = parseInt(decoder.decode(arr), 8); + meta[key as keyof UntarOptions] = parseInt(decoder.decode(arr), 8); } } ); @@ -459,7 +465,7 @@ export class Untar { (key): void => { const arr = trim(header[key]); if (arr.byteLength > 0) { - meta[key] = decoder.decode(arr); + meta[key as keyof UntarOptions] = decoder.decode(arr); } } ); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ccad44e4f74c..b993f7aafb0c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,7 +14,7 @@ jobs: - script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/' - script: npx eslint **/*.ts --max-warnings=0 - script: deno run --allow-run --allow-write --allow-read format.ts --check - - script: deno run --allow-run --allow-net --allow-write --allow-read test.ts + - script: deno run --allow-run --allow-net --allow-write --allow-read --config=tsconfig.test.json test.ts - job: "Mac" pool: @@ -26,7 +26,7 @@ jobs: - script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/' - script: eslint **/*.ts --max-warnings=0 - script: deno run --allow-run --allow-write --allow-read format.ts --check - - script: deno run --allow-run --allow-net --allow-write --allow-read test.ts + - script: deno run --allow-run --allow-net --allow-write --allow-read --config=tsconfig.test.json test.ts - job: "Windows" pool: @@ -37,4 +37,4 @@ jobs: - bash: echo "##vso[task.prependpath]C:\Users\VssAdministrator\.deno\\bin" - bash: npx eslint **/*.ts --max-warnings=0 - bash: deno.exe run --allow-run --allow-write --allow-read format.ts --check - - bash: deno.exe run --allow-run --allow-net --allow-write --allow-read test.ts + - bash: deno.exe run --allow-run --allow-net --allow-write --allow-read --config=tsconfig.test.json test.ts diff --git a/encoding/csv.ts b/encoding/csv.ts index 191961ace284..aa2ceb1cf053 100644 --- a/encoding/csv.ts +++ b/encoding/csv.ts @@ -28,7 +28,7 @@ export interface ParseOptions { function chkOptions(opt: ParseOptions): void { if ( INVALID_RUNE.includes(opt.comma) || - INVALID_RUNE.includes(opt.comment) || + (opt.comment && INVALID_RUNE.includes(opt.comment)) || opt.comma === opt.comment ) { throw new Error("Invalid Delimiter"); @@ -130,7 +130,7 @@ export async function readAll( } if (lineResult.length > 0) { - if (_nbFields && _nbFields !== lineResult.length) { + if (_nbFields! && _nbFields! !== lineResult.length) { throw new ParseError(lineIndex, lineIndex, "wrong number of fields"); } result.push(lineResult); diff --git a/encoding/csv_test.ts b/encoding/csv_test.ts index 40a2abcef9a9..0cf95b473a7b 100644 --- a/encoding/csv_test.ts +++ b/encoding/csv_test.ts @@ -441,7 +441,7 @@ for (const t of testCases) { if (t.Error) { let err; try { - actual = await readAll(new BufReader(new StringReader(t.Input)), { + actual = await readAll(new BufReader(new StringReader(t.Input!)), { comma: comma, comment: comment, trimLeadingSpace: trim, @@ -454,7 +454,7 @@ for (const t of testCases) { assert(err); assertEquals(err.message, t.Error); } else { - actual = await readAll(new BufReader(new StringReader(t.Input)), { + actual = await readAll(new BufReader(new StringReader(t.Input!)), { comma: comma, comment: comment, trimLeadingSpace: trim, diff --git a/encoding/toml.ts b/encoding/toml.ts index cc96322fb2fc..b47e31bba77a 100644 --- a/encoding/toml.ts +++ b/encoding/toml.ts @@ -3,20 +3,19 @@ import { deepAssign } from "../util/deep_assign.ts"; import { pad } from "../strings/pad.ts"; class KeyValuePair { - key: string; - value: unknown; + constructor(public key: string, public value: unknown) {} } class ParserGroup { - type: string; - name: string; arrValues: unknown[] = []; - objValues: object = {}; + objValues: Record = {}; + + constructor(public type: string, public name: string) {} } class ParserContext { currentGroup?: ParserGroup; - output: object = {}; + output: Record = {}; } class Parser { @@ -27,7 +26,7 @@ class Parser { this.context = new ParserContext(); } _sanitize(): void { - const out = []; + const out: string[] = []; for (let i = 0; i < this.tomlLines.length; i++) { const s = this.tomlLines[i]; const trimmed = s.trim(); @@ -124,28 +123,30 @@ class Parser { this.tomlLines = merged; } _unflat(keys: string[], values: object = {}, cObj: object = {}): object { - let out = {}; + let out: Record = {}; if (keys.length === 0) { return cObj; } else { if (Object.keys(cObj).length === 0) { cObj = values; } - let key = keys.pop(); - out[key] = cObj; + let key: string | undefined = keys.pop(); + if (key) { + out[key] = cObj; + } return this._unflat(keys, values, out); } } _groupToOutput(): void { - const arrProperty = this.context.currentGroup.name - .replace(/"/g, "") + const arrProperty = this.context + .currentGroup!.name.replace(/"/g, "") .replace(/'/g, "") .split("."); let u = {}; - if (this.context.currentGroup.type === "array") { - u = this._unflat(arrProperty, this.context.currentGroup.arrValues); + if (this.context.currentGroup!.type === "array") { + u = this._unflat(arrProperty, this.context.currentGroup!.arrValues); } else { - u = this._unflat(arrProperty, this.context.currentGroup.objValues); + u = this._unflat(arrProperty, this.context.currentGroup!.objValues); } deepAssign(this.context.output, u); delete this.context.currentGroup; @@ -167,22 +168,22 @@ class Parser { if (this.context.currentGroup) { this._groupToOutput(); } - let g = new ParserGroup(); - g.name = line.match(captureReg)[1]; - if (g.name.match(/\[.*\]/)) { - g.type = "array"; - g.name = g.name.match(captureReg)[1]; + + let type; + let name = line.match(captureReg)![1]; + if (name.match(/\[.*\]/)) { + type = "array"; + name = name.match(captureReg)![1]; } else { - g.type = "object"; + type = "object"; } - this.context.currentGroup = g; + this.context.currentGroup = new ParserGroup(type, name); } _processDeclaration(line: string): KeyValuePair { - let kv = new KeyValuePair(); const idx = line.indexOf("="); - kv.key = line.substring(0, idx).trim(); - kv.value = this._parseData(line.slice(idx + 1)); - return kv; + const key = line.substring(0, idx).trim(); + const value = this._parseData(line.slice(idx + 1)); + return new KeyValuePair(key, value); } // TODO (zekth) Need refactor using ACC _parseData(dataString: string): unknown { @@ -353,23 +354,27 @@ class Parser { _cleanOutput(): void { this._propertyClean(this.context.output); } - _propertyClean(obj: object): void { + _propertyClean(obj: Record): void { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { let k = keys[i]; - let v = obj[k]; - let pathDeclaration = this._parseDeclarationName(k); - delete obj[k]; - if (pathDeclaration.length > 1) { - k = pathDeclaration.shift(); - k = k.replace(/"/g, ""); - v = this._unflat(pathDeclaration, v as object); - } else { - k = k.replace(/"/g, ""); - } - obj[k] = v; - if (v instanceof Object) { - this._propertyClean(v); + if (k) { + let v = obj[k]; + let pathDeclaration = this._parseDeclarationName(k); + delete obj[k]; + if (pathDeclaration.length > 1) { + const shift = pathDeclaration.shift(); + if (shift) { + k = shift.replace(/"/g, ""); + v = this._unflat(pathDeclaration, v as object); + } + } else { + k = k.replace(/"/g, ""); + } + obj[k] = v; + if (v instanceof Object) { + this._propertyClean(v); + } } } } @@ -393,18 +398,26 @@ class Dumper { this.output = this._format(); return this.output; } - _parse(obj: object, path: string = ""): string[] { + _parse(obj: Record, path: string = ""): string[] { const out = []; const props = Object.keys(obj); const propObj = props.filter( - (e): boolean => - (obj[e] instanceof Array && !this._isSimplySerializable(obj[e][0])) || - !this._isSimplySerializable(obj[e]) + (e: string): boolean => { + if (obj[e] instanceof Array) { + const d: unknown[] = obj[e] as unknown[]; + return !this._isSimplySerializable(d[0]); + } + return !this._isSimplySerializable(obj[e]); + } ); const propPrim = props.filter( - (e): boolean => - !(obj[e] instanceof Array && !this._isSimplySerializable(obj[e][0])) && - this._isSimplySerializable(obj[e]) + (e: string): boolean => { + if (obj[e] instanceof Array) { + const d: unknown[] = obj[e] as unknown[]; + return this._isSimplySerializable(d[0]); + } + return this._isSimplySerializable(obj[e]); + } ); const k = propPrim.concat(propObj); for (let i = 0; i < k.length; i++) { @@ -435,7 +448,11 @@ class Dumper { } else if (typeof value === "object") { out.push(""); out.push(this._header(path + prop)); - out.push(...this._parse(value, `${path}${prop}.`)); + if (value) { + const toParse: Record = value; + out.push(...this._parse(toParse, `${path}${prop}.`)); + } + // out.push(...this._parse(value, `${path}${prop}.`)); } } out.push(""); diff --git a/flags/all_bool_test.ts b/flags/all_bool_test.ts index 22b6bcd2d23d..711bf3da1adb 100755 --- a/flags/all_bool_test.ts +++ b/flags/all_bool_test.ts @@ -19,7 +19,7 @@ test(function flagBooleanTrue(): void { // flag boolean true only affects double hyphen arguments without equals signs test(function flagBooleanTrueOnlyAffectsDoubleDash(): void { - var argv = parse(["moo", "--honk", "cow", "-p", "55", "--tacos=good"], { + const argv = parse(["moo", "--honk", "cow", "-p", "55", "--tacos=good"], { boolean: true }); diff --git a/flags/dotted_test.ts b/flags/dotted_test.ts index 6a27eb6f7707..e5c69ce6df54 100755 --- a/flags/dotted_test.ts +++ b/flags/dotted_test.ts @@ -8,17 +8,18 @@ test(function dottedAlias(): void { default: { "a.b": 11 }, alias: { "a.b": "aa.bb" } }); + console.log(argv.a); assertEquals(argv.a.b, 22); assertEquals(argv.aa.bb, 22); }); test(function dottedDefault(): void { - const argv = parse("", { default: { "a.b": 11 }, alias: { "a.b": "aa.bb" } }); + const argv = parse([], { default: { "a.b": 11 }, alias: { "a.b": "aa.bb" } }); assertEquals(argv.a.b, 11); assertEquals(argv.aa.bb, 11); }); test(function dottedDefaultWithNoAlias(): void { - const argv = parse("", { default: { "a.b": 11 } }); + const argv = parse([], { default: { "a.b": 11 } }); assertEquals(argv.a.b, 11); }); diff --git a/flags/mod.ts b/flags/mod.ts index 433f4eb154df..7b4451a02d4c 100644 --- a/flags/mod.ts +++ b/flags/mod.ts @@ -1,16 +1,16 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. export interface ArgParsingOptions { - unknown?: Function; + unknown?: (i: unknown) => unknown; boolean?: boolean | string | string[]; alias?: { [key: string]: string | string[] }; string?: string | string[]; - default?: { [key: string]: any }; // eslint-disable-line @typescript-eslint/no-explicit-any + default?: { [key: string]: unknown }; // eslint-disable-line @typescript-eslint/no-explicit-any "--"?: boolean; stopEarly?: boolean; } const DEFAULT_OPTIONS = { - unknown: (i): unknown => i, + unknown: (i: unknown): unknown => i, boolean: false, alias: {}, string: [], @@ -19,16 +19,27 @@ const DEFAULT_OPTIONS = { stopEarly: false }; +interface Flags { + bools: { [key: string]: boolean }; + strings: { [key: string]: boolean }; + unknownFn: (i: unknown) => unknown; + allBools: boolean; +} + +interface NestedMapping { + [key: string]: NestedMapping | unknown; +} + function isNumber(x: unknown): boolean { if (typeof x === "number") return true; if (/^0x[0-9a-f]+$/i.test(String(x))) return true; return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(String(x)); } -function hasKey(obj, keys): boolean { +function hasKey(obj: NestedMapping, keys: string[]): boolean { let o = obj; - keys.slice(0, -1).forEach(function(key): void { - o = o[key] || {}; + keys.slice(0, -1).forEach(function(key: string): void { + o = (o[key] || {}) as NestedMapping; }); const key = keys[keys.length - 1]; @@ -36,7 +47,8 @@ function hasKey(obj, keys): boolean { } export function parse( - args, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: any[], initialOptions?: ArgParsingOptions // eslint-disable-next-line @typescript-eslint/no-explicit-any ): { [key: string]: any } { @@ -45,65 +57,85 @@ export function parse( ...(initialOptions || {}) }; - const flags = { + const flags: Flags = { bools: {}, strings: {}, unknownFn: options.unknown!, allBools: false }; - // TODO: get rid of this, providing two different options - if (typeof options["boolean"] === "boolean" && options["boolean"]) { - flags.allBools = true; - } else { - [] - .concat(options["boolean"]) - .filter(Boolean) - .forEach(function(key): void { - flags.bools[key] = true; - }); + if (options.boolean !== undefined) { + if (typeof options.boolean === "boolean") { + flags.allBools = !!options.boolean; + } else { + const booleanArgs: string[] = + typeof options.boolean === "string" + ? [options.boolean] + : options.boolean; + + booleanArgs.filter(Boolean).forEach( + (key: string): void => { + flags.bools[key] = true; + } + ); + } } - const aliases = {}; - Object.keys(options.alias).forEach(function(key): void { - aliases[key] = [].concat(options.alias[key]); - aliases[key].forEach(function(x): void { - aliases[x] = [key].concat( - aliases[key].filter(function(y): boolean { - return x !== y; - }) - ); - }); - }); + const aliases: { [key: string]: string[] } = {}; + if (options.alias !== undefined) { + for (const key in options.alias) { + const val = options.alias[key]; + + if (typeof val === "string") { + aliases[key] = [val]; + } else { + aliases[key] = val; + } - [] - .concat(options.string) - .filter(Boolean) - .forEach(function(key): void { + for (const alias of aliases[key]) { + aliases[alias] = [key].concat( + aliases[key].filter((y: string): boolean => alias !== y) + ); + } + } + } + + if (options.string !== undefined) { + const stringArgs = + typeof options.string === "string" ? [options.string] : options.string; + + stringArgs.filter(Boolean).forEach(function(key): void { flags.strings[key] = true; if (aliases[key]) { - flags.strings[aliases[key]] = true; + aliases[key].forEach( + (alias: string): void => { + flags.strings[alias] = true; + } + ); } }); + } const defaults = options.default!; - const argv = { _: [] }; + const argv: { [key: string]: unknown[] } = { _: [] }; - function argDefined(key, arg): boolean { + function argDefined(key: string, arg: string): boolean { return ( (flags.allBools && /^--[^=]+$/.test(arg)) || - flags.strings[key] || flags.bools[key] || - aliases[key] + !!flags.strings[key] || + !!aliases[key] ); } - function setKey(obj, keys, value): void { + function setKey(obj: NestedMapping, keys: string[], value: unknown): void { let o = obj; keys.slice(0, -1).forEach(function(key): void { - if (o[key] === undefined) o[key] = {}; - o = o[key]; + if (o[key] === undefined) { + o[key] = {}; + } + o = o[key] as NestedMapping; }); const key = keys[keys.length - 1]; @@ -114,13 +146,17 @@ export function parse( ) { o[key] = value; } else if (Array.isArray(o[key])) { - o[key].push(value); + (o[key] as unknown[]).push(value); } else { o[key] = [o[key], value]; } } - function setArg(key, val, arg = null): void { + function setArg( + key: string, + val: unknown, + arg: string | undefined = undefined + ): void { if (arg && flags.unknownFn && !argDefined(key, arg)) { if (flags.unknownFn(arg) === false) return; } @@ -133,7 +169,7 @@ export function parse( }); } - function aliasIsBoolean(key): boolean { + function aliasIsBoolean(key: string): boolean { return aliases[key].some(function(x): boolean { return flags.bools[x]; }); @@ -143,8 +179,9 @@ export function parse( setArg(key, defaults[key] === undefined ? false : defaults[key]); }); - let notFlags = []; + let notFlags: string[] = []; + // all args after "--" are not parsed if (args.indexOf("--") !== -1) { notFlags = args.slice(args.indexOf("--") + 1); args = args.slice(0, args.indexOf("--")); @@ -157,18 +194,21 @@ export function parse( // Using [\s\S] instead of . because js doesn't support the // 'dotall' regex modifier. See: // http://stackoverflow.com/a/1068308/13216 - const m = arg.match(/^--([^=]+)=([\s\S]*)$/); + const m = arg.match(/^--([^=]+)=([\s\S]*)$/)!; const key = m[1]; - let value = m[2]; + const value = m[2]; + if (flags.bools[key]) { - value = value !== "false"; + const booleanValue = value !== "false"; + setArg(key, booleanValue, arg); + } else { + setArg(key, value, arg); } - setArg(key, value, arg); } else if (/^--no-.+/.test(arg)) { - const key = arg.match(/^--no-(.+)/)[1]; + const key = arg.match(/^--no-(.+)/)![1]; setArg(key, false, arg); } else if (/^--.+/.test(arg)) { - const key = arg.match(/^--(.+)/)[1]; + const key = arg.match(/^--(.+)/)![1]; const next = args[i + 1]; if ( next !== undefined && diff --git a/flags/unknown_test.ts b/flags/unknown_test.ts index 84d4db8995bb..dde725a75d4a 100755 --- a/flags/unknown_test.ts +++ b/flags/unknown_test.ts @@ -4,8 +4,8 @@ import { assertEquals } from "../testing/asserts.ts"; import { parse } from "./mod.ts"; test(function booleanAndAliasIsNotUnknown(): void { - const unknown = []; - function unknownFn(arg): boolean { + const unknown: unknown[] = []; + function unknownFn(arg: unknown): boolean { unknown.push(arg); return false; } @@ -23,8 +23,8 @@ test(function booleanAndAliasIsNotUnknown(): void { }); test(function flagBooleanTrueAnyDoubleHyphenArgumentIsNotUnknown(): void { - const unknown = []; - function unknownFn(arg): boolean { + const unknown: unknown[] = []; + function unknownFn(arg: unknown): boolean { unknown.push(arg); return false; } @@ -40,8 +40,8 @@ test(function flagBooleanTrueAnyDoubleHyphenArgumentIsNotUnknown(): void { }); test(function stringAndAliasIsNotUnkown(): void { - const unknown = []; - function unknownFn(arg): boolean { + const unknown: unknown[] = []; + function unknownFn(arg: unknown): boolean { unknown.push(arg); return false; } @@ -59,8 +59,8 @@ test(function stringAndAliasIsNotUnkown(): void { }); test(function defaultAndAliasIsNotUnknown(): void { - const unknown = []; - function unknownFn(arg): boolean { + const unknown: unknown[] = []; + function unknownFn(arg: unknown): boolean { unknown.push(arg); return false; } @@ -78,8 +78,8 @@ test(function defaultAndAliasIsNotUnknown(): void { }); test(function valueFollowingDoubleHyphenIsNotUnknown(): void { - const unknown = []; - function unknownFn(arg): boolean { + const unknown: unknown[] = []; + function unknownFn(arg: unknown): boolean { unknown.push(arg); return false; } diff --git a/fs/copy.ts b/fs/copy.ts index d02ca290f056..b51106e3ab6b 100644 --- a/fs/copy.ts +++ b/fs/copy.ts @@ -22,7 +22,7 @@ async function ensureValidCopy( options: CopyOptions, isCopyFolder: boolean = false ): Promise { - let destStat: Deno.FileInfo; + let destStat: Deno.FileInfo | null; destStat = await Deno.lstat(dest).catch( (): Promise => Promise.resolve(null) @@ -39,7 +39,7 @@ async function ensureValidCopy( } } - return destStat; + return destStat!; } function ensureValidCopySync( @@ -48,7 +48,7 @@ function ensureValidCopySync( options: CopyOptions, isCopyFolder: boolean = false ): Deno.FileInfo { - let destStat: Deno.FileInfo; + let destStat: Deno.FileInfo | null; try { destStat = Deno.lstatSync(dest); @@ -56,8 +56,8 @@ function ensureValidCopySync( // ignore error } - if (destStat) { - if (isCopyFolder && !destStat.isDirectory()) { + if (destStat!) { + if (isCopyFolder && !destStat!.isDirectory()) { throw new Error( `Cannot overwrite non-directory '${dest}' with directory '${src}'.` ); @@ -67,7 +67,7 @@ function ensureValidCopySync( } } - return destStat; + return destStat!; } /* copy file to dest */ @@ -80,7 +80,7 @@ async function copyFile( await Deno.copyFile(src, dest); if (options.preserveTimestamps) { const statInfo = await Deno.stat(src); - await Deno.utime(dest, statInfo.accessed, statInfo.modified); + await Deno.utime(dest, statInfo.accessed!, statInfo.modified!); } } /* copy file to dest synchronously */ @@ -89,7 +89,7 @@ function copyFileSync(src: string, dest: string, options: CopyOptions): void { Deno.copyFileSync(src, dest); if (options.preserveTimestamps) { const statInfo = Deno.statSync(src); - Deno.utimeSync(dest, statInfo.accessed, statInfo.modified); + Deno.utimeSync(dest, statInfo.accessed!, statInfo.modified!); } } @@ -105,7 +105,7 @@ async function copySymLink( await Deno.symlink(originSrcFilePath, dest, type); if (options.preserveTimestamps) { const statInfo = await Deno.lstat(src); - await Deno.utime(dest, statInfo.accessed, statInfo.modified); + await Deno.utime(dest, statInfo.accessed!, statInfo.modified!); } } @@ -121,7 +121,7 @@ function copySymlinkSync( Deno.symlinkSync(originSrcFilePath, dest, type); if (options.preserveTimestamps) { const statInfo = Deno.lstatSync(src); - Deno.utimeSync(dest, statInfo.accessed, statInfo.modified); + Deno.utimeSync(dest, statInfo.accessed!, statInfo.modified!); } } @@ -139,13 +139,13 @@ async function copyDir( if (options.preserveTimestamps) { const srcStatInfo = await Deno.stat(src); - await Deno.utime(dest, srcStatInfo.accessed, srcStatInfo.modified); + await Deno.utime(dest, srcStatInfo.accessed!, srcStatInfo.modified!); } const files = await Deno.readDir(src); for (const file of files) { - const srcPath = path.join(src, file.name); + const srcPath = path.join(src, file.name!); const destPath = path.join(dest, path.basename(srcPath as string)); if (file.isDirectory()) { await copyDir(srcPath, destPath, options); @@ -167,13 +167,13 @@ function copyDirSync(src: string, dest: string, options: CopyOptions): void { if (options.preserveTimestamps) { const srcStatInfo = Deno.statSync(src); - Deno.utimeSync(dest, srcStatInfo.accessed, srcStatInfo.modified); + Deno.utimeSync(dest, srcStatInfo.accessed!, srcStatInfo.modified!); } const files = Deno.readDirSync(src); for (const file of files) { - const srcPath = path.join(src, file.name); + const srcPath = path.join(src, file.name!); const destPath = path.join(dest, path.basename(srcPath as string)); if (file.isDirectory()) { copyDirSync(srcPath, destPath, options); diff --git a/fs/globrex.ts b/fs/globrex.ts index 439cea348860..56def02f8187 100644 --- a/fs/globrex.ts +++ b/fs/globrex.ts @@ -66,7 +66,7 @@ export function globrex( // Helper function to build string and segments function add( - str, + str: string, options: AddOptions = { split: false, last: false, only: "" } ): void { const { split, last, only } = options; @@ -114,13 +114,13 @@ export function globrex( if (c === ")") { if (ext.length) { add(c); - let type = ext.pop(); + let type: string | undefined = ext.pop(); if (type === "@") { add("{1}"); } else if (type === "!") { add("([^/]*)"); } else { - add(type); + add(type as string); } continue; } diff --git a/fs/globrex_test.ts b/fs/globrex_test.ts index 34821b6203d5..c6732b9ea788 100644 --- a/fs/globrex_test.ts +++ b/fs/globrex_test.ts @@ -5,29 +5,45 @@ import { test } from "../testing/mod.ts"; import { assertEquals } from "../testing/asserts.ts"; import { globrex, GlobrexResult } from "./globrex.ts"; +import { GlobOptions } from "./glob.ts"; const isWin = Deno.build.os === "win"; const t = { equal: assertEquals, is: assertEquals }; -function match(glob, strUnix, strWin?, opts = {}): boolean { +function match( + glob: string, + strUnix: string, + strWin?: string | object, + opts = {} +): boolean { if (typeof strWin === "object") { opts = strWin; - strWin = false; + strWin = ""; } let res = globrex(glob, opts); return res.regex.test(isWin && strWin ? strWin : strUnix); } -function matchRegex(t, pattern, ifUnix, ifWin, opts): GlobrexResult { +function matchRegex( + pattern: string, + ifUnix: string, + ifWin: string, + opts: GlobOptions +): GlobrexResult { const res = globrex(pattern, opts); - const { regex } = opts.filepath ? res.path : res; + const { regex } = opts.filepath ? res.path! : res; t.is(regex.toString(), isWin ? ifWin : ifUnix, "~> regex matches expectant"); return res; } -function matchSegments(t, pattern, ifUnix, ifWin, opts): GlobrexResult { +function matchSegments( + pattern: string, + ifUnix: RegExp[], + ifWin: RegExp[], + opts: GlobOptions +): GlobrexResult { const res = globrex(pattern, { filepath: true, ...opts }); - const str = res.path.segments.join(" "); + const str = res.path!.segments.join(" "); const exp = (isWin ? ifWin : ifUnix).join(" "); t.is(str, exp); return res; @@ -191,7 +207,7 @@ test({ t.equal(match("f?o", "fooo", { extended: true }), false); t.equal(match("f?oo", "foo", { extended: true }), false); - const tester = (globstar): void => { + const tester = (globstar: boolean): void => { t.equal( match("f?o", "foo", { extended: true, globstar, flags: "g" }), true @@ -235,7 +251,7 @@ test({ t.equal(match("fo[!tz]", "fot", { extended: true }), false); t.equal(match("fo[!tz]", "fob", { extended: true }), true); - const tester = (globstar): void => { + const tester = (globstar: boolean): void => { t.equal( match("fo[oz]", "foo", { extended: true, globstar, flags: "g" }), true @@ -321,7 +337,7 @@ test({ t.equal(match("foo{bar,baaz}", "foobuzz", { extended: true }), false); t.equal(match("foo{bar,b*z}", "foobuzz", { extended: true }), true); - const tester = (globstar): void => { + const tester = (globstar: boolean): void => { t.equal( match("foo{bar,baaz}", "foobaaz", { extended: true, @@ -405,7 +421,7 @@ test({ false ); - const tester = (globstar): void => { + const tester = (globstar: boolean): void => { t.equal( match( "http://?o[oz].b*z.com/{*.js,*.html}", @@ -456,7 +472,7 @@ test({ test({ name: "globrex: standard globstar", fn(): void { - const tester = (globstar): void => { + const tester = (globstar: boolean): void => { t.equal( match( "http://foo.com/**/{*.js,*.html}", @@ -491,7 +507,7 @@ test({ test({ name: "globrex: remaining chars should match themself", fn(): void { - const tester = (globstar): void => { + const tester = (globstar: boolean): void => { const testExtStr = "\\/$^+.()=!|,.*"; t.equal(match(testExtStr, testExtStr, { extended: true }), true); t.equal( @@ -801,47 +817,43 @@ test({ res = globrex("", opts); t.is(res.hasOwnProperty("path"), true); - t.is(res.path.hasOwnProperty("regex"), true); - t.is(res.path.hasOwnProperty("segments"), true); - t.is(Array.isArray(res.path.segments), true); + t.is(res.path!.hasOwnProperty("regex"), true); + t.is(res.path!.hasOwnProperty("segments"), true); + t.is(Array.isArray(res.path!.segments), true); pattern = "foo/bar/baz.js"; res = matchRegex( - t, pattern, "/^foo\\/bar\\/baz\\.js$/", "/^foo\\\\+bar\\\\+baz\\.js$/", opts ); - t.is(res.path.segments.length, 3); + t.is(res.path!.segments.length, 3); res = matchRegex( - t, "../foo/bar.js", "/^\\.\\.\\/foo\\/bar\\.js$/", "/^\\.\\.\\\\+foo\\\\+bar\\.js$/", opts ); - t.is(res.path.segments.length, 3); + t.is(res.path!.segments.length, 3); res = matchRegex( - t, "*/bar.js", "/^.*\\/bar\\.js$/", "/^.*\\\\+bar\\.js$/", opts ); - t.is(res.path.segments.length, 2); + t.is(res.path!.segments.length, 2); opts.globstar = true; res = matchRegex( - t, "**/bar.js", "/^((?:[^\\/]*(?:\\/|$))*)bar\\.js$/", "/^((?:[^\\\\]*(?:\\\\|$))*)bar\\.js$/", opts ); - t.is(res.path.segments.length, 2); + t.is(res.path!.segments.length, 2); } }); @@ -854,42 +866,42 @@ test({ unix = [/^foo$/, /^bar$/, /^([^\/]*)$/, /^baz\.(md|js|txt)$/]; win = [/^foo$/, /^bar$/, /^([^\\]*)$/, /^baz\.(md|js|txt)$/]; - matchSegments(t, "foo/bar/*/baz.{md,js,txt}", unix, win, { + matchSegments("foo/bar/*/baz.{md,js,txt}", unix, win, { ...opts, globstar: true }); unix = [/^foo$/, /^.*$/, /^baz\.md$/]; win = [/^foo$/, /^.*$/, /^baz\.md$/]; - matchSegments(t, "foo/*/baz.md", unix, win, opts); + matchSegments("foo/*/baz.md", unix, win, opts); unix = [/^foo$/, /^.*$/, /^baz\.md$/]; win = [/^foo$/, /^.*$/, /^baz\.md$/]; - matchSegments(t, "foo/**/baz.md", unix, win, opts); + matchSegments("foo/**/baz.md", unix, win, opts); unix = [/^foo$/, /^((?:[^\/]*(?:\/|$))*)$/, /^baz\.md$/]; win = [/^foo$/, /^((?:[^\\]*(?:\\|$))*)$/, /^baz\.md$/]; - matchSegments(t, "foo/**/baz.md", unix, win, { ...opts, globstar: true }); + matchSegments("foo/**/baz.md", unix, win, { ...opts, globstar: true }); unix = [/^foo$/, /^.*$/, /^.*\.md$/]; win = [/^foo$/, /^.*$/, /^.*\.md$/]; - matchSegments(t, "foo/**/*.md", unix, win, opts); + matchSegments("foo/**/*.md", unix, win, opts); unix = [/^foo$/, /^((?:[^\/]*(?:\/|$))*)$/, /^([^\/]*)\.md$/]; win = [/^foo$/, /^((?:[^\\]*(?:\\|$))*)$/, /^([^\\]*)\.md$/]; - matchSegments(t, "foo/**/*.md", unix, win, { ...opts, globstar: true }); + matchSegments("foo/**/*.md", unix, win, { ...opts, globstar: true }); unix = [/^foo$/, /^:$/, /^b:az$/]; win = [/^foo$/, /^:$/, /^b:az$/]; - matchSegments(t, "foo/:/b:az", unix, win, opts); + matchSegments("foo/:/b:az", unix, win, opts); unix = [/^foo$/, /^baz\.md$/]; win = [/^foo$/, /^baz\.md$/]; - matchSegments(t, "foo///baz.md", unix, win, { ...opts, strict: true }); + matchSegments("foo///baz.md", unix, win, { ...opts, strict: true }); unix = [/^foo$/, /^baz\.md$/]; win = [/^foo$/, /^baz\.md$/]; - matchSegments(t, "foo///baz.md", unix, win, { ...opts, strict: false }); + matchSegments("foo///baz.md", unix, win, { ...opts, strict: false }); } }); diff --git a/fs/path/join_test.ts b/fs/path/join_test.ts index d82a1b47109a..2c0f35e48260 100644 --- a/fs/path/join_test.ts +++ b/fs/path/join_test.ts @@ -108,18 +108,21 @@ const windowsJoinTests = [ test(function join() { joinTests.forEach(function(p) { - const actual = path.posix.join.apply(null, p[0]); + const _p = p[0] as string[]; + const actual = path.posix.join.apply(null, _p); assertEquals(actual, p[1]); }); }); test(function joinWin32() { joinTests.forEach(function(p) { - const actual = path.win32.join.apply(null, p[0]).replace(backslashRE, "/"); + const _p = p[0] as string[]; + const actual = path.win32.join.apply(null, _p).replace(backslashRE, "/"); assertEquals(actual, p[1]); }); windowsJoinTests.forEach(function(p) { - const actual = path.win32.join.apply(null, p[0]); + const _p = p[0] as string[]; + const actual = path.win32.join.apply(null, _p); assertEquals(actual, p[1]); }); }); diff --git a/fs/path/parse_format_test.ts b/fs/path/parse_format_test.ts index 05327a13950c..8829891da5f7 100644 --- a/fs/path/parse_format_test.ts +++ b/fs/path/parse_format_test.ts @@ -79,8 +79,8 @@ const unixSpecialCaseFormatTests = [ [{}, ""] ]; -function checkParseFormat(path, paths): void { - paths.forEach(function(p) { +function checkParseFormat(path: any, paths: any): void { + paths.forEach(function(p: Record[]) { const element = p[0]; const output = path.parse(element); assertEquals(typeof output.root, "string"); @@ -95,8 +95,8 @@ function checkParseFormat(path, paths): void { }); } -function checkSpecialCaseParseFormat(path, testCases): void { - testCases.forEach(function(testCase) { +function checkSpecialCaseParseFormat(path: any, testCases: any): void { + testCases.forEach(function(testCase: Record[]) { const element = testCase[0]; const expect = testCase[1]; const output = path.parse(element); @@ -106,7 +106,7 @@ function checkSpecialCaseParseFormat(path, testCases): void { }); } -function checkFormat(path, testCases): void { +function checkFormat(path: any, testCases: unknown[][]): void { testCases.forEach(function(testCase) { assertEquals(path.format(testCase[0]), testCase[1]); }); diff --git a/fs/path/resolve_test.ts b/fs/path/resolve_test.ts index 7ee9513c1405..606570aadb3e 100644 --- a/fs/path/resolve_test.ts +++ b/fs/path/resolve_test.ts @@ -37,14 +37,16 @@ const posixTests = test(function resolve() { posixTests.forEach(function(p) { - const actual = path.posix.resolve.apply(null, p[0]); + const _p = p[0] as string[]; + const actual = path.posix.resolve.apply(null, _p); assertEquals(actual, p[1]); }); }); test(function resolveWin32() { windowsTests.forEach(function(p) { - const actual = path.win32.resolve.apply(null, p[0]); + const _p = p[0] as string[]; + const actual = path.win32.resolve.apply(null, _p); assertEquals(actual, p[1]); }); }); diff --git a/fs/path/utils.ts b/fs/path/utils.ts index e50cb6d3c49e..7a4cd7299e07 100644 --- a/fs/path/utils.ts +++ b/fs/path/utils.ts @@ -49,7 +49,7 @@ export function normalizeString( let code: number; for (let i = 0, len = path.length; i <= len; ++i) { if (i < len) code = path.charCodeAt(i); - else if (isPathSeparator(code)) break; + else if (isPathSeparator(code!)) break; else code = CHAR_FORWARD_SLASH; if (isPathSeparator(code)) { @@ -107,7 +107,7 @@ export function _format( sep: string, pathObject: FormatInputPathObject ): string { - const dir: string | null = pathObject.dir || pathObject.root; + const dir: string | undefined = pathObject.dir || pathObject.root; const base: string = pathObject.base || (pathObject.name || "") + (pathObject.ext || ""); if (!dir) return base; diff --git a/fs/path/win32.ts b/fs/path/win32.ts index 6b906bc7b3e2..d42cc4885d99 100644 --- a/fs/path/win32.ts +++ b/fs/path/win32.ts @@ -171,7 +171,7 @@ export function normalize(path: string): string { const len = path.length; if (len === 0) return "."; let rootEnd = 0; - let device: string; + let device: string | undefined; let isAbsolute = false; const code = path.charCodeAt(0); @@ -301,7 +301,7 @@ export function join(...paths: string[]): string { const pathsCount = paths.length; if (pathsCount === 0) return "."; - let joined: string; + let joined: string | undefined; let firstPart: string; for (let i = 0; i < pathsCount; ++i) { let path = paths[i]; @@ -329,6 +329,7 @@ export function join(...paths: string[]): string { // path.join('//server', 'share') -> '\\\\server\\share\\') let needsReplace = true; let slashCount = 0; + firstPart = firstPart!; if (isPathSeparator(firstPart.charCodeAt(0))) { ++slashCount; const firstLen = firstPart.length; diff --git a/fs/utils.ts b/fs/utils.ts index 83390ad706ed..ab5bf2f0ef63 100644 --- a/fs/utils.ts +++ b/fs/utils.ts @@ -16,10 +16,14 @@ export function isSubdir( } const srcArray = src.split(sep); const destArray = dest.split(sep); - - return srcArray.reduce((acc, current, i): boolean => { - return acc && destArray[i] === current; - }, true); + // see: https://github.com/Microsoft/TypeScript/issues/30821 + return srcArray.reduce( + // @ts-ignore + (acc: true, current: string, i: number): boolean => { + return acc && destArray[i] === current; + }, + true + ); } export type PathType = "file" | "dir" | "symlink"; @@ -29,7 +33,7 @@ export type PathType = "file" | "dir" | "symlink"; * * @param fileInfo A FileInfo describes a file and is returned by `stat`, `lstat` */ -export function getFileInfoType(fileInfo: Deno.FileInfo): PathType { +export function getFileInfoType(fileInfo: Deno.FileInfo): PathType | undefined { return fileInfo.isFile() ? "file" : fileInfo.isDirectory() diff --git a/fs/walk.ts b/fs/walk.ts index 5cfd7e63dbef..4520fe1746d2 100644 --- a/fs/walk.ts +++ b/fs/walk.ts @@ -71,7 +71,7 @@ export async function* walk( root: string, options: WalkOptions = {} ): AsyncIterableIterator { - options.maxDepth -= 1; + options.maxDepth! -= 1; let ls: FileInfo[] = []; try { ls = await readDir(root); @@ -90,14 +90,14 @@ export async function* walk( } } - const filename = join(root, info.name); + const filename = join(root, info.name!); if (info.isFile()) { if (include(filename, options)) { yield { filename, info }; } } else { - if (!(options.maxDepth < 0)) { + if (!(options.maxDepth! < 0)) { yield* walk(filename, options); } } @@ -109,7 +109,7 @@ export function* walkSync( root: string = ".", options: WalkOptions = {} ): IterableIterator { - options.maxDepth -= 1; + options.maxDepth! -= 1; let ls: FileInfo[] = []; try { ls = readDirSync(root); @@ -127,14 +127,14 @@ export function* walkSync( } } - const filename = join(root, info.name); + const filename = join(root, info.name!); if (info.isFile()) { if (include(filename, options)) { yield { filename, info }; } } else { - if (!(options.maxDepth < 0)) { + if (!(options.maxDepth! < 0)) { yield* walkSync(filename, options); } } diff --git a/fs/walk_test.ts b/fs/walk_test.ts index 20e105a52641..1111f9f00f63 100644 --- a/fs/walk_test.ts +++ b/fs/walk_test.ts @@ -5,7 +5,7 @@ import { test, TestFunction, runIfMain } from "../testing/mod.ts"; import { assertEquals } from "../testing/asserts.ts"; export async function testWalk( - setup: (string) => void | Promise, + setup: (arg0: string) => void | Promise, t: TestFunction ): Promise { const name = t.name; diff --git a/http/cookie.ts b/http/cookie.ts index 900d2941be2e..026ed19848e0 100644 --- a/http/cookie.ts +++ b/http/cookie.ts @@ -45,8 +45,8 @@ function toString(cookie: Cookie): string { if (cookie.httpOnly) { out.push("HttpOnly"); } - if (Number.isInteger(cookie.maxAge)) { - assert(cookie.maxAge > 0, "Max-Age must be an integer superior to 0"); + if (Number.isInteger(cookie.maxAge!)) { + assert(cookie.maxAge! > 0, "Max-Age must be an integer superior to 0"); out.push(`Max-Age=${cookie.maxAge}`); } if (cookie.domain) { @@ -75,10 +75,10 @@ function toString(cookie: Cookie): string { export function getCookies(req: ServerRequest): Cookies { if (req.headers.has("Cookie")) { const out: Cookies = {}; - const c = req.headers.get("Cookie").split(";"); + const c = req.headers.get("Cookie")!.split(";"); for (const kv of c) { const cookieVal = kv.split("="); - const key = cookieVal.shift().trim(); + const key = cookieVal.shift()!.trim(); out[key] = cookieVal.join("="); } return out; diff --git a/http/cookie_test.ts b/http/cookie_test.ts index 4b4e2759d469..3d2e98afc57e 100644 --- a/http/cookie_test.ts +++ b/http/cookie_test.ts @@ -38,7 +38,7 @@ test({ let res: Response = {}; delCookie(res, "deno"); assertEquals( - res.headers.get("Set-Cookie"), + res.headers!.get("Set-Cookie"), "deno=; Expires=Thus, 01 Jan 1970 00:00:00 GMT" ); } diff --git a/http/file_server_test.ts b/http/file_server_test.ts index 1e2d86c4da1c..201524e7b0fb 100644 --- a/http/file_server_test.ts +++ b/http/file_server_test.ts @@ -6,7 +6,8 @@ import { assert, assertEquals } from "../testing/asserts.ts"; import { BufReader, EOF } from "../io/bufio.ts"; import { TextProtoReader } from "../textproto/mod.ts"; -let fileServer; +let fileServer: Deno.Process; + async function startFileServer(): Promise { fileServer = run({ args: [ @@ -21,14 +22,14 @@ async function startFileServer(): Promise { stdout: "piped" }); // Once fileServer is ready it will write to its stdout. - const r = new TextProtoReader(new BufReader(fileServer.stdout)); + const r = new TextProtoReader(new BufReader(fileServer.stdout!)); const s = await r.readLine(); assert(s !== EOF && s.includes("server listening")); } function killFileServer(): void { fileServer.close(); - fileServer.stdout.close(); + fileServer.stdout!.close(); } test(async function serveFile(): Promise { diff --git a/http/racing_server_test.ts b/http/racing_server_test.ts index f98072c16fa7..5433665019dc 100644 --- a/http/racing_server_test.ts +++ b/http/racing_server_test.ts @@ -5,20 +5,20 @@ import { assert, assertEquals } from "../testing/asserts.ts"; import { BufReader, EOF } from "../io/bufio.ts"; import { TextProtoReader } from "../textproto/mod.ts"; -let server; +let server: Deno.Process; async function startServer(): Promise { server = run({ args: ["deno", "run", "-A", "http/racing_server.ts"], stdout: "piped" }); // Once fileServer is ready it will write to its stdout. - const r = new TextProtoReader(new BufReader(server.stdout)); + const r = new TextProtoReader(new BufReader(server.stdout!)); const s = await r.readLine(); assert(s !== EOF && s.includes("Racing server listening...")); } function killServer(): void { server.close(); - server.stdout.close(); + server.stdout!.close(); } let input = `GET / HTTP/1.1 diff --git a/http/server.ts b/http/server.ts index 5ea52a0b8d9e..5c56a2ec2bf2 100644 --- a/http/server.ts +++ b/http/server.ts @@ -73,11 +73,10 @@ export async function writeResponse(w: Writer, r: Response): Promise { let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`; setContentLength(r); + const headers = r.headers!; - if (r.headers) { - for (const [key, value] of r.headers) { - out += `${key}: ${value}\r\n`; - } + for (const [key, value] of headers!) { + out += `${key}: ${value}\r\n`; } out += "\r\n"; @@ -88,8 +87,8 @@ export async function writeResponse(w: Writer, r: Response): Promise { if (r.body instanceof Uint8Array) { const n = await writer.write(r.body); assert(n === r.body.byteLength); - } else if (r.headers.has("content-length")) { - const bodyLength = parseInt(r.headers.get("content-length")); + } else if (headers.has("content-length")) { + const bodyLength = parseInt(headers.get("content-length")!); const n = await copy(writer, r.body); assert(n === bodyLength); } else { @@ -99,19 +98,19 @@ export async function writeResponse(w: Writer, r: Response): Promise { } export class ServerRequest { - url: string; - method: string; - proto: string; - protoMinor: number; - protoMajor: number; - headers: Headers; - r: BufReader; - w: BufWriter; + url!: string; + method!: string; + proto!: string; + protoMinor!: number; + protoMajor!: number; + headers!: Headers; + r!: BufReader; + w!: BufWriter; done: Deferred = deferred(); public async *bodyStream(): AsyncIterableIterator { if (this.headers.has("content-length")) { - const len = +this.headers.get("content-length"); + const len = +this.headers.get("content-length")!; if (Number.isNaN(len)) { return new Uint8Array(0); } @@ -128,7 +127,7 @@ export class ServerRequest { } else { if (this.headers.has("transfer-encoding")) { const transferEncodings = this.headers - .get("transfer-encoding") + .get("transfer-encoding")! .split(",") .map((e): string => e.trim().toLowerCase()); if (transferEncodings.includes("chunked")) { @@ -334,14 +333,14 @@ export class Server implements AsyncIterable { // Wait for the request to be processed before we accept a new request on // this connection. - await req.done; + await req!.done; } - if (req === EOF) { + if (req! === EOF) { // The connection was gracefully closed. } else if (err) { // An error was thrown while parsing request headers. - await writeResponse(req.w, { + await writeResponse(req!.w, { status: 400, body: new TextEncoder().encode(`${err.message}\r\n\r\n`) }); diff --git a/http/server_test.ts b/http/server_test.ts index e24ab0be9f49..2a6163d91426 100644 --- a/http/server_test.ts +++ b/http/server_test.ts @@ -336,65 +336,64 @@ malformedHeader // https://github.com/golang/go/blob/go1.12.5/src/net/http/request_test.go#L377-L443 // TODO(zekth) fix tests test(async function testReadRequestError(): Promise { - const testCases = { - 0: { + const testCases = [ + { in: "GET / HTTP/1.1\r\nheader: foo\r\n\r\n", headers: [{ key: "header", value: "foo" }] }, - 1: { + { in: "GET / HTTP/1.1\r\nheader:foo\r\n", err: UnexpectedEOFError }, - 2: { in: "", err: EOF }, - 3: { + { in: "", err: EOF }, + { in: "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n", err: "http: method cannot contain a Content-Length" }, - 4: { + { in: "HEAD / HTTP/1.1\r\n\r\n", headers: [] }, // Multiple Content-Length values should either be // deduplicated if same or reject otherwise // See Issue 16490. - 5: { + { in: "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 0\r\n\r\nGopher hey\r\n", err: "cannot contain multiple Content-Length headers" }, - 6: { + { in: "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 6\r\n\r\nGopher\r\n", err: "cannot contain multiple Content-Length headers" }, - 7: { + { in: "PUT / HTTP/1.1\r\nContent-Length: 6 \r\nContent-Length: 6\r\nContent-Length:6\r\n\r\nGopher\r\n", headers: [{ key: "Content-Length", value: "6" }] }, - 8: { + { in: "PUT / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 6 \r\n\r\n", err: "cannot contain multiple Content-Length headers" }, // Setting an empty header is swallowed by textproto // see: readMIMEHeader() - // 9: { + // { // in: "POST / HTTP/1.1\r\nContent-Length:\r\nContent-Length: 3\r\n\r\n", // err: "cannot contain multiple Content-Length headers" // }, - 10: { + { in: "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n", headers: [{ key: "Content-Length", value: "0" }] }, - 11: { + { in: "POST / HTTP/1.1\r\nContent-Length:0\r\ntransfer-encoding: chunked\r\n\r\n", headers: [], err: "http: Transfer-Encoding and Content-Length cannot be send together" } - }; - for (const p in testCases) { - const test = testCases[p]; + ]; + for (const test of testCases) { const reader = new BufReader(new StringReader(test.in)); let err; let req; @@ -408,12 +407,12 @@ test(async function testReadRequestError(): Promise { } else if (typeof test.err === "string") { assertEquals(err.message, test.err); } else if (test.err) { - assert(err instanceof test.err); + assert(err instanceof (test.err as typeof UnexpectedEOFError)); } else { assertEquals(err, undefined); assertNotEquals(req, EOF); - for (const h of test.headers) { - assertEquals(req.headers.get(h.key), h.value); + for (const h of test.headers!) { + assertEquals((req! as ServerRequest).headers.get(h.key), h.value); } } } diff --git a/io/bufio.ts b/io/bufio.ts index 815c94eed8cd..99b5638161f0 100644 --- a/io/bufio.ts +++ b/io/bufio.ts @@ -40,8 +40,8 @@ export interface ReadLineResult { /** BufReader implements buffering for a Reader object. */ export class BufReader implements Reader { - private buf: Uint8Array; - private rd: Reader; // Reader provided by caller. + private buf!: Uint8Array; + private rd!: Reader; // Reader provided by caller. private r = 0; // buf read position. private w = 0; // buf write position. private eof = false; @@ -342,7 +342,7 @@ export class BufReader implements Reader { try { await this._fill(); } catch (err) { - err.partial = slice; + err.partial = slice!; throw err; } } @@ -439,7 +439,7 @@ export class BufWriter implements Writer { if (this.err !== null) throw this.err; if (this.n === 0) return; - let n: number; + let n = 0; try { n = await this.wr.write(this.buf.subarray(0, this.n)); } catch (e) { @@ -479,7 +479,7 @@ export class BufWriter implements Writer { if (p.length === 0) return 0; let nn = 0; - let n: number; + let n = 0; while (p.byteLength > this.available()) { if (this.buffered() === 0) { // Large write, empty buffer. diff --git a/io/writers.ts b/io/writers.ts index 86901872892d..de070d48a35d 100644 --- a/io/writers.ts +++ b/io/writers.ts @@ -6,6 +6,7 @@ import { decode, encode } from "../strings/mod.ts"; export class StringWriter implements Writer { private chunks: Uint8Array[] = []; private byteLength: number = 0; + private cache: string | undefined; constructor(private base: string = "") { const c = encode(base); @@ -16,12 +17,10 @@ export class StringWriter implements Writer { async write(p: Uint8Array): Promise { this.chunks.push(p); this.byteLength += p.byteLength; - this.cache = null; + this.cache = undefined; return p.byteLength; } - private cache: string; - toString(): string { if (this.cache) { return this.cache; @@ -33,6 +32,6 @@ export class StringWriter implements Writer { offs += chunk.byteLength; } this.cache = decode(buf); - return this.cache; + return this.cache!; } } diff --git a/log/handlers.ts b/log/handlers.ts index f13a858e95f7..1f68e9794e09 100644 --- a/log/handlers.ts +++ b/log/handlers.ts @@ -40,14 +40,14 @@ export class BaseHandler { return this.formatter.replace( /{(\S+)}/g, (match, p1): string => { - const value = logRecord[p1]; + const value = logRecord[p1 as keyof LogRecord]; // do not interpolate missing values if (!value) { return match; } - return value; + return String(value); } ); } @@ -87,7 +87,7 @@ export class ConsoleHandler extends BaseHandler { } export abstract class WriterHandler extends BaseHandler { - protected _writer: Writer; + protected _writer!: Writer; private _encoder = new TextEncoder(); log(msg: string): void { @@ -100,7 +100,7 @@ interface FileHandlerOptions extends HandlerOptions { } export class FileHandler extends WriterHandler { - private _file: File; + private _file!: File; private _filename: string; constructor(levelName: string, options: FileHandlerOptions) { diff --git a/log/levels.ts b/log/levels.ts index 3fc86616186e..20cafb205729 100644 --- a/log/levels.ts +++ b/log/levels.ts @@ -1,5 +1,5 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -export const LogLevel = { +export const LogLevel: Record = { NOTSET: 0, DEBUG: 10, INFO: 20, @@ -8,15 +8,6 @@ export const LogLevel = { CRITICAL: 50 }; -const byName = { - NOTSET: LogLevel.NOTSET, - DEBUG: LogLevel.DEBUG, - INFO: LogLevel.INFO, - WARNING: LogLevel.WARNING, - ERROR: LogLevel.ERROR, - CRITICAL: LogLevel.CRITICAL -}; - const byLevel = { [LogLevel.NOTSET]: "NOTSET", [LogLevel.DEBUG]: "DEBUG", @@ -27,7 +18,7 @@ const byLevel = { }; export function getLevelByName(name: string): number { - return byName[name]; + return LogLevel[name]; } export function getLevelName(level: number): string { diff --git a/log/logger_test.ts b/log/logger_test.ts index eb4e7673df93..2aca71d1ca9d 100644 --- a/log/logger_test.ts +++ b/log/logger_test.ts @@ -10,7 +10,7 @@ class TestHandler extends BaseHandler { public records: LogRecord[] = []; handle(record: LogRecord): void { - this.records.push({ ...record, datetime: null }); + this.records.push({ ...record }); super.handle(record); } @@ -38,33 +38,29 @@ test(function customHandler(): void { logger.debug("foo", 1, 2); - assertEquals(handler.records, [ - { - msg: "foo", - args: [1, 2], - datetime: null, - level: LogLevel.DEBUG, - levelName: "DEBUG" - } - ]); + const record = handler.records[0]; + assertEquals(record.msg, "foo"); + assertEquals(record.args, [1, 2]); + assertEquals(record.level, LogLevel.DEBUG); + assertEquals(record.levelName, "DEBUG"); assertEquals(handler.messages, ["DEBUG foo"]); }); test(function logFunctions(): void { - let handler: TestHandler; - - const doLog = (level: string): void => { - handler = new TestHandler(level); + const doLog = (level: string): TestHandler => { + const handler = new TestHandler(level); let logger = new Logger(level, [handler]); logger.debug("foo"); logger.info("bar"); logger.warning("baz"); logger.error("boo"); logger.critical("doo"); + return handler; }; - doLog("DEBUG"); + let handler: TestHandler; + handler = doLog("DEBUG"); assertEquals(handler.messages, [ "DEBUG foo", @@ -74,7 +70,7 @@ test(function logFunctions(): void { "CRITICAL doo" ]); - doLog("INFO"); + handler = doLog("INFO"); assertEquals(handler.messages, [ "INFO bar", @@ -83,15 +79,15 @@ test(function logFunctions(): void { "CRITICAL doo" ]); - doLog("WARNING"); + handler = doLog("WARNING"); assertEquals(handler.messages, ["WARNING baz", "ERROR boo", "CRITICAL doo"]); - doLog("ERROR"); + handler = doLog("ERROR"); assertEquals(handler.messages, ["ERROR boo", "CRITICAL doo"]); - doLog("CRITICAL"); + handler = doLog("CRITICAL"); assertEquals(handler.messages, ["CRITICAL doo"]); }); diff --git a/log/mod.ts b/log/mod.ts index 9149e860444f..d294cdc07377 100644 --- a/log/mod.ts +++ b/log/mod.ts @@ -50,7 +50,7 @@ export const handlers = { export function getLogger(name?: string): Logger { if (!name) { - return state.loggers.get("default"); + return state.loggers.get("default")!; } if (!state.loggers.has(name)) { @@ -59,7 +59,7 @@ export function getLogger(name?: string): Logger { return logger; } - return state.loggers.get(name); + return state.loggers.get(name)!; } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -78,10 +78,6 @@ export const error = (msg: string, ...args: any[]): void => export const critical = (msg: string, ...args: any[]): void => getLogger("default").critical(msg, ...args); -export function getHandler(name: string): BaseHandler { - return state.handlers.get(name); -} - export async function setup(config: LogConfig): Promise { state.config = { handlers: { ...DEFAULT_CONFIG.handlers, ...config.handlers }, @@ -118,7 +114,7 @@ export async function setup(config: LogConfig): Promise { handlerNames.forEach( (handlerName): void => { if (state.handlers.has(handlerName)) { - handlers.push(state.handlers.get(handlerName)); + handlers.push(state.handlers.get(handlerName)!); } } ); diff --git a/log/test.ts b/log/test.ts index 710de182f2ec..c42c7ed38cf6 100644 --- a/log/test.ts +++ b/log/test.ts @@ -16,7 +16,8 @@ class TestHandler extends log.handlers.BaseHandler { } test(async function defaultHandlers(): Promise { - const loggers = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const loggers: { [key: string]: (msg: string, ...args: any[]) => void } = { DEBUG: log.debug, INFO: log.info, WARNING: log.warning, @@ -29,9 +30,8 @@ test(async function defaultHandlers(): Promise { continue; } - const level = LogLevel[levelName]; const logger = loggers[levelName]; - const handler = new TestHandler(level); + const handler = new TestHandler(levelName); await log.setup({ handlers: { diff --git a/mime/multipart.ts b/mime/multipart.ts index 580b81dc3138..461563a4e69d 100644 --- a/mime/multipart.ts +++ b/mime/multipart.ts @@ -177,20 +177,20 @@ class PartReader implements Reader, Closer { close(): void {} - private contentDisposition: string; - private contentDispositionParams: { [key: string]: string }; + private contentDisposition!: string; + private contentDispositionParams!: { [key: string]: string }; private getContentDispositionParams(): { [key: string]: string } { if (this.contentDispositionParams) return this.contentDispositionParams; const cd = this.headers.get("content-disposition"); - const params = {}; - const comps = cd.split(";"); + const params: { [key: string]: string } = {}; + const comps = cd!.split(";"); this.contentDisposition = comps[0]; comps .slice(1) - .map((v): string => v.trim()) + .map((v: string): string => v.trim()) .map( - (kv): void => { + (kv: string): void => { const [k, v] = kv.split("="); if (v) { const s = v.charAt(0); @@ -292,7 +292,7 @@ export class MultipartReader { file.close(); formFile = { filename: p.fileName, - type: p.headers.get("content-type"), + type: p.headers.get("content-type")!, tempfile: filepath, size }; @@ -302,20 +302,20 @@ export class MultipartReader { } else { formFile = { filename: p.fileName, - type: p.headers.get("content-type"), + type: p.headers.get("content-type")!, content: buf.bytes(), size: buf.length }; maxMemory -= n; maxValueBytes -= n; } - result[p.formName] = formFile; + result[p.formName] = formFile!; } return result; } - private currentPart: PartReader; - private partsRead: number; + private currentPart: PartReader | undefined; + private partsRead: number = 0; private async nextPart(): Promise { if (this.currentPart) { @@ -437,7 +437,7 @@ export class MultipartWriter { return this._boundary; } - private lastPart: PartWriter; + private lastPart: PartWriter | undefined; private bufWriter: BufWriter; private isClosed: boolean = false; diff --git a/mime/multipart_test.ts b/mime/multipart_test.ts index ed033ad9accd..a2fc960b7136 100644 --- a/mime/multipart_test.ts +++ b/mime/multipart_test.ts @@ -142,6 +142,7 @@ test(async function multipartMultipartWriter3(): Promise { ); await assertThrowsAsync( async (): Promise => { + // @ts-ignore await mw.writeFile("bar", "file", null); }, Error, @@ -197,7 +198,7 @@ test(async function multipartMultipartReader2(): Promise { assertEquals(form["bar"], "bar"); const file = form["file"] as FormFile; assertEquals(file.type, "application/octet-stream"); - const f = await open(file.tempfile); + const f = await open(file.tempfile!); const w = new StringWriter(); await copy(w, f); const json = JSON.parse(w.toString()); @@ -205,7 +206,7 @@ test(async function multipartMultipartReader2(): Promise { f.close(); } finally { const file = form["file"] as FormFile; - await remove(file.tempfile); + await remove(file.tempfile!); } }); diff --git a/prettier/main_test.ts b/prettier/main_test.ts index 86d6a75a50f4..bbd7f4bc1499 100644 --- a/prettier/main_test.ts +++ b/prettier/main_test.ts @@ -13,7 +13,7 @@ async function run( ): Promise<{ stdout: string; code: number | undefined }> { const p = xrun({ args, stdout: "piped" }); - const stdout = decoder.decode(await readAll(p.stdout)); + const stdout = decoder.decode(await readAll(p.stdout!)); const { code } = await p.status(); return { stdout, code }; diff --git a/prettier/testdata/opts/0.ts b/prettier/testdata/opts/0.ts index fb85014a5e9e..400e7ee56ed2 100644 --- a/prettier/testdata/opts/0.ts +++ b/prettier/testdata/opts/0.ts @@ -1,2 +1,6 @@ -console.log(0) -console.log([function foo() {}, function baz() {}, a => {}]) +console.log(0); +console.log([ + function foo() {}, + function baz() {}, + a => {} +]); diff --git a/prettier/util.ts b/prettier/util.ts index 1c5513c8d037..b8f79005db00 100644 --- a/prettier/util.ts +++ b/prettier/util.ts @@ -2,7 +2,7 @@ const { build, run } = Deno; // Runs a command in cross-platform way -export function xrun(opts): Deno.Process { +export function xrun(opts: Deno.RunOptions): Deno.Process { return run({ ...opts, args: build.os === "win" ? ["cmd.exe", "/c", ...opts.args] : opts.args diff --git a/testing/asserts.ts b/testing/asserts.ts index a2583c22a983..cbdaf3a944d9 100644 --- a/testing/asserts.ts +++ b/testing/asserts.ts @@ -183,7 +183,7 @@ export function assertArrayContains( expected: unknown[], msg?: string ): void { - let missing = []; + let missing: unknown[] = []; for (let i = 0; i < expected.length; i++) { let found = false; for (let j = 0; j < actual.length; j++) { diff --git a/testing/format.ts b/testing/format.ts index 8ed066eb05a6..af8391b2308f 100644 --- a/testing/format.ts +++ b/testing/format.ts @@ -525,16 +525,10 @@ const getConfig = (options: Options): Config => ({ */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function format(val: any, options: Optional = {}): string { - const opts = Object.keys(DEFAULT_OPTIONS).reduce( - (acc: Options, k: keyof Options): unknown => { - const opt = options[k]; - if (typeof opt === "undefined") { - return { ...acc, [k]: DEFAULT_OPTIONS[k] }; - } - return { ...acc, [k]: opt }; - }, - {} - ) as Options; + const opts: Options = { + ...DEFAULT_OPTIONS, + ...options + }; const basicResult = printBasicValue(val, opts); if (basicResult !== null) { return basicResult; diff --git a/testing/mod.ts b/testing/mod.ts index fab8145e82fb..4ec241c206d1 100644 --- a/testing/mod.ts +++ b/testing/mod.ts @@ -54,7 +54,7 @@ interface TestStats { interface TestResult { name: string; - error: Error; + error?: Error; ok: boolean; printed: boolean; } @@ -68,7 +68,7 @@ function createTestResults(tests: TestDefinition[]): TestResults { return tests.reduce( (acc: TestResults, { name }: TestDefinition, i: number): TestResults => { acc.keys.set(name, i); - acc.cases.set(i, { name, printed: false, ok: false, error: null }); + acc.cases.set(i, { name, printed: false, ok: false, error: undefined }); return acc; }, { cases: new Map(), keys: new Map() } @@ -114,11 +114,11 @@ function printResults( } function previousPrinted(name: string, results: TestResults): boolean { - const curIndex: number = results.keys.get(name); + const curIndex: number = results.keys.get(name)!; if (curIndex === 0) { return true; } - return results.cases.get(curIndex - 1).printed; + return results.cases.get(curIndex - 1)!.printed; } async function createTestCase( @@ -127,7 +127,7 @@ async function createTestCase( exitOnFail: boolean, { fn, name }: TestDefinition ): Promise { - const result: TestResult = results.cases.get(results.keys.get(name)); + const result: TestResult = results.cases.get(results.keys.get(name)!)!; try { await fn(); stats.passed++; diff --git a/testing/pretty.ts b/testing/pretty.ts index b2ab79d70220..f471bd6fd162 100644 --- a/testing/pretty.ts +++ b/testing/pretty.ts @@ -38,7 +38,7 @@ function createSign(diffType: DiffType): string { } function buildMessage(diffResult: ReadonlyArray>): string[] { - const messages = []; + const messages: string[] = []; messages.push(""); messages.push(""); messages.push( diff --git a/textproto/mod.ts b/textproto/mod.ts index 66f303905e49..6c4e42e518b3 100644 --- a/textproto/mod.ts +++ b/textproto/mod.ts @@ -82,7 +82,7 @@ export class TextProtoReader { throw new UnexpectedEOFError(); } else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) { throw new ProtocolError( - `malformed MIME header initial line: ${str(line)}` + `malformed MIME header initial line: ${str(line!)}` ); } @@ -140,7 +140,7 @@ export class TextProtoReader { const { line: l, more } = r; // Avoid the copy if the first call produced a full line. - if (!line && !more) { + if (!line! && !more) { // TODO(ry): // This skipSpace() is definitely misplaced, but I don't know where it // comes from nor how to fix it. @@ -150,6 +150,7 @@ export class TextProtoReader { return l; } + // @ts-ignore line = append(line, l); if (!more) { break; diff --git a/textproto/reader_test.ts b/textproto/reader_test.ts index bd0d39fd339e..dfe918282078 100644 --- a/textproto/reader_test.ts +++ b/textproto/reader_test.ts @@ -83,7 +83,7 @@ test({ test({ name: "[textproto] Reader : Large MIME Header", async fn(): Promise { - const data = []; + const data: string[] = []; // Go test is 16*1024. But seems it can't handle more for (let i = 0; i < 1024; i++) { data.push("x"); diff --git a/tsconfig.json b/tsconfig.json index f943386c2837..f438205b013d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "tsconfig.test.json", "compilerOptions": { "allowJs": true, "baseUrl": ".", @@ -7,7 +8,6 @@ "noEmit": true, "pretty": true, "resolveJsonModule": true, - "strict": true, "target": "esnext", "lib": ["esnext"] }, diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 000000000000..aee0ec940fcd --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "strict": true + } +} diff --git a/util/async.ts b/util/async.ts index 15edb1b42daf..b737c4cc8907 100644 --- a/util/async.ts +++ b/util/async.ts @@ -25,7 +25,7 @@ export function deferred(): Deferred { methods = { resolve, reject }; } ); - return Object.assign(promise, methods) as Deferred; + return Object.assign(promise, methods)! as Deferred; } interface TaggedYieldedValue { diff --git a/util/deep_assign.ts b/util/deep_assign.ts index 77bf5e9b368a..1dfc00a5be5c 100644 --- a/util/deep_assign.ts +++ b/util/deep_assign.ts @@ -1,12 +1,15 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -export function deepAssign(target: object, ...sources: object[]): object { +export function deepAssign( + target: Record, + ...sources: object[] +): object | undefined { for (let i = 0; i < sources.length; i++) { const source = sources[i]; if (!source || typeof source !== `object`) { return; } Object.entries(source).forEach( - ([key, value]): void => { + ([key, value]: [string, unknown]): void => { if (value instanceof Date) { target[key] = new Date(value); return; @@ -22,7 +25,7 @@ export function deepAssign(target: object, ...sources: object[]): object { if (typeof target[key] !== `object` || !target[key]) { target[key] = {}; } - deepAssign(target[key], value); + deepAssign(target[key] as Record, value!); } ); } diff --git a/ws/mod.ts b/ws/mod.ts index 7d8200dfcd95..2ae6cabda3e9 100644 --- a/ws/mod.ts +++ b/ws/mod.ts @@ -31,19 +31,25 @@ export interface WebSocketCloseEvent { reason?: string; } -export function isWebSocketCloseEvent(a): a is WebSocketCloseEvent { - return a && typeof a["code"] === "number"; +export function isWebSocketCloseEvent( + a: WebSocketEvent +): a is WebSocketCloseEvent { + return typeof a === "object" && a.hasOwnProperty("code"); } export type WebSocketPingEvent = ["ping", Uint8Array]; -export function isWebSocketPingEvent(a): a is WebSocketPingEvent { +export function isWebSocketPingEvent( + a: WebSocketEvent +): a is WebSocketPingEvent { return Array.isArray(a) && a[0] === "ping" && a[1] instanceof Uint8Array; } export type WebSocketPongEvent = ["pong", Uint8Array]; -export function isWebSocketPongEvent(a): a is WebSocketPongEvent { +export function isWebSocketPongEvent( + a: WebSocketEvent +): a is WebSocketPongEvent { return Array.isArray(a) && a[0] === "pong" && a[1] instanceof Uint8Array; } @@ -436,6 +442,8 @@ async function handshake( if (!m) { throw new Error("ws: invalid status line: " + statusLine); } + + // @ts-ignore const { version, statusCode } = m.groups; if (version !== "HTTP/1.1" || statusCode !== "101") { throw new Error( diff --git a/ws/sha1.ts b/ws/sha1.ts index d01df21adf75..dc8ba680c977 100644 --- a/ws/sha1.ts +++ b/ws/sha1.ts @@ -77,11 +77,11 @@ export class Sha1 { if (notString) { for (i = start; index < length && i < 64; ++index) { - blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; + blocks[i >> 2] |= (message[index] as number) << SHIFT[i++ & 3]; } } else { for (i = start; index < length && i < 64; ++index) { - code = message.charCodeAt(index); + code = (message as string).charCodeAt(index); if (code < 0x80) { blocks[i >> 2] |= code << SHIFT[i++ & 3]; } else if (code < 0x800) { @@ -94,7 +94,8 @@ export class Sha1 { } else { code = 0x10000 + - (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); + (((code & 0x3ff) << 10) | + ((message as string).charCodeAt(++index) & 0x3ff)); blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; diff --git a/ws/test.ts b/ws/test.ts index bac82453dcb6..e14af1d559bd 100644 --- a/ws/test.ts +++ b/ws/test.ts @@ -166,20 +166,31 @@ test(function wsAcceptable(): void { ); }); -const invalidHeaders = [ - { "sec-websocket-key": "aaa" }, - { upgrade: "websocket" }, - { upgrade: "invalid", "sec-websocket-key": "aaa" }, - { upgrade: "websocket", "sec-websocket-ky": "" } -]; - test(function wsAcceptableInvalid(): void { - for (const pat of invalidHeaders) { - const ret = acceptable({ - headers: new Headers(pat) - }); - assertEquals(ret, false); - } + assertEquals( + acceptable({ + headers: new Headers({ "sec-websocket-key": "aaa" }) + }), + false + ); + assertEquals( + acceptable({ + headers: new Headers({ upgrade: "websocket" }) + }), + false + ); + assertEquals( + acceptable({ + headers: new Headers({ upgrade: "invalid", "sec-websocket-key": "aaa" }) + }), + false + ); + assertEquals( + acceptable({ + headers: new Headers({ upgrade: "websocket", "sec-websocket-ky": "" }) + }), + false + ); }); test(async function wsWriteReadMaskedFrame(): Promise {