From 3b949c2bb26173e13962645ce4ad4e00faadfe42 Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Mon, 9 Dec 2024 14:06:08 +0800 Subject: [PATCH 1/2] Use relative paths within std instead of @std Fixes error `Relative import path "@std/internal/build-message" not prefixed with / or ./ or ../ and not in import map` when using the repo with file:/// import from 3rd party code --- assert/almost_equals_test.ts | 2 +- assert/array_includes.ts | 2 +- assert/equals.ts | 8 ++++---- assert/greater.ts | 2 +- assert/greater_or_equal.ts | 2 +- assert/is_error.ts | 2 +- assert/less.ts | 2 +- assert/less_or_equal.ts | 2 +- assert/not_strict_equals.ts | 2 +- assert/strict_equals.ts | 10 +++++----- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/assert/almost_equals_test.ts b/assert/almost_equals_test.ts index 3989c94d25f7..6d314055322b 100644 --- a/assert/almost_equals_test.ts +++ b/assert/almost_equals_test.ts @@ -37,7 +37,7 @@ Deno.test("assertAlmostEquals() throws values outside higher precision range", ( ); }); -Deno.test("assertAlmostEquals() matches infinity with inifinity", () => { +Deno.test("assertAlmostEquals() matches infinity with infinity", () => { assertAlmostEquals(Infinity, Infinity); }); diff --git a/assert/array_includes.ts b/assert/array_includes.ts index bcddd540ac05..177150cc1768 100644 --- a/assert/array_includes.ts +++ b/assert/array_includes.ts @@ -1,7 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. import { equal } from "./equal.ts"; -import { format } from "@std/internal/format"; +import { format } from "../internal/format.ts"; import { AssertionError } from "./assertion_error.ts"; /** An array-like object (`Array`, `Uint8Array`, `NodeList`, etc.) that is not a string */ diff --git a/assert/equals.ts b/assert/equals.ts index d7ee8c0f6868..29dbb98d18eb 100644 --- a/assert/equals.ts +++ b/assert/equals.ts @@ -1,10 +1,10 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. import { equal } from "./equal.ts"; -import { buildMessage } from "@std/internal/build-message"; -import { diff } from "@std/internal/diff"; -import { diffStr } from "@std/internal/diff-str"; -import { format } from "@std/internal/format"; +import { buildMessage } from "../internal/build_message.ts"; +import { diff } from "../internal/diff.ts"; +import { diffStr } from "../internal/diff_str.ts"; +import { format } from "../internal/format.ts"; import { AssertionError } from "./assertion_error.ts"; diff --git a/assert/greater.ts b/assert/greater.ts index 7b19e717101a..41738156a117 100644 --- a/assert/greater.ts +++ b/assert/greater.ts @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. -import { format } from "@std/internal/format"; +import { format } from "../internal/format.ts"; import { AssertionError } from "./assertion_error.ts"; /** diff --git a/assert/greater_or_equal.ts b/assert/greater_or_equal.ts index 22a6260649a9..65fc338fe9c6 100644 --- a/assert/greater_or_equal.ts +++ b/assert/greater_or_equal.ts @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. -import { format } from "@std/internal/format"; +import { format } from "../internal/format.ts"; import { AssertionError } from "./assertion_error.ts"; /** diff --git a/assert/is_error.ts b/assert/is_error.ts index 8f06aac4a00c..be3383bcda08 100644 --- a/assert/is_error.ts +++ b/assert/is_error.ts @@ -1,7 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. import { AssertionError } from "./assertion_error.ts"; -import { stripAnsiCode } from "@std/internal/styles"; +import { stripAnsiCode } from "../internal/styles.ts"; /** * Make an assertion that `error` is an `Error`. diff --git a/assert/less.ts b/assert/less.ts index 872758b8b92d..2d952cf7087e 100644 --- a/assert/less.ts +++ b/assert/less.ts @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. -import { format } from "@std/internal/format"; +import { format } from "../internal/format.ts"; import { AssertionError } from "./assertion_error.ts"; /** diff --git a/assert/less_or_equal.ts b/assert/less_or_equal.ts index 3c07e94ebeaf..308e32498a2f 100644 --- a/assert/less_or_equal.ts +++ b/assert/less_or_equal.ts @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. -import { format } from "@std/internal/format"; +import { format } from "../internal/format.ts"; import { AssertionError } from "./assertion_error.ts"; /** diff --git a/assert/not_strict_equals.ts b/assert/not_strict_equals.ts index e29beef4d9a1..d7d84d9047fd 100644 --- a/assert/not_strict_equals.ts +++ b/assert/not_strict_equals.ts @@ -1,7 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. import { AssertionError } from "./assertion_error.ts"; -import { format } from "@std/internal/format"; +import { format } from "../internal/format.ts"; /** * Make an assertion that `actual` and `expected` are not strictly equal, using diff --git a/assert/strict_equals.ts b/assert/strict_equals.ts index c43876013e2b..9027eeeb354c 100644 --- a/assert/strict_equals.ts +++ b/assert/strict_equals.ts @@ -1,10 +1,10 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // This module is browser compatible. -import { buildMessage } from "@std/internal/build-message"; -import { diff } from "@std/internal/diff"; -import { diffStr } from "@std/internal/diff-str"; -import { format } from "@std/internal/format"; -import { red } from "@std/internal/styles"; +import { buildMessage } from "../internal/build_message.ts"; +import { diff } from "../internal/diff.ts"; +import { diffStr } from "../internal/diff_str.ts"; +import { format } from "../internal/format.ts"; +import { red } from "../internal/styles.ts"; import { AssertionError } from "./assertion_error.ts"; /** From 80d9af5978a2ca363472ac23d1864008746dea4e Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Mon, 9 Dec 2024 14:09:22 +0800 Subject: [PATCH 2/2] Stricter typing for assertLess, assertLessOrEqual, asserGreater, assertGreaterOrEqual - disallow undefined actual values because any comparison with undefined returns false - disallow null expected values - narrow the returned type to exclude undefined --- assert/greater.ts | 9 +++++++-- assert/greater_or_equal.ts | 9 +++++---- assert/greater_or_equal_test.ts | 30 +++++++++++++++++++++++++++++ assert/greater_test.ts | 29 ++++++++++++++++++++++++++++ assert/less.ts | 9 +++++++-- assert/less_or_equal.ts | 9 +++++---- assert/less_or_equal_test.ts | 34 +++++++++++++++++++++++++++++++-- assert/less_test.ts | 29 ++++++++++++++++++++++++++++ 8 files changed, 144 insertions(+), 14 deletions(-) diff --git a/assert/greater.ts b/assert/greater.ts index 41738156a117..965b2b5f9281 100644 --- a/assert/greater.ts +++ b/assert/greater.ts @@ -21,8 +21,13 @@ import { AssertionError } from "./assertion_error.ts"; * @param expected The expected value to compare. * @param msg The optional message to display if the assertion fails. */ -export function assertGreater(actual: T, expected: T, msg?: string) { - if (actual > expected) return; +export function assertGreater( + actual: Exclude | null, + expected: NonNullable, + msg?: string, +): asserts actual is Exclude | null { + // Coerce null to 0 to avoid "Object is possibly null" + if ((actual ?? 0) > expected) return; const actualString = format(actual); const expectedString = format(expected); diff --git a/assert/greater_or_equal.ts b/assert/greater_or_equal.ts index 65fc338fe9c6..1d454f885b86 100644 --- a/assert/greater_or_equal.ts +++ b/assert/greater_or_equal.ts @@ -22,11 +22,12 @@ import { AssertionError } from "./assertion_error.ts"; * @param msg The optional message to display if the assertion fails. */ export function assertGreaterOrEqual( - actual: T, - expected: T, + actual: Exclude | null, + expected: NonNullable, msg?: string, -) { - if (actual >= expected) return; +): asserts actual is Exclude | null { + // Coerce null to 0 to avoid "Object is possibly null" + if ((actual ?? 0) >= expected) return; const actualString = format(actual); const expectedString = format(expected); diff --git a/assert/greater_or_equal_test.ts b/assert/greater_or_equal_test.ts index 2a7040fc0f80..507e7dc07fdb 100644 --- a/assert/greater_or_equal_test.ts +++ b/assert/greater_or_equal_test.ts @@ -1,11 +1,41 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assertGreaterOrEqual, assertThrows } from "./mod.ts"; +import { assertType, type IsExact } from "../testing/types.ts"; Deno.test("assertGreaterOrEqual() matches when actual value is greater or equal than expected value", () => { assertGreaterOrEqual(2, 1); assertGreaterOrEqual(1n, 1n); + assertGreaterOrEqual(1.1, 1); + assertGreaterOrEqual(null, 0); // coerced to 0 }); Deno.test("assertGreaterOrEqual() throws when actual value is smaller than expected value", () => { assertThrows(() => assertGreaterOrEqual(1, 2)); + assertThrows(() => assertGreaterOrEqual(null, 1)); + + // Compile-time errors + // assertThrows(() => assertGreater(undefined, 1)); + // assertThrows(() => assertGreater(0, null)); +}); + +Deno.test("assertGreaterOrEqual() on strings", () => { + // Strings + assertGreaterOrEqual("", ""); + assertThrows(() => assertGreaterOrEqual("", "a")); + assertThrows(() => assertGreaterOrEqual(null, "a")); +}); + +Deno.test("assertGreater type narrowing", () => { + const n = 0 as number | undefined; + // @ts-expect-error -- `undefined` not allowed for n; disable to see compile-time error below + assertGreaterOrEqual(n, 0); // `undefined` narrowed out + assertType>(true); + const s = "" as string | undefined; + // @ts-expect-error -- `undefined` not allowed for s + assertGreaterOrEqual(s, ""); // `undefined` narrowed out + assertType>(true); + const b = false as boolean | undefined; + // @ts-expect-error -- `undefined` not allowed for b + assertGreaterOrEqual(b, false); // `undefined` narrowed out + assertType>(true); }); diff --git a/assert/greater_test.ts b/assert/greater_test.ts index f8350ef33958..e4fdd3a9ab79 100644 --- a/assert/greater_test.ts +++ b/assert/greater_test.ts @@ -1,12 +1,41 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assertGreater, assertThrows } from "./mod.ts"; +import { assertType, type IsExact } from "../testing/types.ts"; Deno.test("assertGreaterOrEqual() matches when actual value is greater than expected value", () => { assertGreater(2, 1); assertGreater(2n, 1n); assertGreater(1.1, 1); + assertGreater(null, -1); // coerced to 0 }); Deno.test("assertGreaterOrEqual() throws when actual value is smaller or equal than expected value", () => { assertThrows(() => assertGreater(1, 2)); + assertThrows(() => assertGreater(null, 0)); + + // Compile-time errors + // assertThrows(() => assertGreater(undefined, 1)); + // assertThrows(() => assertGreater(0, null)); +}); + +Deno.test("assertGreater() on strings", () => { + // Strings + assertGreater("b", "a"); + assertThrows(() => assertGreater("", "a")); + assertThrows(() => assertGreater(null, "a")); +}); + +Deno.test("assertGreater type narrowing", () => { + const n = 0 as number | undefined; + // @ts-expect-error -- `undefined` not allowed for n; disable to see compile-time error below + assertGreater(n, -1); // `undefined` narrowed out + assertType>(true); + const s = "a" as string | undefined; + // @ts-expect-error -- `undefined` not allowed for s + assertGreater(s, ""); // `undefined` narrowed out + assertType>(true); + const b = true as boolean | undefined; + // @ts-expect-error -- `undefined` not allowed for b + assertGreater(b, false); // `undefined` narrowed out + assertType>(true); }); diff --git a/assert/less.ts b/assert/less.ts index 2d952cf7087e..1e5c71ed5135 100644 --- a/assert/less.ts +++ b/assert/less.ts @@ -20,8 +20,13 @@ import { AssertionError } from "./assertion_error.ts"; * @param expected The expected value to compare. * @param msg The optional message to display if the assertion fails. */ -export function assertLess(actual: T, expected: T, msg?: string) { - if (actual < expected) return; +export function assertLess( + actual: Exclude | null, + expected: NonNullable, + msg?: string, +): asserts actual is Exclude | null { + // Coerce null to 0 to avoid "Object is possibly null" + if ((actual ?? 0) < expected) return; const actualString = format(actual); const expectedString = format(expected); diff --git a/assert/less_or_equal.ts b/assert/less_or_equal.ts index 308e32498a2f..e1496fd1663e 100644 --- a/assert/less_or_equal.ts +++ b/assert/less_or_equal.ts @@ -22,11 +22,12 @@ import { AssertionError } from "./assertion_error.ts"; * @param msg The optional message to display if the assertion fails. */ export function assertLessOrEqual( - actual: T, - expected: T, + actual: Exclude | null, + expected: NonNullable, msg?: string, -) { - if (actual <= expected) return; +): asserts actual is Exclude | null { + // Coerce null to 0 to avoid "Object is possibly null" + if ((actual ?? 0) <= expected) return; const actualString = format(actual); const expectedString = format(expected); diff --git a/assert/less_or_equal_test.ts b/assert/less_or_equal_test.ts index c69b42ca1676..4c716fb6158c 100644 --- a/assert/less_or_equal_test.ts +++ b/assert/less_or_equal_test.ts @@ -1,9 +1,39 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assertLessOrEqual, assertThrows } from "./mod.ts"; +import { assertType, type IsExact } from "../testing/types.ts"; -Deno.test("assertLessOrEqual", () => { +Deno.test("assertLessOrEqualOrEqual", () => { + // Numbers assertLessOrEqual(1, 2); - assertLessOrEqual(1n, 1n); + assertLessOrEqual(1n, 2n); + assertLessOrEqual(1, 1.1); + assertLessOrEqual(null, 1); // coerced to 0 + // Failures assertThrows(() => assertLessOrEqual(2, 1)); + assertThrows(() => assertLessOrEqual(null, -1)); + + // Compile-time errors + // assertThrows(() => assertLessOrEqual(undefined, 1)); + // assertThrows(() => assertLessOrEqual(0, null)); + + // Strings + assertLessOrEqual("a", "a"); + assertThrows(() => assertLessOrEqual("a", "")); + assertThrows(() => assertLessOrEqual(null, "a")); +}); + +Deno.test("assertLessOrEqualOrEqual() type narrowing", () => { + const n = 0 as number | undefined; + // @ts-expect-error -- `undefined` not allowed for n + assertLessOrEqual(n, 0); // `undefined` narrowed out + assertType>(true); + const s = "" as string | undefined; + // @ts-expect-error -- `undefined` not allowed for s + assertLessOrEqual(s, ""); // `undefined` narrowed out + assertType>(true); + const b = false as boolean | undefined; + // @ts-expect-error -- `undefined` not allowed for b + assertLessOrEqual(b, false); // `undefined` narrowed out + assertType>(true); }); diff --git a/assert/less_test.ts b/assert/less_test.ts index 48b79a22c3f6..cf78a1fc3a2d 100644 --- a/assert/less_test.ts +++ b/assert/less_test.ts @@ -1,10 +1,39 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { assertLess, assertThrows } from "./mod.ts"; +import { assertType, type IsExact } from "../testing/types.ts"; Deno.test("assertLess", () => { + // Numbers assertLess(1, 2); assertLess(1n, 2n); assertLess(1, 1.1); + assertLess(null, 1); // coerced to 0 + // Failures assertThrows(() => assertLess(2, 1)); + assertThrows(() => assertLess(null, -1)); + + // Compile-time errors + // assertThrows(() => assertLess(undefined, 1)); + // assertThrows(() => assertLess(-1, null)); + + // Strings + assertLess("a", "b"); + assertThrows(() => assertLess("a", "")); + assertThrows(() => assertLess(null, "a")); +}); + +Deno.test("assertLess() type narrowing", () => { + const n = 0 as number | undefined; + // @ts-expect-error -- `undefined` not allowed for n; disable to see compile-time error below + assertLess(n, 1); // `undefined` narrowed out + assertType>(true); + const s = "" as string | undefined; + // @ts-expect-error -- `undefined` not allowed for s + assertLess(s, "a"); // `undefined` narrowed out + assertType>(true); + const b = false as boolean | undefined; + // @ts-expect-error -- `undefined` not allowed for b + assertLess(b, true); // `undefined` narrowed out + assertType>(true); });