[njs] Introduced fs.access and friends.
Dmitry Volyntsev
xeioex at nginx.com
Fri Feb 7 14:35:06 UTC 2020
details: https://hg.nginx.org/njs/rev/1f3e045ea017
branches:
changeset: 1322:1f3e045ea017
user: Artem S. Povalyukhin <artem.povaluhin at gmail.com>
date: Sun Jan 26 21:56:23 2020 +0300
description:
Introduced fs.access and friends.
diffstat:
src/njs_fs.c | 137 ++++++++++++++++++++++++++++++++++++++++
src/test/njs_interactive_test.c | 5 +-
src/test/njs_unit_test.c | 48 ++++++++++++++
test/js/fs_promises_001.js | 4 +-
test/js/fs_promises_002.js | 71 ++++++++++++++++++++
test/njs_expect_test.exp | 7 +-
6 files changed, 268 insertions(+), 4 deletions(-)
diffs (374 lines):
diff -r 03ec7b441da8 -r 1f3e045ea017 src/njs_fs.c
--- a/src/njs_fs.c Sat Jan 25 21:55:50 2020 +0300
+++ b/src/njs_fs.c Sun Jan 26 21:56:23 2020 +0300
@@ -466,6 +466,68 @@ njs_fs_rename_sync(njs_vm_t *vm, njs_val
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)
{
u_char *p, *end, *start;
@@ -810,6 +872,14 @@ static const njs_object_prop_t njs_fs_p
.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
}
+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[] =
{
{
@@ -838,12 +952,35 @@ static const njs_object_prop_t njs_fs_o
{
.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"),
.value = njs_native_function2(njs_fs_read_file, 0, NJS_FS_CALLBACK),
.writable = 1,
diff -r 03ec7b441da8 -r 1f3e045ea017 src/test/njs_interactive_test.c
--- a/src/test/njs_interactive_test.c Sat Jan 25 21:55:50 2020 +0300
+++ b/src/test/njs_interactive_test.c Sun Jan 26 21:56:23 2020 +0300
@@ -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 -r 03ec7b441da8 -r 1f3e045ea017 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Sat Jan 25 21:55:50 2020 +0300
+++ b/src/test/njs_unit_test.c Sun Jan 26 21:56:23 2020 +0300
@@ -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 -r 03ec7b441da8 -r 1f3e045ea017 test/js/fs_promises_001.js
--- a/test/js/fs_promises_001.js Sat Jan 25 21:55:50 2020 +0300
+++ b/test/js/fs_promises_001.js Sun Jan 26 21:56:23 2020 +0300
@@ -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 -r 03ec7b441da8 -r 1f3e045ea017 test/js/fs_promises_002.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/fs_promises_002.js Sun Jan 26 21:56:23 2020 +0300
@@ -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 -r 03ec7b441da8 -r 1f3e045ea017 test/njs_expect_test.exp
--- a/test/njs_expect_test.exp Sat Jan 25 21:55:50 2020 +0300
+++ b/test/njs_expect_test.exp Sun Jan 26 21:56:23 2020 +0300
@@ -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"
More information about the nginx-devel
mailing list