summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/_util/std_asserts.ts
diff options
context:
space:
mode:
authorKenta Moriuchi <moriken@kimamass.com>2023-12-08 18:00:03 +0900
committerGitHub <noreply@github.com>2023-12-08 18:00:03 +0900
commitb24356d9b9827062bee35e720b5889a403ae89f3 (patch)
treedcbad198c448550dec1e79c9f26d3f79c4c6ec13 /ext/node/polyfills/_util/std_asserts.ts
parent3a74fa60ca948b0bc1608ae0ad6e00236ccc846a (diff)
fix(ext/node): use primordials in ext/node/polyfills/_util (#21444)
Diffstat (limited to 'ext/node/polyfills/_util/std_asserts.ts')
-rw-r--r--ext/node/polyfills/_util/std_asserts.ts160
1 files changed, 117 insertions, 43 deletions
diff --git a/ext/node/polyfills/_util/std_asserts.ts b/ext/node/polyfills/_util/std_asserts.ts
index 4258a7495..061b0515d 100644
--- a/ext/node/polyfills/_util/std_asserts.ts
+++ b/ext/node/polyfills/_util/std_asserts.ts
@@ -1,15 +1,43 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// vendored from std/assert/mod.ts
-// TODO(petamoriken): enable prefer-primordials for node polyfills
-// deno-lint-ignore-file prefer-primordials
-
+import { primordials } from "ext:core/mod.js";
+import { URLPrototype } from "ext:deno_url/00_url.js";
import { red } from "ext:deno_node/_util/std_fmt_colors.ts";
import {
buildMessage,
diff,
diffstr,
} from "ext:deno_node/_util/std_testing_diff.ts";
+const {
+ DatePrototype,
+ ArrayPrototypeJoin,
+ ArrayPrototypeMap,
+ DatePrototypeGetTime,
+ Error,
+ NumberIsNaN,
+ Object,
+ ObjectIs,
+ ObjectKeys,
+ ObjectPrototypeIsPrototypeOf,
+ ReflectHas,
+ ReflectOwnKeys,
+ RegExpPrototype,
+ RegExpPrototypeTest,
+ SafeMap,
+ SafeRegExp,
+ String,
+ StringPrototypeReplace,
+ StringPrototypeSplit,
+ SymbolIterator,
+ TypeError,
+ WeakMapPrototype,
+ WeakSetPrototype,
+ WeakRefPrototype,
+ WeakRefPrototypeDeref,
+} = primordials;
+
+const FORMAT_PATTERN = new SafeRegExp(/(?=["\\])/g);
/** Converts the input into a string. Objects, Sets and Maps are sorted so as to
* make tests less flaky */
@@ -26,7 +54,7 @@ export function format(v: unknown): string {
// getters should be true in assertEquals.
getters: true,
})
- : `"${String(v).replace(/(?=["\\])/g, "\\")}"`;
+ : `"${StringPrototypeReplace(String(v), FORMAT_PATTERN, "\\")}"`;
}
const CAN_NOT_DISPLAY = "[Cannot display]";
@@ -38,56 +66,75 @@ export class AssertionError extends Error {
}
}
-function isKeyedCollection(x: unknown): x is Set<unknown> {
- return [Symbol.iterator, "size"].every((k) => k in (x as Set<unknown>));
+function isKeyedCollection(
+ x: unknown,
+): x is { size: number; entries(): Iterable<[unknown, unknown]> } {
+ return ReflectHas(x, SymbolIterator) && ReflectHas(x, "size");
}
/** Deep equality comparison used in assertions */
export function equal(c: unknown, d: unknown): boolean {
- const seen = new Map();
+ const seen = new SafeMap();
return (function compare(a: unknown, b: unknown): boolean {
// Have to render RegExp & Date for string comparison
// unless it's mistreated as object
if (
a &&
b &&
- ((a instanceof RegExp && b instanceof RegExp) ||
- (a instanceof URL && b instanceof URL))
+ ((ObjectPrototypeIsPrototypeOf(RegExpPrototype, a) &&
+ ObjectPrototypeIsPrototypeOf(RegExpPrototype, b)) ||
+ (ObjectPrototypeIsPrototypeOf(URLPrototype, a) &&
+ ObjectPrototypeIsPrototypeOf(URLPrototype, b)))
) {
return String(a) === String(b);
}
- if (a instanceof Date && b instanceof Date) {
- const aTime = a.getTime();
- const bTime = b.getTime();
+ if (
+ ObjectPrototypeIsPrototypeOf(DatePrototype, a) &&
+ ObjectPrototypeIsPrototypeOf(DatePrototype, b)
+ ) {
+ const aTime = DatePrototypeGetTime(a);
+ const bTime = DatePrototypeGetTime(b);
// Check for NaN equality manually since NaN is not
// equal to itself.
- if (Number.isNaN(aTime) && Number.isNaN(bTime)) {
+ if (NumberIsNaN(aTime) && NumberIsNaN(bTime)) {
return true;
}
return aTime === bTime;
}
if (typeof a === "number" && typeof b === "number") {
- return Number.isNaN(a) && Number.isNaN(b) || a === b;
+ return NumberIsNaN(a) && NumberIsNaN(b) || a === b;
}
- if (Object.is(a, b)) {
+ if (ObjectIs(a, b)) {
return true;
}
if (a && typeof a === "object" && b && typeof b === "object") {
if (a && b && !constructorsEqual(a, b)) {
return false;
}
- if (a instanceof WeakMap || b instanceof WeakMap) {
- if (!(a instanceof WeakMap && b instanceof WeakMap)) return false;
+ if (
+ ObjectPrototypeIsPrototypeOf(WeakMapPrototype, a) ||
+ ObjectPrototypeIsPrototypeOf(WeakMapPrototype, b)
+ ) {
+ if (
+ !(ObjectPrototypeIsPrototypeOf(WeakMapPrototype, a) &&
+ ObjectPrototypeIsPrototypeOf(WeakMapPrototype, b))
+ ) return false;
throw new TypeError("cannot compare WeakMap instances");
}
- if (a instanceof WeakSet || b instanceof WeakSet) {
- if (!(a instanceof WeakSet && b instanceof WeakSet)) return false;
+ if (
+ ObjectPrototypeIsPrototypeOf(WeakSetPrototype, a) ||
+ ObjectPrototypeIsPrototypeOf(WeakSetPrototype, b)
+ ) {
+ if (
+ !(ObjectPrototypeIsPrototypeOf(WeakSetPrototype, a) &&
+ ObjectPrototypeIsPrototypeOf(WeakSetPrototype, b))
+ ) return false;
throw new TypeError("cannot compare WeakSet instances");
}
if (seen.get(a) === b) {
return true;
}
- if (Object.keys(a || {}).length !== Object.keys(b || {}).length) {
+ if (ObjectKeys(a || {}).length !== ObjectKeys(b || {}).length) {
return false;
}
seen.set(a, b);
@@ -98,7 +145,10 @@ export function equal(c: unknown, d: unknown): boolean {
let unmatchedEntries = a.size;
+ // TODO(petamoriken): use primordials
+ // deno-lint-ignore prefer-primordials
for (const [aKey, aValue] of a.entries()) {
+ // deno-lint-ignore prefer-primordials
for (const [bKey, bValue] of b.entries()) {
/* Given that Map keys can be references, we need
* to ensure that they are also deeply equal */
@@ -111,27 +161,34 @@ export function equal(c: unknown, d: unknown): boolean {
}
}
}
-
return unmatchedEntries === 0;
}
+
const merged = { ...a, ...b };
- for (
- const key of [
- ...Object.getOwnPropertyNames(merged),
- ...Object.getOwnPropertySymbols(merged),
- ]
- ) {
+ const keys = ReflectOwnKeys(merged);
+ for (let i = 0; i < keys.length; ++i) {
+ const key = keys[i];
type Key = keyof typeof merged;
if (!compare(a && a[key as Key], b && b[key as Key])) {
return false;
}
- if (((key in a) && (!(key in b))) || ((key in b) && (!(key in a)))) {
+ if (
+ (ReflectHas(a, key) && !ReflectHas(b, key)) ||
+ (ReflectHas(b, key) && !ReflectHas(a, key))
+ ) {
return false;
}
}
- if (a instanceof WeakRef || b instanceof WeakRef) {
- if (!(a instanceof WeakRef && b instanceof WeakRef)) return false;
- return compare(a.deref(), b.deref());
+
+ if (
+ ObjectPrototypeIsPrototypeOf(WeakRefPrototype, a) ||
+ ObjectPrototypeIsPrototypeOf(WeakRefPrototype, b)
+ ) {
+ if (
+ !(ObjectPrototypeIsPrototypeOf(WeakRefPrototype, a) &&
+ ObjectPrototypeIsPrototypeOf(WeakRefPrototype, b))
+ ) return false;
+ return compare(WeakRefPrototypeDeref(a), WeakRefPrototypeDeref(b));
}
return true;
}
@@ -166,8 +223,14 @@ export function assertEquals<T>(actual: T, expected: T, msg?: string) {
(typeof expected === "string");
const diffResult = stringDiff
? diffstr(actual as string, expected as string)
- : diff(actualString.split("\n"), expectedString.split("\n"));
- const diffMsg = buildMessage(diffResult, { stringDiff }).join("\n");
+ : diff(
+ StringPrototypeSplit(actualString, "\n"),
+ StringPrototypeSplit(expectedString, "\n"),
+ );
+ const diffMsg = ArrayPrototypeJoin(
+ buildMessage(diffResult, { stringDiff }),
+ "\n",
+ );
message = `Values are not equal:\n${diffMsg}`;
} catch {
message = `\n${red(red(CAN_NOT_DISPLAY))} + \n\n`;
@@ -209,7 +272,7 @@ export function assertStrictEquals<T>(
expected: T,
msg?: string,
): asserts actual is T {
- if (Object.is(actual, expected)) {
+ if (ObjectIs(actual, expected)) {
return;
}
@@ -222,10 +285,13 @@ export function assertStrictEquals<T>(
const expectedString = format(expected);
if (actualString === expectedString) {
- const withOffset = actualString
- .split("\n")
- .map((l) => ` ${l}`)
- .join("\n");
+ const withOffset = ArrayPrototypeJoin(
+ ArrayPrototypeMap(
+ StringPrototypeSplit(actualString, "\n"),
+ (l: string) => ` ${l}`,
+ ),
+ "\n",
+ );
message =
`Values have the same structure but are not reference-equal:\n\n${
red(withOffset)
@@ -236,8 +302,14 @@ export function assertStrictEquals<T>(
(typeof expected === "string");
const diffResult = stringDiff
? diffstr(actual as string, expected as string)
- : diff(actualString.split("\n"), expectedString.split("\n"));
- const diffMsg = buildMessage(diffResult, { stringDiff }).join("\n");
+ : diff(
+ StringPrototypeSplit(actualString, "\n"),
+ StringPrototypeSplit(expectedString, "\n"),
+ );
+ const diffMsg = ArrayPrototypeJoin(
+ buildMessage(diffResult, { stringDiff }),
+ "\n",
+ );
message = `Values are not strictly equal:\n${diffMsg}`;
} catch {
message = `\n${CAN_NOT_DISPLAY} + \n\n`;
@@ -255,7 +327,7 @@ export function assertNotStrictEquals<T>(
expected: T,
msg?: string,
) {
- if (!Object.is(actual, expected)) {
+ if (!ObjectIs(actual, expected)) {
return;
}
@@ -268,10 +340,11 @@ export function assertNotStrictEquals<T>(
* then throw. */
export function assertMatch(
actual: string,
+ // deno-lint-ignore prefer-primordials
expected: RegExp,
msg?: string,
) {
- if (!expected.test(actual)) {
+ if (!RegExpPrototypeTest(expected, actual)) {
if (!msg) {
msg = `actual: "${actual}" expected to match: "${expected}"`;
}
@@ -283,10 +356,11 @@ export function assertMatch(
* then throw. */
export function assertNotMatch(
actual: string,
+ // deno-lint-ignore prefer-primordials
expected: RegExp,
msg?: string,
) {
- if (expected.test(actual)) {
+ if (RegExpPrototypeTest(expected, actual)) {
if (!msg) {
msg = `actual: "${actual}" expected to not match: "${expected}"`;
}