| # |
| # Copyright (C) Dmitry Volyntsev |
| # Copyright (C) NGINX, Inc. |
| # |
| |
| proc njs_test {body {opts ""}} { |
| |
| if {$opts eq ""} { |
| spawn -nottycopy njs |
| |
| } else { |
| eval spawn -nottycopy njs $opts |
| } |
| |
| # TODO: |
| # SIGINT handling race condition |
| # deb9-amd64-generic-njs-try |
| # ub1404-armv7-generic-njs-try |
| # ub1804-arm64-generic-njs-try |
| # UTF8 terminal support issue |
| # sol11-amd64-sunpro-njs-try |
| # ub1604-arm64-generic-njs-try |
| |
| # set timeout 30 |
| # expect_before timeout { exit 1 } |
| |
| expect -re "interactive njs \\d+\.\\d+\.\\d+\r\n\r" |
| expect "v.<Tab> -> the properties and prototype methods of v.\r |
| \r |
| >> " |
| |
| set len [llength $body] |
| for {set i 0} {$i < $len} {incr i} { |
| set pair [lindex $body $i] |
| send [lindex $pair 0] |
| expect [lindex $pair 1] |
| } |
| |
| # Ctrl-C |
| send \x03 |
| expect eof |
| } |
| |
| proc njs_run {opts expected_re} { |
| catch {exec njs {*}$opts} out |
| if {[regexp $expected_re $out match] == 0} { |
| return -code error "njs_run: unexpected output '$out' vs '$expected_re'" |
| } |
| } |
| |
| njs_test { |
| {"njs.version\r\n" |
| "njs.version\r\n\*\.\*\.\*"} |
| } |
| |
| # simple multi line interaction |
| njs_test { |
| {"var a = 1\r\n" |
| "var a = 1\r\nundefined\r\n>> "} |
| {"a *= 2\r\n" |
| "a *= 2\r\n2\r\n>> "} |
| } |
| |
| # Global completions, no |
| njs_test { |
| {"\t\tn" |
| "\a\r\nDisplay all*possibilities? (y or n)*>> "} |
| } |
| |
| # Global completions, yes |
| njs_test { |
| {"\t\ty" |
| "\a\r\nDisplay all*possibilities? (y or n)*Array"} |
| } |
| |
| # Global completions, single partial match |
| |
| # \a* is WORKAROUND for libedit-20170329.3.1-r3 |
| # which inserts '\rESC[6G' after '\a'. |
| njs_test { |
| {"O\t" |
| "O\a*bject"} |
| } |
| |
| njs_test { |
| {"Ma\t" |
| "Ma\a*th"} |
| } |
| |
| # FIXME: completions for external objects |
| # are not supported |
| |
| # njs_test { |
| # {"conso\t" |
| # "conso\a*le"} |
| # } |
| |
| # Global completions, multiple partial match |
| njs_test { |
| {"cons\t\t" |
| "console*const"} |
| } |
| |
| njs_test { |
| {"O\t" |
| "O\a*bject"} |
| {"\t\t" |
| "Object.create*Object.isSealed"} |
| } |
| |
| njs_test { |
| {"Object.\t\t" |
| "Object.create*Object.isSealed"} |
| } |
| |
| njs_test { |
| {"Object.g\t" |
| "Object.g\a*et"} |
| {"\t\t" |
| "Object.getOwnPropertyDescriptor*Object.getPrototypeOf"} |
| } |
| |
| njs_test { |
| {"JS\t" |
| "JS\a*ON"} |
| {"\t\t" |
| "JSON.parse*JSON.stringify"} |
| } |
| |
| # Global completions, no matches |
| njs_test { |
| {"1.\t\t" |
| "1."} |
| } |
| |
| njs_test { |
| {"1..\t\t" |
| "1.."} |
| } |
| |
| njs_test { |
| {"'abc'.\t\t" |
| "'abc'."} |
| } |
| |
| # Global completions, global vars |
| njs_test { |
| {"var a = 1; var aa = 2\r\n" |
| "var a = 1; var aa = 2\r\nundefined\r\n>> "} |
| {"a\t\t" |
| "a*aa*arguments*await"} |
| } |
| |
| # z*z is WORKAROUND for libedit-20170329.3.1-r3 |
| # which inserts bogus '\a' between 'z' |
| njs_test { |
| {"var zz = 1\r\n" |
| "var zz = 1\r\nundefined\r\n>> "} |
| {"1 + z\t\r\n" |
| "1 + z*z*\r\n2"} |
| } |
| |
| njs_test { |
| {"unknown_var\t\t" |
| "unknown_var"} |
| } |
| |
| njs_test { |
| {"unknown_var.\t\t" |
| "unknown_var."} |
| } |
| |
| # An object's level completions |
| njs_test { |
| {"var o = {zz:1, zb:2}\r\n" |
| "var o = {zz:1, zb:2}\r\nundefined\r\n>> "} |
| {"o.z\t\t" |
| "o.zb*o.zz"} |
| } |
| |
| njs_test { |
| {"var d = new Date()\r\n" |
| "var d = new Date()\r\nundefined\r\n>> "} |
| {"d.to\t\t" |
| "d.toDateString*d.toLocaleDateString*d.toString"} |
| } |
| |
| njs_test { |
| {"var o = {a:new Date()}\r\n" |
| "var o = {a:new Date()}\r\nundefined\r\n>> "} |
| {"o.a.to\t\t" |
| "o.a.toDateString*o.a.toLocaleDateString*o.a.toString"} |
| } |
| |
| njs_test { |
| {"var o = {a:1,b:2,333:'t'}\r\n" |
| "var o = {a:1,b:2,333:'t'}\r\nundefined\r\n>> "} |
| {"o.3\t\t" |
| "o.3"} |
| } |
| |
| njs_test { |
| {"var a = Array(5000000); a.aab = 1; a.aac = 2\r\n" |
| "var a = Array(5000000); a.aab = 1; a.aac = 2\r\n2\r\n>> "} |
| {"a.\t\t" |
| "a.aab*"} |
| } |
| |
| njs_test { |
| {"var a = new Uint8Array([5,6,7,8,8]); a.aab = 1; a.aac = 2\r\n" |
| "var a = new Uint8Array(\\\[5,6,7,8,8]); a.aab = 1; a.aac = 2\r\n2\r\n>> "} |
| {"a.\t\t" |
| "a.aab*"} |
| } |
| |
| # function declarations in interactive mode |
| njs_test { |
| {"function a() { return 1; }\r\n" |
| "undefined\r\n>> "} |
| {"a();\r\n" |
| "1\r\n>> "} |
| {"function a() { return 2; }\r\n" |
| "undefined\r\n>> "} |
| {"a();\r\n" |
| "2\r\n>> "} |
| } |
| |
| # console object |
| njs_test { |
| {"console[Symbol.toStringTag]\r\n" |
| "console\\\[Symbol.toStringTag]\r\n'Console'\r\n>> "} |
| {"Object.prototype.toString.call(console)\r\n" |
| "Object.prototype.toString.call(console)\r\n'\\\[object Console]'\r\n>> "} |
| {"console.toString()\r\n" |
| "console.toString()\r\n'\\\[object Console]'\r\n>> "} |
| {"console\r\n" |
| "console\r\nConsole *>> "} |
| {"delete console.log\r\n" |
| "delete console.log\r\ntrue\r\n>>"} |
| {"console\r\n" |
| "console\r\nConsole *>> "} |
| } |
| |
| # console log functions |
| njs_test { |
| {"console[Symbol.toStringTag]\r\n" |
| "console\\\[Symbol.toStringTag]\r\n'Console'\r\n>> "} |
| {"console\r\n" |
| "console\r\nConsole *>> "} |
| {"console.log()\r\n" |
| "console.log()\r\nundefined\r\n>> "} |
| {"console.log('')\r\n" |
| "console.log('')\r\n\r\nundefined\r\n>> "} |
| {"console.log(1)\r\n" |
| "console.log(1)\r\n1\r\nundefined\r\n>> "} |
| {"console.log(1, 'a')\r\n" |
| "console.log(1, 'a')\r\n1 a\r\nundefined\r\n>> "} |
| {"print(1, 'a')\r\n" |
| "print(1, 'a')\r\n1 a\r\nundefined\r\n>> "} |
| {"console.log('\\tабв\\nгд')\r\n" |
| "console.log('\\\\tабв\\\\nгд')\r\n\tабв\r\nгд\r\nundefined\r\n>> "} |
| {"console.dump()\r\n" |
| "console.dump()\r\nundefined\r\n>> "} |
| {"console.dump(1)\r\n" |
| "console.dump(1)\r\n1\r\nundefined\r\n>> "} |
| {"console.dump(1, 'a')\r\n" |
| "console.dump(1, 'a')\r\n1 a\r\nundefined\r\n>> "} |
| } |
| |
| # console.time* functions |
| njs_test { |
| {"console.time()\r\n" |
| "console.time()\r\nundefined\r\n>> "} |
| {"console.timeEnd()\r\n" |
| "console.timeEnd()\r\ndefault: *.*ms\r\nundefined\r\n>> "} |
| {"console.time(undefined)\r\n" |
| "console.time(undefined)\r\nundefined\r\n>> "} |
| {"console.timeEnd(undefined)\r\n" |
| "console.timeEnd(undefined)\r\ndefault: *.*ms\r\nundefined\r\n>> "} |
| {"console.time('abc')\r\n" |
| "console.time('abc')\r\nundefined\r\n>> "} |
| {"console.time('abc')\r\n" |
| "console.time('abc')\r\nTimer \"abc\" already exists.\r\nundefined\r\n>> "} |
| {"console.timeEnd('abc')\r\n" |
| "console.timeEnd('abc')\r\nabc: *.*ms\r\nundefined\r\n>> "} |
| {"console.time(true)\r\n" |
| "console.time(true)\r\nundefined\r\n>> "} |
| {"console.timeEnd(true)\r\n" |
| "console.timeEnd(true)\r\ntrue: *.*ms\r\nundefined\r\n>> "} |
| {"console.time(42)\r\n" |
| "console.time(42)\r\nundefined\r\n>> "} |
| {"console.timeEnd(42)\r\n" |
| "console.timeEnd(42)\r\n42: *.*ms\r\nundefined\r\n>> "} |
| {"console.timeEnd()\r\n" |
| "console.timeEnd()\r\nTimer \"default\" doesn’t exist."} |
| {"console.timeEnd('abc')\r\n" |
| "console.timeEnd('abc')\r\nTimer \"abc\" doesn’t exist."} |
| } |
| |
| njs_test { |
| {"console.ll()\r\n" |
| "console.ll()\r\nThrown:\r\nTypeError: (intermediate value)\\\[\"ll\"] is not a function"} |
| } |
| |
| njs_test { |
| {"console.log.length\r\n" |
| "console.log.length\r\n0"} |
| } |
| |
| njs_test { |
| {"var print = console.log.bind(console); print(1, 'a', [1, 2])\r\n" |
| "1 a \\\[1,2]\r\nundefined\r\n>> "} |
| {"var print = console.dump.bind(console); print(1, 'a', [1, 2])\r\n" |
| "1 a \\\[\r\n 1,\r\n 2\r\n]\r\nundefined\r\n>> "} |
| {"var print = console.log.bind(console); print(console.a.a)\r\n" |
| "TypeError: cannot get property \"a\" of undefined*at console.log"} |
| {"print(console.a.a)\r\n" |
| "TypeError: cannot get property \"a\" of undefined*at console.log"} |
| } |
| |
| # Backtraces for external objects |
| njs_test { |
| {"console.log(console.a.a)\r\n" |
| "console.log(console.a.a)\r\nThrown:\r\nTypeError:*at console.log (native)"} |
| } |
| |
| # dumper |
| njs_test { |
| {"var o = {toString: function(){}, log: console.log}\r\n" |
| "undefined\r\n>> "} |
| {"o\r\n" |
| "o\r\n{\r\n toString: \\\[Function],\r\n log: \\\[Function: log]\r\n}"} |
| } |
| |
| njs_test { |
| {"[1, new Number(2), 'a', new String('αβZγ'), true, new Boolean(false)]\r\n" |
| "\\\[\r\n 1,\r\n \\\[Number: 2],\r\n 'a',\r\n \\\[String: 'αβZγ'],\r\n true,\r\n \\\[Boolean: false]\r\n]"} |
| } |
| |
| njs_test { |
| {"[undefined,,null]\r\n" |
| "\\\[\r\n undefined,\r\n <empty>,\r\n null\r\n]"} |
| } |
| |
| njs_test { |
| {"[InternalError(),TypeError('msg'), new RegExp(), /^undef$/m, new Date(0)]\r\n" |
| "\\\[\r\n InternalError,\r\n TypeError: msg,\r\n /(?:)/,\r\n /^undef$/m,\r\n 1970-01-01T00:00:00.000Z\r\n]"} |
| } |
| |
| # dumper excapes special characters as JSON.stringify() |
| # except '\"' |
| njs_test { |
| {"\"\\r\\0\\\"\"\r\n" |
| "\\\\r\\\\u0000\""} |
| } |
| |
| njs_test { |
| {"[{a:1}]\r\n" |
| "\r\n\\\[\r\n {\r\n a: 1\r\n }\r\n]"} |
| } |
| |
| # Backtraces are reset between invocations |
| njs_test { |
| {"JSON.parse(Error())\r\n" |
| "JSON.parse(Error())\r\nThrown:\r\nSyntaxError: Unexpected token at position 0*at JSON.parse (native)"} |
| {"JSON.parse(Error()\r\n" |
| "JSON.parse(Error()\r\nThrown:\r\nSyntaxError: Unexpected end of input in shell:1"} |
| } |
| |
| njs_test { |
| {"try { console.log({ toString: function() { throw 'test'; } }) } catch (e) {}\r\n" |
| "undefined"} |
| {"function f() { throw 't' }; try { console.log({ toString: function() { return f() } }) } catch (e) {}\r\n" |
| "undefined"} |
| } |
| |
| njs_test { |
| {"(function() { throw 'test' })()\r\n" |
| "Thrown:\r\ntest"} |
| } |
| |
| njs_test { |
| {"function f() { return ({}.a.a); }\r\n" |
| "undefined"} |
| {"var e; try {f()} catch (ee) {e = ee}\r\n" |
| "undefined"} |
| {"Object.keys(null)\r\n" |
| "Thrown:\r\nTypeError: cannot convert null argument to object"} |
| {"e\r\n" |
| "TypeError: cannot get property \"a\" of undefined*at f (shell:1)"} |
| } |
| |
| # Non-ASCII characters |
| njs_test { |
| {"'絵文å—'\r\n" |
| "'絵文å—'"} |
| {"var v = 'абвгдеёжзийкл';v[10]\r\n" |
| "'й'"} |
| } |
| |
| # Immediate events |
| |
| njs_test { |
| {"var t = setImmediate(console.log, 'a', 'aa')\r\n" |
| "undefined\r\na aa"} |
| } |
| |
| njs_test { |
| {"var a = 1 + 1; setTimeout(function (x) {a = x}, 0, 'a'); a\r\n" |
| "2"} |
| {"a\r\n" |
| "a\r\n'a'"} |
| } |
| |
| njs_test { |
| {"setTimeout(function () {}, 1, 'a')\r\n" |
| "njs_console_set_timer(): async timers unsupported"} |
| } |
| |
| njs_test { |
| {"var a = 1 + 1; setTimeout(function (x) { setTimeout(function (y) {a = y}, 0, x)}, 0, 'a'); a\r\n" |
| "2"} |
| {"a\r\n" |
| "a\r\n'a'"} |
| } |
| |
| njs_test { |
| {"var a = 1 + 1; setImmediate(function (x) { setImmediate(function (y) {a = y}, x)}, 'a'); a\r\n" |
| "2"} |
| {"a\r\n" |
| "a\r\n'a'"} |
| } |
| |
| njs_test { |
| {"var i = 0; (function x() { if (i < 10) setImmediate(x); i++; })()\r\n" |
| "undefined"} |
| {"i\r\n" |
| "i\r\n11"} |
| } |
| |
| njs_test { |
| {"var a = 0, t = setImmediate(function() {a = 1}); clearTimeout(t)\r\n" |
| "undefined"} |
| {"a\r\n" |
| "a\r\n0"} |
| } |
| |
| njs_test { |
| {"var i = 0; (function x() { if (i < 3) setImmediate(x); i++; throw 'Oops';})()\r\n" |
| "Oops"} |
| {"i\r\n" |
| "i\r\n4"} |
| } |
| |
| njs_test { |
| {"var i = 0, queue = []; (function x() { if (i < 5) setImmediate(x); queue.push(i++); })()\r\n" |
| "undefined"} |
| {"queue.toString()\r\n" |
| "queue.toString()\r\n'0,1,2,3,4,5'"} |
| } |
| |
| # require('fs').readFile() |
| |
| njs_run {"./test/js/fs_readFile.js" "test/fs/utf8"} "αβZγ Buffer 7" |
| njs_run {"./test/js/fs_readFile.js" "test/fs/utf8" "utf8"} "αβZγ string 4" |
| njs_run {"./test/js/fs_readFile.js" "test/fs/utf8" "utf8" "r+"} "αβZγ string 4" |
| njs_run {"./test/js/fs_readFile.js" "test/fs/nonexistent"} \ |
| "{\"errno\":2,\"code\":\"ENOENT\",\"path\":\"test/fs/nonexistent\",\"syscall\":\"open\"}" |
| njs_run {"./test/js/fs_readFile.js" "test/fs/non_utf8" "utf8"} "�� string 2" |
| njs_run {"./test/js/fs_readFile.js" "test/fs/non_utf8" "hex"} "8080 string 4" |
| njs_run {"./test/js/fs_readFile.js" "test/fs/non_utf8" "base64"} "gIA= string 4" |
| |
| njs_test { |
| {"var fs = require('fs')\r\n" |
| "undefined\r\n>> "} |
| {"fs.readFile('test/fs/ascii', 'utf8', function (e, data) {console.log(data[599], data[600])})\r\n" |
| "undefined\r\nx undefined\r\n>> "} |
| {"fs.readFile('test/fs/ascii', {encoding:'utf8',flag:'r+'}, function (e, data) {console.log(data[599], data[600])})\r\n" |
| "undefined\r\nx undefined\r\n>> "} |
| {"fs.readFile(Buffer.from([0x80,0x80]), function(e) {console.log(e.path.codePointAt())})\r\n" |
| "undefined\r\n65533"} |
| } |
| |
| njs_test { |
| {"var fs = require('fs')\r\n" |
| "undefined\r\n>> "} |
| {"fs.readFile('/proc/version', (e, data) => {console.log(e || data.slice(0,5) == 'Linux')})\r\n" |
| "undefined\r\ntrue\r\n>> "} |
| {"fs.readFile('/proc/cpuinfo', (e, data) => {console.log(e || data.slice(0,9) == 'processor')})\r\n" |
| "undefined\r\ntrue\r\n>> "} |
| } |
| |
| # require('fs').readFileSync() |
| |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/utf8"} "αβZγ Buffer 7" |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/utf8" "utf8"} "αβZγ string 4" |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/utf8" "utf8" "r+"} "αβZγ string 4" |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/nonexistent"} \ |
| "{\"errno\":2,\"code\":\"ENOENT\",\"path\":\"test/fs/nonexistent\",\"syscall\":\"open\"}" |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/non_utf8" "utf8"} "�� string 2" |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/non_utf8" "hex"} "8080 string 4" |
| njs_run {"./test/js/fs_readFileSync.js" "test/fs/non_utf8" "base64"} "gIA= string 4" |
| |
| njs_test { |
| {"var fs = require('fs')\r\n" |
| "undefined\r\n>> "} |
| {"fs.readFileSync('test/fs/non_utf8', 'utf8').charCodeAt(1)\r\n" |
| "65533"} |
| {"fs.readFile('x'.repeat(8192))\r\n" |
| "TypeError: \"path\" is too long >= 4096"} |
| } |
| |
| njs_test { |
| {"var fs = require('fs'), file\r\n" |
| "undefined\r\n>> "} |
| {"try { file = fs.readFileSync('/proc/version')} catch (e) {}\r\n" |
| "undefined"} |
| {"(!file || file.slice(0,5) == 'Linux')\r\n" |
| "true"} |
| {"try { file = fs.readFileSync('/proc/cpuinfo')} catch (e) {}\r\n" |
| "undefined"} |
| {"(!file || file.slice(0,9) == 'processor')\r\n" |
| "true"} |
| } |
| |
| # require('fs').writeFile() |
| |
| njs_run {"./test/js/fs_writeFile.js" "ABCD" "Buffer" "1"} "BCD" |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "DataView"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "414243" "Object" "hex"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "String"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "Symbol"} "TypeError: Cannot convert a Symbol value to a string*" |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "Uint8Array"} "ABC" |
| |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "String" "utf8"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "String" "utf8" "0o666"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "ABC" "String" "utf8" "0o222"} "Error: Permission denied*" |
| njs_run {"./test/js/fs_writeFile.js" "414243" "String" "hex"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "QUJD" "String" "base64"} "ABC" |
| njs_run {"./test/js/fs_writeFile.js" "QUJD" "String" "base64url"} "ABC" |
| |
| njs_test { |
| {"var fs = require('fs')\r\n" |
| "undefined\r\n>> "} |
| {"fs.writeFile('/invalid_path', 'ABC', function (e) { console.log(JSON.stringify(e))})\r\n" |
| "undefined\r\n{\"errno\":13,\"code\":\"EACCES\",\"path\":\"/invalid_path\",\"syscall\":\"open\"}\r\n>> "} |
| {"fs.writeFile(Buffer.from('/invalid_path'), 'ABC', function (e) { console.log(typeof e.path)})\r\n" |
| "undefined\r\nstring\r\n>> "} |
| } |
| |
| # require('fs').writeFileSync() |
| |
| njs_run {"./test/js/fs_writeFileSync.js" "ABCD" "Buffer" "1"} "BCD" |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "DataView"} "ABC" |
| njs_run {"./test/js/fs_writeFileSync.js" "414243" "Object" "hex"} "ABC" |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "String"} "ABC" |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "Symbol"} "TypeError: Cannot convert a Symbol value to a string*" |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "Uint8Array"} "ABC" |
| |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "String" "utf8"} "ABC" |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "String" "utf8" "0o666"} "ABC" |
| njs_run {"./test/js/fs_writeFileSync.js" "ABC" "String" "utf8" "0o222"} "Error: Permission denied*" |
| njs_run {"./test/js/fs_writeFileSync.js" "78797a" "String" "hex"} "xyz" |
| njs_run {"./test/js/fs_writeFileSync.js" "eHl6" "String" "base64"} "xyz" |
| njs_run {"./test/js/fs_writeFileSync.js" "eHl6" "String" "base64url"} "xyz" |
| |
| njs_test { |
| {"var fs = require('fs'), fn = './build/test/file2';\r\n" |
| "undefined\r\n>> "} |
| {"fs.writeFileSync(fn, 'ABC')\r\n" |
| "undefined\r\n>> "} |
| {"fs.writeFileSync(fn, 'ABC')\r\n" |
| "undefined\r\n>> "} |
| {"fs.readFileSync(fn, 'utf8')\r\n" |
| "'ABC'\r\n>> "} |
| } |
| |
| # require('fs').appendFile() |
| |
| njs_run {"./test/js/fs_appendFile.js" "ABCD" "Buffer" "1"} "BCDBCD" |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "DataView"} "ABCABC" |
| njs_run {"./test/js/fs_appendFile.js" "414243" "Object" "hex"} "ABCABC" |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "String"} "ABCABC" |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "Symbol"} "TypeError: Cannot convert a Symbol value to a string*" |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "Uint8Array"} "ABCABC" |
| |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "String" "utf8"} "ABC" |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "String" "utf8" "0o666"} "ABC" |
| njs_run {"./test/js/fs_appendFile.js" "ABC" "String" "utf8" "0o222"} "Error: Permission denied*" |
| njs_run {"./test/js/fs_appendFile.js" "414243" "String" "hex"} "ABC" |
| njs_run {"./test/js/fs_appendFile.js" "QUJD" "String" "base64"} "ABC" |
| njs_run {"./test/js/fs_appendFile.js" "QUJD" "String" "base64url"} "ABC" |
| |
| # require('fs').appendFileSync() |
| |
| njs_run {"./test/js/fs_appendFileSync.js" "ABCD" "Buffer" "1"} "BCDBCD" |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "DataView"} "ABCABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "414243" "Object" "hex"} "ABCABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "String"} "ABCABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "Symbol"} "TypeError: Cannot convert a Symbol value to a string*" |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "Uint8Array"} "ABCABC" |
| |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "String" "utf8"} "ABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "String" "utf8" "0o666"} "ABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "ABC" "String" "utf8" "0o222"} "Error: Permission denied*" |
| njs_run {"./test/js/fs_appendFileSync.js" "414243" "String" "hex"} "ABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "QUJD" "String" "base64"} "ABC" |
| njs_run {"./test/js/fs_appendFileSync.js" "QUJD" "String" "base64url"} "ABC" |
| |
| # require('fs').renameSync() |
| |
| njs_test { |
| {"var fs = require('fs'), mktemp = ()=> `/tmp/njs_${Math.round(Math.random() * 1000000)}`\r\n" |
| "undefined\r\n>> "} |
| {"var fn1 = mktemp(), fn2 = mktemp();\r\n" |
| "undefined\r\n>> "} |
| {"fs.writeFileSync(fn1, 'ABC')\r\n" |
| "undefined\r\n>> "} |
| {"fs.renameSync(fn1, fn2)\r\n" |
| "undefined\r\n>> "} |
| {"String(fs.readFileSync(fn2))\r\n" |
| "'ABC'\r\n>> "} |
| } |
| |
| njs_test { |
| {"var fs = require('fs'), fn = './build/test/file2'\r\n" |
| "undefined\r\n>> "} |
| {"fs.writeFileSync(fn, 'ABC')\r\n" |
| "undefined\r\n>> "} |
| {"fs.renameSync(fn, 'test/fs/')\r\n" |
| "Error: Not a directory*"} |
| } |
| |
| # require('fs').realpathSync() |
| |
| njs_test { |
| {"var fs = require('fs')\r\n" |
| "undefined\r\n>> "} |
| {"fs.realpathSync('./build/test/..').endsWith('build')\r\n" |
| "true\r\n>> "} |
| {"fs.realpathSync('./build/test/..', {encoding:'buffer'}) instanceof Buffer\r\n" |
| "true\r\n>> "} |
| } |
| |
| njs_run {"-c" "setTimeout(() => {console.log('A'.repeat(1024))}, 0); ref"} \ |
| "^Thrown: |
| ReferenceError: \"ref\" is not defined |
| at main \\\(string:1\\\)\n$" |
| |
| njs_run {"-c" "setTimeout(() => {ref}, 0); setTimeout(() => {console.log('A'.repeat(1024))}, 0)"} \ |
| "^Thrown: |
| ReferenceError: \"ref\" is not defined |
| at anonymous \\\(string:1\\\) |
| at main \\\(string:1\\\)\n$" |
| |
| # Modules |
| |
| njs_run {"-p" "test/module/libs" "./test/module/normal.js"} \ |
| "passed!" |
| |
| njs_run {"-p" "test/module/libs/" "./test/module/normal.js"} \ |
| "passed!" |
| |
| njs_run {"-p" "test/module" "-p" "test/module/libs" "./test/module/normal.js"} \ |
| "passed!" |
| |
| njs_run {"./test/module/normal.js"} \ |
| "SyntaxError: Cannot find module \"hash.js\" in lib1.js:13" |
| |
| njs_run {"-p" "test/module/libs" "./test/module/exception.js"} \ |
| "at error \\(sub1.js:6\\)" |
| |
| njs_run {"-p" "test/module" "./test/module/recursive.js"} \ |
| "SyntaxError: Cannot import itself \"./test/module/recursive.js\" in recursive.js:1" |
| |
| # CLI OPTIONS |
| |
| # help |
| |
| njs_run {"-h"} "Options" |
| |
| # ast |
| |
| njs_run {"-a" "-c" "console.log(1*2)"} "{\"name\": \"END\"" |
| |
| # command |
| |
| njs_run {"-c" "console.log(\"a b c\")"} "a b c" |
| |
| njs_run {"-c" "console.log("} "SyntaxError: Unexpected end of input in string:1" |
| |
| |
| # process |
| |
| njs_run {"-c" "console.log(typeof process.argv)"} "object" |
| njs_run {"-c" "console.log(process.argv.slice(2))" "AAA"} "AAA" |
| |
| njs_run {"-c" "console.log(typeof process.env)"} "object" |
| njs_run {"-c" "console.log(process.env.HOME != undefined)"} "true" |
| njs_run {"-c" "console.log(process.env.___UNDECLARED != undefined)"} "false" |
| |
| njs_run {"-c" "console.log(process.pid)"} "\\d+" |
| |
| njs_run {"-c" "console.log(process.ppid)"} "\\d+" |
| |
| |
| # script args |
| |
| njs_run {"test/script_args.js" "A" "B"} "AB" |
| |
| # disassemble |
| |
| njs_test { |
| {"1+1\r\n" |
| " 1 | 00000 ADD*\r\n*2"} |
| {"__unknown\r\n" |
| " 1 | 00000 GLOBAL GET*\r\n*REFERENCE ERROR*"} |
| {"for (var n in [1]) {try {break} finally{}}\r\n" |
| " 1 | 00000 ARRAY*\r\n*TRY BREAK*PROP NEXT*-*\r\n\r\nundefined"} |
| {"(function() {try {return} finally{}})()\r\n" |
| " 1 | 00000 TRY START*\r\n*TRY RETURN*\r\n\r\nundefined"} |
| } "-d" |
| |
| # modules |
| |
| # FIXME: |
| # During import, the variable is declared regardless of the result of the import. |
| # Because of this, in the console mode, checking the variable after the import |
| # error may give an incorrect result. |
| # |
| # For example: |
| # {"import ref from 'ref_exception.js'\r\n" |
| # "ReferenceError: \"undeclared\" is not defined"} |
| # {"ref\r\n" |
| # "ReferenceError: \"ref\" is not defined\r\n"} |
| |
| njs_test { |
| {"import lib1 from 'lib1.js'; import lib2 from 'lib1.js'\r\n" |
| "undefined\r\n"} |
| {"lib2.inc()\r\n" |
| "undefined\r\n"} |
| {"lib1.get()\r\n" |
| "1\r\n"} |
| {"import m from 'return.js'\r\n" |
| "Illegal return statement in return.js:1\r\n"} |
| {"import m from 'empty.js'\r\n" |
| "export statement is required in empty.js:1\r\n"} |
| {"import m from 'export.js'\r\n" |
| "Identifier \"default\" has already been declared in export.js:5\r\n"} |
| {"import m from 'export_non_default.js'\r\n" |
| "Non-default export is not supported in export_non_default.js:3\r\n"} |
| {"import m from 'export_non_assignment.js'\r\n" |
| "Unexpected token \",\" in export_non_assignment.js:1\r\n"} |
| {"import ref from 'ref_exception.js'\r\n" |
| "ReferenceError: \"undeclared\" is not defined"} |
| {"var ref\r\n" |
| "undefined\r\n"} |
| {"import ref from 'ref_exception.js'\r\n" |
| "ReferenceError: \"undeclared\" is not defined"} |
| {"import m from 'declaration_exception.js'\r\n" |
| "SyntaxError: \"f\" has already been declared in declaration_exception.js:6"} |
| {"import m from 'loading_exception.js'\r\n" |
| "Error: loading exception\r\n at module \\(loading_exception.js:1\\)"} |
| {"import lib3 from 'lib1.js'\r\n" |
| "undefined\r\n"} |
| } "-p test/module/ -p test/module/libs/" |
| |
| njs_test { |
| {"import m from 'export_name.js'\r\n" |
| "undefined\r\n"} |
| {"m.prod(3,4)\r\n" |
| "12\r\n"} |
| {"import m from 'export_expression.js'\r\n" |
| "undefined\r\n"} |
| {"m.sum(3,4)\r\n" |
| "7\r\n"} |
| {"import m from 'export_expression2.js'\r\n" |
| "undefined\r\n"} |
| {"m.prod(3,4)\r\n" |
| "12\r\n"} |
| } "-p test/module/" |
| |
| njs_run {"-q" "./test/module/normal.js"} \ |
| "SyntaxError: Cannot find module \"hash.js\" in 13" |
| |
| njs_run {"-p" "test/module/libs/" "-d" "./test/module/normal.js"} \ |
| "passed!" |
| |
| # sandboxing |
| |
| njs_test { |
| {"var fs = require('fs')\r\n" |
| "Error: Cannot find module \"fs\"\r\n"} |
| } "-s" |
| |
| njs_test { |
| {"var crypto = require('crypto')\r\n" |
| "undefined\r\n"} |
| } "-s" |
| |
| |
| # safe mode |
| |
| njs_test { |
| {"new Function()\r\n" |
| "TypeError: function constructor is disabled in \"safe\" mode\r\n"} |
| {"(new Function('return this'))() === globalThis\r\n" |
| "true\r\n"} |
| {"new Function('return this;')\r\n" |
| "[Function]"} |
| {"new Function('return thi')\r\n" |
| "TypeError: function constructor is disabled in \"safe\" mode\r\n"} |
| } "-u" |
| |
| |
| # source type |
| |
| njs_test { |
| {"this\r\n" |
| "this\r\nundefined"} |
| {"(() => this)()\r\n" |
| "(() => this)()\r\nundefined"} |
| } "-t module" |
| |
| njs_test { |
| {"this.NaN\r\n" |
| "this.NaN\r\nNaN"} |
| } "-t script" |
| |
| |
| # version |
| |
| njs_run {"-v"} "\\d+\.\\d+\.\\d+" |
| |
| |
| # Promise |
| |
| njs_run {"./test/js/promise_set_timeout.js"} \ |
| "One,Two,Three |
| One,Two,Three,Four,Five,Six,Seven,Eight" |
| |
| njs_run {"./test/js/promise_s1.js"} \ |
| "One |
| Two |
| Three |
| 123 |
| Four |
| Five |
| Six |
| Seven |
| Eight" |
| |
| njs_run {"./test/js/promise_s2.js"} \ |
| "One |
| Two |
| Three" |
| |
| njs_run {"./test/js/promise_s3.js"} \ |
| "One |
| Two |
| Three |
| Rejected: Error: Blah" |
| |
| njs_run {"./test/js/promise_s4.js"} \ |
| "Error: Oh my" |
| |
| njs_run {"./test/js/promise_s5.js"} \ |
| "Success" |
| |
| njs_run {"./test/js/promise_s6.js"} \ |
| "1" |
| |
| njs_run {"./test/js/promise_s7.js"} \ |
| "true |
| fulfilled!" |
| |
| njs_run {"./test/js/promise_s8.js"} \ |
| "Ok" |
| |
| njs_run {"./test/js/promise_s9.js"} \ |
| "S |
| true" |
| |
| njs_run {"./test/js/promise_s10.js"} \ |
| "One |
| Two |
| Three |
| Oh no" |
| |
| njs_run {"./test/js/promise_s11.js"} \ |
| "end |
| S: all |
| R: all" |
| |
| njs_run {"./test/js/promise_s12.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s13.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s14.js"} \ |
| "TypeError: oops |
| at anonymous \\\(promise_s14.js:5\\\) |
| at native \\\(native\\\) |
| at main \\\(promise_s14.js:9\\\) |
| |
| Done" |
| |
| njs_run {"./test/js/promise_s15.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s16.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s17.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s18.js"} \ |
| "State 1 |
| State 2 |
| State 3 |
| State 4 |
| State 5 |
| Done" |
| |
| njs_run {"./test/js/promise_s19.js"} \ |
| "Throw! |
| undefined |
| Reject! |
| Done" |
| |
| njs_run {"./test/js/promise_s20.js"} \ |
| "true |
| Done" |
| |
| njs_run {"./test/js/promise_s21.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s22.js"} \ |
| "true |
| Done" |
| |
| njs_run {"./test/js/promise_s23.js"} \ |
| "true |
| Done" |
| |
| njs_run {"./test/js/promise_s24.js"} \ |
| "true" |
| |
| njs_run {"./test/js/promise_s25.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_s26.js"} \ |
| "BoxedPromise.constructor |
| BoxedPromise.prototype.then |
| BoxedPromise resolve OK |
| BoxedPromise.constructor |
| BoxedPromise.prototype.then |
| BoxedPromise reject OK |
| BoxedPromise.constructor |
| BoxedPromise.prototype.then |
| BoxedPromise.prototype.then |
| BoxedPromise chain OK |
| BoxedPromise.prototype.then |
| BoxedPromise finally OK |
| BoxedPromise sync done |
| |
| BoxedPromise.prototype.then |
| BoxedPromise.prototype.then |
| resolved BoxedPromise |
| rejected BoxedPromise |
| then BoxedPromise |
| then BoxedPromise |
| finally BoxedPromise |
| BoxedPromise.constructor |
| BoxedPromise.prototype.then |
| BoxedPromise.prototype.then |
| BoxedPromise async done |
| |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| PatchedPromise resolve OK |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| PatchedPromise reject OK |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| PatchedPromise chain OK |
| PatchedPromise.constructor |
| PatchedPromise finally OK |
| PatchedPromise sync done |
| |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| resolved PatchedPromise |
| rejected PatchedPromise |
| then PatchedPromise |
| then PatchedPromise |
| finally PatchedPromise |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| PatchedPromise.constructor |
| PatchedPromise async done" |
| |
| njs_run {"./test/js/fs_promises_001.js"} \ |
| "init ok true |
| short circut ok true |
| chain ok true |
| error 1 ok true |
| error 2 ok true |
| errors ok" |
| |
| njs_run {"./test/js/fs_promises_002.js"} \ |
| "testSync ok true |
| testCallback ok true |
| testPromise ok true" |
| |
| njs_run {"./test/js/fs_promises_003.js"} \ |
| "test fs.unlinkSync |
| test fs.unlink |
| test fsp.unlink" |
| |
| njs_run {"./test/js/fs_promises_004.js"} \ |
| "test fs.symlinkSync |
| test fs.symlink |
| test fsp.symlink" |
| |
| njs_run {"./test/js/fs_promises_005.js"} \ |
| "test fs.mkdirSync |
| test fs.mkdir |
| test fsp.mkdir" |
| |
| njs_run {"./test/js/fs_promises_006.js"} \ |
| "test fs.renameSync |
| test fs.rename |
| test fsp.rename" |
| |
| njs_run {"./test/js/fs_promises_007.js"} \ |
| "test fs.readdirSync |
| test fs.readdir |
| test fsp.readdir" |
| |
| njs_run {"./test/js/fs_promises_008.js"} \ |
| "test recursive fs.mkdirSync" |
| |
| njs_run {"./test/js/fs_promises_009.js"} \ |
| "test recursive fs.rmdirSync" |
| |
| njs_run {"./test/js/promise_then_throw_finally_catch.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_catch_throw.js"} \ |
| "Error: unhandled promise rejection: ReferenceError: \"nonExsistingInCatch\" is not defined" |
| |
| njs_run {"./test/js/promise_then_throw.js"} \ |
| "Error: unhandled promise rejection: ReferenceError: \"nonExsisting\" is not defined" |
| |
| njs_run {"./test/js/promise_then_throw_catch.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_catch_then_throw_catch.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_finally.js"} \ |
| "here |
| Thrown: |
| Error: unhandled promise rejection: nope" |
| |
| njs_run {"./test/js/promise_finally_throw.js"} \ |
| "Error: unhandled promise rejection: ReferenceError: \"nonExsistingInFinally\" is not defined" |
| |
| njs_run {"./test/js/promise_finally_throw_catch.js"} \ |
| "Done" |
| |
| njs_run {"./test/js/promise_two_then_throw.js"} \ |
| "Error: unhandled promise rejection: ReferenceError: \"nonExsistingOne\" is not defined" |
| |
| njs_run {"./test/js/promise_two_first_then_throw.js"} \ |
| "Error: unhandled promise rejection: ReferenceError: \"nonExsistingOne\" is not defined" |
| |
| njs_run {"./test/js/promise_reject_catch.js"} \ |
| "rejected test" |
| |
| njs_run {"./test/js/promise_reject_post_catch.js"} \ |
| "Error: unhandled promise rejection: undefined" |
| |
| njs_run {"./test/js/promise_all.js"} \ |
| "resolved:\\\[\\\['one','two'],\\\['three','four']]" |
| |
| njs_run {"./test/js/promise_all_throw.js"} \ |
| "rejected:foo" |
| |
| njs_run {"./test/js/promise_allSettled.js"} \ |
| "resolved:resolved:F:0,3,42,here|R:finally,finally after rejected,foo,here too,yes" |
| |
| njs_run {"./test/js/promise_allSettled_string.js"} \ |
| "resolved:F:a,b,c|R:" |
| |
| njs_run {"./test/js/promise_any.js"} \ |
| "resolved:4" |
| |
| njs_run {"./test/js/promise_any_all_rejected.js"} \ |
| "reject:AggregateError: All promises were rejected" |
| |
| njs_run {"./test/js/promise_race.js"} \ |
| "resolved:one" |
| |
| njs_run {"./test/js/promise_race_throw.js"} \ |
| "rejected:one" |