diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /js/src/tests/non262/shell.js | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/shell.js')
-rw-r--r-- | js/src/tests/non262/shell.js | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/js/src/tests/non262/shell.js b/js/src/tests/non262/shell.js new file mode 100644 index 0000000000..2e4f9e5224 --- /dev/null +++ b/js/src/tests/non262/shell.js @@ -0,0 +1,339 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +(function(global) { + const undefined = void 0; + + /* + * completesNormally(CODE) returns true if evaluating CODE (as eval + * code) completes normally (rather than throwing an exception). + */ + global.completesNormally = function completesNormally(code) { + try { + eval(code); + return true; + } catch (exception) { + return false; + } + } + + /* + * raisesException(EXCEPTION)(CODE) returns true if evaluating CODE (as + * eval code) throws an exception object that is an instance of EXCEPTION, + * and returns false if it throws any other error or evaluates + * successfully. For example: raises(TypeError)("0()") == true. + */ + global.raisesException = function raisesException(exception) { + return function (code) { + try { + eval(code); + return false; + } catch (actual) { + return actual instanceof exception; + } + }; + }; + + /* + * Return true if A is equal to B, where equality on arrays and objects + * means that they have the same set of enumerable properties, the values + * of each property are deep_equal, and their 'length' properties are + * equal. Equality on other types is ==. + */ + global.deepEqual = function deepEqual(a, b) { + if (typeof a != typeof b) + return false; + + if (typeof a == 'object') { + var props = {}; + // For every property of a, does b have that property with an equal value? + for (var prop in a) { + if (!deepEqual(a[prop], b[prop])) + return false; + props[prop] = true; + } + // Are all of b's properties present on a? + for (var prop in b) + if (!props[prop]) + return false; + // length isn't enumerable, but we want to check it, too. + return a.length == b.length; + } + + if (a === b) { + // Distinguish 0 from -0, even though they are ===. + return a !== 0 || 1/a === 1/b; + } + + // Treat NaNs as equal, even though NaN !== NaN. + // NaNs are the only non-reflexive values, i.e., if a !== a, then a is a NaN. + // isNaN is broken: it converts its argument to number, so isNaN("foo") => true + return a !== a && b !== b; + } + + /** Make an iterator with a return method. */ + global.makeIterator = function makeIterator(overrides) { + var throwMethod; + if (overrides && overrides.throw) + throwMethod = overrides.throw; + var iterator = { + throw: throwMethod, + next: function(x) { + if (overrides && overrides.next) + return overrides.next(x); + return { done: false }; + }, + return: function(x) { + if (overrides && overrides.ret) + return overrides.ret(x); + return { done: true }; + } + }; + + return function() { return iterator; }; + }; + + /** Yield every permutation of the elements in some array. */ + global.Permutations = function* Permutations(items) { + if (items.length == 0) { + yield []; + } else { + items = items.slice(0); + for (let i = 0; i < items.length; i++) { + let swap = items[0]; + items[0] = items[i]; + items[i] = swap; + for (let e of Permutations(items.slice(1, items.length))) + yield [items[0]].concat(e); + } + } + }; + + if (typeof global.assertThrowsValue === 'undefined') { + global.assertThrowsValue = function assertThrowsValue(f, val, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if ((exc === val) === (val === val) && (val !== 0 || 1 / exc === 1 / val)) + return; + fullmsg = "Assertion failed: expected exception " + val + ", got " + exc; + } + if (fullmsg === undefined) + fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown"; + if (msg !== undefined) + fullmsg += " - " + msg; + throw new Error(fullmsg); + }; + } + + if (typeof global.assertThrowsInstanceOf === 'undefined') { + global.assertThrowsInstanceOf = function assertThrowsInstanceOf(f, ctor, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if (exc instanceof ctor) + return; + fullmsg = `Assertion failed: expected exception ${ctor.name}, got ${exc}`; + } + + if (fullmsg === undefined) + fullmsg = `Assertion failed: expected exception ${ctor.name}, no exception thrown`; + if (msg !== undefined) + fullmsg += " - " + msg; + + throw new Error(fullmsg); + }; + } + + global.assertDeepEq = (function(){ + var call = Function.prototype.call, + Array_isArray = Array.isArray, + Array_includes = call.bind(Array.prototype.includes), + Map_ = Map, + Error_ = Error, + Symbol_ = Symbol, + Symbol_keyFor = Symbol.keyFor, + Symbol_description = call.bind(Object.getOwnPropertyDescriptor(Symbol.prototype, "description").get), + Map_has = call.bind(Map.prototype.has), + Map_get = call.bind(Map.prototype.get), + Map_set = call.bind(Map.prototype.set), + Object_toString = call.bind(Object.prototype.toString), + Function_toString = call.bind(Function.prototype.toString), + Object_getPrototypeOf = Object.getPrototypeOf, + Object_hasOwnProperty = call.bind(Object.prototype.hasOwnProperty), + Object_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, + Object_isExtensible = Object.isExtensible, + Object_getOwnPropertyNames = Object.getOwnPropertyNames; + + // Return true iff ES6 Type(v) isn't Object. + // Note that `typeof document.all === "undefined"`. + function isPrimitive(v) { + return (v === null || + v === undefined || + typeof v === "boolean" || + typeof v === "number" || + typeof v === "string" || + typeof v === "symbol"); + } + + function assertSameValue(a, b, msg) { + try { + assertEq(a, b); + } catch (exc) { + throw Error_(exc.message + (msg ? " " + msg : "")); + } + } + + function assertSameClass(a, b, msg) { + var ac = Object_toString(a), bc = Object_toString(b); + assertSameValue(ac, bc, msg); + switch (ac) { + case "[object Function]": + if (typeof isProxy !== "undefined" && !isProxy(a) && !isProxy(b)) + assertSameValue(Function_toString(a), Function_toString(b), msg); + } + } + + function at(prevmsg, segment) { + return prevmsg ? prevmsg + segment : "at _" + segment; + } + + // Assert that the arguments a and b are thoroughly structurally equivalent. + // + // For the sake of speed, we cut a corner: + // var x = {}, y = {}, ax = [x]; + // assertDeepEq([ax, x], [ax, y]); // passes (?!) + // + // Technically this should fail, since the two object graphs are different. + // (The graph of [ax, y] contains one more object than the graph of [ax, x].) + // + // To get technically correct behavior, pass {strictEquivalence: true}. + // This is slower because we have to walk the entire graph, and Object.prototype + // is big. + // + return function assertDeepEq(a, b, options) { + var strictEquivalence = options ? options.strictEquivalence : false; + + function assertSameProto(a, b, msg) { + check(Object_getPrototypeOf(a), Object_getPrototypeOf(b), at(msg, ".__proto__")); + } + + function failPropList(na, nb, msg) { + throw Error_("got own properties " + JSON.stringify(na) + ", expected " + JSON.stringify(nb) + + (msg ? " " + msg : "")); + } + + function assertSameProps(a, b, msg) { + var na = Object_getOwnPropertyNames(a), + nb = Object_getOwnPropertyNames(b); + if (na.length !== nb.length) + failPropList(na, nb, msg); + + // Ignore differences in whether Array elements are stored densely. + if (Array_isArray(a)) { + na.sort(); + nb.sort(); + } + + for (var i = 0; i < na.length; i++) { + var name = na[i]; + if (name !== nb[i]) + failPropList(na, nb, msg); + var da = Object_getOwnPropertyDescriptor(a, name), + db = Object_getOwnPropertyDescriptor(b, name); + var pmsg = at(msg, /^[_$A-Za-z0-9]+$/.test(name) + ? /0|[1-9][0-9]*/.test(name) ? "[" + name + "]" : "." + name + : "[" + JSON.stringify(name) + "]"); + assertSameValue(da.configurable, db.configurable, at(pmsg, ".[[Configurable]]")); + assertSameValue(da.enumerable, db.enumerable, at(pmsg, ".[[Enumerable]]")); + if (Object_hasOwnProperty(da, "value")) { + if (!Object_hasOwnProperty(db, "value")) + throw Error_("got data property, expected accessor property" + pmsg); + check(da.value, db.value, pmsg); + } else { + if (Object_hasOwnProperty(db, "value")) + throw Error_("got accessor property, expected data property" + pmsg); + check(da.get, db.get, at(pmsg, ".[[Get]]")); + check(da.set, db.set, at(pmsg, ".[[Set]]")); + } + } + }; + + const wellKnownSymbols = Reflect.ownKeys(Symbol) + .map(key => Symbol[key]) + .filter(value => typeof value === "symbol"); + + // The standard doesn't offer a convenient way to distinguish well-known + // symbols from user-created symbols. + function isSimilarSymbol(a, b) { + // Fast path for same symbols. + if (a === b) { + return true; + } + + // 1. Symbol descriptions must match. + // 2. Either both symbols are in the registry or none is. + // 3. Neither symbol must be a well-known symbol, because those are + // already handled through the fast path. + return Symbol_description(a) === Symbol_description(b) && + Symbol_keyFor(a) === Symbol_keyFor(b) && + !Array_includes(wellKnownSymbols, a) && + !Array_includes(wellKnownSymbols, b); + } + + var ab = new Map_(); + var bpath = new Map_(); + + function check(a, b, path) { + if (typeof a === "symbol") { + // Symbols are primitives, but they have identity. + // Symbol("x") !== Symbol("x") but + // assertDeepEq(Symbol("x"), Symbol("x")) should pass. + if (typeof b !== "symbol") { + throw Error_("got " + String(a) + ", expected " + String(b) + " " + path); + } else if (!isSimilarSymbol(a, b)) { + throw Error_("got " + String(a) + ", expected " + String(b) + " " + path); + } else if (Map_has(ab, a)) { + assertSameValue(Map_get(ab, a), b, path); + } else if (Map_has(bpath, b)) { + var bPrevPath = Map_get(bpath, b) || "_"; + throw Error_("got distinct symbols " + at(path, "") + " and " + + at(bPrevPath, "") + ", expected the same symbol both places"); + } else { + Map_set(ab, a, b); + Map_set(bpath, b, path); + } + } else if (isPrimitive(a)) { + assertSameValue(a, b, path); + } else if (isPrimitive(b)) { + throw Error_("got " + Object_toString(a) + ", expected " + String(b) + " " + path); + } else if (Map_has(ab, a)) { + assertSameValue(Map_get(ab, a), b, path); + } else if (Map_has(bpath, b)) { + var bPrevPath = Map_get(bpath, b) || "_"; + throw Error_("got distinct objects " + at(path, "") + " and " + at(bPrevPath, "") + + ", expected the same object both places"); + } else { + Map_set(ab, a, b); + Map_set(bpath, b, path); + if (a !== b || strictEquivalence) { + assertSameClass(a, b, path); + assertSameProto(a, b, path); + assertSameProps(a, b, path); + assertSameValue(Object_isExtensible(a), + Object_isExtensible(b), + at(path, ".[[Extensible]]")); + } + } + } + + check(a, b, ""); + }; + })(); + +})(this); |