details: https://hg.nginx.org/njs/rev/167f75576f49 branches: changeset: 2175:167f75576f49 user: Dmitry Volyntsev <xei...@nginx.com> date: Mon Jul 03 12:49:00 2023 -0700 description: Added njs_vm_external_constructor().
The new API allows to add new constructor/prototype pairs. diffstat: external/njs_crypto_module.c | 1 + external/njs_fs_module.c | 1 + external/njs_query_string_module.c | 1 + external/njs_shell.c | 1 + external/njs_webcrypto_module.c | 1 + external/njs_xml_module.c | 1 + external/njs_zlib_module.c | 1 + nginx/ngx_http_js_module.c | 1 + nginx/ngx_js.c | 1 + nginx/ngx_js_fetch.c | 1 + nginx/ngx_stream_js_module.c | 1 + src/njs.h | 18 ++- src/njs_array.c | 2 +- src/njs_array_buffer.c | 2 +- src/njs_async.c | 2 +- src/njs_buffer.c | 13 +- src/njs_builtin.c | 127 ++++---------------- src/njs_date.c | 2 +- src/njs_error.c | 16 +- src/njs_extern.c | 71 +++++++++++ src/njs_function.c | 10 +- src/njs_json.c | 2 +- src/njs_object.c | 16 +- src/njs_parser.c | 6 +- src/njs_promise.c | 12 +- src/njs_regexp.c | 8 +- src/njs_typed_array.c | 6 +- src/njs_value.c | 2 +- src/njs_value.h | 5 +- src/njs_vm.c | 224 ++++++++++++++++++++++++++++++++++-- src/njs_vm.h | 34 ++-- src/njs_vmcode.c | 2 +- src/test/njs_externals_test.c | 113 ++++++++++++++++++- src/test/njs_unit_test.c | 44 +++++++- 34 files changed, 561 insertions(+), 187 deletions(-) diffs (truncated from 1548 to 1000 lines): diff -r 3386684745b7 -r 167f75576f49 external/njs_crypto_module.c --- a/external/njs_crypto_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_crypto_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -287,6 +287,7 @@ static njs_int_t njs_crypto_hmac_prot njs_module_t njs_crypto_module = { .name = njs_str("crypto"), + .preinit = NULL, .init = njs_crypto_init, }; diff -r 3386684745b7 -r 167f75576f49 external/njs_fs_module.c --- a/external/njs_fs_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_fs_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -1407,6 +1407,7 @@ static njs_int_t njs_fs_bytes_written njs_module_t njs_fs_module = { .name = njs_str("fs"), + .preinit = NULL, .init = njs_fs_init, }; diff -r 3386684745b7 -r 167f75576f49 external/njs_query_string_module.c --- a/external/njs_query_string_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_query_string_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -105,6 +105,7 @@ static njs_external_t njs_ext_query_str njs_module_t njs_query_string_module = { .name = njs_str("querystring"), + .preinit = NULL, .init = njs_query_string_init, }; diff -r 3386684745b7 -r 167f75576f49 external/njs_shell.c --- a/external/njs_shell.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_shell.c Mon Jul 03 12:49:00 2023 -0700 @@ -254,6 +254,7 @@ static njs_vm_ops_t njs_console_ops = { njs_module_t njs_console_module = { .name = njs_str("console"), + .preinit = NULL, .init = njs_externals_init, }; diff -r 3386684745b7 -r 167f75576f49 external/njs_webcrypto_module.c --- a/external/njs_webcrypto_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_webcrypto_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -659,6 +659,7 @@ static njs_external_t njs_ext_webcrypto njs_module_t njs_webcrypto_module = { .name = njs_str("webcrypto"), + .preinit = NULL, .init = njs_webcrypto_init, }; diff -r 3386684745b7 -r 167f75576f49 external/njs_xml_module.c --- a/external/njs_xml_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_xml_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -402,6 +402,7 @@ static njs_external_t njs_ext_xml_attr[ njs_module_t njs_xml_module = { .name = njs_str("xml"), + .preinit = NULL, .init = njs_xml_init, }; diff -r 3386684745b7 -r 167f75576f49 external/njs_zlib_module.c --- a/external/njs_zlib_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/external/njs_zlib_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -176,6 +176,7 @@ static njs_external_t njs_ext_zlib[] = njs_module_t njs_zlib_module = { .name = njs_str("zlib"), + .preinit = NULL, .init = njs_zlib_init, }; diff -r 3386684745b7 -r 167f75576f49 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/nginx/ngx_http_js_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -786,6 +786,7 @@ static njs_vm_meta_t ngx_http_js_metas = njs_module_t ngx_js_http_module = { .name = njs_str("http"), + .preinit = NULL, .init = ngx_js_http_init, }; diff -r 3386684745b7 -r 167f75576f49 nginx/ngx_js.c --- a/nginx/ngx_js.c Fri Jun 30 21:02:44 2023 -0700 +++ b/nginx/ngx_js.c Mon Jul 03 12:49:00 2023 -0700 @@ -165,6 +165,7 @@ static njs_external_t ngx_js_ext_core[] njs_module_t ngx_js_ngx_module = { .name = njs_str("ngx"), + .preinit = NULL, .init = ngx_js_core_init, }; diff -r 3386684745b7 -r 167f75576f49 nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Fri Jun 30 21:02:44 2023 -0700 +++ b/nginx/ngx_js_fetch.c Mon Jul 03 12:49:00 2023 -0700 @@ -656,6 +656,7 @@ static njs_int_t ngx_http_js_fetch_he njs_module_t ngx_js_fetch_module = { .name = njs_str("fetch"), + .preinit = NULL, .init = ngx_js_fetch_init, }; diff -r 3386684745b7 -r 167f75576f49 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Fri Jun 30 21:02:44 2023 -0700 +++ b/nginx/ngx_stream_js_module.c Mon Jul 03 12:49:00 2023 -0700 @@ -568,6 +568,7 @@ static njs_int_t ngx_stream_js_sessio njs_module_t ngx_js_stream_module = { .name = njs_str("stream"), + .preinit = NULL, .init = ngx_js_stream_init, }; diff -r 3386684745b7 -r 167f75576f49 src/njs.h --- a/src/njs.h Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs.h Mon Jul 03 12:49:00 2023 -0700 @@ -257,6 +257,7 @@ typedef njs_int_t (*njs_addon_init_pt)(n typedef struct { njs_str_t name; + njs_addon_init_pt preinit; njs_addon_init_pt init; } njs_module_t; @@ -403,6 +404,10 @@ NJS_EXPORT njs_int_t njs_vm_add_path(njs NJS_EXPORT njs_int_t njs_vm_external_prototype(njs_vm_t *vm, const njs_external_t *definition, njs_uint_t n); +NJS_EXPORT njs_int_t njs_vm_external_constructor(njs_vm_t *vm, + const njs_str_t *name, njs_function_native_t native, + const njs_external_t *ctor_props, njs_uint_t ctor_nprops, + const njs_external_t *proto_props, njs_uint_t proto_nprops); NJS_EXPORT njs_int_t njs_vm_external_create(njs_vm_t *vm, njs_value_t *value, njs_int_t proto_id, njs_external_ptr_t external, njs_bool_t shared); NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm, @@ -417,6 +422,15 @@ NJS_EXPORT njs_int_t njs_value_property_ NJS_EXPORT uintptr_t njs_vm_meta(njs_vm_t *vm, njs_uint_t index); NJS_EXPORT njs_vm_opt_t *njs_vm_options(njs_vm_t *vm); +NJS_EXPORT njs_int_t njs_error_constructor(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t type, njs_value_t *retval); +NJS_EXPORT njs_int_t njs_object_prototype_create_constructor(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +NJS_EXPORT njs_int_t njs_object_prototype_create(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); + NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native, njs_bool_t shared, njs_bool_t ctor); @@ -433,7 +447,9 @@ NJS_EXPORT njs_function_t *njs_vm_functi NJS_EXPORT njs_bool_t njs_vm_constructor(njs_vm_t *vm); NJS_EXPORT void njs_vm_throw(njs_vm_t *vm, const njs_value_t *value); -NJS_EXPORT void njs_vm_error2(njs_vm_t *vm, unsigned type, const char *fmt, +NJS_EXPORT void njs_vm_error2(njs_vm_t *vm, unsigned error_type, + const char *fmt, ...); +NJS_EXPORT void njs_vm_error3(njs_vm_t *vm, unsigned type, const char *fmt, ...); NJS_EXPORT void njs_vm_exception_get(njs_vm_t *vm, njs_value_t *retval); NJS_EXPORT njs_mp_t *njs_vm_memory_pool(njs_vm_t *vm); diff -r 3386684745b7 -r 167f75576f49 src/njs_array.c --- a/src/njs_array.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_array.c Mon Jul 03 12:49:00 2023 -0700 @@ -83,7 +83,7 @@ njs_array_alloc(njs_vm_t *vm, njs_bool_t array->start = array->data; njs_lvlhsh_init(&array->object.hash); array->object.shared_hash = vm->shared->array_instance_hash; - array->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_ARRAY].object; + array->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_ARRAY); array->object.slots = NULL; array->object.type = NJS_ARRAY; array->object.shared = 0; diff -r 3386684745b7 -r 167f75576f49 src/njs_array_buffer.c --- a/src/njs_array_buffer.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_array_buffer.c Mon Jul 03 12:49:00 2023 -0700 @@ -33,7 +33,7 @@ njs_array_buffer_alloc(njs_vm_t *vm, uin goto memory_error; } - proto = &vm->prototypes[NJS_OBJ_TYPE_ARRAY_BUFFER].object; + proto = njs_vm_proto(vm, NJS_OBJ_TYPE_ARRAY_BUFFER); njs_lvlhsh_init(&array->object.hash); njs_lvlhsh_init(&array->object.shared_hash); diff -r 3386684745b7 -r 167f75576f49 src/njs_async.c --- a/src/njs_async.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_async.c Mon Jul 03 12:49:00 2023 -0700 @@ -18,7 +18,7 @@ njs_async_function_frame_invoke(njs_vm_t njs_value_t ctor; njs_promise_capability_t *capability; - njs_set_function(&ctor, &vm->constructors[NJS_OBJ_TYPE_PROMISE]); + njs_set_function(&ctor, &njs_vm_ctor(vm, NJS_OBJ_TYPE_PROMISE)); capability = njs_promise_new_capability(vm, &ctor); if (njs_slow_path(capability == NULL)) { diff -r 3386684745b7 -r 167f75576f49 src/njs_buffer.c --- a/src/njs_buffer.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_buffer.c Mon Jul 03 12:49:00 2023 -0700 @@ -126,6 +126,7 @@ static njs_external_t njs_ext_buffer[] njs_module_t njs_buffer_module = { .name = njs_str("buffer"), + .preinit = NULL, .init = njs_buffer_init, }; @@ -147,7 +148,7 @@ njs_buffer_set(njs_vm_t *vm, njs_value_t buffer = (njs_array_buffer_t *) &array[1]; - proto = &vm->prototypes[NJS_OBJ_TYPE_ARRAY_BUFFER].object; + proto = njs_vm_proto(vm, NJS_OBJ_TYPE_ARRAY_BUFFER); njs_lvlhsh_init(&buffer->object.hash); njs_lvlhsh_init(&buffer->object.shared_hash); @@ -161,7 +162,7 @@ njs_buffer_set(njs_vm_t *vm, njs_value_t buffer->u.data = (void *) start; buffer->size = size; - proto = &vm->prototypes[NJS_OBJ_TYPE_BUFFER].object; + proto = njs_vm_proto(vm, NJS_OBJ_TYPE_BUFFER); array->type = NJS_OBJ_TYPE_UINT8_ARRAY; njs_lvlhsh_init(&array->object.hash); @@ -197,7 +198,7 @@ njs_buffer_alloc(njs_vm_t *vm, size_t si return NULL; } - array->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_BUFFER].object; + array->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_BUFFER); return array; } @@ -462,7 +463,7 @@ njs_buffer_from_array_buffer(njs_vm_t *v return NJS_ERROR; } - buffer->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_BUFFER].object; + buffer->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_BUFFER); buffer->offset = off; buffer->byte_length = len; @@ -943,7 +944,7 @@ njs_buffer_is_buffer(njs_vm_t *vm, njs_v array = njs_buffer_slot_internal(vm, njs_arg(args, nargs, 1)); if (njs_fast_path(array != NULL && array->object.__proto__ - == &vm->prototypes[NJS_OBJ_TYPE_BUFFER].object)) + == njs_vm_proto(vm, NJS_OBJ_TYPE_BUFFER))) { is = 1; } @@ -2184,7 +2185,7 @@ njs_buffer_prototype_slice(njs_vm_t *vm, } array = njs_typed_array(retval); - array->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_BUFFER].object; + array->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_BUFFER); return NJS_OK; } diff -r 3386684745b7 -r 167f75576f49 src/njs_builtin.c --- a/src/njs_builtin.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_builtin.c Mon Jul 03 12:49:00 2023 -0700 @@ -115,7 +115,7 @@ njs_object_hash_init(njs_vm_t *vm, njs_l njs_int_t njs_builtin_objects_create(njs_vm_t *vm) { - njs_int_t ret; + njs_int_t ret, index; njs_uint_t i; njs_object_t *object, *string_object; njs_function_t *constructor; @@ -129,6 +129,8 @@ njs_builtin_objects_create(njs_vm_t *vm) return NJS_ERROR; } + vm->shared = shared; + njs_lvlhsh_init(&shared->keywords_hash); njs_lvlhsh_init(&shared->values_hash); @@ -204,34 +206,42 @@ njs_builtin_objects_create(njs_vm_t *vm) return NJS_ERROR; } - prototype = shared->prototypes; + for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) { + index = njs_vm_ctor_push(vm); + if (njs_slow_path(index < 0)) { + return NJS_ERROR; + } - for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) { - prototype[i] = njs_object_type_init[i]->prototype_value; + njs_assert_msg((njs_uint_t) index == i, + "ctor index should match object type"); - ret = njs_object_hash_init(vm, &prototype[i].object.shared_hash, + prototype = njs_shared_prototype(shared, i); + *prototype = njs_object_type_init[i]->prototype_value; + + ret = njs_object_hash_init(vm, &prototype->object.shared_hash, njs_object_type_init[i]->prototype_props); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - prototype[i].object.extensible = 1; + prototype->object.extensible = 1; } - shared->prototypes[NJS_OBJ_TYPE_REGEXP].regexp.pattern = - shared->empty_regexp_pattern; - - constructor = shared->constructors; + prototype = njs_shared_prototype(shared, NJS_OBJ_TYPE_REGEXP); + prototype->regexp.pattern = shared->empty_regexp_pattern; for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) { + constructor = njs_shared_ctor(shared, i); + if (njs_object_type_init[i]->constructor_props == NULL) { + njs_memzero(constructor, sizeof(njs_function_t)); continue; } - constructor[i] = njs_object_type_init[i]->constructor; - constructor[i].object.shared = 0; + *constructor = njs_object_type_init[i]->constructor; + constructor->object.shared = 0; - ret = njs_object_hash_init(vm, &constructor[i].object.shared_hash, + ret = njs_object_hash_init(vm, &constructor->object.shared_hash, njs_object_type_init[i]->constructor_props); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; @@ -259,91 +269,6 @@ njs_builtin_objects_create(njs_vm_t *vm) njs_lvlhsh_init(&shared->modules_hash); - vm->shared = shared; - - return NJS_OK; -} - - -njs_int_t -njs_builtin_objects_clone(njs_vm_t *vm, njs_value_t *global) -{ - size_t size; - njs_uint_t i; - njs_object_t *object_prototype, *function_prototype, - *typed_array_prototype, *error_prototype, *async_prototype, - *typed_array_ctor, *error_ctor; - - /* - * Copy both prototypes and constructors arrays by one memcpy() - * because they are stored together. - */ - size = (sizeof(njs_object_prototype_t) + sizeof(njs_function_t)) - * NJS_OBJ_TYPE_MAX; - - memcpy(vm->prototypes, vm->shared->prototypes, size); - - object_prototype = &vm->prototypes[NJS_OBJ_TYPE_OBJECT].object; - - for (i = NJS_OBJ_TYPE_ARRAY; i < NJS_OBJ_TYPE_NORMAL_MAX; i++) { - vm->prototypes[i].object.__proto__ = object_prototype; - } - - typed_array_prototype = &vm->prototypes[NJS_OBJ_TYPE_TYPED_ARRAY].object; - - for (i = NJS_OBJ_TYPE_TYPED_ARRAY_MIN; - i < NJS_OBJ_TYPE_TYPED_ARRAY_MAX; - i++) - { - vm->prototypes[i].object.__proto__ = typed_array_prototype; - } - - vm->prototypes[NJS_OBJ_TYPE_ARRAY_ITERATOR].object.__proto__ = - &vm->prototypes[NJS_OBJ_TYPE_ITERATOR].object; - - vm->prototypes[NJS_OBJ_TYPE_BUFFER].object.__proto__ = - &vm->prototypes[NJS_OBJ_TYPE_UINT8_ARRAY].object; - - error_prototype = &vm->prototypes[NJS_OBJ_TYPE_ERROR].object; - error_prototype->__proto__ = object_prototype; - - for (i = NJS_OBJ_TYPE_EVAL_ERROR; i < NJS_OBJ_TYPE_MAX; i++) { - vm->prototypes[i].object.__proto__ = error_prototype; - } - - function_prototype = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object; - - async_prototype = &vm->prototypes[NJS_OBJ_TYPE_ASYNC_FUNCTION].object; - async_prototype->__proto__ = function_prototype; - - for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_NORMAL_MAX; i++) { - vm->constructors[i].object.__proto__ = function_prototype; - } - - typed_array_ctor = &vm->constructors[NJS_OBJ_TYPE_TYPED_ARRAY].object; - - for (i = NJS_OBJ_TYPE_TYPED_ARRAY_MIN; - i < NJS_OBJ_TYPE_TYPED_ARRAY_MAX; - i++) - { - vm->constructors[i].object.__proto__ = typed_array_ctor; - } - - error_ctor = &vm->constructors[NJS_OBJ_TYPE_ERROR].object; - error_ctor->__proto__ = function_prototype; - - for (i = NJS_OBJ_TYPE_EVAL_ERROR; i < NJS_OBJ_TYPE_MAX; i++) { - vm->constructors[i].object.__proto__ = error_ctor; - } - - vm->global_object.__proto__ = object_prototype; - - njs_set_undefined(global); - njs_set_object(global, &vm->global_object); - - vm->string_object = vm->shared->string_object; - vm->string_object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_STRING].object; - return NJS_OK; } @@ -838,7 +763,7 @@ njs_builtin_match_native_function(njs_vm /* Constructor from built-in modules (not-mapped to global object). */ for (i = NJS_OBJ_TYPE_HIDDEN_MIN; i < NJS_OBJ_TYPE_HIDDEN_MAX; i++) { - njs_set_object(&value, &vm->constructors[i].object); + njs_set_object(&value, &njs_vm_ctor(vm, i).object); ret = njs_value_property(vm, &value, njs_value_arg(&njs_string_name), &tag); @@ -847,7 +772,7 @@ njs_builtin_match_native_function(njs_vm njs_string_get(&tag, &ctx.match); } - ret = njs_object_traverse(vm, &vm->constructors[i].object, &ctx, + ret = njs_object_traverse(vm, njs_object(&value), &ctx, njs_builtin_traverse); if (ret == NJS_DONE) { @@ -1253,7 +1178,7 @@ njs_top_level_constructor(njs_vm_t *vm, return NJS_DECLINED; } - ctor = &vm->constructors[njs_prop_magic16(self)]; + ctor = &njs_vm_ctor(vm, njs_prop_magic16(self)); njs_set_function(retval, ctor); } diff -r 3386684745b7 -r 167f75576f49 src/njs_date.c --- a/src/njs_date.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_date.c Mon Jul 03 12:49:00 2023 -0700 @@ -364,7 +364,7 @@ njs_date_alloc(njs_vm_t *vm, double time date->object.extensible = 1; date->object.error_data = 0; date->object.fast_array = 0; - date->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_DATE].object; + date->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_DATE); date->object.slots = NULL; date->time = time; diff -r 3386684745b7 -r 167f75576f49 src/njs_error.c --- a/src/njs_error.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_error.c Mon Jul 03 12:49:00 2023 -0700 @@ -76,7 +76,7 @@ njs_throw_error(njs_vm_t *vm, njs_object va_list args; va_start(args, fmt); - njs_throw_error_va(vm, &vm->prototypes[type].object, fmt, args); + njs_throw_error_va(vm, njs_vm_proto(vm, type), fmt, args); va_end(args); } @@ -96,7 +96,7 @@ njs_error_fmt_new(njs_vm_t *vm, njs_valu va_end(args); } - njs_error_new(vm, dst, &vm->prototypes[type].object, buf, p - buf); + njs_error_new(vm, dst, njs_vm_proto(vm, type), buf, p - buf); } @@ -298,7 +298,7 @@ memory_error: } -static njs_int_t +njs_int_t njs_error_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t type, njs_value_t *retval) { @@ -339,7 +339,7 @@ njs_error_constructor(njs_vm_t *vm, njs_ } } - error = njs_error_alloc(vm, &vm->prototypes[type].object, NULL, + error = njs_error_alloc(vm, njs_vm_proto(vm, type), NULL, njs_is_defined(value) ? value : NULL, njs_is_defined(&list) ? &list : NULL); if (njs_slow_path(error == NULL)) { @@ -499,15 +499,13 @@ const njs_object_init_t njs_aggregate_e void njs_memory_error_set(njs_vm_t *vm, njs_value_t *value) { - njs_object_t *object; - njs_object_prototype_t *prototypes; + njs_object_t *object; - prototypes = vm->prototypes; object = &vm->memory_error_object; njs_lvlhsh_init(&object->hash); njs_lvlhsh_init(&object->shared_hash); - object->__proto__ = &prototypes[NJS_OBJ_TYPE_INTERNAL_ERROR].object; + object->__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_INTERNAL_ERROR); object->slots = NULL; object->type = NJS_OBJECT; object->shared = 1; @@ -555,7 +553,7 @@ njs_memory_error_prototype_create(njs_vm function = njs_function(value); proto = njs_property_prototype_create(vm, &function->object.hash, - &vm->prototypes[index].object); + njs_vm_proto(vm, index)); if (proto == NULL) { proto = &njs_value_undefined; } diff -r 3386684745b7 -r 167f75576f49 src/njs_extern.c --- a/src/njs_extern.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_extern.c Mon Jul 03 12:49:00 2023 -0700 @@ -315,6 +315,77 @@ njs_vm_external_prototype(njs_vm_t *vm, } +static njs_int_t +njs_vm_external_constructor_handler(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_set_function(retval, &njs_vm_ctor(vm, njs_prop_magic32(prop))); + + return NJS_OK; +} + + +njs_int_t +njs_vm_external_constructor(njs_vm_t *vm, const njs_str_t *name, + njs_function_native_t native, const njs_external_t *ctor_props, + njs_uint_t ctor_nprops, const njs_external_t *proto_props, + njs_uint_t proto_nprops) +{ + njs_int_t ret, index, proto_id; + njs_arr_t **pprotos; + njs_function_t *constructor; + njs_exotic_slots_t *slots; + njs_object_prototype_t *prototype; + + index = njs_vm_ctor_push(vm); + if (njs_slow_path(index < 0)) { + njs_internal_error(vm, "njs_vm_ctor_push() failed"); + return -1; + } + + proto_id = njs_vm_external_prototype(vm, proto_props, proto_nprops); + if (njs_slow_path(proto_id < 0)) { + njs_internal_error(vm, "njs_vm_external_prototype(proto_props) failed"); + return -1; + } + + prototype = njs_shared_prototype(vm->shared, index); + njs_memzero(prototype, sizeof(njs_object_prototype_t)); + prototype->object.type = NJS_OBJECT; + prototype->object.extensible = 1; + + pprotos = njs_arr_item(vm->protos, proto_id); + slots = (*pprotos)->start; + prototype->object.shared_hash = slots->external_shared_hash; + + proto_id = njs_vm_external_prototype(vm, ctor_props, ctor_nprops); + if (njs_slow_path(proto_id < 0)) { + njs_internal_error(vm, "njs_vm_external_prototype(ctor_props) failed"); + return -1; + } + + constructor = njs_shared_ctor(vm->shared, index); + njs_memzero(constructor, sizeof(njs_function_t)); + constructor->object.type = NJS_FUNCTION; + constructor->u.native = native; + constructor->magic8 = index; + constructor->native = 1; + constructor->ctor = 1; + + pprotos = njs_arr_item(vm->protos, proto_id); + slots = (*pprotos)->start; + constructor->object.shared_hash = slots->external_shared_hash; + + ret = njs_vm_bind_handler(vm, name, njs_vm_external_constructor_handler, 0, + index, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + return index; +} + + njs_int_t njs_vm_external_create(njs_vm_t *vm, njs_value_t *value, njs_int_t proto_id, njs_external_ptr_t external, njs_bool_t shared) diff -r 3386684745b7 -r 167f75576f49 src/njs_function.c --- a/src/njs_function.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_function.c Mon Jul 03 12:49:00 2023 -0700 @@ -46,10 +46,10 @@ njs_function_alloc(njs_vm_t *vm, njs_fun } if (async) { - proto = &vm->prototypes[NJS_OBJ_TYPE_ASYNC_FUNCTION].object; + proto = njs_vm_proto(vm, NJS_OBJ_TYPE_ASYNC_FUNCTION); } else { - proto = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object; + proto = njs_vm_proto(vm, NJS_OBJ_TYPE_FUNCTION); } function->object.__proto__ = proto; @@ -84,7 +84,7 @@ njs_vm_function_alloc(njs_vm_t *vm, njs_ 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.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_FUNCTION); function->object.type = NJS_FUNCTION; return function; @@ -212,7 +212,7 @@ njs_function_copy(njs_vm_t *vm, njs_func type = njs_function_object_type(vm, function); - copy->object.__proto__ = &vm->prototypes[type].object; + copy->object.__proto__ = njs_vm_proto(vm, type); copy->object.shared = 0; if (copy->ctor) { @@ -1370,7 +1370,7 @@ njs_function_prototype_bind(njs_vm_t *vm /* Bound functions have no "prototype" property. */ function->object.shared_hash = vm->shared->arrow_instance_hash; - function->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object; + function->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_FUNCTION); function->object.shared = 0; function->context = njs_function(&args[0]); diff -r 3386684745b7 -r 167f75576f49 src/njs_json.c --- a/src/njs_json.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_json.c Mon Jul 03 12:49:00 2023 -0700 @@ -1979,7 +1979,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ if (njs_slow_path(vm->top_frame == NULL)) { /* An exception was thrown during compilation. */ - njs_vm_init(vm); + njs_vm_runtime_init(vm); } if (njs_is_valid(&vm->exception)) { diff -r 3386684745b7 -r 167f75576f49 src/njs_object.c --- a/src/njs_object.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_object.c Mon Jul 03 12:49:00 2023 -0700 @@ -45,7 +45,7 @@ njs_object_alloc(njs_vm_t *vm) if (njs_fast_path(object != NULL)) { njs_lvlhsh_init(&object->hash); njs_lvlhsh_init(&object->shared_hash); - object->__proto__ = &vm->prototypes[NJS_OBJ_TYPE_OBJECT].object; + object->__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_OBJECT); object->slots = NULL; object->type = NJS_OBJECT; object->shared = 0; @@ -80,7 +80,7 @@ njs_object_value_copy(njs_vm_t *vm, njs_ if (njs_fast_path(object != NULL)) { memcpy(object, njs_object(value), size); - object->__proto__ = &vm->prototypes[NJS_OBJ_TYPE_OBJECT].object; + object->__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_OBJECT); object->shared = 0; value->data.u.object = object; return object; @@ -119,7 +119,7 @@ njs_object_value_alloc(njs_vm_t *vm, njs ov->object.error_data = 0; ov->object.fast_array = 0; - ov->object.__proto__ = &vm->prototypes[prototype_index].object; + ov->object.__proto__ = njs_vm_proto(vm, prototype_index); ov->object.slots = NULL; if (value != NULL) { @@ -1501,7 +1501,7 @@ njs_object_get_prototype_of(njs_vm_t *vm index = njs_primitive_prototype_index(value->type); if (njs_is_symbol(value)) { - njs_set_object(retval, &vm->prototypes[index].object); + njs_set_object(retval, njs_vm_proto(vm, index)); } else { njs_set_object_value(retval, @@ -1843,7 +1843,7 @@ njs_primitive_prototype_get_proto(njs_vm } else { index = njs_primitive_prototype_index(value->type); - proto = &vm->prototypes[index].object; + proto = njs_vm_proto(vm, index); } if (proto != NULL) { @@ -1875,7 +1875,7 @@ njs_object_prototype_create(njs_vm_t *vm function = njs_function(value); index = function - vm->constructors; - if (index >= 0 && index < NJS_OBJ_TYPE_MAX) { + if (index >= 0 && (size_t) index < vm->constructors_size) { proto = njs_property_prototype_create(vm, &function->object.hash, &vm->prototypes[index].object); } @@ -2111,7 +2111,7 @@ njs_object_prototype_create_constructor( prototype = (njs_object_prototype_t *) object; index = prototype - vm->prototypes; - if (index >= 0 && index < NJS_OBJ_TYPE_MAX) { + if (index >= 0 && (size_t) index < vm->constructors_size) { goto found; } @@ -2128,7 +2128,7 @@ njs_object_prototype_create_constructor( found: - njs_set_function(&constructor, &vm->constructors[index]); + njs_set_function(&constructor, &njs_vm_ctor(vm, index)); setval = &constructor; cons = njs_property_constructor_set(vm, &prototype->object.hash, setval); diff -r 3386684745b7 -r 167f75576f49 src/njs_parser.c --- a/src/njs_parser.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_parser.c Mon Jul 03 12:49:00 2023 -0700 @@ -9199,6 +9199,10 @@ njs_parser_error(njs_vm_t *vm, njs_objec static const njs_value_t file_name = njs_string("fileName"); static const njs_value_t line_number = njs_string("lineNumber"); + if (njs_slow_path(vm->top_frame == NULL)) { + njs_vm_runtime_init(vm); + } + p = msg; end = msg + NJS_MAX_ERROR_STR; @@ -9217,7 +9221,7 @@ njs_parser_error(njs_vm_t *vm, njs_objec p = njs_sprintf(p, end, " in %uD", line); } - njs_error_new(vm, &error, &vm->prototypes[type].object, msg, p - msg); + njs_error_new(vm, &error, njs_vm_proto(vm, type), msg, p - msg); njs_set_number(&value, line); njs_value_property_set(vm, &error, njs_value_arg(&line_number), &value); diff -r 3386684745b7 -r 167f75576f49 src/njs_promise.c --- a/src/njs_promise.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_promise.c Mon Jul 03 12:49:00 2023 -0700 @@ -131,7 +131,7 @@ njs_promise_alloc(njs_vm_t *vm) promise->object.extensible = 1; promise->object.error_data = 0; promise->object.fast_array = 0; - promise->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_PROMISE].object; + promise->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_PROMISE); promise->object.slots = NULL; data = (njs_promise_data_t *) ((uint8_t *) promise + sizeof(njs_promise_t)); @@ -265,7 +265,7 @@ njs_promise_create_function(njs_vm_t *vm context = NULL; } - function->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object; + function->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_FUNCTION); function->object.shared_hash = vm->shared->arrow_instance_hash; function->object.type = NJS_FUNCTION; function->object.extensible = 1; @@ -1352,8 +1352,8 @@ njs_promise_perform_all(njs_vm_t *vm, nj if (handler == njs_promise_perform_any_handler) { error = njs_error_alloc(vm, - &vm->prototypes[NJS_OBJ_TYPE_AGGREGATE_ERROR].object, - NULL, &string_any_rejected, &argument); + njs_vm_proto(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR), + NULL, &string_any_rejected, &argument); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } @@ -1730,8 +1730,8 @@ njs_promise_any_reject_element_functions njs_mp_free(vm->mem_pool, context->remaining_elements); error = njs_error_alloc(vm, - &vm->prototypes[NJS_OBJ_TYPE_AGGREGATE_ERROR].object, - NULL, &string_any_rejected, &arr_value); + njs_vm_proto(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR), + NULL, &string_any_rejected, &arr_value); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } diff -r 3386684745b7 -r 167f75576f49 src/njs_regexp.c --- a/src/njs_regexp.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_regexp.c Mon Jul 03 12:49:00 2023 -0700 @@ -503,7 +503,7 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regex if (njs_fast_path(regexp != NULL)) { njs_lvlhsh_init(®exp->object.hash); regexp->object.shared_hash = vm->shared->regexp_instance_hash; - regexp->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_REGEXP].object; + regexp->object.__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_REGEXP); regexp->object.slots = NULL; regexp->object.type = NJS_REGEXP; regexp->object.shared = 0; @@ -628,7 +628,7 @@ njs_regexp_prototype_flag(njs_vm_t *vm, } if (njs_slow_path(!njs_is_regexp(this))) { - if (njs_object(this) == &vm->prototypes[NJS_OBJ_TYPE_REGEXP].object) { + if (njs_object(this) == njs_vm_proto(vm, NJS_OBJ_TYPE_REGEXP)) { njs_set_undefined(retval); return NJS_OK; } @@ -679,7 +679,7 @@ njs_regexp_prototype_source(njs_vm_t *vm } if (njs_slow_path(!njs_is_regexp(this))) { - if (njs_object(this) == &vm->prototypes[NJS_OBJ_TYPE_REGEXP].object) { + if (njs_object(this) == njs_vm_proto(vm, NJS_OBJ_TYPE_REGEXP)) { njs_value_assign(retval, &njs_string_empty_regexp); return NJS_OK; } @@ -1553,7 +1553,7 @@ njs_regexp_prototype_symbol_split(njs_vm return ret; } - njs_set_function(&constructor, &vm->constructors[NJS_OBJ_TYPE_REGEXP]); + njs_set_function(&constructor, &njs_vm_ctor(vm, NJS_OBJ_TYPE_REGEXP)); ret = njs_value_species_constructor(vm, rx, &constructor, &constructor); if (njs_slow_path(ret != NJS_OK)) { diff -r 3386684745b7 -r 167f75576f49 src/njs_typed_array.c --- a/src/njs_typed_array.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_typed_array.c Mon Jul 03 12:49:00 2023 -0700 @@ -180,7 +180,7 @@ njs_typed_array_alloc(njs_vm_t *vm, njs_ njs_lvlhsh_init(&array->object.hash); njs_lvlhsh_init(&array->object.shared_hash); - array->object.__proto__ = &vm->prototypes[type].object; + array->object.__proto__ = njs_vm_proto(vm, type); array->object.type = NJS_TYPED_ARRAY; array->object.extensible = 1; array->object.fast_array = 1; @@ -264,7 +264,7 @@ njs_typed_array_species_create(njs_vm_t array = njs_typed_array(exemplar); - njs_set_function(&constructor, &vm->constructors[array->type]); + njs_set_function(&constructor, &njs_vm_ctor(vm, array->type)); ret = njs_value_species_constructor(vm, exemplar, &constructor, &constructor); @@ -2413,7 +2413,7 @@ njs_data_view_constructor(njs_vm_t *vm, njs_lvlhsh_init(&view->object.hash); njs_lvlhsh_init(&view->object.shared_hash); - view->object.__proto__ = &vm->prototypes[view->type].object; + view->object.__proto__ = njs_vm_proto(vm, view->type); view->object.type = NJS_DATA_VIEW; view->object.extensible = 1; diff -r 3386684745b7 -r 167f75576f49 src/njs_value.c --- a/src/njs_value.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_value.c Mon Jul 03 12:49:00 2023 -0700 @@ -638,7 +638,7 @@ njs_property_query(njs_vm_t *vm, njs_pro case NJS_NUMBER: case NJS_SYMBOL: index = njs_primitive_prototype_index(value->type); - obj = &vm->prototypes[index].object; + obj = njs_vm_proto(vm, index); break; case NJS_STRING: diff -r 3386684745b7 -r 167f75576f49 src/njs_value.h --- a/src/njs_value.h Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_value.h Mon Jul 03 12:49:00 2023 -0700 @@ -625,9 +625,8 @@ typedef struct { ((value)->type >= NJS_OBJECT) -#define njs_has_prototype(vm, value, proto) \ - (((njs_object_prototype_t *) \ - njs_object(value)->__proto__ - (vm)->prototypes) == proto) +#define njs_has_prototype(vm, value, proto_id) \ + (njs_object(value)->__proto__ == njs_vm_proto(vm, proto_id)) #define njs_is_object_value(value) \ diff -r 3386684745b7 -r 167f75576f49 src/njs_vm.c --- a/src/njs_vm.c Fri Jun 30 21:02:44 2023 -0700 +++ b/src/njs_vm.c Mon Jul 03 12:49:00 2023 -0700 @@ -9,6 +9,7 @@ static njs_int_t njs_vm_handle_events(njs_vm_t *vm); +static njs_int_t njs_vm_protos_init(njs_vm_t *vm, njs_value_t *global); const njs_str_t njs_entry_empty = njs_str(""); @@ -78,13 +79,47 @@ njs_vm_create(njs_vm_opt_t *options) vm->trace.data = vm; if (options->init) { - ret = njs_vm_init(vm); + ret = njs_vm_runtime_init(vm); if (njs_slow_path(ret != NJS_OK)) { return NULL; } } for (i = 0; njs_modules[i] != NULL; i++) { + if (njs_modules[i]->preinit == NULL) { + continue; + } + + ret = njs_modules[i]->preinit(vm); + if (njs_slow_path(ret != NJS_OK)) { + return NULL; + } + } + + if (options->addons != NULL) { + addons = options->addons; + for (i = 0; addons[i] != NULL; i++) { + if (addons[i]->preinit == NULL) { + continue; + } + + ret = addons[i]->preinit(vm); + if (njs_slow_path(ret != NJS_OK)) { + return NULL; + } + } + } + + ret = njs_vm_protos_init(vm, &vm->global_value); + if (njs_slow_path(ret != NJS_OK)) { + return NULL; + } + + for (i = 0; njs_modules[i] != NULL; i++) { + if (njs_modules[i]->init == NULL) { + continue; + } + ret = njs_modules[i]->init(vm); if (njs_slow_path(ret != NJS_OK)) { return NULL; @@ -94,6 +129,10 @@ njs_vm_create(njs_vm_opt_t *options) if (options->addons != NULL) { addons = options->addons; for (i = 0; addons[i] != NULL; i++) { + if (addons[i]->init == NULL) { + continue; + } + ret = addons[i]->init(vm); if (njs_slow_path(ret != NJS_OK)) { return NULL; @@ -111,6 +150,51 @@ njs_vm_create(njs_vm_opt_t *options) } +njs_int_t +njs_vm_ctor_push(njs_vm_t *vm) +{ + njs_function_t *ctor; + njs_vm_shared_t *shared; + njs_object_prototype_t *prototype; + + shared = vm->shared; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel