From 2ca356c7259cca3deda3f995b0bad6249a42df01 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Tue, 21 Dec 2021 15:49:13 +0000 Subject: [PATCH] Tests: moving module tests into separate test suites. --- src/test/njs_unit_test.c | 4601 +++++++++++++++++++------------------- 1 file changed, 2315 insertions(+), 2286 deletions(-) diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index aa296d46..4f13f14c 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -17710,2952 +17710,2957 @@ static njs_unit_test_t njs_test[] = { njs_str("require.hasOwnProperty('length')"), njs_str("true") }, - { njs_str("var fs = require('fs'); typeof fs"), - njs_str("object") }, - - { njs_str("var fs = require('fs'); Object.isExtensible(fs)"), - njs_str("true") }, + /* setTimeout(). */ - { njs_str("require('fs') === require('fs')"), - njs_str("true") }, + { njs_str("setTimeout()"), + njs_str("TypeError: too few arguments") }, - { njs_str("require('fs').a = 1; require('fs').a"), - njs_str("1") }, + { njs_str("setTimeout(function(){})"), + njs_str("InternalError: not supported by host environment") }, - /* require('fs').readFile() */ + { njs_str("setTimeout(function(){}, 12)"), + njs_str("InternalError: not supported by host environment") }, - { njs_str("var fs = require('fs');" - "fs.readFile()"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + /* clearTimeout(). */ - { njs_str("var fs = require('fs');" - "var path = Buffer.from('/broken'); path[3] = 0;" - "fs.readFile(path)"), - njs_str("TypeError: \"path\" must be a Buffer without null bytes") }, + { njs_str("clearTimeout()"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path')"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("clearTimeout(123)"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path', 'utf8')"), - njs_str("TypeError: \"callback\" must be a function") }, + /* Trick: number to boolean. */ - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path', {flag:'xx'})"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("var a = 0; !!a"), + njs_str("false") }, - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path', {flag:'xx'}, 1)"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("var a = 5; !!a"), + njs_str("true") }, - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path', {flag:'xx'}, function () {})"), - njs_str("TypeError: Unknown file open flags: \"xx\"") }, + /* Trick: flooring. */ - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path', {encoding:'ascii'}, function () {})"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("var n = -10.12345; ~~n"), + njs_str("-10") }, - { njs_str("var fs = require('fs');" - "fs.readFile('/njs_unknown_path', 'ascii', function () {})"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("var n = 10.12345; ~~n"), + njs_str("10") }, - /* require('fs').readFileSync() */ + /* es5id: 8.2_A1_T1 */ + /* es5id: 8.2_A1_T2 */ - { njs_str("var fs = require('fs');" - "fs.readFileSync()"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + { njs_str("var x = null;"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.readFileSync({})"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + /* es5id: 8.2_A2 */ - { njs_str("var fs = require('fs');" - "fs.readFileSync('/njs_unknown_path', {flag:'xx'})"), - njs_str("TypeError: Unknown file open flags: \"xx\"") }, + { njs_str("var null;"), + njs_str("SyntaxError: Unexpected token \"null\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.readFileSync(Buffer.from('/njs_unknown_path'), {encoding:'ascii'})"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + /* es5id: 8.2_A3 */ - { njs_str("var fs = require('fs');" - "fs.readFileSync('/njs_unknown_path', 'ascii')"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("typeof(null) === \"object\""), + njs_str("true") }, - { njs_str("var fs = require('fs');" - "fs.readFileSync('/njs_unknown_path', true)"), - njs_str("TypeError: Unknown options type: \"boolean\" (a string or object required)") }, + /* Module. */ + { njs_str("import;"), + njs_str("SyntaxError: Non-default import is not supported in 1") }, - /* require('fs').writeFile() */ + { njs_str("import {x} from y"), + njs_str("SyntaxError: Non-default import is not supported in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile()"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + { njs_str("import x from y"), + njs_str("SyntaxError: Unexpected token \"y\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile({}, '', function () {})"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + { njs_str("import x from {"), + njs_str("SyntaxError: Unexpected token \"{\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path')"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("import x from ''"), + njs_str("SyntaxError: Cannot find module \"\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '')"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("import x from 'crypto'"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '', undefined)"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("import x from 'crypto' 1"), + njs_str("SyntaxError: Unexpected token \"1\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '', 'utf8')"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("if (1) {import x from 'crypto'}"), + njs_str("SyntaxError: Illegal import statement in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '', {flag:'xx'}, function () {})"), - njs_str("TypeError: Unknown file open flags: \"xx\"") }, + { njs_str("export"), + njs_str("SyntaxError: Illegal export statement in 1") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '', {encoding:'ascii'}, function () {})"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("Object.assign(undefined)"), + njs_str("TypeError: cannot convert null or undefined to object") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '', 'ascii', function () {})"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("Object.assign(null)"), + njs_str("TypeError: cannot convert null or undefined to object") }, - { njs_str("var fs = require('fs');" - "fs.writeFile('/njs_unknown_path', '', true, function () {})"), - njs_str("TypeError: Unknown options type: \"boolean\" (a string or object required)") }, + { njs_str("Object.assign({x:123}).toString()"), + njs_str("[object Object]") }, - /* require('fs').writeFileSync() */ + { njs_str("Object.assign({x:123}).x"), + njs_str("123") }, - { njs_str("var fs = require('fs');" - "fs.writeFileSync()"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + { njs_str("Object.assign(true)"), + njs_str("true") }, - { njs_str("var fs = require('fs');" - "fs.writeFileSync({}, '')"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + { njs_str("Object.assign(123)"), + njs_str("123") }, - { njs_str("var fs = require('fs');" - "fs.writeFileSync('/njs_unknown_path', '', {flag:'xx'})"), - njs_str("TypeError: Unknown file open flags: \"xx\"") }, + { njs_str("var o1 = {a:1, b:1, c:1}; var o2 = {b:2, c:2}; " + "var o3 = {c:3}; var obj = Object.assign({}, o1, o2, o3); " + "Object.values(obj);"), + njs_str("1,2,3") }, - { njs_str("var fs = require('fs');" - "fs.writeFileSync('/njs_unknown_path', '', {encoding:'ascii'})"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("var v1 = 'abc'; var v2 = true; var v3 = 10; " + "var obj = Object.assign({}, v1, null, v2, undefined, v3); " + "Object.values(obj);"), + njs_str("a,b,c") }, - { njs_str("var fs = require('fs');" - "fs.writeFileSync('/njs_unknown_path', '', 'ascii')"), - njs_str("TypeError: \"ascii\" encoding is not supported") }, + { njs_str("Object.assign(true, {a:123})"), + njs_str("true") }, - { njs_str("var fs = require('fs');" - "fs.writeFileSync('/njs_unknown_path', '', true)"), - njs_str("TypeError: Unknown options type: \"boolean\" (a string or object required)") }, + { njs_str("Object.assign(true, {a:123}).a"), + njs_str("123") }, - /* require('fs').renameSync() */ + { njs_str("var y = Object.create({s:123}); y.z = 456;" + "Object.assign({}, y).s;"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.renameSync()"), - njs_str("TypeError: \"oldPath\" must be a string or Buffer") }, + { njs_str("var obj = {s:123}; Object.defineProperty(obj," + "'p1', {value:12, enumerable:false});" + "Object.assign({}, obj).p1"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.renameSync('/njs_unknown_path')"), - njs_str("TypeError: \"newPath\" must be a string or Buffer") }, + { njs_str("var obj = {s:123}; Object.defineProperty(obj," + "'x', {value:12, writable:false});" + "Object.assign(obj, {x:4})"), + njs_str("TypeError: Cannot assign to read-only property \"x\" of object") }, - { njs_str("var fs = require('fs');" - "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" - ".map((x) => { try { fs.renameSync(x, '/njs_unknown_path'); } " - " catch (e) { return (e instanceof TypeError); } })" - ".every((x) => x === true)"), - njs_str("true")}, + { njs_str("var obj = {foo:1, get bar() {return 2;}};" + "var copy = Object.assign({}, obj);" + "Object.getOwnPropertyDescriptor(copy, 'bar').get"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" - ".map((x) => { try { fs.renameSync('/njs_unknown_path', x); } " - " catch (e) { return (e instanceof TypeError); } })" - ".every((x) => x === true)"), - njs_str("true")}, + { njs_str("try{var x = Object.defineProperty({}, 'foo'," + "{value:1, writable:false});" + "Object.assign(x, {bar:2}, {foo:2});}catch(error){};" + "x.bar"), + njs_str("2") }, - /* require('fs').access() */ + { njs_str("var a = Object.defineProperty({}, 'a'," + "{get(){Object.defineProperty(this, 'b'," + "{value:2,enumerable:false});" + "return 1}, enumerable:1}); a.b =1;" + "var x = Object.assign({}, a);x.b;"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.access()"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + /* let and const */ - { njs_str("var fs = require('fs');" - "fs.access('/njs_unknown_path')"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("var let = 123;" + "let"), + njs_str("SyntaxError: Unexpected token \"let\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.access('/njs_unknown_path', fs.constants.F_OK)"), - njs_str("TypeError: \"callback\" must be a function") }, + { njs_str("var const = 123"), + njs_str("SyntaxError: Unexpected token \"const\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.access('/njs_unknown_path', 'fail', function () {})"), - njs_str("TypeError: \"mode\" must be a number") }, + /* Async */ - /* require('fs').accessSync() */ + { njs_str("var async;" + "function f() {" + " async\n" + " function foo() {}" + "}" + "f()"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.accessSync()"), - njs_str("TypeError: \"path\" must be a string or Buffer") }, + { njs_str("var async;" + "function f() {" + " async;" + " function foo() {}" + "}" + "f()"), + njs_str("undefined") }, - { njs_str("var fs = require('fs');" - "fs.accessSync('/njs_unknown_path', 'fail')"), - njs_str("TypeError: \"mode\" must be a number") }, + { njs_str("var async;" + "async\n" + "function foo() {}"), + njs_str("undefined") }, - { njs_str("var " - "fs = require('fs')," - "func = [" - "'access'," - "'accessSync'," - "'readFile'," - "'readFileSync'," - "'writeFile'," - "'writeFileSync'," - "'appendFile'," - "'appendFileSync'," - "'rename'," - "'renameSync'," - "'symlink'," - "'symlinkSync'," - "'unlink'," - "'unlinkSync'," - "'realpath'," - "'realpathSync'," - "'mkdir'," - "'mkdirSync'," - "'rmdir'," - "'rmdirSync'," - "'readdir'," - "'readdirSync'," - "]," - "test = (fname) =>" - "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" - ".map((x) => { try { fs[fname](x); } " - " catch (e) { return (e instanceof TypeError); } })" - ".every((x) => x === true);" - "func.map(test).every((x) => x)"), - njs_str("true")}, + { njs_str("new\""), + njs_str("SyntaxError: Unterminated string \"\"\" in 1") }, - /* require('fs').promises */ + { njs_str("new\"\\UFFFF"), + njs_str("SyntaxError: Unterminated string \"\"\\UFFFF\" in 1") }, - { njs_str("var fs = require('fs');" - "typeof fs.promises"), - njs_str("object") }, + { njs_str("new/la"), + njs_str("SyntaxError: Unterminated RegExp \"/la\" in 1") }, - { njs_str("var " - "fs = require('fs').promises," - "func = [" - "'access'," - "'readFile'," - "'writeFile'," - "'appendFile'," - "'rename'," - "'symlink'," - "'unlink'," - "'realpath'," - "'mkdir'," - "'rmdir'," - "'readdir'," - "];" - "func.every((x) => typeof fs[x] == 'function')"), - njs_str("true")}, + { njs_str("{name; {/ / /}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - /* require('fs').constants */ + { njs_str("[(]"), + njs_str("SyntaxError: Unexpected token \"]\" in 1") }, - { njs_str("var fs = require('fs');" - "typeof fs.constants"), - njs_str("object") }, + { njs_str("[...]"), + njs_str("SyntaxError: Unexpected token \"]\" in 1") }, - { njs_str("var " - "fsc = require('fs').constants," - "items = [" - "'F_OK'," - "'R_OK'," - "'W_OK'," - "'X_OK'," - "];" - "items.every((x) => typeof fsc[x] == 'number')"), - njs_str("true")}, + { njs_str("switch () {}"), + njs_str("SyntaxError: Unexpected token \")\" in 1") }, - /* require('fs').Dirent */ + { njs_str("switch ([(]) {}"), + njs_str("SyntaxError: Unexpected token \"]\" in 1") }, - { njs_str("var fs = require('fs');" - "typeof fs.Dirent"), - njs_str("function") }, + { njs_str("{{}{-}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var fs = require('fs');" - "fs.Dirent('file', 123)"), - njs_str("TypeError: the Dirent constructor must be called with new") }, + { njs_str("{{}{+}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var fs = require('fs');" - "var e = new fs.Dirent('file', 123); [e.name, e.type]"), - njs_str("file,123") }, + { njs_str("{{}{delete}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var " - "fs = require('fs')," - "e = new fs.Dirent('file', 0)," - "func = [" - "'isDirectory'," - "'isFile'," - "'isBlockDevice'," - "'isCharacterDevice'," - "'isSymbolicLink'," - "'isFIFO'," - "'isSocket'," - "];" - "func.every((x) => typeof e[x] == 'function')"), - njs_str("true")}, + { njs_str("{{}{++}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - /* require('crypto').createHash() */ + { njs_str("{{}{++1}"), + njs_str("ReferenceError: Invalid left-hand side in prefix operation in 1") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "[Object.prototype.toString.call(h), njs.dump(h),h]"), - njs_str("[object Hash],Hash {},[object Hash]") }, + { njs_str("{{}{1++}"), + njs_str("ReferenceError: Invalid left-hand side in postfix operation in 1") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "var Hash = h.constructor; " - "Hash('sha1').update('AB').digest('hex')"), - njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d") }, + { njs_str("{{}{1/}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "h.constructor.name"), - njs_str("Hash") }, + { njs_str("{{}{1>>}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHash.bind(undefined, 'md5');" - "['hex', 'base64', 'base64url'].map(e => {" - " var h = hash().update('AB').digest().toString(e);" - " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" - " var h3 = hash().update('A').update('B').digest(e);" - " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" - " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" - " return h;" - "})"), - njs_str("b86fc6b051f63d73de262d4c34e3a0a9," - "uG/GsFH2PXPeJi1MNOOgqQ==," - "uG_GsFH2PXPeJi1MNOOgqQ") }, + { njs_str("{{}{r=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" - "['hex', 'base64', 'base64url'].map(e => {" - " var h = hash().update('4142', 'hex').digest().toString(e);" - " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" - " var h3 = hash().update('A').update('B').digest(e);" - " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" - " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" - " return h;" - "})"), - njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d," - "BtlFlCqiamG+GMPiK/GbvKjdK10=," - "BtlFlCqiamG-GMPiK_GbvKjdK10") }, + { njs_str("{{}{var a = }"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" - "['hex', 'base64', 'base64url'].every(e => {" - " var h = hash().digest(e);" - " var h2 = hash().update('').digest(e);" - " if (h !== h2) {throw new Error(`digest($e):$h != update('').digest($e):$h2`)};" - " return true;" - "})"), - njs_str("true") }, + { njs_str("{{}T=>}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" - "[" - " ['AB']," - " ['4142', 'hex']," - " ['QUI=', 'base64']," - " ['QUI', 'base64url']" - "].every(args => {" - " return hash().update(args[0], args[1]).digest('hex') === '06d945942aa26a61be18c3e22bf19bbca8dd2b5d';" - "})"), - njs_str("true") }, + { njs_str("{{}a = b +}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha256');" - "['hex', 'base64', 'base64url'].map(e => {" - " var h = hash().update('AB').digest().toString(e);" - " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" - " var h3 = hash().update('A').update('B').digest(e);" - " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" - " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" - " return h;" - "})"), - njs_str("38164fbd17603d73f696b8b4d72664d735bb6a7c88577687fd2ae33fd6964153," - "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH/SrjP9aWQVM=," - "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH_SrjP9aWQVM") }, + { njs_str("{{}a = b -}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHash;" - "njs.dump(['', 'abc'.repeat(100)].map(v => {" - " return ['md5', 'sha1', 'sha256'].map(h => {" - " return hash(h).update(v).digest('hex');" - " })" - "}))"), - njs_str("[['d41d8cd98f00b204e9800998ecf8427e'," - "'da39a3ee5e6b4b0d3255bfef95601890afd80709'," - "'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855']," - "['f571117acbd8153c8dc3c81b8817773a'," - "'c95466320eaae6d19ee314ae4f135b12d45ced9a'," - "'d9f5aeb06abebb3be3f38adec9a2e3b94228d52193be923eb4e24c9b56ee0930']]") }, + { njs_str("{{}a = b *}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHash()"), - njs_str("TypeError: algorithm must be a string") }, + { njs_str("{{}a = b /}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHash([])"), - njs_str("TypeError: algorithm must be a string") }, + { njs_str("{{}a = b %}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHash('sha512')"), - njs_str("TypeError: not supported algorithm: \"sha512\"") }, + { njs_str("{{}a = b++}"), + njs_str("ReferenceError: \"a\" is not defined") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update()"), - njs_str("TypeError: data argument \"undefined\" is not a string or Buffer-like object") }, + { njs_str("{{}a = b--}"), + njs_str("ReferenceError: \"a\" is not defined") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update({})"), - njs_str("TypeError: data argument \"object\" is not a string or Buffer-like object") }, + { njs_str("{{}a =}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').digest('latin1')"), - njs_str("TypeError: Unknown digest encoding: \"latin1\"") }, + { njs_str("{{}a +=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("require('crypto').createHash('sha1').digest() instanceof Buffer"), - njs_str("true") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').digest('hex'); h.digest('hex')"), - njs_str("Error: Digest already called") }, + { njs_str("{{}a -=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').digest('hex'); h.update('B')"), - njs_str("Error: Digest already called") }, + { njs_str("{{}a *=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("typeof require('crypto').createHash('md5')"), - njs_str("object") }, + { njs_str("{{}a /=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - /* require('crypto').createHmac() */ + { njs_str("{{}a %=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha1', '');" - "[Object.prototype.toString.call(h), njs.dump(h),h]"), - njs_str("[object Hmac],Hmac {},[object Hmac]") }, + { njs_str("{{}a ===}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'md5', '');" - "['hex', 'base64', 'base64url'].map(e => {" - " var h = hmac().update('AB').digest().toString(e);" - " var h2 = hmac().update(Buffer.from('XABX').subarray(1,3)).digest(e);" - " var h3 = hmac().update('A').update('B').digest(e);" - " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" - " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" - " return h;" - "})"), - njs_str("9e0e9e545ef63d41dfb653daecf8ebc7," - "ng6eVF72PUHftlPa7Pjrxw==," - "ng6eVF72PUHftlPa7Pjrxw") }, + { njs_str("{{}a ==}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'sha1', '');" - "['hex', 'base64', 'base64url'].map(e => {" - " var h = hmac().update('AB').digest().toString(e);" - " var h2 = hmac().update(Buffer.from('XABX').subarray(1,3)).digest(e);" - " var h3 = hmac().update('A').update('B').digest(e);" - " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" - " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" - " return h;" - "})"), - njs_str("d32c0b6637cc2dfe4670f3fe48ef4434123c4810," - "0ywLZjfMLf5GcPP+SO9ENBI8SBA=," - "0ywLZjfMLf5GcPP-SO9ENBI8SBA") }, + { njs_str("{{}a !=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hash = require('crypto').createHmac.bind(undefined, 'sha1', '');" - "[" - " ['AB']," - " ['4142', 'hex']," - " ['QUI=', 'base64']," - " ['QUI', 'base64url']" - "].every(args => {" - " return hash().update(args[0], args[1]).digest('hex') === 'd32c0b6637cc2dfe4670f3fe48ef4434123c4810';" - "})"), - njs_str("true") }, + { njs_str("{{}a !==}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'sha256', '');" - "['hex', 'base64', 'base64url'].map(e => {" - " var h = hmac().update('AB').digest().toString(e);" - " var h2 = hmac().update(Buffer.from('AB')).digest(e);" - " var h3 = hmac().update('A').update('B').digest(e);" - " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" - " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" - " return h;" - "})"), - njs_str("d53400095496267cf02e5dbd4b0bf9fbfb5f36f311ea7d9809af5487421743e3," - "1TQACVSWJnzwLl29Swv5+/tfNvMR6n2YCa9Uh0IXQ+M=," - "1TQACVSWJnzwLl29Swv5-_tfNvMR6n2YCa9Uh0IXQ-M") }, + { njs_str("{{}a >}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var hmac = require('crypto').createHmac;" - "njs.dump(['', 'abc'.repeat(100)].map(v => {" - " return ['md5', 'sha1', 'sha256'].map(h => {" - " return hmac(h, Buffer.from('secret')).update(v).digest('hex');" - " })" - "}))"), - njs_str("[['5c8db03f04cec0f43bcb060023914190'," - "'25af6174a0fcecc4d346680a72b7ce644b9a88e8'," - "'f9e66e179b6747ae54108f82f8ade8b3c25d76fd30afde6c395822c530196169']," - "['91eb74a225cdd3bbfccc34396c6e3ac5'," - "'0aac71e3a813a7acc4a809cfdedb2ecba04ffc5e'," - "'8660d2d51d6f20f61d5aadfb6c43df7fd05fc2fc4967d8aec1846f3d9ec03987']]") }, + { njs_str("{{}a <}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha1', '');" - "var Hmac = h.constructor; " - "Hmac('sha1', '').digest('hex')"), - njs_str("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d") }, + { njs_str("{{}a <=}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha1', '');" - "h.constructor.name"), - njs_str("Hmac") }, + { njs_str("{{}a &&}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("require('crypto').createHmac('sha1', '').digest() instanceof Buffer"), - njs_str("true") }, + { njs_str("{{}a ||}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha256', 'A'.repeat(64));" - "h.update('AB').digest('hex')"), - njs_str("ee9dce43b12eb3e865614ad9c1a8d4fad4b6eac2b64647bd24cd192888d3f367") }, + { njs_str("{{}a ??}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha256', 'A'.repeat(100));" - "h.update('AB').digest('hex')"), - njs_str("5647b6c429701ff512f0f18232b4507065d2376ca8899a816a0a6e721bf8ddcc") }, + { njs_str("{{}a &}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac()"), - njs_str("TypeError: algorithm must be a string") }, + { njs_str("{{}a |}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac([])"), - njs_str("TypeError: algorithm must be a string") }, + { njs_str("{{}a ^}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha512', '')"), - njs_str("TypeError: not supported algorithm: \"sha512\"") }, + { njs_str("{{}a <<}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha1', [])"), - njs_str("TypeError: key argument \"array\" is not a string or Buffer-like object") }, + { njs_str("{{}a >>}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('A').digest('hex'); h.digest('hex')"), - njs_str("Error: Digest already called") }, + { njs_str("{{}new}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('A').digest('hex'); h.update('B')"), - njs_str("Error: Digest already called") }, + { njs_str("{{}delete}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("typeof require('crypto').createHmac('md5', 'a')"), - njs_str("object") }, + { njs_str("{{}void}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var cr = require('crypto'); var h = cr.createHash('sha1');" - "h.update.call(cr.createHmac('sha1', 's'), '')"), - njs_str("TypeError: \"this\" is not a hash object") }, + { njs_str("{{}typeof}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - /* setTimeout(). */ + { njs_str("{{} ({a: 1, b: {}\n}\n})\n}"), + njs_str("SyntaxError: Unexpected token \"}\" in 3") }, - { njs_str("setTimeout()"), - njs_str("TypeError: too few arguments") }, + { njs_str("object?."), + njs_str("SyntaxError: Unexpected end of input in 1") }, - { njs_str("setTimeout(function(){})"), - njs_str("InternalError: not supported by host environment") }, + { njs_str("`${{a: 1, b}}`"), + njs_str("ReferenceError: \"b\" is not defined") }, - { njs_str("setTimeout(function(){}, 12)"), - njs_str("InternalError: not supported by host environment") }, + { njs_str("`${{a: 1, b:}}`"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - /* clearTimeout(). */ + { njs_str("`${{a: 1, b:,}}`"), + njs_str("SyntaxError: Unexpected token \",\" in 1") }, - { njs_str("clearTimeout()"), - njs_str("undefined") }, + { njs_str("`${{a: 1, b: 2,}}`"), + njs_str("[object Object]") }, - { njs_str("clearTimeout(123)"), - njs_str("undefined") }, + { njs_str("`${{a: 1,, b: 2}}`"), + njs_str("SyntaxError: Unexpected token \",\" in 1") }, - /* Trick: number to boolean. */ + { njs_str("`${{f(){-} - {}}`"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var a = 0; !!a"), - njs_str("false") }, + { njs_str("for (;1-;) {}"), + njs_str("SyntaxError: Unexpected token \";\" in 1") }, - { njs_str("var a = 5; !!a"), - njs_str("true") }, + { njs_str("var str = String(str); str"), + njs_str("undefined") }, - /* Trick: flooring. */ + { njs_str("var t = \"123\"; t = parseInt(t); t"), + njs_str("123") }, - { njs_str("var n = -10.12345; ~~n"), - njs_str("-10") }, + /* TextEncoder. */ - { njs_str("var n = 10.12345; ~~n"), - njs_str("10") }, + { njs_str("var en = new TextEncoder(); typeof en.encode()"), + njs_str("object") }, - /* es5id: 8.2_A1_T1 */ - /* es5id: 8.2_A1_T2 */ + { njs_str("var en = new TextEncoder(); en.encode()"), + njs_str("") }, - { njs_str("var x = null;"), - njs_str("undefined") }, + { njs_str("var en = new TextEncoder(); var res = en.encode('α'); res"), + njs_str("206,177") }, - /* es5id: 8.2_A2 */ + { njs_str("var en = new TextEncoder(); var res = en.encode('α1α'); res[2]"), + njs_str("49") }, - { njs_str("var null;"), - njs_str("SyntaxError: Unexpected token \"null\" in 1") }, + { njs_str("var en = new TextEncoder(); en.encode(String.bytesFrom([0xCE]))"), + njs_str("239,191,189") }, - /* es5id: 8.2_A3 */ + { njs_str("var en = new TextEncoder();" + "en.encode(String.bytesFrom([0xCE, 0xB1, 0xCE]))"), + njs_str("206,177,239,191,189") }, - { njs_str("typeof(null) === \"object\""), - njs_str("true") }, + { njs_str("var en = new TextEncoder();" + "en.encode(String.bytesFrom([0xCE, 0xCE, 0xB1]))"), + njs_str("239,191,189,206,177") }, - /* Module. */ + { njs_str("var en = new TextEncoder(); en.encoding"), + njs_str("utf-8") }, - { njs_str("import;"), - njs_str("SyntaxError: Non-default import is not supported in 1") }, + { njs_str("TextEncoder.prototype.encode.apply({}, [])"), + njs_str("TypeError: \"this\" is not a TextEncoder") }, - { njs_str("import {x} from y"), - njs_str("SyntaxError: Non-default import is not supported in 1") }, + { njs_str("var en = new TextEncoder();" + "var utf8 = new Uint8Array(5);" + "var res = en.encodeInto('ααααα', utf8); njs.dump(res)"), + njs_str("{read:2,written:4}") }, - { njs_str("import x from y"), - njs_str("SyntaxError: Unexpected token \"y\" in 1") }, + { njs_str("var en = new TextEncoder();" + "var utf8 = new Uint8Array(10);" + "var res = en.encodeInto('ααααα', utf8); njs.dump(res)"), + njs_str("{read:5,written:10}") }, - { njs_str("import x from {"), - njs_str("SyntaxError: Unexpected token \"{\" in 1") }, + { njs_str("var en = new TextEncoder();" + "var utf8 = new Uint8Array(10);" + "en.encodeInto('ααααα', utf8.subarray(2)); utf8[0]"), + njs_str("0") }, - { njs_str("import x from ''"), - njs_str("SyntaxError: Cannot find module \"\" in 1") }, + { njs_str("var str = String.bytesFrom([0xCE]);" + "var en = new TextEncoder();" + "var utf8 = new Uint8Array(3);" + "var res = en.encodeInto(str, utf8); " + "[njs.dump(res), utf8]"), + njs_str("{read:1,written:3},239,191,189") }, - { njs_str("import x from 'crypto'"), - njs_str("undefined") }, - - { njs_str("import x from 'crypto' 1"), - njs_str("SyntaxError: Unexpected token \"1\" in 1") }, + { njs_str("var str = String.bytesFrom([0xCE]);" + "var en = new TextEncoder();" + "var utf8 = new Uint8Array(5);" + "en.encodeInto(str, utf8); utf8"), + njs_str("239,191,189,0,0") }, - { njs_str("if (1) {import x from 'crypto'}"), - njs_str("SyntaxError: Illegal import statement in 1") }, + { njs_str("var str = String.bytesFrom([0xCE, 0xB1, 0xCE]);" + "var en = new TextEncoder();" + "var utf8 = new Uint8Array(5);" + "var res = en.encodeInto(str, utf8);" + "[njs.dump(res), utf8]"), + njs_str("{read:2,written:5},206,177,239,191,189") }, - { njs_str("export"), - njs_str("SyntaxError: Illegal export statement in 1") }, + { njs_str("var str = String.bytesFrom([0xCE, 0xCE, 0xB1]);" + "var en = new TextEncoder();" + "var utf8 = new Uint8Array(5);" + "var res = en.encodeInto(str, utf8);" + "[njs.dump(res), utf8]"), + njs_str("{read:2,written:5},239,191,189,206,177") }, - { njs_str("Object.assign(undefined)"), - njs_str("TypeError: cannot convert null or undefined to object") }, + { njs_str("TextEncoder.prototype.encodeInto.apply({}, [])"), + njs_str("TypeError: \"this\" is not a TextEncoder") }, - { njs_str("Object.assign(null)"), - njs_str("TypeError: cannot convert null or undefined to object") }, + { njs_str("(new TextEncoder()).encodeInto('', 0.12) "), + njs_str("TypeError: The \"destination\" argument must be an instance of Uint8Array") }, - { njs_str("Object.assign({x:123}).toString()"), - njs_str("[object Object]") }, + /* TextDecoder. */ - { njs_str("Object.assign({x:123}).x"), - njs_str("123") }, + { njs_str("var de = new TextDecoder();" + "var u8arr = new Uint8Array([240, 160, 174, 183]);" + "var u16arr = new Uint16Array(u8arr.buffer);" + "var u32arr = new Uint32Array(u8arr.buffer);" + "[u8arr, u16arr, u32arr].map(v=>de.decode(v)).join(',')"), + njs_str("𠮷,𠮷,𠮷") }, - { njs_str("Object.assign(true)"), - njs_str("true") }, + { njs_str("var de = new TextDecoder();" + "[new Uint8Array([240, 160]), " + " new Uint8Array([174]), " + " new Uint8Array([183])].map(v=>de.decode(v, {stream: 1}))[2]"), + njs_str("𠮷") }, - { njs_str("Object.assign(123)"), - njs_str("123") }, + { njs_str("var de = new TextDecoder();" + "de.decode(new Uint8Array([240, 160]), {stream: 1});" + "de.decode(new Uint8Array([174]), {stream: 1});" + "de.decode(new Uint8Array([183]))"), + njs_str("𠮷") }, - { njs_str("var o1 = {a:1, b:1, c:1}; var o2 = {b:2, c:2}; " - "var o3 = {c:3}; var obj = Object.assign({}, o1, o2, o3); " - "Object.values(obj);"), - njs_str("1,2,3") }, + { njs_str("var de = new TextDecoder();" + "de.decode(new Uint8Array([240, 160]), {stream: 1});" + "de.decode()"), + njs_str("�") }, - { njs_str("var v1 = 'abc'; var v2 = true; var v3 = 10; " - "var obj = Object.assign({}, v1, null, v2, undefined, v3); " - "Object.values(obj);"), - njs_str("a,b,c") }, + { njs_str("var de = new TextDecoder('utf-8', {fatal: true});" + "de.decode(new Uint8Array([240, 160]))"), + njs_str("TypeError: The encoded data was not valid") }, - { njs_str("Object.assign(true, {a:123})"), - njs_str("true") }, + { njs_str("var de = new TextDecoder('utf-8', {fatal: false});" + "de.decode(new Uint8Array([240, 160]))"), + njs_str("�") }, - { njs_str("Object.assign(true, {a:123}).a"), - njs_str("123") }, + { njs_str("var en = new TextEncoder();" + "var de = new TextDecoder('utf-8', {ignoreBOM: true});" + "en.encode(de.decode(new Uint8Array([239, 187, 191, 50])))"), + njs_str("239,187,191,50") }, - { njs_str("var y = Object.create({s:123}); y.z = 456;" - "Object.assign({}, y).s;"), - njs_str("undefined") }, + { njs_str("var en = new TextEncoder();" + "var de = new TextDecoder('utf-8', {ignoreBOM: false});" + "en.encode(de.decode(new Uint8Array([239, 187, 191, 50])))"), + njs_str("50") }, - { njs_str("var obj = {s:123}; Object.defineProperty(obj," - "'p1', {value:12, enumerable:false});" - "Object.assign({}, obj).p1"), - njs_str("undefined") }, + { njs_str("var en = new TextEncoder(); var de = new TextDecoder();" + "en.encode(de.decode(new Uint8Array([239, 187, 191, 50])))"), + njs_str("50") }, - { njs_str("var obj = {s:123}; Object.defineProperty(obj," - "'x', {value:12, writable:false});" - "Object.assign(obj, {x:4})"), - njs_str("TypeError: Cannot assign to read-only property \"x\" of object") }, + { njs_str("var de = new TextDecoder(); de.decode('')"), + njs_str("TypeError: The \"input\" argument must be an instance of TypedArray") }, - { njs_str("var obj = {foo:1, get bar() {return 2;}};" - "var copy = Object.assign({}, obj);" - "Object.getOwnPropertyDescriptor(copy, 'bar').get"), - njs_str("undefined") }, + { njs_str("var de = new TextDecoder({})"), + njs_str("RangeError: The \"[object Object]\" encoding is not supported") }, - { njs_str("try{var x = Object.defineProperty({}, 'foo'," - "{value:1, writable:false});" - "Object.assign(x, {bar:2}, {foo:2});}catch(error){};" - "x.bar"), - njs_str("2") }, + { njs_str("var de = new TextDecoder('foo')"), + njs_str("RangeError: The \"foo\" encoding is not supported") }, - { njs_str("var a = Object.defineProperty({}, 'a'," - "{get(){Object.defineProperty(this, 'b'," - "{value:2,enumerable:false});" - "return 1}, enumerable:1}); a.b =1;" - "var x = Object.assign({}, a);x.b;"), - njs_str("undefined") }, + { njs_str("var de = new TextDecoder(); de.encoding"), + njs_str("utf-8") }, - /* let and const */ + { njs_str("var de = new TextDecoder(); de.fatal"), + njs_str("false") }, - { njs_str("var let = 123;" - "let"), - njs_str("SyntaxError: Unexpected token \"let\" in 1") }, + { njs_str("var de = new TextDecoder(); de.ignoreBOM"), + njs_str("false") }, - { njs_str("var const = 123"), - njs_str("SyntaxError: Unexpected token \"const\" in 1") }, + { njs_str("TextDecoder.prototype.decode.apply({}, new Uint8Array([1]))"), + njs_str("TypeError: \"this\" is not a TextDecoder") }, - /* Async */ + { njs_str("var de = new TextDecoder();" + "var buf = new Uint32Array([1,2,3]).buffer;" + "var en = new TextEncoder();" + "njs.dump(new Uint32Array(en.encode(de.decode(buf)).buffer))"), + njs_str("Uint32Array [1,2,3]") }, - { njs_str("var async;" - "function f() {" - " async\n" - " function foo() {}" - "}" - "f()"), - njs_str("undefined") }, + { njs_str("var de = new TextDecoder();" + "var buf = new Uint32Array([1,2,3]).subarray(1,2);" + "var en = new TextEncoder();" + "njs.dump(new Uint32Array(en.encode(de.decode(buf)).buffer))"), + njs_str("Uint32Array [2]") }, - { njs_str("var async;" - "function f() {" - " async;" - " function foo() {}" - "}" - "f()"), - njs_str("undefined") }, + /* let */ - { njs_str("var async;" - "async\n" - "function foo() {}"), + { njs_str("let x"), njs_str("undefined") }, - { njs_str("new\""), - njs_str("SyntaxError: Unterminated string \"\"\" in 1") }, + { njs_str("let x = 123; x"), + njs_str("123") }, - { njs_str("new\"\\UFFFF"), - njs_str("SyntaxError: Unterminated string \"\"\\UFFFF\" in 1") }, + { njs_str("let x = [123]; x"), + njs_str("123") }, - { njs_str("new/la"), - njs_str("SyntaxError: Unterminated RegExp \"/la\" in 1") }, + { njs_str("let x = () => x; x()"), + njs_str("[object Function]") }, - { njs_str("{name; {/ / /}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let x = (() => x)()"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("[(]"), - njs_str("SyntaxError: Unexpected token \"]\" in 1") }, + { njs_str("x; let x"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("[...]"), - njs_str("SyntaxError: Unexpected token \"]\" in 1") }, + { njs_str("x; let x = 123"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("switch () {}"), - njs_str("SyntaxError: Unexpected token \")\" in 1") }, + { njs_str("let x = x + 123"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("switch ([(]) {}"), - njs_str("SyntaxError: Unexpected token \"]\" in 1") }, + { njs_str("let x = (x, 1)"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}{-}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let x = x"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}{+}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let x; var x"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("{{}{delete}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("var x; let x"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("{{}{++}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let x; function x() {}"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("{{}{++1}"), - njs_str("ReferenceError: Invalid left-hand side in prefix operation in 1") }, + { njs_str("function x() {} let x"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("{{}{1++}"), - njs_str("ReferenceError: Invalid left-hand side in postfix operation in 1") }, + { njs_str("function x() {let x; var x}"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("{{}{1/}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function x() {var x; let x}"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("{{}{1>>}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("var x = function f() {let f}"), + njs_str("undefined") }, - { njs_str("{{}{r=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let a; let x = 1;" + "{let x = 2; a = x}" + "[x, a]"), + njs_str("1,2") }, - { njs_str("{{}{var a = }"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let a; let x = 1;" + "if (true) {let x = 2; a = x}" + "[x, a]"), + njs_str("1,2") }, - { njs_str("{{}T=>}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("var a = 5, b = 10, arr = [];" + "{let a = 4; var b = 1; arr.push(a); arr.push(b)}" + "arr.push(a); arr.push(b); arr"), + njs_str("4,1,5,1") }, - { njs_str("{{}a = b +}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function func() {return x}" + "let x = 123;" + "func()"), + njs_str("123") }, - { njs_str("{{}a = b -}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function func() {return x}" + "func();" + "let x = 123"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a = b *}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function func() {return () => x}" + "let x = 123;" + "func()()"), + njs_str("123") }, - { njs_str("{{}a = b /}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function func() {x = x + 1; let x}"), + njs_str("undefined") }, - { njs_str("{{}a = b %}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function func() {return () => x}" + "func()();" + "let x = 123;"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a = b++}"), - njs_str("ReferenceError: \"a\" is not defined") }, + { njs_str("var arr = [];" + "" + "for (var i = 0; i < 10; i++) {" + " let x = i;" + "" + " arr.push( (n) => {x += n; return x} );" + "}" + "" + "[" + " arr[0](2), arr[1](1), arr[2](4), arr[3](7), arr[4](0)," + " arr[5](1), arr[6](2), arr[7](5), arr[8](8), arr[9](10)" + "]"), + njs_str("2,2,6,10,4,6,8,12,16,19") }, - { njs_str("{{}a = b--}"), - njs_str("ReferenceError: \"a\" is not defined") }, + { njs_str("var arr = [];" + "" + "for (let i = 0; i < 10; i++) {" + " arr.push( (n) => {i += n; return i} );" + "}" + "" + "[" + " arr[0](2), arr[1](1), arr[2](4), arr[3](7), arr[4](0)," + " arr[5](1), arr[6](2), arr[7](5), arr[8](8), arr[9](10)" + "]"), + njs_str("2,2,6,10,4,6,8,12,16,19") }, - { njs_str("{{}a =}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("for (let i = 0; i < 1; i++) {" + " let i = i + 2;" + "}"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a +=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let arr = [], res = [];" + "for (let i = 0, f = function() { return i }; i < 5; i++) {" + " arr.push(f);" + "}" + "for (let i = 0; i < 5; i++) {" + " res.push(arr[i]());" + "} res"), + njs_str("0,0,0,0,0") }, - { njs_str("{{}a -=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let arr = [], res = [];" + "for (let i = 0; arr.push(() => i), i < 10; i++) {}" + "for (let k = 0; k < 10; k++) {res.push(arr[k]())}" + "res"), + njs_str("0,1,2,3,4,5,6,7,8,9") }, - { njs_str("{{}a *=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let res = [];" + "for (let n in [1,2,3]) {res.push(n)}" + "res"), + njs_str("0,1,2") }, - { njs_str("{{}a /=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let arr = [], res = [];" + "" + "for (let n in [1,2,3]) {" + " arr.push(() => n);" + "}" + "" + "for (let n in arr) {" + " res.push(arr[n]());" + "}" + "res"), + njs_str("0,1,2") }, - { njs_str("{{}a %=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let arr = [];" + "" + "for (let n in [1,2,3]) {" + " let n = 1;" + " arr.push(n);" + "}" + "arr"), + njs_str("1,1,1") }, - { njs_str("{{}a ===}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("for (let n in [1,2,3]) {" + " let n = n + 1;" + "}"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a ==}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("for (let n in [1,2,3]) {}" + "n"), + njs_str("ReferenceError: \"n\" is not defined") }, - { njs_str("{{}a !=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("for (let n in [1,n,3]) {}"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a !==}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("(function() {" + "function f() {return x + 1}" + "function abc() {f()};" + "abc();" + "let x;" + "}())"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a >}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("function func() {var x = 1; {let x = x + 1} } func()"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a <}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("if (false) let x = 1"), + njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, - { njs_str("{{}a <=}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("while (false) let x = 1"), + njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, - { njs_str("{{}a &&}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("for (;;) let x = 1"), + njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, - { njs_str("{{}a ||}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("try {} catch (e) {let e}"), + njs_str("SyntaxError: \"e\" has already been declared in 1") }, - { njs_str("{{}a ??}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let arr = [], x = 2;" + "switch(true) {default: let x = 1; arr.push(x)}" + "arr.push(x); arr"), + njs_str("1,2") }, - { njs_str("{{}a &}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("switch(true) {case false: let x = 1; default: x = 2}"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}a |}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let res;" + "switch(true) {case true: let x = 1; default: x = 2; res = x} res"), + njs_str("2") }, - { njs_str("{{}a ^}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let null"), + njs_str("SyntaxError: Unexpected token \"null\" in 1") }, - { njs_str("{{}a <<}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let continue"), + njs_str("SyntaxError: Unexpected token \"continue\" in 1") }, - { njs_str("{{}a >>}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let undefined"), + njs_str("SyntaxError: \"undefined\" has already been declared in 1") }, - { njs_str("{{}new}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let a = 1; globalThis.a"), + njs_str("undefined") }, - { njs_str("{{}delete}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("if (false) {x = 2} else {x = 1} let x;"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("{{}void}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let let"), + njs_str("SyntaxError: Unexpected token \"let\" in 1") }, - { njs_str("{{}typeof}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("let null"), + njs_str("SyntaxError: Unexpected token \"null\" in 1") }, - { njs_str("{{} ({a: 1, b: {}\n}\n})\n}"), - njs_str("SyntaxError: Unexpected token \"}\" in 3") }, + { njs_str("function let() {}"), + njs_str("SyntaxError: Unexpected token \"let\" in 1") }, - { njs_str("object?."), - njs_str("SyntaxError: Unexpected end of input in 1") }, + { njs_str("function static() {}"), + njs_str("SyntaxError: Unexpected token \"static\" in 1") }, - { njs_str("`${{a: 1, b}}`"), - njs_str("ReferenceError: \"b\" is not defined") }, + /* const */ - { njs_str("`${{a: 1, b:}}`"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("const x"), + njs_str("SyntaxError: missing initializer in const declaration") }, - { njs_str("`${{a: 1, b:,}}`"), - njs_str("SyntaxError: Unexpected token \",\" in 1") }, + { njs_str("const x = 1; x"), + njs_str("1") }, - { njs_str("`${{a: 1, b: 2,}}`"), - njs_str("[object Object]") }, + { njs_str("const x = 1; x = 1"), + njs_str("TypeError: assignment to constant variable") }, - { njs_str("`${{a: 1,, b: 2}}`"), - njs_str("SyntaxError: Unexpected token \",\" in 1") }, + { njs_str("function abc() {const x}"), + njs_str("SyntaxError: missing initializer in const declaration") }, - { njs_str("`${{f(){-} - {}}`"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("const x = [123]; x"), + njs_str("123") }, - { njs_str("for (;1-;) {}"), - njs_str("SyntaxError: Unexpected token \";\" in 1") }, + { njs_str("const x = () => x; x()"), + njs_str("[object Function]") }, - { njs_str("var str = String(str); str"), - njs_str("undefined") }, + { njs_str("const x = (() => x)()"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var t = \"123\"; t = parseInt(t); t"), - njs_str("123") }, + { njs_str("x; const x = 123"), + njs_str("ReferenceError: cannot access variable before initialization") }, - /* Query String */ + { njs_str("const x = x + 123"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz');" - "njs.dump(obj)"), - njs_str("{baz:'fuz'}") }, + { njs_str("const x; var x"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=');" - "njs.dump(obj)"), - njs_str("{baz:''}") }, + { njs_str("const x; let x"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax');" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("let x; const x"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&');" - "njs.dump(obj)"), - njs_str("{baz:'fuz'}") }, + { njs_str("const x = 1; function x() {}"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('&baz=fuz');" - "njs.dump(obj)"), - njs_str("{baz:'fuz'}") }, + { njs_str("function x() {} const x = 1"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('&&&&&baz=fuz');" - "njs.dump(obj)"), - njs_str("{baz:'fuz'}") }, + { njs_str("function x() {const x; var x}"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('=fuz');" - "njs.dump(obj)"), - njs_str("{:'fuz'}") }, + { njs_str("function x() {var x; const x}"), + njs_str("SyntaxError: \"x\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('=fuz=');" - "njs.dump(obj)"), - njs_str("{:'fuz='}") }, + { njs_str("const x = function f() {const f = 1}"), + njs_str("undefined") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('===fu=z');" - "njs.dump(obj)"), - njs_str("{:'==fu=z'}") }, + { njs_str("let res; const x = 1;" + "{const x = 2; res = x}" + "[x, res]"), + njs_str("1,2") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&baz=tax');" - "njs.dump(obj)"), - njs_str("{baz:['fuz','tax']}") }, + { njs_str("let res; const x = 1;" + "if (true) {const x = 2; res = x}" + "[x, res]"), + njs_str("1,2") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('freespace');" - "njs.dump(obj)"), - njs_str("{freespace:''}") }, + { njs_str("function func() {return x}" + "const x = 123;" + "func()"), + njs_str("123") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('name&value=12');" - "njs.dump(obj)"), - njs_str("{name:'',value:'12'}") }, + { njs_str("function func() {return x}" + "func();" + "const x = 123"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', 'fuz');" - "njs.dump(obj)"), - njs_str("{baz:'',&muz:'tax'}") }, + { njs_str("function func() {return () => x}" + "const x = 123;" + "func()()"), + njs_str("123") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', '');" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("function func() {return () => x++}" + "const x = 123;" + "func()()"), + njs_str("TypeError: assignment to constant variable") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', null);" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("for (const i = 0; i < 1; i++) {}"), + njs_str("TypeError: assignment to constant variable") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', undefined);" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("let res = [];" + "for (const n in [1,2,3]) {res.push(n)}" + "res"), + njs_str("0,1,2") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz123muz=tax', 123);" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("let arr = [], res = [];" + "" + "for (const n in [1,2,3]) {" + " arr.push(() => n);" + "}" + "" + "for (let n in arr) {" + " res.push(arr[n]());" + "}" + "res"), + njs_str("0,1,2") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuzαααmuz=tax', 'ααα');" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("let arr = [];" + "" + "for (const n in [1,2,3]) {" + " let n = 1;" + " arr.push(n);" + "}" + "arr"), + njs_str("1,1,1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', '=');" - "njs.dump(obj)"), - njs_str("{baz:'',fuz&muz:'',tax:''}") }, + { njs_str("for (const n in [1,2,3]) {" + " let n = n + 1;" + "}"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', null, 'fuz');" - "njs.dump(obj)"), - njs_str("{baz=:'',muz=tax:''}") }, + { njs_str("for (const n in [1,2,3]) {}" + "n"), + njs_str("ReferenceError: \"n\" is not defined") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', null, '&');" - "njs.dump(obj)"), - njs_str("{baz=fuz:'',muz=tax:''}") }, + { njs_str("for (const n in [1,n,3]) {}"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz123fuz&muz123tax', null, 123);" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("(function() {" + "function f() {return x + 1}" + "function abc() {f()};" + "abc();" + "const x = 1;" + "}())"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('bazαααfuz&muzαααtax', null, 'ααα');" - "njs.dump(obj)"), - njs_str("{baz:'fuz',muz:'tax'}") }, + { njs_str("if (false) const x = 1"), + njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=fuz&muz=tax', null, null, {maxKeys: 1});" - "njs.dump(obj)"), - njs_str("{baz:'fuz'}") }, + { njs_str("while (false) const x = 1"), + njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, - { njs_str("var qs = require('querystring'); var out = [];" - "var obj = qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: (key) => {out.push(key)}});" - "out.join('; ');"), - njs_str("baz; fuz; muz; tax") }, + { njs_str("for (;;) const x = 1"), + njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, - { njs_str("var qs = require('querystring'); var i = 0;" - "var obj = qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: (key) => 'α' + i++});" - "njs.dump(obj);"), - njs_str("{α0:'α1',α2:'α3'}") }, + { njs_str("try {} catch (e) {const e = 1}"), + njs_str("SyntaxError: \"e\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: 123});"), - njs_str("TypeError: option decodeURIComponent is not a function") }, + { njs_str("let arr = []; const x = 2;" + "switch(true) {default: const x = 1; arr.push(x)}" + "arr.push(x); arr"), + njs_str("1,2") }, - { njs_str("var qs = require('querystring');" - "qs.unescape = 123;" - "qs.parse('baz=fuz&muz=tax');"), - njs_str("TypeError: QueryString.unescape is not a function") }, + { njs_str("let res;" + "switch(true) {case true: const x = 1; default: x = 2; res = x} res"), + njs_str("TypeError: assignment to constant variable") }, - { njs_str("var qs = require('querystring'); var out = [];" - "qs.unescape = (key) => {out.push(key)};" - "qs.parse('baz=fuz&muz=tax');" - "out.join('; ');"), - njs_str("baz; fuz; muz; tax") }, + { njs_str("const null"), + njs_str("SyntaxError: Unexpected token \"null\" in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('ba%32z=f%32uz');" - "njs.dump(obj)"), - njs_str("{ba2z:'f2uz'}") }, + { njs_str("const continue"), + njs_str("SyntaxError: Unexpected token \"continue\" in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('ba%32z=f%32uz');" - "njs.dump(obj)"), - njs_str("{ba2z:'f2uz'}") }, + { njs_str("const undefined"), + njs_str("SyntaxError: \"undefined\" has already been declared in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('ba%F0%9F%92%A9z=f%F0%9F%92%A9uz');" - "njs.dump(obj)"), - njs_str("{ba💩z:'f💩uz'}") }, + { njs_str("const a = 1; globalThis.a"), + njs_str("undefined") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('======');" - "njs.dump(obj)"), - njs_str("{:'====='}") }, + { njs_str("if (false) {x = 2} else {x = 1} const x = 0"), + njs_str("ReferenceError: cannot access variable before initialization") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=%F0%9F%A9');" - "njs.dump(obj)"), - njs_str("{baz:'�'}") }, + { njs_str("const const"), + njs_str("SyntaxError: Unexpected token \"const\" in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=αααααα%\x00\x01\x02αααα');" - "njs.dump(obj)"), - njs_str("{baz:'αααααα%\\u0000\\u0001\\u0002αααα'}") }, + /* Async/Await */ - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=%F6α');" - "njs.dump(obj)"), - njs_str("{baz:'�α'}") }, + { njs_str("async function f() {}; f.prototype"), + njs_str("undefined") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=%F6');" - "njs.dump(obj)"), - njs_str("{baz:'�'}") }, + { njs_str("async function f() {await 1}"), + njs_str("undefined") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=%FG');" - "njs.dump(obj)"), - njs_str("{baz:'%FG'}") }, + { njs_str("function f() {await 1}"), + njs_str("SyntaxError: await is only valid in async functions in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=%F');" - "njs.dump(obj)"), - njs_str("{baz:'%F'}") }, + { njs_str("async function f() {function a() {await 1}}"), + njs_str("SyntaxError: await is only valid in async functions in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('baz=%');" - "njs.dump(obj)"), - njs_str("{baz:'%'}") }, + { njs_str("async function f() {() => {await 1}}"), + njs_str("SyntaxError: await is only valid in async functions in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = qs.parse('ba+z=f+uz');" - "njs.dump(obj)"), - njs_str("{ba z:'f uz'}") }, - - - { njs_str("var qs = require('querystring');" - "qs.parse('X='+'α'.repeat(33)).X.length"), - njs_str("33") }, + { njs_str("function f() {async () => {await 1}}"), + njs_str("undefined") }, - { njs_str("var qs = require('querystring');" - "var x = qs.parse('X='+'α1'.repeat(33)).X;" - "[x.length, x[33], x[34]]"), - njs_str("66,1,α") }, + { njs_str("let f = async () => {await 1}"), + njs_str("undefined") }, - { njs_str("var qs = require('querystring');" - "var s = qs.parse('X='+String.bytesFrom(Array(16).fill(0x9d))).X;" - "[s.length, s.toUTF8().length, s[15]]"), - njs_str("16,48,�") }, + { njs_str("let f = () => {await 1}"), + njs_str("SyntaxError: await is only valid in async functions in 1") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz'})"), - njs_str("baz=fuz") }, + { njs_str("(async function() {await 1})"), + njs_str("[object AsyncFunction]") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'})"), - njs_str("baz=fuz&muz=tax") }, + { njs_str("(function() {await 1})"), + njs_str("SyntaxError: await is only valid in async functions in 1") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baαz': 'fαuz', 'muαz': 'tαax'});"), - njs_str("ba%CE%B1z=f%CE%B1uz&mu%CE%B1z=t%CE%B1ax") }, + { njs_str("let ctor = Object.getPrototypeOf(async function(){}).constructor;" + "ctor"), + njs_str("[object Function]") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': ['fuz', 'tax']})"), - njs_str("baz=fuz&baz=tax") }, + { njs_str("let ctor = Object.getPrototypeOf(async function(){}).constructor;" + "ctor()"), + njs_str("[object AsyncFunction]") }, - { njs_str("var qs = require('querystring');" - njs_declare_sparse_array("arr", 2) - "arr[0] = 0; arr[1] = 1.5;" - "qs.stringify({'baz': arr})"), - njs_str("baz=0&baz=1.5") }, + { njs_str("let ctor = Object.getPrototypeOf(async function(){}).constructor;" + "new ctor();"), + njs_str("[object AsyncFunction]") }, - { njs_str("var qs = require('querystring'); var out = [];" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, null, {encodeURIComponent: (key) => {out.push(key)}});" - "out.join('; ')"), - njs_str("baz; fuz; muz; tax") }, + { njs_str("let f = new Function('x', 'await 1; return x'); f(1)"), + njs_str("SyntaxError: await is only valid in async functions in runtime:1") }, - { njs_str("var qs = require('querystring'); " - "qs.stringify({a: 'b'}, null, null, " - " {encodeURIComponent: () => String.bytesFrom([0x9d])})"), - njs_str("TypeError: got non-UTF8 string from encoder") }, + { njs_str("new AsyncFunction()"), + njs_str("ReferenceError: \"AsyncFunction\" is not defined") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, null, {encodeURIComponent: 123});" - "out.join('; ')"), - njs_str("TypeError: option encodeURIComponent is not a function") }, + { njs_str("(async function() {console.log(await 111)})"), + njs_str("SyntaxError: await in arguments not supported in 1") }, - { njs_str("var qs = require('querystring');" - "qs.escape = 123;" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'})"), - njs_str("TypeError: QueryString.escape is not a function") }, + { njs_str("(async function() {console.log('Number: ' + await 111)})"), + njs_str("SyntaxError: await in arguments not supported in 1") }, - { njs_str("var qs = require('querystring'); var out = [];" - "qs.escape = (key) => {out.push(key)};" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'});" - "out.join('; ')"), - njs_str("baz; fuz; muz; tax") }, + { njs_str("function f(a) {}" + "(async function() {f(await 111)})"), + njs_str("SyntaxError: await in arguments not supported in 1") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, '****')"), - njs_str("baz=fuz****muz=tax") }, + { njs_str("async () => [await x(1)(),]; async () => [await x(1)()]"), + njs_str("[object AsyncFunction]") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, '^^^^')"), - njs_str("baz^^^^fuz&muz^^^^tax") }, + { njs_str("function f(a, b, c) {}" + "(async function() {f(1, 'a', await 111)})"), + njs_str("SyntaxError: await in arguments not supported in 1") }, - { njs_str("var qs = require('querystring');" - "var obj = {A:'α'}; obj['δ'] = 'D';" - "var s = qs.stringify(obj,'γ=','&β'); [s, s.length]"), - njs_str("A&β%CE%B1γ=%CE%B4&βD,20") }, + { njs_str("function f(a) {}" + "(async function() {f('Number: ' + await 111)})"), + njs_str("SyntaxError: await in arguments not supported in 1") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, '', '')"), - njs_str("baz=fuz&muz=tax") }, + { njs_str("async function af() {await encrypt({},}"), + njs_str("SyntaxError: Unexpected token \"}\" in 1") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, undefined, undefined)"), - njs_str("baz=fuz&muz=tax") }, + { njs_str("let x = {async af() {await Promise.resolve(1)}}; x.af"), + njs_str("[object AsyncFunction]") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, '?', '/')"), - njs_str("baz/fuz?muz/tax") }, + { njs_str("let name = 'af', x = {async [name]() {await Promise.resolve(1)}}; x.af"), + njs_str("[object AsyncFunction]") }, +}; - { njs_str("var qs = require('querystring');" - "qs.stringify('123')"), - njs_str("") }, - { njs_str("var qs = require('querystring');" - "qs.stringify(123)"), - njs_str("") }, +static njs_unit_test_t njs_safe_test[] = +{ + { njs_str("(new Function('return this'))() === globalThis"), + njs_str("true") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({X: String.bytesFrom(Array(4).fill(0x9d))})"), - njs_str("X=%9D%9D%9D%9D") }, + { njs_str("(new Function('return this;'))() === globalThis"), + njs_str("true") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({X:{toString(){return 3}}})"), - njs_str("X=") }, + { njs_str("(new Function('return this '))() === globalThis"), + njs_str("true") }, - { njs_str("var qs = require('querystring');" - "qs.stringify({ name: undefined, age: 12 })"), - njs_str("name=&age=12") }, + { njs_str("(new Function('return thi'))()"), + njs_str("TypeError: function constructor is disabled in \"safe\" mode") }, - { njs_str("var qs = require('querystring');" - "qs.stringify(Object.create({ name: undefined, age: 12 }))"), - njs_str("") }, + { njs_str("(new Function('){return 1337})//', 'return this'))()"), + njs_str("TypeError: function constructor is disabled in \"safe\" mode") }, +}; - { njs_str("var qs = require('querystring');" - "qs.stringify([])"), - njs_str("") }, - { njs_str("var qs = require('querystring');" - "qs.stringify(['','',''])"), - njs_str("0=&1=&2=") }, +static njs_unit_test_t njs_denormals_test[] = +{ + { njs_str("2.2250738585072014e-308"), + njs_str("2.2250738585072014e-308") }, - { njs_str("var qs = require('querystring');" - "qs.stringify([undefined, null, Symbol(), Object(0), Object('test'), Object(false),,,])"), - njs_str("0=&1=&2=&3=&4=&5=") }, +#ifndef NJS_SUNC + { njs_str("2.2250738585072014E-308.toString(2) == ('0.' + '0'.repeat(1021) + '1')"), + njs_str("true") }, -#if 0 - { njs_str("var qs = require('querystring');" - "qs.stringify([NaN, Infinity, -Infinity, 2**69, 2**70])"), - njs_str("0=&1=&2=&3=590295810358705700000&4=1.1805916207174113e%2B21") }, -#else - { njs_str("var qs = require('querystring');" - "qs.stringify([NaN, Infinity, -Infinity, 2**69, 2**70])"), - njs_str("0=&1=&2=&3=590295810358705700000&4=1.1805916207174114e%2B21") }, -#endif + { njs_str("Number('2.2250738585072014E-323')"), + njs_str("2.5e-323") }, - { njs_str("var qs = require('querystring');" - "qs.stringify([[1,2,3],[4,5,6]])"), - njs_str("0=1&0=2&0=3&1=4&1=5&1=6") }, + { njs_str("Number('2.2250738585072014E-323') + 0"), + njs_str("2.5e-323") }, - { njs_str("var qs = require('querystring');" - "qs.stringify([['a',,,],['b',,,]])"), - njs_str("0=a&0=&0=&1=b&1=&1=") }, + /* Smallest positive double (next_double(0)). */ + { njs_str("5E-324.toString(36) === '0.' + '0'.repeat(207) + '3'"), + njs_str("true") }, - { njs_str("var qs = require('querystring');" - "qs.stringify([[,'a','b',,]])"), - njs_str("0=&0=a&0=b&0=") }, + /* Maximum fraction length. */ + { njs_str("2.2250738585072014E-323.toString(2) == ('0.' + '0'.repeat(1071) + '101')"), + njs_str("true") }, - { njs_str("var qs = require('querystring');" - "qs.escape('abcααααdef')"), - njs_str("abc%CE%B1%CE%B1%CE%B1%CE%B1def") }, + /* Denormals. */ + { njs_str("var zeros = count => '0'.repeat(count);" + "[" + " [1.8858070859709815e-308, `0.${zeros(1022)}1101100011110111011100000100011001111101110001010111`]," + // FIXME: " [Number.MIN_VALUE, `0.${zeros(1073)}1`]" + " [-5.06631661953108e-309, `-0.${zeros(1024)}11101001001010000001101111010101011111111011010111`]," + " [6.22574126804e-313, `0.${zeros(1037)}11101010101101100111000110100111001`]," + " [-4e-323, `-0.${zeros(1070)}1`]," + "].every(t=>t[0].toString(2) === t[1])"), + njs_str("true") }, - { njs_str("var qs = require('querystring');" - "qs.unescape('abc%CE%B1%CE%B1%CE%B1%CE%B1def')"), - njs_str("abcααααdef") }, + { njs_str("4.94065645841246544176568792868e-324.toExponential()"), + njs_str("5e-324") }, - /* TextEncoder. */ + { njs_str("4.94065645841246544176568792868e-324.toExponential(10)"), + njs_str("4.9406564584e-324") }, +#endif - { njs_str("var en = new TextEncoder(); typeof en.encode()"), - njs_str("object") }, +}; - { njs_str("var en = new TextEncoder(); en.encode()"), - njs_str("") }, - { njs_str("var en = new TextEncoder(); var res = en.encode('α'); res"), - njs_str("206,177") }, +static njs_unit_test_t njs_disabled_denormals_test[] = +{ + { njs_str("Number('2.2250738585072014E-323')"), + njs_str("0") }, - { njs_str("var en = new TextEncoder(); var res = en.encode('α1α'); res[2]"), - njs_str("49") }, + { njs_str("Number('2.2250738585072014E-323') + 0"), + njs_str("0") }, - { njs_str("var en = new TextEncoder(); en.encode(String.bytesFrom([0xCE]))"), - njs_str("239,191,189") }, + /* Smallest positive double (next_double(0)). */ + { njs_str("5E-324.toString(36)"), + njs_str("0") }, - { njs_str("var en = new TextEncoder();" - "en.encode(String.bytesFrom([0xCE, 0xB1, 0xCE]))"), - njs_str("206,177,239,191,189") }, + { njs_str("2.2250738585072014E-323.toString(2)"), + njs_str("0") }, - { njs_str("var en = new TextEncoder();" - "en.encode(String.bytesFrom([0xCE, 0xCE, 0xB1]))"), - njs_str("239,191,189,206,177") }, + /* Smallest normal double. */ - { njs_str("var en = new TextEncoder(); en.encoding"), - njs_str("utf-8") }, + { njs_str("2.2250738585072014e-308"), + njs_str("2.2250738585072014e-308") }, - { njs_str("TextEncoder.prototype.encode.apply({}, [])"), - njs_str("TypeError: \"this\" is not a TextEncoder") }, + { njs_str("2.2250738585072014e-308/2"), + njs_str("0") }, - { njs_str("var en = new TextEncoder();" - "var utf8 = new Uint8Array(5);" - "var res = en.encodeInto('ααααα', utf8); njs.dump(res)"), - njs_str("{read:2,written:4}") }, - - { njs_str("var en = new TextEncoder();" - "var utf8 = new Uint8Array(10);" - "var res = en.encodeInto('ααααα', utf8); njs.dump(res)"), - njs_str("{read:5,written:10}") }, - - { njs_str("var en = new TextEncoder();" - "var utf8 = new Uint8Array(10);" - "en.encodeInto('ααααα', utf8.subarray(2)); utf8[0]"), - njs_str("0") }, + /* Denormals. */ + { njs_str("[" + "1.8858070859709815e-308," + "-5.06631661953108e-309," + "6.22574126804e-313," + "-4e-323," + "].map(v=>v.toString(2))"), + njs_str("0,0,0,0") }, +}; - { njs_str("var str = String.bytesFrom([0xCE]);" - "var en = new TextEncoder();" - "var utf8 = new Uint8Array(3);" - "var res = en.encodeInto(str, utf8); " - "[njs.dump(res), utf8]"), - njs_str("{read:1,written:3},239,191,189") }, - { njs_str("var str = String.bytesFrom([0xCE]);" - "var en = new TextEncoder();" - "var utf8 = new Uint8Array(5);" - "en.encodeInto(str, utf8); utf8"), - njs_str("239,191,189,0,0") }, +static njs_unit_test_t njs_fs_module_test[] = +{ + { njs_str("var fs = require('fs'); typeof fs"), + njs_str("object") }, - { njs_str("var str = String.bytesFrom([0xCE, 0xB1, 0xCE]);" - "var en = new TextEncoder();" - "var utf8 = new Uint8Array(5);" - "var res = en.encodeInto(str, utf8);" - "[njs.dump(res), utf8]"), - njs_str("{read:2,written:5},206,177,239,191,189") }, + { njs_str("var fs = require('fs'); Object.isExtensible(fs)"), + njs_str("true") }, - { njs_str("var str = String.bytesFrom([0xCE, 0xCE, 0xB1]);" - "var en = new TextEncoder();" - "var utf8 = new Uint8Array(5);" - "var res = en.encodeInto(str, utf8);" - "[njs.dump(res), utf8]"), - njs_str("{read:2,written:5},239,191,189,206,177") }, + { njs_str("require('fs') === require('fs')"), + njs_str("true") }, - { njs_str("TextEncoder.prototype.encodeInto.apply({}, [])"), - njs_str("TypeError: \"this\" is not a TextEncoder") }, + { njs_str("require('fs').a = 1; require('fs').a"), + njs_str("1") }, - { njs_str("(new TextEncoder()).encodeInto('', 0.12) "), - njs_str("TypeError: The \"destination\" argument must be an instance of Uint8Array") }, + { njs_str("var fs = require('fs');" + "fs.readFile()"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - /* TextDecoder. */ + { njs_str("var fs = require('fs');" + "var path = Buffer.from('/broken'); path[3] = 0;" + "fs.readFile(path)"), + njs_str("TypeError: \"path\" must be a Buffer without null bytes") }, - { njs_str("var de = new TextDecoder();" - "var u8arr = new Uint8Array([240, 160, 174, 183]);" - "var u16arr = new Uint16Array(u8arr.buffer);" - "var u32arr = new Uint32Array(u8arr.buffer);" - "[u8arr, u16arr, u32arr].map(v=>de.decode(v)).join(',')"), - njs_str("𠮷,𠮷,𠮷") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path')"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var de = new TextDecoder();" - "[new Uint8Array([240, 160]), " - " new Uint8Array([174]), " - " new Uint8Array([183])].map(v=>de.decode(v, {stream: 1}))[2]"), - njs_str("𠮷") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path', 'utf8')"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var de = new TextDecoder();" - "de.decode(new Uint8Array([240, 160]), {stream: 1});" - "de.decode(new Uint8Array([174]), {stream: 1});" - "de.decode(new Uint8Array([183]))"), - njs_str("𠮷") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path', {flag:'xx'})"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var de = new TextDecoder();" - "de.decode(new Uint8Array([240, 160]), {stream: 1});" - "de.decode()"), - njs_str("�") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path', {flag:'xx'}, 1)"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var de = new TextDecoder('utf-8', {fatal: true});" - "de.decode(new Uint8Array([240, 160]))"), - njs_str("TypeError: The encoded data was not valid") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path', {flag:'xx'}, function () {})"), + njs_str("TypeError: Unknown file open flags: \"xx\"") }, - { njs_str("var de = new TextDecoder('utf-8', {fatal: false});" - "de.decode(new Uint8Array([240, 160]))"), - njs_str("�") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path', {encoding:'ascii'}, function () {})"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var en = new TextEncoder();" - "var de = new TextDecoder('utf-8', {ignoreBOM: true});" - "en.encode(de.decode(new Uint8Array([239, 187, 191, 50])))"), - njs_str("239,187,191,50") }, + { njs_str("var fs = require('fs');" + "fs.readFile('/njs_unknown_path', 'ascii', function () {})"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var en = new TextEncoder();" - "var de = new TextDecoder('utf-8', {ignoreBOM: false});" - "en.encode(de.decode(new Uint8Array([239, 187, 191, 50])))"), - njs_str("50") }, + /* require('fs').readFileSync() */ - { njs_str("var en = new TextEncoder(); var de = new TextDecoder();" - "en.encode(de.decode(new Uint8Array([239, 187, 191, 50])))"), - njs_str("50") }, + { njs_str("var fs = require('fs');" + "fs.readFileSync()"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("var de = new TextDecoder(); de.decode('')"), - njs_str("TypeError: The \"input\" argument must be an instance of TypedArray") }, + { njs_str("var fs = require('fs');" + "fs.readFileSync({})"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("var de = new TextDecoder({})"), - njs_str("RangeError: The \"[object Object]\" encoding is not supported") }, + { njs_str("var fs = require('fs');" + "fs.readFileSync('/njs_unknown_path', {flag:'xx'})"), + njs_str("TypeError: Unknown file open flags: \"xx\"") }, - { njs_str("var de = new TextDecoder('foo')"), - njs_str("RangeError: The \"foo\" encoding is not supported") }, + { njs_str("var fs = require('fs');" + "fs.readFileSync(Buffer.from('/njs_unknown_path'), {encoding:'ascii'})"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var de = new TextDecoder(); de.encoding"), - njs_str("utf-8") }, + { njs_str("var fs = require('fs');" + "fs.readFileSync('/njs_unknown_path', 'ascii')"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var de = new TextDecoder(); de.fatal"), - njs_str("false") }, + { njs_str("var fs = require('fs');" + "fs.readFileSync('/njs_unknown_path', true)"), + njs_str("TypeError: Unknown options type: \"boolean\" (a string or object required)") }, - { njs_str("var de = new TextDecoder(); de.ignoreBOM"), - njs_str("false") }, - { njs_str("TextDecoder.prototype.decode.apply({}, new Uint8Array([1]))"), - njs_str("TypeError: \"this\" is not a TextDecoder") }, + /* require('fs').writeFile() */ - { njs_str("var de = new TextDecoder();" - "var buf = new Uint32Array([1,2,3]).buffer;" - "var en = new TextEncoder();" - "njs.dump(new Uint32Array(en.encode(de.decode(buf)).buffer))"), - njs_str("Uint32Array [1,2,3]") }, + { njs_str("var fs = require('fs');" + "fs.writeFile()"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("var de = new TextDecoder();" - "var buf = new Uint32Array([1,2,3]).subarray(1,2);" - "var en = new TextEncoder();" - "njs.dump(new Uint32Array(en.encode(de.decode(buf)).buffer))"), - njs_str("Uint32Array [2]") }, + { njs_str("var fs = require('fs');" + "fs.writeFile({}, '', function () {})"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - /* Buffer */ + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path')"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("new Buffer();"), - njs_str("TypeError: Buffer is not a constructor") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '')"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var buf = Buffer.alloc();"), - njs_str("TypeError: \"size\" argument must be of type number") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '', undefined)"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var buf = Buffer.alloc('best buffer');"), - njs_str("TypeError: \"size\" argument must be of type number") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '', 'utf8')"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("var buf = Buffer.alloc(-1);"), - njs_str("RangeError: invalid size") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '', {flag:'xx'}, function () {})"), + njs_str("TypeError: Unknown file open flags: \"xx\"") }, - { njs_str("var buf = Buffer.alloc(4); njs.dump(buf)"), - njs_str("Buffer [0,0,0,0]") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '', {encoding:'ascii'}, function () {})"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var buf = Buffer.alloc(4, 88); buf"), - njs_str("XXXX") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '', 'ascii', function () {})"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var buf = Buffer.alloc(4, 945); njs.dump(buf)"), - njs_str("Buffer [177,177,177,177]") }, + { njs_str("var fs = require('fs');" + "fs.writeFile('/njs_unknown_path', '', true, function () {})"), + njs_str("TypeError: Unknown options type: \"boolean\" (a string or object required)") }, - { njs_str("var buf = Buffer.alloc(4, -1); njs.dump(buf)"), - njs_str("Buffer [255,255,255,255]") }, + /* require('fs').writeFileSync() */ - { njs_str("var buf = Buffer.alloc(4, -1, 'utf-128'); njs.dump(buf)"), - njs_str("Buffer [255,255,255,255]") }, + { njs_str("var fs = require('fs');" + "fs.writeFileSync()"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("var buf = Buffer.alloc(10, 'α'); buf"), - njs_str("ααααα") }, + { njs_str("var fs = require('fs');" + "fs.writeFileSync({}, '')"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("var buf = Buffer.alloc(4, 'α'); njs.dump(buf)"), - njs_str("Buffer [206,177,206,177]") }, + { njs_str("var fs = require('fs');" + "fs.writeFileSync('/njs_unknown_path', '', {flag:'xx'})"), + njs_str("TypeError: Unknown file open flags: \"xx\"") }, - { njs_str("var buf = Buffer.alloc(2, 'ααααα'); njs.dump(buf)"), - njs_str("Buffer [206,177]") }, + { njs_str("var fs = require('fs');" + "fs.writeFileSync('/njs_unknown_path', '', {encoding:'ascii'})"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var buf = Buffer.alloc(1, 'α'); njs.dump(buf)"), - njs_str("Buffer [206]") }, + { njs_str("var fs = require('fs');" + "fs.writeFileSync('/njs_unknown_path', '', 'ascii')"), + njs_str("TypeError: \"ascii\" encoding is not supported") }, - { njs_str("var buf = Buffer.alloc(4, 'ZXZpbA==', 'base64'); buf"), - njs_str("evil") }, + { njs_str("var fs = require('fs');" + "fs.writeFileSync('/njs_unknown_path', '', true)"), + njs_str("TypeError: Unknown options type: \"boolean\" (a string or object required)") }, - { njs_str("var buf = Buffer.alloc(8, 'ZXZpbA==', 'base64'); buf"), - njs_str("evilevil") }, + /* require('fs').renameSync() */ - { njs_str("var buf = Buffer.alloc(8, 'evil', 'utf-128'); buf"), - njs_str("TypeError: \"utf-128\" encoding is not supported") }, + { njs_str("var fs = require('fs');" + "fs.renameSync()"), + njs_str("TypeError: \"oldPath\" must be a string or Buffer") }, - { njs_str("var foo = new Uint8Array(10).fill(88);" - "var buf = Buffer.alloc(8, foo); buf"), - njs_str("XXXXXXXX") }, + { njs_str("var fs = require('fs');" + "fs.renameSync('/njs_unknown_path')"), + njs_str("TypeError: \"newPath\" must be a string or Buffer") }, - { njs_str("[1,2,10,20].every(v => {" - " var src = new Uint16Array(v).fill(0xB1CE);" - " var buf = Buffer.alloc(10, src);" - " return buf.toString() === " njs_evar("'ααααα'", "'�αααα�'") - "})"), - njs_str("true") }, + { njs_str("var fs = require('fs');" + "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" + ".map((x) => { try { fs.renameSync(x, '/njs_unknown_path'); } " + " catch (e) { return (e instanceof TypeError); } })" + ".every((x) => x === true)"), + njs_str("true")}, - { njs_str("var foo = Buffer.alloc(10, 'α');" - "var buf = Buffer.alloc(4, foo); buf"), - njs_str("αα") }, + { njs_str("var fs = require('fs');" + "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" + ".map((x) => { try { fs.renameSync('/njs_unknown_path', x); } " + " catch (e) { return (e instanceof TypeError); } })" + ".every((x) => x === true)"), + njs_str("true")}, - { njs_str("var buf = Buffer.allocUnsafe(10).fill('α'); buf"), - njs_str("ααααα") }, + /* require('fs').access() */ - { njs_str("var buf = Buffer.allocUnsafe(-1)"), - njs_str("RangeError: invalid size") }, + { njs_str("var fs = require('fs');" + "fs.access()"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("[" - " ['6576696c', 'hex', 4]," - " ['6576696', 'hex', 3]," - " ['', 'hex', 0]," - " ['', 'base64', 0]," - " ['ZXZpbA==', 'base64', 4]," - " ['ZXZpbA', 'base64url', 4]," - " ['ααααα', undefined, 10]," - "].every(args => Buffer.byteLength(args[0], args[1]) == args[2])"), - njs_str("true") }, + { njs_str("var fs = require('fs');" + "fs.access('/njs_unknown_path')"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("Buffer.from([])"), - njs_str("") }, + { njs_str("var fs = require('fs');" + "fs.access('/njs_unknown_path', fs.constants.F_OK)"), + njs_str("TypeError: \"callback\" must be a function") }, - { njs_str("Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72])"), - njs_str("buffer") }, + { njs_str("var fs = require('fs');" + "fs.access('/njs_unknown_path', 'fail', function () {})"), + njs_str("TypeError: \"mode\" must be a number") }, - { njs_str(njs_declare_sparse_array("arr", 6) - "[0x62, 0x75, 0x66, 0x66, 0x65, 0x72].map((v, i) => {arr[i] = v;});" - "Buffer.from(arr)"), - njs_str("buffer") }, + /* require('fs').accessSync() */ - { njs_str("Buffer.from({length:3, 0:0x62, 1:0x75, 2:0x66})"), - njs_str("buf") }, + { njs_str("var fs = require('fs');" + "fs.accessSync()"), + njs_str("TypeError: \"path\" must be a string or Buffer") }, - { njs_str("njs.dump(Buffer.from([-1,1,255,22323,-Infinity,Infinity,NaN]))"), - njs_str("Buffer [255,1,255,51,0,0,0]") }, + { njs_str("var fs = require('fs');" + "fs.accessSync('/njs_unknown_path', 'fail')"), + njs_str("TypeError: \"mode\" must be a number") }, - { njs_str("var buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); njs.dump(buf)"), - njs_str("Buffer [98,117,102,102,101,114]") }, + { njs_str("var " + "fs = require('fs')," + "func = [" + "'access'," + "'accessSync'," + "'readFile'," + "'readFileSync'," + "'writeFile'," + "'writeFileSync'," + "'appendFile'," + "'appendFileSync'," + "'rename'," + "'renameSync'," + "'symlink'," + "'symlinkSync'," + "'unlink'," + "'unlinkSync'," + "'realpath'," + "'realpathSync'," + "'mkdir'," + "'mkdirSync'," + "'rmdir'," + "'rmdirSync'," + "'readdir'," + "'readdirSync'," + "]," + "test = (fname) =>" + "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" + ".map((x) => { try { fs[fname](x); } " + " catch (e) { return (e instanceof TypeError); } })" + ".every((x) => x === true);" + "func.map(test).every((x) => x)"), + njs_str("true")}, - { njs_str("var buf = Buffer.from([1,2,3]); njs.dump(Buffer.from(buf.toJSON()))"), - njs_str("Buffer [1,2,3]") }, + /* require('fs').promises */ - { njs_str("[" - " {type: 'B'}," - " {type: undefined}," - " {type:'Buffer'}," - " {type:'Buffer', data:null}," - " {type:'Buffer', data:{}}," - "].every(v=>{ try { Buffer.from(v)} catch(e) {return e.name == 'TypeError'}})"), - njs_str("true") }, + { njs_str("var fs = require('fs');" + "typeof fs.promises"), + njs_str("object") }, - { njs_str("var foo = new Uint16Array(2);" - "foo[0] = 5000; foo[1] = 4000;" - "var buf = Buffer.from(foo.buffer);" - "foo[1] = 6000;" - "njs.dump(buf)"), - njs_str("Buffer [" njs_evar("136,19,112,23", "19,136,23,112") "]") }, + { njs_str("var " + "fs = require('fs').promises," + "func = [" + "'access'," + "'readFile'," + "'writeFile'," + "'appendFile'," + "'rename'," + "'symlink'," + "'unlink'," + "'realpath'," + "'mkdir'," + "'rmdir'," + "'readdir'," + "];" + "func.every((x) => typeof fs[x] == 'function')"), + njs_str("true")}, - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 1); njs.dump(buf)"), - njs_str("Buffer [" njs_evar("3,182,3", "182,3,182") "]") }, + /* require('fs').constants */ - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, -1); njs.dump(buf)"), - njs_str("RangeError: invalid index") }, + { njs_str("var fs = require('fs');" + "typeof fs.constants"), + njs_str("object") }, - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 5); njs.dump(buf)"), - njs_str("RangeError: \"offset\" is outside of buffer bounds") }, + { njs_str("var " + "fsc = require('fs').constants," + "items = [" + "'F_OK'," + "'R_OK'," + "'W_OK'," + "'X_OK'," + "];" + "items.every((x) => typeof fsc[x] == 'number')"), + njs_str("true")}, - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 2, 1); njs.dump(buf)"), - njs_str("Buffer [" njs_evar("182", "3") "]") }, + /* require('fs').Dirent */ - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 2, -1); njs.dump(buf)"), - njs_str("Buffer []") }, + { njs_str("var fs = require('fs');" + "typeof fs.Dirent"), + njs_str("function") }, - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 2, 3); njs.dump(buf)"), - njs_str("RangeError: \"length\" is outside of buffer bounds") }, + { njs_str("var fs = require('fs');" + "fs.Dirent('file', 123)"), + njs_str("TypeError: the Dirent constructor must be called with new") }, - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 2, 0); njs.dump(buf)"), - njs_str("Buffer []") }, + { njs_str("var fs = require('fs');" + "var e = new fs.Dirent('file', 123); [e.name, e.type]"), + njs_str("file,123") }, - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, 2, 2); njs.dump(buf)"), - njs_str("Buffer [" njs_evar("182,3", "3,182") "]") }, + { njs_str("var " + "fs = require('fs')," + "e = new fs.Dirent('file', 0)," + "func = [" + "'isDirectory'," + "'isFile'," + "'isBlockDevice'," + "'isCharacterDevice'," + "'isSymbolicLink'," + "'isFIFO'," + "'isSocket'," + "];" + "func.every((x) => typeof e[x] == 'function')"), + njs_str("true")}, +}; - { njs_str("var foo = new Uint16Array(2).fill(950);" - "var buf = Buffer.from(foo.buffer, '2', '2'); njs.dump(buf)"), - njs_str("Buffer [" njs_evar("182,3", "3,182") "]") }, - { njs_str("var foo = new Uint32Array(1).fill(0xF1F2F3F4);" - "var buf = Buffer.from(foo); njs.dump(buf)"), - njs_str("Buffer [244]") }, +static njs_unit_test_t njs_crypto_module_test[] = +{ + { njs_str("var h = require('crypto').createHash('sha1');" + "[Object.prototype.toString.call(h), njs.dump(h),h]"), + njs_str("[object Hash],Hash {},[object Hash]") }, - { njs_str("var foo = new Uint32Array(2).fill(0xF1F2F3F4);" - "var buf = Buffer.from(foo); njs.dump(buf)"), - njs_str("Buffer [244,244]") }, + { njs_str("var h = require('crypto').createHash('sha1');" + "var Hash = h.constructor; " + "Hash('sha1').update('AB').digest('hex')"), + njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d") }, - { njs_str("var foo = new Uint8Array(5);" - "foo[0] = 1; foo[1] = 2; foo[2] = 3; foo[3] = 4; foo[4] = 5;" - "foo = foo.subarray(1, 3);" - "var buf = Buffer.from(foo); njs.dump(buf)"), - njs_str("Buffer [2,3]") }, + { njs_str("var h = require('crypto').createHash('sha1');" + "h.constructor.name"), + njs_str("Hash") }, - { njs_str("var buf = Buffer.from(''); njs.dump(buf)"), - njs_str("Buffer []") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'md5');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hash().update('AB').digest().toString(e);" + " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hash().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("b86fc6b051f63d73de262d4c34e3a0a9," + "uG/GsFH2PXPeJi1MNOOgqQ==," + "uG_GsFH2PXPeJi1MNOOgqQ") }, - { njs_str("var buf = Buffer.from('α'); njs.dump(buf)"), - njs_str("Buffer [206,177]") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hash().update('4142', 'hex').digest().toString(e);" + " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hash().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d," + "BtlFlCqiamG+GMPiK/GbvKjdK10=," + "BtlFlCqiamG-GMPiK_GbvKjdK10") }, - { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => arr;" - "njs.dump(Buffer.from(arr))"), - njs_str("Buffer [1,2,3]") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" + "['hex', 'base64', 'base64url'].every(e => {" + " var h = hash().digest(e);" + " var h2 = hash().update('').digest(e);" + " if (h !== h2) {throw new Error(`digest($e):$h != update('').digest($e):$h2`)};" + " return true;" + "})"), + njs_str("true") }, - { njs_str("var obj = new Object(); obj.valueOf = () => obj;" - "Buffer.from(obj)"), - njs_str("TypeError: first argument object is not a string or Buffer-like object") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" + "[" + " ['AB']," + " ['4142', 'hex']," + " ['QUI=', 'base64']," + " ['QUI', 'base64url']" + "].every(args => {" + " return hash().update(args[0], args[1]).digest('hex') === '06d945942aa26a61be18c3e22bf19bbca8dd2b5d';" + "})"), + njs_str("true") }, - { njs_str("var obj = new Object(); obj.valueOf = () => undefined;" - "njs.dump(Buffer.from(obj))"), - njs_str("TypeError: first argument undefined is not a string or Buffer-like object") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha256');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hash().update('AB').digest().toString(e);" + " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hash().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("38164fbd17603d73f696b8b4d72664d735bb6a7c88577687fd2ae33fd6964153," + "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH/SrjP9aWQVM=," + "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH_SrjP9aWQVM") }, - { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => null;" - "njs.dump(Buffer.from(arr))"), - njs_str("Buffer [1,2,3]") }, + { njs_str("var hash = require('crypto').createHash;" + "njs.dump(['', 'abc'.repeat(100)].map(v => {" + " return ['md5', 'sha1', 'sha256'].map(h => {" + " return hash(h).update(v).digest('hex');" + " })" + "}))"), + njs_str("[['d41d8cd98f00b204e9800998ecf8427e'," + "'da39a3ee5e6b4b0d3255bfef95601890afd80709'," + "'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855']," + "['f571117acbd8153c8dc3c81b8817773a'," + "'c95466320eaae6d19ee314ae4f135b12d45ced9a'," + "'d9f5aeb06abebb3be3f38adec9a2e3b94228d52193be923eb4e24c9b56ee0930']]") }, - { njs_str("var obj = new Object(); obj.valueOf = () => new Array(1,2,3);" - "njs.dump(Buffer.from(obj))"), - njs_str("Buffer [1,2,3]") }, + { njs_str("var h = require('crypto').createHash()"), + njs_str("TypeError: algorithm must be a string") }, - { njs_str("njs.dump(Buffer.from(new String('test')))"), - njs_str("Buffer [116,101,115,116]") }, + { njs_str("var h = require('crypto').createHash([])"), + njs_str("TypeError: algorithm must be a string") }, - { njs_str("[" - " ['6576696c', 'hex']," - " ['ZXZpbA==', 'base64']," - " ['ZXZpbA==#', 'base64']," - " ['ZXZpbA', 'base64url']," - " ['ZXZpbA##', 'base64url']," - "].every(args => Buffer.from(args[0], args[1]) == 'evil')"), + { njs_str("var h = require('crypto').createHash('sha512')"), + njs_str("TypeError: not supported algorithm: \"sha512\"") }, + + { njs_str("var h = require('crypto').createHash('sha1');" + "h.update()"), + njs_str("TypeError: data argument \"undefined\" is not a string or Buffer-like object") }, + + { njs_str("var h = require('crypto').createHash('sha1');" + "h.update({})"), + njs_str("TypeError: data argument \"object\" is not a string or Buffer-like object") }, + + { njs_str("var h = require('crypto').createHash('sha1');" + "h.update('A').digest('latin1')"), + njs_str("TypeError: Unknown digest encoding: \"latin1\"") }, + + { njs_str("require('crypto').createHash('sha1').digest() instanceof Buffer"), njs_str("true") }, - { njs_str("var buf = Buffer.from(String.bytesFrom([0xF3])); buf"), - njs_str("�") }, + { njs_str("var h = require('crypto').createHash('sha1');" + "h.update('A').digest('hex'); h.digest('hex')"), + njs_str("Error: Digest already called") }, - { njs_str("Buffer.from('', 'utf-128')"), - njs_str("TypeError: \"utf-128\" encoding is not supported") }, + { njs_str("var h = require('crypto').createHash('sha1');" + "h.update('A').digest('hex'); h.update('B')"), + njs_str("Error: Digest already called") }, - { njs_str("[Buffer.from('α'), new Uint8Array(10), {}, 1]" - ".map(v=>Buffer.isBuffer(v))"), - njs_str("true,false,false,false") }, + { njs_str("typeof require('crypto').createHash('md5')"), + njs_str("object") }, - { njs_str("['utf8', 'utf-8', 'hex', 'base64', 'base64url', 'utf-88', '1hex']" - ".map(v=>Buffer.isEncoding(v))"), - njs_str("true,true,true,true,true,false,false") }, + { njs_str("var h = require('crypto').createHmac('sha1', '');" + "[Object.prototype.toString.call(h), njs.dump(h),h]"), + njs_str("[object Hmac],Hmac {},[object Hmac]") }, - { njs_str("[" - " ['ABC', 'ABCD', -1]," - " ['ABCD', 'ABC', 1]," - " ['ABC', 'ACB', -1]," - " ['ACB', 'ABC', 1]," - " ['ABC', 'ABC', 0]," - " ['', 'ABC', -1]," - " ['', '', 0]," - "].every(args => {" - " if (Buffer.compare(Buffer.from(args[0]), Buffer.from(args[1])) != args[2]) {" - " throw new TypeError(" - " `Buffer.compare(Buffer.from(${args[0]}), Buffer.from(${args[1]})) != ${args[2]}`);" - " }" - " return true;" + { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'md5', '');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hmac().update('AB').digest().toString(e);" + " var h2 = hmac().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hmac().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" "})"), - njs_str("true") }, + njs_str("9e0e9e545ef63d41dfb653daecf8ebc7," + "ng6eVF72PUHftlPa7Pjrxw==," + "ng6eVF72PUHftlPa7Pjrxw") }, - { njs_str("[" - " ['ABC', 'ABCD', -1]," - " ['ABCD', 'ABC', 1]," - " ['ABC', 'ACB', -1]," - " ['ACB', 'ABC', 1]," - " ['ABC', 'ABC', 0]," - " ['', 'ABC', -1]," - " ['', '', 0]," - "].every(args => {" - " if (Buffer.from(args[0]).compare(Buffer.from(args[1])) != args[2]) {" - " throw new TypeError(" - " `Buffer.from(${args[0]}).compare(Buffer.from(${args[1]})) != ${args[2]}`);" - " }" - " return true;" + { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'sha1', '');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hmac().update('AB').digest().toString(e);" + " var h2 = hmac().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hmac().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" "})"), - njs_str("true") }, + njs_str("d32c0b6637cc2dfe4670f3fe48ef4434123c4810," + "0ywLZjfMLf5GcPP+SO9ENBI8SBA=," + "0ywLZjfMLf5GcPP-SO9ENBI8SBA") }, - { njs_str("var buf = Buffer.from('ABCD');" + { njs_str("var hash = require('crypto').createHmac.bind(undefined, 'sha1', '');" "[" - " [0,3,0,2, -1]," - " [0,2,0,3, 1]," - " [3,4,3,4, 0]," - " [undefined, undefined, undefined, undefined, 0]," - " [-1, undefined, undefined, undefined, 'invalid index']," - " [0, -1, undefined, undefined, 'invalid index']," - " [0, 0, -1, undefined, 'invalid index']," - " [0, 0, 0, -1, 'invalid index']," - "]" - ".every(as => {" - " try {" - " if (buf.compare(buf, as[0], as[1], as[2], as[3]) != as[4]) {" - " throw new TypeError(" - " `buf.compare(${as[0]}, ${as[1]}, ${as[2]}, ${as[3]}) != ${as[4]}`);" - " }" - " } catch (e) { return e.message == as[4]}" - " return true;" + " ['AB']," + " ['4142', 'hex']," + " ['QUI=', 'base64']," + " ['QUI', 'base64url']" + "].every(args => {" + " return hash().update(args[0], args[1]).digest('hex') === 'd32c0b6637cc2dfe4670f3fe48ef4434123c4810';" "})"), njs_str("true") }, - { njs_str("var buf1 = Buffer.from('ABCD');" - "var buf2 = Buffer.from('ABCD');" - "buf1.compare(buf2, 5)"), - njs_str("RangeError: \"targetStart\" is out of range: 5") }, - - { njs_str("var buf1 = Buffer.from('ABCD');" - "var buf2 = Buffer.from('ABCD');" - "buf1.compare(buf2, 0, 3, 5)"), - njs_str("RangeError: \"sourceStart\" is out of range: 5") }, + { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'sha256', '');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hmac().update('AB').digest().toString(e);" + " var h2 = hmac().update(Buffer.from('AB')).digest(e);" + " var h3 = hmac().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("d53400095496267cf02e5dbd4b0bf9fbfb5f36f311ea7d9809af5487421743e3," + "1TQACVSWJnzwLl29Swv5+/tfNvMR6n2YCa9Uh0IXQ+M=," + "1TQACVSWJnzwLl29Swv5-_tfNvMR6n2YCa9Uh0IXQ-M") }, - { njs_str("var arr = new Uint8Array(4);" - "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" - "arr = arr.subarray(1, 4);" - "var buf = Buffer.from('ABCD');" - "buf.compare(arr, 0, 3, 1, 4)"), - njs_str("0") }, + { njs_str("var hmac = require('crypto').createHmac;" + "njs.dump(['', 'abc'.repeat(100)].map(v => {" + " return ['md5', 'sha1', 'sha256'].map(h => {" + " return hmac(h, Buffer.from('secret')).update(v).digest('hex');" + " })" + "}))"), + njs_str("[['5c8db03f04cec0f43bcb060023914190'," + "'25af6174a0fcecc4d346680a72b7ce644b9a88e8'," + "'f9e66e179b6747ae54108f82f8ade8b3c25d76fd30afde6c395822c530196169']," + "['91eb74a225cdd3bbfccc34396c6e3ac5'," + "'0aac71e3a813a7acc4a809cfdedb2ecba04ffc5e'," + "'8660d2d51d6f20f61d5aadfb6c43df7fd05fc2fc4967d8aec1846f3d9ec03987']]") }, - { njs_str("['123', 'abc', '124', '', 'AB', 'ABCD']" - ".map(v=>Buffer.from(v)).sort(Buffer.compare).map(v=>v.toString())"), - njs_str(",123,124,AB,ABCD,abc") }, + { njs_str("var h = require('crypto').createHmac('sha1', '');" + "var Hmac = h.constructor; " + "Hmac('sha1', '').digest('hex')"), + njs_str("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d") }, - { njs_str("Buffer.compare(Buffer.alloc(1), 'text')"), - njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") }, + { njs_str("var h = require('crypto').createHmac('sha1', '');" + "h.constructor.name"), + njs_str("Hmac") }, - { njs_str("Buffer.compare('text', Buffer.from('ACB'))"), - njs_str("TypeError: \"source\" argument must be an instance of Buffer or Uint8Array") }, + { njs_str("require('crypto').createHmac('sha1', '').digest() instanceof Buffer"), + njs_str("true") }, - { njs_str("Buffer.concat()"), - njs_str("TypeError: \"list\" argument must be an instance of Array") }, + { njs_str("var h = require('crypto').createHmac('sha256', 'A'.repeat(64));" + "h.update('AB').digest('hex')"), + njs_str("ee9dce43b12eb3e865614ad9c1a8d4fad4b6eac2b64647bd24cd192888d3f367") }, - { njs_str("Buffer.concat([])"), - njs_str("") }, + { njs_str("var h = require('crypto').createHmac('sha256', 'A'.repeat(100));" + "h.update('AB').digest('hex')"), + njs_str("5647b6c429701ff512f0f18232b4507065d2376ca8899a816a0a6e721bf8ddcc") }, - { njs_str("Buffer.concat([new Uint16Array(10)])"), - njs_str("TypeError: \"list[0]\" argument must be an instance of Buffer or Uint8Array") }, + { njs_str("var h = require('crypto').createHmac()"), + njs_str("TypeError: algorithm must be a string") }, - { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)]).fill('abc')"), - njs_str("abc") }, + { njs_str("var h = require('crypto').createHmac([])"), + njs_str("TypeError: algorithm must be a string") }, - { njs_str("Buffer.concat([Buffer.from('AB'), Buffer.from('CD')])"), - njs_str("ABCD") }, - - { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)], 2).fill('abc')"), - njs_str("ab") }, + { njs_str("var h = require('crypto').createHmac('sha512', '')"), + njs_str("TypeError: not supported algorithm: \"sha512\"") }, - { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)], 6).fill('abc')"), - njs_str("abcabc") }, + { njs_str("var h = require('crypto').createHmac('sha1', [])"), + njs_str("TypeError: key argument \"array\" is not a string or Buffer-like object") }, - { njs_str(njs_declare_sparse_array("list", 2) - "list[0] = new Uint8Array(2); list[1] = new Uint8Array(3);" - "Buffer.concat(list).fill('ab');"), - njs_str("ababa") }, + { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" + "h.update('A').digest('hex'); h.digest('hex')"), + njs_str("Error: Digest already called") }, - { njs_str("Buffer.concat([], '123')"), - njs_str("TypeError: \"length\" argument must be of type number") }, + { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" + "h.update('A').digest('hex'); h.update('B')"), + njs_str("Error: Digest already called") }, - { njs_str("Buffer.concat([], -1)"), - njs_str("RangeError: \"length\" is out of range") }, + { njs_str("typeof require('crypto').createHmac('md5', 'a')"), + njs_str("object") }, - { njs_str("var buf = Buffer.from('α'); buf[1]"), - njs_str("177") }, + { njs_str("var cr = require('crypto'); var h = cr.createHash('sha1');" + "h.update.call(cr.createHmac('sha1', 's'), '')"), + njs_str("TypeError: \"this\" is not a hash object") }, +}; - { njs_str("var buf = Buffer.from('α'); buf[1] = 1; njs.dump(buf)"), - njs_str("Buffer [206,1]") }, +static njs_unit_test_t njs_querystring_module_test[] = +{ + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz');" + "njs.dump(obj)"), + njs_str("{baz:'fuz'}") }, - { njs_str("var arrBuf = new ArrayBuffer(16);" - "var buf = Buffer.from(arrBuf); buf.buffer === arrBuf"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=');" + "njs.dump(obj)"), + njs_str("{baz:''}") }, - { njs_str("[" - " [[0], 4, '65,66,67,68,0,0,0,0,0,0']," - " [[5], 4, '0,0,0,0,0,65,66,67,68,0']," - " [[8], 2, '0,0,0,0,0,0,0,0,65,66']," - " [[8,2,4], 2, '0,0,0,0,0,0,0,0,67,68']," - " [[10], 0, '0,0,0,0,0,0,0,0,0,0']," - "]" - ".every(args => {" - " var buf1 = Buffer.from('ABCD');" - " var buf2 = Buffer.alloc(10, 0);" - " var as = args[0];" - " var length = buf1.copy(buf2, as[0], as[1], as[2]);" - "" - " if (length != args[1]) {" - " throw new TypeError(`buf1.copy(buf2, ${as[0]}, ${as[1]}, ${as[2]}): ${length} != ${args[1]}`)" - " }" - "" - " if (njs.dump(buf2) != `Buffer [${args[2]}]`) {" - " throw new TypeError(" - " `buf1.copy(buf2, ${as[0]}, ${as[1]}, ${as[2]}): ${njs.dump(buf2)} != Buffer [${args[2]}]`);" - " }" - " return true;" - "})"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax');" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("[" - " [[0], 'ABCDEF']," - " [[0,2], 'CDEFEF']," - " [[0,2,6], 'CDEFEF']," - " [[1,2,4], 'ACDDEF']," - " [[1,2,3], 'ACCDEF']" - "]" - ".every(args => {" - " var buf = Buffer.from('ABCDEF');" - " var as = args[0];" - " buf.copy(buf, as[0], as[1], as[2]);" - "" - " if (buf.toString() != args[1]) {" - " throw new TypeError(" - " `buf.copy(buf, ${as[0]}, ${as[1]}, ${as[2]}): buf.toString() != ${args[1]}`);" - " }" - " return true;" - "})"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&');" + "njs.dump(obj)"), + njs_str("{baz:'fuz'}") }, - { njs_str("var buf1 = Buffer.from('ABCD');" - "var buf2 = Buffer.alloc(10, 0);" - "buf1.copy(buf2, -1)"), - njs_str("RangeError: invalid index") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('&baz=fuz');" + "njs.dump(obj)"), + njs_str("{baz:'fuz'}") }, - { njs_str("var buf1 = Buffer.from('ABCD');" - "var buf2 = Buffer.alloc(10, 0);" - "buf1.copy(buf2, 0, -1)"), - njs_str("RangeError: invalid index") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('&&&&&baz=fuz');" + "njs.dump(obj)"), + njs_str("{baz:'fuz'}") }, - { njs_str("var buf1 = Buffer.from('ABCD');" - "var buf2 = Buffer.alloc(10, 0);" - "buf1.copy(buf2, 0, 5)"), - njs_str("RangeError: \"sourceStart\" is out of range: 5") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('=fuz');" + "njs.dump(obj)"), + njs_str("{:'fuz'}") }, - { njs_str("var arr = new Uint8Array(4);" - "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" - "arr = arr.subarray(1, 4);" - "var buf1 = Buffer.from(arr);" - "var buf2 = Buffer.alloc(10, 0);" - "var length = buf1.copy(buf2, 1, 1, 2); [length, njs.dump(buf2)]"), - njs_str("1,Buffer [0,67,0,0,0,0,0,0,0,0]") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('=fuz=');" + "njs.dump(obj)"), + njs_str("{:'fuz='}") }, - { njs_str("var arr = new Uint8Array(4);" - "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" - "arr = arr.subarray(1, 4);" - "var buf1 = Buffer.from(arr);" - "var buf2 = Buffer.alloc(10, 0);" - "var length = buf1.copy(buf2, 1, 1, 2); [length, njs.dump(buf2)]"), - njs_str("1,Buffer [0,67,0,0,0,0,0,0,0,0]") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('===fu=z');" + "njs.dump(obj)"), + njs_str("{:'==fu=z'}") }, - { njs_str("[" - " ['ABC', 'ABCD', false]," - " ['ABCD', 'ABC', false]," - " ['ABC', 'ACB', false]," - " ['ACB', 'ABC', false]," - " ['ABC', 'ABC', true]," - " ['', 'ABC', false]," - " ['', '', true]," - "].every(args => {" - " if (Buffer.from(args[0]).equals(Buffer.from(args[1])) != args[2]) {" - " throw new TypeError(" - " `Buffer.from(${args[0]}).compare(Buffer.from(${args[1]})) != ${args[2]}`);" - " }" - " return true;" - "})"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&baz=tax');" + "njs.dump(obj)"), + njs_str("{baz:['fuz','tax']}") }, - { njs_str("Buffer.from([1,2]).equals(new ArrayBuffer(1))"), - njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('freespace');" + "njs.dump(obj)"), + njs_str("{freespace:''}") }, - { njs_str("Buffer.from([1,2]).equals(1)"), - njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('name&value=12');" + "njs.dump(obj)"), + njs_str("{name:'',value:'12'}") }, - { njs_str("var buf = Buffer.alloc(4);" - "buf.fill('ZXZpbA==', 'base64')"), - njs_str("evil") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', 'fuz');" + "njs.dump(obj)"), + njs_str("{baz:'',&muz:'tax'}") }, - { njs_str("var buf = Buffer.alloc(4);" - "buf.fill('6576696c', 'hex')"), - njs_str("evil") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', '');" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("var buf = Buffer.alloc(4);" - "buf.fill('ZXZpbA==', '')"), - njs_str("TypeError: \"\" encoding is not supported") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', null);" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("var buf = Buffer.alloc(8);" - "buf.fill('6576696c', 'hex')"), - njs_str("evilevil") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', undefined);" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("var buf = Buffer.alloc(10);" - "buf.fill('evil')"), - njs_str("evilevilev") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz123muz=tax', 123);" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("var buf = Buffer.allocUnsafe(5);" - "buf[3] = 1;" - "buf.fill(''); njs.dump(buf)"), - njs_str("Buffer [0,0,0,0,0]") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuzαααmuz=tax', 'ααα');" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("var arr = new Uint8Array(4);" - "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" - "arr = arr.subarray(1, 4);" - "var buf = Buffer.allocUnsafe(6);" - "buf.fill(arr); njs.dump(buf)"), - njs_str("Buffer [66,67,68,66,67,68]") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', '=');" + "njs.dump(obj)"), + njs_str("{baz:'',fuz&muz:'',tax:''}") }, - { njs_str("var buf = Buffer.alloc(6, 'ABCDEF');" - "buf.fill(buf, 2, 6)"), - njs_str("ABABCD") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', null, 'fuz');" + "njs.dump(obj)"), + njs_str("{baz=:'',muz=tax:''}") }, - { njs_str("Buffer.alloc(6).fill(0x41)"), - njs_str("AAAAAA") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', null, '&');" + "njs.dump(obj)"), + njs_str("{baz=fuz:'',muz=tax:''}") }, - { njs_str("Buffer.alloc(6).fill({valueOf(){return 0x42}})"), - njs_str("BBBBBB") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz123fuz&muz123tax', null, 123);" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("njs.dump(Buffer.alloc(3).fill(-1))"), - njs_str("Buffer [255,255,255]") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('bazαααfuz&muzαααtax', null, 'ααα');" + "njs.dump(obj)"), + njs_str("{baz:'fuz',muz:'tax'}") }, - { njs_str("[NaN, Infinity, -Infinity, undefined, null, {}]" - ".every(v => njs.dump(Buffer.alloc(3).fill(v)) == 'Buffer [0,0,0]')"), - njs_str("true") }, - - { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 4,3))"), - njs_str("Buffer [0,0,0,0,0,0]") }, - - { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 3,3))"), - njs_str("Buffer [0,0,0,0,0,0]") }, - - { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 2,3))"), - njs_str("Oops") }, - - { njs_str("njs.dump(Buffer.alloc(5).fill('α'))"), - njs_str("Buffer [206,177,206,177,206]") }, - - { njs_str("Buffer.alloc(4).fill('ABCD', -1)"), - njs_str("RangeError: invalid index") }, - - { njs_str("Buffer.alloc(4).fill('ABCD', 5)"), - njs_str("RangeError: \"offset\" is out of range") }, - - { njs_str("Buffer.alloc(4).fill('ABCD', 0, -1)"), - njs_str("RangeError: invalid index") }, - - { njs_str("Buffer.alloc(4).fill('ABCD', 0, 5)"), - njs_str("RangeError: \"end\" is out of range") }, - - { njs_str("Buffer.alloc(513).fill('A'.repeat(512)).length"), - njs_str("513") }, - - { njs_str("njs.dump(Buffer.alloc(4).fill((new Uint8Array(5)).fill(1)))"), - njs_str("Buffer [1,1,1,1]") }, - - { njs_str("var src = new Uint8Array(10).fill(255);" - "var u8 = new Uint8Array(src.buffer, 1, 8);" - "u8.set([1,2,3,4,5,6,7,8]);" - "njs.dump(Buffer.alloc(9).fill(u8))"), - njs_str("Buffer [1,2,3,4,5,6,7,8,1]") }, - - { njs_str("Buffer.alloc(513).fill((new Uint8Array(512)).fill(1)).length"), - njs_str("513") }, - - { njs_str("Buffer.alloc(4).fill('ABCD', undefined, undefined, 'utf-128')"), - njs_str("TypeError: \"utf-128\" encoding is not supported") }, - - { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 3);" - "buf1.fill('B', 1, 2); njs.dump(buf1)"), - njs_str("Buffer [66,66]") }, - - { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 3);" - "buf1.fill(0x42, 1, 2); njs.dump(buf1)"), - njs_str("Buffer [66,66]") }, - - { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 2);" - "var buf2 = Buffer.from('ABCD').subarray(1, 3);" - "buf2.fill(buf1, 1, 2); njs.dump(buf2)"), - njs_str("Buffer [66,66]") }, - - { njs_str("var buf = Buffer.from('ABCD');" - "['BC', 'CB', 'ABCD', 'ABCDE', ''].map(v=>buf.indexOf(v))"), - njs_str("1,-1,0,-1,0") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=fuz&muz=tax', null, null, {maxKeys: 1});" + "njs.dump(obj)"), + njs_str("{baz:'fuz'}") }, - { njs_str("var buf = Buffer.from('ABCD');" - "[0,5,-2,-1].map(v=>buf.indexOf('C', v))"), - njs_str("2,-1,2,-1") }, + { njs_str("var qs = require('querystring'); var out = [];" + "var obj = qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: (key) => {out.push(key)}});" + "out.join('; ');"), + njs_str("baz; fuz; muz; tax") }, - { njs_str("var buf = Buffer.from('evil');" - "buf.indexOf('ZXZpbA==', undefined, 'base64')"), - njs_str("0") }, + { njs_str("var qs = require('querystring'); var i = 0;" + "var obj = qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: (key) => 'α' + i++});" + "njs.dump(obj);"), + njs_str("{α0:'α1',α2:'α3'}") }, - { njs_str("var buf = Buffer.from('evil');" - "buf.indexOf('6576696c', undefined, 'hex')"), - njs_str("0") }, + { njs_str("var qs = require('querystring');" + "qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: 123});"), + njs_str("TypeError: option decodeURIComponent is not a function") }, - { njs_str("var buf = Buffer.from('ABCD');" - "buf.indexOf('C', undefined, 'utf-128')"), - njs_str("TypeError: \"utf-128\" encoding is not supported") }, + { njs_str("var qs = require('querystring');" + "qs.unescape = 123;" + "qs.parse('baz=fuz&muz=tax');"), + njs_str("TypeError: QueryString.unescape is not a function") }, - { njs_str("var buf = Buffer.from('ABCDABC');" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.indexOf(Buffer.from(v)))"), - njs_str("1,-1,0,-1,0,2,-1") }, + { njs_str("var qs = require('querystring'); var out = [];" + "qs.unescape = (key) => {out.push(key)};" + "qs.parse('baz=fuz&muz=tax');" + "out.join('; ');"), + njs_str("baz; fuz; muz; tax") }, - { njs_str("var buf = Buffer.from('ABCDABC');" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.includes(Buffer.from(v)))"), - njs_str("true,false,true,false,true,true,false") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('ba%32z=f%32uz');" + "njs.dump(obj)"), + njs_str("{ba2z:'f2uz'}") }, - { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.indexOf(Buffer.from(v)))"), - njs_str("1,-1,0,-1,0,2,-1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('ba%32z=f%32uz');" + "njs.dump(obj)"), + njs_str("{ba2z:'f2uz'}") }, - { njs_str("var buf = Buffer.from('ABCD');" - "buf.indexOf(0x43)"), - njs_str("2") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('ba%F0%9F%92%A9z=f%F0%9F%92%A9uz');" + "njs.dump(obj)"), + njs_str("{ba💩z:'f💩uz'}") }, - { njs_str("var buf = Buffer.from('ABCD');" - "buf.indexOf(0x43, -2)"), - njs_str("2") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('======');" + "njs.dump(obj)"), + njs_str("{:'====='}") }, - { njs_str("var buf = Buffer.from('ABCD');" - "buf.indexOf(0x43, -1)"), - njs_str("-1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=%F0%9F%A9');" + "njs.dump(obj)"), + njs_str("{baz:'�'}") }, - { njs_str("var buf1 = Buffer.from('ABCD');" - "var buf2 = Buffer.from('XXCX').subarray(2, 3);" - "buf1.indexOf(buf2)"), - njs_str("2") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=αααααα%\x00\x01\x02αααα');" + "njs.dump(obj)"), + njs_str("{baz:'αααααα%\\u0000\\u0001\\u0002αααα'}") }, - { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 4);" - "buf1.indexOf(0x43)"), - njs_str("1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=%F6α');" + "njs.dump(obj)"), + njs_str("{baz:'�α'}") }, - { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 4);" - "buf1.indexOf('C')"), - njs_str("1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=%F6');" + "njs.dump(obj)"), + njs_str("{baz:'�'}") }, - { njs_str("var buf = Buffer.from('ABCDABC');" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(v))"), - njs_str("5,-1,0,-1,7,6,-1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=%FG');" + "njs.dump(obj)"), + njs_str("{baz:'%FG'}") }, - { njs_str("var buf = Buffer.from('ABCDABC');" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(Buffer.from(v)))"), - njs_str("5,-1,0,-1,7,6,-1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=%F');" + "njs.dump(obj)"), + njs_str("{baz:'%F'}") }, - { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(v))"), - njs_str("5,-1,0,-1,7,6,-1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('baz=%');" + "njs.dump(obj)"), + njs_str("{baz:'%'}") }, - { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);" - "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(Buffer.from(v)))"), - njs_str("5,-1,0,-1,7,6,-1") }, + { njs_str("var qs = require('querystring');" + "var obj = qs.parse('ba+z=f+uz');" + "njs.dump(obj)"), + njs_str("{ba z:'f uz'}") }, - { njs_str("var buf = Buffer.from('CABCD');" - "[2,-2,1,-10,10,-5,-4,0].map(v=>buf.lastIndexOf('C', v))"), - njs_str("0,3,0,-1,3,0,0,0") }, - { njs_str("var buf = Buffer.from('CABCD');" - "[2,-2,1,-10,10,-5,-4,0].map(v=>buf.lastIndexOf(Buffer.from('CZ').subarray(0,1), v))"), - njs_str("0,3,0,-1,3,0,0,0") }, + { njs_str("var qs = require('querystring');" + "qs.parse('X='+'α'.repeat(33)).X.length"), + njs_str("33") }, - { njs_str("var buf = Buffer.from('CABCD');" - "buf.lastIndexOf(0x43)"), - njs_str("3") }, + { njs_str("var qs = require('querystring');" + "var x = qs.parse('X='+'α1'.repeat(33)).X;" + "[x.length, x[33], x[34]]"), + njs_str("66,1,α") }, - { njs_str("var buf = Buffer.from('CABCD');" - "[2,1,0,4,5,-1,-5].map(v=>buf.lastIndexOf(0x43, v))"), - njs_str("0,0,0,3,3,3,0") }, + { njs_str("var qs = require('querystring');" + "var s = qs.parse('X='+String.bytesFrom(Array(16).fill(0x9d))).X;" + "[s.length, s.toUTF8().length, s[15]]"), + njs_str("16,48,�") }, - { njs_str("var buf1 = Buffer.from('ACBCD').subarray(1, 4);" - "var buf2 = Buffer.from('C');" - "buf1.lastIndexOf(buf2)"), - njs_str("2") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz'})"), + njs_str("baz=fuz") }, - { njs_str("var buf1 = Buffer.from('XXCXX').subarray(2,3);" - "buf1.lastIndexOf(Buffer.from('X'))"), - njs_str("-1") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'})"), + njs_str("baz=fuz&muz=tax") }, - { njs_str("var buf = Buffer.from('ACBCD').subarray(1, 4);" - "buf.lastIndexOf(0x43)"), - njs_str("2") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baαz': 'fαuz', 'muαz': 'tαax'});"), + njs_str("ba%CE%B1z=f%CE%B1uz&mu%CE%B1z=t%CE%B1ax") }, - { njs_str("var buf = Buffer.from('ACBCD').subarray(1, 4);" - "buf.lastIndexOf('C')"), - njs_str("2") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': ['fuz', 'tax']})"), + njs_str("baz=fuz&baz=tax") }, - { njs_str("['swap16', 'swap32', 'swap64'].every(method => {" - " var buf = Buffer.from([]);" - " buf[method]();" - " return njs.dump(buf) === 'Buffer []';" - "})"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + njs_declare_sparse_array("arr", 2) + "arr[0] = 0; arr[1] = 1.5;" + "qs.stringify({'baz': arr})"), + njs_str("baz=0&baz=1.5") }, - { njs_str("['swap16', 'swap32', 'swap64'].every(method => {" - " var buf = Buffer.from([1,2,3]);" - " try { buf[method]() } " - " catch(e) {return e.message === `Buffer size must be a multiple of ${method.substr(4)}-bits`};" - "})"), - njs_str("true") }, + { njs_str("var qs = require('querystring'); var out = [];" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, null, {encodeURIComponent: (key) => {out.push(key)}});" + "out.join('; ')"), + njs_str("baz; fuz; muz; tax") }, - { njs_str("['swap16', 'swap32', 'swap64'].map(method => {" - " var buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);" - " buf[method]();" - " return njs.dump(buf);" - "})"), - njs_str("Buffer [2,1,4,3,6,5,8,7]," - "Buffer [4,3,2,1,8,7,6,5]," - "Buffer [8,7,6,5,4,3,2,1]") }, + { njs_str("var qs = require('querystring'); " + "qs.stringify({a: 'b'}, null, null, " + " {encodeURIComponent: () => String.bytesFrom([0x9d])})"), + njs_str("TypeError: got non-UTF8 string from encoder") }, - { njs_str("['swap16', 'swap32', 'swap64'].map(method => {" - " var u8 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8]);" - " var buf = Buffer.from(u8.buffer, 1);" - " buf[method]();" - " return njs.dump(buf);" - "})"), - njs_str("Buffer [2,1,4,3,6,5,8,7]," - "Buffer [4,3,2,1,8,7,6,5]," - "Buffer [8,7,6,5,4,3,2,1]") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, null, {encodeURIComponent: 123});" + "out.join('; ')"), + njs_str("TypeError: option encodeURIComponent is not a function") }, - { njs_str("njs.dump(Buffer.from('αααα').toJSON())"), - njs_str("{type:'Buffer',data:[206,177,206,177,206,177,206,177]}") }, + { njs_str("var qs = require('querystring');" + "qs.escape = 123;" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'})"), + njs_str("TypeError: QueryString.escape is not a function") }, - { njs_str("njs.dump(Buffer.from('').toJSON())"), - njs_str("{type:'Buffer',data:[]}") }, + { njs_str("var qs = require('querystring'); var out = [];" + "qs.escape = (key) => {out.push(key)};" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'});" + "out.join('; ')"), + njs_str("baz; fuz; muz; tax") }, - { njs_str("[" - " [['base64'], 'ZXZpbA==']," - " [['base64url'], 'ZXZpbA']," - " [['hex'], '6576696c']," - " [[undefined,1,3], 'vi']," - " [[undefined,5], '']," - " [[undefined,undefined,5], 'evil']," - " [[undefined,undefined,undefined], 'evil']," - "].every(args => {" - " var buf = Buffer.from('evil');" - " var as = args[0];" - " if (buf.toString(as[0], as[1], as[2]) != args[1]) {" - " throw new TypeError(" - " `buf.toString(${as[0]}, ${as[1]}, ${as[2]}) != ${args[1]}`);" - " }" - " return true;" - "})"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, '****')"), + njs_str("baz=fuz****muz=tax") }, - { njs_str("Buffer.from('evil').toString('utf-128')"), - njs_str("TypeError: \"utf-128\" encoding is not supported") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, '^^^^')"), + njs_str("baz^^^^fuz&muz^^^^tax") }, - { njs_str("var buf = Buffer.allocUnsafe(4);" - "var len = buf.write('ZXZpbA==', 'base64'); [len, buf]"), - njs_str("4,evil") }, + { njs_str("var qs = require('querystring');" + "var obj = {A:'α'}; obj['δ'] = 'D';" + "var s = qs.stringify(obj,'γ=','&β'); [s, s.length]"), + njs_str("A&β%CE%B1γ=%CE%B4&βD,20") }, - { njs_str("var buf = Buffer.allocUnsafe(4);" - "var len = buf.write('ZXZpbA==', undefined, 'base64'); [len, buf]"), - njs_str("4,evil") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, '', '')"), + njs_str("baz=fuz&muz=tax") }, - { njs_str("var buf = Buffer.allocUnsafe(4);" - "var len = buf.write('ZXZpbA==', undefined, undefined, 'base64'); [len, buf]"), - njs_str("4,evil") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, undefined, undefined)"), + njs_str("baz=fuz&muz=tax") }, - { njs_str("Buffer.allocUnsafe(4).write()"), - njs_str("TypeError: first argument must be a string") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, '?', '/')"), + njs_str("baz/fuz?muz/tax") }, - { njs_str("Buffer.allocUnsafe(4).write({a: 1})"), - njs_str("TypeError: first argument must be a string") }, + { njs_str("var qs = require('querystring');" + "qs.stringify('123')"), + njs_str("") }, - { njs_str("Buffer.alloc(4).write('evil', 4, 1);"), - njs_str("RangeError: \"offset\" is out of range") }, + { njs_str("var qs = require('querystring');" + "qs.stringify(123)"), + njs_str("") }, - { njs_str("Buffer.alloc(4).write('evil', -1);"), - njs_str("RangeError: invalid index") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({X: String.bytesFrom(Array(4).fill(0x9d))})"), + njs_str("X=%9D%9D%9D%9D") }, - { njs_str("var buf = Buffer.alloc(4);" - "var len = buf.write('evil', 3, 1); [len, njs.dump(buf)]"), - njs_str("1,Buffer [0,0,0,101]") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({X:{toString(){return 3}}})"), + njs_str("X=") }, - { njs_str("var buf = Buffer.alloc(4);" - "var len = buf.write('evil', 0, 5); [len, buf]"), - njs_str("4,evil") }, + { njs_str("var qs = require('querystring');" + "qs.stringify({ name: undefined, age: 12 })"), + njs_str("name=&age=12") }, - { njs_str("Buffer.alloc(4).write('evil', undefined, -1);"), - njs_str("RangeError: invalid index") }, + { njs_str("var qs = require('querystring');" + "qs.stringify(Object.create({ name: undefined, age: 12 }))"), + njs_str("") }, - { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" - "[1,2,3,4,5,6].map(byte => [buf.readUIntLE(0, byte), buf.readUIntLE(1, byte)])"), - njs_str("250,251," - "64506,64763," - "16579578,16645371," - "4261215226,4278058235," - "1095182908410,1099494718715," - "281470647991290,274877890034939") }, + { njs_str("var qs = require('querystring');" + "qs.stringify([])"), + njs_str("") }, - { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" - "[1,2,3,4,5,6].map(byte => [buf.readIntLE(0, byte), buf.readIntLE(1, byte)])"), - njs_str("-6,-5," - "-1030,-773," - "-197638,-131845," - "-33752070,-16909061," - "-4328719366,-16909061," - "-4328719366,-6597086675717") }, + { njs_str("var qs = require('querystring');" + "qs.stringify(['','',''])"), + njs_str("0=&1=&2=") }, - { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" - "[1,2,3,4,5,6].map(byte => [buf.readUIntBE(0, byte), buf.readUIntBE(1, byte)])"), - njs_str("250,251," - "64251,64508," - "16448508,16514301," - "4210818301,4227661310," - "1077969485310,1082281295615," - "275960188239615,277064011677689") }, + { njs_str("var qs = require('querystring');" + "qs.stringify([undefined, null, Symbol(), Object(0), Object('test'), Object(false),,,])"), + njs_str("0=&1=&2=&3=&4=&5=") }, - { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" - "[1,2,3,4,5,6].map(byte => [buf.readIntBE(0, byte), buf.readIntBE(1, byte)])"), - njs_str("-6,-5," - "-1285,-1028," - "-328708,-262915," - "-84148995,-67305986," - "-21542142466,-17230332161," - "-5514788471041,-4410965032967") }, +#if 0 + { njs_str("var qs = require('querystring');" + "qs.stringify([NaN, Infinity, -Infinity, 2**69, 2**70])"), + njs_str("0=&1=&2=&3=590295810358705700000&4=1.1805916207174113e%2B21") }, +#else + { njs_str("var qs = require('querystring');" + "qs.stringify([NaN, Infinity, -Infinity, 2**69, 2**70])"), + njs_str("0=&1=&2=&3=590295810358705700000&4=1.1805916207174114e%2B21") }, +#endif - { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" - "function t(sign, endianness, offset) { " - " return [1,2,4].every(size => {" - " var method = `read${sign}Int${size * 8}`;" - " if (size > 1) { method += endianness};" - " var gmethod = `read${sign}Int${endianness}`;" - " var gv = buf[gmethod](offset, size);" - " var sv = buf[method](offset);" - " if (gv != sv) {throw Error(`${gmethod}(${offset},${size}):${gv} != ${method}(${offset}):${sv}`)}" - " return true;" - " });" - "}; " - "t('U', 'LE', 0) && t('U', 'LE', 1)" - "&& t('', 'LE', 0) && t('', 'LE', 1)" - "&& t('U', 'BE', 0) && t('U', 'BE', 1)" - "&& t('', 'BE', 0) && t('', 'BE', 1)"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "qs.stringify([[1,2,3],[4,5,6]])"), + njs_str("0=1&0=2&0=3&1=4&1=5&1=6") }, - { njs_str("var buf = Buffer.alloc(9);" - "function t(sign, endianness, offset) { " - " return [1,2,4].every(size => {" - " var rgmethod = `read${sign}Int${endianness}`;" - " var wgmethod = `write${sign}Int${endianness}`;" - " var rmethod = `read${sign}Int${size * 8}`;" - " var wmethod = `write${sign}Int${size * 8}`;" - " if (size > 1) { rmethod += endianness; wmethod += endianness; };" - " var v = 0x7abbccddeeff & (size * 8 - 1);" - "" - " var ret = buf[wgmethod](v, offset, size);" - " if(ret !== offset + size) {" - " throw Error(`${wgmethod} returned ${ret}, need ${offset + size}`);" - " }" - "" - " var gv = buf[rgmethod](offset, size);" - "" - " buf.fill(0);" - " buf[wmethod](v, offset);" - " var sv = buf[rmethod](offset);" - " if (gv != sv) {throw Error(`${wmethod}(${v}, ${offset}):${sv} != ${wgmethod}(${v},${offset}):${gv}`)}" - " return true;" - " });" - "}; " - "t('U', 'LE', 0) && t('U', 'LE', 1)" - "&& t('', 'LE', 0) && t('', 'LE', 1)" - "&& t('U', 'BE', 0) && t('U', 'BE', 1)" - "&& t('', 'BE', 0) && t('', 'BE', 1)"), - njs_str("true") }, + { njs_str("var qs = require('querystring');" + "qs.stringify([['a',,,],['b',,,]])"), + njs_str("0=a&0=&0=&1=b&1=&1=") }, - { njs_str(njs_buffer_byte_map("writeUIntLE", "+", 1)), - njs_str("Buffer [128,0,0,0,0,0]," - "Buffer [0,64,0,0,0,0]," - "Buffer [0,0,32,0,0,0]," - "Buffer [0,0,0,16,0,0]," - "Buffer [0,0,0,0,8,0]," - "Buffer [0,0,0,0,0,4]") }, + { njs_str("var qs = require('querystring');" + "qs.stringify([[,'a','b',,]])"), + njs_str("0=&0=a&0=b&0=") }, - { njs_str(njs_buffer_byte_map("writeUIntBE", "+", 1)), - njs_str("Buffer [128,0,0,0,0,0]," - "Buffer [64,0,0,0,0,0]," - "Buffer [32,0,0,0,0,0]," - "Buffer [16,0,0,0,0,0]," - "Buffer [8,0,0,0,0,0]," - "Buffer [4,0,0,0,0,0]") }, + { njs_str("var qs = require('querystring');" + "qs.escape('abcααααdef')"), + njs_str("abc%CE%B1%CE%B1%CE%B1%CE%B1def") }, - { njs_str(njs_buffer_byte_map("writeIntLE", "-", 2)), - njs_str("Buffer [192,0,0,0,0,0]," - "Buffer [0,224,0,0,0,0]," - "Buffer [0,0,240,0,0,0]," - "Buffer [0,0,0,248,0,0]," - "Buffer [0,0,0,0,252,0]," - "Buffer [0,0,0,0,0,254]") }, + { njs_str("var qs = require('querystring');" + "qs.unescape('abc%CE%B1%CE%B1%CE%B1%CE%B1def')"), + njs_str("abcααααdef") }, +}; - { njs_str(njs_buffer_byte_map("writeIntBE", "-", 2)), - njs_str("Buffer [192,0,0,0,0,0]," - "Buffer [224,0,0,0,0,0]," - "Buffer [240,0,0,0,0,0]," - "Buffer [248,0,0,0,0,0]," - "Buffer [252,0,0,0,0,0]," - "Buffer [254,0,0,0,0,0]") }, - { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleBE()"), - njs_str("8.20788039913184e-304") }, +static njs_unit_test_t njs_buffer_module_test[] = +{ + { njs_str("new Buffer();"), + njs_str("TypeError: Buffer is not a constructor") }, - { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleLE()"), - njs_str("5.447603722011605e-270") }, + { njs_str("var buf = Buffer.alloc();"), + njs_str("TypeError: \"size\" argument must be of type number") }, - { njs_str("Buffer.from([1, 2, 3, 4]).readFloatBE()"), - njs_str("2.387939260590663e-38") }, + { njs_str("var buf = Buffer.alloc('best buffer');"), + njs_str("TypeError: \"size\" argument must be of type number") }, - { njs_str("Buffer.from([1, 2, 3, 4]).readFloatLE()"), - njs_str("1.539989614439558e-36") }, + { njs_str("var buf = Buffer.alloc(-1);"), + njs_str("RangeError: invalid size") }, - { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleBE(1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(4); njs.dump(buf)"), + njs_str("Buffer [0,0,0,0]") }, - { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleLE(1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(4, 88); buf"), + njs_str("XXXX") }, - { njs_str("Buffer.from([1, 2, 3, 4]).readFloatBE(1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(4, 945); njs.dump(buf)"), + njs_str("Buffer [177,177,177,177]") }, - { njs_str("Buffer.from([1, 2, 3, 4]).readFloatLE(1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(4, -1); njs.dump(buf)"), + njs_str("Buffer [255,255,255,255]") }, - { njs_str("var buf = Buffer.allocUnsafe(8);" - "buf.writeDoubleBE(123.456); njs.dump(buf)"), - njs_str("Buffer [64,94,221,47,26,159,190,119]") }, + { njs_str("var buf = Buffer.alloc(4, -1, 'utf-128'); njs.dump(buf)"), + njs_str("Buffer [255,255,255,255]") }, - { njs_str("var buf = Buffer.allocUnsafe(8);" - "buf.writeDoubleLE(123.456); njs.dump(buf)"), - njs_str("Buffer [119,190,159,26,47,221,94,64]") }, + { njs_str("var buf = Buffer.alloc(10, 'α'); buf"), + njs_str("ααααα") }, - { njs_str("var buf = Buffer.allocUnsafe(4);" - "buf.writeFloatBE(123.456); njs.dump(buf)"), - njs_str("Buffer [66,246,233,121]") }, + { njs_str("var buf = Buffer.alloc(4, 'α'); njs.dump(buf)"), + njs_str("Buffer [206,177,206,177]") }, - { njs_str("var buf = Buffer.allocUnsafe(4);" - "buf.writeFloatLE(123.456); njs.dump(buf)"), - njs_str("Buffer [121,233,246,66]") }, + { njs_str("var buf = Buffer.alloc(2, 'ααααα'); njs.dump(buf)"), + njs_str("Buffer [206,177]") }, - { njs_str("var buf = Buffer.allocUnsafe(8).writeDoubleBE(123.456, 1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(1, 'α'); njs.dump(buf)"), + njs_str("Buffer [206]") }, - { njs_str("var buf = Buffer.allocUnsafe(8).writeDoubleLE(123.456, 1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(4, 'ZXZpbA==', 'base64'); buf"), + njs_str("evil") }, - { njs_str("var buf = Buffer.allocUnsafe(4).writeFloatBE(123.456, 1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(8, 'ZXZpbA==', 'base64'); buf"), + njs_str("evilevil") }, - { njs_str("var buf = Buffer.allocUnsafe(4).writeFloatLE(123.456, 1)"), - njs_str("RangeError: index 1 is outside the bound of the buffer") }, + { njs_str("var buf = Buffer.alloc(8, 'evil', 'utf-128'); buf"), + njs_str("TypeError: \"utf-128\" encoding is not supported") }, - { njs_str("var buffer = require('buffer');" - "buffer.Buffer.alloc(5).fill('ABC')"), - njs_str("ABCAB") }, + { njs_str("var foo = new Uint8Array(10).fill(88);" + "var buf = Buffer.alloc(8, foo); buf"), + njs_str("XXXXXXXX") }, - { njs_str("var buffer = require('buffer');" - "typeof buffer.kMaxLength === 'number' "), + { njs_str("[1,2,10,20].every(v => {" + " var src = new Uint16Array(v).fill(0xB1CE);" + " var buf = Buffer.alloc(10, src);" + " return buf.toString() === " njs_evar("'ααααα'", "'�αααα�'") + "})"), njs_str("true") }, - { njs_str("var buffer = require('buffer');" - "typeof buffer.constants.MAX_LENGTH === 'number' "), + { njs_str("var foo = Buffer.alloc(10, 'α');" + "var buf = Buffer.alloc(4, foo); buf"), + njs_str("αα") }, + + { njs_str("var buf = Buffer.allocUnsafe(10).fill('α'); buf"), + njs_str("ααααα") }, + + { njs_str("var buf = Buffer.allocUnsafe(-1)"), + njs_str("RangeError: invalid size") }, + + { njs_str("[" + " ['6576696c', 'hex', 4]," + " ['6576696', 'hex', 3]," + " ['', 'hex', 0]," + " ['', 'base64', 0]," + " ['ZXZpbA==', 'base64', 4]," + " ['ZXZpbA', 'base64url', 4]," + " ['ααααα', undefined, 10]," + "].every(args => Buffer.byteLength(args[0], args[1]) == args[2])"), njs_str("true") }, - { njs_str("var buffer = require('buffer');" - "typeof buffer.constants.MAX_STRING_LENGTH === 'number' "), + { njs_str("Buffer.from([])"), + njs_str("") }, + + { njs_str("Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72])"), + njs_str("buffer") }, + + { njs_str(njs_declare_sparse_array("arr", 6) + "[0x62, 0x75, 0x66, 0x66, 0x65, 0x72].map((v, i) => {arr[i] = v;});" + "Buffer.from(arr)"), + njs_str("buffer") }, + + { njs_str("Buffer.from({length:3, 0:0x62, 1:0x75, 2:0x66})"), + njs_str("buf") }, + + { njs_str("njs.dump(Buffer.from([-1,1,255,22323,-Infinity,Infinity,NaN]))"), + njs_str("Buffer [255,1,255,51,0,0,0]") }, + + { njs_str("var buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); njs.dump(buf)"), + njs_str("Buffer [98,117,102,102,101,114]") }, + + { njs_str("var buf = Buffer.from([1,2,3]); njs.dump(Buffer.from(buf.toJSON()))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("[" + " {type: 'B'}," + " {type: undefined}," + " {type:'Buffer'}," + " {type:'Buffer', data:null}," + " {type:'Buffer', data:{}}," + "].every(v=>{ try { Buffer.from(v)} catch(e) {return e.name == 'TypeError'}})"), njs_str("true") }, - /* let */ + { njs_str("var foo = new Uint16Array(2);" + "foo[0] = 5000; foo[1] = 4000;" + "var buf = Buffer.from(foo.buffer);" + "foo[1] = 6000;" + "njs.dump(buf)"), + njs_str("Buffer [" njs_evar("136,19,112,23", "19,136,23,112") "]") }, - { njs_str("let x"), - njs_str("undefined") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 1); njs.dump(buf)"), + njs_str("Buffer [" njs_evar("3,182,3", "182,3,182") "]") }, - { njs_str("let x = 123; x"), - njs_str("123") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, -1); njs.dump(buf)"), + njs_str("RangeError: invalid index") }, - { njs_str("let x = [123]; x"), - njs_str("123") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 5); njs.dump(buf)"), + njs_str("RangeError: \"offset\" is outside of buffer bounds") }, - { njs_str("let x = () => x; x()"), - njs_str("[object Function]") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 2, 1); njs.dump(buf)"), + njs_str("Buffer [" njs_evar("182", "3") "]") }, - { njs_str("let x = (() => x)()"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 2, -1); njs.dump(buf)"), + njs_str("Buffer []") }, - { njs_str("x; let x"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 2, 3); njs.dump(buf)"), + njs_str("RangeError: \"length\" is outside of buffer bounds") }, - { njs_str("x; let x = 123"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 2, 0); njs.dump(buf)"), + njs_str("Buffer []") }, - { njs_str("let x = x + 123"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, 2, 2); njs.dump(buf)"), + njs_str("Buffer [" njs_evar("182,3", "3,182") "]") }, - { njs_str("let x = (x, 1)"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var foo = new Uint16Array(2).fill(950);" + "var buf = Buffer.from(foo.buffer, '2', '2'); njs.dump(buf)"), + njs_str("Buffer [" njs_evar("182,3", "3,182") "]") }, - { njs_str("let x = x"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var foo = new Uint32Array(1).fill(0xF1F2F3F4);" + "var buf = Buffer.from(foo); njs.dump(buf)"), + njs_str("Buffer [244]") }, + + { njs_str("var foo = new Uint32Array(2).fill(0xF1F2F3F4);" + "var buf = Buffer.from(foo); njs.dump(buf)"), + njs_str("Buffer [244,244]") }, + + { njs_str("var foo = new Uint8Array(5);" + "foo[0] = 1; foo[1] = 2; foo[2] = 3; foo[3] = 4; foo[4] = 5;" + "foo = foo.subarray(1, 3);" + "var buf = Buffer.from(foo); njs.dump(buf)"), + njs_str("Buffer [2,3]") }, + + { njs_str("var buf = Buffer.from(''); njs.dump(buf)"), + njs_str("Buffer []") }, + + { njs_str("var buf = Buffer.from('α'); njs.dump(buf)"), + njs_str("Buffer [206,177]") }, + + { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => arr;" + "njs.dump(Buffer.from(arr))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => obj;" + "Buffer.from(obj)"), + njs_str("TypeError: first argument object is not a string or Buffer-like object") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => undefined;" + "njs.dump(Buffer.from(obj))"), + njs_str("TypeError: first argument undefined is not a string or Buffer-like object") }, + + { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => null;" + "njs.dump(Buffer.from(arr))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => new Array(1,2,3);" + "njs.dump(Buffer.from(obj))"), + njs_str("Buffer [1,2,3]") }, - { njs_str("let x; var x"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("njs.dump(Buffer.from(new String('test')))"), + njs_str("Buffer [116,101,115,116]") }, - { njs_str("var x; let x"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("[" + " ['6576696c', 'hex']," + " ['ZXZpbA==', 'base64']," + " ['ZXZpbA==#', 'base64']," + " ['ZXZpbA', 'base64url']," + " ['ZXZpbA##', 'base64url']," + "].every(args => Buffer.from(args[0], args[1]) == 'evil')"), + njs_str("true") }, - { njs_str("let x; function x() {}"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("var buf = Buffer.from(String.bytesFrom([0xF3])); buf"), + njs_str("�") }, - { njs_str("function x() {} let x"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("Buffer.from('', 'utf-128')"), + njs_str("TypeError: \"utf-128\" encoding is not supported") }, - { njs_str("function x() {let x; var x}"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("[Buffer.from('α'), new Uint8Array(10), {}, 1]" + ".map(v=>Buffer.isBuffer(v))"), + njs_str("true,false,false,false") }, - { njs_str("function x() {var x; let x}"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("['utf8', 'utf-8', 'hex', 'base64', 'base64url', 'utf-88', '1hex']" + ".map(v=>Buffer.isEncoding(v))"), + njs_str("true,true,true,true,true,false,false") }, - { njs_str("var x = function f() {let f}"), - njs_str("undefined") }, + { njs_str("[" + " ['ABC', 'ABCD', -1]," + " ['ABCD', 'ABC', 1]," + " ['ABC', 'ACB', -1]," + " ['ACB', 'ABC', 1]," + " ['ABC', 'ABC', 0]," + " ['', 'ABC', -1]," + " ['', '', 0]," + "].every(args => {" + " if (Buffer.compare(Buffer.from(args[0]), Buffer.from(args[1])) != args[2]) {" + " throw new TypeError(" + " `Buffer.compare(Buffer.from(${args[0]}), Buffer.from(${args[1]})) != ${args[2]}`);" + " }" + " return true;" + "})"), + njs_str("true") }, - { njs_str("let a; let x = 1;" - "{let x = 2; a = x}" - "[x, a]"), - njs_str("1,2") }, + { njs_str("[" + " ['ABC', 'ABCD', -1]," + " ['ABCD', 'ABC', 1]," + " ['ABC', 'ACB', -1]," + " ['ACB', 'ABC', 1]," + " ['ABC', 'ABC', 0]," + " ['', 'ABC', -1]," + " ['', '', 0]," + "].every(args => {" + " if (Buffer.from(args[0]).compare(Buffer.from(args[1])) != args[2]) {" + " throw new TypeError(" + " `Buffer.from(${args[0]}).compare(Buffer.from(${args[1]})) != ${args[2]}`);" + " }" + " return true;" + "})"), + njs_str("true") }, - { njs_str("let a; let x = 1;" - "if (true) {let x = 2; a = x}" - "[x, a]"), - njs_str("1,2") }, + { njs_str("var buf = Buffer.from('ABCD');" + "[" + " [0,3,0,2, -1]," + " [0,2,0,3, 1]," + " [3,4,3,4, 0]," + " [undefined, undefined, undefined, undefined, 0]," + " [-1, undefined, undefined, undefined, 'invalid index']," + " [0, -1, undefined, undefined, 'invalid index']," + " [0, 0, -1, undefined, 'invalid index']," + " [0, 0, 0, -1, 'invalid index']," + "]" + ".every(as => {" + " try {" + " if (buf.compare(buf, as[0], as[1], as[2], as[3]) != as[4]) {" + " throw new TypeError(" + " `buf.compare(${as[0]}, ${as[1]}, ${as[2]}, ${as[3]}) != ${as[4]}`);" + " }" + " } catch (e) { return e.message == as[4]}" + " return true;" + "})"), + njs_str("true") }, - { njs_str("var a = 5, b = 10, arr = [];" - "{let a = 4; var b = 1; arr.push(a); arr.push(b)}" - "arr.push(a); arr.push(b); arr"), - njs_str("4,1,5,1") }, + { njs_str("var buf1 = Buffer.from('ABCD');" + "var buf2 = Buffer.from('ABCD');" + "buf1.compare(buf2, 5)"), + njs_str("RangeError: \"targetStart\" is out of range: 5") }, - { njs_str("function func() {return x}" - "let x = 123;" - "func()"), - njs_str("123") }, + { njs_str("var buf1 = Buffer.from('ABCD');" + "var buf2 = Buffer.from('ABCD');" + "buf1.compare(buf2, 0, 3, 5)"), + njs_str("RangeError: \"sourceStart\" is out of range: 5") }, - { njs_str("function func() {return x}" - "func();" - "let x = 123"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var arr = new Uint8Array(4);" + "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" + "arr = arr.subarray(1, 4);" + "var buf = Buffer.from('ABCD');" + "buf.compare(arr, 0, 3, 1, 4)"), + njs_str("0") }, - { njs_str("function func() {return () => x}" - "let x = 123;" - "func()()"), - njs_str("123") }, + { njs_str("['123', 'abc', '124', '', 'AB', 'ABCD']" + ".map(v=>Buffer.from(v)).sort(Buffer.compare).map(v=>v.toString())"), + njs_str(",123,124,AB,ABCD,abc") }, - { njs_str("function func() {x = x + 1; let x}"), - njs_str("undefined") }, + { njs_str("Buffer.compare(Buffer.alloc(1), 'text')"), + njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") }, - { njs_str("function func() {return () => x}" - "func()();" - "let x = 123;"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("Buffer.compare('text', Buffer.from('ACB'))"), + njs_str("TypeError: \"source\" argument must be an instance of Buffer or Uint8Array") }, - { njs_str("var arr = [];" - "" - "for (var i = 0; i < 10; i++) {" - " let x = i;" - "" - " arr.push( (n) => {x += n; return x} );" - "}" - "" - "[" - " arr[0](2), arr[1](1), arr[2](4), arr[3](7), arr[4](0)," - " arr[5](1), arr[6](2), arr[7](5), arr[8](8), arr[9](10)" - "]"), - njs_str("2,2,6,10,4,6,8,12,16,19") }, + { njs_str("Buffer.concat()"), + njs_str("TypeError: \"list\" argument must be an instance of Array") }, - { njs_str("var arr = [];" - "" - "for (let i = 0; i < 10; i++) {" - " arr.push( (n) => {i += n; return i} );" - "}" - "" - "[" - " arr[0](2), arr[1](1), arr[2](4), arr[3](7), arr[4](0)," - " arr[5](1), arr[6](2), arr[7](5), arr[8](8), arr[9](10)" - "]"), - njs_str("2,2,6,10,4,6,8,12,16,19") }, + { njs_str("Buffer.concat([])"), + njs_str("") }, - { njs_str("for (let i = 0; i < 1; i++) {" - " let i = i + 2;" - "}"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("Buffer.concat([new Uint16Array(10)])"), + njs_str("TypeError: \"list[0]\" argument must be an instance of Buffer or Uint8Array") }, - { njs_str("let arr = [], res = [];" - "for (let i = 0, f = function() { return i }; i < 5; i++) {" - " arr.push(f);" - "}" - "for (let i = 0; i < 5; i++) {" - " res.push(arr[i]());" - "} res"), - njs_str("0,0,0,0,0") }, + { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)]).fill('abc')"), + njs_str("abc") }, - { njs_str("let arr = [], res = [];" - "for (let i = 0; arr.push(() => i), i < 10; i++) {}" - "for (let k = 0; k < 10; k++) {res.push(arr[k]())}" - "res"), - njs_str("0,1,2,3,4,5,6,7,8,9") }, + { njs_str("Buffer.concat([Buffer.from('AB'), Buffer.from('CD')])"), + njs_str("ABCD") }, - { njs_str("let res = [];" - "for (let n in [1,2,3]) {res.push(n)}" - "res"), - njs_str("0,1,2") }, + { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)], 2).fill('abc')"), + njs_str("ab") }, - { njs_str("let arr = [], res = [];" - "" - "for (let n in [1,2,3]) {" - " arr.push(() => n);" - "}" - "" - "for (let n in arr) {" - " res.push(arr[n]());" - "}" - "res"), - njs_str("0,1,2") }, + { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)], 6).fill('abc')"), + njs_str("abcabc") }, - { njs_str("let arr = [];" - "" - "for (let n in [1,2,3]) {" - " let n = 1;" - " arr.push(n);" - "}" - "arr"), - njs_str("1,1,1") }, + { njs_str(njs_declare_sparse_array("list", 2) + "list[0] = new Uint8Array(2); list[1] = new Uint8Array(3);" + "Buffer.concat(list).fill('ab');"), + njs_str("ababa") }, - { njs_str("for (let n in [1,2,3]) {" - " let n = n + 1;" - "}"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("Buffer.concat([], '123')"), + njs_str("TypeError: \"length\" argument must be of type number") }, - { njs_str("for (let n in [1,2,3]) {}" - "n"), - njs_str("ReferenceError: \"n\" is not defined") }, + { njs_str("Buffer.concat([], -1)"), + njs_str("RangeError: \"length\" is out of range") }, - { njs_str("for (let n in [1,n,3]) {}"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.from('α'); buf[1]"), + njs_str("177") }, - { njs_str("(function() {" - "function f() {return x + 1}" - "function abc() {f()};" - "abc();" - "let x;" - "}())"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.from('α'); buf[1] = 1; njs.dump(buf)"), + njs_str("Buffer [206,1]") }, - { njs_str("function func() {var x = 1; {let x = x + 1} } func()"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var arrBuf = new ArrayBuffer(16);" + "var buf = Buffer.from(arrBuf); buf.buffer === arrBuf"), + njs_str("true") }, - { njs_str("if (false) let x = 1"), - njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, + { njs_str("[" + " [[0], 4, '65,66,67,68,0,0,0,0,0,0']," + " [[5], 4, '0,0,0,0,0,65,66,67,68,0']," + " [[8], 2, '0,0,0,0,0,0,0,0,65,66']," + " [[8,2,4], 2, '0,0,0,0,0,0,0,0,67,68']," + " [[10], 0, '0,0,0,0,0,0,0,0,0,0']," + "]" + ".every(args => {" + " var buf1 = Buffer.from('ABCD');" + " var buf2 = Buffer.alloc(10, 0);" + " var as = args[0];" + " var length = buf1.copy(buf2, as[0], as[1], as[2]);" + "" + " if (length != args[1]) {" + " throw new TypeError(`buf1.copy(buf2, ${as[0]}, ${as[1]}, ${as[2]}): ${length} != ${args[1]}`)" + " }" + "" + " if (njs.dump(buf2) != `Buffer [${args[2]}]`) {" + " throw new TypeError(" + " `buf1.copy(buf2, ${as[0]}, ${as[1]}, ${as[2]}): ${njs.dump(buf2)} != Buffer [${args[2]}]`);" + " }" + " return true;" + "})"), + njs_str("true") }, - { njs_str("while (false) let x = 1"), - njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, + { njs_str("[" + " [[0], 'ABCDEF']," + " [[0,2], 'CDEFEF']," + " [[0,2,6], 'CDEFEF']," + " [[1,2,4], 'ACDDEF']," + " [[1,2,3], 'ACCDEF']" + "]" + ".every(args => {" + " var buf = Buffer.from('ABCDEF');" + " var as = args[0];" + " buf.copy(buf, as[0], as[1], as[2]);" + "" + " if (buf.toString() != args[1]) {" + " throw new TypeError(" + " `buf.copy(buf, ${as[0]}, ${as[1]}, ${as[2]}): buf.toString() != ${args[1]}`);" + " }" + " return true;" + "})"), + njs_str("true") }, - { njs_str("for (;;) let x = 1"), - njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, + { njs_str("var buf1 = Buffer.from('ABCD');" + "var buf2 = Buffer.alloc(10, 0);" + "buf1.copy(buf2, -1)"), + njs_str("RangeError: invalid index") }, - { njs_str("try {} catch (e) {let e}"), - njs_str("SyntaxError: \"e\" has already been declared in 1") }, + { njs_str("var buf1 = Buffer.from('ABCD');" + "var buf2 = Buffer.alloc(10, 0);" + "buf1.copy(buf2, 0, -1)"), + njs_str("RangeError: invalid index") }, - { njs_str("let arr = [], x = 2;" - "switch(true) {default: let x = 1; arr.push(x)}" - "arr.push(x); arr"), - njs_str("1,2") }, + { njs_str("var buf1 = Buffer.from('ABCD');" + "var buf2 = Buffer.alloc(10, 0);" + "buf1.copy(buf2, 0, 5)"), + njs_str("RangeError: \"sourceStart\" is out of range: 5") }, - { njs_str("switch(true) {case false: let x = 1; default: x = 2}"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var arr = new Uint8Array(4);" + "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" + "arr = arr.subarray(1, 4);" + "var buf1 = Buffer.from(arr);" + "var buf2 = Buffer.alloc(10, 0);" + "var length = buf1.copy(buf2, 1, 1, 2); [length, njs.dump(buf2)]"), + njs_str("1,Buffer [0,67,0,0,0,0,0,0,0,0]") }, - { njs_str("let res;" - "switch(true) {case true: let x = 1; default: x = 2; res = x} res"), - njs_str("2") }, + { njs_str("var arr = new Uint8Array(4);" + "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" + "arr = arr.subarray(1, 4);" + "var buf1 = Buffer.from(arr);" + "var buf2 = Buffer.alloc(10, 0);" + "var length = buf1.copy(buf2, 1, 1, 2); [length, njs.dump(buf2)]"), + njs_str("1,Buffer [0,67,0,0,0,0,0,0,0,0]") }, - { njs_str("let null"), - njs_str("SyntaxError: Unexpected token \"null\" in 1") }, + { njs_str("[" + " ['ABC', 'ABCD', false]," + " ['ABCD', 'ABC', false]," + " ['ABC', 'ACB', false]," + " ['ACB', 'ABC', false]," + " ['ABC', 'ABC', true]," + " ['', 'ABC', false]," + " ['', '', true]," + "].every(args => {" + " if (Buffer.from(args[0]).equals(Buffer.from(args[1])) != args[2]) {" + " throw new TypeError(" + " `Buffer.from(${args[0]}).compare(Buffer.from(${args[1]})) != ${args[2]}`);" + " }" + " return true;" + "})"), + njs_str("true") }, - { njs_str("let continue"), - njs_str("SyntaxError: Unexpected token \"continue\" in 1") }, + { njs_str("Buffer.from([1,2]).equals(new ArrayBuffer(1))"), + njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") }, - { njs_str("let undefined"), - njs_str("SyntaxError: \"undefined\" has already been declared in 1") }, + { njs_str("Buffer.from([1,2]).equals(1)"), + njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") }, - { njs_str("let a = 1; globalThis.a"), - njs_str("undefined") }, + { njs_str("var buf = Buffer.alloc(4);" + "buf.fill('ZXZpbA==', 'base64')"), + njs_str("evil") }, - { njs_str("if (false) {x = 2} else {x = 1} let x;"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.alloc(4);" + "buf.fill('6576696c', 'hex')"), + njs_str("evil") }, - { njs_str("let let"), - njs_str("SyntaxError: Unexpected token \"let\" in 1") }, + { njs_str("var buf = Buffer.alloc(4);" + "buf.fill('ZXZpbA==', '')"), + njs_str("TypeError: \"\" encoding is not supported") }, - { njs_str("let null"), - njs_str("SyntaxError: Unexpected token \"null\" in 1") }, + { njs_str("var buf = Buffer.alloc(8);" + "buf.fill('6576696c', 'hex')"), + njs_str("evilevil") }, - { njs_str("function let() {}"), - njs_str("SyntaxError: Unexpected token \"let\" in 1") }, + { njs_str("var buf = Buffer.alloc(10);" + "buf.fill('evil')"), + njs_str("evilevilev") }, - { njs_str("function static() {}"), - njs_str("SyntaxError: Unexpected token \"static\" in 1") }, + { njs_str("var buf = Buffer.allocUnsafe(5);" + "buf[3] = 1;" + "buf.fill(''); njs.dump(buf)"), + njs_str("Buffer [0,0,0,0,0]") }, - /* const */ + { njs_str("var arr = new Uint8Array(4);" + "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;" + "arr = arr.subarray(1, 4);" + "var buf = Buffer.allocUnsafe(6);" + "buf.fill(arr); njs.dump(buf)"), + njs_str("Buffer [66,67,68,66,67,68]") }, - { njs_str("const x"), - njs_str("SyntaxError: missing initializer in const declaration") }, + { njs_str("var buf = Buffer.alloc(6, 'ABCDEF');" + "buf.fill(buf, 2, 6)"), + njs_str("ABABCD") }, - { njs_str("const x = 1; x"), - njs_str("1") }, + { njs_str("Buffer.alloc(6).fill(0x41)"), + njs_str("AAAAAA") }, - { njs_str("const x = 1; x = 1"), - njs_str("TypeError: assignment to constant variable") }, + { njs_str("Buffer.alloc(6).fill({valueOf(){return 0x42}})"), + njs_str("BBBBBB") }, - { njs_str("function abc() {const x}"), - njs_str("SyntaxError: missing initializer in const declaration") }, + { njs_str("njs.dump(Buffer.alloc(3).fill(-1))"), + njs_str("Buffer [255,255,255]") }, - { njs_str("const x = [123]; x"), - njs_str("123") }, + { njs_str("[NaN, Infinity, -Infinity, undefined, null, {}]" + ".every(v => njs.dump(Buffer.alloc(3).fill(v)) == 'Buffer [0,0,0]')"), + njs_str("true") }, - { njs_str("const x = () => x; x()"), - njs_str("[object Function]") }, + { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 4,3))"), + njs_str("Buffer [0,0,0,0,0,0]") }, - { njs_str("const x = (() => x)()"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 3,3))"), + njs_str("Buffer [0,0,0,0,0,0]") }, - { njs_str("x; const x = 123"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 2,3))"), + njs_str("Oops") }, - { njs_str("const x = x + 123"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("njs.dump(Buffer.alloc(5).fill('α'))"), + njs_str("Buffer [206,177,206,177,206]") }, - { njs_str("const x; var x"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("Buffer.alloc(4).fill('ABCD', -1)"), + njs_str("RangeError: invalid index") }, - { njs_str("const x; let x"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("Buffer.alloc(4).fill('ABCD', 5)"), + njs_str("RangeError: \"offset\" is out of range") }, - { njs_str("let x; const x"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("Buffer.alloc(4).fill('ABCD', 0, -1)"), + njs_str("RangeError: invalid index") }, - { njs_str("const x = 1; function x() {}"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("Buffer.alloc(4).fill('ABCD', 0, 5)"), + njs_str("RangeError: \"end\" is out of range") }, - { njs_str("function x() {} const x = 1"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("Buffer.alloc(513).fill('A'.repeat(512)).length"), + njs_str("513") }, - { njs_str("function x() {const x; var x}"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("njs.dump(Buffer.alloc(4).fill((new Uint8Array(5)).fill(1)))"), + njs_str("Buffer [1,1,1,1]") }, - { njs_str("function x() {var x; const x}"), - njs_str("SyntaxError: \"x\" has already been declared in 1") }, + { njs_str("var src = new Uint8Array(10).fill(255);" + "var u8 = new Uint8Array(src.buffer, 1, 8);" + "u8.set([1,2,3,4,5,6,7,8]);" + "njs.dump(Buffer.alloc(9).fill(u8))"), + njs_str("Buffer [1,2,3,4,5,6,7,8,1]") }, - { njs_str("const x = function f() {const f = 1}"), - njs_str("undefined") }, + { njs_str("Buffer.alloc(513).fill((new Uint8Array(512)).fill(1)).length"), + njs_str("513") }, - { njs_str("let res; const x = 1;" - "{const x = 2; res = x}" - "[x, res]"), - njs_str("1,2") }, + { njs_str("Buffer.alloc(4).fill('ABCD', undefined, undefined, 'utf-128')"), + njs_str("TypeError: \"utf-128\" encoding is not supported") }, - { njs_str("let res; const x = 1;" - "if (true) {const x = 2; res = x}" - "[x, res]"), - njs_str("1,2") }, + { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 3);" + "buf1.fill('B', 1, 2); njs.dump(buf1)"), + njs_str("Buffer [66,66]") }, - { njs_str("function func() {return x}" - "const x = 123;" - "func()"), - njs_str("123") }, + { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 3);" + "buf1.fill(0x42, 1, 2); njs.dump(buf1)"), + njs_str("Buffer [66,66]") }, - { njs_str("function func() {return x}" - "func();" - "const x = 123"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 2);" + "var buf2 = Buffer.from('ABCD').subarray(1, 3);" + "buf2.fill(buf1, 1, 2); njs.dump(buf2)"), + njs_str("Buffer [66,66]") }, - { njs_str("function func() {return () => x}" - "const x = 123;" - "func()()"), - njs_str("123") }, + { njs_str("var buf = Buffer.from('ABCD');" + "['BC', 'CB', 'ABCD', 'ABCDE', ''].map(v=>buf.indexOf(v))"), + njs_str("1,-1,0,-1,0") }, - { njs_str("function func() {return () => x++}" - "const x = 123;" - "func()()"), - njs_str("TypeError: assignment to constant variable") }, + { njs_str("var buf = Buffer.from('ABCD');" + "[0,5,-2,-1].map(v=>buf.indexOf('C', v))"), + njs_str("2,-1,2,-1") }, - { njs_str("for (const i = 0; i < 1; i++) {}"), - njs_str("TypeError: assignment to constant variable") }, + { njs_str("var buf = Buffer.from('evil');" + "buf.indexOf('ZXZpbA==', undefined, 'base64')"), + njs_str("0") }, - { njs_str("let res = [];" - "for (const n in [1,2,3]) {res.push(n)}" - "res"), - njs_str("0,1,2") }, + { njs_str("var buf = Buffer.from('evil');" + "buf.indexOf('6576696c', undefined, 'hex')"), + njs_str("0") }, - { njs_str("let arr = [], res = [];" - "" - "for (const n in [1,2,3]) {" - " arr.push(() => n);" - "}" - "" - "for (let n in arr) {" - " res.push(arr[n]());" - "}" - "res"), - njs_str("0,1,2") }, + { njs_str("var buf = Buffer.from('ABCD');" + "buf.indexOf('C', undefined, 'utf-128')"), + njs_str("TypeError: \"utf-128\" encoding is not supported") }, - { njs_str("let arr = [];" - "" - "for (const n in [1,2,3]) {" - " let n = 1;" - " arr.push(n);" - "}" - "arr"), - njs_str("1,1,1") }, + { njs_str("var buf = Buffer.from('ABCDABC');" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.indexOf(Buffer.from(v)))"), + njs_str("1,-1,0,-1,0,2,-1") }, - { njs_str("for (const n in [1,2,3]) {" - " let n = n + 1;" - "}"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.from('ABCDABC');" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.includes(Buffer.from(v)))"), + njs_str("true,false,true,false,true,true,false") }, - { njs_str("for (const n in [1,2,3]) {}" - "n"), - njs_str("ReferenceError: \"n\" is not defined") }, + { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.indexOf(Buffer.from(v)))"), + njs_str("1,-1,0,-1,0,2,-1") }, - { njs_str("for (const n in [1,n,3]) {}"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.from('ABCD');" + "buf.indexOf(0x43)"), + njs_str("2") }, - { njs_str("(function() {" - "function f() {return x + 1}" - "function abc() {f()};" - "abc();" - "const x = 1;" - "}())"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.from('ABCD');" + "buf.indexOf(0x43, -2)"), + njs_str("2") }, - { njs_str("if (false) const x = 1"), - njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, + { njs_str("var buf = Buffer.from('ABCD');" + "buf.indexOf(0x43, -1)"), + njs_str("-1") }, - { njs_str("while (false) const x = 1"), - njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, + { njs_str("var buf1 = Buffer.from('ABCD');" + "var buf2 = Buffer.from('XXCX').subarray(2, 3);" + "buf1.indexOf(buf2)"), + njs_str("2") }, - { njs_str("for (;;) const x = 1"), - njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, + { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 4);" + "buf1.indexOf(0x43)"), + njs_str("1") }, - { njs_str("try {} catch (e) {const e = 1}"), - njs_str("SyntaxError: \"e\" has already been declared in 1") }, + { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 4);" + "buf1.indexOf('C')"), + njs_str("1") }, - { njs_str("let arr = []; const x = 2;" - "switch(true) {default: const x = 1; arr.push(x)}" - "arr.push(x); arr"), - njs_str("1,2") }, + { njs_str("var buf = Buffer.from('ABCDABC');" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(v))"), + njs_str("5,-1,0,-1,7,6,-1") }, - { njs_str("let res;" - "switch(true) {case true: const x = 1; default: x = 2; res = x} res"), - njs_str("TypeError: assignment to constant variable") }, + { njs_str("var buf = Buffer.from('ABCDABC');" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(Buffer.from(v)))"), + njs_str("5,-1,0,-1,7,6,-1") }, - { njs_str("const null"), - njs_str("SyntaxError: Unexpected token \"null\" in 1") }, + { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(v))"), + njs_str("5,-1,0,-1,7,6,-1") }, - { njs_str("const continue"), - njs_str("SyntaxError: Unexpected token \"continue\" in 1") }, + { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);" + "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(Buffer.from(v)))"), + njs_str("5,-1,0,-1,7,6,-1") }, - { njs_str("const undefined"), - njs_str("SyntaxError: \"undefined\" has already been declared in 1") }, + { njs_str("var buf = Buffer.from('CABCD');" + "[2,-2,1,-10,10,-5,-4,0].map(v=>buf.lastIndexOf('C', v))"), + njs_str("0,3,0,-1,3,0,0,0") }, - { njs_str("const a = 1; globalThis.a"), - njs_str("undefined") }, + { njs_str("var buf = Buffer.from('CABCD');" + "[2,-2,1,-10,10,-5,-4,0].map(v=>buf.lastIndexOf(Buffer.from('CZ').subarray(0,1), v))"), + njs_str("0,3,0,-1,3,0,0,0") }, - { njs_str("if (false) {x = 2} else {x = 1} const x = 0"), - njs_str("ReferenceError: cannot access variable before initialization") }, + { njs_str("var buf = Buffer.from('CABCD');" + "buf.lastIndexOf(0x43)"), + njs_str("3") }, - { njs_str("const const"), - njs_str("SyntaxError: Unexpected token \"const\" in 1") }, + { njs_str("var buf = Buffer.from('CABCD');" + "[2,1,0,4,5,-1,-5].map(v=>buf.lastIndexOf(0x43, v))"), + njs_str("0,0,0,3,3,3,0") }, - /* Async/Await */ + { njs_str("var buf1 = Buffer.from('ACBCD').subarray(1, 4);" + "var buf2 = Buffer.from('C');" + "buf1.lastIndexOf(buf2)"), + njs_str("2") }, - { njs_str("async function f() {}; f.prototype"), - njs_str("undefined") }, + { njs_str("var buf1 = Buffer.from('XXCXX').subarray(2,3);" + "buf1.lastIndexOf(Buffer.from('X'))"), + njs_str("-1") }, - { njs_str("async function f() {await 1}"), - njs_str("undefined") }, + { njs_str("var buf = Buffer.from('ACBCD').subarray(1, 4);" + "buf.lastIndexOf(0x43)"), + njs_str("2") }, - { njs_str("function f() {await 1}"), - njs_str("SyntaxError: await is only valid in async functions in 1") }, + { njs_str("var buf = Buffer.from('ACBCD').subarray(1, 4);" + "buf.lastIndexOf('C')"), + njs_str("2") }, - { njs_str("async function f() {function a() {await 1}}"), - njs_str("SyntaxError: await is only valid in async functions in 1") }, + { njs_str("['swap16', 'swap32', 'swap64'].every(method => {" + " var buf = Buffer.from([]);" + " buf[method]();" + " return njs.dump(buf) === 'Buffer []';" + "})"), + njs_str("true") }, - { njs_str("async function f() {() => {await 1}}"), - njs_str("SyntaxError: await is only valid in async functions in 1") }, + { njs_str("['swap16', 'swap32', 'swap64'].every(method => {" + " var buf = Buffer.from([1,2,3]);" + " try { buf[method]() } " + " catch(e) {return e.message === `Buffer size must be a multiple of ${method.substr(4)}-bits`};" + "})"), + njs_str("true") }, - { njs_str("function f() {async () => {await 1}}"), - njs_str("undefined") }, + { njs_str("['swap16', 'swap32', 'swap64'].map(method => {" + " var buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);" + " buf[method]();" + " return njs.dump(buf);" + "})"), + njs_str("Buffer [2,1,4,3,6,5,8,7]," + "Buffer [4,3,2,1,8,7,6,5]," + "Buffer [8,7,6,5,4,3,2,1]") }, - { njs_str("let f = async () => {await 1}"), - njs_str("undefined") }, + { njs_str("['swap16', 'swap32', 'swap64'].map(method => {" + " var u8 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8]);" + " var buf = Buffer.from(u8.buffer, 1);" + " buf[method]();" + " return njs.dump(buf);" + "})"), + njs_str("Buffer [2,1,4,3,6,5,8,7]," + "Buffer [4,3,2,1,8,7,6,5]," + "Buffer [8,7,6,5,4,3,2,1]") }, - { njs_str("let f = () => {await 1}"), - njs_str("SyntaxError: await is only valid in async functions in 1") }, + { njs_str("njs.dump(Buffer.from('αααα').toJSON())"), + njs_str("{type:'Buffer',data:[206,177,206,177,206,177,206,177]}") }, - { njs_str("(async function() {await 1})"), - njs_str("[object AsyncFunction]") }, + { njs_str("njs.dump(Buffer.from('').toJSON())"), + njs_str("{type:'Buffer',data:[]}") }, - { njs_str("(function() {await 1})"), - njs_str("SyntaxError: await is only valid in async functions in 1") }, + { njs_str("[" + " [['base64'], 'ZXZpbA==']," + " [['base64url'], 'ZXZpbA']," + " [['hex'], '6576696c']," + " [[undefined,1,3], 'vi']," + " [[undefined,5], '']," + " [[undefined,undefined,5], 'evil']," + " [[undefined,undefined,undefined], 'evil']," + "].every(args => {" + " var buf = Buffer.from('evil');" + " var as = args[0];" + " if (buf.toString(as[0], as[1], as[2]) != args[1]) {" + " throw new TypeError(" + " `buf.toString(${as[0]}, ${as[1]}, ${as[2]}) != ${args[1]}`);" + " }" + " return true;" + "})"), + njs_str("true") }, - { njs_str("let ctor = Object.getPrototypeOf(async function(){}).constructor;" - "ctor"), - njs_str("[object Function]") }, + { njs_str("Buffer.from('evil').toString('utf-128')"), + njs_str("TypeError: \"utf-128\" encoding is not supported") }, - { njs_str("let ctor = Object.getPrototypeOf(async function(){}).constructor;" - "ctor()"), - njs_str("[object AsyncFunction]") }, + { njs_str("var buf = Buffer.allocUnsafe(4);" + "var len = buf.write('ZXZpbA==', 'base64'); [len, buf]"), + njs_str("4,evil") }, - { njs_str("let ctor = Object.getPrototypeOf(async function(){}).constructor;" - "new ctor();"), - njs_str("[object AsyncFunction]") }, + { njs_str("var buf = Buffer.allocUnsafe(4);" + "var len = buf.write('ZXZpbA==', undefined, 'base64'); [len, buf]"), + njs_str("4,evil") }, - { njs_str("let f = new Function('x', 'await 1; return x'); f(1)"), - njs_str("SyntaxError: await is only valid in async functions in runtime:1") }, + { njs_str("var buf = Buffer.allocUnsafe(4);" + "var len = buf.write('ZXZpbA==', undefined, undefined, 'base64'); [len, buf]"), + njs_str("4,evil") }, - { njs_str("new AsyncFunction()"), - njs_str("ReferenceError: \"AsyncFunction\" is not defined") }, + { njs_str("Buffer.allocUnsafe(4).write()"), + njs_str("TypeError: first argument must be a string") }, - { njs_str("(async function() {console.log(await 111)})"), - njs_str("SyntaxError: await in arguments not supported in 1") }, + { njs_str("Buffer.allocUnsafe(4).write({a: 1})"), + njs_str("TypeError: first argument must be a string") }, - { njs_str("(async function() {console.log('Number: ' + await 111)})"), - njs_str("SyntaxError: await in arguments not supported in 1") }, + { njs_str("Buffer.alloc(4).write('evil', 4, 1);"), + njs_str("RangeError: \"offset\" is out of range") }, - { njs_str("function f(a) {}" - "(async function() {f(await 111)})"), - njs_str("SyntaxError: await in arguments not supported in 1") }, + { njs_str("Buffer.alloc(4).write('evil', -1);"), + njs_str("RangeError: invalid index") }, - { njs_str("async () => [await x(1)(),]; async () => [await x(1)()]"), - njs_str("[object AsyncFunction]") }, + { njs_str("var buf = Buffer.alloc(4);" + "var len = buf.write('evil', 3, 1); [len, njs.dump(buf)]"), + njs_str("1,Buffer [0,0,0,101]") }, - { njs_str("function f(a, b, c) {}" - "(async function() {f(1, 'a', await 111)})"), - njs_str("SyntaxError: await in arguments not supported in 1") }, + { njs_str("var buf = Buffer.alloc(4);" + "var len = buf.write('evil', 0, 5); [len, buf]"), + njs_str("4,evil") }, - { njs_str("function f(a) {}" - "(async function() {f('Number: ' + await 111)})"), - njs_str("SyntaxError: await in arguments not supported in 1") }, + { njs_str("Buffer.alloc(4).write('evil', undefined, -1);"), + njs_str("RangeError: invalid index") }, - { njs_str("async function af() {await encrypt({},}"), - njs_str("SyntaxError: Unexpected token \"}\" in 1") }, + { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" + "[1,2,3,4,5,6].map(byte => [buf.readUIntLE(0, byte), buf.readUIntLE(1, byte)])"), + njs_str("250,251," + "64506,64763," + "16579578,16645371," + "4261215226,4278058235," + "1095182908410,1099494718715," + "281470647991290,274877890034939") }, - { njs_str("let x = {async af() {await Promise.resolve(1)}}; x.af"), - njs_str("[object AsyncFunction]") }, + { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" + "[1,2,3,4,5,6].map(byte => [buf.readIntLE(0, byte), buf.readIntLE(1, byte)])"), + njs_str("-6,-5," + "-1030,-773," + "-197638,-131845," + "-33752070,-16909061," + "-4328719366,-16909061," + "-4328719366,-6597086675717") }, - { njs_str("let name = 'af', x = {async [name]() {await Promise.resolve(1)}}; x.af"), - njs_str("[object AsyncFunction]") }, -}; + { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" + "[1,2,3,4,5,6].map(byte => [buf.readUIntBE(0, byte), buf.readUIntBE(1, byte)])"), + njs_str("250,251," + "64251,64508," + "16448508,16514301," + "4210818301,4227661310," + "1077969485310,1082281295615," + "275960188239615,277064011677689") }, + { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" + "[1,2,3,4,5,6].map(byte => [buf.readIntBE(0, byte), buf.readIntBE(1, byte)])"), + njs_str("-6,-5," + "-1285,-1028," + "-328708,-262915," + "-84148995,-67305986," + "-21542142466,-17230332161," + "-5514788471041,-4410965032967") }, -static njs_unit_test_t njs_safe_test[] = -{ - { njs_str("(new Function('return this'))() === globalThis"), + { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);" + "function t(sign, endianness, offset) { " + " return [1,2,4].every(size => {" + " var method = `read${sign}Int${size * 8}`;" + " if (size > 1) { method += endianness};" + " var gmethod = `read${sign}Int${endianness}`;" + " var gv = buf[gmethod](offset, size);" + " var sv = buf[method](offset);" + " if (gv != sv) {throw Error(`${gmethod}(${offset},${size}):${gv} != ${method}(${offset}):${sv}`)}" + " return true;" + " });" + "}; " + "t('U', 'LE', 0) && t('U', 'LE', 1)" + "&& t('', 'LE', 0) && t('', 'LE', 1)" + "&& t('U', 'BE', 0) && t('U', 'BE', 1)" + "&& t('', 'BE', 0) && t('', 'BE', 1)"), njs_str("true") }, - { njs_str("(new Function('return this;'))() === globalThis"), + { njs_str("var buf = Buffer.alloc(9);" + "function t(sign, endianness, offset) { " + " return [1,2,4].every(size => {" + " var rgmethod = `read${sign}Int${endianness}`;" + " var wgmethod = `write${sign}Int${endianness}`;" + " var rmethod = `read${sign}Int${size * 8}`;" + " var wmethod = `write${sign}Int${size * 8}`;" + " if (size > 1) { rmethod += endianness; wmethod += endianness; };" + " var v = 0x7abbccddeeff & (size * 8 - 1);" + "" + " var ret = buf[wgmethod](v, offset, size);" + " if(ret !== offset + size) {" + " throw Error(`${wgmethod} returned ${ret}, need ${offset + size}`);" + " }" + "" + " var gv = buf[rgmethod](offset, size);" + "" + " buf.fill(0);" + " buf[wmethod](v, offset);" + " var sv = buf[rmethod](offset);" + " if (gv != sv) {throw Error(`${wmethod}(${v}, ${offset}):${sv} != ${wgmethod}(${v},${offset}):${gv}`)}" + " return true;" + " });" + "}; " + "t('U', 'LE', 0) && t('U', 'LE', 1)" + "&& t('', 'LE', 0) && t('', 'LE', 1)" + "&& t('U', 'BE', 0) && t('U', 'BE', 1)" + "&& t('', 'BE', 0) && t('', 'BE', 1)"), njs_str("true") }, - { njs_str("(new Function('return this '))() === globalThis"), - njs_str("true") }, + { njs_str(njs_buffer_byte_map("writeUIntLE", "+", 1)), + njs_str("Buffer [128,0,0,0,0,0]," + "Buffer [0,64,0,0,0,0]," + "Buffer [0,0,32,0,0,0]," + "Buffer [0,0,0,16,0,0]," + "Buffer [0,0,0,0,8,0]," + "Buffer [0,0,0,0,0,4]") }, - { njs_str("(new Function('return thi'))()"), - njs_str("TypeError: function constructor is disabled in \"safe\" mode") }, + { njs_str(njs_buffer_byte_map("writeUIntBE", "+", 1)), + njs_str("Buffer [128,0,0,0,0,0]," + "Buffer [64,0,0,0,0,0]," + "Buffer [32,0,0,0,0,0]," + "Buffer [16,0,0,0,0,0]," + "Buffer [8,0,0,0,0,0]," + "Buffer [4,0,0,0,0,0]") }, - { njs_str("(new Function('){return 1337})//', 'return this'))()"), - njs_str("TypeError: function constructor is disabled in \"safe\" mode") }, -}; + { njs_str(njs_buffer_byte_map("writeIntLE", "-", 2)), + njs_str("Buffer [192,0,0,0,0,0]," + "Buffer [0,224,0,0,0,0]," + "Buffer [0,0,240,0,0,0]," + "Buffer [0,0,0,248,0,0]," + "Buffer [0,0,0,0,252,0]," + "Buffer [0,0,0,0,0,254]") }, + { njs_str(njs_buffer_byte_map("writeIntBE", "-", 2)), + njs_str("Buffer [192,0,0,0,0,0]," + "Buffer [224,0,0,0,0,0]," + "Buffer [240,0,0,0,0,0]," + "Buffer [248,0,0,0,0,0]," + "Buffer [252,0,0,0,0,0]," + "Buffer [254,0,0,0,0,0]") }, -static njs_unit_test_t njs_denormals_test[] = -{ - { njs_str("2.2250738585072014e-308"), - njs_str("2.2250738585072014e-308") }, + { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleBE()"), + njs_str("8.20788039913184e-304") }, -#ifndef NJS_SUNC - { njs_str("2.2250738585072014E-308.toString(2) == ('0.' + '0'.repeat(1021) + '1')"), - njs_str("true") }, + { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleLE()"), + njs_str("5.447603722011605e-270") }, - { njs_str("Number('2.2250738585072014E-323')"), - njs_str("2.5e-323") }, + { njs_str("Buffer.from([1, 2, 3, 4]).readFloatBE()"), + njs_str("2.387939260590663e-38") }, - { njs_str("Number('2.2250738585072014E-323') + 0"), - njs_str("2.5e-323") }, + { njs_str("Buffer.from([1, 2, 3, 4]).readFloatLE()"), + njs_str("1.539989614439558e-36") }, - /* Smallest positive double (next_double(0)). */ - { njs_str("5E-324.toString(36) === '0.' + '0'.repeat(207) + '3'"), - njs_str("true") }, + { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleBE(1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - /* Maximum fraction length. */ - { njs_str("2.2250738585072014E-323.toString(2) == ('0.' + '0'.repeat(1071) + '101')"), - njs_str("true") }, + { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleLE(1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - /* Denormals. */ - { njs_str("var zeros = count => '0'.repeat(count);" - "[" - " [1.8858070859709815e-308, `0.${zeros(1022)}1101100011110111011100000100011001111101110001010111`]," - // FIXME: " [Number.MIN_VALUE, `0.${zeros(1073)}1`]" - " [-5.06631661953108e-309, `-0.${zeros(1024)}11101001001010000001101111010101011111111011010111`]," - " [6.22574126804e-313, `0.${zeros(1037)}11101010101101100111000110100111001`]," - " [-4e-323, `-0.${zeros(1070)}1`]," - "].every(t=>t[0].toString(2) === t[1])"), - njs_str("true") }, + { njs_str("Buffer.from([1, 2, 3, 4]).readFloatBE(1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - { njs_str("4.94065645841246544176568792868e-324.toExponential()"), - njs_str("5e-324") }, + { njs_str("Buffer.from([1, 2, 3, 4]).readFloatLE(1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - { njs_str("4.94065645841246544176568792868e-324.toExponential(10)"), - njs_str("4.9406564584e-324") }, -#endif + { njs_str("var buf = Buffer.allocUnsafe(8);" + "buf.writeDoubleBE(123.456); njs.dump(buf)"), + njs_str("Buffer [64,94,221,47,26,159,190,119]") }, -}; + { njs_str("var buf = Buffer.allocUnsafe(8);" + "buf.writeDoubleLE(123.456); njs.dump(buf)"), + njs_str("Buffer [119,190,159,26,47,221,94,64]") }, + { njs_str("var buf = Buffer.allocUnsafe(4);" + "buf.writeFloatBE(123.456); njs.dump(buf)"), + njs_str("Buffer [66,246,233,121]") }, -static njs_unit_test_t njs_disabled_denormals_test[] = -{ - { njs_str("Number('2.2250738585072014E-323')"), - njs_str("0") }, + { njs_str("var buf = Buffer.allocUnsafe(4);" + "buf.writeFloatLE(123.456); njs.dump(buf)"), + njs_str("Buffer [121,233,246,66]") }, - { njs_str("Number('2.2250738585072014E-323') + 0"), - njs_str("0") }, + { njs_str("var buf = Buffer.allocUnsafe(8).writeDoubleBE(123.456, 1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - /* Smallest positive double (next_double(0)). */ - { njs_str("5E-324.toString(36)"), - njs_str("0") }, + { njs_str("var buf = Buffer.allocUnsafe(8).writeDoubleLE(123.456, 1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - { njs_str("2.2250738585072014E-323.toString(2)"), - njs_str("0") }, + { njs_str("var buf = Buffer.allocUnsafe(4).writeFloatBE(123.456, 1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - /* Smallest normal double. */ + { njs_str("var buf = Buffer.allocUnsafe(4).writeFloatLE(123.456, 1)"), + njs_str("RangeError: index 1 is outside the bound of the buffer") }, - { njs_str("2.2250738585072014e-308"), - njs_str("2.2250738585072014e-308") }, + { njs_str("var buffer = require('buffer');" + "buffer.Buffer.alloc(5).fill('ABC')"), + njs_str("ABCAB") }, - { njs_str("2.2250738585072014e-308/2"), - njs_str("0") }, + { njs_str("var buffer = require('buffer');" + "typeof buffer.kMaxLength === 'number' "), + njs_str("true") }, - /* Denormals. */ - { njs_str("[" - "1.8858070859709815e-308," - "-5.06631661953108e-309," - "6.22574126804e-313," - "-4e-323," - "].map(v=>v.toString(2))"), - njs_str("0,0,0,0") }, + { njs_str("var buffer = require('buffer');" + "typeof buffer.constants.MAX_LENGTH === 'number' "), + njs_str("true") }, + + { njs_str("var buffer = require('buffer');" + "typeof buffer.constants.MAX_STRING_LENGTH === 'number' "), + njs_str("true") }, }; @@ -23374,6 +23379,30 @@ static njs_test_suite_t njs_suites[] = njs_nitems(njs_module_test), njs_unit_test }, + { njs_str("fs module"), + { .repeat = 1, .unsafe = 1 }, + njs_fs_module_test, + njs_nitems(njs_fs_module_test), + njs_unit_test }, + + { njs_str("crypto module"), + { .repeat = 1, .unsafe = 1 }, + njs_crypto_module_test, + njs_nitems(njs_crypto_module_test), + njs_unit_test }, + + { njs_str("querystring module"), + { .repeat = 1, .unsafe = 1 }, + njs_querystring_module_test, + njs_nitems(njs_querystring_module_test), + njs_unit_test }, + + { njs_str("buffer module"), + { .repeat = 1, .unsafe = 1 }, + njs_buffer_module_test, + njs_nitems(njs_buffer_module_test), + njs_unit_test }, + { njs_str("externals"), { .externals = 1, .repeat = 1, .unsafe = 1 }, njs_externals_test, -- 2.47.3