blob: f788fd43193f78e76de0c228d870968759a4e664 [file] [log] [blame]
/*
* Copyright (C) Igor Sysoev
* Copyright (C) NGINX, Inc.
*/
#include <njs_main.h>
#include "njs_externals_test.h"
#define NJS_HAVE_LARGE_STACK (!NJS_HAVE_ADDRESS_SANITIZER && !NJS_HAVE_MEMORY_SANITIZER)
#ifdef NJS_HAVE_LITTLE_ENDIAN
#define njs_evar(little, big) little
#else
#define njs_evar(little, big) big
#endif
#define njs_declare_sparse_array(nm, sz) \
"var " nm " = Array(" njs_stringify(sz) "); " \
"Object.defineProperty(" nm ", '0'," \
"{writable:true, enumerable:false, configurable:true});" \
"delete " nm "[0];"
#define njs_buffer_byte_map(func, sign, divisor) \
"var buf = Buffer.alloc(6);" \
"[1,2,3,4,5,6].map(byte => {" \
" buf." func "(" sign "(2 ** (byte * 7)) / " \
njs_stringify(divisor) ", 0, byte);" \
" return njs.dump(buf);" \
"})"
typedef struct {
njs_str_t script;
njs_str_t ret;
} njs_unit_test_t;
static njs_unit_test_t njs_test[] =
{
{ njs_str("@"),
njs_str("SyntaxError: Unexpected token \"@\" in 1") },
{ njs_str("}"),
njs_str("SyntaxError: Unexpected token \"}\" in 1") },
{ njs_str("1}"),
njs_str("SyntaxError: Unexpected token \"}\" in 1") },
{ njs_str("/***/1/*\n**/"),
njs_str("1") },
{ njs_str("/***/1// "),
njs_str("1") },
{ njs_str(">"),
njs_str("SyntaxError: Unexpected token \">\" in 1") },
{ njs_str(">>"),
njs_str("SyntaxError: Unexpected token \">>\" in 1") },
{ njs_str(">>>"),
njs_str("SyntaxError: Unexpected token \">>>\" in 1") },
{ njs_str("=="),
njs_str("SyntaxError: Unexpected token \"==\" in 1") },
{ njs_str("?"),
njs_str("SyntaxError: Unexpected token \"?\" in 1") },
/* Variable declarations. */
{ njs_str("var x"),
njs_str("undefined") },
{ njs_str("var x;"),
njs_str("undefined") },
{ njs_str("var x;;"),
njs_str("undefined") },
{ njs_str("var x = 0"),
njs_str("undefined") },
{ njs_str("var x = 0;"),
njs_str("undefined") },
{ njs_str("var x = 0;;"),
njs_str("undefined") },
{ njs_str("var; a"),
njs_str("SyntaxError: Unexpected token \";\" in 1") },
{ njs_str("var + a"),
njs_str("SyntaxError: Unexpected token \"+\" in 1") },
{ njs_str("//\r\n; var + a"),
njs_str("SyntaxError: Unexpected token \"+\" in 2") },
{ njs_str("/*\n*/; var + a"),
njs_str("SyntaxError: Unexpected token \"+\" in 2") },
{ njs_str("var \n a \n = 1; a"),
njs_str("1") },
{ njs_str("var \n a, \n b; b"),
njs_str("undefined") },
{ njs_str("var from = 2; from + 2"),
njs_str("4") },
{ njs_str("var a / ="),
njs_str("SyntaxError: Unexpected token \"/\" in 1") },
{ njs_str("var a = 1; var b; a"),
njs_str("1") },
{ njs_str("a = 1;for(;a;a--)var a; a"),
njs_str("0") },
{ njs_str("if(1)if(0){0?0:0}else\nvar a\nelse\nvar b"),
njs_str("undefined") },
{ njs_str("var a = 1; var a; a"),
njs_str("1") },
{ njs_str("(function (x) {if (x) { var a = 3; return a} else { var a = 4; return a}})(1)"),
njs_str("3") },
{ njs_str("(function (x) {if (x) { var a = 3; return a} else { var a = 4; return a}})(0)"),
njs_str("4") },
{ njs_str("function f(){return 2}; var f; f()"),
njs_str("2") },
{ njs_str("function f(){return 2}; var f = 1; f()"),
njs_str("TypeError: number is not a function") },
{ njs_str("function f(){return 1}; function f(){return 2}; f()"),
njs_str("2") },
{ njs_str("var f = 1; function f() {}; f"),
njs_str("1") },
{ njs_str("var f = 1; function f() {}; f"),
njs_str("1") },
{ njs_str("function f(a) {return function (x) {return a(x)}} f(1)(0)"),
njs_str("TypeError: number is not a function") },
{ njs_str("var x = 0;"
""
"function f1() {"
" function f2() {"
" return x;"
" };"
""
" return f2();"
""
" var x = 1;"
"}"
""
"f1() === undefined"),
njs_str("true") },
{ njs_str("var fn = function fn() {return fn.test}; fn.test = 'test'; fn()"),
njs_str("test") },
{ njs_str("var body;"
"var n = 'outside';"
"var before = function() {return n};"
""
"var func = function n() {"
" var n;"
" body = function() {return n};"
"};"
""
"func();"
""
"[before(), body()]"),
njs_str("outside,") },
{ njs_str("var func = function x(x) {return x}; func()"),
njs_str("undefined") },
#if 0 /* TODO */
{ njs_str("var a; Object.getOwnPropertyDescriptor(this, 'a').value"),
njs_str("undefined") },
#endif
{ njs_str("f() = 1"),
njs_str("ReferenceError: Invalid left-hand side in assignment in 1") },
{ njs_str("f.a() = 1"),
njs_str("ReferenceError: Invalid left-hand side in assignment in 1") },
{ njs_str("++f()"),
njs_str("ReferenceError: Invalid left-hand side in prefix operation in 1") },
{ njs_str("f()++"),
njs_str("ReferenceError: Invalid left-hand side in postfix operation in 1") },
/* Numbers. */
{ njs_str("0"),
njs_str("0") },
{ njs_str("-0"),
njs_str("-0") },
{ njs_str(".0"),
njs_str("0") },
{ njs_str("0.1"),
njs_str("0.1") },
{ njs_str(".9"),
njs_str("0.9") },
{ njs_str("-.0_1"),
njs_str("-0.01") },
{ njs_str("0.000_001"),
njs_str("0.000001") },
{ njs_str("0.00000_123456"),
njs_str("0.00000123456") },
{ njs_str("0.0000001"),
njs_str("1e-7") },
{ njs_str("1.1000000"),
njs_str("1.1") },
{ njs_str("1_0"),
njs_str("10") },
{ njs_str("99_999_999_999_999_999_999"),
njs_str("100000000000000000000") },
{ njs_str("9999999999999999999_9.1_1_1"),
njs_str("100000000000000000000") },
{ njs_str("999999999999999999999"),
njs_str("1e+21") },
{ njs_str("9223372036854775808"),
njs_str("9223372036854776000") },
{ njs_str("18446744073709551616"),
njs_str("18446744073709552000") },
{ njs_str("1.79769313_48623157E+3_0_8"),
njs_str("1.7976931348623157e+308") },
{ njs_str("+1"),
njs_str("1") },
{ njs_str("+1\n"),
njs_str("1") },
{ njs_str("."),
njs_str("SyntaxError: Unexpected token \".\" in 1") },
{ njs_str("0_1"),
njs_str("SyntaxError: Unexpected token \"0_\" in 1") },
{ njs_str("1_"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
{ njs_str("1__0"),
njs_str("SyntaxError: Unexpected token \"__0\" in 1") },
{ njs_str("._1"),
njs_str("SyntaxError: Unexpected token \".\" in 1") },
{ njs_str(".1_"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
{ njs_str("1_.1"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
{ njs_str(".0__1"),
njs_str("SyntaxError: Unexpected token \"__1\" in 1") },
{ njs_str("1e_1"),
njs_str("SyntaxError: Unexpected token \"_1\" in 1") },
{ njs_str("1e-_1"),
njs_str("SyntaxError: Unexpected token \"_1\" in 1") },
{ njs_str("1E1__0"),
njs_str("SyntaxError: Unexpected token \"__0\" in 1") },
{ njs_str("1_e1"),
njs_str("SyntaxError: Unexpected token \"_e1\" in 1") },
{ njs_str("1e1_"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
{ njs_str("-_1"),
njs_str("ReferenceError: \"_1\" is not defined") },
{ njs_str("_1"),
njs_str("ReferenceError: \"_1\" is not defined") },
/* Octal Numbers. */
{ njs_str("0o0"),
njs_str("0") },
{ njs_str("0O10"),
njs_str("8") },
{ njs_str("0o011"),
njs_str("9") },
{ njs_str("-0O7_7_7"),
njs_str("-511") },
{ njs_str("0o"),
njs_str("SyntaxError: Unexpected token \"0o\" in 1") },
{ njs_str("0O778"),
njs_str("SyntaxError: Unexpected token \"0O778\" in 1") },
{ njs_str("0O_7"),
njs_str("SyntaxError: Unexpected token \"_7\" in 1") },
{ njs_str("0o7_"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
{ njs_str("0o7__7"),
njs_str("SyntaxError: Unexpected token \"__7\" in 1") },
/* Legacy Octal Numbers are deprecated. */
{ njs_str("00"),
njs_str("SyntaxError: Unexpected token \"00\" in 1") },
{ njs_str("08"),
njs_str("SyntaxError: Unexpected token \"08\" in 1") },
{ njs_str("09"),
njs_str("SyntaxError: Unexpected token \"09\" in 1") },
{ njs_str("0011"),
njs_str("SyntaxError: Unexpected token \"00\" in 1") },
{ njs_str("0_"),
njs_str("SyntaxError: Unexpected token \"0_\" in 1") },
{ njs_str("0_1"),
njs_str("SyntaxError: Unexpected token \"0_\" in 1") },
{ njs_str("00_1"),
njs_str("SyntaxError: Unexpected token \"00\" in 1") },
/* Binary Numbers. */
{ njs_str("0b0"),
njs_str("0") },
{ njs_str("0B10"),
njs_str("2") },
{ njs_str("0b0_1_0_1"),
njs_str("5") },
{ njs_str("-0B1111_1111"),
njs_str("-255") },
{ njs_str("0b"),
njs_str("SyntaxError: Unexpected token \"0b\" in 1") },
{ njs_str("0B12"),
njs_str("SyntaxError: Unexpected token \"0B12\" in 1") },
{ njs_str("0b_11"),
njs_str("SyntaxError: Unexpected token \"_11\" in 1") },
{ njs_str("0B1__1"),
njs_str("SyntaxError: Unexpected token \"__1\" in 1") },
{ njs_str("0b11_"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
/* Hex Numbers. */
{ njs_str("0x0"),
njs_str("0") },
{ njs_str("-0x1"),
njs_str("-1") },
{ njs_str("0xffFF"),
njs_str("65535") },
{ njs_str("0X00_00_BE_EF"),
njs_str("48879") },
{ njs_str("0x"),
njs_str("SyntaxError: Unexpected token \"0x\" in 1") },
{ njs_str("0xffff."),
njs_str("SyntaxError: Unexpected end of input in 1") },
{ njs_str("0x12g"),
njs_str("SyntaxError: Unexpected token \"g\" in 1") },
{ njs_str("0X_ff"),
njs_str("SyntaxError: Unexpected token \"_ff\" in 1") },
{ njs_str("0xff_"),
njs_str("SyntaxError: Unexpected token \"_\" in 1") },
{ njs_str("0Xf__f"),
njs_str("SyntaxError: Unexpected token \"__f\" in 1") },
{ njs_str(""),
njs_str("undefined") },
{ njs_str("\n"),
njs_str("undefined") },
{ njs_str(";"),
njs_str("undefined") },
{ njs_str("\n +1"),
njs_str("1") },
/* Scientific notation. */
{ njs_str("0e0"),
njs_str("0") },
{ njs_str("0.0e0"),
njs_str("0") },
{ njs_str("1e0"),
njs_str("1") },
{ njs_str("1e1"),
njs_str("10") },
{ njs_str("1.e01"),
njs_str("10") },
{ njs_str("5.7e1"),
njs_str("57") },
{ njs_str("5.7e-1"),
njs_str("0.57") },
{ njs_str("-5.7e-1"),
njs_str("-0.57") },
{ njs_str("1.1e-01"),
njs_str("0.11") },
{ njs_str("5.7e-2"),
njs_str("0.057") },
{ njs_str("1.1e+01"),
njs_str("11") },
{ njs_str("-.01e-01"),
njs_str("-0.001") },
{ njs_str("1e9"),
njs_str("1000000000") },
{ njs_str("1.0e308"),
njs_str("1e+308") },
{ njs_str("0e309"),
njs_str("0") },
{ njs_str("0e-309"),
njs_str("0") },
{ njs_str("1e309"),
njs_str("Infinity") },
{ njs_str("-1e309"),
njs_str("-Infinity") },
{ njs_str("1e"),
njs_str("SyntaxError: Unexpected token \"e\" in 1") },
{ njs_str("1.e"),
njs_str("SyntaxError: Unexpected token \"e\" in 1") },
{ njs_str("1e+"),
njs_str("SyntaxError: Unexpected token \"e\" in 1") },
{ njs_str("1.e-"),
njs_str("SyntaxError: Unexpected token \"e\" in 1") },
{ njs_str("1eZ"),
njs_str("SyntaxError: Unexpected token \"eZ\" in 1") },
{ njs_str(".e1"),
njs_str("SyntaxError: Unexpected token \".\" in 1") },
{ njs_str("Number.prototype.X = function(){return 123;};"
"(1).X()"),
njs_str("123") },
/* Indices. */
{ njs_str("var a = []; a[-1] = 2; a[-1] == a['-1']"),
njs_str("true") },
{ njs_str("var a = []; a[Infinity] = 2; a[Infinity] == a['Infinity']"),
njs_str("true") },
{ njs_str("var a = []; a[NaN] = 2; a[NaN] == a['NaN']"),
njs_str("true") },
#define NJS_NOT_CANONICAL_INDICES "['+0', '-0', '1.', '0.', '0.0', '4294967295', " \
" '4294967296', '-1', '1.1', '9223372036854775808']"
{ njs_str("var a = [1,2]; "
NJS_NOT_CANONICAL_INDICES
".every(v=>(a[v] === undefined))"),
njs_str("true") },
{ njs_str("var a = [1,2]; "
NJS_NOT_CANONICAL_INDICES
".every(v=>{a[v] = 'a'; return a[v] === 'a'})"),
njs_str("true") },
/* Number.toString(radix) method. */
{ njs_str("0..toString(2)"),
njs_str("0") },
{ njs_str("(1234.567).toString(3)"),
njs_str("1200201.120022100021001021021002202") },
{ njs_str("(1234.567).toString(5)"),
njs_str("14414.240414141414141414") },
{ njs_str("(1234.567).toString(17)"),
njs_str("44a.9aeb6faa0da") },
{ njs_str("(1234.567).toString(36)"),
njs_str("ya.kety9sifl") },
{ njs_str("Number(-1.1).toString(36)"),
njs_str("-1.3llllllllm") },
{ njs_str("Math.pow(-2, 1023).toString(2).length"),
njs_str("1025") },
{ njs_str("8.0625.toString(2)"),
njs_str("1000.0001") },
{ njs_str("(1/3).toString(2)"),
njs_str("0.010101010101010101010101010101010101010101010101010101") },
{ njs_str("9999..toString(3)"),
njs_str("111201100") },
{ njs_str("-9999..toString(3)"),
njs_str("-111201100") },
{ njs_str("81985529216486895..toString(16)"),
njs_str("123456789abcdf0") },
{ njs_str("0xffff.toString(16)"),
njs_str("ffff") },
{ njs_str("30520..toString(36)"),
njs_str("njs") },
{ njs_str("Infinity.toString()"),
njs_str("Infinity") },
{ njs_str("Infinity.toString(2)"),
njs_str("Infinity") },
{ njs_str("Infinity.toString(10)"),
njs_str("Infinity") },
{ njs_str("Infinity.toString(NaN)"),
njs_str("RangeError") },
{ njs_str("Infinity.toString({})"),
njs_str("RangeError") },
{ njs_str("Infinity.toString(Infinity)"),
njs_str("RangeError") },
{ njs_str("NaN.toString()"),
njs_str("NaN") },
{ njs_str("NaN.toString(2)"),
njs_str("NaN") },
{ njs_str("NaN.toString(10)"),
njs_str("NaN") },
{ njs_str("NaN.toString(Infinity)"),
njs_str("RangeError") },
{ njs_str("NaN.toString({})"),
njs_str("RangeError") },
{ njs_str("NaN.toString(NaN)"),
njs_str("RangeError") },
{ njs_str("1.2312313132.toString(14)"),
njs_str("1.3346da6d5d455c") },
{ njs_str("7.799999999999999.toString(14)"),
njs_str("7.b2b2b2b2b2b2a5") },
#ifndef NJS_SUNC
{ njs_str("1e20.toString(14)"),
njs_str("33cb3bb449c2a92000") },
{ njs_str("1.7976931348623157E+308.toString(36) == ('1a1e4vngaiqo' + '0'.repeat(187))"),
njs_str("true") },
/* Largest positive double (prev_double(INFINITY)). */
{ njs_str("1.7976931348623157E+308.toString(2) == ('1'.repeat(53) + '0'.repeat(971))"),
njs_str("true") },
{ njs_str("Array(5).fill().map((n, i) => i + 10).map((v)=>(1.2312313132).toString(v))"),
njs_str("1.2312313132,1.25a850416057383,1.293699002749414,1.3010274cab0288,1.3346da6d5d455c") },
{ njs_str("Array(5).fill().map((n, i) => 36 - i).map((v)=>(1e23).toString(v))"),
njs_str("ga894a06abs0000,o5hlsorok4y0000,128fpsprqld20000,1m1s0ajv6cmo0000,2kmg5hv19br00000") },
#endif
/* Number.prototype.toFixed(frac) method. */
{ njs_str("(900.1).toFixed(1)"),
njs_str("900.1") },
{ njs_str("(0).toFixed(0)"),
njs_str("0") },
{ njs_str("(0).toFixed(3)"),
njs_str("0.000") },
{ njs_str("(7).toFixed()"),
njs_str("7") },
{ njs_str("(7).toFixed(0)"),
njs_str("7") },
{ njs_str("(7).toFixed(2)"),
njs_str("7.00") },
{ njs_str("(-900.1).toFixed(3.3)"),
njs_str("-900.100") },
{ njs_str("(900.123).toFixed(5)"),
njs_str("900.12300") },
{ njs_str("(1/3).toFixed(5)"),
njs_str("0.33333") },
{ njs_str("(new Number(1/3)).toFixed(5)"),
njs_str("0.33333") },
{ njs_str("(new Number(1/3)).toFixed(5)"),
njs_str("0.33333") },
{ njs_str("(1/3).toFixed({toString(){return '5'}})"),
njs_str("0.33333") },
{ njs_str("(1/3).toFixed(100)"),
njs_str("0.3333333333333333148296162562473909929394721984863281250000000000000000000000000000000000000000000000") },
{ njs_str("(1.23e+20).toFixed(2)"),
njs_str("123000000000000000000.00") },
{ njs_str("(1.23e-10).toFixed(2)"),
njs_str("0.00") },
{ njs_str("(1.23e-10).toFixed(15)"),
njs_str("0.000000000123000") },
{ njs_str("(1.23e-10).toFixed(100)"),
njs_str("0.0000000001229999999999999888422768137255427361997917046210204716771841049194335937500000000000000000") },
{ njs_str("NaN.toFixed(1)"),
njs_str("NaN") },
#if 0 /* FIXME: bignum support is requred to support frac >= 20 */
{ njs_str("(2 ** -100).toFixed(100)"),
njs_str("0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625") },
#endif
/* Number.prototype.toPrecision(prec) method. */
{ njs_str("Array(4).fill().map((n, i) => i+1).map((v)=>(1/7).toPrecision(v))"),
njs_str("0.1,0.14,0.143,0.1429") },
{ njs_str("Array(4).fill().map((n, i) => i+1).map((v)=>(0).toPrecision(v))"),
njs_str("0,0.0,0.00,0.000") },
{ njs_str("Array(4).fill().map((n, i) => i+1).map((v)=>(1/2).toPrecision(v))"),
njs_str("0.5,0.50,0.500,0.5000") },
{ njs_str("Array(6).fill().map((n, i) => i+2).map((v)=>(1/v).toPrecision(5))"),
njs_str("0.50000,0.33333,0.25000,0.20000,0.16667,0.14286") },
{ njs_str("Array(6).fill().map((n, i) => i+2).map((v)=>(1/(v*100)).toPrecision(5))"),
njs_str("0.0050000,0.0033333,0.0025000,0.0020000,0.0016667,0.0014286") },
{ njs_str("Array(6).fill().map((n, i) => i+1).map((v)=>(10*v/7).toPrecision(5))"),
njs_str("1.4286,2.8571,4.2857,5.7143,7.1429,8.5714") },
{ njs_str("Array(6).fill().map((n, i) => i+1).map((v)=>(v/3).toPrecision(5))"),
njs_str("0.33333,0.66667,1.0000,1.3333,1.6667,2.0000") },
{ njs_str("Array(6).fill().map((n, i) => i+1).map((v)=>((Math.pow(-1,v))*(2*v)/3).toPrecision(5))"),
njs_str("-0.66667,1.3333,-2.0000,2.6667,-3.3333,4.0000") },
{ njs_str("Array(12).fill().map((n, i) => i-3).map((v)=>(2**v).toPrecision(6))"),
njs_str("0.125000,0.250000,0.500000,1.00000,2.00000,4.00000,8.00000,16.0000,32.0000,64.0000,128.000,256.000") },
{ njs_str("Array(5).fill().map((n, i) => i+16).map((v)=>(4.1).toPrecision(v))"),
njs_str("4.100000000000000,4.0999999999999996,4.09999999999999964,4.099999999999999644,4.0999999999999996447") },
{ njs_str("Array(3).fill().map((n, i) => i + 19).map((v)=>(2**(-v)).toPrecision(20))"),
njs_str("0.0000019073486328125000000,9.5367431640625000000e-7,4.7683715820312500000e-7") },
{ njs_str("Array(3).fill().map((n, i) => i + 32).map((v)=>(2**(v)+0.1).toPrecision(10))"),
njs_str("4294967296,8589934592,1.717986918e+10") },
#if 0 /* FIXME: bignum support is requred to support prec >= 20 */
{ njs_str("(1/7).toPrecision(100)"),
njs_str("0.1428571428571428492126926812488818541169166564941406250000000000000000000000000000000000000000000000") },
{ njs_str("(2**128).toPrecision(40)"),
njs_str("340282366920938463463374607431768211456.0") },
#endif
{ njs_str("(2**128).toPrecision(1)"),
njs_str("3e+38") },
{ njs_str("(2**128).toPrecision(2)"),
njs_str("3.4e+38") },
{ njs_str("(2**128).toPrecision(40)"),
njs_str("340282366920938463490000000000000000000.0") },
{ njs_str("(123).toPrecision(0)"),
njs_str("RangeError: precision argument must be between 1 and 100") },
{ njs_str("(123).toPrecision(2.4)"),
njs_str("1.2e+2") },
{ njs_str("(123).toPrecision(101)"),
njs_str("RangeError: precision argument must be between 1 and 100") },
{ njs_str("(2**10000).toPrecision()"),
njs_str("Infinity") },
{ njs_str("(-(2**10000)).toPrecision()"),
njs_str("-Infinity") },
{ njs_str("var v = parseFloat('9'.repeat(98));"
"[98,100].map(p=>v.toPrecision(p).length)"),
njs_str("98,101") },
{ njs_str("(-0).toPrecision(2)"),
njs_str("0.0") },
{ njs_str("NaN.toPrecision()"),
njs_str("NaN") },
{ njs_str("NaN.toPrecision(0)"),
njs_str("NaN") },
{ njs_str("(10**22).toPrecision()"),
njs_str("1e+22") },
{ njs_str("Number.prototype.toPrecision.call('12')"),
njs_str("TypeError: unexpected value type:string") },
{ njs_str("(1000000000000000128).toString()"),
njs_str("1000000000000000100") },
{ njs_str("(1000000000000000128).toFixed(0)"),
njs_str("1000000000000000128") },
{ njs_str("(1e21).toFixed(1)"),
njs_str("1e+21") },
{ njs_str("Number.prototype.toFixed.call({})"),
njs_str("TypeError: unexpected value type:object") },
{ njs_str("(0).toFixed(-1)"),
njs_str("RangeError: digits argument must be between 0 and 100") },
{ njs_str("(0).toFixed(101)"),
njs_str("RangeError: digits argument must be between 0 and 100") },
/* Number.prototype.toExponential(frac) method. */
{ njs_str("Array(3).fill().map((n, i) => i + 1).map((v)=>(0).toExponential(v))"),
njs_str("0.0e+0,0.00e+0,0.000e+0") },
{ njs_str("Array(6).fill().map((n, i) => i + 1).map((v)=>((Math.pow(-1,v))*(2*v)/3).toExponential(5))"),
njs_str("-6.66667e-1,1.33333e+0,-2.00000e+0,2.66667e+0,-3.33333e+0,4.00000e+0") },
{ njs_str("Array(5).fill().map((n, i) => i + 1).map((v)=>((Math.pow(-1,v))*(2*v)/3).toExponential())"),
njs_str("-6.666666666666666e-1,1.3333333333333333e+0,-2e+0,2.6666666666666667e+0,-3.3333333333333337e+0") },
{ njs_str("1.7976931348623157e+308.toExponential()"),
njs_str("1.7976931348623157e+308") },
#if 0 /* FIXME: bignum support is requred to support prec >= 20 */
{ njs_str("(1/7).toExponential(100)"),
njs_str("1.4285714285714284921269268124888185411691665649414062500000000000000000000000000000000000000000000000e-1") },
#endif
{ njs_str("var v = 1.7976931348623157e+308; Number(v.toExponential()) == v"),
njs_str("true") },
{ njs_str("(123).toExponential(-1)"),
njs_str("RangeError: digits argument must be between 0 and 100") },
{ njs_str("(123).toExponential(2.4)"),
njs_str("1.23e+2") },
{ njs_str("(123).toExponential(101)"),
njs_str("RangeError: digits argument must be between 0 and 100") },
{ njs_str("[2**10000,-(2**10000),NaN].map((v)=>v.toExponential())"),
njs_str("Infinity,-Infinity,NaN") },
{ njs_str("[2**10000,-(2**10000),NaN].map((v)=>v.toExponential(1000))"),
njs_str("Infinity,-Infinity,NaN") },
{ njs_str("Number.prototype.toExponential.call('12')"),
njs_str("TypeError: unexpected value type:string") },
/* An object "valueOf/toString" methods. */
{ njs_str("var a = { valueOf: function() { return 1 } }; +a"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; +a"),
njs_str("1") },
{ njs_str("var a = { valueOf: 2,"
" toString: function() { return '1' } }; +a"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return 1 } }; ''+a"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return [] },"
" toString: function() { return '1' } }; +a"),
njs_str("1") },
{ njs_str("var a = { toString: function() { return 'a' } };"
"var b = { toString: function() { return a+'b' } }; '0'+b"),
njs_str("0ab") },
{ njs_str("({valueOf:()=>'4'}) / ({valueOf:()=>2})"),
njs_str("2") },
{ njs_str("({valueOf:()=>{throw 'x'}}) / ({valueOf:()=>{throw 'y'}});"
"var e; try { x/y } catch(ex) {e = ex}; ex"),
njs_str("x") },
{ njs_str("({valueOf:()=>{ try {throw 'x'} catch (ex) {return 6} } }) / 2"),
njs_str("3") },
{ njs_str("({valueOf:()=>2}) / ({valueOf:()=>{throw 'y'}});"
"var e; try { x/y } catch(ex) {e = ex}; ex"),
njs_str("y") },
{ njs_str("({valueOf:()=>'4'}) % ({valueOf:()=>3})"),
njs_str("1") },
{ njs_str("({valueOf:()=>9}) >>> ({valueOf:()=>2})"),
njs_str("2") },
{ njs_str("({valueOf:()=>0x1f}) & ({valueOf:()=>0xf})"),
njs_str("15") },
{ njs_str("({valueOf:()=>0x1f}) ^ ({valueOf:()=>0xf})"),
njs_str("16") },
{ njs_str("({valueOf:()=>0xf}) == ({valueOf:()=>0xf})"),
njs_str("false") },
{ njs_str("var e; try {({valueOf: String.prototype.valueOf}) == 1} "
"catch (ex) { e = ex}; e"),
njs_str("TypeError: unexpected value type:object") },
{ njs_str("({valueOf:()=>0xf}) == 0xf"),
njs_str("true") },
{ njs_str("0xf == ({valueOf:()=>0xf})"),
njs_str("true") },
{ njs_str("({valueOf:()=>'0xf'}) == 0xf"),
njs_str("true") },
{ njs_str("0xf == ({valueOf:()=>'0xf'})"),
njs_str("true") },
{ njs_str("({valueOf:()=>0xf}) == '0xf'"),
njs_str("true") },
{ njs_str("'0xf' == ({valueOf:()=>0xf})"),
njs_str("true") },
/**/
{ njs_str("1 + undefined"),
njs_str("NaN") },
{ njs_str("1 + ''"),
njs_str("1") },
{ njs_str("0xA + ''"),
njs_str("10") },
{ njs_str("undefined + undefined"),
njs_str("NaN") },
{ njs_str("var undefined"),
njs_str("undefined") },
{ njs_str("1.2 + 5.7"),
njs_str("6.9") },
{ njs_str("0xf + 1"),
njs_str("16") },
{ njs_str("1 + 1 + '2' + 1 + 1"),
njs_str("2211") },
{ njs_str("'gg' + -0"),
njs_str("gg0") },
{ njs_str("1.2 - '5.7'"),
njs_str("-4.5") },
{ njs_str("1.2 + -'5.7'"),
njs_str("-4.5") },
{ njs_str("1.2 - '-5.7'"),
njs_str("6.9") },
{ njs_str("5 - ' \t 12 \t'"),
njs_str("-7") },
{ njs_str("5 - '12zz'"),
njs_str("NaN") },
{ njs_str("5 - '0x2'"),
njs_str("3") },
{ njs_str("5 - '-0x2'"),
njs_str("7") },
{ njs_str("5 - '\t 0x2 \t'"),
njs_str("3") },
{ njs_str("5 - '\t\\u000c0x2 \t'"),
njs_str("3") },
{ njs_str("5 - '0x2 z'"),
njs_str("NaN") },
{ njs_str("12 - '5.7e1'"),
njs_str("-45") },
{ njs_str("12 - '5.e1'"),
njs_str("-38") },
{ njs_str("12 - '5.7e+01'"),
njs_str("-45") },
{ njs_str("12 - '5.7e-01'"),
njs_str("11.43") },
{ njs_str("12 - ' 5.7e1 '"),
njs_str("-45") },
{ njs_str("12 - '5.7e'"),
njs_str("NaN") },
{ njs_str("12 - '5.7e+'"),
njs_str("NaN") },
{ njs_str("12 - '5.7e-'"),
njs_str("NaN") },
{ njs_str("12 - ' 5.7e1 z'"),
njs_str("NaN") },
{ njs_str("5 - '0x'"),
njs_str("NaN") },
{ njs_str("1 + +'3'"),
njs_str("4") },
{ njs_str("1 - undefined"),
njs_str("NaN") },
{ njs_str("1 - ''"),
njs_str("1") },
{ njs_str("undefined - undefined"),
njs_str("NaN") },
/* String.toString() method. */
{ njs_str("'A'.toString()"),
njs_str("A") },
{ njs_str("'A'.toBytes().toString('latin1')"),
njs_str("TypeError: Unknown encoding: \"latin1\"") },
{ njs_str("'ABCD'.toBytes().toString('hex')"),
njs_str("41424344") },
{ njs_str("'\\x00\\xAA\\xBB\\xFF'.toBytes().toString('hex')"),
njs_str("00aabbff") },
{ njs_str("'\\x00\\xAA\\xBB\\xFF'.toBytes().toString('base64')"),
njs_str("AKq7/w==") },
{ njs_str("'ABCD'.toBytes().toString('base64')"),
njs_str("QUJDRA==") },
{ njs_str("'ABC'.toBytes().toString('base64')"),
njs_str("QUJD") },
{ njs_str("'AB'.toBytes().toString('base64')"),
njs_str("QUI=") },
{ njs_str("'A'.toBytes().toString('base64')"),
njs_str("QQ==") },
{ njs_str("''.toBytes().toString('base64')"),
njs_str("") },
{ njs_str("'\\x00\\xAA\\xBB\\xFF'.toBytes().toString('base64url')"),
njs_str("AKq7_w") },
{ njs_str("'ABCD'.toBytes().toString('base64url')"),
njs_str("QUJDRA") },
{ njs_str("'ABC'.toBytes().toString('base64url')"),
njs_str("QUJD") },
{ njs_str("'AB'.toBytes().toString('base64url')"),
njs_str("QUI") },
{ njs_str("'A'.toBytes().toString('base64url')"),
njs_str("QQ") },
{ njs_str("''.toBytes().toString('base64url')"),
njs_str("") },
/* Assignment. */
{ njs_str("var a, b = (a = [2]) * (3 * 4); a +' '+ b"),
njs_str("2 24") },
{ njs_str("var a = 1; var b = a += 1; b"),
njs_str("2") },
{ njs_str("var a = 1; var b = a -= 1; b"),
njs_str("0") },
{ njs_str("var a = 1; var b = a <<= 1; b"),
njs_str("2") },
/* 3 address operation and side effect. */
{ njs_str("var a = 1; function f(x) { a = x; return 2 }; a+f(5)+' '+a"),
njs_str("3 5") },
{ njs_str("var a = 1; function f(x) { a = x; return 2 }; a += f(5)"),
njs_str("3") },
{ njs_str("var x; x in (x = 1, [1, 2, 3])"),
njs_str("false") },
/* Exponentiation. */
{ njs_str("2 ** 3 ** 2"),
njs_str("512") },
{ njs_str("2 ** (3 ** 2)"),
njs_str("512") },
{ njs_str("(2 ** 3) ** 2"),
njs_str("64") },
{ njs_str("3 ** 2 - 9"),
njs_str("0") },
{ njs_str("-9 + 3 ** 2"),
njs_str("0") },
{ njs_str("-3 ** 2"),
njs_str("SyntaxError: Either left-hand side or entire exponentiation "
"must be parenthesized in 1") },
{ njs_str("-(3) ** 2"),
njs_str("SyntaxError: Either left-hand side or entire exponentiation "
"must be parenthesized in 1") },
{ njs_str("-(3 ** 2)"),
njs_str("-9") },
{ njs_str("(-3) ** 2"),
njs_str("9") },
{ njs_str("1 ** NaN"),
njs_str("NaN") },
{ njs_str("'a' ** -0"),
njs_str("1") },
{ njs_str("1.1 ** Infinity"),
njs_str("Infinity") },
{ njs_str("(-1.1) ** -Infinity"),
njs_str("0") },
{ njs_str("(-1) ** Infinity"),
njs_str("NaN") },
{ njs_str("1 ** -Infinity"),
njs_str("NaN") },
{ njs_str("(-0.9) ** Infinity"),
njs_str("0") },
{ njs_str("0.9 ** -Infinity"),
njs_str("Infinity") },
{ njs_str("'Infinity' ** 0.1"),
njs_str("Infinity") },
{ njs_str("Infinity ** '-0.1'"),
njs_str("0") },
{ njs_str("(-Infinity) ** 3"),
njs_str("-Infinity") },
{ njs_str("'-Infinity' ** '3.1'"),
njs_str("Infinity") },
{ njs_str("(-Infinity) ** '-3'"),
njs_str("-0") },
{ njs_str("'-Infinity' ** -2"),
njs_str("0") },
{ njs_str("'0' ** 0.1"),
njs_str("0") },
#ifndef __NetBSD__ /* NetBSD 7: pow(0, negative) == -Infinity. */
{ njs_str("0 ** '-0.1'"),
njs_str("Infinity") },
#endif
{ njs_str("(-0) ** 3"),
njs_str("-0") },
{ njs_str("'-0' ** '3.1'"),
njs_str("0") },
{ njs_str("(-0) ** '-3'"),
njs_str("-Infinity") },
#ifndef __NetBSD__ /* NetBSD 7: pow(0, negative) == -Infinity. */
{ njs_str("'-0' ** -2"),
njs_str("Infinity") },
#endif
{ njs_str("(-3) ** 0.1"),
njs_str("NaN") },
{ njs_str("var a = 0.1; a **= -2"),
njs_str("99.99999999999999") },
{ njs_str("var a = 1; a **= NaN"),
njs_str("NaN") },
{ njs_str("var a = 'a'; a **= -0"),
njs_str("1") },
{ njs_str("var a = 1.1; a **= Infinity"),
njs_str("Infinity") },
{ njs_str("var a = -1.1; a **= -Infinity"),
njs_str("0") },
{ njs_str("var a = -1; a **= Infinity"),
njs_str("NaN") },
{ njs_str("var a = 1; a **= -Infinity"),
njs_str("NaN") },
{ njs_str("var a = -0.9; a **= Infinity"),
njs_str("0") },
{ njs_str("var a = 0.9; a **= -Infinity"),
njs_str("Infinity") },
{ njs_str("var a = 'Infinity'; a **= 0.1"),
njs_str("Infinity") },
{ njs_str("var a = Infinity; a **= '-0.1'"),
njs_str("0") },
{ njs_str("var a = -Infinity; a **= 3"),
njs_str("-Infinity") },
{ njs_str("var a = '-Infinity'; a **= '3.1'"),
njs_str("Infinity") },
{ njs_str("var a = -Infinity; a **= '-3'"),
njs_str("-0") },
{ njs_str("var a = '-Infinity'; a **= -2"),
njs_str("0") },
{ njs_str("var a = '0'; a **= 0.1"),
njs_str("0") },
#ifndef __NetBSD__ /* NetBSD 7: pow(0, negative) == -Infinity. */
{ njs_str("var a = 0; a **= '-0.1'"),
njs_str("Infinity") },
#endif
{ njs_str("var a = -0; a **= 3"),
njs_str("-0") },
{ njs_str("var a = '-0'; a **= '3.1'"),
njs_str("0") },
{ njs_str("var a = -0; a **= '-3'"),
njs_str("-Infinity") },
#ifndef __NetBSD__ /* NetBSD 7: pow(0, negative) == -Infinity. */
{ njs_str("var a = '-0'; a **= -2"),
njs_str("Infinity") },
#endif
{ njs_str("var a = -3; a **= 0.1"),
njs_str("NaN") },
/**/
{ njs_str("12 | 6"),
njs_str("14") },
{ njs_str("12 | 'abc'"),
njs_str("12") },
{ njs_str("-1 | 0"),
njs_str("-1") },
{ njs_str("-2147483648 | 0"),
njs_str("-2147483648") },
{ njs_str("1024.9 | 0"),
njs_str("1024") },
{ njs_str("-1024.9 | 0"),
njs_str("-1024") },
{ njs_str("9007199254740991 | 0"),
njs_str("-1") },
{ njs_str("9007199254740992 | 0"),
njs_str("0") },
{ njs_str("9007199254740993 | 0"),
njs_str("0") },
#if 0
{ njs_str("9223372036854775808 | 0"),
njs_str("0") },
#endif
{ njs_str("9223372036854777856 | 0"),
njs_str("2048") },
{ njs_str("-9223372036854777856 | 0"),
njs_str("-2048") },
{ njs_str("NaN | 0"),
njs_str("0") },
{ njs_str("-NaN | 0"),
njs_str("0") },
{ njs_str("Infinity | 0"),
njs_str("0") },
{ njs_str("-Infinity | 0"),
njs_str("0") },
{ njs_str("+0 | 0"),
njs_str("0") },
{ njs_str("-0 | 0"),
njs_str("0") },
{ njs_str("32.5 << 2.4"),
njs_str("128") },
{ njs_str("32.5 << 'abc'"),
njs_str("32") },
{ njs_str("'abc' << 2"),
njs_str("0") },
{ njs_str("-1 << 0"),
njs_str("-1") },
{ njs_str("-1 << -1"),
njs_str("-2147483648") },
{ njs_str("-2147483648 << 0"),
njs_str("-2147483648") },
#if 0
{ njs_str("9223372036854775808 << 0"),
njs_str("0") },
#endif
{ njs_str("9223372036854777856 << 0"),
njs_str("2048") },
{ njs_str("-9223372036854777856 << 0"),
njs_str("-2048") },
{ njs_str("NaN << 0"),
njs_str("0") },
{ njs_str("32.5 >> 2.4"),
njs_str("8") },
{ njs_str("-1 >> 30"),
njs_str("-1") },
{ njs_str("'abc' >> 2"),
njs_str("0") },
{ njs_str("-1 >> 0"),
njs_str("-1") },
{ njs_str("-1 >> -1"),
njs_str("-1") },
{ njs_str("-2147483648 >> 0"),
njs_str("-2147483648") },
{ njs_str("-2147483648 >> -1"),
njs_str("-1") },
#if 0
{ njs_str("9223372036854775808 >> 0"),
njs_str("0") },
#endif
{ njs_str("9223372036854777856 >> 0"),
njs_str("2048") },
{ njs_str("-9223372036854777856 >> 0"),
njs_str("-2048") },
{ njs_str("NaN >> 0"),
njs_str("0") },
{ njs_str("-1 >>> 30"),
njs_str("3") },
{ njs_str("NaN >>> 1"),
njs_str("0") },
#if 0
{ njs_str("9223372036854775808 >>> 1"),
njs_str("0") },
#endif
{ njs_str("-1 >>> 0"),
njs_str("4294967295") },
{ njs_str("-1 >>> -1"),
njs_str("1") },
{ njs_str("-2147483648 >>> 0"),
njs_str("2147483648") },
{ njs_str("-2147483648 >>> -1"),
njs_str("1") },
#if 0
{ njs_str("9223372036854775808 >>> 0"),
njs_str("0") },
#endif
{ njs_str("9223372036854777856 >>> 0"),
njs_str("2048") },
{ njs_str("-9223372036854777856 >>> 0"),
njs_str("4294965248") },
{ njs_str("NaN >>> 0"),
njs_str("0") },
{ njs_str("!2"),
njs_str("false") },
/**/
{ njs_str("var a = { valueOf: function() { return 1 } }; ~a"),
njs_str("-2") },
{ njs_str("var a = { valueOf: function() { return '1' } }; ~a"),
njs_str("-2") },
/**/
{ njs_str("1 || 2"),
njs_str("1") },
{ njs_str("var a = 1; 1 || (a = 2); a"),
njs_str("1") },
{ njs_str("var x; x = 0 || x; x"),
njs_str("undefined") },
{ njs_str("var x; x = 1 && x; x"),
njs_str("undefined") },
{ njs_str("1 || 2 || 3"),
njs_str("1") },
{ njs_str("1 || (2 + 2) || 3"),
njs_str("1") },
{ njs_str("1 && 2"),
njs_str("2") },
{ njs_str("1 && 2 && 3"),
njs_str("3") },
{ njs_str("var a = 1; 0 && (a = 2); a"),
njs_str("1") },
{ njs_str("false && true || true"),
njs_str("true") },
{ njs_str("false && (true || true)"),
njs_str("false") },
{ njs_str("true && (null ?? true)"),
njs_str("true") },
{ njs_str("(null || undefined) ?? (true && true)"),
njs_str("true") },
{ njs_str("undefined ?? null ?? false ?? true"),
njs_str("false") },
{ njs_str("1 && 1 ?? true"),
njs_str("SyntaxError: Unexpected token \"??\" in 1") },
{ njs_str("null ?? 0 || 1"),
njs_str("SyntaxError: Unexpected token \"||\" in 1") },
{ njs_str("var a = true; a = -~!a"),
njs_str("1") },
{ njs_str("12 & 6"),
njs_str("4") },
{ njs_str("-1 & 65536"),
njs_str("65536") },
{ njs_str("-2147483648 & 65536"),
njs_str("0") },
#if 0
{ njs_str("9223372036854775808 & 65536"),
njs_str("0") },
#endif
{ njs_str("NaN & 65536"),
njs_str("0") },
{ njs_str("12 ^ 6"),
njs_str("10") },
{ njs_str("-1 ^ 65536"),
njs_str("-65537") },
{ njs_str("-2147483648 ^ 65536"),
njs_str("-2147418112") },
#if 0
{ njs_str("9223372036854775808 ^ 65536"),
njs_str("65536") },
#endif
{ njs_str("NaN ^ 65536"),
njs_str("65536") },
{ njs_str("var x = '1'; +x + 2"),
njs_str("3") },
/* Weird things. */
{ njs_str("'3' -+-+-+ '1' + '1' / '3' * '6' + '2'"),
njs_str("42") },
{ njs_str("((+!![])+(+!![])+(+!![])+(+!![])+[])+((+!![])+(+!![])+[])"),
njs_str("42") },
{ njs_str("1+[[]+[]]-[]+[[]-[]]-1"),
njs_str("9") },
{ njs_str("[[]+[]]-[]+[[]-[]]"),
njs_str("00") },
{ njs_str("!--[][1]"),
njs_str("true") },
{ njs_str("[].concat[1,2,3]"),
njs_str("undefined") },
/**/
{ njs_str("'true' == true"),
njs_str("false") },
{ njs_str("null == false"),
njs_str("false") },
{ njs_str("0 == null"),
njs_str("false") },
{ njs_str("!null"),
njs_str("true") },
{ njs_str("0 === -0"),
njs_str("true") },
{ njs_str("1/-0"),
njs_str("-Infinity") },
{ njs_str("1/0 === 1/-0"),
njs_str("false") },
{ njs_str("1 == true"),
njs_str("true") },
{ njs_str("NaN === NaN"),
njs_str("false") },
{ njs_str("NaN !== NaN"),
njs_str("true") },
{ njs_str("NaN == NaN"),
njs_str("false") },
{ njs_str("NaN != NaN"),
njs_str("true") },
{ njs_str("NaN == false"),
njs_str("false") },
{ njs_str("Infinity == Infinity"),
njs_str("true") },
{ njs_str("-Infinity == -Infinity"),
njs_str("true") },
{ njs_str("-Infinity < Infinity"),
njs_str("true") },
{ njs_str("Infinity - Infinity"),
njs_str("NaN") },
{ njs_str("Infinity - -Infinity"),
njs_str("Infinity") },
{ njs_str("undefined == 0"),
njs_str("false") },
{ njs_str("undefined == null"),
njs_str("true") },
{ njs_str("'1' == 1"),
njs_str("true") },
{ njs_str("'1a' == '1'"),
njs_str("false") },
{ njs_str("'abc' == 'abc'"),
njs_str("true") },
{ njs_str("'abc' < 'abcde'"),
njs_str("true") },
{ njs_str("0 == ''"),
njs_str("true") },
{ njs_str("0 == ' '"),
njs_str("true") },
{ njs_str("0 == ' '"),
njs_str("true") },
{ njs_str("0 == '0'"),
njs_str("true") },
{ njs_str("0 == ' 0 '"),
njs_str("true") },
{ njs_str("0 == '000'"),
njs_str("true") },
{ njs_str("'0' == ''"),
njs_str("false") },
{ njs_str("1 < 2"),
njs_str("true") },
{ njs_str("NaN < NaN"),
njs_str("false") },
{ njs_str("NaN > NaN"),
njs_str("false") },
{ njs_str("undefined < 1"),
njs_str("false") },
{ njs_str("[] == false"),
njs_str("true") },
{ njs_str("[0] == false"),
njs_str("true") },
{ njs_str("[0,0] == false"),
njs_str("false") },
{ njs_str("({}) == false"),
njs_str("false") },
{ njs_str("new Number(1) == new String('1')"),
njs_str("false") },
{ njs_str("var a = Object; a == Object"),
njs_str("true") },
{ njs_str("'1' == new Number(1)"),
njs_str("true") },
{ njs_str("new Number(null) + ''"),
njs_str("0") },
{ njs_str("new String('abc') == 'abc'"),
njs_str("true") },
{ njs_str("false == new String('0')"),
njs_str("true") },
{ njs_str("var a = { valueOf: function() { return 5 } }; a == 5"),
njs_str("true") },
{ njs_str("var a = { valueOf: function() { return '5' } }; a == 5"),
njs_str("true") },
{ njs_str("var a = { valueOf: function() { return '5' } }; a == '5'"),
njs_str("true") },
{ njs_str("var a = { valueOf: function() { return 5 } }; a == '5'"),
njs_str("true") },
{ njs_str("var a = { toString: function() { return true } }; '1' == a"),
njs_str("true") },
{ njs_str("var a = { valueOf: function() { return 'b' },"
" toString: function() { return 'a' } }; a == 'a'"),
njs_str("false") },
/* Comparisions. */
{ njs_str("1 < 2"),
njs_str("true") },
{ njs_str("1 < 1"),
njs_str("false") },
{ njs_str("1 <= 1"),
njs_str("true") },
{ njs_str("1 <= 2"),
njs_str("true") },
{ njs_str("2 > 1"),
njs_str("true") },
{ njs_str("1 > 2"),
njs_str("false") },
{ njs_str("1 > 1"),
njs_str("false") },
{ njs_str("1 >= 1"),
njs_str("true") },
{ njs_str("2 >= 1"),
njs_str("true") },
{ njs_str("1 >= 2"),
njs_str("false") },
/**/
{ njs_str("null === null"),
njs_str("true") },
{ njs_str("null !== null"),
njs_str("false") },
{ njs_str("null == null"),
njs_str("true") },
{ njs_str("null != null"),
njs_str("false") },
{ njs_str("null < null"),
njs_str("false") },
{ njs_str("null > null"),
njs_str("false") },
{ njs_str("null <= null"),
njs_str("true") },
{ njs_str("null >= null"),
njs_str("true") },
/**/
{ njs_str("null === undefined"),
njs_str("false") },
{ njs_str("null !== undefined"),
njs_str("true") },
{ njs_str("null == undefined"),
njs_str("true") },
{ njs_str("null != undefined"),
njs_str("false") },
{ njs_str("null < undefined"),
njs_str("false") },
{ njs_str("null > undefined"),
njs_str("false") },
{ njs_str("null <= undefined"),
njs_str("false") },
{ njs_str("null >= undefined"),
njs_str("false") },
/**/
{ njs_str("null === false"),
njs_str("false") },
{ njs_str("null !== false"),
njs_str("true") },
{ njs_str("null == false"),
njs_str("false") },
{ njs_str("null != false"),
njs_str("true") },
{ njs_str("null < false"),
njs_str("false") },
{ njs_str("null > false"),
njs_str("false") },
{ njs_str("null <= false"),
njs_str("true") },
{ njs_str("null >= false"),
njs_str("true") },
/**/
{ njs_str("null === true"),
njs_str("false") },
{ njs_str("null !== true"),
njs_str("true") },
{ njs_str("null == true"),
njs_str("false") },
{ njs_str("null != true"),
njs_str("true") },
{ njs_str("null < true"),
njs_str("true") },
{ njs_str("null > true"),
njs_str("false") },
{ njs_str("null <= true"),
njs_str("true") },
{ njs_str("null >= true"),
njs_str("false") },
/**/
{ njs_str("Infinity === Infinity"),
njs_str("true") },
{ njs_str("Infinity !== Infinity"),
njs_str("false") },
{ njs_str("Infinity == Infinity"),
njs_str("true") },
{ njs_str("Infinity != Infinity"),
njs_str("false") },
{ njs_str("Infinity < Infinity"),
njs_str("false") },
{ njs_str("Infinity > Infinity"),
njs_str("false") },
{ njs_str("Infinity <= Infinity"),
njs_str("true") },
{ njs_str("Infinity >= Infinity"),
njs_str("true") },
/**/
{ njs_str("-Infinity === Infinity"),
njs_str("false") },
{ njs_str("-Infinity !== Infinity"),
njs_str("true") },
{ njs_str("-Infinity == Infinity"),
njs_str("false") },
{ njs_str("-Infinity != Infinity"),
njs_str("true") },
{ njs_str("-Infinity < Infinity"),
njs_str("true") },
{ njs_str("-Infinity > Infinity"),
njs_str("false") },
{ njs_str("-Infinity <= Infinity"),
njs_str("true") },
{ njs_str("-Infinity >= Infinity"),
njs_str("false") },
{ njs_str("Boolean(Infinity)"),
njs_str("true") },
{ njs_str("!Infinity === false"),
njs_str("true") },
{ njs_str("var Infinity"),
njs_str("undefined") },
#if 0 /* ES5FIX */
{ njs_str("Infinity = 1"),
njs_str("TypeError: Cannot assign to read-only property "Infinity" of object") },
#endif
/**/
{ njs_str("NaN === NaN"),
njs_str("false") },
{ njs_str("NaN !== NaN"),
njs_str("true") },
{ njs_str("NaN == NaN"),
njs_str("false") },
{ njs_str("NaN != NaN"),
njs_str("true") },
{ njs_str("NaN < NaN"),
njs_str("false") },
{ njs_str("NaN > NaN"),
njs_str("false") },
{ njs_str("NaN >= NaN"),
njs_str("false") },
{ njs_str("NaN <= NaN"),
njs_str("false") },
{ njs_str("var NaN"),
njs_str("undefined") },
#if 0 /* ES5FIX */
{ njs_str("NaN = 1"),
njs_str("TypeError: Cannot assign to read-only property "NaN" of object") },
#endif
/**/
{ njs_str("null < 0"),
njs_str("false") },
{ njs_str("null < 1"),
njs_str("true") },
{ njs_str("null < NaN"),
njs_str("false") },
{ njs_str("null < -Infinity"),
njs_str("false") },
{ njs_str("null < Infinity"),
njs_str("true") },
{ njs_str("null < 'null'"),
njs_str("false") },
{ njs_str("null < '1'"),
njs_str("true") },
{ njs_str("null < [1]"),
njs_str("true") },
{ njs_str("null < ({})"),
njs_str("false") },
{ njs_str("var a = { valueOf: function() { return 1 } }; null < a"),
njs_str("true") },
{ njs_str("var a = { valueOf: function() { return 'null' } };null < a"),
njs_str("false") },
{ njs_str("var a = { valueOf: function() { return '1' } }; null < a"),
njs_str("true") },
{ njs_str("1 < {valueOf: ()=>{throw 'x'}}"),
njs_str("x") },
{ njs_str("({valueOf: ()=>{throw 'x'}}) <= ({valueOf:()=>{throw 'y'}})"),
njs_str("x") },
{ njs_str("({valueOf:()=>{throw 'x'}}) > ({valueOf:()=>{throw 'y'}})"),
njs_str("x") },
/**/
{ njs_str("undefined == undefined"),
njs_str("true") },
{ njs_str("undefined != undefined"),
njs_str("false") },
{ njs_str("undefined === undefined"),
njs_str("true") },
{ njs_str("undefined !== undefined"),
njs_str("false") },
{ njs_str("undefined < undefined"),
njs_str("false") },
{ njs_str("undefined < null"),
njs_str("false") },
{ njs_str("undefined < false"),
njs_str("false") },
{ njs_str("undefined < true"),
njs_str("false") },
{ njs_str("undefined < 0"),
njs_str("false") },
{ njs_str("undefined < 1"),
njs_str("false") },
{ njs_str("undefined < NaN"),
njs_str("false") },
{ njs_str("undefined < -Infinity"),
njs_str("false") },
{ njs_str("undefined < Infinity"),
njs_str("false") },
{ njs_str("undefined < 'undefined'"),
njs_str("false") },
{ njs_str("undefined < '1'"),
njs_str("false") },
{ njs_str("undefined < [1]"),
njs_str("false") },
{ njs_str("undefined < ({})"),
njs_str("false") },
{ njs_str("var a = { valueOf: function() { return 1 } }; undefined < a"),
njs_str("false") },
{ njs_str("var a = { valueOf: function() { return 'undefined' } };"
"undefined < a"),
njs_str("false") },
{ njs_str("var a = { valueOf: function() { return '1' } };"
"undefined < a"),
njs_str("false") },
/**/
{ njs_str("false < 1"),
njs_str("true") },
{ njs_str("true < 1"),
njs_str("false") },
{ njs_str("-1 < 1"),
njs_str("true") },
{ njs_str("-1 < '1'"),
njs_str("true") },
{ njs_str("NaN < NaN"),
njs_str("false") },
{ njs_str("-Infinity < Infinity"),
njs_str("true") },
{ njs_str("Infinity < -Infinity"),
njs_str("false") },
{ njs_str("1 < 'abc'"),
njs_str("false") },
/**/
{ njs_str("[] === []"),
njs_str("false") },
{ njs_str("[] !== []"),
njs_str("true") },
{ njs_str("[] == []"),
njs_str("false") },
{ njs_str("[] != []"),
njs_str("true") },
{ njs_str("[] < []"),
njs_str("false") },
{ njs_str("[] > []"),
njs_str("false") },
{ njs_str("[] >= []"),
njs_str("true") },
{ njs_str("[] <= []"),
njs_str("true") },
/**/
{ njs_str("({}) === ({})"),
njs_str("false") },
{ njs_str("({}) !== ({})"),
njs_str("true") },
{ njs_str("({}) == ({})"),
njs_str("false") },
{ njs_str("({}) != ({})"),
njs_str("true") },
{ njs_str("({}) > ({})"),
njs_str("false") },
{ njs_str("({}) <= ({})"),
njs_str("true") },
{ njs_str("({}) >= ({})"),
njs_str("true") },
/**/
{ njs_str("[0] == ({})"),
njs_str("false") },
{ njs_str("[0] != ({})"),
njs_str("true") },
{ njs_str("[0] <= ({})"),
njs_str("true") },
{ njs_str("[0] >= ({})"),
njs_str("false") },
/**/
{ njs_str("new String('1') > new Number(1)"),
njs_str("false") },
{ njs_str("new Boolean(true) > '1'"),
njs_str("false") },
{ njs_str("'0' >= new Number(1)"),
njs_str("false") },
{ njs_str("'1' >= new Number(1)"),
njs_str("true") },
{ njs_str("new String('1') < new Number(1)"),
njs_str("false") },
{ njs_str("new Boolean(true) < '1'"),
njs_str("false") },
{ njs_str("new String('1') <= new Number(1)"),
njs_str("true") },
{ njs_str("new Boolean(true) <= '1'"),
njs_str("true") },
{ njs_str("'-1' < {valueOf: function() {return -2}}"),
njs_str("false") },
{ njs_str("new 0[isNaN]"),
njs_str("TypeError: (intermediate value)[\"[object Function]\"] is not a function") },
{ njs_str("new 0[undefined]"),
njs_str("TypeError: (intermediate value)[\"undefined\"] is not a function") },
/**/
{ njs_str("var a; a = 1 ? 2 : 3"),
njs_str("2") },
{ njs_str("var a; a = 1 ? 2 : 3 ? 4 : 5"),
njs_str("2") },
{ njs_str("var a; a = 0 ? 2 : 3 ? 4 : 5"),
njs_str("4") },
{ njs_str("0 ? 2 ? 3 : 4 : 5"),
njs_str("5") },
{ njs_str("1 ? 2 ? 3 : 4 : 5"),
njs_str("3") },
{ njs_str("1 ? 0 ? 3 : 4 : 5"),
njs_str("4") },
{ njs_str("(1 ? 0 : 3) ? 4 : 5"),
njs_str("5") },
{ njs_str("var a; a = (1 + 2) ? 2 ? 3 + 4 : 5 : 6"),
njs_str("7") },
{ njs_str("var a; a = (1 ? 2 : 3) + 4"),
njs_str("6") },
{ njs_str("var a, b; a = 1 ? b = 2 + 4 : b = 3"),
njs_str("6") },
{ njs_str("var a; a = 1 ? [1,2] : []"),
njs_str("1,2") },
/**/
{ njs_str("var a = { valueOf: function() { return 1 } }; +a"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; +a"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return 1 } }; -a"),
njs_str("-1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; -a"),
njs_str("-1") },
/* Increment. */
{ njs_str("var a = 1; ++a"),
njs_str("2") },
{ njs_str("var a = '1'; ++a"),
njs_str("2") },
{ njs_str("var a = [1]; ++a"),
njs_str("2") },
{ njs_str("var a = {}; ++a"),
njs_str("NaN") },
{ njs_str("var a = [1,2,3]; var b = 1; b = ++a[b]; b + ' '+ a"),
njs_str("3 1,3,3") },
{ njs_str("var a = { valueOf: function() { return 1 } };"
"++a +' '+ a +' '+ typeof a"),
njs_str("2 2 number") },
{ njs_str("var a = { valueOf: function() { return '1' } };"
"++a +' '+ a +' '+ typeof a"),
njs_str("2 2 number") },
{ njs_str("var a = { valueOf: function() { return [1] } };"
"++a +' '+ a +' '+ typeof a"),
njs_str("NaN NaN number") },
{ njs_str("var a = { valueOf: function() { return {} } };"
"++a +' '+ a +' '+ typeof a"),
njs_str("NaN NaN number") },
/**/
{ njs_str("var a = 1; a = ++a"),
njs_str("2") },
{ njs_str("var a = '1'; a = ++a"),
njs_str("2") },
{ njs_str("var a = [1]; a = ++a"),
njs_str("2") },
{ njs_str("var a = {}; a = ++a"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } }; a = ++a"),
njs_str("2") },
{ njs_str("var a = { valueOf: function() { return '1' } }; a = ++a"),
njs_str("2") },
{ njs_str("var a = { valueOf: function() { return [1] } }; a = ++a"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; a = ++a"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; var b = ++a; a +' '+ b"),
njs_str("2 2") },
{ njs_str("var a = '1'; var b = ++a; a +' '+ b"),
njs_str("2 2") },
{ njs_str("var a = [1]; var b = ++a; a +' '+ b"),
njs_str("2 2") },
{ njs_str("var a = {}; var b = ++a; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } };"
"var b = ++a; a +' '+ b"),
njs_str("2 2") },
{ njs_str("var a = { valueOf: function() { return '1' } };"
"var b = ++a; a +' '+ b"),
njs_str("2 2") },
{ njs_str("var a = { valueOf: function() { return [1] } };"
"var b = ++a; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return {} } };"
"var b = ++a; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = 0; a = a + ++a; a"),
njs_str("1") },
{ njs_str("var a = 0; a += a + ++a; a"),
njs_str("1") },
{ njs_str("var i = 0, arr = ['a', 'b'];"
"arr[i] = arr[i] + arr[++i]; arr"),
njs_str("ab,b") },
{ njs_str("var i = 0, arr = ['a', 'b'];"
"arr[i] += arr[i] + arr[++i]; arr"),
njs_str("aab,b") },
/* Post increment. */
{ njs_str("var a = 1; a++"),
njs_str("1") },
{ njs_str("var a = '1'; a++"),
njs_str("1") },
{ njs_str("var a = [1]; a++"),
njs_str("1") },
{ njs_str("var a = {}; a++"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } }; a++"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; a++"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return [1] } }; a++"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; a++"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; a = a++"),
njs_str("1") },
{ njs_str("var a = '1'; a = a++"),
njs_str("1") },
{ njs_str("var a = [1]; a = a++"),
njs_str("1") },
{ njs_str("var a = {}; a = a++"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } }; a = a++"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; a = a++"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return [1] } }; a = a++"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; a = a++"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; var b = a++; a +' '+ b"),
njs_str("2 1") },
{ njs_str("var a = '1'; var b = a++; a +' '+ b"),
njs_str("2 1") },
{ njs_str("var a = [1]; var b = a++; a +' '+ b"),
njs_str("2 1") },
{ njs_str("var a = {}; var b = a++; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } };"
"var b = a++; a +' '+ b"),
njs_str("2 1") },
{ njs_str("var a = { valueOf: function() { return '1' } };"
"var b = a++; a +' '+ b"),
njs_str("2 1") },
{ njs_str("var a = { valueOf: function() { return [1] } };"
"var b = a++; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return {} } };"
"var b = a++; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = 0; a = a + a++; a"),
njs_str("0") },
{ njs_str("var a = 0; a += a + a++; a"),
njs_str("0") },
{ njs_str("var i = 1, arr = ['a', 'b'];"
"arr[i] = arr[i] + arr[i++]; arr"),
njs_str("a,bb") },
{ njs_str("var i = 1, arr = ['a', 'b'];"
"arr[i] += arr[i] + arr[i++]; arr"),
njs_str("a,bbb") },
/* Decrement. */
{ njs_str("var a = 1; --a"),
njs_str("0") },
{ njs_str("var a = '1'; --a"),
njs_str("0") },
{ njs_str("var a = [1]; --a"),
njs_str("0") },
{ njs_str("var a = {}; --a"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1} }; --a"),
njs_str("0") },
{ njs_str("var a = { valueOf: function() { return '1'} }; --a"),
njs_str("0") },
{ njs_str("var a = { valueOf: function() { return [1]} }; --a"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; --a"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; a = --a"),
njs_str("0") },
{ njs_str("var a = '1'; a = --a"),
njs_str("0") },
{ njs_str("var a = [1]; a = --a"),
njs_str("0") },
{ njs_str("var a = {}; a = --a"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1} }; a = --a"),
njs_str("0") },
{ njs_str("var a = { valueOf: function() { return '1'} }; a = --a"),
njs_str("0") },
{ njs_str("var a = { valueOf: function() { return [1]} }; a = --a"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; a = --a"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; var b = --a; a +' '+ b"),
njs_str("0 0") },
{ njs_str("var a = '1'; var b = --a; a +' '+ b"),
njs_str("0 0") },
{ njs_str("var a = [1]; var b = --a; a +' '+ b"),
njs_str("0 0") },
{ njs_str("var a = {}; var b = --a; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } };"
"var b = --a; a +' '+ b"),
njs_str("0 0") },
{ njs_str("var a = { valueOf: function() { return '1' } };"
"var b = --a; a +' '+ b"),
njs_str("0 0") },
{ njs_str("var a = { valueOf: function() { return [1] } };"
"var b = --a; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return {} } };"
"var b = --a; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = 0; a = a + --a; a"),
njs_str("-1") },
{ njs_str("var a = 0; a -= a + --a; a"),
njs_str("1") },
{ njs_str("var i = 1, arr = ['a', 'b'];"
"arr[i] = arr[i] + arr[--i]; arr"),
njs_str("a,ba") },
{ njs_str("var i = 1, arr = ['a', 'b'];"
"arr[i] += arr[i] + arr[--i]; arr"),
njs_str("a,bba") },
/* Post decrement. */
{ njs_str("var a = 1; a--"),
njs_str("1") },
{ njs_str("var a = '1'; a--"),
njs_str("1") },
{ njs_str("var a = [1]; a--"),
njs_str("1") },
{ njs_str("var a = {}; a--"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } }; a--"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; a--"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return [1] } }; a--"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; a--"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; a = a--"),
njs_str("1") },
{ njs_str("var a = '1'; a = a--"),
njs_str("1") },
{ njs_str("var a = [1]; a = a--"),
njs_str("1") },
{ njs_str("var a = {}; a = a--"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } }; a = a--"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return '1' } }; a = a--"),
njs_str("1") },
{ njs_str("var a = { valueOf: function() { return [1] } }; a = a--"),
njs_str("NaN") },
{ njs_str("var a = { valueOf: function() { return {} } }; a = a--"),
njs_str("NaN") },
/**/
{ njs_str("var a = 1; var b = a--; a +' '+ b"),
njs_str("0 1") },
{ njs_str("var a = '1'; var b = a--; a +' '+ b"),
njs_str("0 1") },
{ njs_str("var a = [1]; var b = a--; a +' '+ b"),
njs_str("0 1") },
{ njs_str("var a = {}; var b = a--; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return 1 } };"
"var b = a--; a +' '+ b"),
njs_str("0 1") },
{ njs_str("var a = { valueOf: function() { return '1' } };"
"var b = a--; a +' '+ b"),
njs_str("0 1") },
{ njs_str("var a = { valueOf: function() { return [1] } };"
"var b = a--; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = { valueOf: function() { return {} } };"
"var b = a--; a +' '+ b"),
njs_str("NaN NaN") },
{ njs_str("var a = 0; a = a + a--; a"),
njs_str("0") },
{ njs_str("var a = 0; a += a + a--; a"),
njs_str("0") },
{ njs_str("var i = 1, arr = ['a', 'b'];"
"arr[i] = arr[i] + arr[i--]; arr"),
njs_str("a,bb") },
{ njs_str("var i = 1, arr = ['a', 'b'];"
"arr[i] += arr[i] + arr[i--]; arr"),
njs_str("a,bbb") },
/**/
{ njs_str("var a, b; a = 2; b = ++a + ++a; a + ' ' + b"),
njs_str("4 7") },
{ njs_str("var a, b; a = 2; b = a++ + a++; a + ' ' + b"),
njs_str("4 5") },
{ njs_str("var a, b; a = b = 7; a +' '+ b"),
njs_str("7 7") },
{ njs_str("var a, b, c; a = b = c = 5; a +' '+ b +' '+ c"),
njs_str("5 5 5") },
{ njs_str("var a, b, c; a = b = (c = 5) + 2; a +' '+ b +' '+ c"),
njs_str("7 7 5") },
{ njs_str("1, 2 + 5, 3"),
njs_str("3") },
{ njs_str("var a, b; a = 1 /* YES */\n b = a + 2 \n \n + 1 \n + 3"),
njs_str("7") },
{ njs_str("var a, b; a = 1 // YES \n b = a + 2 \n \n + 1 \n + 3"),
njs_str("7") },
{ njs_str("var a; a = 0; ++ \n a"),
njs_str("1") },
{ njs_str("var a; a = 0\n ++a"),
njs_str("1") },
{ njs_str("a = 0; a \n ++"),
njs_str("SyntaxError: Unexpected end of input in 2") },
{ njs_str("a = 0; a \n --"),
njs_str("SyntaxError: Unexpected end of input in 2") },
{ njs_str("var a = 0; a \n + 1"),
njs_str("1") },
{ njs_str("var a = 0; a \n +\n 1"),
njs_str("1") },
{ njs_str("var a; a = 1 ? 2 \n : 3"),
njs_str("2") },
{ njs_str("var a, b, c;"
"a = 0 / 0; b = 1 / 0; c = -1 / 0; a +' '+ b +' '+ c"),
njs_str("NaN Infinity -Infinity") },
{ njs_str("var a, b; a = (b = 7) + 5; var c; a +' '+ b +' '+ c"),
njs_str("12 7 undefined") },
{ njs_str("var a, b = 1, c; a +' '+ b +' '+ c"),
njs_str("undefined 1 undefined") },
{ njs_str("var a = 1, b = a + 1; a +' '+ b"),
njs_str("1 2") },
{ njs_str("var a; a = a = 1"),
njs_str("1") },
{ njs_str("var a = 1, \n b; a +' '+ b"),
njs_str("1 undefined") },
{ njs_str("var a; a = b + 1; var b; a +' '+ b"),
njs_str("NaN undefined") },
{ njs_str("var a += 1"),
njs_str("SyntaxError: Unexpected token \"+=\" in 1") },
{ njs_str("var a = a + 1"),
njs_str("undefined") },
{ njs_str("var a; a = b + 1; var b = 1; a +' '+ b"),
njs_str("NaN 1") },
{ njs_str("var a; (a) = 1"),
njs_str("1") },
{ njs_str("a"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("\na"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("\n\na"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("a + a"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("a = b + 1"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("a = a + 1"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("a += 1"),
njs_str("ReferenceError: \"a\" is not defined") },
{ njs_str("a += 1; var a = 2"),
njs_str("undefined") },
{ njs_str("var a = 1"),
njs_str("undefined") },
{ njs_str("var a = 1; a = (a = 2) + a"),
njs_str("4") },
{ njs_str("var a = 1; a = a + (a = 2)"),
njs_str("3") },
{ njs_str("var a = 1; a += (a = 2)"),
njs_str("3") },
{ njs_str("var a = b = 1; var b; a +' '+ b"),
njs_str("1 1") },
{ njs_str("var a \n if (!a) a = 3; a"),
njs_str("3") },
/* automatic semicolon insertion. */
{ njs_str("(a\n--"),
njs_str("SyntaxError: Unexpected token \"--\" in 2") },
{ njs_str("(a\n++"),
njs_str("SyntaxError: Unexpected token \"++\" in 2") },
{ njs_str("var x = 0, y = 2; x\n--\ny; [x,y]"),
njs_str("0,1") },
{ njs_str("function f() {return\n}"),
njs_str("undefined") },
/* if. */
{ njs_str("if (0);"),
njs_str("undefined") },
{ njs_str("if (0) {}"),
njs_str("undefined") },
{ njs_str("if (0);else;"),
njs_str("undefined") },
{ njs_str("var a = 1; if (true); else a = 2; a"),
njs_str("1") },
{ njs_str("var a = 1; if (false); else a = 2; a"),
njs_str("2") },
{ njs_str("var a = 1; if (true) a = 2; else a = 3; a"),
njs_str("2") },
{ njs_str("var a = 3; if (true) if (false); else a = 2; a"),
njs_str("2") },
{ njs_str("var a = 3; if (true) if (false); else; a = 2; a"),
njs_str("2") },
{ njs_str("var a = [3], b; if (1==1||2==2) { b = '1'+'2'+a[0] }; b"),
njs_str("123") },
{ njs_str("(function(){ if(true) return 1 else return 0; })()"),
njs_str("SyntaxError: Unexpected token \"else\" in 1") },
{ njs_str("(function(){ if(true) return 1; else return 0; })()"),
njs_str("1") },
{ njs_str("(function(){ if(true) return 1;; else return 0; })()"),
njs_str("SyntaxError: Unexpected token \"else\" in 1") },
{ njs_str("(function(){ if(true) return 1\n else return 0; })()"),
njs_str("1") },
{ njs_str("(function(){ if(true) return 1\n;\n else return 0; })()"),
njs_str("1") },
{ njs_str("function f(n) {if (n) throw 'foo' else return 1}; f(0)"),
njs_str("SyntaxError: Unexpected token \"else\" in 1") },
{ njs_str("function f(n) {if (n)\n throw 'foo'\nelse return 1}; f(0)"),
njs_str("1") },
{ njs_str("function f(n) {if (n)\n throw 'foo'\nelse return 1}; f(1)"),
njs_str("foo") },
{ njs_str("function f(n) {if (n == 1) throw 'foo'\nelse if (n == 2) return 1}; f(2)"),
njs_str("1") },
{ njs_str("(function(){ for (var p in [1] ){ if (1) break else return 0; }})()"),
njs_str("SyntaxError: Unexpected token \"else\" in 1") },
{ njs_str("(function(){ for (var p in [1] ){ if (1) break\n else return 0; }})()"),
njs_str("undefined") },
{ njs_str("(function(){ for (var p in [1] ){ if (1) break; else return 0; }})()"),
njs_str("undefined") },
{ njs_str("(function(){ for (var p in [1] ){ if (1) continue else return 0; }})()"),
njs_str("SyntaxError: Unexpected token \"else\" in 1") },
{ njs_str("(function(){ for (var p in [1] ){ if (1) continue\n else return 0; }})()"),
njs_str("undefined") },
{ njs_str("(function(){ for (var p in [1] ){ if (1) continue; else return 0; }})()"),
njs_str("undefined") },
{ njs_str("(function(x){ if\n(x) return -1; else return 0; })(0)"),
njs_str("0") },
{ njs_str("(function(x){ if\n(\nx) return -1; else return 0; })(0)"),
njs_str("0") },
{ njs_str("(function(x){ if\n(\nx)\nreturn -1; else return 0; })(0)"),
njs_str("0") },
{ njs_str("(function(x){ if\n(\nx)\nreturn -1\n else return 0; })(0)"),
njs_str("0") },
{ njs_str("(function(x){ if\n(\nx)\nreturn -1\n else\nreturn 0; })(0)"),
njs_str("0") },
/* do while. */
{ njs_str("do { break } if (false)"),
njs_str("SyntaxError: Unexpected token \"if\" in 1") },
/* for in. */
{ njs_str("for (null in undefined);"),
njs_str("ReferenceError: Invalid left-hand side \"null\" in for-in statement in 1") },
{ njs_str("for (var a, b in []);"),
njs_str("SyntaxError: Unexpected token \"in\" in 1") },
{ njs_str("var s = ''; for (var p in [1,2]) {s += p}; s"),
njs_str("01") },
{ njs_str("var s; for (var p in [1]) {s = typeof(p)}; s"),
njs_str("string") },
{ njs_str("var s = ''; for (var p in {a:1, b:2}) {s += p}; s"),
njs_str("ab") },
{ njs_str("var s = '';"
"var o = Object.defineProperty({}, 'x', {value:1});"
"Object.defineProperty(o, 'y', {value:2, enumerable:true});"
"for (var p in o) {s += p}; s"),
njs_str("y") },
{ njs_str("var o = {a:1, b:2}; var arr = []; "
"for (var a in o) {arr.push(a)}; arr"),
njs_str("a,b") },
{ njs_str("var o = {a:1, b:2}; var arr = []; delete o.a; "
"for (var a in o) {arr.push(a)}; arr"),
njs_str("b") },
{ njs_str("var a = []; for (var k in new Uint8Array([1,2,3])) { a.push(k); }; a"),
njs_str("0,1,2") },
/* switch. */
{ njs_str("switch"),
njs_str("SyntaxError: Unexpected end of input in 1") },
{ njs_str("switch (1);"),
njs_str("SyntaxError: Unexpected token \";\" in 1") },
{ njs_str("switch (1) { do { } while (1) }"),
njs_str("SyntaxError: Unexpected token \"do\" in 1") },
{ njs_str("switch (1) {}"),
njs_str("undefined") },
{ njs_str("switch (1) {default:}"),
njs_str("undefined") },
{ njs_str("switch (1) {case 0:}"),
njs_str("undefined") },
{ njs_str("switch (1) {default:;}"),
njs_str("undefined") },
{ njs_str("switch (1) {default:; default:}"),
njs_str("SyntaxError: More than one default clause in switch statement in 1") },
{ njs_str("switch (1) {case 0:;}"),
njs_str("undefined") },
{ njs_str("var a = 'A'; switch (a) {"
"case 0: a += '0';"
"case 1: a += '1';"
"}; a"),
njs_str("A") },
{ njs_str("var a = 'A'; switch (0) {"
"case 0: a += '0';"
"case 1: a += '1';"
"}; a"),
njs_str("A01") },
{ njs_str("var a = 'A'; switch (0) {"
"case 0: a += '0'; break;"
"case 1: a += '1';"
"}; a"),
njs_str("A0") },
{ njs_str("var a = 'A'; switch (1) {"
"case 0: a += '0';"
"case 1: a += '1';"
"}; a"),
njs_str("A1") },
{ njs_str("var a = 'A'; switch (2) {"
"case 0: a += '0';"
"case 1: a += '1';"
"default: a += 'D';"
"}; a"),
njs_str("AD") },
{ njs_str("var a = 'A'; switch (2) {"
"case 0: a += '0';"
"default: a += 'D';"
"case 1: a += '1';"
"}; a"),
njs_str("AD1") },
{ njs_str("var a = 'A'; function f(x) { a += x; return 0 }"
"switch (a) {"
"case f(1):"
"default:"
"case f(2): a += 'D';"
"case f(3): a += 'T';"
"} a"),
njs_str("A123DT") },
{ njs_str("[isNaN, undefined, isFinite]."
"map((v)=>{switch(v) { case isNaN: return 1; default: return 0;}})"),
njs_str("1,0,0") },
{ njs_str("switch (1) {case 1: ii > 1; ii => default:}"),
njs_str("SyntaxError: Unexpected token \"default\" in 1") },
{ njs_str("switch (1) {case 1: ii > 1; var a = functin () {default:}"),
njs_str("SyntaxError: Unexpected token \"{\" in 1") },
{ njs_str("switch (1) {default: ii > 1; ii => case 2:}"),
njs_str("SyntaxError: Unexpected token \"case\" in 1") },
{ njs_str("switch (1) {default: ii > 1; var a = functin () {case 2:}"),
njs_str("SyntaxError: Unexpected token \"{\" in 1") },
{ njs_str("switch (1) {case 1: ii > 1; ii => case 2:}"),
njs_str("SyntaxError: Unexpected token \"case\" in 1") },
{ njs_str("switch (1) {case 1: ii > 1; var a = functin () {case 2:}"),
njs_str("SyntaxError: Unexpected token \"{\" in 1") },
/* continue. */
{ njs_str("continue"),
njs_str("SyntaxError: Illegal continue statement in 1") },
{ njs_str("\n{\ncontinue;\n}"),
njs_str("SyntaxError: Illegal continue statement in 3") },
{ njs_str("do continue while (false)"),
njs_str("SyntaxError: Unexpected token \"while\" in 1") },
{ njs_str("do continue; while (false)"),
njs_str("undefined") },
{ njs_str("do { continue } while (false)"),
njs_str("undefined") },
{ njs_str("var i = 0; do if (i++ > 9) continue; while (i < 100); i"),
njs_str("100") },
{ njs_str("while (false) continue"),
njs_str("undefined") },
{ njs_str("while (false) continue;"),
njs_str("undefined") },
{ njs_str("while (false) { continue }"),
njs_str("undefined") },
{ njs_str("var i = 0; while (i < 100) if (i++ > 9) continue; i"),
njs_str("100") },
{ njs_str("for ( ;null; ) continue"),
njs_str("undefined") },
{ njs_str("for ( ;null; ) continue;"),
njs_str("undefined") },
{ njs_str("for ( ;null; ) { continue }"),
njs_str("undefined") },
{ njs_str("var i; for (i = 0; i < 100; i++) if (i > 9) continue; i"),
njs_str("100") },
{ njs_str("var a = [], i; for (i in a) continue"),
njs_str("undefined") },
{ njs_str("var a = [], i; for (i in a) continue;"),
njs_str("undefined") },
{ njs_str("var a = [], i; for (i in a) { continue }"),
njs_str("undefined") },
{ njs_str("var a = [1,2,3,4,5]; var s = 0, i;"
"for (i in a) { if (a[i] > 4) continue; else s += a[i] } s"),
njs_str("10") },
{ njs_str("var a = [1,2,3,4,5]; var s = 0, i;"
"for (i in a) { if (a[i] > 4) continue; s += a[i] } s"),
njs_str("10") },
{ njs_str("var a; for (a = 1; a; a--) switch (a) { case 0: continue }"),
njs_str("undefined") },
{ njs_str("var a = [1,2,3], i; for (i in a) {Object.seal({})}"),
njs_str("undefined") },
{ njs_str("var i; for (i in [1,2,3]) {Object.seal({});}"),
njs_str("undefined") },
{ njs_str("while (0) {continue\n}"),
njs_str("undefined") },
/* break. */
{ njs_str("break"),
njs_str("SyntaxError: Illegal break statement in 1") },
{ njs_str("{break}"),
njs_str("SyntaxError: Illegal break statement in 1") },
{ njs_str("\nbreak"),
njs_str("SyntaxError: Illegal break statement in 2") },
{ njs_str("do break while (true)"),
njs_str("SyntaxError: Unexpected token \"while\" in 1") },
{ njs_str("do break; while (true)"),
njs_str("undefined") },
{ njs_str("do { break } while (true)"),
njs_str("undefined") },
{ njs_str("var i = 0; do if (i++ > 9) break; while (i < 100); i"),
njs_str("11") },
{ njs_str("while (true) break"),
njs_str("undefined") },
{ njs_str("while (true) break;"),
njs_str("undefined") },
{ njs_str("while (true) { break }"),
njs_str("undefined") },
{ njs_str("var i = 0; while (i < 100) if (i++ > 9) break; i"),
njs_str("11") },
{ njs_str("for ( ;; ) break"),
njs_str("undefined") },
{ njs_str("for ( ;; ) break;"),
njs_str("undefined") },
{ njs_str("for ( ;; ) { break }"),
njs_str("undefined") },
{ njs_str("var i; for (i = 0; i < 100; i++) if (i > 9) break; i"),
njs_str("10") },
{ njs_str("var a = [], i; for (i in a) break"),
njs_str("undefined") },
{ njs_str("var a = [], i; for (i in a) break;"),
njs_str("undefined") },
{ njs_str("var a = [], i; for (i in a) { break }"),
njs_str("undefined") },
{ njs_str("var a = [1,2,3,4,5]; var s = 0, i;"
"for (i in a) { if (a[i] > 4) break; else s += a[i] } s"),
njs_str("10") },
{ njs_str("var a = [1,2,3,4,5]; var s = 0, i;"
"for (i in a) { if (a[i] > 4) break; s += a[i] } s"),
njs_str("10") },
{ njs_str("var a = [1,2,3,4,5]; var s = 0, i;"
"for (i in a) if (a[i] > 4) break; s += a[i]; s"),
njs_str("5") },
{ njs_str("while (0) {break\n}"),
njs_str("undefined") },
/* Labels. */
{ njs_str("var n = 0; a:{n++}; a:{n++}; n"),
njs_str("2") },
{ njs_str("a: throw 'a'"),
njs_str("a") },
{ njs_str("a\n:\n1"),
njs_str("1") },
{ njs_str("a\n\n:1"),
njs_str("1") },
{ njs_str("a:\n\n1"),
njs_str("1") },
{ njs_str("a:\n\n"),
njs_str("SyntaxError: Unexpected end of input in 3") },
{ njs_str("a : var n = 0; b :++n"),
njs_str("1") },
{ njs_str("a:{a:1}"),
njs_str("SyntaxError: Label \"a\" has already been declared in 1") },
{ njs_str("for (var i in [1]) {break b}"),
njs_str("SyntaxError: Undefined label \"b\" in 1") },
{ njs_str("for (var i in [1]) {continue b}"),
njs_str("SyntaxError: Undefined label \"b\" in 1") },
{ njs_str("a:{break b}"),
njs_str("SyntaxError: Undefined label \"b\" in 1") },
{ njs_str("a:{continue b}"),
njs_str("SyntaxError: Undefined label \"b\" in 1") },
{ njs_str("a:function name() {}"),
njs_str("SyntaxError: In strict mode code, functions can only be declared at top level or inside a block.") },
#if 0 /* TODO */
{ njs_str("a:{1; break a}"),
njs_str("1") },
#endif
{ njs_str("var a = 0; a:{a++}; a"),
njs_str("1") },
{ njs_str("var a = 0; a:{break a; a++}; a"),
njs_str("0") },
{ njs_str("var r = 0; "
"out: for (var i in [1,2,3]) { if (i == 2) {break out;}; r++}; r"),
njs_str("2") },
{ njs_str("var r = 0; "
"out: for (var i = 0; i < 5; i++) { if (i == 2) {break out;}; r++}; r"),
njs_str("2") },
{ njs_str("var l1 = 0, l2 = 0; "
"out: "
"for (var i in [1,2,3]) { "
" for (var j in [1,2,3]) { "
" if (i == 1 && j == 1) {break;}"
" l2++;"
" }"
" l1++;"
"}; [l1, l2]"),
njs_str("3,7") },
{ njs_str("var l1 = 0, l2 = 0; "
"out: "
"for (var i in [1,2,3]) { "
" for (var j in [1,2,3]) { "
" if (i == 1 && j == 1) {break out;}"
" l2++;"
" }"
" l1++;"
"}; [l1, l2]"),
njs_str("1,4") },
{ njs_str("var l1 = 0, l2 = 0; "
"out: "
"for (var i in [1,2,3]) { "
" for (var j in [1,2,3]) { "
" if (i == 1 && j == 1) {continue out;}"
" l2++;"
" }"
" l1++;"
"}; [l1, l2]"),
njs_str("2,7") },
{ njs_str("var l1 = 0, l2 = 0; "
"out: "
"for (var i in [1,2,3]) { "
" l1++;"
" switch (i) { "
" case '1':"
" break out;"
" default:"
" }"
" l2++;"
"}; [l1, l2]"),
njs_str("2,1") },
{ njs_str("var l1 = 0, l2 = 0; "
"out: "
"for (var i in [1,2,3]) { "
" l1++;"
" switch (i) { "
" case '1':"
" continue out;"
" default:"
" }"
" l2++;"
"}; [l1, l2]"),
njs_str("3,2") },
{ njs_str("var l1 = 0, l2 = 0, i = 0, j; "
"out: "
"while (i < 3) { "
" j = 0;"
" while (j < 3) { "
" if (i == 1 && j == 1) {break out;}"
" l2++;"
" j++;"
" }"
" l1++;"
" i++;"
"}; [l1, l2]"),
njs_str("1,4") },
{ njs_str("var l1 = 0, l2 = 0, i = 0, j; "
"out: "
"while (i < 3) { "
" j = 0;"
" while (j < 3) { "
" if (i == 1 && j == 1) {i++; continue out;}"
" l2++;"
" j++;"
" }"
" l1++;"
" i++;"
"}; [l1, l2]"),
njs_str("2,7") },
{ njs_str("var l1 = 0, l2 = 0, i = 0, j; "
"out: "
"do { "
" j = 0;"
" do { "
" if (i == 1 && j == 1) {break out;}"
" l2++;"
" j++;"
" } while (j < 3)"
" l1++;"
" i++;"
"} while (i < 3); [l1, l2]"),
njs_str("1,4") },
{ njs_str("var l1 = 0, l2 = 0, i = 0, j; "
"out: "
"do { "
" j = 0;"
" do { "
" if (i == 1 && j == 1) {i++; continue out;}"
" l2++;"
" j++;"
" } while (j < 3)"
" l1++;"
" i++;"
"} while (i < 3); [l1, l2]"),
njs_str("2,7") },
{ njs_str("out1: while (1) { out2: while (1) { "
" try { break out1; break out2; } catch (e) {}"
"}}"),
njs_str("InternalError: break/return instructions with different labels "
"(\"out1\" vs \"out2\") from try-catch block are not supported") },
{ njs_str("out1: while (1) { out2: while (1) { "
" try { } catch (e) {break out1; break out2;} finally {}"
"}}"),
njs_str("InternalError: break/return instructions with different labels "
"(\"out1\" vs \"out2\") from try-catch block are not supported") },
{ njs_str("out1: while (1) { out2: while (1) { "
" try { break out1; } catch (e) {break out2;} finally {}"
"}}"),
njs_str("InternalError: try break/return instructions with different labels "
"(\"out1\" vs \"out2\") from try-catch block are not supported") },
{ njs_str("out1: while (1) { out2: while (1) { "
" try { break out1; break out2; } finally {}"
"}}"),
njs_str("InternalError: break/return instructions with different labels "
"(\"out1\" vs \"out2\") from try-catch block are not supported") },
{ njs_str("out1: while (1) { out2: while (1) { "
" try { continue out1; continue out2; } catch (e) {}"
"}}"),
njs_str("InternalError: continue instructions with different labels "
"(\"out1\" vs \"out2\") from try-catch block are not supported") },
{ njs_str("out1: while (1) { out2: while (1) { "
" try { continue out1; } catch (e) {continue out2;} finally {}"
"}}"),
njs_str("InternalError: try continue instructions with different labels "
"(\"out1\" vs \"out2\") from try-catch block are not supported") },