[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