From: Dmitry Volyntsev Date: Mon, 30 Jul 2018 17:00:31 +0000 (+0300) Subject: Fixed applying call() to methods of external values. X-Git-Tag: 0.2.3~1 X-Git-Url: http://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=6cea6c6f1b5f7a36cf92a9aff9f68f658bd566cd;p=njs.git Fixed applying call() to methods of external values. This correctly fixes #20 on Github. --- diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 5e2d4bbf..25dd457b 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -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); diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index 87e313e0..0464acc6 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -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; diff --git a/njs/njs.h b/njs/njs.h index 56a7d0d6..bbe37470 100644 --- 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); diff --git a/njs/njs_extern.c b/njs/njs_extern.c index 4ed6b93d..25ff9164 100644 --- a/njs/njs_extern.c +++ b/njs/njs_extern.c @@ -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) { diff --git a/njs/njs_vm.c b/njs/njs_vm.c index d278d146..dab8ad88 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -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; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index c78fc3b6..f437c2e4 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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; }