[njs] Introduced tags for NJS_DATA type.

Dmitry Volyntsev xeioex at nginx.com
Thu Jul 30 17:48:16 UTC 2020


details:   https://hg.nginx.org/njs/rev/0fad09ddb37a
branches:  
changeset: 1484:0fad09ddb37a
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jul 30 17:47:05 2020 +0000
description:
Introduced tags for NJS_DATA type.

NJS_DATA is designed to contain arbitrary opaque pointers.
Tags are used to distinguish different opaque pointers.

diffstat:

 src/njs.h                |   2 -
 src/njs_crypto.c         |  60 ++++++++++++++++++++---------------------------
 src/njs_extern.c         |  11 +++-----
 src/njs_promise.c        |  14 +++++-----
 src/njs_value.c          |  14 -----------
 src/njs_value.h          |  25 +++++++++++++++++--
 src/test/njs_unit_test.c |   4 +++
 7 files changed, 63 insertions(+), 67 deletions(-)

diffs (396 lines):

diff -r cb490ee06ac2 -r 0fad09ddb37a src/njs.h
--- a/src/njs.h	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/njs.h	Thu Jul 30 17:47:05 2020 +0000
@@ -341,11 +341,9 @@ NJS_EXPORT void njs_vm_memory_error(njs_
 NJS_EXPORT void njs_value_undefined_set(njs_value_t *value);
 NJS_EXPORT void njs_value_boolean_set(njs_value_t *value, int yn);
 NJS_EXPORT void njs_value_number_set(njs_value_t *value, double num);
-NJS_EXPORT void njs_value_data_set(njs_value_t *value, void *data);
 
 NJS_EXPORT uint8_t njs_value_bool(const njs_value_t *value);
 NJS_EXPORT double njs_value_number(const njs_value_t *value);
-NJS_EXPORT void *njs_value_data(const njs_value_t *value);
 NJS_EXPORT njs_function_t *njs_value_function(const njs_value_t *value);
 
 NJS_EXPORT uint16_t njs_vm_prop_magic16(njs_object_prop_t *prop);
diff -r cb490ee06ac2 -r 0fad09ddb37a src/njs_crypto.c
--- a/src/njs_crypto.c	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/njs_crypto.c	Thu Jul 30 17:47:05 2020 +0000
@@ -184,7 +184,7 @@ njs_crypto_create_hash(njs_vm_t *vm, njs
 
     alg->init(&dgst->u);
 
-    njs_set_data(&hash->value, dgst);
+    njs_set_data(&hash->value, dgst, NJS_DATA_TAG_CRYPTO_HASH);
     njs_set_object_value(&vm->retval, hash);
 
     return NJS_OK;
@@ -196,6 +196,7 @@ njs_hash_prototype_update(njs_vm_t *vm, 
     njs_index_t unused)
 {
     njs_str_t     data;
+    njs_value_t   *this;
     njs_digest_t  *dgst;
 
     if (njs_slow_path(nargs < 2 || !njs_is_string(&args[1]))) {
@@ -203,19 +204,16 @@ njs_hash_prototype_update(njs_vm_t *vm, 
         return NJS_ERROR;
     }
 
-    if (njs_slow_path(!njs_is_object_value(&args[0]))) {
-        njs_type_error(vm, "\"this\" is not an object_value");
-        return NJS_ERROR;
-    }
+    this = njs_argument(args, 0);
 
-    if (njs_slow_path(!njs_is_data(njs_object_value(&args[0])))) {
-        njs_type_error(vm, "value of \"this\" is not a data type");
+    if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HASH))) {
+        njs_type_error(vm, "\"this\" is not a hash object");
         return NJS_ERROR;
     }
 
     njs_string_get(&args[1], &data);
 
-    dgst = njs_value_data(njs_object_value(&args[0]));
+    dgst = njs_object_data(this);
 
     if (njs_slow_path(dgst->alg == NULL)) {
         njs_error(vm, "Digest already called");
@@ -224,7 +222,7 @@ njs_hash_prototype_update(njs_vm_t *vm, 
 
     dgst->alg->update(&dgst->u, data.start, data.length);
 
-    vm->retval = args[0];
+    vm->retval = *this;
 
     return NJS_OK;
 }
@@ -237,6 +235,7 @@ njs_hash_prototype_digest(njs_vm_t *vm, 
     u_char            digest[32], *p;
     njs_int_t         ret;
     njs_str_t         enc_name, str;
+    njs_value_t       *this;
     njs_digest_t      *dgst;
     njs_hash_alg_t    *alg;
     njs_crypto_enc_t  *enc;
@@ -246,13 +245,10 @@ njs_hash_prototype_digest(njs_vm_t *vm, 
         return NJS_ERROR;
     }
 
-    if (njs_slow_path(!njs_is_object_value(&args[0]))) {
-        njs_type_error(vm, "\"this\" is not an object_value");
-        return NJS_ERROR;
-    }
+    this = njs_argument(args, 0);
 
-    if (njs_slow_path(!njs_is_data(njs_object_value(&args[0])))) {
-        njs_type_error(vm, "value of \"this\" is not a data type");
+    if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HASH))) {
+        njs_type_error(vm, "\"this\" is not a hash object");
         return NJS_ERROR;
     }
 
@@ -267,7 +263,7 @@ njs_hash_prototype_digest(njs_vm_t *vm, 
         }
     }
 
-    dgst = njs_value_data(njs_object_value(&args[0]));
+    dgst = njs_object_data(this);
 
     if (njs_slow_path(dgst->alg == NULL)) {
         njs_error(vm, "Digest already called");
@@ -465,7 +461,7 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs
         return NJS_ERROR;
     }
 
-    njs_set_data(&hmac->value, ctx);
+    njs_set_data(&hmac->value, ctx, NJS_DATA_TAG_CRYPTO_HMAC);
     njs_set_object_value(&vm->retval, hmac);
 
     return NJS_OK;
@@ -476,27 +472,25 @@ static njs_int_t
 njs_hmac_prototype_update(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused)
 {
-    njs_str_t   data;
-    njs_hmac_t  *ctx;
+    njs_str_t    data;
+    njs_hmac_t   *ctx;
+    njs_value_t  *this;
 
     if (njs_slow_path(nargs < 2 || !njs_is_string(&args[1]))) {
         njs_type_error(vm, "data must be a string");
         return NJS_ERROR;
     }
 
-    if (njs_slow_path(!njs_is_object_value(&args[0]))) {
-        njs_type_error(vm, "\"this\" is not an object_value");
-        return NJS_ERROR;
-    }
+    this = njs_argument(args, 0);
 
-    if (njs_slow_path(!njs_is_data(njs_object_value(&args[0])))) {
-        njs_type_error(vm, "value of \"this\" is not a data type");
+    if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HMAC))) {
+        njs_type_error(vm, "\"this\" is not a hash object");
         return NJS_ERROR;
     }
 
     njs_string_get(&args[1], &data);
 
