From 4d4bd0eb92802b898436d1b8e969ca686da2c9d2 Mon Sep 17 00:00:00 2001 From: Kenta Moriuchi Date: Wed, 4 Sep 2024 14:15:01 +0900 Subject: [PATCH] refactor(archive,async,cli,csv,dotenv,encoding,expect,fmt,front-matter,fs,http,internal,log,net,path,semver,testing,text,webgpu,yaml): enable `"exactOptionalPropertyTypes"` option (#5892) --- archive/tar.ts | 26 +++++---- archive/untar.ts | 8 ++- archive/untar_stream.ts | 15 ++--- archive/untar_test.ts | 2 +- async/retry_test.ts | 1 + cli/parse_args_test.ts | 96 +++++++++++++++---------------- cli/spinner.ts | 2 +- csv/parse.ts | 6 +- csv/parse_stream_test.ts | 15 ++--- csv/parse_test.ts | 14 +++-- csv/stringify_stream.ts | 14 ++++- deno.json | 1 + dotenv/parse.ts | 2 +- encoding/base58.ts | 4 +- expect/_assert_equals.ts | 2 +- expect/_assert_not_equals.ts | 6 +- expect/_build_message.ts | 4 +- expect/_equal.ts | 6 +- expect/_utils.ts | 13 +++-- fmt/bytes.ts | 18 ++++-- fmt/bytes_test.ts | 11 ++++ fmt/duration_test.ts | 1 + fmt/printf.ts | 16 +++--- front_matter/_shared.ts | 2 +- fs/expand_glob.ts | 21 ++++--- fs/walk.ts | 34 +++++++---- http/_negotiation/common.ts | 4 +- http/_negotiation/encoding.ts | 6 +- http/_negotiation/language.ts | 6 +- http/_negotiation/media_type.ts | 14 ++--- http/cookie.ts | 2 +- http/file_server.ts | 41 +++++++------ http/user_agent.ts | 10 ++-- internal/diff.ts | 2 +- log/file_handler.ts | 5 +- log/logger.ts | 2 +- log/setup.ts | 8 +-- net/get_network_address.ts | 4 +- path/_common/format.ts | 2 +- semver/increment.ts | 2 +- semver/increment_test.ts | 32 ++++++++--- testing/_test_suite.ts | 87 ++++++++++++++++------------ testing/bdd.ts | 43 +++++++++----- testing/mock.ts | 8 +-- testing/mock_test.ts | 9 +-- testing/snapshot.ts | 4 +- text/_util.ts | 2 +- webgpu/describe_texture_format.ts | 8 ++- webgpu/texture_with_data.ts | 22 +++++-- yaml/_loader_state.ts | 8 +-- yaml/parse.ts | 4 +- yaml/stringify.ts | 2 +- 52 files changed, 404 insertions(+), 273 deletions(-) diff --git a/archive/tar.ts b/archive/tar.ts index 88cbbf422..32e38935f 100644 --- a/archive/tar.ts +++ b/archive/tar.ts @@ -70,7 +70,7 @@ const USTAR_MAGIC_HEADER = "ustar\u000000" as const; * Simple file reader */ class FileReader implements Reader { - #file?: Deno.FsFile; + #file: Deno.FsFile | undefined; #filePath: string; constructor(filePath: string) { @@ -112,7 +112,7 @@ function formatHeader(data: TarData): Uint8Array { const buffer = new Uint8Array(HEADER_LENGTH); let offset = 0; for (const { field, length } of USTAR_STRUCTURE) { - const entry = encoder.encode(data[field as keyof TarData] || ""); + const entry = encoder.encode(data[field as keyof TarData] ?? ""); buffer.set(entry, offset); offset += length; } @@ -334,7 +334,7 @@ export class Tar { } } - source = source || {}; + source = source ?? {}; // set meta data let info: Deno.FileInfo | undefined; @@ -351,8 +351,8 @@ export class Tar { const mtime = Math.floor( source.mtime ?? (info?.mtime ?? new Date()).valueOf() / 1000, ); - const uid = source.uid || 0; - const gid = source.gid || 0; + const uid = source.uid ?? 0; + const gid = source.gid ?? 0; if (typeof source.owner === "string" && source.owner.length >= 32) { throw new Error( @@ -375,7 +375,6 @@ export class Tar { : (info?.isDirectory ? FileTypes.directory : FileTypes.file); const tarData: TarDataWithSource = { fileName, - fileNamePrefix, fileMode: pad(mode, 7), uid: pad(uid, 7), gid: pad(gid, 7), @@ -384,11 +383,18 @@ export class Tar { checksum: " ", type: type.toString(), ustar: USTAR_MAGIC_HEADER, - owner: source.owner || "", - group: source.group || "", - filePath: source.filePath, - reader: source.reader, + owner: source.owner ?? "", + group: source.group ?? "", }; + if (fileNamePrefix !== undefined) { + tarData.fileNamePrefix = fileNamePrefix; + } + if (source.filePath !== undefined) { + tarData.filePath = source.filePath; + } + if (source.reader !== undefined) { + tarData.reader = source.reader; + } // calculate the checksum let checksum = 0; diff --git a/archive/untar.ts b/archive/untar.ts index 7d76c67b8..2ea629c2b 100644 --- a/archive/untar.ts +++ b/archive/untar.ts @@ -168,7 +168,7 @@ export class TarEntry implements Reader { this.#reader = reader; // File Size - this.#size = this.fileSize || 0; + this.#size = this.fileSize ?? 0; // Entry Size const blocks = Math.ceil(this.#size / HEADER_LENGTH); this.#entrySize = blocks * HEADER_LENGTH; @@ -259,7 +259,7 @@ export class TarEntry implements Reader { const n = await readBlock(this.#reader, block); const bytesLeft = this.#size - this.#read; - this.#read += n || 0; + this.#read += n ?? 0; if (n === null || bytesLeft <= 0) { if (n === null) this.#consumed = true; return null; @@ -449,7 +449,9 @@ export class Untar { }); meta.fileSize = parseInt(decoder.decode(header.fileSize), 8); - meta.type = FileTypes[parseInt(meta.type!)] ?? meta.type; + if (meta.type !== undefined) { + meta.type = FileTypes[parseInt(meta.type!)] ?? meta.type; + } // Only create the `linkName` property for symbolic links to minimize // the effect on existing code that only deals with non-links. diff --git a/archive/untar_stream.ts b/archive/untar_stream.ts index 1b8acffd6..57a4ab4d6 100644 --- a/archive/untar_stream.ts +++ b/archive/untar_stream.ts @@ -271,15 +271,16 @@ export class UntarStream }; } - yield { - path: ("prefix" in header && header.prefix.length - ? header.prefix + "/" - : "") + header.name, + const entry: TarStreamEntry = { + path: ( + "prefix" in header && header.prefix.length ? header.prefix + "/" : "" + ) + header.name, header, - readable: ["1", "2", "3", "4", "5", "6"].includes(header.typeflag) - ? undefined - : this.#readableFile(header.size), }; + if (!["1", "2", "3", "4", "5", "6"].includes(header.typeflag)) { + entry.readable = this.#readableFile(header.size); + } + yield entry; } } diff --git a/archive/untar_test.ts b/archive/untar_test.ts index 577d87cc1..3c51a3f0a 100644 --- a/archive/untar_test.ts +++ b/archive/untar_test.ts @@ -26,7 +26,7 @@ async function createTar(entries: TestEntry[]): Promise { contentSize: file.content.byteLength, }; } else { - options = { filePath: file.filePath }; + options = { filePath: file.filePath! }; } await tar.append(file.name, options); diff --git a/async/retry_test.ts b/async/retry_test.ts index 17e4bf8d9..d3e217d45 100644 --- a/async/retry_test.ts +++ b/async/retry_test.ts @@ -35,6 +35,7 @@ Deno.test("retry() fails after five errors by default", async () => { Deno.test("retry() fails after five errors when undefined is passed", async () => { const fiveErrors = generateErroringFunction(5); await assertRejects(() => + // @ts-expect-error: explicitly giving undefined retry(fiveErrors, { maxAttempts: undefined, minTimeout: 100, diff --git a/cli/parse_args_test.ts b/cli/parse_args_test.ts index 2132c06ec..d95912104 100644 --- a/cli/parse_args_test.ts +++ b/cli/parse_args_test.ts @@ -986,7 +986,7 @@ Deno.test("parseArgs() handles types of all boolean disabled and string args", f typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; + foo?: string; _: Array; } > @@ -1061,9 +1061,9 @@ Deno.test("parseArgs() handles types of all boolean and string args", function ( typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; - bar?: string | undefined; - "foo-bar"?: string | undefined; + foo?: string; + bar?: string; + "foo-bar"?: string; _: Array; } > @@ -1084,10 +1084,10 @@ Deno.test("parseArgs() handles types of all boolean and string args with default typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; + foo?: string; bar: string | number; baz: unknown; - "foo-bar"?: string | undefined; + "foo-bar"?: string; _: Array; } > @@ -1144,9 +1144,9 @@ Deno.test("parseArgs() handles types of string args", function () { typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; - bar?: string | undefined; - "foo-bar"?: string | undefined; + foo?: string; + bar?: string; + "foo-bar"?: string; _: Array; } > @@ -1166,10 +1166,10 @@ Deno.test("parseArgs() handles types of string args with defaults", function () typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; + foo?: string; bar: string | boolean; baz: unknown; - "foo-bar"?: string | undefined; + "foo-bar"?: string; _: Array; } > @@ -1186,9 +1186,9 @@ Deno.test("parseArgs() handles types of boolean and string args", function () { typeof argv, & { [x: string]: unknown } & { - beep?: string | undefined; - boop?: string | undefined; - "beep-boop"?: string | undefined; + beep?: string; + boop?: string; + "beep-boop"?: string; foo: boolean; bar: boolean; "foo-bar": boolean; @@ -1214,8 +1214,8 @@ Deno.test("parseArgs() handles types of boolean and string args with defaults", & { [x: string]: unknown } & { foo: boolean; - boop?: string | undefined; - "beep-boop"?: string | undefined; + boop?: string; + "beep-boop"?: string; bar: number | boolean; baz: unknown; beep: string | Date; @@ -1294,12 +1294,12 @@ Deno.test("parseArgs() handles types of dotted string args", function () { typeof argv, & { [x: string]: unknown } & { - blubb?: string | undefined; + blubb?: string; foo?: { - bar?: string | undefined; + bar?: string; baz?: { - biz?: string | undefined; - buz?: string | undefined; + biz?: string; + buz?: string; }; }; _: Array; @@ -1332,7 +1332,7 @@ Deno.test("parseArgs() handles types of dotted string args with defaults", funct bar: string | number; baz: { biz: string | Date; - buz?: string | undefined; + buz?: string; }; }; bla: unknown; @@ -1357,14 +1357,14 @@ Deno.test("parseArgs() handles types of dotted string and boolean args", functio bar: boolean; baz: { biz: boolean; - buz?: string | undefined; + buz?: string; }; }; - bla?: string | undefined; + bla?: string; beep: { - boop?: string | undefined; + boop?: string; bib: { - bab?: string | undefined; + bab?: string; bub: boolean; }; }; @@ -1406,7 +1406,7 @@ Deno.test("parseArgs() handles types of dotted string and boolean args with defa bar: boolean | number; baz: { biz: boolean | Date; - buz?: string | undefined; + buz?: string; }; }; beep: { @@ -1448,7 +1448,7 @@ Deno.test("parseArgs() handles types of dotted string and boolean args with flat bar: boolean | number; baz: { biz: boolean | Date; - buz?: string | undefined; + buz?: string; }; }; beep: { @@ -1480,8 +1480,8 @@ Deno.test("parseArgs() handles types of dotted args with union defaults", functi & { foo: number | { bar?: { - baz?: string | undefined; - } | undefined; + baz?: string; + }; }; beep: Date | { boop: { @@ -1510,7 +1510,7 @@ Deno.test("parseArgs() handles types of dotted args with nested union defaults", & { foo: { bar: number | { - baz?: string | undefined; + baz?: string; }; }; beep: { @@ -1577,7 +1577,7 @@ Deno.test("parseArgs() handles types of collect args", function () { typeof argv, & { [x: string]: unknown } & { - bar?: string | undefined; + bar?: string; dotted: { boop: Array; beep: boolean; @@ -1703,11 +1703,11 @@ Deno.test("parseArgs() handles types of negatable args", function () { typeof argv, & { [x: string]: unknown } & { - beep?: string | undefined; - boop?: string | false | undefined; + beep?: string; + boop?: string | false; dotted: { - zig?: string | false | undefined; - zag?: string | undefined; + zig?: string | false; + zag?: string; tick: boolean; tock: boolean; }; @@ -1739,11 +1739,11 @@ Deno.test("parseArgs() handles types of collect all args with defaults", functio & { [x: string]: unknown } & { foo: boolean; - beep?: string | undefined; + beep?: string; bar: number | boolean; boop: string | false | TextDecoder; dotted: { - zag?: string | undefined; + zag?: string; tock: boolean; tick: boolean | Date; zig: string | false | RegExp; @@ -1770,8 +1770,8 @@ Deno.test("parseArgs() handles types of alias args", function () { typeof argv, & { [x: string]: unknown } & { - beep?: string | undefined; - boop?: string | undefined; + beep?: string; + boop?: string; foo: boolean; bar: boolean; baz: boolean; @@ -1803,7 +1803,7 @@ Deno.test("parseArgs() handles types of alias args with options", function () { & { baz: boolean; biz: boolean; - bib?: string | undefined; + bib?: string; foo: number | boolean; bar: number | boolean; beep: string | false | Date; @@ -1827,7 +1827,7 @@ Deno.test("parseArgs() handles types of double dash option", function () { typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; + foo?: string; _: Array; "--": Array; } @@ -1849,7 +1849,7 @@ Deno.test("parseArgs() handles types of nullish defaults", function () { typeof argv, & { [x: string]: unknown } & { - foo?: string | undefined; + foo?: string; bar: string | undefined; baz: string | null; _: Array; @@ -1864,7 +1864,7 @@ Deno.test("parseArgs() handles types of parse generics", function () { IsExact< typeof argv, { - foo?: number | undefined; + foo?: number; bar: string; _: Array; "--": Array; @@ -1879,7 +1879,7 @@ Deno.test("parseArgs() handles types of args generics", function () { IsExact< ArgsResult, { - foo?: number | undefined; + foo?: number; bar: string; _: Array; "--": Array; @@ -1893,14 +1893,14 @@ Deno.test("parseArgs() handles types of parse options generics", function () { assertType< IsExact< Pick, - { string?: "bar" | "baz" | ReadonlyArray<"bar" | "baz"> | undefined } + { string?: "bar" | "baz" | ReadonlyArray<"bar" | "baz"> } > >(true); assertType< IsExact< Pick, - { boolean?: "foo" | ReadonlyArray<"foo"> | undefined } + { boolean?: "foo" | ReadonlyArray<"foo"> } > >(true); @@ -1913,7 +1913,7 @@ Deno.test("parseArgs() handles types of parse options generics", function () { bar?: unknown; baz?: unknown; foo?: unknown; - } | undefined; + }; } > >(true); @@ -1934,7 +1934,7 @@ Deno.test("parseArgs() handles types of parse options generic defaults", functio // deno-lint-ignore no-explicit-any [x: string]: any; _: (string | number)[]; - "--"?: string[] | undefined; + "--"?: string[]; } > >(true); diff --git a/cli/spinner.ts b/cli/spinner.ts index 00fb78322..d674acd89 100644 --- a/cli/spinner.ts +++ b/cli/spinner.ts @@ -123,7 +123,7 @@ export class Spinner { message: string; #interval: number; - #color?: Color; + #color: Color | undefined; #intervalId: number | undefined; #active = false; diff --git a/csv/parse.ts b/csv/parse.ts index c6d7b5443..b22cab218 100644 --- a/csv/parse.ts +++ b/csv/parse.ts @@ -21,9 +21,9 @@ class Parser { #options: { separator: string; trimLeadingSpace: boolean; - comment?: string; - lazyQuotes?: boolean; - fieldsPerRecord?: number; + comment: string | undefined; + lazyQuotes: boolean | undefined; + fieldsPerRecord: number | undefined; }; constructor({ separator = ",", diff --git a/csv/parse_stream_test.ts b/csv/parse_stream_test.ts index 1c894f12d..ec00377c8 100644 --- a/csv/parse_stream_test.ts +++ b/csv/parse_stream_test.ts @@ -415,6 +415,7 @@ x,,, await t.step(testCase.name, async () => { const options: CsvParseStreamOptions = {}; if ("separator" in testCase) { + // @ts-expect-error: explicitly giving undefined options.separator = testCase.separator; } if ("comment" in testCase) { @@ -507,7 +508,7 @@ Deno.test({ // skipFirstRow option { - const { readable } = new CsvParseStream({ skipFirstRow: undefined }); + const { readable } = new CsvParseStream({}); type _ = AssertTrue>>; } { @@ -526,7 +527,7 @@ Deno.test({ // columns option { - const { readable } = new CsvParseStream({ columns: undefined }); + const { readable } = new CsvParseStream({}); type _ = AssertTrue>>; } { @@ -547,17 +548,11 @@ Deno.test({ // skipFirstRow option + columns option { - const { readable } = new CsvParseStream({ - skipFirstRow: false, - columns: undefined, - }); + const { readable } = new CsvParseStream({ skipFirstRow: false }); type _ = AssertTrue>>; } { - const { readable } = new CsvParseStream({ - skipFirstRow: true, - columns: undefined, - }); + const { readable } = new CsvParseStream({ skipFirstRow: true }); type _ = AssertTrue< IsExact< typeof readable, diff --git a/csv/parse_test.ts b/csv/parse_test.ts index aa887038b..0835778e6 100644 --- a/csv/parse_test.ts +++ b/csv/parse_test.ts @@ -960,7 +960,7 @@ Deno.test({ // skipFirstRow option { - const parsed = parse("a\nb", { skipFirstRow: undefined }); + const parsed = parse("a\nb", {}); type _ = AssertTrue>; } { @@ -976,7 +976,7 @@ Deno.test({ // columns option { - const parsed = parse("a\nb", { columns: undefined }); + const parsed = parse("a\nb", {}); type _ = AssertTrue>; } { @@ -994,11 +994,17 @@ Deno.test({ // skipFirstRow option + columns option { - const parsed = parse("a\nb", { skipFirstRow: false, columns: undefined }); + const parsed = parse( + "a\nb", + { skipFirstRow: false }, + ); type _ = AssertTrue>; } { - const parsed = parse("a\nb", { skipFirstRow: true, columns: undefined }); + const parsed = parse( + "a\nb", + { skipFirstRow: true }, + ); type _ = AssertTrue< IsExact[]> >; diff --git a/csv/stringify_stream.ts b/csv/stringify_stream.ts index 1cc9addff..3aa30e2ef 100644 --- a/csv/stringify_stream.ts +++ b/csv/stringify_stream.ts @@ -107,7 +107,12 @@ export class CsvStringifyStream if (columns && columns.length > 0) { try { controller.enqueue( - stringify([columns], { separator, headers: false }), + stringify( + [columns], + separator !== undefined + ? { separator, headers: false } + : { headers: false }, + ), ); } catch (error) { controller.error(error); @@ -117,7 +122,12 @@ export class CsvStringifyStream transform(chunk, controller) { try { controller.enqueue( - stringify([chunk], { separator, headers: false, columns }), + stringify( + [chunk], + separator !== undefined + ? { separator, headers: false, columns } + : { headers: false, columns }, + ), ); } catch (error) { controller.error(error); diff --git a/deno.json b/deno.json index e54d3bba8..a82e9dceb 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,7 @@ { "compilerOptions": { "strict": true, + "exactOptionalPropertyTypes": true, "useUnknownInCatchVariables": true, "noImplicitOverride": true, "noUncheckedIndexedAccess": true diff --git a/dotenv/parse.ts b/dotenv/parse.ts index 010473786..e26309400 100644 --- a/dotenv/parse.ts +++ b/dotenv/parse.ts @@ -26,7 +26,7 @@ function expandCharacters(str: string): string { return str.replace( /\\([nrt])/g, - ($1: keyof CharactersMap): string => charactersMap[$1] || "", + ($1: keyof CharactersMap): string => charactersMap[$1] ?? "", ); } diff --git a/encoding/base58.ts b/encoding/base58.ts index 8d0fef6ab..83df983bb 100644 --- a/encoding/base58.ts +++ b/encoding/base58.ts @@ -78,7 +78,7 @@ export function encodeBase58(data: ArrayBuffer | Uint8Array | string): string { (carry > 0 || i < length) && reverseIterator !== -1; reverseIterator--, i++ ) { - carry += (b58Encoding[reverseIterator] || 0) * 256; + carry += (b58Encoding[reverseIterator] ?? 0) * 256; b58Encoding[reverseIterator] = Math.round(carry % 58); carry = Math.floor(carry / 58); } @@ -153,7 +153,7 @@ export function decodeBase58(b58: string): Uint8Array { (carry > 0 || i < length) && reverseIterator !== -1; reverseIterator--, i++ ) { - carry += 58 * (output[reverseIterator] || 0); + carry += 58 * (output[reverseIterator] ?? 0); output[reverseIterator] = Math.round(carry % 256); carry = Math.floor(carry / 256); } diff --git a/expect/_assert_equals.ts b/expect/_assert_equals.ts index 2bb05e1f1..992f6baf9 100644 --- a/expect/_assert_equals.ts +++ b/expect/_assert_equals.ts @@ -33,6 +33,6 @@ export function assertEquals( return; } - const message = buildEqualErrorMessage(actual, expected, options || {}); + const message = buildEqualErrorMessage(actual, expected, options ?? {}); throw new AssertionError(message); } diff --git a/expect/_assert_not_equals.ts b/expect/_assert_not_equals.ts index 23270bd37..1b5423a9a 100644 --- a/expect/_assert_not_equals.ts +++ b/expect/_assert_not_equals.ts @@ -24,14 +24,12 @@ import type { EqualOptions } from "./_types.ts"; export function assertNotEquals( actual: T, expected: T, - options?: EqualOptions, + options: EqualOptions = {}, ) { - const { msg } = options || {}; - if (!equal(actual, expected, options)) { return; } - const message = buildNotEqualErrorMessage(actual, expected, { msg }); + const message = buildNotEqualErrorMessage(actual, expected, options); throw new AssertionError(message); } diff --git a/expect/_build_message.ts b/expect/_build_message.ts index 2e223207e..ef3394f18 100644 --- a/expect/_build_message.ts +++ b/expect/_build_message.ts @@ -17,7 +17,7 @@ export function buildEqualErrorMessage( expected: T, options: EqualErrorMessageOptions, ): string { - const { formatter = format, msg } = options || {}; + const { formatter = format, msg } = options ?? {}; const msgSuffix = msg ? `: ${msg}` : "."; const actualString = formatter(actual); const expectedString = formatter(expected); @@ -39,7 +39,7 @@ export function buildNotEqualErrorMessage( expected: T, options: EqualErrorMessageOptions, ): string { - const { msg } = options || {}; + const { msg } = options ?? {}; const actualString = String(actual); const expectedString = String(expected); diff --git a/expect/_equal.ts b/expect/_equal.ts index f316db2b3..edb444c73 100644 --- a/expect/_equal.ts +++ b/expect/_equal.ts @@ -39,7 +39,7 @@ function asymmetricEqual(a: unknown, b: unknown) { * @param options for the equality check */ export function equal(c: unknown, d: unknown, options?: EqualOptions): boolean { - const { customTesters = [], strictCheck } = options || {}; + const { customTesters = [], strictCheck } = options ?? {}; const seen = new Map(); return (function compare(a: unknown, b: unknown): boolean { @@ -113,8 +113,8 @@ export function equal(c: unknown, d: unknown, options?: EqualOptions): boolean { return true; } - const aKeys = Object.keys(a || {}); - const bKeys = Object.keys(b || {}); + const aKeys = Object.keys(a ?? {}); + const bKeys = Object.keys(b ?? {}); let aLen = aKeys.length; let bLen = bKeys.length; diff --git a/expect/_utils.ts b/expect/_utils.ts index 130627589..0411e155d 100644 --- a/expect/_utils.ts +++ b/expect/_utils.ts @@ -6,12 +6,17 @@ import type { Tester } from "./_types.ts"; import { equal } from "./_equal.ts"; export function buildEqualOptions(options: EqualOptionUtil): EqualOptions { - const { customMessage, customTesters = [], strictCheck } = options || {}; - return { + const { customMessage, customTesters = [], strictCheck } = options ?? {}; + const ret: EqualOptions = { customTesters, - msg: customMessage, - strictCheck, }; + if (customMessage !== undefined) { + ret.msg = customMessage; + } + if (strictCheck !== undefined) { + ret.strictCheck = strictCheck; + } + return ret; } export function isPromiseLike(value: unknown): value is PromiseLike { diff --git a/fmt/bytes.ts b/fmt/bytes.ts index 8e8dcc669..a86923d99 100644 --- a/fmt/bytes.ts +++ b/fmt/bytes.ts @@ -172,12 +172,20 @@ export function format( function getLocaleOptions( { maximumFractionDigits, minimumFractionDigits }: FormatOptions, ): LocaleOptions | undefined { - if (maximumFractionDigits || minimumFractionDigits) { - return { - maximumFractionDigits, - minimumFractionDigits, - }; + if ( + maximumFractionDigits === undefined && minimumFractionDigits === undefined + ) { + return; } + + const ret: LocaleOptions = {}; + if (maximumFractionDigits !== undefined) { + ret.maximumFractionDigits = maximumFractionDigits; + } + if (minimumFractionDigits !== undefined) { + ret.minimumFractionDigits = minimumFractionDigits; + } + return ret; } /** diff --git a/fmt/bytes_test.ts b/fmt/bytes_test.ts index ac636e310..765951829 100644 --- a/fmt/bytes_test.ts +++ b/fmt/bytes_test.ts @@ -87,11 +87,22 @@ Deno.test("format() handles locale option", () => { assertEquals(format(10.1, { locale: false }), "10.1 B"); assertEquals(format(1e30, { locale: false }), "1000000 YB"); + // @ts-expect-error: explicitly giving undefined assertEquals(format(-0.4, { locale: undefined }), "-0.4 B"); + // @ts-expect-error: explicitly giving undefined assertEquals(format(0.4, { locale: undefined }), "0.4 B"); + // @ts-expect-error: explicitly giving undefined assertEquals(format(1001, { locale: undefined }), "1 kB"); + // @ts-expect-error: explicitly giving undefined assertEquals(format(10.1, { locale: undefined }), "10.1 B"); + // @ts-expect-error: explicitly giving undefined assertEquals(format(1e30, { locale: undefined }), "1000000 YB"); + + assertEquals(format(-0.4, {}), "-0.4 B"); + assertEquals(format(0.4, {}), "0.4 B"); + assertEquals(format(1001, {}), "1 kB"); + assertEquals(format(10.1, {}), "10.1 B"); + assertEquals(format(1e30, {}), "1000000 YB"); }); Deno.test("format() handles signed option", () => { diff --git a/fmt/duration_test.ts b/fmt/duration_test.ts index 63e848991..27d0edaff 100644 --- a/fmt/duration_test.ts +++ b/fmt/duration_test.ts @@ -20,6 +20,7 @@ Deno.test({ name: "format() handles default style (narrow)", fn() { assertEquals( + // @ts-expect-error: explicitly giving undefined format(99674, { style: undefined }), "0d 0h 1m 39s 674ms 0µs 0ns", ); diff --git a/fmt/printf.ts b/fmt/printf.ts index c7733a1d0..bbb2d3052 100644 --- a/fmt/printf.ts +++ b/fmt/printf.ts @@ -184,12 +184,12 @@ const F = { } as const; class Flags { - plus?: boolean; - dash?: boolean; - sharp?: boolean; - space?: boolean; - zero?: boolean; - lessthan?: boolean; + plus: boolean | undefined; + dash: boolean | undefined; + sharp: boolean | undefined; + space: boolean | undefined; + zero: boolean | undefined; + lessthan: boolean | undefined; width = -1; precision = -1; } @@ -213,7 +213,7 @@ class Printf { haveSeen: boolean[]; // barf, store precision and width errors for later processing ... - tmpError?: string; + tmpError: string | undefined; constructor(format: string, ...args: unknown[]) { this.format = format; @@ -719,7 +719,7 @@ class Printf { ? this.flags.precision : DEFAULT_PRECISION; const [fractional, rounding] = this.roundFractionToPrecision( - m[F.fractional] || "", + m[F.fractional] ?? "", precision, ); diff --git a/front_matter/_shared.ts b/front_matter/_shared.ts index 9914afa64..00376fdad 100644 --- a/front_matter/_shared.ts +++ b/front_matter/_shared.ts @@ -15,7 +15,7 @@ export function extractAndParse( if (!match || match.index !== 0) { throw new TypeError("Unexpected end of input"); } - const frontMatter = match.at(-1)?.replace(/^\s+|\s+$/g, "") || ""; + const frontMatter = match.at(-1)?.replace(/^\s+|\s+$/g, "") ?? ""; const attrs = parse(frontMatter) as T; const body = input.replace(match[0], ""); return { frontMatter, body, attrs }; diff --git a/fs/expand_glob.ts b/fs/expand_glob.ts index 5fb663134..3669efcd7 100644 --- a/fs/expand_glob.ts +++ b/fs/expand_glob.ts @@ -66,12 +66,15 @@ function split(path: string): SplitPath { .replace(new RegExp(`^${s}|${s}$`, "g"), "") .split(SEPARATOR_PATTERN); const isAbsolute_ = isAbsolute(path); - return { + const split: SplitPath = { segments, isAbsolute: isAbsolute_, - hasTrailingSep: !!path.match(new RegExp(`${s}$`)), - winRoot: isWindows && isAbsolute_ ? segments.shift() : undefined, + hasTrailingSep: path.match(new RegExp(`${s}$`)) !== null, }; + if (isWindows && isAbsolute_) { + split.winRoot = segments.shift()!; + } + return split; } function throwUnlessNotFound(error: unknown) { @@ -276,9 +279,9 @@ export async function* expandGlob( includeDirs = true, extended = true, globstar = true, - caseInsensitive, - followSymlinks, - canonicalize, + caseInsensitive = false, + followSymlinks = false, + canonicalize = true, } = options ?? {}; const { @@ -433,9 +436,9 @@ export function* expandGlobSync( includeDirs = true, extended = true, globstar = true, - caseInsensitive, - followSymlinks, - canonicalize, + caseInsensitive = false, + followSymlinks = false, + canonicalize = true, } = options ?? {}; const { diff --git a/fs/walk.ts b/fs/walk.ts index e3c04c0e6..4869db3f9 100644 --- a/fs/walk.ts +++ b/fs/walk.ts @@ -500,16 +500,23 @@ export async function* walk( } if (isSymlink || isDirectory) { - yield* walk(path, { + const opts: WalkOptions = { maxDepth: maxDepth - 1, includeFiles, includeDirs, includeSymlinks, followSymlinks, - exts, - match, - skip, - }); + }; + if (exts !== undefined) { + opts.exts = exts; + } + if (match !== undefined) { + opts.match = match; + } + if (skip !== undefined) { + opts.skip = skip; + } + yield* walk(path, opts); } else if (includeFiles && include(path, exts, match, skip)) { yield { path, ...entry }; } @@ -923,16 +930,23 @@ export function* walkSync( } if (isSymlink || isDirectory) { - yield* walkSync(path, { + const opts: WalkOptions = { maxDepth: maxDepth - 1, includeFiles, includeDirs, includeSymlinks, followSymlinks, - exts, - match, - skip, - }); + }; + if (exts !== undefined) { + opts.exts = exts; + } + if (match !== undefined) { + opts.match = match; + } + if (skip !== undefined) { + opts.skip = skip; + } + yield* walkSync(path, opts); } else if (includeFiles && include(path, exts, match, skip)) { yield { path, ...entry }; } diff --git a/http/_negotiation/common.ts b/http/_negotiation/common.ts index b7534f432..ef3d8878c 100644 --- a/http/_negotiation/common.ts +++ b/http/_negotiation/common.ts @@ -31,9 +31,9 @@ export interface Specificity { i: number; - o?: number; + o: number | undefined; q: number; - s?: number; + s: number | undefined; } export function compareSpecs(a: Specificity, b: Specificity): number { diff --git a/http/_negotiation/encoding.ts b/http/_negotiation/encoding.ts index 9600d5630..243e6872b 100644 --- a/http/_negotiation/encoding.ts +++ b/http/_negotiation/encoding.ts @@ -46,7 +46,7 @@ function parseEncoding( return undefined; } - const encoding = match[1]; + const encoding = match[1]!; let q = 1; if (match[2]) { const params = match[2].split(";"); @@ -59,7 +59,7 @@ function parseEncoding( } } - return { encoding, q, i }; + return { encoding, o: undefined, q, i, s: undefined }; } function specify( @@ -104,8 +104,10 @@ function parseAcceptEncoding(accept: string): EncodingSpecificity[] { if (!hasIdentity) { parsedAccepts.push({ encoding: "identity", + o: undefined, q: minQuality, i: accepts.length - 1, + s: undefined, }); } diff --git a/http/_negotiation/language.ts b/http/_negotiation/language.ts index 35a70c05b..0f055bd45 100644 --- a/http/_negotiation/language.ts +++ b/http/_negotiation/language.ts @@ -33,7 +33,7 @@ import { compareSpecs, isQuality, type Specificity } from "./common.ts"; interface LanguageSpecificity extends Specificity { prefix: string; - suffix?: string; + suffix: string | undefined; full: string; } @@ -53,7 +53,7 @@ function parseLanguage( return undefined; } - const full = suffix ? `${prefix}-${suffix}` : prefix; + const full = suffix !== undefined ? `${prefix}-${suffix}` : prefix; let q = 1; if (match[3]) { @@ -67,7 +67,7 @@ function parseLanguage( } } - return { prefix, suffix, full, q, i }; + return { prefix, suffix, full, i, o: undefined, q, s: undefined }; } function parseAcceptLanguage(accept: string): LanguageSpecificity[] { diff --git a/http/_negotiation/media_type.ts b/http/_negotiation/media_type.ts index f82d5f2d7..99a26dca5 100644 --- a/http/_negotiation/media_type.ts +++ b/http/_negotiation/media_type.ts @@ -80,7 +80,7 @@ function parseMediaType( } } - return { type, subtype, params, q, i }; + return { type, subtype, params, i, o: undefined, q, s: undefined }; } function parseAccept(accept: string): MediaTypeSpecificity[] { @@ -131,8 +131,8 @@ function specify( if (keys.length) { if ( keys.every((key) => - (spec.params[key] || "").toLowerCase() === - (p.params[key] || "").toLowerCase() + (spec.params[key] ?? "").toLowerCase() === + (p.params[key] ?? "").toLowerCase() ) ) { s |= 1; @@ -161,9 +161,9 @@ function getMediaTypePriority( if ( spec && - ((priority.s || 0) - (spec.s || 0) || - (priority.q || 0) - (spec.q || 0) || - (priority.o || 0) - (spec.o || 0)) < 0 + ((priority.s ?? 0) - (spec.s ?? 0) || + (priority.q ?? 0) - (spec.q ?? 0) || + (priority.o ?? 0) - (spec.o ?? 0)) < 0 ) { priority = spec; } @@ -176,7 +176,7 @@ export function preferredMediaTypes( accept?: string | null, provided?: string[], ): string[] { - const accepts = parseAccept(accept === undefined ? "*/*" : accept || ""); + const accepts = parseAccept(accept === undefined ? "*/*" : accept ?? ""); if (!provided) { return accepts diff --git a/http/cookie.ts b/http/cookie.ts index 662c5128e..f38300ae9 100644 --- a/http/cookie.ts +++ b/http/cookie.ts @@ -384,7 +384,7 @@ function parseSetCookie(value: string): Cookie | null { cookie.httpOnly = true; break; case "samesite": - cookie.sameSite = value as Cookie["sameSite"]; + cookie.sameSite = value as NonNullable; break; default: if (!Array.isArray(cookie.unparsed)) { diff --git a/http/file_server.ts b/http/file_server.ts index e1fa376d6..6a22d9215 100644 --- a/http/file_server.ts +++ b/http/file_server.ts @@ -179,7 +179,7 @@ export async function serveFile( return createStandardResponse(STATUS_CODE.MethodNotAllowed); } - let { etagAlgorithm: algorithm, fileInfo } = options ?? {}; + let { etagAlgorithm: algorithm = "SHA-256", fileInfo } = options ?? {}; try { fileInfo ??= await Deno.stat(filePath); @@ -682,11 +682,12 @@ async function createServeDirResponse( req: Request, opts: ServeDirOptions, ) { - const target = opts.fsRoot || "."; + const target = opts.fsRoot ?? "."; const urlRoot = opts.urlRoot; const showIndex = opts.showIndex ?? true; const showDotfiles = opts.showDotfiles || false; - const { etagAlgorithm, showDirListing, quiet } = opts; + const { etagAlgorithm = "SHA-256", showDirListing = false, quiet = false } = + opts; const url = new URL(req.url); const decodedUrl = decodeURIComponent(url.pathname); @@ -800,7 +801,7 @@ function main() { }, }); const port = serverArgs.port ? Number(serverArgs.port) : undefined; - const headers = serverArgs.header || []; + const headers = serverArgs.header ?? []; const host = serverArgs.host; const certFile = serverArgs.cert; const keyFile = serverArgs.key; @@ -855,21 +856,25 @@ function main() { console.log(message); } - if (useTls) { - Deno.serve({ - port, - hostname: host, - onListen, - cert: Deno.readTextFileSync(certFile), - key: Deno.readTextFileSync(keyFile), - }, handler); - } else { - Deno.serve({ - port, - hostname: host, - onListen, - }, handler); + // TODO(petamoriken): Migrate `Deno.ServeTcpOptions | (Deno.ServeTcpOptions & Deno.TlsCertifiedKeyOptions)` in v2 + const options: { + port?: number; + hostname?: string; + onListen?: (localAddr: Deno.NetAddr) => void; + cert?: string; + key?: string; + } = { + hostname: host, + onListen, + }; + if (port !== undefined) { + options.port = port; } + if (useTls) { + options.cert = Deno.readTextFileSync(certFile); + options.key = Deno.readTextFileSync(keyFile); + } + Deno.serve(options, handler); } function printUsage() { diff --git a/http/user_agent.ts b/http/user_agent.ts index 9e3c8f389..dcee8288c 100644 --- a/http/user_agent.ts +++ b/http/user_agent.ts @@ -980,11 +980,11 @@ const matchers: Matchers = { * ``` */ export class UserAgent { - #browser?: Browser; - #cpu?: Cpu; - #device?: Device; - #engine?: Engine; - #os?: Os; + #browser: Browser | undefined; + #cpu: Cpu | undefined; + #device: Device | undefined; + #engine: Engine | undefined; + #os: Os | undefined; #ua: string; /** diff --git a/internal/diff.ts b/internal/diff.ts index ad091d042..0a9776da2 100644 --- a/internal/diff.ts +++ b/internal/diff.ts @@ -198,7 +198,7 @@ export function createFp( } const isAdding = (down?.y === -1) || k === M || - (slide?.y || 0) > (down?.y || 0) + 1; + (slide?.y ?? 0) > (down?.y ?? 0) + 1; if (slide && isAdding) { const prev = slide.id; ptr++; diff --git a/log/file_handler.ts b/log/file_handler.ts index 137595ae4..c6e1dad1f 100644 --- a/log/file_handler.ts +++ b/log/file_handler.ts @@ -17,6 +17,9 @@ export type LogMode = "a" | "w" | "x"; export interface FileHandlerOptions extends BaseHandlerOptions { filename: string; + /** + * @default {"a"} + */ mode?: LogMode; /** * Buffer size for writing log messages to file, in bytes. @@ -60,7 +63,7 @@ export class FileHandler extends BaseHandler { super(levelName, options); this[filenameSymbol] = options.filename; // default to append mode, write only - this[modeSymbol] = options.mode ? options.mode : "a"; + this[modeSymbol] = options.mode ?? "a"; this[openOptionsSymbol] = { createNew: this[modeSymbol] === "x", create: this[modeSymbol] !== "x", diff --git a/log/logger.ts b/log/logger.ts index f661e3011..2bdfa7c54 100644 --- a/log/logger.ts +++ b/log/logger.ts @@ -72,7 +72,7 @@ export class Logger { ) { this.#loggerName = loggerName; this.#level = getLevelByName(levelName); - this.handlers = options.handlers || []; + this.handlers = options.handlers ?? []; } /** Use this to retrieve the current numeric log level. */ diff --git a/log/setup.ts b/log/setup.ts index 0caa063e1..b4e175f8d 100644 --- a/log/setup.ts +++ b/log/setup.ts @@ -20,7 +20,7 @@ export function setup(config: LogConfig) { state.handlers.clear(); // setup handlers - const handlers = state.config.handlers || {}; + const handlers = state.config.handlers ?? {}; for (const [handlerName, handler] of Object.entries(handlers)) { handler.setup(); @@ -31,9 +31,9 @@ export function setup(config: LogConfig) { state.loggers.clear(); // setup loggers - const loggers = state.config.loggers || {}; + const loggers = state.config.loggers ?? {}; for (const [loggerName, loggerConfig] of Object.entries(loggers)) { - const handlerNames = loggerConfig.handlers || []; + const handlerNames = loggerConfig.handlers ?? []; const handlers: BaseHandler[] = []; handlerNames.forEach((handlerName) => { @@ -43,7 +43,7 @@ export function setup(config: LogConfig) { } }); - const levelName = loggerConfig.level || DEFAULT_LEVEL; + const levelName = loggerConfig.level ?? DEFAULT_LEVEL; const logger = new Logger(loggerName, levelName, { handlers: handlers }); state.loggers.set(loggerName, logger); } diff --git a/net/get_network_address.ts b/net/get_network_address.ts index 5576fc955..8c75f074b 100644 --- a/net/get_network_address.ts +++ b/net/get_network_address.ts @@ -19,7 +19,7 @@ * ```ts no-assert no-eval * import { getNetworkAddress } from "@std/net/get-network-address"; * - * const hostname = getNetworkAddress(); + * const hostname = getNetworkAddress()!; * * Deno.serve({ port: 0, hostname }, () => new Response("Hello, world!")); * ``` @@ -28,7 +28,7 @@ * ```ts no-assert no-eval * import { getNetworkAddress } from "@std/net/get-network-address"; * - * const hostname = getNetworkAddress("IPv6"); + * const hostname = getNetworkAddress("IPv6")!; * * Deno.serve({ port: 0, hostname }, () => new Response("Hello, world!")); * ``` diff --git a/path/_common/format.ts b/path/_common/format.ts index 85739db6b..576d64130 100644 --- a/path/_common/format.ts +++ b/path/_common/format.ts @@ -9,7 +9,7 @@ export function _format( ): string { const dir: string | undefined = pathObject.dir || pathObject.root; const base: string = pathObject.base || - (pathObject.name || "") + (pathObject.ext || ""); + (pathObject.name ?? "") + (pathObject.ext ?? ""); if (!dir) return base; if (base === sep) return dir; if (dir === pathObject.root) return dir + base; diff --git a/semver/increment.ts b/semver/increment.ts index 654b9a301..7d9c36d1d 100644 --- a/semver/increment.ts +++ b/semver/increment.ts @@ -91,7 +91,7 @@ export function increment( ): SemVer { const build = options.build !== undefined ? parseBuild(options.build) - : version.build; + : version.build ?? []; switch (release) { case "premajor": diff --git a/semver/increment_test.ts b/semver/increment_test.ts index 7cd77eb03..f3e4b6567 100644 --- a/semver/increment_test.ts +++ b/semver/increment_test.ts @@ -1,19 +1,25 @@ // Copyright Isaac Z. Schlueter and Contributors. All rights reserved. ISC license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assertEquals, assertThrows } from "@std/assert"; -import type { ReleaseType, SemVer } from "./types.ts"; +import type { ReleaseType } from "./types.ts"; import { increment } from "./increment.ts"; import { format } from "./format.ts"; +interface LooseSemVer { + major: number; + minor: number; + patch: number; + prerelease?: (string | number)[] | undefined; + build?: string[] | undefined; +} + Deno.test("increment()", async (t) => { - // [version, inc, result, identifier] - // increment(version, inc) -> result const versions: [ - SemVer, - ReleaseType, - string?, - string?, - string?, + version: LooseSemVer, + op: ReleaseType, + prerelease: string | undefined, + build: string | undefined, + expected: string | undefined, ][] = [ [ { major: 1, minor: 2, patch: 3 }, @@ -948,7 +954,13 @@ Deno.test("increment()", async (t) => { "1.2.3-0", ], [ - { major: 1, minor: 2, patch: 3, prerelease: undefined, build: undefined }, + { + major: 1, + minor: 2, + patch: 3, + prerelease: undefined, + build: undefined, + }, "pre", undefined, undefined, @@ -965,8 +977,10 @@ Deno.test("increment()", async (t) => { for (const [version, op, prerelease, build, expected] of versions) { await t.step({ + // @ts-expect-error: explicitly giving undefined name: `${op} ${format(version)}`, fn: () => { + // @ts-expect-error: explicitly giving undefined const actual = increment(version, op, { prerelease, build }); assertEquals(format(actual), expected); }, diff --git a/testing/_test_suite.ts b/testing/_test_suite.ts index 805a8b093..bd74f85dd 100644 --- a/testing/_test_suite.ts +++ b/testing/_test_suite.ts @@ -42,24 +42,6 @@ export interface ItDefinition extends Omit { /** The names of all the different types of hooks. */ export type HookNames = "beforeAll" | "afterAll" | "beforeEach" | "afterEach"; -/** Optional test definition keys. */ -const optionalTestDefinitionKeys: (keyof Deno.TestDefinition)[] = [ - "only", - "permissions", - "ignore", - "sanitizeExit", - "sanitizeOps", - "sanitizeResources", -]; - -/** Optional test step definition keys. */ -const optionalTestStepDefinitionKeys: (keyof Deno.TestStepDefinition)[] = [ - "ignore", - "sanitizeExit", - "sanitizeOps", - "sanitizeResources", -]; - /** * A group of tests. */ @@ -126,14 +108,8 @@ export class TestSuiteInternal implements TestSuite { if (!ignore && this.hasOnlyStep) { only = true; } - TestSuiteInternal.registerTest({ + const options: Deno.TestDefinition = { name, - ignore, - only, - permissions, - sanitizeExit, - sanitizeOps, - sanitizeResources, fn: async (t) => { TestSuiteInternal.runningCount++; try { @@ -164,7 +140,26 @@ export class TestSuiteInternal implements TestSuite { TestSuiteInternal.runningCount--; } }, - }); + }; + if (ignore !== undefined) { + options.ignore = ignore; + } + if (only !== undefined) { + options.only = only; + } + if (permissions !== undefined) { + options.permissions = permissions; + } + if (sanitizeExit !== undefined) { + options.sanitizeExit = sanitizeExit; + } + if (sanitizeOps !== undefined) { + options.sanitizeOps = sanitizeOps; + } + if (sanitizeResources !== undefined) { + options.sanitizeResources = sanitizeResources; + } + TestSuiteInternal.registerTest(options); } } @@ -196,9 +191,24 @@ export class TestSuiteInternal implements TestSuite { /** This is used internally to register tests. */ static registerTest(options: Deno.TestDefinition) { options = { ...options }; - optionalTestDefinitionKeys.forEach((key) => { - if (typeof options[key] === "undefined") delete options[key]; - }); + if (options.only === undefined) { + delete options.only; + } + if (options.permissions === undefined) { + delete options.permissions; + } + if (options.ignore === undefined) { + delete options.ignore; + } + if (options.sanitizeExit === undefined) { + delete options.sanitizeExit; + } + if (options.sanitizeOps === undefined) { + delete options.sanitizeOps; + } + if (options.sanitizeResources === undefined) { + delete options.sanitizeResources; + } Deno.test(options); } @@ -289,10 +299,6 @@ export class TestSuiteInternal implements TestSuite { const options: Deno.TestStepDefinition = { name, - ignore, - sanitizeExit, - sanitizeOps, - sanitizeResources, fn: async (t) => { if (permissions) { throw new Error( @@ -328,9 +334,18 @@ export class TestSuiteInternal implements TestSuite { } }, }; - optionalTestStepDefinitionKeys.forEach((key) => { - if (typeof options[key] === "undefined") delete options[key]; - }); + if (ignore !== undefined) { + options.ignore = ignore; + } + if (sanitizeExit !== undefined) { + options.sanitizeExit = sanitizeExit; + } + if (sanitizeOps !== undefined) { + options.sanitizeOps = sanitizeOps; + } + if (sanitizeResources !== undefined) { + options.sanitizeResources = sanitizeResources; + } await t.step(options); } } diff --git a/testing/bdd.ts b/testing/bdd.ts index 81a8e7f71..fc21fc2bc 100644 --- a/testing/bdd.ts +++ b/testing/bdd.ts @@ -516,7 +516,7 @@ function itDefinition(...args: ItArgs): ItDefinition { } return { - suite, + ...(suite !== undefined ? { suite } : {}), ...options, name, fn, @@ -585,14 +585,8 @@ export function it(...args: ItArgs) { sanitizeOps, sanitizeResources, } = options; - TestSuiteInternal.registerTest({ + const opts: Deno.TestDefinition = { name, - ignore, - only, - permissions, - sanitizeExit, - sanitizeOps, - sanitizeResources, async fn(t) { TestSuiteInternal.runningCount++; try { @@ -601,7 +595,26 @@ export function it(...args: ItArgs) { TestSuiteInternal.runningCount--; } }, - }); + }; + if (ignore !== undefined) { + opts.ignore = ignore; + } + if (only !== undefined) { + opts.only = only; + } + if (permissions !== undefined) { + opts.permissions = permissions; + } + if (sanitizeExit !== undefined) { + opts.sanitizeExit = sanitizeExit; + } + if (sanitizeOps !== undefined) { + opts.sanitizeOps = sanitizeOps; + } + if (sanitizeResources !== undefined) { + opts.sanitizeResources = sanitizeResources; + } + TestSuiteInternal.registerTest(opts); } } @@ -999,7 +1012,9 @@ function describeDefinition( options = {}; } else { options = optionsOrFn ?? {}; - if (!fn) fn = (options as Omit, "name">).fn; + if (fn === undefined) { + fn = (options as Omit, "name">).fn; + } } } else if (typeof optionsOrNameOrFn === "function") { fn = optionsOrNameOrFn; @@ -1015,19 +1030,19 @@ function describeDefinition( name = (options as DescribeDefinition).name ?? fn?.name ?? ""; } - if (!suite) { + if (suite === undefined) { suite = options.suite; } - if (!suite && TestSuiteInternal.current) { + if (suite === undefined && TestSuiteInternal.current) { const { symbol } = TestSuiteInternal.current; suite = { symbol }; } return { ...options, - suite, + suite: suite!, name, - fn, + fn: fn!, }; } diff --git a/testing/mock.ts b/testing/mock.ts index b542f218e..468223068 100644 --- a/testing/mock.ts +++ b/testing/mock.ts @@ -720,8 +720,8 @@ function methodSpy< Object.defineProperty(self, property, { configurable: true, - enumerable: propertyDescriptor?.enumerable, - writable: propertyDescriptor?.writable, + enumerable: propertyDescriptor?.enumerable ?? false, + writable: propertyDescriptor?.writable ?? false, value: spy, }); @@ -1173,8 +1173,8 @@ export function stub< Object.defineProperty(self, property, { configurable: true, - enumerable: propertyDescriptor?.enumerable, - writable: propertyDescriptor?.writable, + enumerable: propertyDescriptor?.enumerable ?? false, + writable: propertyDescriptor?.writable ?? false, value: stub, }); diff --git a/testing/mock_test.ts b/testing/mock_test.ts index 51326b2cd..c88eb82c2 100644 --- a/testing/mock_test.ts +++ b/testing/mock_test.ts @@ -13,6 +13,7 @@ import { assertSpyCallArgs, assertSpyCallAsync, assertSpyCalls, + type ExpectedSpyCall, type MethodSpy, MockError, mockSession, @@ -1100,7 +1101,7 @@ Deno.test("assertSpyCall() works with method", () => { args: [7, 4], self: undefined, returned: 7, - }), + } as ExpectedSpyCall), AssertionError, "Spy not called with expected args", ); @@ -1116,7 +1117,7 @@ Deno.test("assertSpyCall() works with method", () => { () => assertSpyCall(spyMethod, 0, { self: undefined, - }), + } as ExpectedSpyCall), AssertionError, "Spy not expected to be called as method on object", ); @@ -1477,7 +1478,7 @@ Deno.test("assertSpyCallAsync() works with method", async () => { args: [7, 4], self: undefined, returned: 7, - }), + } as ExpectedSpyCall), AssertionError, "Spy not called with expected args", ); @@ -1493,7 +1494,7 @@ Deno.test("assertSpyCallAsync() works with method", async () => { () => assertSpyCallAsync(spyMethod, 0, { self: undefined, - }), + } as ExpectedSpyCall), AssertionError, "Spy not expected to be called as method on object", ); diff --git a/testing/snapshot.ts b/testing/snapshot.ts index 461de20f5..7900c04f0 100644 --- a/testing/snapshot.ts +++ b/testing/snapshot.ts @@ -459,7 +459,7 @@ class AssertSnapshotContext { * the count by 1. */ getCount(snapshotName: string) { - let count = this.#snapshotCounts.get(snapshotName) || 0; + let count = this.#snapshotCounts.get(snapshotName) ?? 0; this.#snapshotCounts.set(snapshotName, ++count); return count; } @@ -624,7 +624,7 @@ export async function assertSnapshot( } return { - msg: msgOrOpts, + msg: msgOrOpts!, }; } function getTestName( diff --git a/text/_util.ts b/text/_util.ts index 9b6b21876..5ca9572c9 100644 --- a/text/_util.ts +++ b/text/_util.ts @@ -12,7 +12,7 @@ const WORD_OR_NUMBER_REGEXP = new RegExp( ); export function splitToWords(input: string) { - return input.match(WORD_OR_NUMBER_REGEXP) || []; + return input.match(WORD_OR_NUMBER_REGEXP) ?? []; } export function capitalizeWord(word: string): string { diff --git a/webgpu/describe_texture_format.ts b/webgpu/describe_texture_format.ts index 1d1f7e8d6..e9bea38c9 100644 --- a/webgpu/describe_texture_format.ts +++ b/webgpu/describe_texture_format.ts @@ -36,7 +36,6 @@ const allFlags = GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | * import { assertEquals } from "@std/assert"; * * assertEquals(describeTextureFormat("rgba8unorm"), { - * requiredFeature: undefined, * sampleType: "float", * allowedUsages: 31, * blockDimensions: [1, 1], @@ -359,12 +358,15 @@ export function describeTextureFormat( throw new TypeError(`Unsupported GPUTextureFormat '${format}'`); } - return { - requiredFeature: info[0], + const ret: TextureFormatInfo = { sampleType: info[1], allowedUsages: info[2], blockDimensions: info[3], blockSize: info[4], components: info[5], }; + if (info[0] !== undefined) { + ret.requiredFeature = info[0]; + } + return ret; } diff --git a/webgpu/texture_with_data.ts b/webgpu/texture_with_data.ts index 5ad632a72..bb6f22605 100644 --- a/webgpu/texture_with_data.ts +++ b/webgpu/texture_with_data.ts @@ -12,6 +12,10 @@ function textureDimensionArrayLayerCount( case undefined: case "2d": return normalizeExtent3D(texture.size).depthOrArrayLayers ?? 1; + default: + throw new TypeError( + `Cannot count texture dimension layer: dimension value is "${texture.dimension}"`, + ); } } @@ -22,11 +26,16 @@ function normalizeExtent3D(size: GPUExtent3D): GPUExtent3DDict { "Cannot normalize Extent3d: width is not defined", ); } - return { + const dict: GPUExtent3DDict = { width: size[0], - height: size[1], - depthOrArrayLayers: size[2], }; + if (size[1] !== undefined) { + dict.height = size[1]; + } + if (size[2] !== undefined) { + dict.depthOrArrayLayers = size[2]; + } + return dict; } else { return size; } @@ -46,11 +55,14 @@ function extent3DPhysicalSize( Math.floor(((nSize.height ?? 1) + blockHeight - 1) / blockHeight) * blockHeight; - return { + const dict: GPUExtent3DDict = { width, height, - depthOrArrayLayers: nSize.depthOrArrayLayers, }; + if (nSize.depthOrArrayLayers !== undefined) { + dict.depthOrArrayLayers = nSize.depthOrArrayLayers; + } + return dict; } function extent3DMipLevelSize( diff --git a/yaml/_loader_state.ts b/yaml/_loader_state.ts index caba73668..2e8f75f30 100644 --- a/yaml/_loader_state.ts +++ b/yaml/_loader_state.ts @@ -188,7 +188,7 @@ export class LoaderState { lineStart = 0; position = 0; line = 0; - onWarning?: (error: Error) => void; + onWarning: ((error: Error) => void) | undefined; allowDuplicateKeys: boolean; implicitTypes: Type<"scalar">[]; typeMap: TypeMap; @@ -197,9 +197,9 @@ export class LoaderState { checkLineBreaks = false; tagMap = new Map(); anchorMap = new Map(); - tag?: string | null; - anchor?: string | null; - kind?: string | null; + tag: string | null | undefined; + anchor: string | null | undefined; + kind: string | null | undefined; result: unknown[] | Record | string | null = ""; constructor( diff --git a/yaml/parse.ts b/yaml/parse.ts index 10ed0be3f..64d0c54d1 100644 --- a/yaml/parse.ts +++ b/yaml/parse.ts @@ -79,7 +79,7 @@ export function parse( content = sanitizeInput(content); const state = new LoaderState(content, { ...options, - schema: SCHEMA_MAP.get(options.schema!), + schema: SCHEMA_MAP.get(options.schema!)!, }); const documentGenerator = state.readDocuments(); const document = documentGenerator.next().value; @@ -122,7 +122,7 @@ export function parseAll(content: string, options: ParseOptions = {}): unknown { content = sanitizeInput(content); const state = new LoaderState(content, { ...options, - schema: SCHEMA_MAP.get(options.schema!), + schema: SCHEMA_MAP.get(options.schema!)!, }); return [...state.readDocuments()]; } diff --git a/yaml/stringify.ts b/yaml/stringify.ts index e5159f9c0..39f96008f 100644 --- a/yaml/stringify.ts +++ b/yaml/stringify.ts @@ -112,7 +112,7 @@ export function stringify( ): string { const state = new DumperState({ ...options, - schema: SCHEMA_MAP.get(options.schema!), + schema: SCHEMA_MAP.get(options.schema!)!, }); return state.stringify(data); }