]> git.kaiwu.me - njs.git/commitdiff
Introduced fs.access and friends.
authorArtem S. Povalyukhin <artem.povaluhin@gmail.com>
Sun, 26 Jan 2020 18:56:23 +0000 (21:56 +0300)
committerArtem S. Povalyukhin <artem.povaluhin@gmail.com>
Sun, 26 Jan 2020 18:56:23 +0000 (21:56 +0300)
src/njs_fs.c
src/test/njs_interactive_test.c
src/test/njs_unit_test.c
test/js/fs_promises_001.js
test/js/fs_promises_002.js [new file with mode: 0644]
test/njs_expect_test.exp

index 2e3b15b3436027fd1acf5ff18ec3e4c8b67044b1..5c7462968a8fea1c8b980927a8f76444626e4658 100644 (file)
@@ -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"),
index 685165c587e02249a066e5a4c6210ce87c01174e..cfba40b247ac5a095c899ef18aabaf1b5e28e3f9 100644 (file)
@@ -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',"
index 5ce8f49a81423f7cab1c4610e5cf5a2832a016c4..c39a55ec211f43d4d752a56e9a1a214d89e9ba22 100644 (file)
@@ -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');"
index 74f3a4925919d42ebd9231de72571180f05b9405..477b2549b759f5169ed2c2e2d8055d1a3a93a60e 100644 (file)
@@ -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 (file)
index 0000000..394616e
--- /dev/null
@@ -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 + '___'));
+})
+;
index e5583994425a16de2822234316bc46288d739c91..447b6a7497b4d658427853e35dea23024e6f45e8 100644 (file)
@@ -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"