| // Copyright 2017 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Stripped-down version of test/mjsunit/mjsunit.js that only contains |
| // assertEquals.S |
| var assertEquals; |
| |
| (function () { |
| var ObjectPrototypeToString = Object.prototype.toString; |
| var NumberPrototypeValueOf = Number.prototype.valueOf; |
| var BooleanPrototypeValueOf = Boolean.prototype.valueOf; |
| var StringPrototypeValueOf = String.prototype.valueOf; |
| var DatePrototypeValueOf = Date.prototype.valueOf; |
| var RegExpPrototypeToString = RegExp.prototype.toString; |
| var ArrayPrototypeForEach = Array.prototype.forEach; |
| var ArrayPrototypeJoin = Array.prototype.join; |
| var ArrayPrototypeMap = Array.prototype.map; |
| var ArrayPrototypePush = Array.prototype.push; |
| |
| var BigIntPrototypeValueOf; |
| try { |
| BigIntPrototypeValueOf = BigInt.prototype.valueOf; |
| } catch(e) {} |
| |
| function classOf(object) { |
| var string = ObjectPrototypeToString.call(object); |
| return string.substring(8, string.length - 1); |
| } |
| |
| function ValueOf(value) { |
| switch (classOf(value)) { |
| case "Number": |
| return NumberPrototypeValueOf.call(value); |
| case "BigInt": |
| return BigIntPrototypeValueOf.call(value); |
| case "String": |
| return StringPrototypeValueOf.call(value); |
| case "Boolean": |
| return BooleanPrototypeValueOf.call(value); |
| case "Date": |
| return DatePrototypeValueOf.call(value); |
| default: |
| return value; |
| } |
| } |
| |
| |
| function PrettyPrint(value) { |
| switch (typeof value) { |
| case "string": |
| return JSON.stringify(value); |
| case "bigint": |
| return String(value) + "n"; |
| case "number": |
| if (value === 0 && (1 / value) < 0) return "-0"; |
| // FALLTHROUGH. |
| case "boolean": |
| case "undefined": |
| case "function": |
| case "symbol": |
| return String(value); |
| case "object": |
| if (value === null) return "null"; |
| var objectClass = classOf(value); |
| switch (objectClass) { |
| case "Number": |
| case "BigInt": |
| case "String": |
| case "Boolean": |
| case "Date": |
| return objectClass + "(" + PrettyPrint(ValueOf(value)) + ")"; |
| case "RegExp": |
| return RegExpPrototypeToString.call(value); |
| case "Array": |
| var mapped = ArrayPrototypeMap.call(value, PrettyPrintArrayElement); |
| var joined = ArrayPrototypeJoin.call(mapped, ","); |
| return "[" + joined + "]"; |
| case "Uint8Array": |
| case "Int8Array": |
| case "Int16Array": |
| case "Uint16Array": |
| case "Uint32Array": |
| case "Int32Array": |
| case "Float32Array": |
| case "Float64Array": |
| var joined = ArrayPrototypeJoin.call(value, ","); |
| return objectClass + "([" + joined + "])"; |
| case "Object": |
| break; |
| default: |
| return objectClass + "()"; |
| } |
| var name = value.constructor.name; |
| if (name) return name + "()"; |
| return "Object()"; |
| default: |
| return "-- unknown value --"; |
| } |
| } |
| |
| function PrettyPrintArrayElement(value, index, array) { |
| if (value === undefined && !(index in array)) return ""; |
| return PrettyPrint(value); |
| } |
| |
| failWithMessage = function failWithMessage(message) { |
| throw new Error(message); |
| } |
| |
| function formatFailureText(expectedText, found, name_opt) { |
| var message = "Fail" + "ure"; |
| if (name_opt) { |
| message += " (" + name_opt + ")"; |
| } |
| |
| var foundText = PrettyPrint(found); |
| if (expectedText.length <= 40 && foundText.length <= 40) { |
| message += ": expected <" + expectedText + "> found <" + foundText + ">"; |
| } else { |
| message += ":\nexpected:\n" + expectedText + "\nfound:\n" + foundText; |
| } |
| return message; |
| } |
| |
| function fail(expectedText, found, name_opt) { |
| return failWithMessage(formatFailureText(expectedText, found, name_opt)); |
| } |
| |
| function deepObjectEquals(a, b) { |
| var aProps = Object.keys(a); |
| aProps.sort(); |
| var bProps = Object.keys(b); |
| bProps.sort(); |
| if (!deepEquals(aProps, bProps)) { |
| return false; |
| } |
| for (var i = 0; i < aProps.length; i++) { |
| if (!deepEquals(a[aProps[i]], b[aProps[i]])) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| function deepEquals(a, b) { |
| if (a === b) { |
| // Check for -0. |
| if (a === 0) return (1 / a) === (1 / b); |
| return true; |
| } |
| if (typeof a !== typeof b) return false; |
| if (typeof a === "number") return isNaN(a) && isNaN(b); |
| if (typeof a !== "object" && typeof a !== "function") return false; |
| // Neither a nor b is primitive. |
| var objectClass = classOf(a); |
| if (objectClass !== classOf(b)) return false; |
| if (objectClass === "RegExp") { |
| // For RegExp, just compare pattern and flags using its toString. |
| return RegExpPrototypeToString.call(a) === |
| RegExpPrototypeToString.call(b); |
| } |
| // Functions are only identical to themselves. |
| if (objectClass === "Function") return false; |
| if (objectClass === "Array") { |
| var elementCount = 0; |
| if (a.length !== b.length) { |
| return false; |
| } |
| for (var i = 0; i < a.length; i++) { |
| if (!deepEquals(a[i], b[i])) return false; |
| } |
| return true; |
| } |
| if (objectClass === "String" || objectClass === "Number" || |
| objectClass === "BigInt" || objectClass === "Boolean" || |
| objectClass === "Date") { |
| if (ValueOf(a) !== ValueOf(b)) return false; |
| } |
| return deepObjectEquals(a, b); |
| } |
| |
| assertEquals = function assertEquals(expected, found, name_opt) { |
| if (!deepEquals(found, expected)) { |
| fail(PrettyPrint(expected), found, name_opt); |
| } |
| }; |
| })(); |