NJS_DATA is designed to contain arbitrary opaque pointers.
Tags are used to distinguish different opaque pointers.
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);
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;
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]))) {
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");
dgst->alg->update(&dgst->u, data.start, data.length);
- vm->retval = args[0];
+ vm->retval = *this;
return NJS_OK;
}
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;
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;
}
}
}
- 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");
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;
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");
ctx->alg->update(&ctx->u, data.start, data.length);
- vm->retval = args[0];
+ vm->retval = *this;
return NJS_OK;
}
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;
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;
}
}
}
- 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");
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);
}
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;
}
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;
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;
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);
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;
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;
}
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));
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;
}
-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)
{
}
-void *
-njs_value_data(const njs_value_t *value)
-{
- return njs_data(value);
-}
-
-
njs_function_t *
njs_value_function(const njs_value_t *value)
{
} 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;
((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) \
((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)
(&(_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
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;
{ 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()"),