From c568c31e3ba73f8aafb44233f352e7855528941a Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Wed, 7 Dec 2022 18:11:56 -0800 Subject: [PATCH] Extended njs_vm_function_alloc(). --- external/njs_webcrypto_module.c | 2 +- nginx/ngx_http_js_module.c | 3 ++- nginx/ngx_js_fetch.c | 4 +-- src/njs.h | 2 +- src/njs_function.c | 8 +++++- src/test/njs_externals_test.c | 44 ++++++++++++++++++++++++++++++++- src/test/njs_unit_test.c | 5 +++- 7 files changed, 60 insertions(+), 8 deletions(-) diff --git a/external/njs_webcrypto_module.c b/external/njs_webcrypto_module.c index 38a00d7a..84bf5363 100644 --- a/external/njs_webcrypto_module.c +++ b/external/njs_webcrypto_module.c @@ -2779,7 +2779,7 @@ njs_webcrypto_result(njs_vm_t *vm, njs_value_t *result, njs_int_t rc) goto error; } - callback = njs_vm_function_alloc(vm, njs_promise_trampoline); + callback = njs_vm_function_alloc(vm, njs_promise_trampoline, 0, 0); if (callback == NULL) { goto error; } diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index ac38415f..8f3ca9e6 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -3191,7 +3191,8 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (!detached && callback == NULL) { - callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline); + callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline, 0, + 0); if (callback == NULL) { goto memory_error; } diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index afa9a500..4fbe140a 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -636,7 +636,7 @@ ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log) goto failed; } - callback = njs_vm_function_alloc(vm, ngx_js_http_promise_trampoline); + callback = njs_vm_function_alloc(vm, ngx_js_http_promise_trampoline, 0, 0); if (callback == NULL) { goto failed; } @@ -804,7 +804,7 @@ ngx_js_fetch_promissified_result(njs_vm_t *vm, njs_value_t *result, goto error; } - callback = njs_vm_function_alloc(vm, ngx_js_http_promise_trampoline); + callback = njs_vm_function_alloc(vm, ngx_js_http_promise_trampoline, 0, 0); if (callback == NULL) { goto error; } diff --git a/src/njs.h b/src/njs.h index 420a9d4c..09500d68 100644 --- a/src/njs.h +++ b/src/njs.h @@ -384,7 +384,7 @@ NJS_EXPORT njs_int_t njs_external_property(njs_vm_t *vm, NJS_EXPORT uintptr_t njs_vm_meta(njs_vm_t *vm, njs_uint_t index); NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm, - njs_function_native_t native); + njs_function_native_t native, njs_bool_t shared, njs_bool_t ctor); NJS_EXPORT void njs_disassembler(njs_vm_t *vm); diff --git a/src/njs_function.c b/src/njs_function.c index 7487e6cf..c2215730 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -65,7 +65,8 @@ fail: njs_function_t * -njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native) +njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native, + njs_bool_t shared, njs_bool_t ctor) { njs_function_t *function; @@ -76,7 +77,12 @@ njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native) } function->native = 1; + function->ctor = ctor; + function->object.shared = shared; function->u.native = native; + function->object.shared_hash = vm->shared->function_instance_hash; + function->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object; + function->object.type = NJS_FUNCTION; return function; } diff --git a/src/test/njs_externals_test.c b/src/test/njs_externals_test.c index 5856c234..ddf20f40 100644 --- a/src/test/njs_externals_test.c +++ b/src/test/njs_externals_test.c @@ -417,7 +417,8 @@ njs_unit_test_r_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - callback = njs_vm_function_alloc(vm, njs_unit_test_promise_trampoline); + callback = njs_vm_function_alloc(vm, njs_unit_test_promise_trampoline, 0, + 0); if (callback == NULL) { return NJS_ERROR; } @@ -524,6 +525,29 @@ njs_unit_test_r_bind(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } +static njs_int_t +njs_unit_test_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + njs_unit_test_req_t *sr; + + sr = njs_mp_zalloc(vm->mem_pool, sizeof(njs_unit_test_req_t)); + if (sr == NULL) { + njs_memory_error(vm); + return NJS_ERROR; + } + + if (njs_vm_value_to_bytes(vm, &sr->uri, njs_arg(args, nargs, 1)) + != NJS_OK) + { + return NJS_ERROR; + } + + return njs_vm_external_create(vm, &vm->retval, njs_external_r_proto_id, + sr, 0); +} + + static njs_external_t njs_unit_test_r_c[] = { { @@ -831,9 +855,13 @@ njs_externals_init_internal(njs_vm_t *vm, njs_unit_test_req_init_t *init, { njs_int_t ret; njs_uint_t i, j; + njs_function_t *f; + njs_opaque_value_t value; njs_unit_test_req_t *requests; njs_unit_test_prop_t *prop; + static const njs_str_t external_ctor = njs_str("ExternalConstructor"); + if (shared) { njs_external_r_proto_id = njs_vm_external_prototype(vm, njs_unit_test_r_external, @@ -842,6 +870,20 @@ njs_externals_init_internal(njs_vm_t *vm, njs_unit_test_req_init_t *init, njs_printf("njs_vm_external_prototype() failed\n"); return NJS_ERROR; } + + f = njs_vm_function_alloc(vm, njs_unit_test_constructor, 1, 1); + if (f == NULL) { + njs_printf("njs_vm_function_alloc() failed\n"); + return NJS_ERROR; + } + + njs_value_function_set(njs_value_arg(&value), f); + + ret = njs_vm_bind(vm, &external_ctor, njs_value_arg(&value), 1); + if (njs_slow_path(ret != NJS_OK)) { + njs_printf("njs_vm_bind() failed\n"); + return NJS_ERROR; + } } requests = njs_mp_zalloc(vm->mem_pool, n * sizeof(njs_unit_test_req_t)); diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 7b59c07a..0888d591 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -21652,6 +21652,9 @@ static njs_unit_test_t njs_externals_test[] = { njs_str("var sr = $r.create('XXX'); sr.vars.p = 'a'; sr.vars.p"), njs_str("a") }, + { njs_str("var r = new ExternalConstructor('XXX'); r.uri"), + njs_str("XXX") }, + { njs_str("var p; for (p in $r.method);"), njs_str("undefined") }, @@ -21734,7 +21737,7 @@ static njs_unit_test_t njs_externals_test[] = #endif { njs_str("Object.keys(this).sort()"), - njs_str(N262 "$r,$r2,$r3,$shared," NCRYPTO "global,njs,process") }, + njs_str(N262 "$r,$r2,$r3,$shared,ExternalConstructor," NCRYPTO "global,njs,process") }, { njs_str("Object.getOwnPropertySymbols($r2)[0] == Symbol.toStringTag"), njs_str("true") }, -- 2.47.3