| "use strict"; |
| |
| function assert(actual, expected, message) { |
| if (arguments.length == 1) |
| expected = true; |
| |
| if (actual === expected) |
| return; |
| |
| if (actual !== null && expected !== null |
| && typeof actual == 'object' && typeof expected == 'object' |
| && actual.toString() === expected.toString()) |
| return; |
| |
| throw Error("assertion failed: got |" + actual + "|" + |
| ", expected |" + expected + "|" + |
| (message ? " (" + message + ")" : "")); |
| } |
| |
| // load more elaborate version of assert if available |
| try { __loadScript("test_assert.js"); } catch(e) {} |
| |
| /*----------------*/ |
| |
| function my_func(a, b) |
| { |
| return a + b; |
| } |
| |
| function test_function() |
| { |
| function f(a, b) { |
| var i, tab = []; |
| tab.push(this); |
| for(i = 0; i < arguments.length; i++) |
| tab.push(arguments[i]); |
| return tab; |
| } |
| function constructor1(a) { |
| this.x = a; |
| } |
| |
| var r, g; |
| |
| r = my_func.call(null, 1, 2); |
| assert(r, 3, "call"); |
| |
| r = my_func.apply(null, [1, 2]); |
| assert(r, 3, "apply"); |
| |
| r = new Function("a", "b", "return a + b;"); |
| assert(r(2,3), 5, "function"); |
| |
| g = f.bind(1, 2); |
| assert(g.length, 1); |
| assert(g.name, "bound f"); |
| assert(g(3), [1,2,3]); |
| |
| g = constructor1.bind(null, 1); |
| r = new g(); |
| assert(r.x, 1); |
| } |
| |
| function test() |
| { |
| var r, a, b, c, err; |
| |
| r = Error("hello"); |
| assert(r.message, "hello", "Error"); |
| |
| a = new Object(); |
| a.x = 1; |
| assert(a.x, 1, "Object"); |
| |
| assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf"); |
| Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true }); |
| assert(a.y, 3, "defineProperty"); |
| |
| Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true }); |
| assert(a.z, 4, "get"); |
| a.z = 5; |
| assert(a.z_val, 5, "set"); |
| |
| a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; |
| assert(a.z, 4, "get"); |
| a.z = 5; |
| assert(a.z_val, 5, "set"); |
| |
| b = Object.create(a); |
| assert(Object.getPrototypeOf(b), a, "create"); |
| c = {u:2}; |
| /* XXX: refcount bug in 'b' instead of 'a' */ |
| Object.setPrototypeOf(a, c); |
| assert(Object.getPrototypeOf(a), c, "setPrototypeOf"); |
| |
| a = {}; |
| assert(a.toString(), "[object Object]", "toString"); |
| |
| a = {x:1}; |
| assert(Object.isExtensible(a), true, "extensible"); |
| Object.preventExtensions(a); |
| |
| err = false; |
| try { |
| a.y = 2; |
| } catch(e) { |
| err = true; |
| } |
| assert(Object.isExtensible(a), false, "extensible"); |
| assert(typeof a.y, "undefined", "extensible"); |
| assert(err, true, "extensible"); |
| } |
| |
| function test_enum() |
| { |
| var a, tab; |
| a = {x:1, |
| "18014398509481984": 1, |
| "9007199254740992": 1, |
| "9007199254740991": 1, |
| "4294967296": 1, |
| "4294967295": 1, |
| y:1, |
| "4294967294": 1, |
| "1": 2}; |
| tab = Object.keys(a); |
| // console.log("tab=" + tab.toString()); |
| assert(tab, ["1","4294967294","x","18014398509481984","9007199254740992","9007199254740991","4294967296","4294967295","y"], "keys"); |
| } |
| |
| function test_array() |
| { |
| var a, err; |
| |
| a = [1, 2, 3]; |
| assert(a.length, 3, "array"); |
| assert(a[2], 3, "array1"); |
| |
| a = new Array(10); |
| assert(a.length, 10, "array2"); |
| |
| a = new Array(1, 2); |
| assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3"); |
| |
| a = [1, 2, 3]; |
| a.length = 2; |
| assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4"); |
| |
| a = []; |
| a[1] = 10; |
| a[4] = 3; |
| assert(a.length, 5); |
| |
| a = [1,2]; |
| a.length = 5; |
| a[4] = 1; |
| a.length = 4; |
| assert(a[4] !== 1, true, "array5"); |
| |
| a = [1,2]; |
| a.push(3,4); |
| assert(a.join(), "1,2,3,4", "join"); |
| |
| a = [1,2,3,4,5]; |
| Object.defineProperty(a, "3", { configurable: false }); |
| err = false; |
| try { |
| a.length = 2; |
| } catch(e) { |
| err = true; |
| } |
| assert(err && a.toString() === "1,2,3,4"); |
| } |
| |
| function test_string() |
| { |
| var a; |
| a = String("abc"); |
| assert(a.length, 3, "string"); |
| assert(a[1], "b", "string"); |
| assert(a.charCodeAt(1), 0x62, "string"); |
| assert(String.fromCharCode(65), "A", "string"); |
| assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string"); |
| assert(a.charAt(1), "b"); |
| assert(a.charAt(-1), ""); |
| assert(a.charAt(3), ""); |
| |
| a = "abcd"; |
| assert(a.substring(1, 3), "bc", "substring"); |
| a = String.fromCharCode(0x20ac); |
| assert(a.charCodeAt(0), 0x20ac, "unicode"); |
| assert(a, "€", "unicode"); |
| assert(a, "\u20ac", "unicode"); |
| assert(a, "\u{20ac}", "unicode"); |
| assert("a", "\x61", "unicode"); |
| |
| a = "\u{10ffff}"; |
| assert(a.length, 2, "unicode"); |
| assert(a, "\u{dbff}\u{dfff}", "unicode"); |
| assert(a.codePointAt(0), 0x10ffff); |
| assert(String.fromCodePoint(0x10ffff), a); |
| |
| assert("a".concat("b", "c"), "abc"); |
| |
| assert("abcabc".indexOf("cab"), 2); |
| assert("abcabc".indexOf("cab2"), -1); |
| assert("abc".indexOf("c"), 2); |
| |
| assert("aaa".indexOf("a"), 0); |
| assert("aaa".indexOf("a", NaN), 0); |
| assert("aaa".indexOf("a", -Infinity), 0); |
| assert("aaa".indexOf("a", -1), 0); |
| assert("aaa".indexOf("a", -0), 0); |
| assert("aaa".indexOf("a", 0), 0); |
| assert("aaa".indexOf("a", 1), 1); |
| assert("aaa".indexOf("a", 2), 2); |
| assert("aaa".indexOf("a", 3), -1); |
| assert("aaa".indexOf("a", 4), -1); |
| assert("aaa".indexOf("a", Infinity), -1); |
| |
| assert("aaa".indexOf(""), 0); |
| assert("aaa".indexOf("", NaN), 0); |
| assert("aaa".indexOf("", -Infinity), 0); |
| assert("aaa".indexOf("", -1), 0); |
| assert("aaa".indexOf("", -0), 0); |
| assert("aaa".indexOf("", 0), 0); |
| assert("aaa".indexOf("", 1), 1); |
| assert("aaa".indexOf("", 2), 2); |
| assert("aaa".indexOf("", 3), 3); |
| assert("aaa".indexOf("", 4), 3); |
| assert("aaa".indexOf("", Infinity), 3); |
| |
| assert("aaa".lastIndexOf("a"), 2); |
| assert("aaa".lastIndexOf("a", NaN), 2); |
| assert("aaa".lastIndexOf("a", -Infinity), 0); |
| assert("aaa".lastIndexOf("a", -1), 0); |
| assert("aaa".lastIndexOf("a", -0), 0); |
| assert("aaa".lastIndexOf("a", 0), 0); |
| assert("aaa".lastIndexOf("a", 1), 1); |
| assert("aaa".lastIndexOf("a", 2), 2); |
| assert("aaa".lastIndexOf("a", 3), 2); |
| assert("aaa".lastIndexOf("a", 4), 2); |
| assert("aaa".lastIndexOf("a", Infinity), 2); |
| |
| assert("aaa".lastIndexOf(""), 3); |
| assert("aaa".lastIndexOf("", NaN), 3); |
| assert("aaa".lastIndexOf("", -Infinity), 0); |
| assert("aaa".lastIndexOf("", -1), 0); |
| assert("aaa".lastIndexOf("", -0), 0); |
| assert("aaa".lastIndexOf("", 0), 0); |
| assert("aaa".lastIndexOf("", 1), 1); |
| assert("aaa".lastIndexOf("", 2), 2); |
| assert("aaa".lastIndexOf("", 3), 3); |
| assert("aaa".lastIndexOf("", 4), 3); |
| assert("aaa".lastIndexOf("", Infinity), 3); |
| |
| assert("a,b,c".split(","), ["a","b","c"]); |
| assert(",b,c".split(","), ["","b","c"]); |
| assert("a,b,".split(","), ["a","b",""]); |
| |
| assert("aaaa".split(), [ "aaaa" ]); |
| assert("aaaa".split(undefined, 0), [ ]); |
| assert("aaaa".split(""), [ "a", "a", "a", "a" ]); |
| assert("aaaa".split("", 0), [ ]); |
| assert("aaaa".split("", 1), [ "a" ]); |
| assert("aaaa".split("", 2), [ "a", "a" ]); |
| assert("aaaa".split("a"), [ "", "", "", "", "" ]); |
| assert("aaaa".split("a", 2), [ "", "" ]); |
| assert("aaaa".split("aa"), [ "", "", "" ]); |
| assert("aaaa".split("aa", 0), [ ]); |
| assert("aaaa".split("aa", 1), [ "" ]); |
| assert("aaaa".split("aa", 2), [ "", "" ]); |
| assert("aaaa".split("aaa"), [ "", "a" ]); |
| assert("aaaa".split("aaaa"), [ "", "" ]); |
| assert("aaaa".split("aaaaa"), [ "aaaa" ]); |
| assert("aaaa".split("aaaaa", 0), [ ]); |
| assert("aaaa".split("aaaaa", 1), [ "aaaa" ]); |
| |
| assert(eval('"\0"'), "\0"); |
| |
| assert("abc".padStart(Infinity, ""), "abc"); |
| } |
| |
| function test_math() |
| { |
| var a; |
| a = 1.4; |
| assert(Math.floor(a), 1); |
| assert(Math.ceil(a), 2); |
| assert(Math.imul(0x12345678, 123), -1088058456); |
| assert(Math.fround(0.1), 0.10000000149011612); |
| assert(Math.hypot() == 0); |
| assert(Math.hypot(-2) == 2); |
| assert(Math.hypot(3, 4) == 5); |
| assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15); |
| } |
| |
| function test_number() |
| { |
| assert(parseInt("123"), 123); |
| assert(parseInt(" 123r"), 123); |
| assert(parseInt("0x123"), 0x123); |
| assert(parseInt("0o123"), 0); |
| assert(+" 123 ", 123); |
| assert(+"0b111", 7); |
| assert(+"0o123", 83); |
| assert(parseFloat("0x1234"), 0); |
| assert(parseFloat("Infinity"), Infinity); |
| assert(parseFloat("-Infinity"), -Infinity); |
| assert(parseFloat("123.2"), 123.2); |
| assert(parseFloat("123.2e3"), 123200); |
| assert(Number.isNaN(Number("+"))); |
| assert(Number.isNaN(Number("-"))); |
| assert(Number.isNaN(Number("\x00a"))); |
| |
| assert((25).toExponential(0), "3e+1"); |
| assert((-25).toExponential(0), "-3e+1"); |
| assert((2.5).toPrecision(1), "3"); |
| assert((-2.5).toPrecision(1), "-3"); |
| assert((1.125).toFixed(2), "1.13"); |
| assert((-1.125).toFixed(2), "-1.13"); |
| } |
| |
| function test_eval2() |
| { |
| var g_call_count = 0; |
| /* force non strict mode for f1 and f2 */ |
| var f1 = new Function("eval", "eval(1, 2)"); |
| var f2 = new Function("eval", "eval(...[1, 2])"); |
| function g(a, b) { |
| assert(a, 1); |
| assert(b, 2); |
| g_call_count++; |
| } |
| f1(g); |
| f2(g); |
| assert(g_call_count, 2); |
| } |
| |
| function test_eval() |
| { |
| function f(b) { |
| var x = 1; |
| return eval(b); |
| } |
| var r, a; |
| |
| r = eval("1+1;"); |
| assert(r, 2, "eval"); |
| |
| r = eval("var my_var=2; my_var;"); |
| assert(r, 2, "eval"); |
| assert(typeof my_var, "undefined"); |
| |
| assert(eval("if (1) 2; else 3;"), 2); |
| assert(eval("if (0) 2; else 3;"), 3); |
| |
| assert(f.call(1, "this"), 1); |
| |
| a = 2; |
| assert(eval("a"), 2); |
| |
| eval("a = 3"); |
| assert(a, 3); |
| |
| assert(f("arguments.length", 1), 2); |
| assert(f("arguments[1]", 1), 1); |
| |
| a = 4; |
| assert(f("a"), 4); |
| f("a=3"); |
| assert(a, 3); |
| |
| test_eval2(); |
| } |
| |
| function test_typed_array() |
| { |
| var buffer, a, i; |
| |
| a = new Uint8Array(4); |
| assert(a.length, 4); |
| for(i = 0; i < a.length; i++) |
| a[i] = i; |
| assert(a.join(","), "0,1,2,3"); |
| a[0] = -1; |
| assert(a[0], 255); |
| |
| a = new Int8Array(3); |
| a[0] = 255; |
| assert(a[0], -1); |
| |
| a = new Int32Array(3); |
| a[0] = Math.pow(2, 32) - 1; |
| assert(a[0], -1); |
| assert(a.BYTES_PER_ELEMENT, 4); |
| |
| a = new Uint8ClampedArray(4); |
| a[0] = -100; |
| a[1] = 1.5; |
| a[2] = 0.5; |
| a[3] = 1233.5; |
| assert(a.toString(), "0,2,0,255"); |
| |
| buffer = new ArrayBuffer(16); |
| assert(buffer.byteLength, 16); |
| a = new Uint32Array(buffer, 12, 1); |
| assert(a.length, 1); |
| a[0] = -1; |
| |
| a = new Uint16Array(buffer, 2); |
| a[0] = -1; |
| |
| a = new Float32Array(buffer, 8, 1); |
| a[0] = 1; |
| |
| a = new Uint8Array(buffer); |
| |
| assert(a.toString(), "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255"); |
| |
| assert(a.buffer, buffer); |
| |
| a = new Uint8Array([1, 2, 3, 4]); |
| assert(a.toString(), "1,2,3,4"); |
| a.set([10, 11], 2); |
| assert(a.toString(), "1,2,10,11"); |
| } |
| |
| function test_json() |
| { |
| var a, s; |
| s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}'; |
| a = JSON.parse(s); |
| assert(a.x, 1); |
| assert(a.y, true); |
| assert(a.z, null); |
| assert(JSON.stringify(a), s); |
| |
| /* indentation test */ |
| assert(JSON.stringify([[{x:1,y:{},z:[]},2,3]],undefined,1), |
| `[ |
| [ |
| { |
| "x": 1, |
| "y": {}, |
| "z": [] |
| }, |
| 2, |
| 3 |
| ] |
| ]`); |
| } |
| |
| function test_date() |
| { |
| var d = new Date(1506098258091), a, s; |
| assert(d.toISOString(), "2017-09-22T16:37:38.091Z"); |
| d.setUTCHours(18, 10, 11); |
| assert(d.toISOString(), "2017-09-22T18:10:11.091Z"); |
| a = Date.parse(d.toISOString()); |
| assert((new Date(a)).toISOString(), d.toISOString()); |
| s = new Date("2020-01-01T01:01:01.1Z").toISOString(); |
| assert(s == "2020-01-01T01:01:01.100Z"); |
| s = new Date("2020-01-01T01:01:01.12Z").toISOString(); |
| assert(s == "2020-01-01T01:01:01.120Z"); |
| s = new Date("2020-01-01T01:01:01.123Z").toISOString(); |
| assert(s == "2020-01-01T01:01:01.123Z"); |
| s = new Date("2020-01-01T01:01:01.1234Z").toISOString(); |
| assert(s == "2020-01-01T01:01:01.123Z"); |
| s = new Date("2020-01-01T01:01:01.12345Z").toISOString(); |
| assert(s == "2020-01-01T01:01:01.123Z"); |
| s = new Date("2020-01-01T01:01:01.1235Z").toISOString(); |
| assert(s == "2020-01-01T01:01:01.124Z"); |
| s = new Date("2020-01-01T01:01:01.9999Z").toISOString(); |
| assert(s == "2020-01-01T01:01:02.000Z"); |
| } |
| |
| function test_regexp() |
| { |
| var a, str; |
| str = "abbbbbc"; |
| a = /(b+)c/.exec(str); |
| assert(a[0], "bbbbbc"); |
| assert(a[1], "bbbbb"); |
| assert(a.index, 1); |
| assert(a.input, str); |
| a = /(b+)c/.test(str); |
| assert(a, true); |
| assert(/\x61/.exec("a")[0], "a"); |
| assert(/\u0061/.exec("a")[0], "a"); |
| assert(/\ca/.exec("\x01")[0], "\x01"); |
| assert(/\\a/.exec("\\a")[0], "\\a"); |
| assert(/\c0/.exec("\\c0")[0], "\\c0"); |
| |
| a = /(\.(?=com|org)|\/)/.exec("ah.com"); |
| assert(a.index === 2 && a[0] === "."); |
| |
| a = /(\.(?!com|org)|\/)/.exec("ah.com"); |
| assert(a, null); |
| |
| a = /(?=(a+))/.exec("baaabac"); |
| assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); |
| |
| a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); |
| assert(a, ["zaacbbbcac","z","ac","a",,"c"]); |
| |
| a = eval("/\0a/"); |
| assert(a.toString(), "/\0a/"); |
| assert(a.exec("\0a")[0], "\0a"); |
| |
| assert(/{1a}/.toString(), "/{1a}/"); |
| a = /a{1+/.exec("a{11"); |
| assert(a, ["a{11"] ); |
| } |
| |
| function test_symbol() |
| { |
| var a, b, obj, c; |
| a = Symbol("abc"); |
| obj = {}; |
| obj[a] = 2; |
| assert(obj[a], 2); |
| assert(typeof obj["abc"], "undefined"); |
| assert(String(a), "Symbol(abc)"); |
| b = Symbol("abc"); |
| assert(a == a); |
| assert(a === a); |
| assert(a != b); |
| assert(a !== b); |
| |
| b = Symbol.for("abc"); |
| c = Symbol.for("abc"); |
| assert(b === c); |
| assert(b !== a); |
| |
| assert(Symbol.keyFor(b), "abc"); |
| assert(Symbol.keyFor(a), undefined); |
| |
| a = Symbol("aaa"); |
| assert(a.valueOf(), a); |
| assert(a.toString(), "Symbol(aaa)"); |
| |
| b = Object(a); |
| assert(b.valueOf(), a); |
| assert(b.toString(), "Symbol(aaa)"); |
| } |
| |
| function test_map() |
| { |
| var a, i, n, tab, o, v; |
| n = 1000; |
| a = new Map(); |
| tab = []; |
| for(i = 0; i < n; i++) { |
| v = { }; |
| o = { id: i }; |
| tab[i] = [o, v]; |
| a.set(o, v); |
| } |
| |
| assert(a.size, n); |
| for(i = 0; i < n; i++) { |
| assert(a.get(tab[i][0]), tab[i][1]); |
| } |
| |
| i = 0; |
| a.forEach(function (v, o) { |
| assert(o, tab[i++][0]); |
| assert(a.has(o)); |
| assert(a.delete(o)); |
| assert(!a.has(o)); |
| }); |
| |
| assert(a.size, 0); |
| } |
| |
| function test_weak_map() |
| { |
| var a, i, n, tab, o, v, n2; |
| a = new WeakMap(); |
| n = 10; |
| tab = []; |
| for(i = 0; i < n; i++) { |
| v = { }; |
| o = { id: i }; |
| tab[i] = [o, v]; |
| a.set(o, v); |
| } |
| o = null; |
| |
| n2 = n >> 1; |
| for(i = 0; i < n2; i++) { |
| a.delete(tab[i][0]); |
| } |
| for(i = n2; i < n; i++) { |
| tab[i][0] = null; /* should remove the object from the WeakMap too */ |
| } |
| /* the WeakMap should be empty here */ |
| } |
| |
| function test_generator() |
| { |
| function *f() { |
| var ret; |
| yield 1; |
| ret = yield 2; |
| assert(ret, "next_arg"); |
| return 3; |
| } |
| function *f2() { |
| yield 1; |
| yield 2; |
| return "ret_val"; |
| } |
| function *f1() { |
| var ret = yield *f2(); |
| assert(ret, "ret_val"); |
| return 3; |
| } |
| var g, v; |
| g = f(); |
| v = g.next(); |
| assert(v.value === 1 && v.done === false); |
| v = g.next(); |
| assert(v.value === 2 && v.done === false); |
| v = g.next("next_arg"); |
| assert(v.value === 3 && v.done === true); |
| v = g.next(); |
| assert(v.value === undefined && v.done === true); |
| |
| g = f1(); |
| v = g.next(); |
| assert(v.value === 1 && v.done === false); |
| v = g.next(); |
| assert(v.value === 2 && v.done === false); |
| v = g.next(); |
| assert(v.value === 3 && v.done === true); |
| v = g.next(); |
| assert(v.value === undefined && v.done === true); |
| } |
| |
| test(); |
| test_function(); |
| test_enum(); |
| test_array(); |
| test_string(); |
| test_math(); |
| test_number(); |
| test_eval(); |
| test_typed_array(); |
| test_json(); |
| test_date(); |
| test_regexp(); |
| test_symbol(); |
| test_map(); |
| test_weak_map(); |
| test_generator(); |