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();