1"use strict";
2
3function assert(actual, expected, message) {
4    if (arguments.length == 1)
5        expected = true;
6
7    if (actual === expected)
8        return;
9
10    if (actual !== null && expected !== null
11    &&  typeof actual == 'object' && typeof expected == 'object'
12    &&  actual.toString() === expected.toString())
13        return;
14
15    throw Error("assertion failed: got |" + actual + "|" +
16                ", expected |" + expected + "|" +
17                (message ? " (" + message + ")" : ""));
18}
19
20// load more elaborate version of assert if available
21try { __loadScript("test_assert.js"); } catch(e) {}
22
23/*----------------*/
24
25function my_func(a, b)
26{
27    return a + b;
28}
29
30function test_function()
31{
32    function f(a, b) {
33        var i, tab = [];
34        tab.push(this);
35        for(i = 0; i < arguments.length; i++)
36            tab.push(arguments[i]);
37        return tab;
38    }
39    function constructor1(a) {
40        this.x = a;
41    }
42
43    var r, g;
44
45    r = my_func.call(null, 1, 2);
46    assert(r, 3, "call");
47
48    r = my_func.apply(null, [1, 2]);
49    assert(r, 3, "apply");
50
51    r = new Function("a", "b", "return a + b;");
52    assert(r(2,3), 5, "function");
53
54    g = f.bind(1, 2);
55    assert(g.length, 1);
56    assert(g.name, "bound f");
57    assert(g(3), [1,2,3]);
58
59    g = constructor1.bind(null, 1);
60    r = new g();
61    assert(r.x, 1);
62}
63
64function test()
65{
66    var r, a, b, c, err;
67
68    r = Error("hello");
69    assert(r.message, "hello", "Error");
70
71    a = new Object();
72    a.x = 1;
73    assert(a.x, 1, "Object");
74
75    assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf");
76    Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true });
77    assert(a.y, 3, "defineProperty");
78
79    Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true });
80    assert(a.z, 4, "get");
81    a.z = 5;
82    assert(a.z_val, 5, "set");
83
84    a = { get z() { return 4; }, set z(val) { this.z_val = val; } };
85    assert(a.z, 4, "get");
86    a.z = 5;
87    assert(a.z_val, 5, "set");
88
89    b = Object.create(a);
90    assert(Object.getPrototypeOf(b), a, "create");
91    c = {u:2};
92    /* XXX: refcount bug in 'b' instead of 'a' */
93    Object.setPrototypeOf(a, c);
94    assert(Object.getPrototypeOf(a), c, "setPrototypeOf");
95
96    a = {};
97    assert(a.toString(), "[object Object]", "toString");
98
99    a = {x:1};
100    assert(Object.isExtensible(a), true, "extensible");
101    Object.preventExtensions(a);
102
103    err = false;
104    try {
105        a.y = 2;
106    } catch(e) {
107        err = true;
108    }
109    assert(Object.isExtensible(a), false, "extensible");
110    assert(typeof a.y, "undefined", "extensible");
111    assert(err, true, "extensible");
112}
113
114function test_enum()
115{
116    var a, tab;
117    a = {x:1,
118         "18014398509481984": 1,
119         "9007199254740992": 1,
120         "9007199254740991": 1,
121         "4294967296": 1,
122         "4294967295": 1,
123         y:1,
124         "4294967294": 1,
125         "1": 2};
126    tab = Object.keys(a);
127//    console.log("tab=" + tab.toString());
128    assert(tab, ["1","4294967294","x","18014398509481984","9007199254740992","9007199254740991","4294967296","4294967295","y"], "keys");
129}
130
131function test_array()
132{
133    var a, err;
134
135    a = [1, 2, 3];
136    assert(a.length, 3, "array");
137    assert(a[2], 3, "array1");
138
139    a = new Array(10);
140    assert(a.length, 10, "array2");
141
142    a = new Array(1, 2);
143    assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3");
144
145    a = [1, 2, 3];
146    a.length = 2;
147    assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4");
148
149    a = [];
150    a[1] = 10;
151    a[4] = 3;
152    assert(a.length, 5);
153
154    a = [1,2];
155    a.length = 5;
156    a[4] = 1;
157    a.length = 4;
158    assert(a[4] !== 1, true, "array5");
159
160    a = [1,2];
161    a.push(3,4);
162    assert(a.join(), "1,2,3,4", "join");
163
164    a = [1,2,3,4,5];
165    Object.defineProperty(a, "3", { configurable: false });
166    err = false;
167    try {
168        a.length = 2;
169    } catch(e) {
170        err = true;
171    }
172    assert(err && a.toString() === "1,2,3,4");
173}
174
175function test_string()
176{
177    var a;
178    a = String("abc");
179    assert(a.length, 3, "string");
180    assert(a[1], "b", "string");
181    assert(a.charCodeAt(1), 0x62, "string");
182    assert(String.fromCharCode(65), "A", "string");
183    assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string");
184    assert(a.charAt(1), "b");
185    assert(a.charAt(-1), "");
186    assert(a.charAt(3), "");
187
188    a = "abcd";
189    assert(a.substring(1, 3), "bc", "substring");
190    a = String.fromCharCode(0x20ac);
191    assert(a.charCodeAt(0), 0x20ac, "unicode");
192    assert(a, "€", "unicode");
193    assert(a, "\u20ac", "unicode");
194    assert(a, "\u{20ac}", "unicode");
195    assert("a", "\x61", "unicode");
196
197    a = "\u{10ffff}";
198    assert(a.length, 2, "unicode");
199    assert(a, "\u{dbff}\u{dfff}", "unicode");
200    assert(a.codePointAt(0), 0x10ffff);
201    assert(String.fromCodePoint(0x10ffff), a);
202
203    assert("a".concat("b", "c"), "abc");
204
205    assert("abcabc".indexOf("cab"), 2);
206    assert("abcabc".indexOf("cab2"), -1);
207    assert("abc".indexOf("c"), 2);
208
209    assert("aaa".indexOf("a"), 0);
210    assert("aaa".indexOf("a", NaN), 0);
211    assert("aaa".indexOf("a", -Infinity), 0);
212    assert("aaa".indexOf("a", -1), 0);
213    assert("aaa".indexOf("a", -0), 0);
214    assert("aaa".indexOf("a", 0), 0);
215    assert("aaa".indexOf("a", 1), 1);
216    assert("aaa".indexOf("a", 2), 2);
217    assert("aaa".indexOf("a", 3), -1);
218    assert("aaa".indexOf("a", 4), -1);
219    assert("aaa".indexOf("a", Infinity), -1);
220
221    assert("aaa".indexOf(""), 0);
222    assert("aaa".indexOf("", NaN), 0);
223    assert("aaa".indexOf("", -Infinity), 0);
224    assert("aaa".indexOf("", -1), 0);
225    assert("aaa".indexOf("", -0), 0);
226    assert("aaa".indexOf("", 0), 0);
227    assert("aaa".indexOf("", 1), 1);
228    assert("aaa".indexOf("", 2), 2);
229    assert("aaa".indexOf("", 3), 3);
230    assert("aaa".indexOf("", 4), 3);
231    assert("aaa".indexOf("", Infinity), 3);
232
233    assert("aaa".lastIndexOf("a"), 2);
234    assert("aaa".lastIndexOf("a", NaN), 2);
235    assert("aaa".lastIndexOf("a", -Infinity), 0);
236    assert("aaa".lastIndexOf("a", -1), 0);
237    assert("aaa".lastIndexOf("a", -0), 0);
238    assert("aaa".lastIndexOf("a", 0), 0);
239    assert("aaa".lastIndexOf("a", 1), 1);
240    assert("aaa".lastIndexOf("a", 2), 2);
241    assert("aaa".lastIndexOf("a", 3), 2);
242    assert("aaa".lastIndexOf("a", 4), 2);
243    assert("aaa".lastIndexOf("a", Infinity), 2);
244
245    assert("aaa".lastIndexOf(""), 3);
246    assert("aaa".lastIndexOf("", NaN), 3);
247    assert("aaa".lastIndexOf("", -Infinity), 0);
248    assert("aaa".lastIndexOf("", -1), 0);
249    assert("aaa".lastIndexOf("", -0), 0);
250    assert("aaa".lastIndexOf("", 0), 0);
251    assert("aaa".lastIndexOf("", 1), 1);
252    assert("aaa".lastIndexOf("", 2), 2);
253    assert("aaa".lastIndexOf("", 3), 3);
254    assert("aaa".lastIndexOf("", 4), 3);
255    assert("aaa".lastIndexOf("", Infinity), 3);
256
257    assert("a,b,c".split(","), ["a","b","c"]);
258    assert(",b,c".split(","), ["","b","c"]);
259    assert("a,b,".split(","), ["a","b",""]);
260
261    assert("aaaa".split(), [ "aaaa" ]);
262    assert("aaaa".split(undefined, 0), [ ]);
263    assert("aaaa".split(""), [ "a", "a", "a", "a" ]);
264    assert("aaaa".split("", 0), [ ]);
265    assert("aaaa".split("", 1), [ "a" ]);
266    assert("aaaa".split("", 2), [ "a", "a" ]);
267    assert("aaaa".split("a"), [ "", "", "", "", "" ]);
268    assert("aaaa".split("a", 2), [ "", "" ]);
269    assert("aaaa".split("aa"), [ "", "", "" ]);
270    assert("aaaa".split("aa", 0), [ ]);
271    assert("aaaa".split("aa", 1), [ "" ]);
272    assert("aaaa".split("aa", 2), [ "", "" ]);
273    assert("aaaa".split("aaa"), [ "", "a" ]);
274    assert("aaaa".split("aaaa"), [ "", "" ]);
275    assert("aaaa".split("aaaaa"), [ "aaaa" ]);
276    assert("aaaa".split("aaaaa", 0), [  ]);
277    assert("aaaa".split("aaaaa", 1), [ "aaaa" ]);
278
279    assert(eval('"\0"'), "\0");
280}
281
282function test_math()
283{
284    var a;
285    a = 1.4;
286    assert(Math.floor(a), 1);
287    assert(Math.ceil(a), 2);
288    assert(Math.imul(0x12345678, 123), -1088058456);
289    assert(Math.fround(0.1), 0.10000000149011612);
290    assert(Math.hypot() == 0);
291    assert(Math.hypot(-2) == 2);
292    assert(Math.hypot(3, 4) == 5);
293    assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15);
294}
295
296function test_number()
297{
298    assert(parseInt("123"), 123);
299    assert(parseInt("  123r"), 123);
300    assert(parseInt("0x123"), 0x123);
301    assert(parseInt("0o123"), 0);
302    assert(+"  123   ", 123);
303    assert(+"0b111", 7);
304    assert(+"0o123", 83);
305    assert(parseFloat("0x1234"), 0);
306    assert(parseFloat("Infinity"), Infinity);
307    assert(parseFloat("-Infinity"), -Infinity);
308    assert(parseFloat("123.2"), 123.2);
309    assert(parseFloat("123.2e3"), 123200);
310    assert(Number.isNaN(Number("+")));
311    assert(Number.isNaN(Number("-")));
312    assert(Number.isNaN(Number("\x00a")));
313
314    assert((25).toExponential(0), "3e+1");
315    assert((-25).toExponential(0), "-3e+1");
316    assert((2.5).toPrecision(1), "3");
317    assert((-2.5).toPrecision(1), "-3");
318    assert((1.125).toFixed(2), "1.13");
319    assert((-1.125).toFixed(2), "-1.13");
320}
321
322function test_eval2()
323{
324    var g_call_count = 0;
325    /* force non strict mode for f1 and f2 */
326    var f1 = new Function("eval", "eval(1, 2)");
327    var f2 = new Function("eval", "eval(...[1, 2])");
328    function g(a, b) {
329        assert(a, 1);
330        assert(b, 2);
331        g_call_count++;
332    }
333    f1(g);
334    f2(g);
335    assert(g_call_count, 2);
336}
337
338function test_eval()
339{
340    function f(b) {
341        var x = 1;
342        return eval(b);
343    }
344    var r, a;
345
346    r = eval("1+1;");
347    assert(r, 2, "eval");
348
349    r = eval("var my_var=2; my_var;");
350    assert(r, 2, "eval");
351    assert(typeof my_var, "undefined");
352
353    assert(eval("if (1) 2; else 3;"), 2);
354    assert(eval("if (0) 2; else 3;"), 3);
355
356    assert(f.call(1, "this"), 1);
357
358    a = 2;
359    assert(eval("a"), 2);
360
361    eval("a = 3");
362    assert(a, 3);
363
364    assert(f("arguments.length", 1), 2);
365    assert(f("arguments[1]", 1), 1);
366
367    a = 4;
368    assert(f("a"), 4);
369    f("a=3");
370    assert(a, 3);
371
372    test_eval2();
373}
374
375function test_typed_array()
376{
377    var buffer, a, i;
378
379    a = new Uint8Array(4);
380    assert(a.length, 4);
381    for(i = 0; i < a.length; i++)
382        a[i] = i;
383    assert(a.join(","), "0,1,2,3");
384    a[0] = -1;
385    assert(a[0], 255);
386
387    a = new Int8Array(3);
388    a[0] = 255;
389    assert(a[0], -1);
390
391    a = new Int32Array(3);
392    a[0] = Math.pow(2, 32) - 1;
393    assert(a[0], -1);
394    assert(a.BYTES_PER_ELEMENT, 4);
395
396    a = new Uint8ClampedArray(4);
397    a[0] = -100;
398    a[1] = 1.5;
399    a[2] = 0.5;
400    a[3] = 1233.5;
401    assert(a.toString(), "0,2,0,255");
402
403    buffer = new ArrayBuffer(16);
404    assert(buffer.byteLength, 16);
405    a = new Uint32Array(buffer, 12, 1);
406    assert(a.length, 1);
407    a[0] = -1;
408
409    a = new Uint16Array(buffer, 2);
410    a[0] = -1;
411
412    a = new Float32Array(buffer, 8, 1);
413    a[0] = 1;
414
415    a = new Uint8Array(buffer);
416
417    assert(a.toString(), "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255");
418
419    assert(a.buffer, buffer);
420
421    a = new Uint8Array([1, 2, 3, 4]);
422    assert(a.toString(), "1,2,3,4");
423    a.set([10, 11], 2);
424    assert(a.toString(), "1,2,10,11");
425}
426
427function test_json()
428{
429    var a, s;
430    s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}';
431    a = JSON.parse(s);
432    assert(a.x, 1);
433    assert(a.y, true);
434    assert(a.z, null);
435    assert(JSON.stringify(a), s);
436
437    /* indentation test */
438    assert(JSON.stringify([[{x:1,y:{},z:[]},2,3]],undefined,1),
439`[
440 [
441  {
442   "x": 1,
443   "y": {},
444   "z": []
445  },
446  2,
447  3
448 ]
449]`);
450}
451
452function test_date()
453{
454    var d = new Date(1506098258091), a, s;
455    assert(d.toISOString(), "2017-09-22T16:37:38.091Z");
456    d.setUTCHours(18, 10, 11);
457    assert(d.toISOString(), "2017-09-22T18:10:11.091Z");
458    a = Date.parse(d.toISOString());
459    assert((new Date(a)).toISOString(), d.toISOString());
460    s = new Date("2020-01-01T01:01:01.1Z").toISOString();
461    assert(s ==  "2020-01-01T01:01:01.100Z");
462    s = new Date("2020-01-01T01:01:01.12Z").toISOString();
463    assert(s ==  "2020-01-01T01:01:01.120Z");
464    s = new Date("2020-01-01T01:01:01.123Z").toISOString();
465    assert(s ==  "2020-01-01T01:01:01.123Z");
466    s = new Date("2020-01-01T01:01:01.1234Z").toISOString();
467    assert(s ==  "2020-01-01T01:01:01.123Z");
468    s = new Date("2020-01-01T01:01:01.12345Z").toISOString();
469    assert(s ==  "2020-01-01T01:01:01.123Z");
470    s = new Date("2020-01-01T01:01:01.1235Z").toISOString();
471    assert(s ==  "2020-01-01T01:01:01.124Z");
472    s = new Date("2020-01-01T01:01:01.9999Z").toISOString();
473    assert(s ==  "2020-01-01T01:01:02.000Z");
474}
475
476function test_regexp()
477{
478    var a, str;
479    str = "abbbbbc";
480    a = /(b+)c/.exec(str);
481    assert(a[0], "bbbbbc");
482    assert(a[1], "bbbbb");
483    assert(a.index, 1);
484    assert(a.input, str);
485    a = /(b+)c/.test(str);
486    assert(a, true);
487    assert(/\x61/.exec("a")[0], "a");
488    assert(/\u0061/.exec("a")[0], "a");
489    assert(/\ca/.exec("\x01")[0], "\x01");
490    assert(/\\a/.exec("\\a")[0], "\\a");
491    assert(/\c0/.exec("\\c0")[0], "\\c0");
492
493    a = /(\.(?=com|org)|\/)/.exec("ah.com");
494    assert(a.index === 2 && a[0] === ".");
495
496    a = /(\.(?!com|org)|\/)/.exec("ah.com");
497    assert(a, null);
498
499    a = /(?=(a+))/.exec("baaabac");
500    assert(a.index === 1 && a[0] === "" && a[1] === "aaa");
501
502    a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac");
503    assert(a, ["zaacbbbcac","z","ac","a",,"c"]);
504
505    a = eval("/\0a/");
506    assert(a.toString(), "/\0a/");
507    assert(a.exec("\0a")[0], "\0a");
508
509    assert(/{1a}/.toString(), "/{1a}/");
510    a = /a{1+/.exec("a{11");
511    assert(a, ["a{11"] );
512}
513
514function test_symbol()
515{
516    var a, b, obj, c;
517    a = Symbol("abc");
518    obj = {};
519    obj[a] = 2;
520    assert(obj[a], 2);
521    assert(typeof obj["abc"], "undefined");
522    assert(String(a), "Symbol(abc)");
523    b = Symbol("abc");
524    assert(a == a);
525    assert(a === a);
526    assert(a != b);
527    assert(a !== b);
528
529    b = Symbol.for("abc");
530    c = Symbol.for("abc");
531    assert(b === c);
532    assert(b !== a);
533
534    assert(Symbol.keyFor(b), "abc");
535    assert(Symbol.keyFor(a), undefined);
536
537    a = Symbol("aaa");
538    assert(a.valueOf(), a);
539    assert(a.toString(), "Symbol(aaa)");
540
541    b = Object(a);
542    assert(b.valueOf(), a);
543    assert(b.toString(), "Symbol(aaa)");
544}
545
546function test_map()
547{
548    var a, i, n, tab, o, v;
549    n = 1000;
550    a = new Map();
551    tab = [];
552    for(i = 0; i < n; i++) {
553        v = { };
554        o = { id: i };
555        tab[i] = [o, v];
556        a.set(o, v);
557    }
558
559    assert(a.size, n);
560    for(i = 0; i < n; i++) {
561        assert(a.get(tab[i][0]), tab[i][1]);
562    }
563
564    i = 0;
565    a.forEach(function (v, o) {
566        assert(o, tab[i++][0]);
567        assert(a.has(o));
568        assert(a.delete(o));
569        assert(!a.has(o));
570    });
571
572    assert(a.size, 0);
573}
574
575function test_weak_map()
576{
577    var a, i, n, tab, o, v, n2;
578    a = new WeakMap();
579    n = 10;
580    tab = [];
581    for(i = 0; i < n; i++) {
582        v = { };
583        o = { id: i };
584        tab[i] = [o, v];
585        a.set(o, v);
586    }
587    o = null;
588
589    n2 = n >> 1;
590    for(i = 0; i < n2; i++) {
591        a.delete(tab[i][0]);
592    }
593    for(i = n2; i < n; i++) {
594        tab[i][0] = null; /* should remove the object from the WeakMap too */
595    }
596    /* the WeakMap should be empty here */
597}
598
599function test_generator()
600{
601    function *f() {
602        var ret;
603        yield 1;
604        ret = yield 2;
605        assert(ret, "next_arg");
606        return 3;
607    }
608    function *f2() {
609        yield 1;
610        yield 2;
611        return "ret_val";
612    }
613    function *f1() {
614        var ret = yield *f2();
615        assert(ret, "ret_val");
616        return 3;
617    }
618    var g, v;
619    g = f();
620    v = g.next();
621    assert(v.value === 1 && v.done === false);
622    v = g.next();
623    assert(v.value === 2 && v.done === false);
624    v = g.next("next_arg");
625    assert(v.value === 3 && v.done === true);
626    v = g.next();
627    assert(v.value === undefined && v.done === true);
628
629    g = f1();
630    v = g.next();
631    assert(v.value === 1 && v.done === false);
632    v = g.next();
633    assert(v.value === 2 && v.done === false);
634    v = g.next();
635    assert(v.value === 3 && v.done === true);
636    v = g.next();
637    assert(v.value === undefined && v.done === true);
638}
639
640test();
641test_function();
642test_enum();
643test_array();
644test_string();
645test_math();
646test_number();
647test_eval();
648test_typed_array();
649test_json();
650test_date();
651test_regexp();
652test_symbol();
653test_map();
654test_weak_map();
655test_generator();
656