]> git.kaiwu.me - njs.git/commitdiff
Fixed applying call() to methods of external values.
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 30 Jul 2018 17:00:31 +0000 (20:00 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 30 Jul 2018 17:00:31 +0000 (20:00 +0300)
This correctly fixes #20 on Github.

nginx/ngx_http_js_module.c
nginx/ngx_stream_js_module.c
njs/njs.h
njs/njs_extern.c
njs/njs_vm.c
njs/test/njs_unit_test.c

index 5e2d4bbfaa9baa3de83cf0c87fea4d3c3b296c92..25dd457b95b1d6270ea659df211bdb22cdfa1804 100644 (file)
@@ -1256,7 +1256,10 @@ ngx_http_js_ext_send_header(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 {
     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_value_t *args, nxt_uint_t nargs,
     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_value_t *args, nxt_uint_t nargs,
     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_value_t *args, nxt_uint_t nargs,
         }
     }
 
-    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_t *vm, njs_value_t *args,
         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, njs_value_t *args, nxt_uint_t nargs,
     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, njs_value_t *args, nxt_uint_t nargs,
         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);
 
index 87e313e09f10b60acfa31788f57b9d8be78b41dc..0464acc6c75b14504f35c71970b9c621f6943896 100644 (file)
@@ -886,10 +886,14 @@ ngx_stream_js_ext_log_core(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     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;
index 56a7d0d6c17ae5cb833d74a249b3c4780119ffd4..bbe37470b1b8d355ba94d0d1e0e18014a1d707c7 100644 (file)
--- a/njs/njs.h
+++ b/njs/njs.h
@@ -177,9 +177,11 @@ NXT_EXPORT nxt_int_t njs_vm_run(njs_vm_t *vm);
 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);
index 4ed6b93d70ac91f9556671f1f639ca6154774de9..25ff916459578f5e2bfbe9189571848711538a00 100644 (file)
@@ -166,7 +166,7 @@ njs_vm_external_prototype(njs_vm_t *vm, njs_external_t *external)
 
 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_str_t *var_name,
 }
 
 
+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)
 {
index d278d146782675c8aaa5ff9e6843cde107600873..dab8ad88c1c68d6f2afb42d06abc441fe4b028d6 100644 (file)
@@ -2077,9 +2077,8 @@ njs_function_new_object(njs_vm_t *vm, njs_value_t *value)
 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, njs_value_t *object, njs_value_t *name)
             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;
 
index c78fc3b61dc7e5b4dcfed6efb9d2cc9bc924259c..f437c2e4086493ccf8972dfc34724fcb4c41b32a 100644 (file)
@@ -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 *vm, njs_value_t *args, nxt_uint_t nargs,
 {
     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);
+    r = njs_vm_external(vm, njs_arg(args, nargs, 0));
+    if (nxt_slow_path(r == NULL)) {
+        return NXT_ERROR;
+    }
 
-            return NXT_OK;
-        }
+    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);
     }
 
-    return NXT_ERROR;
+    vm->retval = njs_value_void;
+
+    return NXT_OK;
 }
 
 
@@ -9808,40 +9812,43 @@ njs_unit_test_create_external(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_value_t          *value;
     njs_unit_test_req_t  *r, *sr;
 
-    if (nargs > 1) {
-        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 (njs_vm_value_to_ext_string(vm, &uri, njs_arg(args, nargs, 1), 0)
+        != NJS_OK)
+    {
+        return NXT_ERROR;
+    }
 
-        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) {
+        goto memory_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) {
+        goto memory_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;
 
-        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;
+    }
 
-        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;
 
-        njs_vm_retval_set(vm, value);
+memory_error:
 
-        return NXT_OK;
-    }
+    njs_memory_error(vm);
 
     return NXT_ERROR;
 }