-    ctx = njs_value_data(njs_object_value(&args[0]));
+    ctx = njs_object_data(this);
 
     if (njs_slow_path(ctx->alg == NULL)) {
         njs_error(vm, "Digest already called");
@@ -505,7 +499,7 @@ njs_hmac_prototype_update(njs_vm_t *vm, 
 
     ctx->alg->update(&ctx->u, data.start, data.length);
 
-    vm->retval = args[0];
+    vm->retval = *this;
 
     return NJS_OK;
 }
@@ -519,6 +513,7 @@ njs_hmac_prototype_digest(njs_vm_t *vm, 
     njs_str_t         enc_name, str;
     njs_int_t         ret;
     njs_hmac_t        *ctx;
+    njs_value_t       *this;
     njs_hash_alg_t    *alg;
     njs_crypto_enc_t  *enc;
 
@@ -527,13 +522,10 @@ njs_hmac_prototype_digest(njs_vm_t *vm, 
         return NJS_ERROR;
     }
 
-    if (njs_slow_path(!njs_is_object_value(&args[0]))) {
-        njs_type_error(vm, "\"this\" is not an object_value");
-        return NJS_ERROR;
-    }
+    this = njs_argument(args, 0);
 
-    if (njs_slow_path(!njs_is_data(njs_object_value(&args[0])))) {
-        njs_type_error(vm, "value of \"this\" is not a data type");
+    if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HMAC))) {
+        njs_type_error(vm, "\"this\" is not a hash object");
         return NJS_ERROR;
     }
 
