quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

test_builtin.js (34079B)


      1 "use strict";
      2 
      3 var status = 0;
      4 var throw_errors = true;
      5 
      6 function throw_error(msg) {
      7     if (throw_errors)
      8         throw Error(msg);
      9     console.log(msg);
     10     status = 1;
     11 }
     12 
     13 function assert(actual, expected, message) {
     14     function get_full_type(o) {
     15         var type = typeof(o);
     16         if (type === 'object') {
     17             if (o === null)
     18                 return 'null';
     19             if (o.constructor && o.constructor.name)
     20                 return o.constructor.name;
     21         }
     22         return type;
     23     }
     24 
     25     if (arguments.length == 1)
     26         expected = true;
     27 
     28     if (typeof actual === typeof expected) {
     29         if (actual === expected) {
     30             if (actual !== 0 || (1 / actual) === (1 / expected))
     31                 return;
     32         }
     33         if (typeof actual === 'number') {
     34             if (isNaN(actual) && isNaN(expected))
     35                 return true;
     36         }
     37         if (typeof actual === 'object') {
     38             if (actual !== null && expected !== null
     39             &&  actual.constructor === expected.constructor
     40             &&  actual.toString() === expected.toString())
     41                 return;
     42         }
     43     }
     44     // Should output the source file and line number and extract
     45     //   the expression from the assert call
     46     throw_error("assertion failed: got " +
     47                 get_full_type(actual) + ":|" + actual + "|, expected " +
     48                 get_full_type(expected) + ":|" + expected + "|" +
     49                 (message ? " (" + message + ")" : ""));
     50 }
     51 
     52 function assert_throws(expected_error, func)
     53 {
     54     var err = false;
     55     try {
     56         func();
     57     } catch(e) {
     58         err = true;
     59         if (!(e instanceof expected_error)) {
     60             // Should output the source file and line number and extract
     61             //   the expression from the assert_throws() call
     62             throw_error("unexpected exception type");
     63             return;
     64         }
     65     }
     66     if (!err) {
     67         // Should output the source file and line number and extract
     68         //   the expression from the assert_throws() call
     69         throw_error("expected exception");
     70     }
     71 }
     72 
     73 // load more elaborate version of assert if available
     74 try { __loadScript("test_assert.js"); } catch(e) {}
     75 
     76 /*----------------*/
     77 
     78 function my_func(a, b)
     79 {
     80     return a + b;
     81 }
     82 
     83 function test_function()
     84 {
     85     function f(a, b) {
     86         var i, tab = [];
     87         tab.push(this);
     88         for(i = 0; i < arguments.length; i++)
     89             tab.push(arguments[i]);
     90         return tab;
     91     }
     92     function constructor1(a) {
     93         this.x = a;
     94     }
     95 
     96     var r, g;
     97 
     98     r = my_func.call(null, 1, 2);
     99     assert(r, 3, "call");
    100 
    101     r = my_func.apply(null, [1, 2]);
    102     assert(r, 3, "apply");
    103 
    104     r = (function () { return 1; }).apply(null, undefined);
    105     assert(r, 1);
    106 
    107     assert_throws(TypeError, (function() {
    108         Reflect.apply((function () { return 1; }), null, undefined);
    109     }));
    110 
    111     r = new Function("a", "b", "return a + b;");
    112     assert(r(2,3), 5, "function");
    113 
    114     g = f.bind(1, 2);
    115     assert(g.length, 1);
    116     assert(g.name, "bound f");
    117     assert(g(3), [1,2,3]);
    118 
    119     g = constructor1.bind(null, 1);
    120     r = new g();
    121     assert(r.x, 1);
    122 }
    123 
    124 function test()
    125 {
    126     var r, a, b, c, err;
    127 
    128     r = Error("hello");
    129     assert(r.message, "hello", "Error");
    130 
    131     a = new Object();
    132     a.x = 1;
    133     assert(a.x, 1, "Object");
    134 
    135     assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf");
    136     Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true });
    137     assert(a.y, 3, "defineProperty");
    138 
    139     Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true });
    140     assert(a.z, 4, "get");
    141     a.z = 5;
    142     assert(a.z_val, 5, "set");
    143 
    144     a = { get z() { return 4; }, set z(val) { this.z_val = val; } };
    145     assert(a.z, 4, "get");
    146     a.z = 5;
    147     assert(a.z_val, 5, "set");
    148 
    149     b = Object.create(a);
    150     assert(Object.getPrototypeOf(b), a, "create");
    151     c = {u:2};
    152     /* XXX: refcount bug in 'b' instead of 'a' */
    153     Object.setPrototypeOf(a, c);
    154     assert(Object.getPrototypeOf(a), c, "setPrototypeOf");
    155 
    156     a = {};
    157     assert(a.toString(), "[object Object]", "toString");
    158 
    159     a = {x:1};
    160     assert(Object.isExtensible(a), true, "extensible");
    161     Object.preventExtensions(a);
    162 
    163     err = false;
    164     try {
    165         a.y = 2;
    166     } catch(e) {
    167         err = true;
    168     }
    169     assert(Object.isExtensible(a), false, "extensible");
    170     assert(typeof a.y, "undefined", "extensible");
    171     assert(err, true, "extensible");
    172 }
    173 
    174 function test_enum()
    175 {
    176     var a, tab;
    177     a = {x:1,
    178          "18014398509481984": 1,
    179          "9007199254740992": 1,
    180          "9007199254740991": 1,
    181          "4294967296": 1,
    182          "4294967295": 1,
    183          y:1,
    184          "4294967294": 1,
    185          "1": 2};
    186     tab = Object.keys(a);
    187 //    console.log("tab=" + tab.toString());
    188     assert(tab, ["1","4294967294","x","18014398509481984","9007199254740992","9007199254740991","4294967296","4294967295","y"], "keys");
    189 }
    190 
    191 function test_array()
    192 {
    193     var a, err;
    194 
    195     a = [1, 2, 3];
    196     assert(a.length, 3, "array");
    197     assert(a[2], 3, "array1");
    198 
    199     a = new Array(10);
    200     assert(a.length, 10, "array2");
    201 
    202     a = new Array(1, 2);
    203     assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3");
    204 
    205     a = [1, 2, 3];
    206     a.length = 2;
    207     assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4");
    208 
    209     a = [];
    210     a[1] = 10;
    211     a[4] = 3;
    212     assert(a.length, 5);
    213 
    214     a = [1,2];
    215     a.length = 5;
    216     a[4] = 1;
    217     a.length = 4;
    218     assert(a[4] !== 1, true, "array5");
    219 
    220     a = [1,2];
    221     a.push(3,4);
    222     assert(a.join(), "1,2,3,4", "join");
    223 
    224     a = [1,2,3,4,5];
    225     Object.defineProperty(a, "3", { configurable: false });
    226     err = false;
    227     try {
    228         a.length = 2;
    229     } catch(e) {
    230         err = true;
    231     }
    232     assert(err && a.toString() === "1,2,3,4");
    233 }
    234 
    235 function test_string()
    236 {
    237     var a;
    238     a = String("abc");
    239     assert(a.length, 3, "string");
    240     assert(a[1], "b", "string");
    241     assert(a.charCodeAt(1), 0x62, "string");
    242     assert(String.fromCharCode(65), "A", "string");
    243     assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string");
    244     assert(a.charAt(1), "b");
    245     assert(a.charAt(-1), "");
    246     assert(a.charAt(3), "");
    247 
    248     a = "abcd";
    249     assert(a.substring(1, 3), "bc", "substring");
    250     a = String.fromCharCode(0x20ac);
    251     assert(a.charCodeAt(0), 0x20ac, "unicode");
    252     assert(a, "€", "unicode");
    253     assert(a, "\u20ac", "unicode");
    254     assert(a, "\u{20ac}", "unicode");
    255     assert("a", "\x61", "unicode");
    256 
    257     a = "\u{10ffff}";
    258     assert(a.length, 2, "unicode");
    259     assert(a, "\u{dbff}\u{dfff}", "unicode");
    260     assert(a.codePointAt(0), 0x10ffff);
    261     assert(String.fromCodePoint(0x10ffff), a);
    262 
    263     assert("a".concat("b", "c"), "abc");
    264 
    265     assert("abcabc".indexOf("cab"), 2);
    266     assert("abcabc".indexOf("cab2"), -1);
    267     assert("abc".indexOf("c"), 2);
    268 
    269     assert("aaa".indexOf("a"), 0);
    270     assert("aaa".indexOf("a", NaN), 0);
    271     assert("aaa".indexOf("a", -Infinity), 0);
    272     assert("aaa".indexOf("a", -1), 0);
    273     assert("aaa".indexOf("a", -0), 0);
    274     assert("aaa".indexOf("a", 0), 0);
    275     assert("aaa".indexOf("a", 1), 1);
    276     assert("aaa".indexOf("a", 2), 2);
    277     assert("aaa".indexOf("a", 3), -1);
    278     assert("aaa".indexOf("a", 4), -1);
    279     assert("aaa".indexOf("a", Infinity), -1);
    280 
    281     assert("aaa".indexOf(""), 0);
    282     assert("aaa".indexOf("", NaN), 0);
    283     assert("aaa".indexOf("", -Infinity), 0);
    284     assert("aaa".indexOf("", -1), 0);
    285     assert("aaa".indexOf("", -0), 0);
    286     assert("aaa".indexOf("", 0), 0);
    287     assert("aaa".indexOf("", 1), 1);
    288     assert("aaa".indexOf("", 2), 2);
    289     assert("aaa".indexOf("", 3), 3);
    290     assert("aaa".indexOf("", 4), 3);
    291     assert("aaa".indexOf("", Infinity), 3);
    292 
    293     assert("aaa".lastIndexOf("a"), 2);
    294     assert("aaa".lastIndexOf("a", NaN), 2);
    295     assert("aaa".lastIndexOf("a", -Infinity), 0);
    296     assert("aaa".lastIndexOf("a", -1), 0);
    297     assert("aaa".lastIndexOf("a", -0), 0);
    298     assert("aaa".lastIndexOf("a", 0), 0);
    299     assert("aaa".lastIndexOf("a", 1), 1);
    300     assert("aaa".lastIndexOf("a", 2), 2);
    301     assert("aaa".lastIndexOf("a", 3), 2);
    302     assert("aaa".lastIndexOf("a", 4), 2);
    303     assert("aaa".lastIndexOf("a", Infinity), 2);
    304 
    305     assert("aaa".lastIndexOf(""), 3);
    306     assert("aaa".lastIndexOf("", NaN), 3);
    307     assert("aaa".lastIndexOf("", -Infinity), 0);
    308     assert("aaa".lastIndexOf("", -1), 0);
    309     assert("aaa".lastIndexOf("", -0), 0);
    310     assert("aaa".lastIndexOf("", 0), 0);
    311     assert("aaa".lastIndexOf("", 1), 1);
    312     assert("aaa".lastIndexOf("", 2), 2);
    313     assert("aaa".lastIndexOf("", 3), 3);
    314     assert("aaa".lastIndexOf("", 4), 3);
    315     assert("aaa".lastIndexOf("", Infinity), 3);
    316 
    317     assert("a,b,c".split(","), ["a","b","c"]);
    318     assert(",b,c".split(","), ["","b","c"]);
    319     assert("a,b,".split(","), ["a","b",""]);
    320 
    321     assert("aaaa".split(), [ "aaaa" ]);
    322     assert("aaaa".split(undefined, 0), [ ]);
    323     assert("aaaa".split(""), [ "a", "a", "a", "a" ]);
    324     assert("aaaa".split("", 0), [ ]);
    325     assert("aaaa".split("", 1), [ "a" ]);
    326     assert("aaaa".split("", 2), [ "a", "a" ]);
    327     assert("aaaa".split("a"), [ "", "", "", "", "" ]);
    328     assert("aaaa".split("a", 2), [ "", "" ]);
    329     assert("aaaa".split("aa"), [ "", "", "" ]);
    330     assert("aaaa".split("aa", 0), [ ]);
    331     assert("aaaa".split("aa", 1), [ "" ]);
    332     assert("aaaa".split("aa", 2), [ "", "" ]);
    333     assert("aaaa".split("aaa"), [ "", "a" ]);
    334     assert("aaaa".split("aaaa"), [ "", "" ]);
    335     assert("aaaa".split("aaaaa"), [ "aaaa" ]);
    336     assert("aaaa".split("aaaaa", 0), [  ]);
    337     assert("aaaa".split("aaaaa", 1), [ "aaaa" ]);
    338 
    339     assert(eval('"\0"'), "\0");
    340 
    341     assert("abc".padStart(Infinity, ""), "abc");
    342 }
    343 
    344 function test_math()
    345 {
    346     var a;
    347     a = 1.4;
    348     assert(Math.floor(a), 1);
    349     assert(Math.ceil(a), 2);
    350     assert(Math.imul(0x12345678, 123), -1088058456);
    351     assert(Math.imul(0xB505, 0xB504), 2147441940);
    352     assert(Math.imul(0xB505, 0xB505), -2147479015);
    353     assert(Math.imul((-2)**31, (-2)**31), 0);
    354     assert(Math.imul(2**31-1, 2**31-1), 1);
    355     assert(Math.fround(0.1), 0.10000000149011612);
    356     assert(Math.hypot(), 0);
    357     assert(Math.hypot(-2), 2);
    358     assert(Math.hypot(3, 4), 5);
    359     assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15);
    360     assert(Math.sumPrecise([1,Number.EPSILON/2,Number.MIN_VALUE]), 1.0000000000000002);
    361 }
    362 
    363 function test_number()
    364 {
    365     assert(parseInt("123"), 123);
    366     assert(parseInt("  123r"), 123);
    367     assert(parseInt("0x123"), 0x123);
    368     assert(parseInt("0o123"), 0);
    369     assert(+"  123   ", 123);
    370     assert(+"0b111", 7);
    371     assert(+"0o123", 83);
    372     assert(parseFloat("2147483647"), 2147483647);
    373     assert(parseFloat("2147483648"), 2147483648);
    374     assert(parseFloat("-2147483647"), -2147483647);
    375     assert(parseFloat("-2147483648"), -2147483648);
    376     assert(parseFloat("0x1234"), 0);
    377     assert(parseFloat("Infinity"), Infinity);
    378     assert(parseFloat("-Infinity"), -Infinity);
    379     assert(parseFloat("123.2"), 123.2);
    380     assert(parseFloat("123.2e3"), 123200);
    381     assert(Number.isNaN(Number("+")));
    382     assert(Number.isNaN(Number("-")));
    383     assert(Number.isNaN(Number("\x00a")));
    384 
    385     assert((1-2**-53).toString(12), "0.bbbbbbbbbbbbbba");
    386     assert((1000000000000000128).toString(), "1000000000000000100");
    387     assert((1000000000000000128).toFixed(0), "1000000000000000128");
    388     assert((25).toExponential(0), "3e+1");
    389     assert((-25).toExponential(0), "-3e+1");
    390     assert((2.5).toPrecision(1), "3");
    391     assert((-2.5).toPrecision(1), "-3");
    392     assert((25).toPrecision(1) === "3e+1");
    393     assert((1.125).toFixed(2), "1.13");
    394     assert((-1.125).toFixed(2), "-1.13");
    395     assert((0.5).toFixed(0), "1");
    396     assert((-0.5).toFixed(0), "-1");
    397     assert((-1e-10).toFixed(0), "-0");
    398 
    399     assert((1.3).toString(7), "1.2046204620462046205");
    400     assert((1.3).toString(35), "1.ahhhhhhhhhm");
    401 }
    402 
    403 function test_eval2()
    404 {
    405     var g_call_count = 0;
    406     /* force non strict mode for f1 and f2 */
    407     var f1 = new Function("eval", "eval(1, 2)");
    408     var f2 = new Function("eval", "eval(...[1, 2])");
    409     function g(a, b) {
    410         assert(a, 1);
    411         assert(b, 2);
    412         g_call_count++;
    413     }
    414     f1(g);
    415     f2(g);
    416     assert(g_call_count, 2);
    417 }
    418 
    419 function test_eval()
    420 {
    421     function f(b) {
    422         var x = 1;
    423         return eval(b);
    424     }
    425     var r, a;
    426 
    427     r = eval("1+1;");
    428     assert(r, 2, "eval");
    429 
    430     r = eval("var my_var=2; my_var;");
    431     assert(r, 2, "eval");
    432     assert(typeof my_var, "undefined");
    433 
    434     assert(eval("if (1) 2; else 3;"), 2);
    435     assert(eval("if (0) 2; else 3;"), 3);
    436 
    437     assert(f.call(1, "this"), 1);
    438 
    439     a = 2;
    440     assert(eval("a"), 2);
    441 
    442     eval("a = 3");
    443     assert(a, 3);
    444 
    445     assert(f("arguments.length", 1), 2);
    446     assert(f("arguments[1]", 1), 1);
    447 
    448     a = 4;
    449     assert(f("a"), 4);
    450     f("a=3");
    451     assert(a, 3);
    452 
    453     test_eval2();
    454 }
    455 
    456 function test_typed_array()
    457 {
    458     var buffer, a, i, str;
    459 
    460     a = new Uint8Array(4);
    461     assert(a.length, 4);
    462     for(i = 0; i < a.length; i++)
    463         a[i] = i;
    464     assert(a.join(","), "0,1,2,3");
    465     a[0] = -1;
    466     assert(a[0], 255);
    467 
    468     a = new Int8Array(3);
    469     a[0] = 255;
    470     assert(a[0], -1);
    471 
    472     a = new Int32Array(3);
    473     a[0] = Math.pow(2, 32) - 1;
    474     assert(a[0], -1);
    475     assert(a.BYTES_PER_ELEMENT, 4);
    476 
    477     a = new Uint8ClampedArray(4);
    478     a[0] = -100;
    479     a[1] = 1.5;
    480     a[2] = 0.5;
    481     a[3] = 1233.5;
    482     assert(a.toString(), "0,2,0,255");
    483 
    484     buffer = new ArrayBuffer(16);
    485     assert(buffer.byteLength, 16);
    486     a = new Uint32Array(buffer, 12, 1);
    487     assert(a.length, 1);
    488     a[0] = -1;
    489 
    490     a = new Uint16Array(buffer, 2);
    491     a[0] = -1;
    492 
    493     a = new Float16Array(buffer, 8, 1);
    494     a[0] = 1;
    495 
    496     a = new Float32Array(buffer, 8, 1);
    497     a[0] = 1;
    498 
    499     a = new Uint8Array(buffer);
    500 
    501     str = a.toString();
    502     /* test little and big endian cases */
    503     if (str !== "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255" &&
    504         str !== "0,0,255,255,0,0,0,0,63,128,0,0,255,255,255,255") {
    505         assert(false);
    506     }
    507 
    508     assert(a.buffer, buffer);
    509 
    510     a = new Uint8Array([1, 2, 3, 4]);
    511     assert(a.toString(), "1,2,3,4");
    512     a.set([10, 11], 2);
    513     assert(a.toString(), "1,2,10,11");
    514 
    515     // https://github.com/quickjs-ng/quickjs/issues/1208
    516     buffer = new ArrayBuffer(16);
    517     a = new Uint8Array(buffer);
    518     a.fill(42);
    519     assert(a[0], 42);
    520     buffer.transfer();
    521     assert(a[0], undefined);
    522 }
    523 
    524 /* return [s, line_num, col_num] where line_num and col_num are the
    525    position of the '@' character in 'str'. 's' is str without the '@'
    526    character */
    527 function get_string_pos(str)
    528 {
    529     var p, line_num, col_num, s, q, r;
    530     p = str.indexOf('@');
    531     assert(p >= 0, true);
    532     q = 0;
    533     line_num = 1;
    534     for(;;) {
    535         r = str.indexOf('\n', q);
    536         if (r < 0 || r >= p)
    537             break;
    538         q = r + 1;
    539         line_num++;
    540     }
    541     col_num = p - q + 1;
    542     s = str.slice(0, p) + str.slice(p + 1);
    543     return [s, line_num, col_num];
    544 }
    545 
    546 function check_error_pos(e, expected_error, line_num, col_num, level)
    547 {
    548     var expected_pos, tab, line;
    549     level |= 0;
    550     expected_pos = ":" + line_num + ":" + col_num;
    551     tab = e.stack.split("\n");
    552     line = tab[level];
    553     if (line.slice(-1) == ')')
    554         line = line.slice(0, -1);
    555     if (line.indexOf(expected_pos) < 0) {
    556         throw_error("unexpected line or column number. error=" + e.message +
    557                     ".got |" + line + "|, expected |" + expected_pos + "|");
    558     }
    559 }
    560 
    561 function assert_json_error(str, line_num, col_num)
    562 {
    563     var err = false;
    564     var expected_pos, tab;
    565 
    566     tab = get_string_pos(str);
    567     
    568     try {
    569         JSON.parse(tab[0]);
    570     } catch(e) {
    571         err = true;
    572         if (!(e instanceof SyntaxError)) {
    573             throw_error("unexpected exception type");
    574             return;
    575         }
    576         /* XXX: the way quickjs returns JSON errors is not similar to Node or spiderMonkey */
    577         check_error_pos(e, SyntaxError, tab[1], tab[2]);
    578     }
    579     if (!err) {
    580         throw_error("expected exception");
    581     }
    582 }
    583 
    584 function test_json()
    585 {
    586     var a, s;
    587     s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}';
    588     a = JSON.parse(s);
    589     assert(a.x, 1);
    590     assert(a.y, true);
    591     assert(a.z, null);
    592     assert(JSON.stringify(a), s);
    593 
    594     /* indentation test */
    595     assert(JSON.stringify([[{x:1,y:{},z:[]},2,3]],undefined,1),
    596 `[
    597  [
    598   {
    599    "x": 1,
    600    "y": {},
    601    "z": []
    602   },
    603   2,
    604   3
    605  ]
    606 ]`);
    607 
    608     assert_json_error('\n"  \\@x"');
    609     assert_json_error('\n{ "a": @x }"');
    610 }
    611 
    612 function test_date()
    613 {
    614     // Date Time String format is YYYY-MM-DDTHH:mm:ss.sssZ
    615     // accepted date formats are: YYYY, YYYY-MM and YYYY-MM-DD
    616     // accepted time formats are: THH:mm, THH:mm:ss, THH:mm:ss.sss
    617     // expanded years are represented with 6 digits prefixed by + or -
    618     // -000000 is invalid.
    619     // A string containing out-of-bounds or nonconforming elements
    620     //   is not a valid instance of this format.
    621     // Hence the fractional part after . should have 3 digits and how
    622     // a different number of digits is handled is implementation defined.
    623     assert(Date.parse(""), NaN);
    624     assert(Date.parse("2000"), 946684800000);
    625     assert(Date.parse("2000-01"), 946684800000);
    626     assert(Date.parse("2000-01-01"), 946684800000);
    627     //assert(Date.parse("2000-01-01T"), NaN);
    628     //assert(Date.parse("2000-01-01T00Z"), NaN);
    629     assert(Date.parse("2000-01-01T00:00Z"), 946684800000);
    630     assert(Date.parse("2000-01-01T00:00:00Z"), 946684800000);
    631     assert(Date.parse("2000-01-01T00:00:00.1Z"), 946684800100);
    632     assert(Date.parse("2000-01-01T00:00:00.10Z"), 946684800100);
    633     assert(Date.parse("2000-01-01T00:00:00.100Z"), 946684800100);
    634     assert(Date.parse("2000-01-01T00:00:00.1000Z"), 946684800100);
    635     assert(Date.parse("2000-01-01T00:00:00+00:00"), 946684800000);
    636     //assert(Date.parse("2000-01-01T00:00:00+00:30"), 946686600000);
    637     var d = new Date("2000T00:00");  // Jan 1st 2000, 0:00:00 local time
    638     assert(typeof d === 'object' && d.toString() != 'Invalid Date');
    639     assert((new Date('Jan 1 2000')).toISOString(),
    640            d.toISOString());
    641     assert((new Date('Jan 1 2000 00:00')).toISOString(),
    642            d.toISOString());
    643     assert((new Date('Jan 1 2000 00:00:00')).toISOString(),
    644            d.toISOString());
    645     assert((new Date('Jan 1 2000 00:00:00 GMT+0100')).toISOString(),
    646            '1999-12-31T23:00:00.000Z');
    647     assert((new Date('Jan 1 2000 00:00:00 GMT+0200')).toISOString(),
    648            '1999-12-31T22:00:00.000Z');
    649     assert((new Date('Sat Jan 1 2000')).toISOString(),
    650            d.toISOString());
    651     assert((new Date('Sat Jan 1 2000 00:00')).toISOString(),
    652            d.toISOString());
    653     assert((new Date('Sat Jan 1 2000 00:00:00')).toISOString(),
    654            d.toISOString());
    655     assert((new Date('Sat Jan 1 2000 00:00:00 GMT+0100')).toISOString(),
    656            '1999-12-31T23:00:00.000Z');
    657     assert((new Date('Sat Jan 1 2000 00:00:00 GMT+0200')).toISOString(),
    658            '1999-12-31T22:00:00.000Z');
    659 
    660     var d = new Date(1506098258091);
    661     assert(d.toISOString(), "2017-09-22T16:37:38.091Z");
    662     d.setUTCHours(18, 10, 11);
    663     assert(d.toISOString(), "2017-09-22T18:10:11.091Z");
    664     var a = Date.parse(d.toISOString());
    665     assert((new Date(a)).toISOString(), d.toISOString());
    666 
    667     assert((new Date("2020-01-01T01:01:01.123Z")).toISOString(),
    668                      "2020-01-01T01:01:01.123Z");
    669     /* implementation defined behavior */
    670     assert((new Date("2020-01-01T01:01:01.1Z")).toISOString(),
    671                      "2020-01-01T01:01:01.100Z");
    672     assert((new Date("2020-01-01T01:01:01.12Z")).toISOString(),
    673                      "2020-01-01T01:01:01.120Z");
    674     assert((new Date("2020-01-01T01:01:01.1234Z")).toISOString(),
    675                      "2020-01-01T01:01:01.123Z");
    676     assert((new Date("2020-01-01T01:01:01.12345Z")).toISOString(),
    677                      "2020-01-01T01:01:01.123Z");
    678     assert((new Date("2020-01-01T01:01:01.1235Z")).toISOString(),
    679                      "2020-01-01T01:01:01.123Z");
    680     assert((new Date("2020-01-01T01:01:01.9999Z")).toISOString(),
    681                      "2020-01-01T01:01:01.999Z");
    682 
    683     assert(Date.UTC(2017), 1483228800000);
    684     assert(Date.UTC(2017, 9), 1506816000000);
    685     assert(Date.UTC(2017, 9, 22), 1508630400000);
    686     assert(Date.UTC(2017, 9, 22, 18), 1508695200000);
    687     assert(Date.UTC(2017, 9, 22, 18, 10), 1508695800000);
    688     assert(Date.UTC(2017, 9, 22, 18, 10, 11), 1508695811000);
    689     assert(Date.UTC(2017, 9, 22, 18, 10, 11, 91), 1508695811091);
    690 
    691     assert(Date.UTC(NaN), NaN);
    692     assert(Date.UTC(2017, NaN), NaN);
    693     assert(Date.UTC(2017, 9, NaN), NaN);
    694     assert(Date.UTC(2017, 9, 22, NaN), NaN);
    695     assert(Date.UTC(2017, 9, 22, 18, NaN), NaN);
    696     assert(Date.UTC(2017, 9, 22, 18, 10, NaN), NaN);
    697     assert(Date.UTC(2017, 9, 22, 18, 10, 11, NaN), NaN);
    698     assert(Date.UTC(2017, 9, 22, 18, 10, 11, 91, NaN), 1508695811091);
    699 
    700     // TODO: Fix rounding errors on Windows/Cygwin.
    701     if (!(typeof os !== 'undefined' && ['win32', 'cygwin'].includes(os.platform))) {
    702         // from test262/test/built-ins/Date/UTC/fp-evaluation-order.js
    703         assert(Date.UTC(1970, 0, 1, 80063993375, 29, 1, -288230376151711740), 29312,
    704                'order of operations / precision in MakeTime');
    705         assert(Date.UTC(1970, 0, 213503982336, 0, 0, 0, -18446744073709552000), 34447360,
    706                'precision in MakeDate');
    707     }
    708     //assert(Date.UTC(2017 - 1e9, 9 + 12e9), 1506816000000);  // node fails this
    709     assert(Date.UTC(2017, 9, 22 - 1e10, 18 + 24e10), 1508695200000);
    710     assert(Date.UTC(2017, 9, 22, 18 - 1e10, 10 + 60e10), 1508695800000);
    711     assert(Date.UTC(2017, 9, 22, 18, 10 - 1e10, 11 + 60e10), 1508695811000);
    712     assert(Date.UTC(2017, 9, 22, 18, 10, 11 - 1e12, 91 + 1000e12), 1508695811091);
    713 }
    714 
    715 function test_regexp()
    716 {
    717     var a, str;
    718     str = "abbbbbc";
    719     a = /(b+)c/.exec(str);
    720     assert(a[0], "bbbbbc");
    721     assert(a[1], "bbbbb");
    722     assert(a.index, 1);
    723     assert(a.input, str);
    724     a = /(b+)c/.test(str);
    725     assert(a, true);
    726     assert(/\x61/.exec("a")[0], "a");
    727     assert(/\u0061/.exec("a")[0], "a");
    728     assert(/\ca/.exec("\x01")[0], "\x01");
    729     assert(/\\a/.exec("\\a")[0], "\\a");
    730     assert(/\c0/.exec("\\c0")[0], "\\c0");
    731 
    732     a = /(\.(?=com|org)|\/)/.exec("ah.com");
    733     assert(a.index === 2 && a[0] === ".");
    734 
    735     a = /(\.(?!com|org)|\/)/.exec("ah.com");
    736     assert(a, null);
    737 
    738     a = /(?=(a+))/.exec("baaabac");
    739     assert(a.index === 1 && a[0] === "" && a[1] === "aaa");
    740 
    741     a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac");
    742     assert(a, ["zaacbbbcac","z","ac","a",,"c"]);
    743 
    744     a = eval("/\0a/");
    745     assert(a.toString(), "/\0a/");
    746     assert(a.exec("\0a")[0], "\0a");
    747 
    748     assert(/{1a}/.toString(), "/{1a}/");
    749     a = /a{1+/.exec("a{11");
    750     assert(a, ["a{11"]);
    751 
    752     /* test zero length matches */
    753     a = /(?:(?=(abc)))a/.exec("abc");
    754     assert(a, ["a", "abc"]);
    755     a = /(?:(?=(abc)))?a/.exec("abc");
    756     assert(a, ["a", undefined]);
    757     a = /(?:(?=(abc))){0,2}a/.exec("abc");
    758     assert(a, ["a", undefined]);
    759     a = /(?:|[\w])+([0-9])/.exec("123a23");
    760     assert(a, ["123a23", "3"]);
    761     a = /()*?a/.exec(",");
    762     assert(a, null);
    763 
    764     /* test \b escape */
    765     assert(/[\q{a\b}]/.test("a\b"), true);
    766     assert(/[\b]/.test("\b"), true);
    767     
    768     /* test case insensitive matching (test262 hardly tests it) */
    769     assert("aAbBcC#4".replace(/\p{Lower}/gu,"X"), "XAXBXC#4");
    770 
    771     assert("aAbBcC#4".replace(/\p{Lower}/gui,"X"), "XXXXXX#4");
    772     assert("aAbBcC#4".replace(/\p{Upper}/gui,"X"), "XXXXXX#4");
    773     assert("aAbBcC#4".replace(/\P{Lower}/gui,"X"), "XXXXXXXX");
    774     assert("aAbBcC#4".replace(/\P{Upper}/gui,"X"), "XXXXXXXX");
    775     assert("aAbBcC".replace(/[^b]/gui, "X"), "XXbBXX");
    776     assert("aAbBcC".replace(/[^A-B]/gui, "X"), "aAbBXX");
    777 
    778     assert("aAbBcC#4".replace(/\p{Lower}/gvi,"X"), "XXXXXX#4");
    779     assert("aAbBcC#4".replace(/\P{Lower}/gvi,"X"), "aAbBcCXX");
    780     assert("aAbBcC#4".replace(/[^\P{Lower}]/gvi,"X"), "XXXXXX#4");
    781     assert("aAbBcC#4".replace(/\P{Upper}/gvi,"X"), "aAbBcCXX");
    782     assert("aAbBcC".replace(/[^b]/gvi, "X"), "XXbBXX");
    783     assert("aAbBcC".replace(/[^A-B]/gvi, "X"), "aAbBXX");
    784     assert("aAbBcC".replace(/[[a-c]&&B]/gvi, "X"), "aAXXcC");
    785     assert("aAbBcC".replace(/[[a-c]--B]/gvi, "X"), "XXbBXX");
    786     
    787     assert("abcAbC".replace(/[\q{AbC}]/gvi,"X"), "XX");
    788     /* Note: SpiderMonkey and v8 may not be correct */
    789     assert("abcAbC".replace(/[\q{BC|A}]/gvi,"X"), "XXXX");
    790     assert("abcAbC".replace(/[\q{BC|A}--a]/gvi,"X"), "aXAX");
    791 
    792     /* case where lastIndex points to the second element of a
    793        surrogate pair */
    794     a = /(?:)/gu;
    795     a.lastIndex = 1;
    796     a.exec("🐱");
    797     assert(a.lastIndex, 0);
    798 
    799     a.lastIndex = 1;
    800     a.exec("a\udc00");
    801     assert(a.lastIndex, 1);
    802 
    803     a = /\u{10000}/vgd;
    804     a.lastIndex = 1;
    805     a = a.exec("\u{10000}_\u{10000}");
    806     assert(a.indices[0][0], 0);
    807     assert(a.indices[0][1], 2);
    808 }
    809 
    810 function test_symbol()
    811 {
    812     var a, b, obj, c;
    813     a = Symbol("abc");
    814     obj = {};
    815     obj[a] = 2;
    816     assert(obj[a], 2);
    817     assert(typeof obj["abc"], "undefined");
    818     assert(String(a), "Symbol(abc)");
    819     b = Symbol("abc");
    820     assert(a == a);
    821     assert(a === a);
    822     assert(a != b);
    823     assert(a !== b);
    824 
    825     b = Symbol.for("abc");
    826     c = Symbol.for("abc");
    827     assert(b === c);
    828     assert(b !== a);
    829 
    830     assert(Symbol.keyFor(b), "abc");
    831     assert(Symbol.keyFor(a), undefined);
    832 
    833     a = Symbol("aaa");
    834     assert(a.valueOf(), a);
    835     assert(a.toString(), "Symbol(aaa)");
    836 
    837     b = Object(a);
    838     assert(b.valueOf(), a);
    839     assert(b.toString(), "Symbol(aaa)");
    840 }
    841 
    842 function test_map1(key_type, n)
    843 {
    844     var a, i, tab, o, v;
    845     a = new Map();
    846     tab = [];
    847     for(i = 0; i < n; i++) {
    848         v = { };
    849         switch(key_type) {
    850         case "small_bigint":
    851             o = BigInt(i);
    852             break;
    853         case "bigint":
    854             o = BigInt(i) + (1n << 128n);
    855             break;
    856         case "object":
    857             o = { id: i };
    858             break;
    859         default:
    860             assert(false);
    861         }
    862         tab[i] = [o, v];
    863         a.set(o, v);
    864     }
    865 
    866     assert(a.size, n);
    867     for(i = 0; i < n; i++) {
    868         assert(a.get(tab[i][0]), tab[i][1]);
    869     }
    870 
    871     i = 0;
    872     a.forEach(function (v, o) {
    873         assert(o, tab[i++][0]);
    874         assert(a.has(o));
    875         assert(a.delete(o));
    876         assert(!a.has(o));
    877     });
    878 
    879     assert(a.size, 0);
    880 }
    881 
    882 function test_map()
    883 {
    884     var a, i, n, tab, o, v;
    885     n = 1000;
    886 
    887     a = new Map();
    888     for (var i = 0; i < n; i++) {
    889         a.set(i, i);
    890     }
    891     a.set(-2147483648, 1);
    892     assert(a.get(-2147483648), 1);
    893     assert(a.get(-2147483647 - 1), 1);
    894     assert(a.get(-2147483647.5 - 0.5), 1);
    895 
    896     a.set(1n, 1n);
    897     assert(a.get(1n), 1n);
    898     assert(a.get(2n**1000n - (2n**1000n - 1n)), 1n);
    899 
    900     test_map1("object", n);
    901     test_map1("small_bigint", n);
    902     test_map1("bigint", n);
    903 }
    904 
    905 function test_weak_map()
    906 {
    907     var a, i, n, tab, o, v, n2;
    908     a = new WeakMap();
    909     n = 10;
    910     tab = [];
    911     for(i = 0; i < n; i++) {
    912         v = { };
    913         if (i & 1)
    914             o = Symbol("x" + i);
    915         else
    916             o = { id: i };
    917         tab[i] = [o, v];
    918         a.set(o, v);
    919     }
    920     o = null;
    921 
    922     n2 = 5;
    923     for(i = 0; i < n2; i++) {
    924         a.delete(tab[i][0]);
    925     }
    926     for(i = n2; i < n; i++) {
    927         tab[i][0] = null; /* should remove the object from the WeakMap too */
    928     }
    929     std.gc();
    930     /* the WeakMap should be empty here */
    931 }
    932 
    933 function test_weak_map_cycles()
    934 {
    935     const weak1 = new WeakMap();
    936     const weak2 = new WeakMap();
    937     function createCyclicKey() {
    938         const parent = {};
    939         const child = {parent};
    940         parent.child = child;
    941         return child;
    942     }
    943     function testWeakMap() {
    944         const cyclicKey = createCyclicKey();
    945         const valueOfCyclicKey = {};
    946         weak1.set(cyclicKey, valueOfCyclicKey);
    947         weak2.set(valueOfCyclicKey, 1);
    948     }
    949     testWeakMap();
    950     // Force to free cyclicKey.
    951     std.gc();
    952     // Here will cause sigsegv because [cyclicKey] and [valueOfCyclicKey] in [weak1] was free,
    953     // but weak2's map record was not removed, and it's key refers [valueOfCyclicKey] which is free.
    954     weak2.get({});
    955     std.gc();
    956 }
    957 
    958 function test_weak_ref()
    959 {
    960     var w1, w2, o, i;
    961 
    962     for(i = 0; i < 2; i++) {
    963         if (i == 0)
    964             o = { };
    965         else
    966             o = Symbol("x");
    967         w1 = new WeakRef(o);
    968         assert(w1.deref(), o);
    969         w2 = new WeakRef(o);
    970         assert(w2.deref(), o);
    971         
    972         o = null;
    973         assert(w1.deref(), undefined);
    974         assert(w2.deref(), undefined);
    975         std.gc();
    976         assert(w1.deref(), undefined);
    977         assert(w2.deref(), undefined);
    978     }
    979 }
    980 
    981 function test_finalization_registry()
    982 {
    983     {
    984         let expected = {};
    985         let actual;
    986         let finrec = new FinalizationRegistry(v => { actual = v });
    987         finrec.register({}, expected);
    988         os.setTimeout(() => {
    989             assert(actual, expected);
    990         }, 0);
    991     }
    992     {
    993         let expected = 42;
    994         let actual;
    995         let finrec = new FinalizationRegistry(v => { actual = v });
    996         finrec.register({}, expected);
    997         os.setTimeout(() => {
    998             assert(actual, expected);
    999         }, 0);
   1000     }
   1001     std.gc();
   1002 }
   1003 
   1004 function test_generator()
   1005 {
   1006     function *f() {
   1007         var ret;
   1008         yield 1;
   1009         ret = yield 2;
   1010         assert(ret, "next_arg");
   1011         return 3;
   1012     }
   1013     function *f2() {
   1014         yield 1;
   1015         yield 2;
   1016         return "ret_val";
   1017     }
   1018     function *f1() {
   1019         var ret = yield *f2();
   1020         assert(ret, "ret_val");
   1021         return 3;
   1022     }
   1023     function *f3() {
   1024         var ret;
   1025         /* test stack consistency with nip_n to handle yield return +
   1026          * finally clause */
   1027         try {
   1028             ret = 2 + (yield 1);
   1029         } catch(e) {
   1030         } finally {
   1031             ret++;
   1032         }
   1033         return ret;
   1034     }
   1035     var g, v;
   1036     g = f();
   1037     v = g.next();
   1038     assert(v.value === 1 && v.done === false);
   1039     v = g.next();
   1040     assert(v.value === 2 && v.done === false);
   1041     v = g.next("next_arg");
   1042     assert(v.value === 3 && v.done === true);
   1043     v = g.next();
   1044     assert(v.value === undefined && v.done === true);
   1045 
   1046     g = f1();
   1047     v = g.next();
   1048     assert(v.value === 1 && v.done === false);
   1049     v = g.next();
   1050     assert(v.value === 2 && v.done === false);
   1051     v = g.next();
   1052     assert(v.value === 3 && v.done === true);
   1053     v = g.next();
   1054     assert(v.value === undefined && v.done === true);
   1055 
   1056     g = f3();
   1057     v = g.next();
   1058     assert(v.value === 1 && v.done === false);
   1059     v = g.next(3);
   1060     assert(v.value === 6 && v.done === true);
   1061 }
   1062 
   1063 function rope_concat(n, dir)
   1064 {
   1065     var i, s;
   1066     s = "";
   1067     if (dir > 0) {
   1068         for(i = 0; i < n; i++)
   1069             s += String.fromCharCode(i & 0xffff);
   1070     } else {
   1071         for(i = n - 1; i >= 0; i--)
   1072             s = String.fromCharCode(i & 0xffff) + s;
   1073     }
   1074     
   1075     for(i = 0; i < n; i++) {
   1076         /* test before the assert to go faster */
   1077         if (s.charCodeAt(i) != (i & 0xffff)) {
   1078             assert(s.charCodeAt(i), i & 0xffff);
   1079         }
   1080     }
   1081 }
   1082 
   1083 function test_rope()
   1084 {
   1085     rope_concat(100000, 1);
   1086     rope_concat(100000, -1);
   1087 }
   1088 
   1089 function eval_error(eval_str, expected_error, level)
   1090 {
   1091     var err = false;
   1092     var expected_pos, tab;
   1093 
   1094     tab = get_string_pos(eval_str);
   1095     
   1096     try {
   1097         eval(tab[0]);
   1098     } catch(e) {
   1099         err = true;
   1100         if (!(e instanceof expected_error)) {
   1101             throw_error("unexpected exception type");
   1102             return;
   1103         }
   1104         check_error_pos(e, expected_error, tab[1], tab[2], level);
   1105     }
   1106     if (!err) {
   1107         throw_error("expected exception");
   1108     }
   1109 }
   1110 
   1111 var poisoned_number = {
   1112     valueOf: function() { throw Error("poisoned number") },
   1113 };
   1114 
   1115 function test_line_column_numbers()
   1116 {
   1117     var f, e, tab;
   1118 
   1119     /* The '@' character provides the expected position of the
   1120        error. It is removed before evaluating the string. */
   1121     
   1122     /* parsing */
   1123     eval_error("\n 123 @a ", SyntaxError);
   1124     eval_error("\n  @/*  ", SyntaxError);
   1125     eval_error("function f  @a", SyntaxError);
   1126     /* currently regexp syntax errors point to the start of the regexp */
   1127     eval_error("\n  @/aaa]/u", SyntaxError); 
   1128 
   1129     /* function definitions */
   1130     
   1131     tab = get_string_pos("\n   @function f() { }; f;");
   1132     e = eval(tab[0]);
   1133     assert(e.lineNumber, tab[1]);
   1134     assert(e.columnNumber, tab[2]);
   1135 
   1136     /* errors */
   1137     tab = get_string_pos('\n  Error@("hello");');
   1138     e = eval(tab[0]);
   1139     check_error_pos(e, Error, tab[1], tab[2]);
   1140     
   1141     eval_error('\n  throw Error@("hello");', Error);
   1142 
   1143     /* operators */
   1144     eval_error('\n  1 + 2 @* poisoned_number;', Error, 1);
   1145     eval_error('\n  1 + "café" @* poisoned_number;', Error, 1);
   1146     eval_error('\n  1 + 2 @** poisoned_number;', Error, 1);
   1147     eval_error('\n  2 * @+ poisoned_number;', Error, 1);
   1148     eval_error('\n  2 * @- poisoned_number;', Error, 1);
   1149     eval_error('\n  2 * @~ poisoned_number;', Error, 1);
   1150     eval_error('\n  2 * @++ poisoned_number;', Error, 1);
   1151     eval_error('\n  2 * @-- poisoned_number;', Error, 1);
   1152     eval_error('\n  2 * poisoned_number @++;', Error, 1);
   1153     eval_error('\n  2 * poisoned_number @--;', Error, 1);
   1154 
   1155     /* accessors */
   1156     eval_error('\n 1 + null@[0];', TypeError); 
   1157     eval_error('\n 1 + null @. abcd;', TypeError); 
   1158     eval_error('\n 1 + null @( 1234 );', TypeError);
   1159     eval_error('var obj = { get a() { throw Error("test"); } }\n 1 + obj @. a;',
   1160                Error, 1);
   1161     eval_error('var obj = { set a(b) { throw Error("test"); } }\n obj @. a = 1;',
   1162                Error, 1);
   1163 
   1164     /* variables reference */
   1165     eval_error('\n  1 + @not_def', ReferenceError, 0);
   1166 
   1167     /* assignments */
   1168     eval_error('1 + (@not_def = 1)', ReferenceError, 0);
   1169     eval_error('1 + (@not_def += 2)', ReferenceError, 0);
   1170     eval_error('var a;\n 1 + (a @+= poisoned_number);', Error, 1);
   1171 }
   1172 
   1173 test();
   1174 test_function();
   1175 test_enum();
   1176 test_array();
   1177 test_string();
   1178 test_math();
   1179 test_number();
   1180 test_eval();
   1181 test_typed_array();
   1182 test_json();
   1183 test_date();
   1184 test_regexp();
   1185 test_symbol();
   1186 test_map();
   1187 test_weak_map();
   1188 test_weak_map_cycles();
   1189 test_weak_ref();
   1190 test_finalization_registry();
   1191 test_generator();
   1192 test_rope();
   1193 test_line_column_numbers();