[njs] Fixed applying call() to methods of external values.
Dmitry Volyntsev
xeioex at nginx.com
Mon Jul 30 17:00:51 UTC 2018
details: http://hg.nginx.org/njs/rev/5f00966ffff8
branches:
changeset: 574:5f00966ffff8
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Jul 30 20:00:31 2018 +0300
description:
Fixed applying call() to methods of external values.
This correctly fixes #20 on Github.
diffstat:
nginx/ngx_http_js_module.c | 38 ++++++++++++---
nginx/ngx_stream_js_module.c | 8 ++-
njs/njs.h | 4 +-
njs/njs_extern.c | 15 +++++-
njs/njs_vm.c | 9 +--
njs/test/njs_unit_test.c | 107 ++++++++++++++++++++++--------------------
6 files changed, 112 insertions(+), 69 deletions(-)
diffs (329 lines):
diff -r 8840fd0ff685 -r 5f00966ffff8 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Mon Jul 30 20:00:20 2018 +0300
+++ b/nginx/ngx_http_js_module.c Mon Jul 30 20:00:31 2018 +0300
@@ -1256,7 +1256,10 @@ ngx_http_js_ext_send_header(njs_vm_t *vm
{
ngx_http_request_t *r;
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
if (ngx_http_send_header(r) == NGX_ERROR) {
return NJS_ERROR;
@@ -1278,7 +1281,10 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v
ngx_chain_t *out, *cl, **ll;
ngx_http_request_t *r;
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
out = NULL;
ll = &out;
@@ -1343,7 +1349,10 @@ ngx_http_js_ext_finish(njs_vm_t *vm, njs
ngx_http_js_ctx_t *ctx;
ngx_http_request_t *r;
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
if (ngx_http_send_special(r, NGX_HTTP_LAST) == NGX_ERROR) {
return NJS_ERROR;
@@ -1399,7 +1408,10 @@ ngx_http_js_ext_return(njs_vm_t *vm, njs
}
}
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_argument(args, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
@@ -1437,7 +1449,10 @@ ngx_http_js_ext_internal_redirect(njs_vm
return NJS_ERROR;
}
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_argument(args, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
@@ -1495,10 +1510,14 @@ ngx_http_js_ext_log_core(njs_vm_t *vm, n
ngx_log_handler_pt handler;
ngx_http_request_t *r;
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
+
c = r->connection;
- if (njs_vm_value_to_ext_string(vm, &msg, njs_argument(args, 1), 0)
+ if (njs_vm_value_to_ext_string(vm, &msg, njs_arg(args, nargs, 1), 0)
== NJS_ERROR)
{
return NJS_ERROR;
@@ -1874,7 +1893,10 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm,
return NJS_ERROR;
}
- r = njs_value_data(njs_argument(args, 0));
+ r = njs_vm_external(vm, njs_argument(args, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
diff -r 8840fd0ff685 -r 5f00966ffff8 nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Mon Jul 30 20:00:20 2018 +0300
+++ b/nginx/ngx_stream_js_module.c Mon Jul 30 20:00:31 2018 +0300
@@ -886,10 +886,14 @@ ngx_stream_js_ext_log_core(njs_vm_t *vm,
ngx_log_handler_pt handler;
ngx_stream_session_t *s;
- s = njs_value_data(njs_argument(args, 0));
+ s = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(s == NULL)) {
+ return NXT_ERROR;
+ }
+
c = s->connection;
- if (njs_vm_value_to_ext_string(vm, &msg, njs_argument(args, 1), 0)
+ if (njs_vm_value_to_ext_string(vm, &msg, njs_arg(args, nargs, 1), 0)
== NJS_ERROR)
{
return NJS_ERROR;
diff -r 8840fd0ff685 -r 5f00966ffff8 njs/njs.h
--- a/njs/njs.h Mon Jul 30 20:00:20 2018 +0300
+++ b/njs/njs.h Mon Jul 30 20:00:31 2018 +0300
@@ -177,9 +177,11 @@ NXT_EXPORT nxt_int_t njs_vm_run(njs_vm_t
NXT_EXPORT const njs_extern_t *njs_vm_external_prototype(njs_vm_t *vm,
njs_external_t *external);
NXT_EXPORT nxt_int_t njs_vm_external_create(njs_vm_t *vm,
- njs_value_t *value, const njs_extern_t *proto, void *object);
+ njs_value_t *value, const njs_extern_t *proto, njs_external_ptr_t object);
NXT_EXPORT nxt_int_t njs_vm_external_bind(njs_vm_t *vm,
const nxt_str_t *var_name, njs_value_t *value);
+NXT_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
+ const njs_value_t *value);
NXT_EXPORT void njs_disassembler(njs_vm_t *vm);
NXT_EXPORT nxt_array_t *njs_vm_completions(njs_vm_t *vm, nxt_str_t *expression);
diff -r 8840fd0ff685 -r 5f00966ffff8 njs/njs_extern.c
--- a/njs/njs_extern.c Mon Jul 30 20:00:20 2018 +0300
+++ b/njs/njs_extern.c Mon Jul 30 20:00:31 2018 +0300
@@ -166,7 +166,7 @@ njs_vm_external_prototype(njs_vm_t *vm,
nxt_int_t
njs_vm_external_create(njs_vm_t *vm, njs_value_t *ext_val,
- const njs_extern_t *proto, void *object)
+ const njs_extern_t *proto, njs_external_ptr_t object)
{
void *obj;
@@ -228,6 +228,19 @@ njs_vm_external_bind(njs_vm_t *vm, const
}
+nxt_noinline njs_external_ptr_t
+njs_vm_external(njs_vm_t *vm, const njs_value_t *value)
+{
+ if (nxt_fast_path(njs_is_external(value))) {
+ return njs_extern_object(vm, value);
+ }
+
+ njs_type_error(vm, "external value is expected");
+
+ return NULL;
+}
+
+
njs_array_t *
njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external)
{
diff -r 8840fd0ff685 -r 5f00966ffff8 njs/njs_vm.c
--- a/njs/njs_vm.c Mon Jul 30 20:00:20 2018 +0300
+++ b/njs/njs_vm.c Mon Jul 30 20:00:31 2018 +0300
@@ -2077,9 +2077,8 @@ njs_function_new_object(njs_vm_t *vm, nj
njs_ret_t
njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
{
- void *obj;
njs_ret_t ret;
- njs_value_t this, *value;
+ njs_value_t *value;
njs_object_prop_t *prop;
njs_property_query_t pq;
const njs_extern_t *ext_proto;
@@ -2131,11 +2130,7 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
return NXT_ERROR;
}
- obj = njs_extern_object(vm, object);
-
- this.data.u.data = obj;
-
- ret = njs_function_native_frame(vm, ext_proto->function, &this, NULL,
+ ret = njs_function_native_frame(vm, ext_proto->function, object, NULL,
method->nargs, 0, method->code.ctor);
break;
diff -r 8840fd0ff685 -r 5f00966ffff8 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Mon Jul 30 20:00:20 2018 +0300
+++ b/njs/test/njs_unit_test.c Mon Jul 30 20:00:31 2018 +0300
@@ -3981,13 +3981,20 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("delete $r.one"),
nxt_string("false") },
-#if 0
{ nxt_string("$r.some_method.call($r, 'YES')"),
nxt_string("АБВ") },
+ { nxt_string("var f = $r.some_method.bind($r); f('YES')"),
+ nxt_string("АБВ") },
+
+ { nxt_string("function f(fn, arg) {return fn(arg);}; f($r.some_method.bind($r), 'YES')"),
+ nxt_string("АБВ") },
+
{ nxt_string("$r.some_method.apply($r, ['YES'])"),
nxt_string("АБВ") },
-#endif
+
+ { nxt_string("$r.some_method.call([], 'YES')"),
+ nxt_string("TypeError: external value is expected") },
{ nxt_string("$r.nonexistent"),
nxt_string("undefined") },
@@ -9777,25 +9784,22 @@ njs_unit_test_method_external(njs_vm_t *
{
nxt_int_t ret;
nxt_str_t s;
- uintptr_t next;
njs_unit_test_req_t *r;
- next = 0;
-
- if (nargs > 1) {
-
- ret = njs_value_string_copy(vm, &s, njs_argument(args, 1), &next);
-
- if (ret == NXT_OK && s.length == 3 && memcmp(s.start, "YES", 3) == 0) {
- r = njs_value_data(njs_argument(args, 0));
- njs_string_create(vm, njs_vm_retval(vm), r->uri.start,
- r->uri.length, 0);
-
- return NXT_OK;
- }
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
}
- return NXT_ERROR;
+ ret = njs_vm_value_to_ext_string(vm, &s, njs_arg(args, nargs, 1), 0);
+ if (ret == NXT_OK && s.length == 3 && memcmp(s.start, "YES", 3) == 0) {
+ return njs_string_create(vm, njs_vm_retval(vm), r->uri.start,
+ r->uri.length, 0);
+ }
+
+ vm->retval = njs_value_void;
+
+ return NXT_OK;
}
@@ -9808,41 +9812,44 @@ njs_unit_test_create_external(njs_vm_t *
njs_value_t *value;
njs_unit_test_req_t *r, *sr;
- if (nargs > 1) {
- r = njs_value_data(njs_argument(args, 0));
-
- if (njs_vm_value_to_ext_string(vm, &uri, njs_argument(args, 1), 0)
- == NJS_ERROR)
- {
- return NJS_ERROR;
- }
-
- value = nxt_mem_cache_zalloc(r->mem_cache_pool,
- sizeof(njs_opaque_value_t));
- if (value == NULL) {
- return NXT_ERROR;
- }
-
- sr = nxt_mem_cache_zalloc(r->mem_cache_pool,
- sizeof(njs_unit_test_req_t));
- if (sr == NULL) {
- return NXT_ERROR;
- }
-
- sr->uri = uri;
- sr->mem_cache_pool = r->mem_cache_pool;
- sr->proto = r->proto;
-
- ret = njs_vm_external_create(vm, value, sr->proto, sr);
- if (ret != NXT_OK) {
- return NXT_ERROR;
- }
-
- njs_vm_retval_set(vm, value);
-
- return NXT_OK;
+ r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (nxt_slow_path(r == NULL)) {
+ return NXT_ERROR;
+ }
+
+ if (njs_vm_value_to_ext_string(vm, &uri, njs_arg(args, nargs, 1), 0)
+ != NJS_OK)
+ {
+ return NXT_ERROR;
+ }
+
+ value = nxt_mem_cache_zalloc(r->mem_cache_pool, sizeof(njs_opaque_value_t));
+ if (value == NULL) {
+ goto memory_error;
}
+ sr = nxt_mem_cache_zalloc(r->mem_cache_pool, sizeof(njs_unit_test_req_t));
+ if (sr == NULL) {
+ goto memory_error;
+ }
+
+ sr->uri = uri;
+ sr->mem_cache_pool = r->mem_cache_pool;
+ sr->proto = r->proto;
+
+ ret = njs_vm_external_create(vm, value, sr->proto, sr);
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ njs_vm_retval_set(vm, value);
+
+ return NXT_OK;
+
+memory_error:
+
+ njs_memory_error(vm);
+
return NXT_ERROR;
}
More information about the nginx-devel
mailing list