@@ -548,7 +540,7 @@ njs_hmac_prototype_digest(njs_vm_t *vm, 
         }
     }
 
-    ctx = njs_value_data(njs_object_value(&args[0]));
+    ctx = njs_object_data(this);
 
     if (njs_slow_path(ctx->alg == NULL)) {
         njs_error(vm, "Digest already called");
diff -r cb490ee06ac2 -r 0fad09ddb37a src/njs_extern.c
--- a/src/njs_extern.c	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/njs_extern.c	Thu Jul 30 17:47:05 2020 +0000
@@ -202,7 +202,7 @@ njs_external_prop_handler(njs_vm_t *vm, 
         ov->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_OBJECT].object;
         ov->object.slots = slots;
 
-        njs_set_data(&ov->value, external);
+        njs_set_data(&ov->value, external, NJS_DATA_TAG_EXTERNAL);
         njs_set_object_value(retval, ov);
     }
 
@@ -313,7 +313,7 @@ njs_vm_external_create(njs_vm_t *vm, njs
     ov->object.slots = slots;
 
     njs_set_object_value(value, ov);
-    njs_set_data(&ov->value, external);
+    njs_set_data(&ov->value, external, NJS_DATA_TAG_EXTERNAL);
 
     return NJS_OK;
 }
@@ -322,11 +322,8 @@ njs_vm_external_create(njs_vm_t *vm, njs
 njs_external_ptr_t
 njs_vm_external(njs_vm_t *vm, const njs_value_t *value)
 {
-    if (njs_fast_path(njs_is_object_value(value))) {
-        value = njs_object_value(value);
-        if (njs_fast_path(njs_is_data(value))) {
-            return njs_value_data(value);
-        }
+    if (njs_fast_path(njs_is_object_data(value, NJS_DATA_TAG_EXTERNAL))) {
+        return njs_object_data(value);
     }
 
     return NULL;
diff -r cb490ee06ac2 -r 0fad09ddb37a src/njs_promise.c
--- a/src/njs_promise.c	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/njs_promise.c	Thu Jul 30 17:47:05 2020 +0000
@@ -101,7 +101,7 @@ njs_promise_alloc(njs_vm_t *vm)
     njs_queue_init(&data->reject_queue);
 
     njs_set_promise(&vm->retval, promise);
-    njs_value_data_set(&promise->value, data);
+    njs_set_data(&promise->value, data, 0);
 
     return promise;
 
@@ -453,7 +453,7 @@ njs_promise_trigger_reactions(njs_vm_t *
         function = njs_promise_create_function(vm);
         function->u.native = njs_promise_reaction_job;
 
-        njs_set_data(&arguments[0], reaction);
+        njs_set_data(&arguments[0], reaction, 0);
         arguments[1] = *value;
 
         ret = njs_promise_add_event(vm, function, arguments, 2);
@@ -472,7 +472,7 @@ njs_promise_fulfill(njs_vm_t *vm, njs_pr
     njs_queue_t         queue;
     njs_promise_data_t  *data;
 
-    data = njs_value_data(&promise->value);
+    data = njs_data(&promise->value);
 
     data->result = *value;
     data->state = NJS_PROMISE_FULFILL;
@@ -500,7 +500,7 @@ njs_promise_reject(njs_vm_t *vm, njs_pro
     njs_queue_t         queue;
     njs_promise_data_t  *data;
 
-    data = njs_value_data(&promise->value);
+    data = njs_data(&promise->value);
 
     data->result = *reason;
     data->state = NJS_PROMISE_REJECTED;
@@ -845,7 +845,7 @@ njs_promise_perform_then(njs_vm_t *vm, n
     }
 
     promise = njs_promise(value);
-    data = njs_value_data(&promise->value);
+    data = njs_data(&promise->value);
 
     fulfilled_reaction = njs_mp_alloc(vm->mem_pool,
                                       sizeof(njs_promise_reaction_t));
@@ -878,12 +878,12 @@ njs_promise_perform_then(njs_vm_t *vm, n
         function->u.native = njs_promise_reaction_job;
 
         if (data->state == NJS_PROMISE_REJECTED) {
-            njs_set_data(&arguments[0], rejected_reaction);
+            njs_set_data(&arguments[0], rejected_reaction, 0);
 
             /* TODO: HostPromiseRejectionTracker */
 
         } else {
-            njs_set_data(&arguments[0], fulfilled_reaction);
+            njs_set_data(&arguments[0], fulfilled_reaction, 0);
         }
 
         arguments[1] = data->result;
diff -r cb490ee06ac2 -r 0fad09ddb37a src/njs_value.c
--- a/src/njs_value.c	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/njs_value.c	Thu Jul 30 17:47:05 2020 +0000
@@ -371,13 +371,6 @@ njs_value_number_set(njs_value_t *value,
 }
 
 
-void
-njs_value_data_set(njs_value_t *value, void *data)
-{
-    njs_set_data(value, data);
-}
-
-
 uint8_t
 njs_value_bool(const njs_value_t *value)
 {
@@ -392,13 +385,6 @@ njs_value_number(const njs_value_t *valu
 }
 
 
-void *
-njs_value_data(const njs_value_t *value)
-{
-    return njs_data(value);
-}
-
-
 njs_function_t *
 njs_value_function(const njs_value_t *value)
 {
diff -r cb490ee06ac2 -r 0fad09ddb37a src/njs_value.h
--- a/src/njs_value.h	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/njs_value.h	Thu Jul 30 17:47:05 2020 +0000
@@ -76,6 +76,15 @@ typedef enum {
 } njs_value_type_t;
 
 
+typedef enum {
+    NJS_DATA_TAG_ANY = 0,
+    NJS_DATA_TAG_EXTERNAL,
+    NJS_DATA_TAG_CRYPTO_HASH,
+    NJS_DATA_TAG_CRYPTO_HMAC,
+    NJS_DATA_TAG_MAX
+} njs_data_tag_t;
+
+
 typedef struct njs_string_s           njs_string_t;
 typedef struct njs_object_s           njs_object_t;
 typedef struct njs_object_value_s     njs_object_value_t;
@@ -599,8 +608,8 @@ typedef struct {
     ((value)->type <= NJS_STRING)
 
 
-#define njs_is_data(value)                                                    \
-    ((value)->type == NJS_DATA)
+#define njs_is_data(value, tag)                                               \
+    ((value)->type == NJS_DATA && value->data.magic32 == (tag))
 
 
 #define njs_is_object(value)                                                  \
@@ -616,6 +625,11 @@ typedef struct {
     ((value)->type == NJS_OBJECT_VALUE)
 
 
+#define njs_is_object_data(_value, tag)                                       \
+    (((_value)->type == NJS_OBJECT_VALUE)                                     \
+     && njs_is_data(njs_object_value(_value), tag))
+
+
 #define njs_is_object_string(value)                                           \
     ((value)->type == NJS_OBJECT_STRING)
 
@@ -748,6 +762,10 @@ typedef struct {
     (&(_value)->data.u.object_value->value)
 
 
+#define njs_object_data(_value)                                               \
+    njs_data(njs_object_value(_value))
+
+
 #define njs_set_undefined(value)                                              \
     *(value) = njs_value_undefined
 
@@ -852,8 +870,9 @@ njs_set_symbol(njs_value_t *value, uint3
 
 
 njs_inline void
-njs_set_data(njs_value_t *value, void *data)
+njs_set_data(njs_value_t *value, void *data, njs_data_tag_t tag)
 {
+    value->data.magic32 = tag;
     value->data.u.data = data;
     value->type = NJS_DATA;
     value->data.truth = 1;
diff -r cb490ee06ac2 -r 0fad09ddb37a src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Jul 29 17:00:23 2020 +0000
+++ b/src/test/njs_unit_test.c	Thu Jul 30 17:47:05 2020 +0000
@@ -16956,6 +16956,10 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("typeof require('crypto').createHmac('md5', 'a')"),
       njs_str("object") },
 
+    { 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") },
+
     /* setTimeout(). */
 
     { njs_str("setTimeout()"),


More information about the nginx-devel mailing list