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)

This commit is contained in:
Kenta Moriuchi 2024-09-04 14:15:01 +09:00 committed by GitHub
parent 6aaf191081
commit 4d4bd0eb92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
52 changed files with 404 additions and 273 deletions

View File

@ -70,7 +70,7 @@ const USTAR_MAGIC_HEADER = "ustar\u000000" as const;
* Simple file reader * Simple file reader
*/ */
class FileReader implements Reader { class FileReader implements Reader {
#file?: Deno.FsFile; #file: Deno.FsFile | undefined;
#filePath: string; #filePath: string;
constructor(filePath: string) { constructor(filePath: string) {
@ -112,7 +112,7 @@ function formatHeader(data: TarData): Uint8Array {
const buffer = new Uint8Array(HEADER_LENGTH); const buffer = new Uint8Array(HEADER_LENGTH);
let offset = 0; let offset = 0;
for (const { field, length } of USTAR_STRUCTURE) { 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); buffer.set(entry, offset);
offset += length; offset += length;
} }
@ -334,7 +334,7 @@ export class Tar {
} }
} }
source = source || {}; source = source ?? {};
// set meta data // set meta data
let info: Deno.FileInfo | undefined; let info: Deno.FileInfo | undefined;
@ -351,8 +351,8 @@ export class Tar {
const mtime = Math.floor( const mtime = Math.floor(
source.mtime ?? (info?.mtime ?? new Date()).valueOf() / 1000, source.mtime ?? (info?.mtime ?? new Date()).valueOf() / 1000,
); );
const uid = source.uid || 0; const uid = source.uid ?? 0;
const gid = source.gid || 0; const gid = source.gid ?? 0;
if (typeof source.owner === "string" && source.owner.length >= 32) { if (typeof source.owner === "string" && source.owner.length >= 32) {
throw new Error( throw new Error(
@ -375,7 +375,6 @@ export class Tar {
: (info?.isDirectory ? FileTypes.directory : FileTypes.file); : (info?.isDirectory ? FileTypes.directory : FileTypes.file);
const tarData: TarDataWithSource = { const tarData: TarDataWithSource = {
fileName, fileName,
fileNamePrefix,
fileMode: pad(mode, 7), fileMode: pad(mode, 7),
uid: pad(uid, 7), uid: pad(uid, 7),
gid: pad(gid, 7), gid: pad(gid, 7),
@ -384,11 +383,18 @@ export class Tar {
checksum: " ", checksum: " ",
type: type.toString(), type: type.toString(),
ustar: USTAR_MAGIC_HEADER, ustar: USTAR_MAGIC_HEADER,
owner: source.owner || "", owner: source.owner ?? "",
group: source.group || "", group: source.group ?? "",
filePath: source.filePath,
reader: source.reader,
}; };
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 // calculate the checksum
let checksum = 0; let checksum = 0;

View File

@ -168,7 +168,7 @@ export class TarEntry implements Reader {
this.#reader = reader; this.#reader = reader;
// File Size // File Size
this.#size = this.fileSize || 0; this.#size = this.fileSize ?? 0;
// Entry Size // Entry Size
const blocks = Math.ceil(this.#size / HEADER_LENGTH); const blocks = Math.ceil(this.#size / HEADER_LENGTH);
this.#entrySize = blocks * HEADER_LENGTH; this.#entrySize = blocks * HEADER_LENGTH;
@ -259,7 +259,7 @@ export class TarEntry implements Reader {
const n = await readBlock(this.#reader, block); const n = await readBlock(this.#reader, block);
const bytesLeft = this.#size - this.#read; const bytesLeft = this.#size - this.#read;
this.#read += n || 0; this.#read += n ?? 0;
if (n === null || bytesLeft <= 0) { if (n === null || bytesLeft <= 0) {
if (n === null) this.#consumed = true; if (n === null) this.#consumed = true;
return null; return null;
@ -449,7 +449,9 @@ export class Untar {
}); });
meta.fileSize = parseInt(decoder.decode(header.fileSize), 8); 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 // Only create the `linkName` property for symbolic links to minimize
// the effect on existing code that only deals with non-links. // the effect on existing code that only deals with non-links.

View File

@ -271,15 +271,16 @@ export class UntarStream
}; };
} }
yield { const entry: TarStreamEntry = {
path: ("prefix" in header && header.prefix.length path: (
? header.prefix + "/" "prefix" in header && header.prefix.length ? header.prefix + "/" : ""
: "") + header.name, ) + header.name,
header, 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;
} }
} }

View File

@ -26,7 +26,7 @@ async function createTar(entries: TestEntry[]): Promise<Tar> {
contentSize: file.content.byteLength, contentSize: file.content.byteLength,
}; };
} else { } else {
options = { filePath: file.filePath }; options = { filePath: file.filePath! };
} }
await tar.append(file.name, options); await tar.append(file.name, options);

View File

@ -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 () => { Deno.test("retry() fails after five errors when undefined is passed", async () => {
const fiveErrors = generateErroringFunction(5); const fiveErrors = generateErroringFunction(5);
await assertRejects(() => await assertRejects(() =>
// @ts-expect-error: explicitly giving undefined
retry(fiveErrors, { retry(fiveErrors, {
maxAttempts: undefined, maxAttempts: undefined,
minTimeout: 100, minTimeout: 100,

View File

@ -986,7 +986,7 @@ Deno.test("parseArgs() handles types of all boolean disabled and string args", f
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
_: Array<string | number>; _: Array<string | number>;
} }
> >
@ -1061,9 +1061,9 @@ Deno.test("parseArgs() handles types of all boolean and string args", function (
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
bar?: string | undefined; bar?: string;
"foo-bar"?: string | undefined; "foo-bar"?: string;
_: Array<string | number>; _: Array<string | number>;
} }
> >
@ -1084,10 +1084,10 @@ Deno.test("parseArgs() handles types of all boolean and string args with default
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
bar: string | number; bar: string | number;
baz: unknown; baz: unknown;
"foo-bar"?: string | undefined; "foo-bar"?: string;
_: Array<string | number>; _: Array<string | number>;
} }
> >
@ -1144,9 +1144,9 @@ Deno.test("parseArgs() handles types of string args", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
bar?: string | undefined; bar?: string;
"foo-bar"?: string | undefined; "foo-bar"?: string;
_: Array<string | number>; _: Array<string | number>;
} }
> >
@ -1166,10 +1166,10 @@ Deno.test("parseArgs() handles types of string args with defaults", function ()
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
bar: string | boolean; bar: string | boolean;
baz: unknown; baz: unknown;
"foo-bar"?: string | undefined; "foo-bar"?: string;
_: Array<string | number>; _: Array<string | number>;
} }
> >
@ -1186,9 +1186,9 @@ Deno.test("parseArgs() handles types of boolean and string args", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
beep?: string | undefined; beep?: string;
boop?: string | undefined; boop?: string;
"beep-boop"?: string | undefined; "beep-boop"?: string;
foo: boolean; foo: boolean;
bar: boolean; bar: boolean;
"foo-bar": boolean; "foo-bar": boolean;
@ -1214,8 +1214,8 @@ Deno.test("parseArgs() handles types of boolean and string args with defaults",
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo: boolean; foo: boolean;
boop?: string | undefined; boop?: string;
"beep-boop"?: string | undefined; "beep-boop"?: string;
bar: number | boolean; bar: number | boolean;
baz: unknown; baz: unknown;
beep: string | Date; beep: string | Date;
@ -1294,12 +1294,12 @@ Deno.test("parseArgs() handles types of dotted string args", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
blubb?: string | undefined; blubb?: string;
foo?: { foo?: {
bar?: string | undefined; bar?: string;
baz?: { baz?: {
biz?: string | undefined; biz?: string;
buz?: string | undefined; buz?: string;
}; };
}; };
_: Array<string | number>; _: Array<string | number>;
@ -1332,7 +1332,7 @@ Deno.test("parseArgs() handles types of dotted string args with defaults", funct
bar: string | number; bar: string | number;
baz: { baz: {
biz: string | Date; biz: string | Date;
buz?: string | undefined; buz?: string;
}; };
}; };
bla: unknown; bla: unknown;
@ -1357,14 +1357,14 @@ Deno.test("parseArgs() handles types of dotted string and boolean args", functio
bar: boolean; bar: boolean;
baz: { baz: {
biz: boolean; biz: boolean;
buz?: string | undefined; buz?: string;
}; };
}; };
bla?: string | undefined; bla?: string;
beep: { beep: {
boop?: string | undefined; boop?: string;
bib: { bib: {
bab?: string | undefined; bab?: string;
bub: boolean; bub: boolean;
}; };
}; };
@ -1406,7 +1406,7 @@ Deno.test("parseArgs() handles types of dotted string and boolean args with defa
bar: boolean | number; bar: boolean | number;
baz: { baz: {
biz: boolean | Date; biz: boolean | Date;
buz?: string | undefined; buz?: string;
}; };
}; };
beep: { beep: {
@ -1448,7 +1448,7 @@ Deno.test("parseArgs() handles types of dotted string and boolean args with flat
bar: boolean | number; bar: boolean | number;
baz: { baz: {
biz: boolean | Date; biz: boolean | Date;
buz?: string | undefined; buz?: string;
}; };
}; };
beep: { beep: {
@ -1480,8 +1480,8 @@ Deno.test("parseArgs() handles types of dotted args with union defaults", functi
& { & {
foo: number | { foo: number | {
bar?: { bar?: {
baz?: string | undefined; baz?: string;
} | undefined; };
}; };
beep: Date | { beep: Date | {
boop: { boop: {
@ -1510,7 +1510,7 @@ Deno.test("parseArgs() handles types of dotted args with nested union defaults",
& { & {
foo: { foo: {
bar: number | { bar: number | {
baz?: string | undefined; baz?: string;
}; };
}; };
beep: { beep: {
@ -1577,7 +1577,7 @@ Deno.test("parseArgs() handles types of collect args", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
bar?: string | undefined; bar?: string;
dotted: { dotted: {
boop: Array<string>; boop: Array<string>;
beep: boolean; beep: boolean;
@ -1703,11 +1703,11 @@ Deno.test("parseArgs() handles types of negatable args", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
beep?: string | undefined; beep?: string;
boop?: string | false | undefined; boop?: string | false;
dotted: { dotted: {
zig?: string | false | undefined; zig?: string | false;
zag?: string | undefined; zag?: string;
tick: boolean; tick: boolean;
tock: boolean; tock: boolean;
}; };
@ -1739,11 +1739,11 @@ Deno.test("parseArgs() handles types of collect all args with defaults", functio
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo: boolean; foo: boolean;
beep?: string | undefined; beep?: string;
bar: number | boolean; bar: number | boolean;
boop: string | false | TextDecoder; boop: string | false | TextDecoder;
dotted: { dotted: {
zag?: string | undefined; zag?: string;
tock: boolean; tock: boolean;
tick: boolean | Date; tick: boolean | Date;
zig: string | false | RegExp; zig: string | false | RegExp;
@ -1770,8 +1770,8 @@ Deno.test("parseArgs() handles types of alias args", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
beep?: string | undefined; beep?: string;
boop?: string | undefined; boop?: string;
foo: boolean; foo: boolean;
bar: boolean; bar: boolean;
baz: boolean; baz: boolean;
@ -1803,7 +1803,7 @@ Deno.test("parseArgs() handles types of alias args with options", function () {
& { & {
baz: boolean; baz: boolean;
biz: boolean; biz: boolean;
bib?: string | undefined; bib?: string;
foo: number | boolean; foo: number | boolean;
bar: number | boolean; bar: number | boolean;
beep: string | false | Date; beep: string | false | Date;
@ -1827,7 +1827,7 @@ Deno.test("parseArgs() handles types of double dash option", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
_: Array<string | number>; _: Array<string | number>;
"--": Array<string>; "--": Array<string>;
} }
@ -1849,7 +1849,7 @@ Deno.test("parseArgs() handles types of nullish defaults", function () {
typeof argv, typeof argv,
& { [x: string]: unknown } & { [x: string]: unknown }
& { & {
foo?: string | undefined; foo?: string;
bar: string | undefined; bar: string | undefined;
baz: string | null; baz: string | null;
_: Array<string | number>; _: Array<string | number>;
@ -1864,7 +1864,7 @@ Deno.test("parseArgs() handles types of parse generics", function () {
IsExact< IsExact<
typeof argv, typeof argv,
{ {
foo?: number | undefined; foo?: number;
bar: string; bar: string;
_: Array<string | number>; _: Array<string | number>;
"--": Array<string>; "--": Array<string>;
@ -1879,7 +1879,7 @@ Deno.test("parseArgs() handles types of args generics", function () {
IsExact< IsExact<
ArgsResult, ArgsResult,
{ {
foo?: number | undefined; foo?: number;
bar: string; bar: string;
_: Array<string | number>; _: Array<string | number>;
"--": Array<string>; "--": Array<string>;
@ -1893,14 +1893,14 @@ Deno.test("parseArgs() handles types of parse options generics", function () {
assertType< assertType<
IsExact< IsExact<
Pick<Opts, "string">, Pick<Opts, "string">,
{ string?: "bar" | "baz" | ReadonlyArray<"bar" | "baz"> | undefined } { string?: "bar" | "baz" | ReadonlyArray<"bar" | "baz"> }
> >
>(true); >(true);
assertType< assertType<
IsExact< IsExact<
Pick<Opts, "boolean">, Pick<Opts, "boolean">,
{ boolean?: "foo" | ReadonlyArray<"foo"> | undefined } { boolean?: "foo" | ReadonlyArray<"foo"> }
> >
>(true); >(true);
@ -1913,7 +1913,7 @@ Deno.test("parseArgs() handles types of parse options generics", function () {
bar?: unknown; bar?: unknown;
baz?: unknown; baz?: unknown;
foo?: unknown; foo?: unknown;
} | undefined; };
} }
> >
>(true); >(true);
@ -1934,7 +1934,7 @@ Deno.test("parseArgs() handles types of parse options generic defaults", functio
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
[x: string]: any; [x: string]: any;
_: (string | number)[]; _: (string | number)[];
"--"?: string[] | undefined; "--"?: string[];
} }
> >
>(true); >(true);

View File

@ -123,7 +123,7 @@ export class Spinner {
message: string; message: string;
#interval: number; #interval: number;
#color?: Color; #color: Color | undefined;
#intervalId: number | undefined; #intervalId: number | undefined;
#active = false; #active = false;

View File

@ -21,9 +21,9 @@ class Parser {
#options: { #options: {
separator: string; separator: string;
trimLeadingSpace: boolean; trimLeadingSpace: boolean;
comment?: string; comment: string | undefined;
lazyQuotes?: boolean; lazyQuotes: boolean | undefined;
fieldsPerRecord?: number; fieldsPerRecord: number | undefined;
}; };
constructor({ constructor({
separator = ",", separator = ",",

View File

@ -415,6 +415,7 @@ x,,,
await t.step(testCase.name, async () => { await t.step(testCase.name, async () => {
const options: CsvParseStreamOptions = {}; const options: CsvParseStreamOptions = {};
if ("separator" in testCase) { if ("separator" in testCase) {
// @ts-expect-error: explicitly giving undefined
options.separator = testCase.separator; options.separator = testCase.separator;
} }
if ("comment" in testCase) { if ("comment" in testCase) {
@ -507,7 +508,7 @@ Deno.test({
// skipFirstRow option // skipFirstRow option
{ {
const { readable } = new CsvParseStream({ skipFirstRow: undefined }); const { readable } = new CsvParseStream({});
type _ = AssertTrue<IsExact<typeof readable, ReadableStream<string[]>>>; type _ = AssertTrue<IsExact<typeof readable, ReadableStream<string[]>>>;
} }
{ {
@ -526,7 +527,7 @@ Deno.test({
// columns option // columns option
{ {
const { readable } = new CsvParseStream({ columns: undefined }); const { readable } = new CsvParseStream({});
type _ = AssertTrue<IsExact<typeof readable, ReadableStream<string[]>>>; type _ = AssertTrue<IsExact<typeof readable, ReadableStream<string[]>>>;
} }
{ {
@ -547,17 +548,11 @@ Deno.test({
// skipFirstRow option + columns option // skipFirstRow option + columns option
{ {
const { readable } = new CsvParseStream({ const { readable } = new CsvParseStream({ skipFirstRow: false });
skipFirstRow: false,
columns: undefined,
});
type _ = AssertTrue<IsExact<typeof readable, ReadableStream<string[]>>>; type _ = AssertTrue<IsExact<typeof readable, ReadableStream<string[]>>>;
} }
{ {
const { readable } = new CsvParseStream({ const { readable } = new CsvParseStream({ skipFirstRow: true });
skipFirstRow: true,
columns: undefined,
});
type _ = AssertTrue< type _ = AssertTrue<
IsExact< IsExact<
typeof readable, typeof readable,

View File

@ -960,7 +960,7 @@ Deno.test({
// skipFirstRow option // skipFirstRow option
{ {
const parsed = parse("a\nb", { skipFirstRow: undefined }); const parsed = parse("a\nb", {});
type _ = AssertTrue<IsExact<typeof parsed, string[][]>>; type _ = AssertTrue<IsExact<typeof parsed, string[][]>>;
} }
{ {
@ -976,7 +976,7 @@ Deno.test({
// columns option // columns option
{ {
const parsed = parse("a\nb", { columns: undefined }); const parsed = parse("a\nb", {});
type _ = AssertTrue<IsExact<typeof parsed, string[][]>>; type _ = AssertTrue<IsExact<typeof parsed, string[][]>>;
} }
{ {
@ -994,11 +994,17 @@ Deno.test({
// skipFirstRow option + columns option // skipFirstRow option + columns option
{ {
const parsed = parse("a\nb", { skipFirstRow: false, columns: undefined }); const parsed = parse(
"a\nb",
{ skipFirstRow: false },
);
type _ = AssertTrue<IsExact<typeof parsed, string[][]>>; type _ = AssertTrue<IsExact<typeof parsed, string[][]>>;
} }
{ {
const parsed = parse("a\nb", { skipFirstRow: true, columns: undefined }); const parsed = parse(
"a\nb",
{ skipFirstRow: true },
);
type _ = AssertTrue< type _ = AssertTrue<
IsExact<typeof parsed, Record<string, string>[]> IsExact<typeof parsed, Record<string, string>[]>
>; >;

View File

@ -107,7 +107,12 @@ export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
if (columns && columns.length > 0) { if (columns && columns.length > 0) {
try { try {
controller.enqueue( controller.enqueue(
stringify([columns], { separator, headers: false }), stringify(
[columns],
separator !== undefined
? { separator, headers: false }
: { headers: false },
),
); );
} catch (error) { } catch (error) {
controller.error(error); controller.error(error);
@ -117,7 +122,12 @@ export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
transform(chunk, controller) { transform(chunk, controller) {
try { try {
controller.enqueue( controller.enqueue(
stringify([chunk], { separator, headers: false, columns }), stringify(
[chunk],
separator !== undefined
? { separator, headers: false, columns }
: { headers: false, columns },
),
); );
} catch (error) { } catch (error) {
controller.error(error); controller.error(error);

View File

@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"strict": true, "strict": true,
"exactOptionalPropertyTypes": true,
"useUnknownInCatchVariables": true, "useUnknownInCatchVariables": true,
"noImplicitOverride": true, "noImplicitOverride": true,
"noUncheckedIndexedAccess": true "noUncheckedIndexedAccess": true

View File

@ -26,7 +26,7 @@ function expandCharacters(str: string): string {
return str.replace( return str.replace(
/\\([nrt])/g, /\\([nrt])/g,
($1: keyof CharactersMap): string => charactersMap[$1] || "", ($1: keyof CharactersMap): string => charactersMap[$1] ?? "",
); );
} }

View File

@ -78,7 +78,7 @@ export function encodeBase58(data: ArrayBuffer | Uint8Array | string): string {
(carry > 0 || i < length) && reverseIterator !== -1; (carry > 0 || i < length) && reverseIterator !== -1;
reverseIterator--, i++ reverseIterator--, i++
) { ) {
carry += (b58Encoding[reverseIterator] || 0) * 256; carry += (b58Encoding[reverseIterator] ?? 0) * 256;
b58Encoding[reverseIterator] = Math.round(carry % 58); b58Encoding[reverseIterator] = Math.round(carry % 58);
carry = Math.floor(carry / 58); carry = Math.floor(carry / 58);
} }
@ -153,7 +153,7 @@ export function decodeBase58(b58: string): Uint8Array {
(carry > 0 || i < length) && reverseIterator !== -1; (carry > 0 || i < length) && reverseIterator !== -1;
reverseIterator--, i++ reverseIterator--, i++
) { ) {
carry += 58 * (output[reverseIterator] || 0); carry += 58 * (output[reverseIterator] ?? 0);
output[reverseIterator] = Math.round(carry % 256); output[reverseIterator] = Math.round(carry % 256);
carry = Math.floor(carry / 256); carry = Math.floor(carry / 256);
} }

View File

@ -33,6 +33,6 @@ export function assertEquals<T>(
return; return;
} }
const message = buildEqualErrorMessage(actual, expected, options || {}); const message = buildEqualErrorMessage(actual, expected, options ?? {});
throw new AssertionError(message); throw new AssertionError(message);
} }

View File

@ -24,14 +24,12 @@ import type { EqualOptions } from "./_types.ts";
export function assertNotEquals<T>( export function assertNotEquals<T>(
actual: T, actual: T,
expected: T, expected: T,
options?: EqualOptions, options: EqualOptions = {},
) { ) {
const { msg } = options || {};
if (!equal(actual, expected, options)) { if (!equal(actual, expected, options)) {
return; return;
} }
const message = buildNotEqualErrorMessage(actual, expected, { msg }); const message = buildNotEqualErrorMessage(actual, expected, options);
throw new AssertionError(message); throw new AssertionError(message);
} }

View File

@ -17,7 +17,7 @@ export function buildEqualErrorMessage<T>(
expected: T, expected: T,
options: EqualErrorMessageOptions, options: EqualErrorMessageOptions,
): string { ): string {
const { formatter = format, msg } = options || {}; const { formatter = format, msg } = options ?? {};
const msgSuffix = msg ? `: ${msg}` : "."; const msgSuffix = msg ? `: ${msg}` : ".";
const actualString = formatter(actual); const actualString = formatter(actual);
const expectedString = formatter(expected); const expectedString = formatter(expected);
@ -39,7 +39,7 @@ export function buildNotEqualErrorMessage<T>(
expected: T, expected: T,
options: EqualErrorMessageOptions, options: EqualErrorMessageOptions,
): string { ): string {
const { msg } = options || {}; const { msg } = options ?? {};
const actualString = String(actual); const actualString = String(actual);
const expectedString = String(expected); const expectedString = String(expected);

View File

@ -39,7 +39,7 @@ function asymmetricEqual(a: unknown, b: unknown) {
* @param options for the equality check * @param options for the equality check
*/ */
export function equal(c: unknown, d: unknown, options?: EqualOptions): boolean { export function equal(c: unknown, d: unknown, options?: EqualOptions): boolean {
const { customTesters = [], strictCheck } = options || {}; const { customTesters = [], strictCheck } = options ?? {};
const seen = new Map(); const seen = new Map();
return (function compare(a: unknown, b: unknown): boolean { return (function compare(a: unknown, b: unknown): boolean {
@ -113,8 +113,8 @@ export function equal(c: unknown, d: unknown, options?: EqualOptions): boolean {
return true; return true;
} }
const aKeys = Object.keys(a || {}); const aKeys = Object.keys(a ?? {});
const bKeys = Object.keys(b || {}); const bKeys = Object.keys(b ?? {});
let aLen = aKeys.length; let aLen = aKeys.length;
let bLen = bKeys.length; let bLen = bKeys.length;

View File

@ -6,12 +6,17 @@ import type { Tester } from "./_types.ts";
import { equal } from "./_equal.ts"; import { equal } from "./_equal.ts";
export function buildEqualOptions(options: EqualOptionUtil): EqualOptions { export function buildEqualOptions(options: EqualOptionUtil): EqualOptions {
const { customMessage, customTesters = [], strictCheck } = options || {}; const { customMessage, customTesters = [], strictCheck } = options ?? {};
return { const ret: EqualOptions = {
customTesters, 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<unknown> { export function isPromiseLike(value: unknown): value is PromiseLike<unknown> {

View File

@ -172,12 +172,20 @@ export function format(
function getLocaleOptions( function getLocaleOptions(
{ maximumFractionDigits, minimumFractionDigits }: FormatOptions, { maximumFractionDigits, minimumFractionDigits }: FormatOptions,
): LocaleOptions | undefined { ): LocaleOptions | undefined {
if (maximumFractionDigits || minimumFractionDigits) { if (
return { maximumFractionDigits === undefined && minimumFractionDigits === undefined
maximumFractionDigits, ) {
minimumFractionDigits, return;
};
} }
const ret: LocaleOptions = {};
if (maximumFractionDigits !== undefined) {
ret.maximumFractionDigits = maximumFractionDigits;
}
if (minimumFractionDigits !== undefined) {
ret.minimumFractionDigits = minimumFractionDigits;
}
return ret;
} }
/** /**

View File

@ -87,11 +87,22 @@ Deno.test("format() handles locale option", () => {
assertEquals(format(10.1, { locale: false }), "10.1 B"); assertEquals(format(10.1, { locale: false }), "10.1 B");
assertEquals(format(1e30, { locale: false }), "1000000 YB"); assertEquals(format(1e30, { locale: false }), "1000000 YB");
// @ts-expect-error: explicitly giving undefined
assertEquals(format(-0.4, { locale: undefined }), "-0.4 B"); assertEquals(format(-0.4, { locale: undefined }), "-0.4 B");
// @ts-expect-error: explicitly giving undefined
assertEquals(format(0.4, { locale: undefined }), "0.4 B"); assertEquals(format(0.4, { locale: undefined }), "0.4 B");
// @ts-expect-error: explicitly giving undefined
assertEquals(format(1001, { locale: undefined }), "1 kB"); assertEquals(format(1001, { locale: undefined }), "1 kB");
// @ts-expect-error: explicitly giving undefined
assertEquals(format(10.1, { locale: undefined }), "10.1 B"); assertEquals(format(10.1, { locale: undefined }), "10.1 B");
// @ts-expect-error: explicitly giving undefined
assertEquals(format(1e30, { locale: undefined }), "1000000 YB"); 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", () => { Deno.test("format() handles signed option", () => {

View File

@ -20,6 +20,7 @@ Deno.test({
name: "format() handles default style (narrow)", name: "format() handles default style (narrow)",
fn() { fn() {
assertEquals( assertEquals(
// @ts-expect-error: explicitly giving undefined
format(99674, { style: undefined }), format(99674, { style: undefined }),
"0d 0h 1m 39s 674ms 0µs 0ns", "0d 0h 1m 39s 674ms 0µs 0ns",
); );

View File

@ -184,12 +184,12 @@ const F = {
} as const; } as const;
class Flags { class Flags {
plus?: boolean; plus: boolean | undefined;
dash?: boolean; dash: boolean | undefined;
sharp?: boolean; sharp: boolean | undefined;
space?: boolean; space: boolean | undefined;
zero?: boolean; zero: boolean | undefined;
lessthan?: boolean; lessthan: boolean | undefined;
width = -1; width = -1;
precision = -1; precision = -1;
} }
@ -213,7 +213,7 @@ class Printf {
haveSeen: boolean[]; haveSeen: boolean[];
// barf, store precision and width errors for later processing ... // barf, store precision and width errors for later processing ...
tmpError?: string; tmpError: string | undefined;
constructor(format: string, ...args: unknown[]) { constructor(format: string, ...args: unknown[]) {
this.format = format; this.format = format;
@ -719,7 +719,7 @@ class Printf {
? this.flags.precision ? this.flags.precision
: DEFAULT_PRECISION; : DEFAULT_PRECISION;
const [fractional, rounding] = this.roundFractionToPrecision( const [fractional, rounding] = this.roundFractionToPrecision(
m[F.fractional] || "", m[F.fractional] ?? "",
precision, precision,
); );

View File

@ -15,7 +15,7 @@ export function extractAndParse<T>(
if (!match || match.index !== 0) { if (!match || match.index !== 0) {
throw new TypeError("Unexpected end of input"); 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 attrs = parse(frontMatter) as T;
const body = input.replace(match[0], ""); const body = input.replace(match[0], "");
return { frontMatter, body, attrs }; return { frontMatter, body, attrs };

View File

@ -66,12 +66,15 @@ function split(path: string): SplitPath {
.replace(new RegExp(`^${s}|${s}$`, "g"), "") .replace(new RegExp(`^${s}|${s}$`, "g"), "")
.split(SEPARATOR_PATTERN); .split(SEPARATOR_PATTERN);
const isAbsolute_ = isAbsolute(path); const isAbsolute_ = isAbsolute(path);
return { const split: SplitPath = {
segments, segments,
isAbsolute: isAbsolute_, isAbsolute: isAbsolute_,
hasTrailingSep: !!path.match(new RegExp(`${s}$`)), hasTrailingSep: path.match(new RegExp(`${s}$`)) !== null,
winRoot: isWindows && isAbsolute_ ? segments.shift() : undefined,
}; };
if (isWindows && isAbsolute_) {
split.winRoot = segments.shift()!;
}
return split;
} }
function throwUnlessNotFound(error: unknown) { function throwUnlessNotFound(error: unknown) {
@ -276,9 +279,9 @@ export async function* expandGlob(
includeDirs = true, includeDirs = true,
extended = true, extended = true,
globstar = true, globstar = true,
caseInsensitive, caseInsensitive = false,
followSymlinks, followSymlinks = false,
canonicalize, canonicalize = true,
} = options ?? {}; } = options ?? {};
const { const {
@ -433,9 +436,9 @@ export function* expandGlobSync(
includeDirs = true, includeDirs = true,
extended = true, extended = true,
globstar = true, globstar = true,
caseInsensitive, caseInsensitive = false,
followSymlinks, followSymlinks = false,
canonicalize, canonicalize = true,
} = options ?? {}; } = options ?? {};
const { const {

View File

@ -500,16 +500,23 @@ export async function* walk(
} }
if (isSymlink || isDirectory) { if (isSymlink || isDirectory) {
yield* walk(path, { const opts: WalkOptions = {
maxDepth: maxDepth - 1, maxDepth: maxDepth - 1,
includeFiles, includeFiles,
includeDirs, includeDirs,
includeSymlinks, includeSymlinks,
followSymlinks, followSymlinks,
exts, };
match, if (exts !== undefined) {
skip, 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)) { } else if (includeFiles && include(path, exts, match, skip)) {
yield { path, ...entry }; yield { path, ...entry };
} }
@ -923,16 +930,23 @@ export function* walkSync(
} }
if (isSymlink || isDirectory) { if (isSymlink || isDirectory) {
yield* walkSync(path, { const opts: WalkOptions = {
maxDepth: maxDepth - 1, maxDepth: maxDepth - 1,
includeFiles, includeFiles,
includeDirs, includeDirs,
includeSymlinks, includeSymlinks,
followSymlinks, followSymlinks,
exts, };
match, if (exts !== undefined) {
skip, 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)) { } else if (includeFiles && include(path, exts, match, skip)) {
yield { path, ...entry }; yield { path, ...entry };
} }

View File

@ -31,9 +31,9 @@
export interface Specificity { export interface Specificity {
i: number; i: number;
o?: number; o: number | undefined;
q: number; q: number;
s?: number; s: number | undefined;
} }
export function compareSpecs(a: Specificity, b: Specificity): number { export function compareSpecs(a: Specificity, b: Specificity): number {

View File

@ -46,7 +46,7 @@ function parseEncoding(
return undefined; return undefined;
} }
const encoding = match[1]; const encoding = match[1]!;
let q = 1; let q = 1;
if (match[2]) { if (match[2]) {
const params = match[2].split(";"); 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( function specify(
@ -104,8 +104,10 @@ function parseAcceptEncoding(accept: string): EncodingSpecificity[] {
if (!hasIdentity) { if (!hasIdentity) {
parsedAccepts.push({ parsedAccepts.push({
encoding: "identity", encoding: "identity",
o: undefined,
q: minQuality, q: minQuality,
i: accepts.length - 1, i: accepts.length - 1,
s: undefined,
}); });
} }

View File

@ -33,7 +33,7 @@ import { compareSpecs, isQuality, type Specificity } from "./common.ts";
interface LanguageSpecificity extends Specificity { interface LanguageSpecificity extends Specificity {
prefix: string; prefix: string;
suffix?: string; suffix: string | undefined;
full: string; full: string;
} }
@ -53,7 +53,7 @@ function parseLanguage(
return undefined; return undefined;
} }
const full = suffix ? `${prefix}-${suffix}` : prefix; const full = suffix !== undefined ? `${prefix}-${suffix}` : prefix;
let q = 1; let q = 1;
if (match[3]) { 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[] { function parseAcceptLanguage(accept: string): LanguageSpecificity[] {

View File

@ -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[] { function parseAccept(accept: string): MediaTypeSpecificity[] {
@ -131,8 +131,8 @@ function specify(
if (keys.length) { if (keys.length) {
if ( if (
keys.every((key) => keys.every((key) =>
(spec.params[key] || "").toLowerCase() === (spec.params[key] ?? "").toLowerCase() ===
(p.params[key] || "").toLowerCase() (p.params[key] ?? "").toLowerCase()
) )
) { ) {
s |= 1; s |= 1;
@ -161,9 +161,9 @@ function getMediaTypePriority(
if ( if (
spec && spec &&
((priority.s || 0) - (spec.s || 0) || ((priority.s ?? 0) - (spec.s ?? 0) ||
(priority.q || 0) - (spec.q || 0) || (priority.q ?? 0) - (spec.q ?? 0) ||
(priority.o || 0) - (spec.o || 0)) < 0 (priority.o ?? 0) - (spec.o ?? 0)) < 0
) { ) {
priority = spec; priority = spec;
} }
@ -176,7 +176,7 @@ export function preferredMediaTypes(
accept?: string | null, accept?: string | null,
provided?: string[], provided?: string[],
): string[] { ): string[] {
const accepts = parseAccept(accept === undefined ? "*/*" : accept || ""); const accepts = parseAccept(accept === undefined ? "*/*" : accept ?? "");
if (!provided) { if (!provided) {
return accepts return accepts

View File

@ -384,7 +384,7 @@ function parseSetCookie(value: string): Cookie | null {
cookie.httpOnly = true; cookie.httpOnly = true;
break; break;
case "samesite": case "samesite":
cookie.sameSite = value as Cookie["sameSite"]; cookie.sameSite = value as NonNullable<Cookie["sameSite"]>;
break; break;
default: default:
if (!Array.isArray(cookie.unparsed)) { if (!Array.isArray(cookie.unparsed)) {

View File

@ -179,7 +179,7 @@ export async function serveFile(
return createStandardResponse(STATUS_CODE.MethodNotAllowed); return createStandardResponse(STATUS_CODE.MethodNotAllowed);
} }
let { etagAlgorithm: algorithm, fileInfo } = options ?? {}; let { etagAlgorithm: algorithm = "SHA-256", fileInfo } = options ?? {};
try { try {
fileInfo ??= await Deno.stat(filePath); fileInfo ??= await Deno.stat(filePath);
@ -682,11 +682,12 @@ async function createServeDirResponse(
req: Request, req: Request,
opts: ServeDirOptions, opts: ServeDirOptions,
) { ) {
const target = opts.fsRoot || "."; const target = opts.fsRoot ?? ".";
const urlRoot = opts.urlRoot; const urlRoot = opts.urlRoot;
const showIndex = opts.showIndex ?? true; const showIndex = opts.showIndex ?? true;
const showDotfiles = opts.showDotfiles || false; 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 url = new URL(req.url);
const decodedUrl = decodeURIComponent(url.pathname); const decodedUrl = decodeURIComponent(url.pathname);
@ -800,7 +801,7 @@ function main() {
}, },
}); });
const port = serverArgs.port ? Number(serverArgs.port) : undefined; const port = serverArgs.port ? Number(serverArgs.port) : undefined;
const headers = serverArgs.header || []; const headers = serverArgs.header ?? [];
const host = serverArgs.host; const host = serverArgs.host;
const certFile = serverArgs.cert; const certFile = serverArgs.cert;
const keyFile = serverArgs.key; const keyFile = serverArgs.key;
@ -855,21 +856,25 @@ function main() {
console.log(message); console.log(message);
} }
if (useTls) { // TODO(petamoriken): Migrate `Deno.ServeTcpOptions | (Deno.ServeTcpOptions & Deno.TlsCertifiedKeyOptions)` in v2
Deno.serve({ const options: {
port, port?: number;
hostname: host, hostname?: string;
onListen, onListen?: (localAddr: Deno.NetAddr) => void;
cert: Deno.readTextFileSync(certFile), cert?: string;
key: Deno.readTextFileSync(keyFile), key?: string;
}, handler); } = {
} else { hostname: host,
Deno.serve({ onListen,
port, };
hostname: host, if (port !== undefined) {
onListen, options.port = port;
}, handler);
} }
if (useTls) {
options.cert = Deno.readTextFileSync(certFile);
options.key = Deno.readTextFileSync(keyFile);
}
Deno.serve(options, handler);
} }
function printUsage() { function printUsage() {

View File

@ -980,11 +980,11 @@ const matchers: Matchers = {
* ``` * ```
*/ */
export class UserAgent { export class UserAgent {
#browser?: Browser; #browser: Browser | undefined;
#cpu?: Cpu; #cpu: Cpu | undefined;
#device?: Device; #device: Device | undefined;
#engine?: Engine; #engine: Engine | undefined;
#os?: Os; #os: Os | undefined;
#ua: string; #ua: string;
/** /**

View File

@ -198,7 +198,7 @@ export function createFp(
} }
const isAdding = (down?.y === -1) || const isAdding = (down?.y === -1) ||
k === M || k === M ||
(slide?.y || 0) > (down?.y || 0) + 1; (slide?.y ?? 0) > (down?.y ?? 0) + 1;
if (slide && isAdding) { if (slide && isAdding) {
const prev = slide.id; const prev = slide.id;
ptr++; ptr++;

View File

@ -17,6 +17,9 @@ export type LogMode = "a" | "w" | "x";
export interface FileHandlerOptions extends BaseHandlerOptions { export interface FileHandlerOptions extends BaseHandlerOptions {
filename: string; filename: string;
/**
* @default {"a"}
*/
mode?: LogMode; mode?: LogMode;
/** /**
* Buffer size for writing log messages to file, in bytes. * Buffer size for writing log messages to file, in bytes.
@ -60,7 +63,7 @@ export class FileHandler extends BaseHandler {
super(levelName, options); super(levelName, options);
this[filenameSymbol] = options.filename; this[filenameSymbol] = options.filename;
// default to append mode, write only // default to append mode, write only
this[modeSymbol] = options.mode ? options.mode : "a"; this[modeSymbol] = options.mode ?? "a";
this[openOptionsSymbol] = { this[openOptionsSymbol] = {
createNew: this[modeSymbol] === "x", createNew: this[modeSymbol] === "x",
create: this[modeSymbol] !== "x", create: this[modeSymbol] !== "x",

View File

@ -72,7 +72,7 @@ export class Logger {
) { ) {
this.#loggerName = loggerName; this.#loggerName = loggerName;
this.#level = getLevelByName(levelName); this.#level = getLevelByName(levelName);
this.handlers = options.handlers || []; this.handlers = options.handlers ?? [];
} }
/** Use this to retrieve the current numeric log level. */ /** Use this to retrieve the current numeric log level. */

View File

@ -20,7 +20,7 @@ export function setup(config: LogConfig) {
state.handlers.clear(); state.handlers.clear();
// setup handlers // setup handlers
const handlers = state.config.handlers || {}; const handlers = state.config.handlers ?? {};
for (const [handlerName, handler] of Object.entries(handlers)) { for (const [handlerName, handler] of Object.entries(handlers)) {
handler.setup(); handler.setup();
@ -31,9 +31,9 @@ export function setup(config: LogConfig) {
state.loggers.clear(); state.loggers.clear();
// setup loggers // setup loggers
const loggers = state.config.loggers || {}; const loggers = state.config.loggers ?? {};
for (const [loggerName, loggerConfig] of Object.entries(loggers)) { for (const [loggerName, loggerConfig] of Object.entries(loggers)) {
const handlerNames = loggerConfig.handlers || []; const handlerNames = loggerConfig.handlers ?? [];
const handlers: BaseHandler[] = []; const handlers: BaseHandler[] = [];
handlerNames.forEach((handlerName) => { 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 }); const logger = new Logger(loggerName, levelName, { handlers: handlers });
state.loggers.set(loggerName, logger); state.loggers.set(loggerName, logger);
} }

View File

@ -19,7 +19,7 @@
* ```ts no-assert no-eval * ```ts no-assert no-eval
* import { getNetworkAddress } from "@std/net/get-network-address"; * import { getNetworkAddress } from "@std/net/get-network-address";
* *
* const hostname = getNetworkAddress(); * const hostname = getNetworkAddress()!;
* *
* Deno.serve({ port: 0, hostname }, () => new Response("Hello, world!")); * Deno.serve({ port: 0, hostname }, () => new Response("Hello, world!"));
* ``` * ```
@ -28,7 +28,7 @@
* ```ts no-assert no-eval * ```ts no-assert no-eval
* import { getNetworkAddress } from "@std/net/get-network-address"; * 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!")); * Deno.serve({ port: 0, hostname }, () => new Response("Hello, world!"));
* ``` * ```

View File

@ -9,7 +9,7 @@ export function _format(
): string { ): string {
const dir: string | undefined = pathObject.dir || pathObject.root; const dir: string | undefined = pathObject.dir || pathObject.root;
const base: string = pathObject.base || const base: string = pathObject.base ||
(pathObject.name || "") + (pathObject.ext || ""); (pathObject.name ?? "") + (pathObject.ext ?? "");
if (!dir) return base; if (!dir) return base;
if (base === sep) return dir; if (base === sep) return dir;
if (dir === pathObject.root) return dir + base; if (dir === pathObject.root) return dir + base;

View File

@ -91,7 +91,7 @@ export function increment(
): SemVer { ): SemVer {
const build = options.build !== undefined const build = options.build !== undefined
? parseBuild(options.build) ? parseBuild(options.build)
: version.build; : version.build ?? [];
switch (release) { switch (release) {
case "premajor": case "premajor":

View File

@ -1,19 +1,25 @@
// Copyright Isaac Z. Schlueter and Contributors. All rights reserved. ISC license. // Copyright Isaac Z. Schlueter and Contributors. All rights reserved. ISC license.
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assertEquals, assertThrows } from "@std/assert"; 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 { increment } from "./increment.ts";
import { format } from "./format.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) => { Deno.test("increment()", async (t) => {
// [version, inc, result, identifier]
// increment(version, inc) -> result
const versions: [ const versions: [
SemVer, version: LooseSemVer,
ReleaseType, op: ReleaseType,
string?, prerelease: string | undefined,
string?, build: string | undefined,
string?, expected: string | undefined,
][] = [ ][] = [
[ [
{ major: 1, minor: 2, patch: 3 }, { major: 1, minor: 2, patch: 3 },
@ -948,7 +954,13 @@ Deno.test("increment()", async (t) => {
"1.2.3-0", "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", "pre",
undefined, undefined,
undefined, undefined,
@ -965,8 +977,10 @@ Deno.test("increment()", async (t) => {
for (const [version, op, prerelease, build, expected] of versions) { for (const [version, op, prerelease, build, expected] of versions) {
await t.step({ await t.step({
// @ts-expect-error: explicitly giving undefined
name: `${op} ${format(version)}`, name: `${op} ${format(version)}`,
fn: () => { fn: () => {
// @ts-expect-error: explicitly giving undefined
const actual = increment(version, op, { prerelease, build }); const actual = increment(version, op, { prerelease, build });
assertEquals(format(actual), expected); assertEquals(format(actual), expected);
}, },

View File

@ -42,24 +42,6 @@ export interface ItDefinition<T> extends Omit<Deno.TestDefinition, "fn"> {
/** The names of all the different types of hooks. */ /** The names of all the different types of hooks. */
export type HookNames = "beforeAll" | "afterAll" | "beforeEach" | "afterEach"; 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. * A group of tests.
*/ */
@ -126,14 +108,8 @@ export class TestSuiteInternal<T> implements TestSuite<T> {
if (!ignore && this.hasOnlyStep) { if (!ignore && this.hasOnlyStep) {
only = true; only = true;
} }
TestSuiteInternal.registerTest({ const options: Deno.TestDefinition = {
name, name,
ignore,
only,
permissions,
sanitizeExit,
sanitizeOps,
sanitizeResources,
fn: async (t) => { fn: async (t) => {
TestSuiteInternal.runningCount++; TestSuiteInternal.runningCount++;
try { try {
@ -164,7 +140,26 @@ export class TestSuiteInternal<T> implements TestSuite<T> {
TestSuiteInternal.runningCount--; 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<T> implements TestSuite<T> {
/** This is used internally to register tests. */ /** This is used internally to register tests. */
static registerTest(options: Deno.TestDefinition) { static registerTest(options: Deno.TestDefinition) {
options = { ...options }; options = { ...options };
optionalTestDefinitionKeys.forEach((key) => { if (options.only === undefined) {
if (typeof options[key] === "undefined") delete options[key]; 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); Deno.test(options);
} }
@ -289,10 +299,6 @@ export class TestSuiteInternal<T> implements TestSuite<T> {
const options: Deno.TestStepDefinition = { const options: Deno.TestStepDefinition = {
name, name,
ignore,
sanitizeExit,
sanitizeOps,
sanitizeResources,
fn: async (t) => { fn: async (t) => {
if (permissions) { if (permissions) {
throw new Error( throw new Error(
@ -328,9 +334,18 @@ export class TestSuiteInternal<T> implements TestSuite<T> {
} }
}, },
}; };
optionalTestStepDefinitionKeys.forEach((key) => { if (ignore !== undefined) {
if (typeof options[key] === "undefined") delete options[key]; 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); await t.step(options);
} }
} }

View File

@ -516,7 +516,7 @@ function itDefinition<T>(...args: ItArgs<T>): ItDefinition<T> {
} }
return { return {
suite, ...(suite !== undefined ? { suite } : {}),
...options, ...options,
name, name,
fn, fn,
@ -585,14 +585,8 @@ export function it<T>(...args: ItArgs<T>) {
sanitizeOps, sanitizeOps,
sanitizeResources, sanitizeResources,
} = options; } = options;
TestSuiteInternal.registerTest({ const opts: Deno.TestDefinition = {
name, name,
ignore,
only,
permissions,
sanitizeExit,
sanitizeOps,
sanitizeResources,
async fn(t) { async fn(t) {
TestSuiteInternal.runningCount++; TestSuiteInternal.runningCount++;
try { try {
@ -601,7 +595,26 @@ export function it<T>(...args: ItArgs<T>) {
TestSuiteInternal.runningCount--; 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<T>(
options = {}; options = {};
} else { } else {
options = optionsOrFn ?? {}; options = optionsOrFn ?? {};
if (!fn) fn = (options as Omit<DescribeDefinition<T>, "name">).fn; if (fn === undefined) {
fn = (options as Omit<DescribeDefinition<T>, "name">).fn;
}
} }
} else if (typeof optionsOrNameOrFn === "function") { } else if (typeof optionsOrNameOrFn === "function") {
fn = optionsOrNameOrFn; fn = optionsOrNameOrFn;
@ -1015,19 +1030,19 @@ function describeDefinition<T>(
name = (options as DescribeDefinition<T>).name ?? fn?.name ?? ""; name = (options as DescribeDefinition<T>).name ?? fn?.name ?? "";
} }
if (!suite) { if (suite === undefined) {
suite = options.suite; suite = options.suite;
} }
if (!suite && TestSuiteInternal.current) { if (suite === undefined && TestSuiteInternal.current) {
const { symbol } = TestSuiteInternal.current; const { symbol } = TestSuiteInternal.current;
suite = { symbol }; suite = { symbol };
} }
return { return {
...options, ...options,
suite, suite: suite!,
name, name,
fn, fn: fn!,
}; };
} }

View File

@ -720,8 +720,8 @@ function methodSpy<
Object.defineProperty(self, property, { Object.defineProperty(self, property, {
configurable: true, configurable: true,
enumerable: propertyDescriptor?.enumerable, enumerable: propertyDescriptor?.enumerable ?? false,
writable: propertyDescriptor?.writable, writable: propertyDescriptor?.writable ?? false,
value: spy, value: spy,
}); });
@ -1173,8 +1173,8 @@ export function stub<
Object.defineProperty(self, property, { Object.defineProperty(self, property, {
configurable: true, configurable: true,
enumerable: propertyDescriptor?.enumerable, enumerable: propertyDescriptor?.enumerable ?? false,
writable: propertyDescriptor?.writable, writable: propertyDescriptor?.writable ?? false,
value: stub, value: stub,
}); });

View File

@ -13,6 +13,7 @@ import {
assertSpyCallArgs, assertSpyCallArgs,
assertSpyCallAsync, assertSpyCallAsync,
assertSpyCalls, assertSpyCalls,
type ExpectedSpyCall,
type MethodSpy, type MethodSpy,
MockError, MockError,
mockSession, mockSession,
@ -1100,7 +1101,7 @@ Deno.test("assertSpyCall() works with method", () => {
args: [7, 4], args: [7, 4],
self: undefined, self: undefined,
returned: 7, returned: 7,
}), } as ExpectedSpyCall),
AssertionError, AssertionError,
"Spy not called with expected args", "Spy not called with expected args",
); );
@ -1116,7 +1117,7 @@ Deno.test("assertSpyCall() works with method", () => {
() => () =>
assertSpyCall(spyMethod, 0, { assertSpyCall(spyMethod, 0, {
self: undefined, self: undefined,
}), } as ExpectedSpyCall),
AssertionError, AssertionError,
"Spy not expected to be called as method on object", "Spy not expected to be called as method on object",
); );
@ -1477,7 +1478,7 @@ Deno.test("assertSpyCallAsync() works with method", async () => {
args: [7, 4], args: [7, 4],
self: undefined, self: undefined,
returned: 7, returned: 7,
}), } as ExpectedSpyCall),
AssertionError, AssertionError,
"Spy not called with expected args", "Spy not called with expected args",
); );
@ -1493,7 +1494,7 @@ Deno.test("assertSpyCallAsync() works with method", async () => {
() => () =>
assertSpyCallAsync(spyMethod, 0, { assertSpyCallAsync(spyMethod, 0, {
self: undefined, self: undefined,
}), } as ExpectedSpyCall),
AssertionError, AssertionError,
"Spy not expected to be called as method on object", "Spy not expected to be called as method on object",
); );

View File

@ -459,7 +459,7 @@ class AssertSnapshotContext {
* the count by 1. * the count by 1.
*/ */
getCount(snapshotName: string) { getCount(snapshotName: string) {
let count = this.#snapshotCounts.get(snapshotName) || 0; let count = this.#snapshotCounts.get(snapshotName) ?? 0;
this.#snapshotCounts.set(snapshotName, ++count); this.#snapshotCounts.set(snapshotName, ++count);
return count; return count;
} }
@ -624,7 +624,7 @@ export async function assertSnapshot(
} }
return { return {
msg: msgOrOpts, msg: msgOrOpts!,
}; };
} }
function getTestName( function getTestName(

View File

@ -12,7 +12,7 @@ const WORD_OR_NUMBER_REGEXP = new RegExp(
); );
export function splitToWords(input: string) { 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 { export function capitalizeWord(word: string): string {

View File

@ -36,7 +36,6 @@ const allFlags = GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST |
* import { assertEquals } from "@std/assert"; * import { assertEquals } from "@std/assert";
* *
* assertEquals(describeTextureFormat("rgba8unorm"), { * assertEquals(describeTextureFormat("rgba8unorm"), {
* requiredFeature: undefined,
* sampleType: "float", * sampleType: "float",
* allowedUsages: 31, * allowedUsages: 31,
* blockDimensions: [1, 1], * blockDimensions: [1, 1],
@ -359,12 +358,15 @@ export function describeTextureFormat(
throw new TypeError(`Unsupported GPUTextureFormat '${format}'`); throw new TypeError(`Unsupported GPUTextureFormat '${format}'`);
} }
return { const ret: TextureFormatInfo = {
requiredFeature: info[0],
sampleType: info[1], sampleType: info[1],
allowedUsages: info[2], allowedUsages: info[2],
blockDimensions: info[3], blockDimensions: info[3],
blockSize: info[4], blockSize: info[4],
components: info[5], components: info[5],
}; };
if (info[0] !== undefined) {
ret.requiredFeature = info[0];
}
return ret;
} }

View File

@ -12,6 +12,10 @@ function textureDimensionArrayLayerCount(
case undefined: case undefined:
case "2d": case "2d":
return normalizeExtent3D(texture.size).depthOrArrayLayers ?? 1; 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", "Cannot normalize Extent3d: width is not defined",
); );
} }
return { const dict: GPUExtent3DDict = {
width: size[0], 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 { } else {
return size; return size;
} }
@ -46,11 +55,14 @@ function extent3DPhysicalSize(
Math.floor(((nSize.height ?? 1) + blockHeight - 1) / blockHeight) * Math.floor(((nSize.height ?? 1) + blockHeight - 1) / blockHeight) *
blockHeight; blockHeight;
return { const dict: GPUExtent3DDict = {
width, width,
height, height,
depthOrArrayLayers: nSize.depthOrArrayLayers,
}; };
if (nSize.depthOrArrayLayers !== undefined) {
dict.depthOrArrayLayers = nSize.depthOrArrayLayers;
}
return dict;
} }
function extent3DMipLevelSize( function extent3DMipLevelSize(

View File

@ -188,7 +188,7 @@ export class LoaderState {
lineStart = 0; lineStart = 0;
position = 0; position = 0;
line = 0; line = 0;
onWarning?: (error: Error) => void; onWarning: ((error: Error) => void) | undefined;
allowDuplicateKeys: boolean; allowDuplicateKeys: boolean;
implicitTypes: Type<"scalar">[]; implicitTypes: Type<"scalar">[];
typeMap: TypeMap; typeMap: TypeMap;
@ -197,9 +197,9 @@ export class LoaderState {
checkLineBreaks = false; checkLineBreaks = false;
tagMap = new Map(); tagMap = new Map();
anchorMap = new Map(); anchorMap = new Map();
tag?: string | null; tag: string | null | undefined;
anchor?: string | null; anchor: string | null | undefined;
kind?: string | null; kind: string | null | undefined;
result: unknown[] | Record<string, unknown> | string | null = ""; result: unknown[] | Record<string, unknown> | string | null = "";
constructor( constructor(

View File

@ -79,7 +79,7 @@ export function parse(
content = sanitizeInput(content); content = sanitizeInput(content);
const state = new LoaderState(content, { const state = new LoaderState(content, {
...options, ...options,
schema: SCHEMA_MAP.get(options.schema!), schema: SCHEMA_MAP.get(options.schema!)!,
}); });
const documentGenerator = state.readDocuments(); const documentGenerator = state.readDocuments();
const document = documentGenerator.next().value; const document = documentGenerator.next().value;
@ -122,7 +122,7 @@ export function parseAll(content: string, options: ParseOptions = {}): unknown {
content = sanitizeInput(content); content = sanitizeInput(content);
const state = new LoaderState(content, { const state = new LoaderState(content, {
...options, ...options,
schema: SCHEMA_MAP.get(options.schema!), schema: SCHEMA_MAP.get(options.schema!)!,
}); });
return [...state.readDocuments()]; return [...state.readDocuments()];
} }

View File

@ -112,7 +112,7 @@ export function stringify(
): string { ): string {
const state = new DumperState({ const state = new DumperState({
...options, ...options,
schema: SCHEMA_MAP.get(options.schema!), schema: SCHEMA_MAP.get(options.schema!)!,
}); });
return state.stringify(data); return state.stringify(data);
} }