[njs] Introduced njs_vm_bind().
Dmitry Volyntsev
xeioex at nginx.com
Tue Nov 26 12:42:35 UTC 2019
details: https://hg.nginx.org/njs/rev/68c9971d7366
branches:
changeset: 1259:68c9971d7366
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Nov 26 15:09:45 2019 +0300
description:
Introduced njs_vm_bind().
This is a generic replacement for njs_vm_external_bind().
diffstat:
src/njs.h | 5 +-
src/njs_builtin.c | 84 ++++++----------------------------------------
src/njs_extern.c | 83 ----------------------------------------------
src/njs_extern.h | 2 -
src/njs_parser_terminal.c | 10 -----
src/njs_shell.c | 12 +++---
src/njs_variable.c | 6 ---
src/njs_vm.c | 41 ++++++++++++++++++++++-
src/njs_vm.h | 1 -
src/test/njs_unit_test.c | 77 ++++++++++++++++++++++++++++++++++--------
test/njs_expect_test.exp | 11 +++--
11 files changed, 129 insertions(+), 203 deletions(-)
diffs (609 lines):
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs.h
--- a/src/njs.h Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs.h Tue Nov 26 15:09:45 2019 +0300
@@ -235,16 +235,17 @@ NJS_EXPORT const njs_extern_t *njs_vm_ex
njs_external_t *external);
NJS_EXPORT njs_int_t njs_vm_external_create(njs_vm_t *vm,
njs_value_t *value, const njs_extern_t *proto, njs_external_ptr_t object);
-NJS_EXPORT njs_int_t njs_vm_external_bind(njs_vm_t *vm,
- const njs_str_t *var_name, const njs_value_t *value);
NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
const njs_value_t *value);
NJS_EXPORT void njs_disassembler(njs_vm_t *vm);
NJS_EXPORT void njs_disassemble(u_char *start, u_char *end);
+NJS_EXPORT njs_int_t njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name,
+ const njs_value_t *value, njs_bool_t shared);
NJS_EXPORT const njs_value_t *njs_vm_value(njs_vm_t *vm, const njs_str_t *name);
NJS_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, const njs_str_t *name);
+
NJS_EXPORT njs_value_t *njs_vm_retval(njs_vm_t *vm);
NJS_EXPORT void njs_vm_retval_set(njs_vm_t *vm, const njs_value_t *value);
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_builtin.c
--- a/src/njs_builtin.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_builtin.c Tue Nov 26 15:09:45 2019 +0300
@@ -176,6 +176,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
return NJS_ERROR;
}
+ object->type = NJS_OBJECT;
object->shared = 1;
object->extensible = 1;
@@ -260,13 +261,6 @@ njs_builtin_objects_create(njs_vm_t *vm)
shared->prototypes[NJS_OBJ_TYPE_REGEXP].regexp.pattern =
shared->empty_regexp_pattern;
- string_object = &shared->string_object;
- njs_lvlhsh_init(&string_object->hash);
- string_object->shared_hash = shared->string_instance_hash;
- string_object->type = NJS_OBJECT_STRING;
- string_object->shared = 1;
- string_object->extensible = 0;
-
constructor = shared->constructors;
for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) {
@@ -286,6 +280,16 @@ njs_builtin_objects_create(njs_vm_t *vm)
}
}
+ vm->global_object = shared->objects[0];
+ vm->global_object.shared = 0;
+
+ string_object = &shared->string_object;
+ njs_lvlhsh_init(&string_object->hash);
+ string_object->shared_hash = shared->string_instance_hash;
+ string_object->type = NJS_OBJECT_STRING;
+ string_object->shared = 1;
+ string_object->extensible = 0;
+
vm->shared = shared;
return NJS_OK;
@@ -333,10 +337,7 @@ njs_builtin_objects_clone(njs_vm_t *vm,
vm->constructors[i].object.__proto__ = error_constructor;
}
- vm->global_object = vm->shared->objects[0];
vm->global_object.__proto__ = object_prototype;
- vm->global_object.shared = 0;
-
njs_set_object(global, &vm->global_object);
vm->string_object = vm->shared->string_object;
@@ -452,15 +453,11 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t
static njs_arr_t *
njs_builtin_completions(njs_vm_t *vm)
{
- u_char *compl;
- size_t len;
njs_arr_t *array;
njs_str_t *completion;
njs_int_t ret;
njs_keyword_t *keyword;
- njs_lvlhsh_each_t lhe, lhe_prop;
- njs_extern_value_t *ev;
- const njs_extern_t *ext_proto, *ext_prop;
+ njs_lvlhsh_each_t lhe;
njs_builtin_traverse_t ctx;
const njs_object_prop_t *prop;
@@ -516,63 +513,6 @@ njs_builtin_completions(njs_vm_t *vm)
njs_string_get(&prop->name, completion);
}
- /* Externals completions. */
-
- njs_lvlhsh_each_init(&lhe, &njs_extern_value_hash_proto);
-
- for ( ;; ) {
- ev = njs_lvlhsh_each(&vm->externals_hash, &lhe);
-
- if (ev == NULL) {
- break;
- }
-
- ext_proto = ev->value.external.proto;
-
- njs_lvlhsh_each_init(&lhe_prop, &njs_extern_hash_proto);
-
- len = ev->name.length + 1;
- compl = njs_mp_zalloc(vm->mem_pool, len);
- if (compl == NULL) {
- return NULL;
- }
-
- njs_sprintf(compl, compl + len, "%V%Z", &ev->name);
-
- completion = njs_arr_add(array);
- if (njs_slow_path(completion == NULL)) {
- return NULL;
- }
-
- completion->length = len;
- completion->start = (u_char *) compl;
-
- for ( ;; ) {
- ext_prop = njs_lvlhsh_each(&ext_proto->hash, &lhe_prop);
-
- if (ext_prop == NULL) {
- break;
- }
-
- len = ev->name.length + ev->name.length + 2;
- compl = njs_mp_zalloc(vm->mem_pool, len);
- if (compl == NULL) {
- return NULL;
- }
-
- njs_sprintf(compl, compl + len, "%V.%V%Z", &ev->name,
- &ext_prop->name);
-
- completion = njs_arr_add(array);
- if (njs_slow_path(completion == NULL)) {
- return NULL;
- }
-
- completion->length = len;
- completion->start = (u_char *) compl;
- }
- }
-
return array;
}
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_extern.c
--- a/src/njs_extern.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_extern.c Tue Nov 26 15:09:45 2019 +0300
@@ -31,21 +31,6 @@ njs_extern_hash_test(njs_lvlhsh_query_t
}
-static njs_int_t
-njs_extern_value_hash_test(njs_lvlhsh_query_t *lhq, void *data)
-{
- njs_extern_value_t *ev;
-
- ev = (njs_extern_value_t *) data;
-
- if (njs_strstr_eq(&lhq->key, &ev->name)) {
- return NJS_OK;
- }
-
- return NJS_DECLINED;
-}
-
-
const njs_lvlhsh_proto_t njs_extern_hash_proto
njs_aligned(64) =
{
@@ -56,16 +41,6 @@ const njs_lvlhsh_proto_t njs_extern_has
};
-const njs_lvlhsh_proto_t njs_extern_value_hash_proto
- njs_aligned(64) =
-{
- NJS_LVLHSH_DEFAULT,
- njs_extern_value_hash_test,
- njs_lvlhsh_alloc,
- njs_lvlhsh_free,
-};
-
-
static njs_extern_t *
njs_vm_external_add(njs_vm_t *vm, njs_lvlhsh_t *hash, njs_external_t *external,
njs_uint_t n)
@@ -215,45 +190,6 @@ njs_vm_external_create(njs_vm_t *vm, njs
}
-njs_int_t
-njs_vm_external_bind(njs_vm_t *vm, const njs_str_t *var_name,
- const njs_value_t *value)
-{
- njs_int_t ret;
- njs_extern_value_t *ev;
- njs_lvlhsh_query_t lhq;
-
- if (njs_slow_path(!njs_is_external(value))) {
- return NJS_ERROR;
- }
-
- ev = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
- sizeof(njs_extern_value_t));
- if (njs_slow_path(ev == NULL)) {
- njs_memory_error(vm);
- return NJS_ERROR;
- }
-
- ev->value = *value;
- ev->name = *var_name;
-
- lhq.key = *var_name;
- lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length);
- lhq.proto = &njs_extern_value_hash_proto;
- lhq.value = ev;
- lhq.replace = 0;
- lhq.pool = vm->mem_pool;
-
- ret = njs_lvlhsh_insert(&vm->externals_hash, &lhq);
- if (njs_slow_path(ret != NJS_OK)) {
- njs_internal_error(vm, "lvlhsh insert failed");
- return ret;
- }
-
- return NJS_OK;
-}
-
-
njs_external_ptr_t
njs_vm_external(njs_vm_t *vm, const njs_value_t *value)
{
@@ -321,25 +257,6 @@ njs_extern_keys_array(njs_vm_t *vm, cons
}
-njs_value_t *
-njs_external_lookup(njs_vm_t *vm, njs_str_t *name, uint32_t hash)
-{
- njs_lvlhsh_query_t lhq;
- njs_extern_value_t *ev;
-
- lhq.key_hash = hash;
- lhq.key = *name;
- lhq.proto = &njs_extern_value_hash_proto;
-
- if (njs_lvlhsh_find(&vm->externals_hash, &lhq) == NJS_OK) {
- ev = (njs_extern_value_t *) lhq.value;
- return &ev->value;
- }
-
- return NULL;
-}
-
-
static njs_int_t
njs_external_match(njs_vm_t *vm, njs_function_native_t func, njs_extern_t *ext,
njs_str_t *name, njs_extern_part_t *head, njs_extern_part_t *ppart)
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_extern.h
--- a/src/njs_extern.h Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_extern.h Tue Nov 26 15:09:45 2019 +0300
@@ -41,13 +41,11 @@ typedef struct {
njs_array_t *njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external);
-njs_value_t *njs_external_lookup(njs_vm_t *vm, njs_str_t *name, uint32_t hash);
njs_int_t njs_external_match_native_function(njs_vm_t *vm,
njs_function_native_t func, njs_str_t *name);
extern const njs_lvlhsh_proto_t njs_extern_hash_proto;
-extern const njs_lvlhsh_proto_t njs_extern_value_hash_proto;
#endif /* _NJS_EXTERN_H_INCLUDED_ */
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_parser_terminal.c
--- a/src/njs_parser_terminal.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_parser_terminal.c Tue Nov 26 15:09:45 2019 +0300
@@ -203,7 +203,6 @@ njs_parser_reference(njs_vm_t *vm, njs_p
njs_str_t *name, uint32_t hash, uint32_t token_line)
{
njs_int_t ret;
- njs_value_t *ext;
njs_variable_t *var;
njs_parser_node_t *node;
njs_parser_scope_t *scope;
@@ -291,15 +290,6 @@ njs_parser_reference(njs_vm_t *vm, njs_p
node->token_line = token_line;
- ext = njs_external_lookup(vm, name, hash);
-
- if (ext != NULL) {
- node->token = NJS_TOKEN_EXTERNAL;
- node->u.value = *ext;
- node->index = (njs_index_t) ext;
- break;
- }
-
ret = njs_variable_reference(vm, parser->scope, node, name, hash,
NJS_REFERENCE);
if (njs_slow_path(ret != NJS_OK)) {
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_shell.c
--- a/src/njs_shell.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_shell.c Tue Nov 26 15:09:45 2019 +0300
@@ -613,28 +613,28 @@ njs_externals_init(njs_vm_t *vm, njs_con
static const njs_str_t name = njs_str("console");
proto = njs_vm_external_prototype(vm, &njs_externals[0]);
- if (proto == NULL) {
+ if (njs_slow_path(proto == NULL)) {
njs_stderror("failed to add console proto\n");
return NJS_ERROR;
}
value = njs_mp_zalloc(vm->mem_pool, sizeof(njs_opaque_value_t));
- if (value == NULL) {
+ if (njs_slow_path(value == NULL)) {
return NJS_ERROR;
}
ret = njs_vm_external_create(vm, value, proto, console);
- if (ret != NJS_OK) {
+ if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
- ret = njs_vm_external_bind(vm, &name, value);
- if (ret != NJS_OK) {
+ ret = njs_vm_bind(vm, &name, value, 1);
+ if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
ret = njs_console_init(vm, console);
- if (ret != NJS_OK) {
+ if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_variable.c
--- a/src/njs_variable.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_variable.c Tue Nov 26 15:09:45 2019 +0300
@@ -683,12 +683,6 @@ njs_vm_value(njs_vm_t *vm, const njs_str
return njs_vmcode_operand(vm, ((njs_variable_t *) lhq.value)->index);
}
- lhq.proto = &njs_extern_value_hash_proto;
-
- if (njs_lvlhsh_find(&vm->externals_hash, &lhq) == NJS_OK) {
- return &((njs_extern_value_t *) lhq.value)->value;
- }
-
return &njs_value_undefined;
}
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_vm.c
--- a/src/njs_vm.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_vm.c Tue Nov 26 15:09:45 2019 +0300
@@ -65,7 +65,6 @@ njs_vm_create(njs_vm_opt_t *options)
return NULL;
}
- njs_lvlhsh_init(&vm->externals_hash);
njs_lvlhsh_init(&vm->external_prototypes_hash);
vm->trace.level = NJS_LEVEL_TRACE;
@@ -570,6 +569,46 @@ njs_vm_retval_set(njs_vm_t *vm, const nj
njs_int_t
+njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name, const njs_value_t *value,
+ njs_bool_t shared)
+{
+ njs_int_t ret;
+ njs_object_t *global;
+ njs_lvlhsh_t *hash;
+ njs_object_prop_t *prop;
+ njs_lvlhsh_query_t lhq;
+
+ prop = njs_object_prop_alloc(vm, &njs_value_undefined, value, 1);
+ if (njs_slow_path(prop == NULL)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_string_new(vm, &prop->name, var_name->start, var_name->length, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ lhq.value = prop;
+ lhq.key = *var_name;
+ lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length);
+ lhq.replace = 1;
+ lhq.pool = vm->mem_pool;
+ lhq.proto = &njs_object_hash_proto;
+
+ global = &vm->global_object;
+ hash = shared ? &global->shared_hash : &global->hash;
+
+ ret = njs_lvlhsh_insert(hash, &lhq);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return ret;
+ }
+
+ return NJS_OK;
+}
+
+
+njs_int_t
njs_vm_value_string_set(njs_vm_t *vm, njs_value_t *value, const u_char *start,
uint32_t size)
{
diff -r 8a41cab86cc2 -r 68c9971d7366 src/njs_vm.h
--- a/src/njs_vm.h Tue Nov 26 15:01:02 2019 +0300
+++ b/src/njs_vm.h Tue Nov 26 15:09:45 2019 +0300
@@ -175,7 +175,6 @@ struct njs_vm_s {
njs_arr_t *external_objects; /* of njs_external_ptr_t */
- njs_lvlhsh_t externals_hash;
njs_lvlhsh_t external_prototypes_hash;
njs_lvlhsh_t variables_hash;
diff -r 8a41cab86cc2 -r 68c9971d7366 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Tue Nov 26 15:01:02 2019 +0300
+++ b/src/test/njs_unit_test.c Tue Nov 26 15:09:45 2019 +0300
@@ -9352,8 +9352,17 @@ static njs_unit_test_t njs_test[] =
{ njs_str("Object.getOwnPropertyNames(this).includes('NaN')"),
njs_str("true") },
- { njs_str("Object.keys(this)"),
- njs_str("njs,process") },
+ { njs_str("Object.keys(this).sort()"),
+ njs_str("$r,$r2,$r3,njs,process") },
+
+ { njs_str("var r = njs.dump(this); "
+ "['$r', 'global', njs.version].every(v=>r.includes(v))"),
+ njs_str("true") },
+
+ { njs_str("var r = JSON.stringify(this); "
+ "['$r', njs.version].every(v=>r.includes(v))"),
+ njs_str("true") },
+
{ njs_str("this.a = 1; this.a"),
njs_str("1") },
@@ -13842,9 +13851,6 @@ static njs_unit_test_t njs_test[] =
{ njs_str("this.njs = 1; njs"),
njs_str("1") },
- { njs_str("njs.dump(this) === `global {njs:njs {version:'${njs.version}'},process:process {}}`"),
- njs_str("true") },
-
{ njs_str("process === process"),
njs_str("true") },
@@ -15233,6 +15239,15 @@ static njs_unit_test_t njs_shared_test[
{ njs_str("var r; for (var i = 0; i < 2**10; i++) {r = $r.create('XXX').uri;}"),
njs_str("undefined") },
+
+ { njs_str("delete $r3.vars.p; $r3.vars.p"),
+ njs_str("undefined") },
+
+ { njs_str("var sr = $r.create('XXX'); sr.vars.p = 'a'; sr.vars.p"),
+ njs_str("a") },
+
+ { njs_str("$r.bind('XXX', 37); XXX"),
+ njs_str("37") },
};
@@ -15793,6 +15808,26 @@ memory_error:
}
+static njs_int_t
+njs_unit_test_bind_external(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t unused)
+{
+ njs_str_t name;
+ njs_unit_test_req_t *r;
+
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (njs_slow_path(r == NULL)) {
+ return NJS_ERROR;
+ }
+
+ if (njs_vm_value_to_string(vm, &name, njs_arg(args, nargs, 1)) != NJS_OK) {
+ return NJS_ERROR;
+ }
+
+ return njs_vm_bind(vm, &name, njs_arg(args, nargs, 2), 0);
+}
+
+
static njs_external_t njs_unit_test_r_props[] = {
{ njs_str("a"),
@@ -15909,6 +15944,17 @@ static njs_external_t njs_unit_test_r_e
njs_unit_test_create_external,
0 },
+ { njs_str("bind"),
+ NJS_EXTERN_METHOD,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ njs_unit_test_bind_external,
+ 0 },
+
};
@@ -15982,15 +16028,14 @@ njs_externals_init(njs_vm_t *vm)
njs_unit_test_prop_t *prop;
proto = njs_vm_external_prototype(vm, &njs_test_external[0]);
- if (proto == NULL) {
+ if (njs_slow_path(proto == NULL)) {
njs_printf("njs_vm_external_prototype() failed\n");
return NJS_ERROR;
}
- requests = njs_mp_zalloc(vm->mem_pool,
- njs_nitems(njs_test_requests)
+ requests = njs_mp_zalloc(vm->mem_pool, njs_nitems(njs_test_requests)
* sizeof(njs_unit_test_req_t));
- if (requests == NULL) {
+ if (njs_slow_path(requests == NULL)) {
return NJS_ERROR;
}
@@ -16002,15 +16047,15 @@ njs_externals_init(njs_vm_t *vm)
ret = njs_vm_external_create(vm, njs_value_arg(&requests[i].value),
proto, &requests[i]);
- if (ret != NJS_OK) {
+ if (njs_slow_path(ret != NJS_OK)) {
njs_printf("njs_vm_external_create() failed\n");
return NJS_ERROR;
}
- ret = njs_vm_external_bind(vm, &njs_test_requests[i].name,
- njs_value_arg(&requests[i].value));
- if (ret != NJS_OK) {
- njs_printf("njs_vm_external_bind() failed\n");
+ ret = njs_vm_bind(vm, &njs_test_requests[i].name,
+ njs_value_arg(&requests[i].value), 1);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_printf("njs_vm_bind() failed\n");
return NJS_ERROR;
}
@@ -16019,13 +16064,13 @@ njs_externals_init(njs_vm_t *vm)
&njs_test_requests[i].props[j].name,
&njs_test_requests[i].props[j].value);
- if (prop == NULL) {
+ if (njs_slow_path(prop == NULL)) {
njs_printf("lvlhsh_unit_test_alloc() failed\n");
return NJS_ERROR;
}
ret = lvlhsh_unit_test_add(&requests[i], prop);
- if (ret != NJS_OK) {
+ if (njs_slow_path(ret != NJS_OK)) {
njs_printf("lvlhsh_unit_test_add() failed\n");
return NJS_ERROR;
}
diff -r 8a41cab86cc2 -r 68c9971d7366 test/njs_expect_test.exp
--- a/test/njs_expect_test.exp Tue Nov 26 15:01:02 2019 +0300
+++ b/test/njs_expect_test.exp Tue Nov 26 15:09:45 2019 +0300
@@ -87,10 +87,13 @@ njs_test {
"Ma\a*th"}
}
-njs_test {
- {"conso\t"
- "conso\a*le"}
-}
+# FIXME: completions for external objects
+# are not supported
+
+# njs_test {
+# {"conso\t"
+# "conso\a*le"}
+# }
# Global completions, multiple partial match
njs_test {
More information about the nginx-devel
mailing list