summaryrefslogtreecommitdiff
path: root/tests/node_compat/test/parallel/test-util-isDeepStrictEqual.js
diff options
context:
space:
mode:
Diffstat (limited to 'tests/node_compat/test/parallel/test-util-isDeepStrictEqual.js')
-rw-r--r--tests/node_compat/test/parallel/test-util-isDeepStrictEqual.js608
1 files changed, 608 insertions, 0 deletions
diff --git a/tests/node_compat/test/parallel/test-util-isDeepStrictEqual.js b/tests/node_compat/test/parallel/test-util-isDeepStrictEqual.js
new file mode 100644
index 000000000..25caac1f7
--- /dev/null
+++ b/tests/node_compat/test/parallel/test-util-isDeepStrictEqual.js
@@ -0,0 +1,608 @@
+// deno-fmt-ignore-file
+// deno-lint-ignore-file
+
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+// Taken from Node 16.13.0
+// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually
+
+"use strict";
+
+// Confirm functionality of `util.isDeepStrictEqual()`.
+
+require("../common");
+
+const assert = require("assert");
+const util = require("util");
+
+class MyDate extends Date {
+ constructor(...args) {
+ super(...args);
+ this[0] = "1";
+ }
+}
+
+class MyRegExp extends RegExp {
+ constructor(...args) {
+ super(...args);
+ this[0] = "1";
+ }
+}
+
+{
+ const arr = new Uint8Array([120, 121, 122, 10]);
+ const buf = Buffer.from(arr);
+ // They have different [[Prototype]]
+ assert.strictEqual(util.isDeepStrictEqual(arr, buf), false);
+
+ const buf2 = Buffer.from(arr);
+ buf2.prop = 1;
+
+ assert.strictEqual(util.isDeepStrictEqual(buf2, buf), false);
+
+ const arr2 = new Uint8Array([120, 121, 122, 10]);
+ arr2.prop = 5;
+ assert.strictEqual(util.isDeepStrictEqual(arr, arr2), false);
+}
+
+{
+ const date = new Date("2016");
+
+ const date2 = new MyDate("2016");
+
+ // deepStrictEqual checks own properties
+ assert.strictEqual(util.isDeepStrictEqual(date, date2), false);
+ assert.strictEqual(util.isDeepStrictEqual(date2, date), false);
+}
+
+{
+ const re1 = new RegExp("test");
+ const re2 = new MyRegExp("test");
+
+ // deepStrictEqual checks all properties
+ assert.strictEqual(util.isDeepStrictEqual(re1, re2), false);
+}
+
+{
+ // For these cases, deepStrictEqual should throw.
+ const similar = new Set([
+ { 0: "1" }, // Object
+ { 0: 1 }, // Object
+ new String("1"), // Object
+ ["1"], // Array
+ [1], // Array
+ new MyDate("2016"), // Date with this[0] = '1'
+ new MyRegExp("test"), // RegExp with this[0] = '1'
+ new Int8Array([1]), // Int8Array
+ new Uint8Array([1]), // Uint8Array
+ new Int16Array([1]), // Int16Array
+ new Uint16Array([1]), // Uint16Array
+ new Int32Array([1]), // Int32Array
+ new Uint32Array([1]), // Uint32Array
+ Buffer.from([1]), // Buffer
+ ]);
+
+ for (const a of similar) {
+ for (const b of similar) {
+ if (a !== b) {
+ assert.strictEqual(util.isDeepStrictEqual(a, b), false);
+ }
+ }
+ }
+}
+
+function utilIsDeepStrict(a, b) {
+ assert.strictEqual(util.isDeepStrictEqual(a, b), true);
+ assert.strictEqual(util.isDeepStrictEqual(b, a), true);
+}
+function notUtilIsDeepStrict(a, b) {
+ assert.strictEqual(util.isDeepStrictEqual(a, b), false);
+ assert.strictEqual(util.isDeepStrictEqual(b, a), false);
+}
+
+// es6 Maps and Sets
+utilIsDeepStrict(new Set(), new Set());
+utilIsDeepStrict(new Map(), new Map());
+
+utilIsDeepStrict(new Set([1, 2, 3]), new Set([1, 2, 3]));
+notUtilIsDeepStrict(new Set([1, 2, 3]), new Set([1, 2, 3, 4]));
+notUtilIsDeepStrict(new Set([1, 2, 3, 4]), new Set([1, 2, 3]));
+utilIsDeepStrict(new Set(["1", "2", "3"]), new Set(["1", "2", "3"]));
+utilIsDeepStrict(
+ new Set([
+ [1, 2],
+ [3, 4],
+ ]),
+ new Set([
+ [3, 4],
+ [1, 2],
+ ])
+);
+
+{
+ const a = [1, 2];
+ const b = [3, 4];
+ const c = [1, 2];
+ const d = [3, 4];
+
+ utilIsDeepStrict(
+ { a: a, b: b, s: new Set([a, b]) },
+ { a: c, b: d, s: new Set([d, c]) }
+ );
+}
+
+utilIsDeepStrict(
+ new Map([
+ [1, 1],
+ [2, 2],
+ ]),
+ new Map([
+ [1, 1],
+ [2, 2],
+ ])
+);
+utilIsDeepStrict(
+ new Map([
+ [1, 1],
+ [2, 2],
+ ]),
+ new Map([
+ [2, 2],
+ [1, 1],
+ ])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [1, 1],
+ [2, 2],
+ ]),
+ new Map([
+ [1, 2],
+ [2, 1],
+ ])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [[1], 1],
+ [{}, 2],
+ ]),
+ new Map([
+ [[1], 2],
+ [{}, 1],
+ ])
+);
+
+notUtilIsDeepStrict(new Set([1]), [1]);
+notUtilIsDeepStrict(new Set(), []);
+notUtilIsDeepStrict(new Set(), {});
+
+notUtilIsDeepStrict(new Map([["a", 1]]), { a: 1 });
+notUtilIsDeepStrict(new Map(), []);
+notUtilIsDeepStrict(new Map(), {});
+
+notUtilIsDeepStrict(new Set(["1"]), new Set([1]));
+
+notUtilIsDeepStrict(new Map([["1", "a"]]), new Map([[1, "a"]]));
+notUtilIsDeepStrict(new Map([["a", "1"]]), new Map([["a", 1]]));
+notUtilIsDeepStrict(new Map([["a", "1"]]), new Map([["a", 2]]));
+
+utilIsDeepStrict(new Set([{}]), new Set([{}]));
+
+// Ref: https://github.com/nodejs/node/issues/13347
+notUtilIsDeepStrict(
+ new Set([{ a: 1 }, { a: 1 }]),
+ new Set([{ a: 1 }, { a: 2 }])
+);
+notUtilIsDeepStrict(
+ new Set([{ a: 1 }, { a: 1 }, { a: 2 }]),
+ new Set([{ a: 1 }, { a: 2 }, { a: 2 }])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [{ x: 1 }, 5],
+ [{ x: 1 }, 5],
+ ]),
+ new Map([
+ [{ x: 1 }, 5],
+ [{ x: 2 }, 5],
+ ])
+);
+
+notUtilIsDeepStrict(new Set([3, "3"]), new Set([3, 4]));
+notUtilIsDeepStrict(
+ new Map([
+ [3, 0],
+ ["3", 0],
+ ]),
+ new Map([
+ [3, 0],
+ [4, 0],
+ ])
+);
+
+notUtilIsDeepStrict(
+ new Set([{ a: 1 }, { a: 1 }, { a: 2 }]),
+ new Set([{ a: 1 }, { a: 2 }, { a: 2 }])
+);
+
+// Mixed primitive and object keys
+utilIsDeepStrict(
+ new Map([
+ [1, "a"],
+ [{}, "a"],
+ ]),
+ new Map([
+ [1, "a"],
+ [{}, "a"],
+ ])
+);
+utilIsDeepStrict(new Set([1, "a", [{}, "a"]]), new Set([1, "a", [{}, "a"]]));
+
+// This is an awful case, where a map contains multiple equivalent keys:
+notUtilIsDeepStrict(
+ new Map([
+ [1, "a"],
+ ["1", "b"],
+ ]),
+ new Map([
+ ["1", "a"],
+ [true, "b"],
+ ])
+);
+notUtilIsDeepStrict(new Set(["a"]), new Set(["b"]));
+utilIsDeepStrict(
+ new Map([
+ [{}, "a"],
+ [{}, "b"],
+ ]),
+ new Map([
+ [{}, "b"],
+ [{}, "a"],
+ ])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [true, "a"],
+ ["1", "b"],
+ [1, "a"],
+ ]),
+ new Map([
+ ["1", "a"],
+ [1, "b"],
+ [true, "a"],
+ ])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [true, "a"],
+ ["1", "b"],
+ [1, "c"],
+ ]),
+ new Map([
+ ["1", "a"],
+ [1, "b"],
+ [true, "a"],
+ ])
+);
+
+// Similar object keys
+notUtilIsDeepStrict(new Set([{}, {}]), new Set([{}, 1]));
+notUtilIsDeepStrict(
+ new Set([
+ [{}, 1],
+ [{}, 1],
+ ]),
+ new Set([
+ [{}, 1],
+ [1, 1],
+ ])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [{}, 1],
+ [{}, 1],
+ ]),
+ new Map([
+ [{}, 1],
+ [1, 1],
+ ])
+);
+notUtilIsDeepStrict(
+ new Map([
+ [{}, 1],
+ [true, 1],
+ ]),
+ new Map([
+ [{}, 1],
+ [1, 1],
+ ])
+);
+
+// Similar primitive key / values
+notUtilIsDeepStrict(new Set([1, true, false]), new Set(["1", 0, "0"]));
+notUtilIsDeepStrict(
+ new Map([
+ [1, 5],
+ [true, 5],
+ [false, 5],
+ ]),
+ new Map([
+ ["1", 5],
+ [0, 5],
+ ["0", 5],
+ ])
+);
+
+// Undefined value in Map
+utilIsDeepStrict(new Map([[1, undefined]]), new Map([[1, undefined]]));
+notUtilIsDeepStrict(new Map([[1, null]]), new Map([["1", undefined]]));
+notUtilIsDeepStrict(new Map([[1, undefined]]), new Map([[2, undefined]]));
+
+// null as key
+utilIsDeepStrict(new Map([[null, 3]]), new Map([[null, 3]]));
+notUtilIsDeepStrict(new Map([[null, undefined]]), new Map([[undefined, null]]));
+notUtilIsDeepStrict(new Set([null]), new Set([undefined]));
+
+// GH-6416. Make sure circular refs don't throw.
+{
+ const b = {};
+ b.b = b;
+ const c = {};
+ c.b = c;
+
+ utilIsDeepStrict(b, c);
+
+ const d = {};
+ d.a = 1;
+ d.b = d;
+ const e = {};
+ e.a = 1;
+ e.b = {};
+
+ notUtilIsDeepStrict(d, e);
+}
+
+// GH-14441. Circular structures should be consistent
+{
+ const a = {};
+ const b = {};
+ a.a = a;
+ b.a = {};
+ b.a.a = a;
+ utilIsDeepStrict(a, b);
+}
+
+{
+ const a = new Set();
+ const b = new Set();
+ const c = new Set();
+ a.add(a);
+ b.add(b);
+ c.add(a);
+ utilIsDeepStrict(b, c);
+}
+
+// GH-7178. Ensure reflexivity of deepEqual with `arguments` objects.
+{
+ const args = (function () {
+ return arguments;
+ })();
+ notUtilIsDeepStrict([], args);
+}
+
+// More checking that arguments objects are handled correctly
+{
+ // eslint-disable-next-line func-style
+ const returnArguments = function () {
+ return arguments;
+ };
+
+ const someArgs = returnArguments("a");
+ const sameArgs = returnArguments("a");
+ const diffArgs = returnArguments("b");
+
+ notUtilIsDeepStrict(someArgs, ["a"]);
+ notUtilIsDeepStrict(someArgs, { 0: "a" });
+ notUtilIsDeepStrict(someArgs, diffArgs);
+ utilIsDeepStrict(someArgs, sameArgs);
+}
+
+{
+ const values = [
+ 123,
+ Infinity,
+ 0,
+ null,
+ undefined,
+ false,
+ true,
+ {},
+ [],
+ () => {},
+ ];
+ utilIsDeepStrict(new Set(values), new Set(values));
+ utilIsDeepStrict(new Set(values), new Set(values.reverse()));
+
+ const mapValues = values.map((v) => [v, { a: 5 }]);
+ utilIsDeepStrict(new Map(mapValues), new Map(mapValues));
+ utilIsDeepStrict(new Map(mapValues), new Map(mapValues.reverse()));
+}
+
+{
+ const s1 = new Set();
+ const s2 = new Set();
+ s1.add(1);
+ s1.add(2);
+ s2.add(2);
+ s2.add(1);
+ utilIsDeepStrict(s1, s2);
+}
+
+{
+ const m1 = new Map();
+ const m2 = new Map();
+ const obj = { a: 5, b: 6 };
+ m1.set(1, obj);
+ m1.set(2, "hi");
+ m1.set(3, [1, 2, 3]);
+
+ m2.set(2, "hi"); // different order
+ m2.set(1, obj);
+ m2.set(3, [1, 2, 3]); // Deep equal, but not reference equal.
+
+ utilIsDeepStrict(m1, m2);
+}
+
+{
+ const m1 = new Map();
+ const m2 = new Map();
+
+ // m1 contains itself.
+ m1.set(1, m1);
+ m2.set(1, new Map());
+
+ notUtilIsDeepStrict(m1, m2);
+}
+
+{
+ const map1 = new Map([[1, 1]]);
+ const map2 = new Map([[1, "1"]]);
+ assert.strictEqual(util.isDeepStrictEqual(map1, map2), false);
+}
+
+{
+ // Two equivalent sets / maps with different key/values applied shouldn't be
+ // the same. This is a terrible idea to do in practice, but deepEqual should
+ // still check for it.
+ const s1 = new Set();
+ const s2 = new Set();
+ s1.x = 5;
+ notUtilIsDeepStrict(s1, s2);
+
+ const m1 = new Map();
+ const m2 = new Map();
+ m1.x = 5;
+ notUtilIsDeepStrict(m1, m2);
+}
+
+{
+ // Circular references.
+ const s1 = new Set();
+ s1.add(s1);
+ const s2 = new Set();
+ s2.add(s2);
+ utilIsDeepStrict(s1, s2);
+
+ const m1 = new Map();
+ m1.set(2, m1);
+ const m2 = new Map();
+ m2.set(2, m2);
+ utilIsDeepStrict(m1, m2);
+
+ const m3 = new Map();
+ m3.set(m3, 2);
+ const m4 = new Map();
+ m4.set(m4, 2);
+ utilIsDeepStrict(m3, m4);
+}
+
+// Handle sparse arrays
+utilIsDeepStrict([1, , , 3], [1, , , 3]);
+notUtilIsDeepStrict([1, , , 3], [1, , , 3, , ,]);
+
+// Handle different error messages
+{
+ const err1 = new Error("foo1");
+ const err2 = new Error("foo2");
+ const err3 = new TypeError("foo1");
+ notUtilIsDeepStrict(err1, err2, assert.AssertionError);
+ notUtilIsDeepStrict(err1, err3, assert.AssertionError);
+ notUtilIsDeepStrict(err1, {}, assert.AssertionError);
+}
+
+// Handle NaN
+assert.strictEqual(util.isDeepStrictEqual(NaN, NaN), true);
+assert.strictEqual(util.isDeepStrictEqual({ a: NaN }, { a: NaN }), true);
+assert.strictEqual(
+ util.isDeepStrictEqual([1, 2, NaN, 4], [1, 2, NaN, 4]),
+ true
+);
+
+// Handle boxed primitives
+{
+ const boxedString = new String("test");
+ const boxedSymbol = Object(Symbol());
+ notUtilIsDeepStrict(new Boolean(true), Object(false));
+ notUtilIsDeepStrict(Object(true), new Number(1));
+ notUtilIsDeepStrict(new Number(2), new Number(1));
+ notUtilIsDeepStrict(boxedSymbol, Object(Symbol()));
+ notUtilIsDeepStrict(boxedSymbol, {});
+ utilIsDeepStrict(boxedSymbol, boxedSymbol);
+ utilIsDeepStrict(Object(true), Object(true));
+ utilIsDeepStrict(Object(2), Object(2));
+ utilIsDeepStrict(boxedString, Object("test"));
+ boxedString.slow = true;
+ notUtilIsDeepStrict(boxedString, Object("test"));
+ boxedSymbol.slow = true;
+ notUtilIsDeepStrict(boxedSymbol, {});
+ utilIsDeepStrict(Object(BigInt(1)), Object(BigInt(1)));
+ notUtilIsDeepStrict(Object(BigInt(1)), Object(BigInt(2)));
+
+ const booleanish = new Boolean(true);
+ Object.defineProperty(booleanish, Symbol.toStringTag, { value: "String" });
+ Object.setPrototypeOf(booleanish, String.prototype);
+ notUtilIsDeepStrict(booleanish, new String("true"));
+
+ const numberish = new Number(42);
+ Object.defineProperty(numberish, Symbol.toStringTag, { value: "String" });
+ Object.setPrototypeOf(numberish, String.prototype);
+ notUtilIsDeepStrict(numberish, new String("42"));
+
+ const stringish = new String("0");
+ Object.defineProperty(stringish, Symbol.toStringTag, { value: "Number" });
+ Object.setPrototypeOf(stringish, Number.prototype);
+ notUtilIsDeepStrict(stringish, new Number(0));
+
+ const bigintish = new Object(BigInt(42));
+ Object.defineProperty(bigintish, Symbol.toStringTag, { value: "String" });
+ Object.setPrototypeOf(bigintish, String.prototype);
+ notUtilIsDeepStrict(bigintish, new String("42"));
+
+ const symbolish = new Object(Symbol("fhqwhgads"));
+ Object.defineProperty(symbolish, Symbol.toStringTag, { value: "String" });
+ Object.setPrototypeOf(symbolish, String.prototype);
+ notUtilIsDeepStrict(symbolish, new String("fhqwhgads"));
+}
+
+// Minus zero
+notUtilIsDeepStrict(0, -0);
+utilIsDeepStrict(-0, -0);
+
+// Handle symbols (enumerable only)
+{
+ const symbol1 = Symbol();
+ const obj1 = { [symbol1]: 1 };
+ const obj2 = { [symbol1]: 1 };
+ const obj3 = { [Symbol()]: 1 };
+ const obj4 = {};
+ // Add a non enumerable symbol as well. It is going to be ignored!
+ Object.defineProperty(obj2, Symbol(), { value: 1 });
+ Object.defineProperty(obj4, symbol1, { value: 1 });
+ notUtilIsDeepStrict(obj1, obj3);
+ utilIsDeepStrict(obj1, obj2);
+ notUtilIsDeepStrict(obj1, obj4);
+ // TypedArrays have a fast path. Test for this as well.
+ const a = new Uint8Array(4);
+ const b = new Uint8Array(4);
+ a[symbol1] = true;
+ b[symbol1] = false;
+ notUtilIsDeepStrict(a, b);
+ b[symbol1] = true;
+ utilIsDeepStrict(a, b);
+ // The same as TypedArrays is valid for boxed primitives
+ const boxedStringA = new String("test");
+ const boxedStringB = new String("test");
+ boxedStringA[symbol1] = true;
+ notUtilIsDeepStrict(boxedStringA, boxedStringB);
+ boxedStringA[symbol1] = true;
+ utilIsDeepStrict(a, b);
+}