[njs] njs_vm_call() interface to call a function outside.
Igor Sysoev
igor at sysoev.ru
Wed Mar 2 12:35:49 UTC 2016
details: http://hg.nginx.com/njs/rev/0dce9318807a
branches:
changeset: 82:0dce9318807a
user: Igor Sysoev <igor at sysoev.ru>
date: Wed Mar 02 15:10:28 2016 +0300
description:
njs_vm_call() interface to call a function outside.
nginx content and variable handlers interface is
function name(request, response) { ... }
Variable handler use a value returned by function as value of the variable.
diffstat:
nginx/ngx_http_js_module.c | 238 +++++++++++++++++++++++++++-----------------
njs/njs_extern.c | 41 +++++++
njs/njs_generator.c | 3 +
njs/njs_parser.c | 8 +-
njs/njs_parser.h | 1 +
njs/njs_vm.h | 11 +-
njs/njscript.c | 55 ++++++++++-
njs/njscript.h | 12 ++-
njs/test/njs_unit_test.c | 30 ++++-
9 files changed, 292 insertions(+), 107 deletions(-)
diffs (715 lines):
diff -r 36541f3695b6 -r 0dce9318807a nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Thu Feb 25 16:32:47 2016 +0300
+++ b/nginx/ngx_http_js_module.c Wed Mar 02 15:10:28 2016 +0300
@@ -32,19 +32,28 @@
typedef struct {
- njs_vm_t *vm;
+ njs_vm_t *vm;
+ njs_function_t *function;
+ njs_opaque_value_t args[2];
+} ngx_http_js_ctx_t;
+
+
+typedef struct {
+ ngx_http_js_ctx_t js;
} ngx_http_js_loc_conf_t;
typedef struct {
- ngx_list_part_t *part;
- ngx_uint_t item;
+ ngx_list_part_t *part;
+ ngx_uint_t item;
} ngx_http_js_table_entry_t;
static ngx_int_t ngx_http_js_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_js_vm_run(ngx_http_request_t *r,
+ ngx_http_js_ctx_t *js, nxt_str_t *value);
static void ngx_http_js_cleanup_mem_cache_pool(void *data);
static void *ngx_http_js_alloc(void *mem, size_t size);
@@ -99,7 +108,8 @@ static njs_ret_t ngx_http_js_ext_next_ar
static char *ngx_http_js_run(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static njs_vm_t *ngx_http_js_compile(ngx_conf_t *cf, ngx_str_t *script);
+static char *ngx_http_js_compile(ngx_conf_t *cf, ngx_http_js_ctx_t *jctx,
+ ngx_str_t *script);
static void *ngx_http_js_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);
@@ -362,15 +372,70 @@ static njs_external_t ngx_http_js_exter
static ngx_int_t
ngx_http_js_handler(ngx_http_request_t *r)
{
- nxt_str_t value;
- njs_vm_t *nvm;
- ngx_pool_cleanup_t *cln;
- nxt_mem_cache_pool_t *mcp;
+ ngx_int_t rc;
ngx_http_js_loc_conf_t *jlcf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http js handler");
+ jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module);
+
+ rc = ngx_http_js_vm_run(r, &jlcf->js, NULL);
+
+ if (rc == NGX_OK) {
+ return rc;
+ }
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
+ uintptr_t data)
+{
+ ngx_http_js_ctx_t *js = (ngx_http_js_ctx_t *) data;
+
+ ngx_int_t rc;
+ nxt_str_t value;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http js variable handler");
+
+ rc = ngx_http_js_vm_run(r, js, &value);
+
+ if (rc == NXT_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (rc == NGX_OK) {
+ v->len = value.len;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = value.data;
+
+ } else {
+ v->not_found = 1;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http js variable done");
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_js_vm_run(ngx_http_request_t *r, ngx_http_js_ctx_t *js,
+ nxt_str_t *value)
+{
+ njs_vm_t *nvm;
+ nxt_int_t ret;
+ nxt_str_t exception;
+ ngx_pool_cleanup_t *cln;
+ nxt_mem_cache_pool_t *mcp;
+
mcp = ngx_http_js_create_mem_cache_pool();
if (mcp == NULL) {
return NGX_ERROR;
@@ -384,85 +449,39 @@ ngx_http_js_handler(ngx_http_request_t *
cln->handler = ngx_http_js_cleanup_mem_cache_pool;
cln->data = mcp;
- jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module);
-
- nvm = njs_vm_clone(jlcf->vm, mcp, (void **) &r);
+ nvm = njs_vm_clone(js->vm, mcp, (void **) &r);
if (nvm == NULL) {
return NGX_ERROR;
}
- if (njs_vm_run(nvm) != NJS_OK) {
- njs_vm_exception(nvm, &value);
+ if (js->function) {
+ ret = njs_vm_call(nvm, js->function, js->args, 2);
+
+ } else {
+ ret = njs_vm_run(nvm);
+ }
+
+ if (ret == NJS_OK) {
+
+ if (value != NULL) {
+ if (njs_vm_retval(nvm, value) != NJS_OK) {
+ return NGX_ERROR;
+ }
+ }
+
+ } else {
+ njs_vm_exception(nvm, &exception);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "js exception: %*s", value.len, value.data);
+ "js exception: %*s", exception.len, exception.data);
- return NGX_ERROR;
+ return NGX_DECLINED;
}
return NGX_OK;
}
-static ngx_int_t
-ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- njs_vm_t *vm = (njs_vm_t *) data;
-
- nxt_str_t value;
- njs_vm_t *nvm;
- ngx_pool_cleanup_t *cln;
- nxt_mem_cache_pool_t *mcp;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http js variable handler");
-
- mcp = ngx_http_js_create_mem_cache_pool();
- if (mcp == NULL) {
- return NGX_ERROR;
- }
-
- cln = ngx_pool_cleanup_add(r->pool, 0);
- if (cln == NULL) {
- return NGX_ERROR;
- }
-
- cln->handler = ngx_http_js_cleanup_mem_cache_pool;
- cln->data = mcp;
-
- nvm = njs_vm_clone(vm, mcp, (void **) &r);
- if (nvm == NULL) {
- return NGX_ERROR;
- }
-
- if (njs_vm_run(nvm) == NJS_OK) {
- if (njs_vm_retval(nvm, &value) != NJS_OK) {
- return NGX_ERROR;
- }
-
- v->len = value.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = value.data;
-
- } else {
- njs_vm_exception(nvm, &value);
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "js exception: %*s", value.len, value.data);
-
- v->not_found = 1;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http js variable done");
-
- return NGX_OK;
-}
-
-
static void
ngx_http_js_cleanup_mem_cache_pool(void *data)
{
@@ -1046,20 +1065,21 @@ ngx_http_js_run(ngx_conf_t *cf, ngx_comm
{
ngx_http_js_loc_conf_t *jlcf = conf;
+ char *ret;
ngx_str_t *value;
ngx_http_core_loc_conf_t *clcf;
value = cf->args->elts;
- if (jlcf->vm) {
+ if (jlcf->js.vm) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"duplicate js handler \"%V\"", &value[1]);
return NGX_CONF_ERROR;
}
- jlcf->vm = ngx_http_js_compile(cf, &value[1]);
- if (jlcf->vm == NULL) {
- return NGX_CONF_ERROR;
+ ret = ngx_http_js_compile(cf, &jlcf->js, &value[1]);
+ if (ret != NGX_CONF_OK) {
+ return ret;
}
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
@@ -1072,8 +1092,9 @@ ngx_http_js_run(ngx_conf_t *cf, ngx_comm
static char *
ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- njs_vm_t *vm;
+ char *ret;
ngx_str_t *value;
+ ngx_http_js_ctx_t *js;
ngx_http_variable_t *v;
value = cf->args->elts;
@@ -1092,32 +1113,38 @@ ngx_http_js_set(ngx_conf_t *cf, ngx_comm
return NGX_CONF_ERROR;
}
- vm = ngx_http_js_compile(cf, &value[2]);
- if (vm == NULL) {
+ js = ngx_palloc(cf->pool, sizeof(ngx_http_js_ctx_t));
+ if (js == NULL) {
return NGX_CONF_ERROR;
}
+ ret = ngx_http_js_compile(cf, js, &value[2]);
+ if (ret != NGX_CONF_OK) {
+ return ret;
+ }
+
v->get_handler = ngx_http_js_variable;
- v->data = (uintptr_t) vm;
+ v->data = (uintptr_t) js;
return NGX_CONF_OK;
}
-static njs_vm_t *
-ngx_http_js_compile(ngx_conf_t *cf, ngx_str_t *script)
+static char *
+ngx_http_js_compile(ngx_conf_t *cf, ngx_http_js_ctx_t *js, ngx_str_t *script)
{
u_char *start, *end;
nxt_int_t rc;
- nxt_str_t s;
+ nxt_str_t s, name;
njs_vm_t *vm;
nxt_lvlhsh_t externals;
+ njs_function_t *function;
njs_vm_shared_t *shared;
nxt_mem_cache_pool_t *mcp;
mcp = ngx_http_js_create_mem_cache_pool();
if (mcp == NULL) {
- return NULL;
+ return NGX_CONF_ERROR;
}
shared = NULL;
@@ -1129,35 +1156,58 @@ ngx_http_js_compile(ngx_conf_t *cf, ngx_
!= NJS_OK)
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals");
- return NULL;
+ return NGX_CONF_ERROR;
}
vm = njs_vm_create(mcp, &shared, &externals);
if (vm == NULL) {
- return NULL;
+ return NGX_CONF_ERROR;
}
start = script->data;
end = start + script->len;
- rc = njs_vm_compile(vm, &start, end);
+ rc = njs_vm_compile(vm, &start, end, &function);
if (rc != NJS_OK) {
njs_vm_exception(vm, &s);
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"js compilation error: \"%*s\"", s.len, s.data);
- return NULL;
+ return NGX_CONF_ERROR;
}
if (start != end) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"extra characters in js script: \"%*s\"",
end - start, start);
- return NULL;
+ return NGX_CONF_ERROR;
}
- return vm;
+ js->vm = vm;
+ js->function = function;
+
+ if (function) {
+ ngx_str_set(&name, "$r");
+
+ rc = njs_external_get(vm, NULL, &name, &js->args[0]);
+ if (rc != NXT_OK) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "could not get $r external");
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_str_set(&name, "response");
+
+ rc = njs_external_get(vm, &js->args[0], &name, &js->args[1]);
+ if (rc != NXT_OK) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "could not get $r.response external");
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ return NGX_CONF_OK;
}
@@ -1187,8 +1237,8 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *c
ngx_http_js_loc_conf_t *prev = parent;
ngx_http_js_loc_conf_t *conf = child;
- if (conf->vm == NULL) {
- conf->vm = prev->vm;
+ if (conf->js.vm == NULL) {
+ conf->js = prev->js;
}
return NGX_CONF_OK;
diff -r 36541f3695b6 -r 0dce9318807a njs/njs_extern.c
--- a/njs/njs_extern.c Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njs_extern.c Wed Mar 02 15:10:28 2016 +0300
@@ -126,6 +126,47 @@ njs_add_external(nxt_lvlhsh_t *hash, nxt
}
+nxt_int_t
+njs_external_get(njs_vm_t *vm, njs_opaque_value_t *obj, nxt_str_t *property,
+ njs_opaque_value_t *value)
+{
+ uint32_t (*key_hash)(const void *, size_t);
+ njs_value_t *object;
+ njs_extern_t *ext;
+ nxt_lvlhsh_t hash;
+ nxt_lvlhsh_query_t lhq;
+
+ object = (njs_value_t *) obj;
+
+ key_hash = nxt_djb_hash;
+ hash = vm->externals_hash;
+
+ if (object != NULL) {
+ if (!njs_is_external(object)) {
+ return NXT_ERROR;
+ }
+
+ ext = object->data.u.external;
+ hash = ext->hash;
+
+ if (ext->type == NJS_EXTERN_CASELESS_OBJECT) {
+ key_hash = nxt_djb_hash_lowcase;
+ }
+ }
+
+ lhq.key_hash = key_hash(property->data, property->len);
+ lhq.key = *property;
+ lhq.proto = &njs_extern_hash_proto;
+
+ if (nxt_lvlhsh_find(&hash, &lhq) == NXT_OK) {
+ *value = *(njs_opaque_value_t *) lhq.value;
+ return NXT_OK;
+ }
+
+ return NXT_ERROR;
+}
+
+
njs_extern_t *
njs_parser_external(njs_vm_t *vm, njs_parser_t *parser)
{
diff -r 36541f3695b6 -r 0dce9318807a njs/njs_generator.c
--- a/njs/njs_generator.c Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njs_generator.c Wed Mar 02 15:10:28 2016 +0300
@@ -163,6 +163,9 @@ njs_generator(njs_vm_t *vm, njs_parser_t
case NJS_TOKEN_END:
return njs_generate_stop_statement(vm, parser, node);
+ case NJS_TOKEN_CALL:
+ return njs_generate_children(vm, parser, node);
+
case NJS_TOKEN_COMMA:
return njs_generate_comma_expression(vm, parser, node);
diff -r 36541f3695b6 -r 0dce9318807a njs/njs_parser.c
--- a/njs/njs_parser.c Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njs_parser.c Wed Mar 02 15:10:28 2016 +0300
@@ -99,7 +99,13 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p
node = parser->node;
- if (node == NULL) {
+ if (node != NULL && node->right != NULL) {
+ if (node->right->token == NJS_TOKEN_FUNCTION) {
+ node->token = NJS_TOKEN_CALL;
+ return node;
+ }
+
+ } else {
/* Empty string, just semicolons or variables declarations. */
node = njs_parser_node_alloc(vm);
diff -r 36541f3695b6 -r 0dce9318807a njs/njs_parser.h
--- a/njs/njs_parser.h Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njs_parser.h Wed Mar 02 15:10:28 2016 +0300
@@ -14,6 +14,7 @@ typedef enum {
NJS_TOKEN_ILLEGAL = 0,
NJS_TOKEN_END,
+ NJS_TOKEN_CALL,
NJS_TOKEN_SPACE,
NJS_TOKEN_LINE_END,
diff -r 36541f3695b6 -r 0dce9318807a njs/njs_vm.h
--- a/njs/njs_vm.h Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njs_vm.h Wed Mar 02 15:10:28 2016 +0300
@@ -130,7 +130,7 @@ struct njs_object_s {
#define NJS_ARGS_TYPES_MAX 3
-typedef struct {
+struct njs_function_s {
njs_object_t object;
uint8_t args_types[NJS_ARGS_TYPES_MAX];
@@ -158,7 +158,7 @@ typedef struct {
} u;
njs_value_t *bound;
-} njs_function_t;
+};
typedef struct njs_continuation_s njs_continuation_t;
@@ -684,10 +684,10 @@ enum njs_functions_e {
#define njs_scope_index(value) \
- ((njs_index_t) (value << NJS_SCOPE_SHIFT))
+ ((njs_index_t) ((value) << NJS_SCOPE_SHIFT))
#define njs_global_scope_index(value) \
- ((njs_index_t) ((value << NJS_SCOPE_SHIFT) | NJS_SCOPE_GLOBAL))
+ ((njs_index_t) (((value) << NJS_SCOPE_SHIFT) | NJS_SCOPE_GLOBAL))
#define NJS_INDEX_OBJECT njs_global_scope_index(NJS_FUNCTION_OBJECT)
@@ -699,7 +699,8 @@ enum njs_functions_e {
#define NJS_INDEX_REGEXP njs_global_scope_index(NJS_FUNCTION_REGEXP)
#define NJS_INDEX_EVAL njs_global_scope_index(NJS_FUNCTION_EVAL)
-#define NJS_INDEX_GLOBAL_OFFSET njs_scope_index(NJS_FUNCTION_MAX)
+#define NJS_INDEX_GLOBAL_RETVAL njs_global_scope_index(NJS_FUNCTION_MAX)
+#define NJS_INDEX_GLOBAL_OFFSET njs_scope_index(NJS_FUNCTION_MAX + 1)
#define njs_offset(index) \
diff -r 36541f3695b6 -r 0dce9318807a njs/njscript.c
--- a/njs/njscript.c Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njscript.c Wed Mar 02 15:10:28 2016 +0300
@@ -167,10 +167,12 @@ njs_vm_destroy(njs_vm_t *vm)
nxt_int_t
-njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end)
+njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end,
+ njs_function_t **function)
{
nxt_int_t ret;
njs_lexer_t *lexer;
+ njs_value_t *value;
njs_parser_t *parser;
njs_parser_node_t *node;
@@ -216,6 +218,16 @@ njs_vm_compile(njs_vm_t *vm, u_char **st
return NJS_ERROR;
}
+ if (function != NULL) {
+ if (node->token == NJS_TOKEN_CALL) {
+ value = njs_variable_value(parser, node->right->index);
+ *function = value->data.u.function;
+
+ } else {
+ *function = NULL;
+ }
+ }
+
*start = parser->lexer->start;
ret = njs_generate_scope(vm, parser, node);
@@ -318,6 +330,47 @@ fail:
nxt_int_t
+njs_vm_call(njs_vm_t *vm, njs_function_t *function, njs_opaque_value_t *args,
+ nxt_uint_t nargs)
+{
+ u_char *current;
+ njs_ret_t ret;
+ njs_value_t *this;
+
+ static const njs_vmcode_stop_t stop[] = {
+ { .code = { .operation = njs_vmcode_stop,
+ .operands = NJS_VMCODE_1OPERAND,
+ .retval = NJS_VMCODE_NO_RETVAL },
+ .retval = NJS_INDEX_GLOBAL_RETVAL },
+ };
+
+ this = (njs_value_t *) &njs_value_void;
+
+ ret = njs_function_frame(vm, function, this,
+ (njs_value_t *) args, nargs, 0);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ current = vm->current;
+ vm->current = (u_char *) stop;
+
+ (void) njs_function_call(vm, NJS_INDEX_GLOBAL_RETVAL, 0);
+
+ ret = njs_vmcode_interpreter(vm);
+
+ vm->current = current;
+
+ if (ret == NJS_STOP) {
+ ret = NXT_OK;
+ }
+
+ return ret;
+}
+
+
+nxt_int_t
njs_vm_run(njs_vm_t *vm)
{
nxt_str_t s;
diff -r 36541f3695b6 -r 0dce9318807a njs/njscript.h
--- a/njs/njscript.h Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/njscript.h Wed Mar 02 15:10:28 2016 +0300
@@ -12,8 +12,13 @@ typedef intptr_t njs_
typedef uintptr_t njs_index_t;
typedef struct njs_vm_s njs_vm_t;
typedef union njs_value_s njs_value_t;
+typedef struct njs_function_s njs_function_t;
typedef struct njs_vm_shared_s njs_vm_shared_t;
+typedef struct {
+ uint64_t filler[2];
+} njs_opaque_value_t;
+
/* sizeof(njs_value_t) is 16 bytes. */
#define njs_argument(args, n) \
@@ -71,14 +76,19 @@ struct njs_external_s {
NXT_EXPORT nxt_int_t njs_add_external(nxt_lvlhsh_t *hash,
nxt_mem_cache_pool_t *mcp, uintptr_t object, njs_external_t *external,
nxt_uint_t n);
+NXT_EXPORT nxt_int_t njs_external_get(njs_vm_t *vm, njs_opaque_value_t *object,
+ nxt_str_t *property, njs_opaque_value_t *value);
NXT_EXPORT njs_vm_t *njs_vm_create(nxt_mem_cache_pool_t *mcp,
njs_vm_shared_t **shared, nxt_lvlhsh_t *externals);
NXT_EXPORT void njs_vm_destroy(njs_vm_t *vm);
-NXT_EXPORT nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end);
+NXT_EXPORT nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end,
+ njs_function_t **function);
NXT_EXPORT njs_vm_t *njs_vm_clone(njs_vm_t *vm, nxt_mem_cache_pool_t *mcp,
void **external);
+NXT_EXPORT nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function,
+ njs_opaque_value_t *args, nxt_uint_t nargs);
NXT_EXPORT nxt_int_t njs_vm_run(njs_vm_t *vm);
NXT_EXPORT njs_ret_t njs_vm_return_string(njs_vm_t *vm, u_char *start,
diff -r 36541f3695b6 -r 0dce9318807a njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Feb 25 16:32:47 2016 +0300
+++ b/njs/test/njs_unit_test.c Wed Mar 02 15:10:28 2016 +0300
@@ -3899,6 +3899,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("eval()"),
nxt_string("") },
+ { nxt_string("function f(req) { return req.uri }"),
+ nxt_string("АБВ") },
+
/* Trick: number to boolean. */
{ nxt_string("var a = 0; !!a"),
@@ -4192,12 +4195,14 @@ njs_unit_test(nxt_bool_t disassemble)
u_char *start;
njs_vm_t *vm, *nvm;
nxt_int_t ret;
- nxt_str_t s;
+ nxt_str_t s, r_name;
nxt_uint_t i;
nxt_bool_t success;
nxt_lvlhsh_t externals;
+ njs_function_t *function;
njs_vm_shared_t *shared;
njs_unit_test_req r;
+ njs_opaque_value_t value;
nxt_mem_cache_pool_t *mcp;
shared = NULL;
@@ -4230,7 +4235,8 @@ njs_unit_test(nxt_bool_t disassemble)
start = njs_test[i].script.data;
- ret = njs_vm_compile(vm, &start, start + njs_test[i].script.len);
+ ret = njs_vm_compile(vm, &start, start + njs_test[i].script.len,
+ &function);
if (ret == NXT_OK) {
if (disassemble) {
@@ -4245,8 +4251,22 @@ njs_unit_test(nxt_bool_t disassemble)
r.uri.len = 6;
r.uri.data = (u_char *) "АБВ";
- if (njs_vm_run(nvm) == NXT_OK) {
-
+ if (function != NULL) {
+ r_name.len = 2;
+ r_name.data = (u_char *) "$r";
+
+ ret = njs_external_get(vm, NULL, &r_name, &value);
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ ret = njs_vm_call(nvm, function, &value, 1);
+
+ } else {
+ ret = njs_vm_run(nvm);
+ }
+
+ if (ret == NXT_OK) {
if (njs_vm_retval(nvm, &s) != NXT_OK) {
return NXT_ERROR;
}
@@ -4329,7 +4349,7 @@ njs_unit_test_benchmark(nxt_str_t *scrip
start = script->data;
- ret = njs_vm_compile(vm, &start, start + script->len);
+ ret = njs_vm_compile(vm, &start, start + script->len, NULL);
if (ret != NXT_OK) {
return NXT_ERROR;
}
More information about the nginx-devel
mailing list