From: Artem S. Povalyukhin Date: Sun, 26 Jan 2020 18:56:23 +0000 (+0300) Subject: Introduced fs.access and friends. X-Git-Tag: 0.3.9~23 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=d71a881ce5bf16254d0f5a5638719e0db546d2be;p=njs.git Introduced fs.access and friends. --- diff --git a/src/njs_fs.c b/src/njs_fs.c index 2e3b15b3..5c746296 100644 --- a/src/njs_fs.c +++ b/src/njs_fs.c @@ -465,6 +465,68 @@ njs_fs_rename_sync(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } +static njs_int_t +njs_fs_access(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t calltype) +{ + int md; + njs_int_t ret; + const char *file_path; + njs_value_t retval, *path, *callback, *mode; + + path = njs_arg(args, nargs, 1); + ret = njs_fs_path_arg(vm, &file_path, path, &njs_str_value("path")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + callback = NULL; + mode = njs_arg(args, nargs, 2); + + if (calltype == NJS_FS_CALLBACK) { + callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); + if (!njs_is_function(callback)) { + njs_type_error(vm, "\"callback\" must be a function"); + return NJS_ERROR; + } + + if (mode == callback) { + mode = njs_value_arg(&njs_value_undefined); + } + } + + switch (mode->type) { + case NJS_UNDEFINED: + md = F_OK; + break; + + case NJS_NUMBER: + md = njs_number(mode); + break; + + default: + njs_type_error(vm, "\"mode\" must be a number"); + return NJS_ERROR; + } + + ret = access(file_path, md); + if (njs_slow_path(ret != 0)) { + ret = njs_fs_error(vm, "access", strerror(errno), path, errno, &retval); + goto done; + } + + njs_set_undefined(&retval); + +done: + + if (ret == NJS_OK) { + return njs_fs_result(vm, &retval, calltype, callback, 1); + } + + return NJS_ERROR; +} + + static njs_int_t njs_fs_fd_read(njs_vm_t *vm, int fd, njs_str_t *data) { @@ -810,6 +872,14 @@ static const njs_object_prop_t njs_fs_promises_properties[] = .writable = 1, .configurable = 1, }, + + { + .type = NJS_PROPERTY, + .name = njs_string("access"), + .value = njs_native_function2(njs_fs_access, 0, NJS_FS_PROMISE), + .writable = 1, + .configurable = 1, + }, }; @@ -827,6 +897,50 @@ njs_fs_promises(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, } +static const njs_object_prop_t njs_fs_constants_properties[] = +{ + { + .type = NJS_PROPERTY, + .name = njs_string("F_OK"), + .value = njs_value(NJS_NUMBER, 0, F_OK), + .enumerable = 1, + }, + { + .type = NJS_PROPERTY, + .name = njs_string("R_OK"), + .value = njs_value(NJS_NUMBER, 1, R_OK), + .enumerable = 1, + }, + { + .type = NJS_PROPERTY, + .name = njs_string("W_OK"), + .value = njs_value(NJS_NUMBER, 1, W_OK), + .enumerable = 1, + }, + { + .type = NJS_PROPERTY, + .name = njs_string("X_OK"), + .value = njs_value(NJS_NUMBER, 1, X_OK), + .enumerable = 1, + }, +}; + + +static const njs_object_init_t njs_fs_constants_init = { + njs_fs_constants_properties, + njs_nitems(njs_fs_constants_properties), +}; + + +static njs_int_t +njs_fs_constants(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, + njs_value_t *unused, njs_value_t *retval) +{ + return njs_object_prop_init(vm, &njs_fs_constants_init, prop, value, + retval); +} + + static const njs_object_prop_t njs_fs_object_properties[] = { { @@ -836,12 +950,35 @@ static const njs_object_prop_t njs_fs_object_properties[] = .configurable = 1, }, + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constants"), + .value = njs_prop_handler(njs_fs_constants), + .enumerable = 1, + }, + { .type = NJS_PROPERTY_HANDLER, .name = njs_string("promises"), .value = njs_prop_handler(njs_fs_promises), }, + { + .type = NJS_PROPERTY, + .name = njs_string("access"), + .value = njs_native_function2(njs_fs_access, 0, NJS_FS_CALLBACK), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("accessSync"), + .value = njs_native_function2(njs_fs_access, 0, NJS_FS_DIRECT), + .writable = 1, + .configurable = 1, + }, + { .type = NJS_PROPERTY, .name = njs_string("readFile"), diff --git a/src/test/njs_interactive_test.c b/src/test/njs_interactive_test.c index 685165c5..cfba40b2 100644 --- a/src/test/njs_interactive_test.c +++ b/src/test/njs_interactive_test.c @@ -233,7 +233,10 @@ static njs_interactive_test_t njs_test[] = " at main (native)\n") }, { njs_str("var fs = require('fs');" - "['readFile'," + "[" + " 'access'," + " 'accessSync'," + " 'readFile'," " 'readFileSync'," " 'writeFile'," " 'writeFileSync'," diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 5ce8f49a..c39a55ec 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -15991,9 +15991,39 @@ static njs_unit_test_t njs_test[] = ".every((x) => x === true)"), njs_str("true")}, + /* require('fs').access() */ + + { njs_str("var fs = require('fs');" + "fs.access()"), + njs_str("TypeError: \"path\" must be a string") }, + + { njs_str("var fs = require('fs');" + "fs.access('/njs_unknown_path')"), + njs_str("TypeError: \"callback\" must be a function") }, + + { 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 fs = require('fs');" + "fs.access('/njs_unknown_path', 'fail', function () {})"), + njs_str("TypeError: \"mode\" must be a number") }, + + /* require('fs').accessSync() */ + + { njs_str("var fs = require('fs');" + "fs.accessSync()"), + njs_str("TypeError: \"path\" must be a string") }, + + { njs_str("var fs = require('fs');" + "fs.accessSync('/njs_unknown_path', 'fail')"), + njs_str("TypeError: \"mode\" must be a number") }, + { njs_str("var " "fs = require('fs')," "func = [" + "'access'," + "'accessSync'," "'readFile'," "'readFileSync'," "'writeFile'," @@ -16018,6 +16048,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var " "fs = require('fs').promises," "func = [" + "'access'," "'readFile'," "'writeFile'," "'appendFile'," @@ -16025,6 +16056,23 @@ static njs_unit_test_t njs_test[] = "func.every((x) => typeof fs[x] == 'function')"), njs_str("true")}, + /* require('fs').constants */ + + { njs_str("var fs = require('fs');" + "typeof fs.constants"), + njs_str("object") }, + + { 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")}, + /* require('crypto').createHash() */ { njs_str("var h = require('crypto').createHash('sha1');" diff --git a/test/js/fs_promises_001.js b/test/js/fs_promises_001.js index 74f3a492..477b2549 100644 --- a/test/js/fs_promises_001.js +++ b/test/js/fs_promises_001.js @@ -15,10 +15,10 @@ Promise.resolve() return fs.readFile(fname).then(fs.readFile); }) .then((data) => { - console.log('short citcut ok', data == fname); + console.log('short circut ok', data == fname); }) .catch((e) => { - console.log('short citcut failed', e); + console.log('short circut failed', e); }) .then(() => { var read = fs.readFile.bind(fs, fname, 'utf8'); diff --git a/test/js/fs_promises_002.js b/test/js/fs_promises_002.js new file mode 100644 index 00000000..394616e5 --- /dev/null +++ b/test/js/fs_promises_002.js @@ -0,0 +1,71 @@ +var fs = require('fs'); +var fsp = fs.promises; +var fname = '/tmp/njs_fs_promises_002'; + +var testSync = new Promise((resolve, reject) => { + var failed = false; + try { + fs.writeFileSync(fname, fname); + + fs.accessSync(fname); + fs.accessSync(fname, fs.constants.R_OK | fs.constants.W_OK); + + try { + fs.accessSync(fname + '___'); + failed = true; + } catch(e) { + failed = (e.syscall != 'access'); + // TODO: e.code != 'ENOENT' + } + resolve(failed); + } catch (e) { + reject(e); + } +}); + +var testCallback = new Promise((resolve, reject) => { + var failed = false; + + fs.writeFileSync(fname, fname); + + fs.access(fname, (err) => { + failed = (err !== undefined); + fs.access(fname, fs.constants.R_OK | fs.constants.W_OK, (err) => { + failed |= (err !== undefined); + fs.access(fname + '___', (err) => { + failed |= ((err === undefined) || (err.syscall != 'access')); + resolve(failed); + }); + }); + }); +}); + +Promise.resolve() +.then(() => testSync) +.then((failed) => { + console.log('testSync ok', !failed); +}) +.catch((e) => { + console.log('testSync failed', e); +}) +.then(() => testCallback) +.then((failed) => { + console.log('testCallback ok', !failed); +}) +.catch((e) => { + console.log('testCallback failed', e); +}) +.then(() => { + fs.writeFileSync(fname, fname); + + return fsp.access(fname) + .then(() => fsp.access(fname, fs.constants.R_OK | fs.constants.W_OK)) + .then(() => fsp.access(fname + '___')); +}) +.then(() => { + console.log('testPromise failed'); +}) +.catch((e) => { + console.log('testPromise ok', (e.syscall == 'access') && (e.path == fname + '___')); +}) +; diff --git a/test/njs_expect_test.exp b/test/njs_expect_test.exp index e5583994..447b6a74 100644 --- a/test/njs_expect_test.exp +++ b/test/njs_expect_test.exp @@ -1064,9 +1064,14 @@ PatchedPromise async done" njs_run {"./test/js/fs_promises_001.js"} \ "init ok true -short citcut ok true +short circut ok true chain ok true error 1 ok true error 2 ok true error 3 ok true errors ok" + +njs_run {"./test/js/fs_promises_002.js"} \ +"testSync ok true +testCallback ok true +testPromise ok true"