From mdounin at mdounin.ru Thu Aug 1 11:04:38 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 01 Aug 2019 11:04:38 +0000 Subject: [nginx] Mail: fixed duplicate resolving. Message-ID: details: https://hg.nginx.org/nginx/rev/fcd92ad76b7b branches: changeset: 7546:fcd92ad76b7b user: Maxim Dounin date: Thu Aug 01 13:50:07 2019 +0300 description: Mail: fixed duplicate resolving. When using SMTP with SSL and resolver, read events might be enabled during address resolving, leading to duplicate ngx_mail_ssl_handshake_handler() calls if something arrives from the client, and duplicate session initialization - including starting another resolving. This can lead to a segmentation fault if the session is closed after first resolving finished. Fix is to block read events while resolving. Reported by Robert Norris, http://mailman.nginx.org/pipermail/nginx/2019-July/058204.html. diffstat: src/mail/ngx_mail_smtp_handler.c | 43 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-) diffs (81 lines): diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -15,6 +15,7 @@ static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx); static void ngx_mail_smtp_resolve_name(ngx_event_t *rev); static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx); +static void ngx_mail_smtp_block_reading(ngx_event_t *rev); static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c); static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev); static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, @@ -88,6 +89,9 @@ ngx_mail_smtp_init_session(ngx_mail_sess ctx->data = s; ctx->timeout = cscf->resolver_timeout; + s->resolver_ctx = ctx; + c->read->handler = ngx_mail_smtp_block_reading; + if (ngx_resolve_addr(ctx) != NGX_OK) { ngx_mail_close_connection(c); } @@ -169,6 +173,9 @@ ngx_mail_smtp_resolve_name(ngx_event_t * ctx->data = s; ctx->timeout = cscf->resolver_timeout; + s->resolver_ctx = ctx; + c->read->handler = ngx_mail_smtp_block_reading; + if (ngx_resolve_name(ctx) != NGX_OK) { ngx_mail_close_connection(c); } @@ -239,6 +246,38 @@ found: static void +ngx_mail_smtp_block_reading(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_resolver_ctx_t *ctx; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp reading blocked"); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + + if (s->resolver_ctx) { + ctx = s->resolver_ctx; + + if (ctx->handler == ngx_mail_smtp_resolve_addr_handler) { + ngx_resolve_addr_done(ctx); + + } else if (ctx->handler == ngx_mail_smtp_resolve_name_handler) { + ngx_resolve_name_done(ctx); + } + + s->resolver_ctx = NULL; + } + + ngx_mail_close_connection(c); + } +} + + +static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_msec_t timeout; @@ -258,6 +297,10 @@ ngx_mail_smtp_greeting(ngx_mail_session_ ngx_mail_close_connection(c); } + if (c->read->ready) { + ngx_post_event(c->read, &ngx_posted_events); + } + if (sscf->greeting_delay) { c->read->handler = ngx_mail_smtp_invalid_pipelining; return; From xeioex at nginx.com Thu Aug 1 13:41:59 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 01 Aug 2019 13:41:59 +0000 Subject: [njs] Removed unused njs_global_variable_value(). Message-ID: details: https://hg.nginx.org/njs/rev/cd56dad88801 branches: changeset: 1088:cd56dad88801 user: Dmitry Volyntsev date: Thu Aug 01 16:41:36 2019 +0300 description: Removed unused njs_global_variable_value(). diffstat: src/njs_variable.h | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-) diffs (15 lines): diff -r f4ac8168e856 -r cd56dad88801 src/njs_variable.h --- a/src/njs_variable.h Tue Jul 30 21:12:08 2019 +0300 +++ b/src/njs_variable.h Thu Aug 01 16:41:36 2019 +0300 @@ -31,11 +31,6 @@ typedef struct { } njs_variable_t; -#define njs_global_variable_value(vm, var) \ - (njs_value_t *) ((u_char *) vm->global_scope \ - + njs_scope_offset((var)->index) - NJS_INDEX_GLOBAL_OFFSET) - - typedef enum { NJS_DECLARATION = 0, NJS_REFERENCE, From xeioex at nginx.com Thu Aug 1 18:01:31 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 01 Aug 2019 18:01:31 +0000 Subject: [njs] Unifying return code variable name. Message-ID: details: https://hg.nginx.org/njs/rev/26802fc27c76 branches: changeset: 1089:26802fc27c76 user: Dmitry Volyntsev date: Thu Aug 01 18:48:39 2019 +0300 description: Unifying return code variable name. Using "ret" everywhere. diffstat: src/njs_builtin.c | 18 +++++++++--------- src/njs_vm.c | 7 +++---- src/test/njs_benchmark.c | 8 ++++---- src/test/njs_unit_test.c | 26 +++++++++++++------------- 4 files changed, 29 insertions(+), 30 deletions(-) diffs (245 lines): diff -r cd56dad88801 -r 26802fc27c76 src/njs_builtin.c --- a/src/njs_builtin.c Thu Aug 01 16:41:36 2019 +0300 +++ b/src/njs_builtin.c Thu Aug 01 18:48:39 2019 +0300 @@ -1000,29 +1000,29 @@ njs_builtin_match_native_function(njs_vm { size_t len; njs_str_t string, middle; - njs_int_t rc; + njs_int_t ret; const njs_object_init_t *obj, **p; const njs_object_prop_t *prop; const njs_function_init_t *fun; middle = njs_str_value("."); - rc = njs_builtin_match(njs_object_init, function, &prop, &obj); + ret = njs_builtin_match(njs_object_init, function, &prop, &obj); - if (rc == NJS_OK) { + if (ret == NJS_OK) { goto found; } - rc = njs_builtin_match(njs_prototype_init, function, &prop, &obj); + ret = njs_builtin_match(njs_prototype_init, function, &prop, &obj); - if (rc == NJS_OK) { + if (ret == NJS_OK) { middle = njs_str_value(".prototype."); goto found; } - rc = njs_builtin_match(njs_constructor_init, function, &prop, &obj); + ret = njs_builtin_match(njs_constructor_init, function, &prop, &obj); - if (rc == NJS_OK) { + if (ret == NJS_OK) { goto found; } @@ -1036,9 +1036,9 @@ njs_builtin_match_native_function(njs_vm } } - rc = njs_builtin_match(njs_module_init, function, &prop, &obj); + ret = njs_builtin_match(njs_module_init, function, &prop, &obj); - if (rc == NJS_OK) { + if (ret == NJS_OK) { goto found; } diff -r cd56dad88801 -r 26802fc27c76 src/njs_vm.c --- a/src/njs_vm.c Thu Aug 01 16:41:36 2019 +0300 +++ b/src/njs_vm.c Thu Aug 01 18:48:39 2019 +0300 @@ -946,7 +946,6 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_va { va_list args; njs_int_t ret; - njs_int_t rc; njs_value_t *name, *value; njs_object_t *object; njs_object_prop_t *prop; @@ -957,7 +956,7 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_va return NJS_ERROR; } - rc = NJS_ERROR; + ret = NJS_ERROR; va_start(args, retval); @@ -999,7 +998,7 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_va } } - rc = NJS_OK; + ret = NJS_OK; njs_set_object(retval, object); @@ -1007,7 +1006,7 @@ done: va_end(args); - return rc; + return ret; } diff -r cd56dad88801 -r 26802fc27c76 src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Thu Aug 01 16:41:36 2019 +0300 +++ b/src/test/njs_benchmark.c Thu Aug 01 18:48:39 2019 +0300 @@ -19,7 +19,7 @@ njs_unit_test_benchmark(njs_str_t *scrip u_char *start; njs_vm_t *vm, *nvm; uint64_t us; - njs_int_t ret, rc; + njs_int_t ret; njs_str_t s; njs_uint_t i; njs_bool_t success; @@ -30,7 +30,7 @@ njs_unit_test_benchmark(njs_str_t *scrip vm = NULL; nvm = NULL; - rc = NJS_ERROR; + ret = NJS_ERROR; vm = njs_vm_create(&options); if (vm == NULL) { @@ -85,7 +85,7 @@ njs_unit_test_benchmark(njs_str_t *scrip msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us)); } - rc = NJS_OK; + ret = NJS_OK; done: @@ -97,7 +97,7 @@ done: njs_vm_destroy(vm); } - return rc; + return ret; } diff -r cd56dad88801 -r 26802fc27c76 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Aug 01 16:41:36 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Aug 01 18:48:39 2019 +0300 @@ -14111,7 +14111,7 @@ njs_unit_test(njs_unit_test_t tests[], s { u_char *start; njs_vm_t *vm, *nvm; - njs_int_t ret, rc; + njs_int_t ret; njs_str_t s; njs_uint_t i; njs_stat_t prev; @@ -14123,7 +14123,7 @@ njs_unit_test(njs_unit_test_t tests[], s prev = *stat; - rc = NJS_ERROR; + ret = NJS_ERROR; for (i = 0; i < num; i++) { @@ -14196,7 +14196,7 @@ njs_unit_test(njs_unit_test_t tests[], s vm = NULL; } - rc = NJS_OK; + ret = NJS_OK; done: @@ -14210,7 +14210,7 @@ done: njs_unit_test_report(name, &prev, stat); - return rc; + return ret; } @@ -14302,7 +14302,7 @@ static njs_int_t njs_vm_json_test(njs_opts_t *opts, njs_stat_t *stat) { njs_vm_t *vm; - njs_int_t ret, rc; + njs_int_t ret; njs_str_t s, *script; njs_uint_t i; njs_bool_t success; @@ -14334,7 +14334,7 @@ njs_vm_json_test(njs_opts_t *opts, njs_s prev = *stat; - rc = NJS_ERROR; + ret = NJS_ERROR; for (i = 0; i < njs_nitems(tests); i++) { @@ -14404,11 +14404,11 @@ njs_vm_json_test(njs_opts_t *opts, njs_s } - rc = NJS_OK; + ret = NJS_OK; done: - if (rc != NJS_OK) { + if (ret != NJS_OK) { if (njs_vm_retval_string(vm, &s) != NJS_OK) { njs_printf("njs_vm_retval_string() failed\n"); @@ -14423,7 +14423,7 @@ done: njs_vm_destroy(vm); } - return rc; + return ret; } @@ -14564,7 +14564,7 @@ static njs_int_t njs_api_test(njs_opts_t *opts, njs_stat_t *stat) { njs_vm_t *vm; - njs_int_t ret, rc; + njs_int_t ret; njs_uint_t i; njs_stat_t prev; njs_vm_opt_t options; @@ -14586,7 +14586,7 @@ njs_api_test(njs_opts_t *opts, njs_stat_ prev = *stat; - rc = NJS_ERROR; + ret = NJS_ERROR; for (i = 0; i < njs_nitems(tests); i++) { vm = njs_vm_create(&options); @@ -14605,7 +14605,7 @@ njs_api_test(njs_opts_t *opts, njs_stat_ vm = NULL; } - rc = NJS_OK; + ret = NJS_OK; done: @@ -14615,7 +14615,7 @@ done: njs_vm_destroy(vm); } - return rc; + return ret; } From xeioex at nginx.com Thu Aug 1 18:01:31 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 01 Aug 2019 18:01:31 +0000 Subject: [njs] Avoiding excessive (njs_value_t *) casts. Message-ID: details: https://hg.nginx.org/njs/rev/b0823626551d branches: changeset: 1090:b0823626551d user: Dmitry Volyntsev date: Thu Aug 01 18:49:28 2019 +0300 description: Avoiding excessive (njs_value_t *) casts. Previously njs_arg() returned expression of type (const njs_value_t *). This caused a lot of casts when calling functions and forced to declared const njs_value_t * variables. NO functional changes. diffstat: nginx/ngx_http_js_module.c | 9 +-- nginx/ngx_stream_js_module.c | 10 ++-- src/njs.h | 3 +- src/njs_array.c | 102 ++++++++++++++++++++---------------------- src/njs_builtin.c | 6 +- src/njs_error.c | 8 +- src/njs_function.c | 31 ++++++------ src/njs_function.h | 6 +- src/njs_json.c | 5 +- src/njs_object.c | 71 +++++++++++++++-------------- src/njs_object.h | 12 ++-- src/njs_object_property.c | 29 +++++------ src/njs_regexp.c | 8 +-- src/njs_string.c | 10 ++-- src/njs_vm.c | 7 +-- src/njs_vmcode.c | 4 +- 16 files changed, 156 insertions(+), 165 deletions(-) diffs (truncated from 1021 to 1000 lines): diff -r 26802fc27c76 -r b0823626551d nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Aug 01 18:48:39 2019 +0300 +++ b/nginx/ngx_http_js_module.c Thu Aug 01 18:49:28 2019 +0300 @@ -139,7 +139,7 @@ static void ngx_http_js_clear_timer(njs_ static void ngx_http_js_timer_handler(ngx_event_t *ev); static void ngx_http_js_handle_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); -static njs_int_t ngx_http_js_string(njs_vm_t *vm, const njs_value_t *value, +static njs_int_t ngx_http_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str); static char *ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, @@ -1246,9 +1246,9 @@ ngx_http_js_ext_return(njs_vm_t *vm, njs { njs_str_t text; ngx_int_t status; + njs_value_t *value; ngx_http_js_ctx_t *ctx; ngx_http_request_t *r; - const njs_value_t *value; ngx_http_complex_value_t cv; r = njs_vm_external(vm, njs_arg(args, nargs, 0)); @@ -1729,10 +1729,9 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, ngx_int_t rc; njs_str_t uri_arg, args_arg, method_name, body_arg; ngx_uint_t method, methods_max, has_body; - njs_value_t *value; + njs_value_t *value, *arg, *options; njs_function_t *callback; ngx_http_js_ctx_t *ctx; - const njs_value_t *arg, *options; ngx_http_request_t *r, *sr; ngx_http_request_body_t *rb; @@ -2187,7 +2186,7 @@ ngx_http_js_handle_event(ngx_http_reques static njs_int_t -ngx_http_js_string(njs_vm_t *vm, const njs_value_t *value, njs_str_t *str) +ngx_http_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str) { if (!njs_value_is_null_or_undefined(value)) { if (njs_vm_value_to_string(vm, str, value) == NJS_ERROR) { diff -r 26802fc27c76 -r b0823626551d nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Thu Aug 01 18:48:39 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Thu Aug 01 18:49:28 2019 +0300 @@ -110,7 +110,7 @@ static void ngx_stream_js_clear_timer(nj static void ngx_stream_js_timer_handler(ngx_event_t *ev); static void ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); -static njs_int_t ngx_stream_js_string(njs_vm_t *vm, const njs_value_t *value, +static njs_int_t ngx_stream_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str); static char *ngx_stream_js_include(ngx_conf_t *cf, ngx_command_t *cmd, @@ -931,7 +931,7 @@ static njs_int_t ngx_stream_js_ext_set_status(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, ngx_int_t status) { - const njs_value_t *code; + njs_value_t *code; ngx_stream_js_ctx_t *ctx; ngx_stream_session_t *s; @@ -1038,8 +1038,8 @@ ngx_stream_js_ext_on(njs_vm_t *vm, njs_v njs_index_t unused) { njs_str_t name; + njs_value_t *callback; njs_vm_event_t *event; - const njs_value_t *callback; ngx_stream_session_t *s; s = njs_vm_external(vm, njs_arg(args, nargs, 0)); @@ -1120,9 +1120,9 @@ ngx_stream_js_ext_send(njs_vm_t *vm, njs unsigned last_buf, flush; njs_str_t buffer; ngx_buf_t *b; + njs_value_t *flags, *value; ngx_chain_t *cl; ngx_connection_t *c; - const njs_value_t *flags, *value; ngx_stream_js_ctx_t *ctx; ngx_stream_session_t *s; @@ -1377,7 +1377,7 @@ ngx_stream_js_handle_event(ngx_stream_se static njs_int_t -ngx_stream_js_string(njs_vm_t *vm, const njs_value_t *value, njs_str_t *str) +ngx_stream_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str) { if (!njs_value_is_null_or_undefined(value)) { if (njs_vm_value_to_string(vm, str, value) == NJS_ERROR) { diff -r 26802fc27c76 -r b0823626551d src/njs.h --- a/src/njs.h Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs.h Thu Aug 01 18:49:28 2019 +0300 @@ -47,7 +47,8 @@ typedef struct { extern const njs_value_t njs_value_undefined; #define njs_arg(args, nargs, n) \ - ((n < nargs) ? njs_argument(args, n) : &njs_value_undefined) + ((n < nargs) ? njs_argument(args, n) \ + : (njs_value_t *) &njs_value_undefined) #define njs_value_assign(dst, src) \ *((njs_opaque_value_t *) dst) = *((njs_opaque_value_t *) src); diff -r 26802fc27c76 -r b0823626551d src/njs_array.c --- a/src/njs_array.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_array.c Thu Aug 01 18:49:28 2019 +0300 @@ -406,7 +406,8 @@ njs_array_prototype_slice(njs_vm_t *vm, static const njs_value_t string_length = njs_string("length"); - ret = njs_value_property(vm, &args[0], &string_length, &prop_length); + ret = njs_value_property(vm, &args[0], njs_value_arg(&string_length), + &prop_length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -942,7 +943,7 @@ njs_array_prototype_join(njs_vm_t *vm, n value = &args[1]; } else { - value = (njs_value_t *) &njs_string_comma; + value = njs_value_arg(&njs_string_comma); } (void) njs_string_prop(&separator, value); @@ -1112,10 +1113,10 @@ static njs_int_t njs_array_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_int_t k, n, index, length; - njs_value_t *start; - njs_array_t *array; - const njs_value_t *this, *value; + njs_int_t k, n, index, length; + njs_value_t *start; + njs_array_t *array; + njs_value_t *this, *value; index = -1; @@ -1252,16 +1253,15 @@ static njs_int_t njs_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_int_t ret; - njs_int_t i, start, end, length; - njs_array_t *array; - njs_value_t name, prop_length; - njs_object_t *object; - const njs_value_t *this, *value; + njs_int_t ret; + njs_int_t i, start, end, length; + njs_array_t *array; + njs_value_t name, prop_length, *this, *value; + njs_object_t *object; static const njs_value_t string_length = njs_string("length"); - this = (njs_value_t *) njs_arg(args, nargs, 0); + this = njs_arg(args, nargs, 0); if (njs_is_primitive(this)) { if (njs_is_null_or_undefined(this)) { @@ -1287,7 +1287,8 @@ njs_array_prototype_fill(njs_vm_t *vm, n length = array->length; } else { - ret = njs_value_property(vm, this, &string_length, &prop_length); + ret = njs_value_property(vm, this, njs_value_arg(&string_length), + &prop_length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -1331,8 +1332,7 @@ njs_array_prototype_fill(njs_vm_t *vm, n while (start < end) { njs_uint32_to_string(&name, start++); - ret = njs_value_property_set(vm, (njs_value_t *) this, &name, - (njs_value_t *) value); + ret = njs_value_property_set(vm, this, &name, value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -1346,8 +1346,8 @@ njs_array_prototype_fill(njs_vm_t *vm, n njs_inline njs_int_t njs_array_iterator_call(njs_vm_t *vm, njs_function_t *function, - const njs_value_t *this_arg, njs_value_t *value, uint32_t n, - njs_value_t *array) + const njs_value_t *this_arg, const njs_value_t *value, uint32_t n, + const njs_value_t *array) { njs_value_t arguments[3]; @@ -1357,8 +1357,8 @@ njs_array_iterator_call(njs_vm_t *vm, nj njs_set_number(&arguments[1], n); arguments[2] = *array; - return njs_function_call(vm, function, (njs_value_t *) this_arg, - arguments, 3, &vm->retval); + return njs_function_call(vm, function, this_arg, arguments, 3, + &vm->retval); } @@ -1368,9 +1368,8 @@ njs_array_prototype_for_each(njs_vm_t *v { uint32_t i, length; njs_int_t ret; - njs_value_t *array, *value; + njs_value_t *array, *value, *this_arg; njs_function_t *function; - const njs_value_t *this_arg; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1379,7 +1378,7 @@ njs_array_prototype_for_each(njs_vm_t *v array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); for (i = 0; i < length; i++) { @@ -1408,9 +1407,9 @@ njs_array_prototype_some(njs_vm_t *vm, n { uint32_t i, length; njs_int_t ret; - njs_value_t *array, *value; + njs_value_t *array, *value, *this_arg; njs_function_t *function; - const njs_value_t *this_arg, *retval; + const njs_value_t *retval; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1419,7 +1418,7 @@ njs_array_prototype_some(njs_vm_t *vm, n array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); retval = &njs_value_false; @@ -1455,9 +1454,9 @@ njs_array_prototype_every(njs_vm_t *vm, { uint32_t i, length; njs_int_t ret; - njs_value_t *array, *value; + njs_value_t *array, *value, *this_arg; njs_function_t *function; - const njs_value_t *this_arg, *retval; + const njs_value_t *retval; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1466,7 +1465,7 @@ njs_array_prototype_every(njs_vm_t *vm, array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); retval = &njs_value_true; @@ -1500,12 +1499,11 @@ static njs_int_t njs_array_prototype_filter(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_array_t *retval; - njs_value_t *array, value; - njs_function_t *function; - const njs_value_t *this_arg; + uint32_t i, length; + njs_int_t ret; + njs_array_t *retval; + njs_value_t *array, value, *this_arg; + njs_function_t *function; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1514,7 +1512,7 @@ njs_array_prototype_filter(njs_vm_t *vm, array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); retval = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE); @@ -1555,9 +1553,9 @@ njs_array_prototype_find(njs_vm_t *vm, n { uint32_t i, length; njs_int_t ret; - njs_value_t *array, value; + njs_value_t *array, value, *this_arg; njs_function_t *function; - const njs_value_t *this_arg, *retval; + const njs_value_t *retval; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1566,7 +1564,7 @@ njs_array_prototype_find(njs_vm_t *vm, n array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); retval = &njs_value_undefined; @@ -1601,12 +1599,11 @@ static njs_int_t njs_array_prototype_find_index(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double index; - uint32_t i, length; - njs_int_t ret; - njs_value_t *array, value; - njs_function_t *function; - const njs_value_t *this_arg; + double index; + uint32_t i, length; + njs_int_t ret; + njs_value_t *array, value, *this_arg; + njs_function_t *function; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1615,7 +1612,7 @@ njs_array_prototype_find_index(njs_vm_t array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); index = -1; @@ -1650,12 +1647,11 @@ static njs_int_t njs_array_prototype_map(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length, size; - njs_int_t ret; - njs_array_t *retval; - njs_value_t *array, *value; - njs_function_t *function; - const njs_value_t *this_arg; + uint32_t i, length, size; + njs_int_t ret; + njs_array_t *retval; + njs_value_t *array, *value, *this_arg; + njs_function_t *function; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); @@ -1664,7 +1660,7 @@ njs_array_prototype_map(njs_vm_t *vm, nj array = &args[0]; length = njs_array_len(array); - function = njs_function(&args[1]); + function = njs_function(&args[1]); this_arg = njs_arg(args, nargs, 2); size = length; diff -r 26802fc27c76 -r b0823626551d src/njs_builtin.c --- a/src/njs_builtin.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_builtin.c Thu Aug 01 18:49:28 2019 +0300 @@ -1067,9 +1067,9 @@ static njs_int_t njs_dump_value(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_str_t str; - njs_uint_t n; - const njs_value_t *value, *indent; + njs_str_t str; + njs_uint_t n; + njs_value_t *value, *indent; value = njs_arg(args, nargs, 1); indent = njs_arg(args, nargs, 2); diff -r 26802fc27c76 -r b0823626551d src/njs_error.c --- a/src/njs_error.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_error.c Thu Aug 01 18:49:28 2019 +0300 @@ -534,9 +534,9 @@ static njs_int_t njs_memory_error_prototype_create(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { - int32_t index; - njs_value_t *proto; - njs_function_t *function; + int32_t index; + njs_function_t *function; + const njs_value_t *proto; /* MemoryError has no its own prototype. */ @@ -546,7 +546,7 @@ njs_memory_error_prototype_create(njs_vm proto = njs_property_prototype_create(vm, &function->object.hash, &vm->prototypes[index].object); if (proto == NULL) { - proto = (njs_value_t *) &njs_value_undefined; + proto = &njs_value_undefined; } *retval = *proto; diff -r 26802fc27c76 -r b0823626551d src/njs_function.c --- a/src/njs_function.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_function.c Thu Aug 01 18:49:28 2019 +0300 @@ -464,8 +464,9 @@ njs_function_frame_alloc(njs_vm_t *vm, s njs_int_t -njs_function_call(njs_vm_t *vm, njs_function_t *function, njs_value_t *this, - njs_value_t *args, njs_uint_t nargs, njs_value_t *retval) +njs_function_call(njs_vm_t *vm, njs_function_t *function, + const njs_value_t *this, const njs_value_t *args, + njs_uint_t nargs, njs_value_t *retval) { njs_int_t ret; njs_value_t dst njs_aligned(16); @@ -944,9 +945,9 @@ static njs_int_t njs_function_prototype_call(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t retval) { - njs_int_t ret; - njs_value_t *this; - njs_function_t *function; + njs_int_t ret; + njs_function_t *function; + const njs_value_t *this; if (!njs_is_function(&args[0])) { njs_type_error(vm, "\"this\" argument is not a function"); @@ -996,14 +997,13 @@ static njs_int_t njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t retval) { - uint32_t i; - njs_int_t ret; - njs_value_t length, name; - njs_array_t *arr; - njs_function_t *func; - const njs_value_t *this, *arr_like; + uint32_t i; + njs_int_t ret; + njs_value_t length, name, *this, *arr_like; + njs_array_t *arr; + njs_function_t *func; - static const njs_value_t njs_string_length = njs_string("length"); + static const njs_value_t string_length = njs_string("length"); if (!njs_is_function(njs_arg(args, nargs, 0))) { njs_type_error(vm, "\"this\" argument is not a function"); @@ -1032,7 +1032,8 @@ njs_function_prototype_apply(njs_vm_t *v return NJS_ERROR; } - ret = njs_value_property(vm, arr_like, &njs_string_length, &length); + ret = njs_value_property(vm, arr_like, njs_value_arg(&string_length), + &length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -1065,7 +1066,7 @@ activate: /* Skip the "apply" method frame. */ vm->top_frame->skip = 1; - ret = njs_function_frame(vm, func, (njs_value_t *) this, args, nargs, 0); + ret = njs_function_frame(vm, func, this, args, nargs, 0); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1099,7 +1100,7 @@ njs_function_prototype_bind(njs_vm_t *vm } if (nargs == 1) { - args = (njs_value_t *) &njs_value_undefined; + args = njs_value_arg(&njs_value_undefined); } else { nargs--; diff -r 26802fc27c76 -r b0823626551d src/njs_function.h --- a/src/njs_function.h Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_function.h Thu Aug 01 18:49:28 2019 +0300 @@ -129,7 +129,7 @@ njs_int_t njs_function_lambda_frame(njs_ const njs_value_t *this, const njs_value_t *args, njs_uint_t nargs, njs_bool_t ctor); njs_int_t njs_function_call(njs_vm_t *vm, njs_function_t *function, - njs_value_t *this, njs_value_t *args, njs_uint_t nargs, + const njs_value_t *this, const njs_value_t *args, njs_uint_t nargs, njs_value_t *retval); njs_int_t njs_function_lambda_call(njs_vm_t *vm); njs_int_t njs_function_native_call(njs_vm_t *vm); @@ -199,8 +199,8 @@ njs_function_frame_invoke(njs_vm_t *vm, njs_inline njs_int_t -njs_function_apply(njs_vm_t *vm, njs_function_t *function, njs_value_t *args, - njs_uint_t nargs, njs_value_t *retval) +njs_function_apply(njs_vm_t *vm, njs_function_t *function, + const njs_value_t *args, njs_uint_t nargs, njs_value_t *retval) { return njs_function_call(vm, function, &args[0], &args[1], nargs - 1, retval); diff -r 26802fc27c76 -r b0823626551d src/njs_json.c --- a/src/njs_json.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_json.c Thu Aug 01 18:49:28 2019 +0300 @@ -252,8 +252,7 @@ njs_json_stringify(njs_vm_t *vm, njs_val double num; njs_int_t i; njs_int_t ret; - njs_value_t *wrapper; - const njs_value_t *replacer, *space; + njs_value_t *wrapper, *replacer, *space; njs_json_stringify_t *stringify, json_stringify; stringify = &json_stringify; @@ -1802,7 +1801,7 @@ njs_json_append_string(njs_json_stringif static char hex2char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - (void) njs_string_prop(&str, (njs_value_t *) value); + (void) njs_string_prop(&str, value); p = str.start; end = p + str.size; diff -r 26802fc27c76 -r b0823626551d src/njs_object.c --- a/src/njs_object.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_object.c Thu Aug 01 18:49:28 2019 +0300 @@ -193,9 +193,9 @@ njs_int_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_uint_t type; - njs_object_t *object; - const njs_value_t *value; + njs_uint_t type; + njs_value_t *value; + njs_object_t *object; value = njs_arg(args, nargs, 1); type = value->type; @@ -244,8 +244,8 @@ static njs_int_t njs_object_create(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_object_t *object; - const njs_value_t *value; + njs_value_t *value; + njs_object_t *object; value = njs_arg(args, nargs, 1); @@ -280,8 +280,8 @@ static njs_int_t njs_object_keys(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_array_t *keys; - const njs_value_t *value; + njs_value_t *value; + njs_array_t *keys; value = njs_arg(args, nargs, 1); @@ -307,8 +307,8 @@ static njs_int_t njs_object_values(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_array_t *array; - const njs_value_t *value; + njs_array_t *array; + njs_value_t *value; value = njs_arg(args, nargs, 1); @@ -334,8 +334,8 @@ static njs_int_t njs_object_entries(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_array_t *array; - const njs_value_t *value; + njs_array_t *array; + njs_value_t *value; value = njs_arg(args, nargs, 1); @@ -1087,9 +1087,8 @@ static njs_int_t njs_object_define_property(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_int_t ret; - njs_value_t *value; - const njs_value_t *name, *desc; + njs_int_t ret; + njs_value_t *value, *name, *desc; if (!njs_is_object(njs_arg(args, nargs, 1))) { njs_type_error(vm, "cannot convert %s argument to object", @@ -1129,11 +1128,10 @@ njs_object_define_properties(njs_vm_t *v njs_index_t unused) { njs_int_t ret; - njs_value_t *value; + njs_value_t *value, *desc; njs_lvlhsh_t *hash; njs_lvlhsh_each_t lhe; njs_object_prop_t *prop; - const njs_value_t *desc; if (!njs_is_object(njs_arg(args, nargs, 1))) { njs_type_error(vm, "cannot convert %s argument to object", @@ -1185,7 +1183,7 @@ static njs_int_t njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - const njs_value_t *value, *property; + njs_value_t *value, *property; value = njs_arg(args, nargs, 1); @@ -1208,9 +1206,8 @@ njs_object_get_own_property_descriptors( njs_int_t ret; uint32_t i, length; njs_array_t *names; - njs_value_t descriptor; + njs_value_t descriptor, *value, *key; njs_object_t *descriptors; - const njs_value_t *value, *key; njs_object_prop_t *pr; njs_lvlhsh_query_t lhq; @@ -1272,8 +1269,8 @@ static njs_int_t njs_object_get_own_property_names(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_array_t *names; - const njs_value_t *value; + njs_array_t *names; + njs_value_t *value; value = njs_arg(args, nargs, 1); @@ -1299,13 +1296,12 @@ static njs_int_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - const njs_value_t *value; + njs_value_t *value; value = njs_arg(args, nargs, 1); if (njs_is_object(value)) { - njs_object_prototype_proto(vm, (njs_value_t *) value, NULL, - &vm->retval); + njs_object_prototype_proto(vm, value, NULL, &vm->retval); return NJS_OK; } @@ -1320,11 +1316,11 @@ static njs_int_t njs_object_freeze(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_value_t *value; njs_lvlhsh_t *hash; njs_object_t *object; njs_object_prop_t *prop; njs_lvlhsh_each_t lhe; - const njs_value_t *value; value = njs_arg(args, nargs, 1); @@ -1361,11 +1357,12 @@ static njs_int_t njs_object_is_frozen(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_value_t *value; njs_lvlhsh_t *hash; njs_object_t *object; njs_object_prop_t *prop; njs_lvlhsh_each_t lhe; - const njs_value_t *value, *retval; + const njs_value_t *retval; value = njs_arg(args, nargs, 1); @@ -1415,9 +1412,9 @@ static njs_int_t njs_object_seal(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_value_t *value; njs_lvlhsh_t *hash; njs_object_t *object; - const njs_value_t *value; njs_object_prop_t *prop; njs_lvlhsh_each_t lhe; @@ -1455,11 +1452,12 @@ static njs_int_t njs_object_is_sealed(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_value_t *value; njs_lvlhsh_t *hash; njs_object_t *object; njs_object_prop_t *prop; njs_lvlhsh_each_t lhe; - const njs_value_t *value, *retval; + const njs_value_t *retval; value = njs_arg(args, nargs, 1); @@ -1505,7 +1503,7 @@ static njs_int_t njs_object_prevent_extensions(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - const njs_value_t *value; + njs_value_t *value; value = njs_arg(args, nargs, 1); @@ -1526,7 +1524,8 @@ static njs_int_t njs_object_is_extensible(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - const njs_value_t *value, *retval; + njs_value_t *value; + const njs_value_t *retval; value = njs_arg(args, nargs, 1); @@ -2114,7 +2113,7 @@ njs_object_prototype_has_own_property(nj njs_uint_t nargs, njs_index_t unused) { njs_int_t ret; - const njs_value_t *value, *property; + njs_value_t *value, *property; njs_property_query_t pq; value = njs_arg(args, nargs, 0); @@ -2129,7 +2128,7 @@ njs_object_prototype_has_own_property(nj njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, (njs_value_t *) value, property); + ret = njs_property_query(vm, &pq, value, property); switch (ret) { case NJS_OK: @@ -2152,7 +2151,8 @@ njs_object_prototype_prop_is_enumerable( njs_uint_t nargs, njs_index_t unused) { njs_int_t ret; - const njs_value_t *value, *property, *retval; + njs_value_t *value, *property; + const njs_value_t *retval; njs_object_prop_t *prop; njs_property_query_t pq; @@ -2168,7 +2168,7 @@ njs_object_prototype_prop_is_enumerable( njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, (njs_value_t *) value, property); + ret = njs_property_query(vm, &pq, value, property); switch (ret) { case NJS_OK: @@ -2195,8 +2195,9 @@ static njs_int_t njs_object_prototype_is_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { + njs_value_t *prototype, *value; njs_object_t *object, *proto; - const njs_value_t *prototype, *value, *retval; + const njs_value_t *retval; retval = &njs_value_false; prototype = &args[0]; diff -r 26802fc27c76 -r b0823626551d src/njs_object.h --- a/src/njs_object.h Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_object.h Thu Aug 01 18:49:28 2019 +0300 @@ -125,19 +125,19 @@ njs_int_t njs_object_prototype_to_string njs_uint_t nargs, njs_index_t unused); njs_int_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_value_t *object, const njs_value_t *property); -njs_int_t njs_value_property(njs_vm_t *vm, const njs_value_t *value, - const njs_value_t *property, njs_value_t *retval); + njs_value_t *object, njs_value_t *property); +njs_int_t njs_value_property(njs_vm_t *vm, njs_value_t *value, + njs_value_t *property, njs_value_t *retval); njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *property, njs_value_t *value); + njs_value_t *property, njs_value_t *value); njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, const njs_value_t *value, uint8_t attributes); njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj, njs_lvlhsh_query_t *lhq); njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *name, const njs_value_t *value); + njs_value_t *name, njs_value_t *value); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, - const njs_value_t *value, const njs_value_t *property); + njs_value_t *value, njs_value_t *property); njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); const char *njs_prop_type_string(njs_object_prop_type_t type); diff -r 26802fc27c76 -r b0823626551d src/njs_object_property.c --- a/src/njs_object_property.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_object_property.c Thu Aug 01 18:49:28 2019 +0300 @@ -46,7 +46,7 @@ static njs_object_prop_t *njs_descriptor njs_int_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, - const njs_value_t *property) + njs_value_t *property) { uint32_t index; njs_int_t ret; @@ -55,7 +55,7 @@ njs_property_query(njs_vm_t *vm, njs_pro njs_function_t *function; if (njs_slow_path(!njs_is_primitive(property))) { - ret = njs_value_to_string(vm, &prop, (njs_value_t *) property); + ret = njs_value_to_string(vm, &prop, property); if (ret != NJS_OK) { return ret; } @@ -479,8 +479,8 @@ njs_external_property_delete(njs_vm_t *v * retval will contain undefined */ njs_int_t -njs_value_property(njs_vm_t *vm, const njs_value_t *value, - const njs_value_t *property, njs_value_t *retval) +njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *property, + njs_value_t *retval) { njs_int_t ret; njs_object_prop_t *prop; @@ -488,7 +488,7 @@ njs_value_property(njs_vm_t *vm, const n njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - ret = njs_property_query(vm, &pq, (njs_value_t *) value, property); + ret = njs_property_query(vm, &pq, value, property); switch (ret) { @@ -521,14 +521,14 @@ njs_value_property(njs_vm_t *vm, const n break; } - return njs_function_apply(vm, njs_function(&prop->getter), - (njs_value_t *) value, 1, retval); + return njs_function_apply(vm, njs_function(&prop->getter), value, + 1, retval); case NJS_PROPERTY_HANDLER: pq.scratch = *prop; prop = &pq.scratch; - ret = prop->value.data.u.prop_handler(vm, (njs_value_t *) value, - NULL, &prop->value); + ret = prop->value.data.u.prop_handler(vm, value, NULL, + &prop->value); if (njs_slow_path(ret != NJS_OK)) { return ret; @@ -568,7 +568,7 @@ njs_value_property(njs_vm_t *vm, const n */ njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *property, njs_value_t *value) + njs_value_t *property, njs_value_t *value) { njs_int_t ret; njs_object_prop_t *prop, *shared; @@ -771,7 +771,7 @@ njs_object_property(njs_vm_t *vm, const */ njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *name, const njs_value_t *value) + njs_value_t *name, njs_value_t *value) { njs_int_t ret; njs_object_prop_t *prop, *prev; @@ -1123,7 +1123,7 @@ static const njs_value_t njs_object_con njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, - const njs_value_t *value, const njs_value_t *property) + njs_value_t *value, njs_value_t *property) { njs_int_t ret; njs_object_t *desc; @@ -1134,7 +1134,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, (njs_value_t *) value, property); + ret = njs_property_query(vm, &pq, value, property); switch (ret) { case NJS_OK: @@ -1158,8 +1158,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, case NJS_PROPERTY_HANDLER: pq.scratch = *prop; prop = &pq.scratch; - ret = prop->value.data.u.prop_handler(vm, (njs_value_t *) value, - NULL, &prop->value); + ret = prop->value.data.u.prop_handler(vm, value, NULL, &prop->value); if (njs_slow_path(ret != NJS_OK)) { return ret; } diff -r 26802fc27c76 -r b0823626551d src/njs_regexp.c --- a/src/njs_regexp.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_regexp.c Thu Aug 01 18:49:28 2019 +0300 @@ -105,8 +105,7 @@ njs_regexp_constructor(njs_vm_t *vm, njs u_char *start; njs_int_t ret; njs_str_t string; - njs_value_t source, flags_string; - const njs_value_t *pattern, *flags; + njs_value_t source, flags_string, *pattern, *flags; njs_regexp_flags_t re_flags; pattern = njs_arg(args, nargs, 1); @@ -130,8 +129,7 @@ njs_regexp_constructor(njs_vm_t *vm, njs re_flags = 0; if (njs_is_regexp(pattern)) { - ret = njs_regexp_prototype_source(vm, (njs_value_t *) pattern, NULL, - &source); + ret = njs_regexp_prototype_source(vm, pattern, NULL, &source); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -142,7 +140,7 @@ njs_regexp_constructor(njs_vm_t *vm, njs } else { if (njs_is_undefined(pattern)) { - pattern = &njs_string_empty; + pattern = njs_value_arg(&njs_string_empty); } ret = njs_primitive_value_to_string(vm, &source, pattern); diff -r 26802fc27c76 -r b0823626551d src/njs_string.c --- a/src/njs_string.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_string.c Thu Aug 01 18:49:28 2019 +0300 @@ -1271,8 +1271,8 @@ static void njs_string_slice_args(njs_slice_prop_t *slice, njs_value_t *args, njs_uint_t nargs) { - ssize_t start, end, length; - const njs_value_t *value; + ssize_t start, end, length; + njs_value_t *value; length = slice->string_length; @@ -1444,7 +1444,7 @@ static njs_int_t njs_string_bytes_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - const njs_value_t *value; + njs_value_t *value; value = njs_arg(args, nargs, 1); @@ -1504,8 +1504,8 @@ static njs_int_t njs_string_bytes_from_string(njs_vm_t *vm, const njs_value_t *args, njs_uint_t nargs) { - njs_str_t enc, str; - const njs_value_t *enc_val; + njs_str_t enc, str; + njs_value_t *enc_val; enc_val = njs_arg(args, nargs, 2); diff -r 26802fc27c76 -r b0823626551d src/njs_vm.c --- a/src/njs_vm.c Thu Aug 01 18:48:39 2019 +0300 +++ b/src/njs_vm.c Thu Aug 01 18:49:28 2019 +0300 @@ -471,12 +471,9 @@ njs_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args, njs_uint_t nargs, njs_index_t retval) { - njs_int_t ret; - njs_value_t *this; + njs_int_t ret; From xeioex at nginx.com Thu Aug 1 18:01:32 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 01 Aug 2019 18:01:32 +0000 Subject: [njs] Merging njs_alignment.h into njs_clang.h. Message-ID: details: https://hg.nginx.org/njs/rev/7356d868d2cd branches: changeset: 1091:7356d868d2cd user: Dmitry Volyntsev date: Thu Aug 01 18:49:29 2019 +0300 description: Merging njs_alignment.h into njs_clang.h. diffstat: src/njs_alignment.h | 49 ------------------------------------------------- src/njs_clang.h | 38 ++++++++++++++++++++++++++++++++++++++ src/njs_main.h | 1 - src/njs_mp.c | 1 - 4 files changed, 38 insertions(+), 51 deletions(-) diffs (121 lines): diff -r b0823626551d -r 7356d868d2cd src/njs_alignment.h --- a/src/njs_alignment.h Thu Aug 01 18:49:28 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NJS_ALIGNMENT_H_INCLUDED_ -#define _NJS_ALIGNMENT_H_INCLUDED_ - - -#ifndef NJS_MAX_ALIGNMENT - -#if (NJS_SOLARIS) -/* x86_64: 16, i386: 4, sparcv9: 16, sparcv8: 8. */ -#define NJS_MAX_ALIGNMENT _MAX_ALIGNMENT - -#elif (NJS_WINDOWS) -/* Win64: 16, Win32: 8. */ -#define NJS_MAX_ALIGNMENT MEMORY_ALLOCATION_ALIGNMENT - -#elif (__amd64__) -#define NJS_MAX_ALIGNMENT 16 - -#elif (__i386__ || __i386) -#define NJS_MAX_ALIGNMENT 4 - -#elif (__arm__) -#define NJS_MAX_ALIGNMENT 16 - -#else -#define NJS_MAX_ALIGNMENT 16 -#endif - -#endif - - -#define njs_align_size(size, a) \ - (((size) + ((size_t) (a) - 1)) & ~((size_t) (a) - 1)) - - -#define njs_align_ptr(p, a) \ - (u_char *) (((uintptr_t) (p) + ((uintptr_t) (a) - 1)) \ - & ~((uintptr_t) (a) - 1)) - -#define njs_trunc_ptr(p, a) \ - (u_char *) ((uintptr_t) (p) & ~((uintptr_t) (a) - 1)) - - -#endif /* _NJS_ALIGNMENT_H_INCLUDED_ */ diff -r b0823626551d -r 7356d868d2cd src/njs_clang.h --- a/src/njs_clang.h Thu Aug 01 18:49:28 2019 +0300 +++ b/src/njs_clang.h Thu Aug 01 18:49:29 2019 +0300 @@ -157,4 +157,42 @@ njs_leading_zeros64(uint64_t x) #endif +#ifndef NJS_MAX_ALIGNMENT + +#if (NJS_SOLARIS) +/* x86_64: 16, i386: 4, sparcv9: 16, sparcv8: 8. */ +#define NJS_MAX_ALIGNMENT _MAX_ALIGNMENT + +#elif (NJS_WINDOWS) +/* Win64: 16, Win32: 8. */ +#define NJS_MAX_ALIGNMENT MEMORY_ALLOCATION_ALIGNMENT + +#elif (__amd64__) +#define NJS_MAX_ALIGNMENT 16 + +#elif (__i386__ || __i386) +#define NJS_MAX_ALIGNMENT 4 + +#elif (__arm__) +#define NJS_MAX_ALIGNMENT 16 + +#else +#define NJS_MAX_ALIGNMENT 16 +#endif + +#endif + + +#define njs_align_size(size, a) \ + (((size) + ((size_t) (a) - 1)) & ~((size_t) (a) - 1)) + + +#define njs_align_ptr(p, a) \ + (u_char *) (((uintptr_t) (p) + ((uintptr_t) (a) - 1)) \ + & ~((uintptr_t) (a) - 1)) + +#define njs_trunc_ptr(p, a) \ + (u_char *) ((uintptr_t) (p) & ~((uintptr_t) (a) - 1)) + + #endif /* _NJS_CLANG_H_INCLUDED_ */ diff -r b0823626551d -r 7356d868d2cd src/njs_main.h --- a/src/njs_main.h Thu Aug 01 18:49:28 2019 +0300 +++ b/src/njs_main.h Thu Aug 01 18:49:29 2019 +0300 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff -r b0823626551d -r 7356d868d2cd src/njs_mp.c --- a/src/njs_mp.c Thu Aug 01 18:49:28 2019 +0300 +++ b/src/njs_mp.c Thu Aug 01 18:49:29 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include From xeioex at nginx.com Thu Aug 1 18:01:32 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 01 Aug 2019 18:01:32 +0000 Subject: [njs] Removing njs_mem_proto_t from njs_mp_t. Message-ID: details: https://hg.nginx.org/njs/rev/84f4da1e7d96 branches: changeset: 1092:84f4da1e7d96 user: Dmitry Volyntsev date: Thu Aug 01 21:01:16 2019 +0300 description: Removing njs_mem_proto_t from njs_mp_t. diffstat: src/njs.h | 2 - src/njs_malloc.c | 18 +++++++++ src/njs_malloc.h | 3 +- src/njs_mp.c | 82 ++++++++++++++++---------------------------- src/njs_mp.h | 22 ++++++++--- src/njs_vm.c | 53 +--------------------------- src/test/lvlhsh_unit_test.c | 65 +---------------------------------- 7 files changed, 69 insertions(+), 176 deletions(-) diffs (479 lines): diff -r 7356d868d2cd -r 84f4da1e7d96 src/njs.h --- a/src/njs.h Thu Aug 01 18:49:29 2019 +0300 +++ b/src/njs.h Thu Aug 01 21:01:16 2019 +0300 @@ -295,6 +295,4 @@ NJS_EXPORT njs_int_t njs_vm_json_parse(n NJS_EXPORT njs_int_t njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs); -extern const njs_mem_proto_t njs_vm_mp_proto; - #endif /* _NJS_H_INCLUDED_ */ diff -r 7356d868d2cd -r 84f4da1e7d96 src/njs_malloc.c --- a/src/njs_malloc.c Thu Aug 01 18:49:29 2019 +0300 +++ b/src/njs_malloc.c Thu Aug 01 21:01:16 2019 +0300 @@ -7,8 +7,26 @@ #include #include #include +#include #include +#include + + +void * +njs_zalloc(size_t size) +{ + void *p; + + p = njs_malloc(size); + + if (njs_fast_path(p != NULL)) { + njs_memzero(p, size); + } + + return p; +} + #if (NJS_HAVE_POSIX_MEMALIGN) diff -r 7356d868d2cd -r 84f4da1e7d96 src/njs_malloc.h --- a/src/njs_malloc.h Thu Aug 01 18:49:29 2019 +0300 +++ b/src/njs_malloc.h Thu Aug 01 21:01:16 2019 +0300 @@ -22,7 +22,8 @@ #define njs_free(p) free(p) -NJS_EXPORT void *njs_memalign(size_t alignment, size_t size); +NJS_EXPORT void *njs_zalloc(size_t size) NJS_MALLOC_LIKE; +NJS_EXPORT void *njs_memalign(size_t alignment, size_t size) NJS_MALLOC_LIKE; #endif /* _NJS_MALLOC_H_INCLUDED_ */ diff -r 7356d868d2cd -r 84f4da1e7d96 src/njs_mp.c --- a/src/njs_mp.c Thu Aug 01 18:49:29 2019 +0300 +++ b/src/njs_mp.c Thu Aug 01 21:01:16 2019 +0300 @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -114,10 +116,6 @@ struct njs_mp_s { uint32_t page_alignment; uint32_t cluster_size; - const njs_mem_proto_t *proto; - void *mem; - void *trace; - njs_mp_slot_t slots[]; }; @@ -155,8 +153,7 @@ static const char *njs_mp_chunk_free(njs njs_mp_t * -njs_mp_create(const njs_mem_proto_t *proto, void *mem, - void *trace, size_t cluster_size, size_t page_alignment, size_t page_size, +njs_mp_create(size_t cluster_size, size_t page_alignment, size_t page_size, size_t min_chunk_size) { /* Alignment and sizes must be a power of 2. */ @@ -181,14 +178,13 @@ njs_mp_create(const njs_mem_proto_t *pro return NULL; } - return njs_mp_fast_create(proto, mem, trace, cluster_size, page_alignment, - page_size, min_chunk_size); + return njs_mp_fast_create(cluster_size, page_alignment, page_size, + min_chunk_size); } njs_mp_t * -njs_mp_fast_create(const njs_mem_proto_t *proto, void *mem, - void *trace, size_t cluster_size, size_t page_alignment, size_t page_size, +njs_mp_fast_create(size_t cluster_size, size_t page_alignment, size_t page_size, size_t min_chunk_size) { njs_mp_t *mp; @@ -203,13 +199,9 @@ njs_mp_fast_create(const njs_mem_proto_t chunk_size /= 2; } while (chunk_size > min_chunk_size); - mp = proto->zalloc(mem, sizeof(njs_mp_t) + slots * sizeof(njs_mp_slot_t)); + mp = njs_zalloc(sizeof(njs_mp_t) + slots * sizeof(njs_mp_slot_t)); if (njs_fast_path(mp != NULL)) { - mp->proto = proto; - mp->mem = mem; - mp->trace = trace; - mp->page_size = page_size; mp->page_alignment = njs_max(page_alignment, NJS_MAX_ALIGNMENT); mp->cluster_size = cluster_size; @@ -271,6 +263,8 @@ njs_mp_destroy(njs_mp_t *mp) njs_mp_block_t *block; njs_rbtree_node_t *node, *next; + njs_debug_alloc("mp destroy\n"); + next = njs_rbtree_root(&mp->blocks); while (next != njs_rbtree_sentinel(&mp->blocks)) { @@ -281,22 +275,20 @@ njs_mp_destroy(njs_mp_t *mp) p = block->start; if (block->type != NJS_MP_EMBEDDED_BLOCK) { - mp->proto->free(mp->mem, block); + njs_free(block); } - mp->proto->free(mp->mem, p); + njs_free(p); } - mp->proto->free(mp->mem, mp); + njs_free(mp); } void * njs_mp_alloc(njs_mp_t *mp, size_t size) { - if (mp->proto->trace != NULL) { - mp->proto->trace(mp->trace, "mem cache alloc: %zd", size); - } + njs_debug_alloc("mp alloc: %uz\n", size); #if !(NJS_DEBUG_MEMORY) @@ -328,10 +320,7 @@ njs_mp_zalloc(njs_mp_t *mp, size_t size) void * njs_mp_align(njs_mp_t *mp, size_t alignment, size_t size) { - if (mp->proto->trace != NULL) { - mp->proto->trace(mp->trace, - "mem cache align: @%zd:%zd", alignment, size); - } + njs_debug_alloc("mp align: @%uz:%uz\n", alignment, size); /* Alignment must be a power of 2. */ @@ -456,9 +445,7 @@ njs_mp_alloc_small(njs_mp_t *mp, size_t #endif } - if (mp->proto->trace != NULL) { - mp->proto->trace(mp->trace, "mem cache chunk:%uz alloc: %p", size, p); - } + njs_debug_alloc("mp chunk:%uz alloc: %p\n", size, p); return p; } @@ -533,9 +520,7 @@ njs_mp_alloc_cluster(njs_mp_t *mp) n = mp->cluster_size >> mp->page_size_shift; - cluster = mp->proto->zalloc(mp->mem, - sizeof(njs_mp_block_t) - + n * sizeof(njs_mp_page_t)); + cluster = njs_zalloc(sizeof(njs_mp_block_t) + n * sizeof(njs_mp_page_t)); if (njs_slow_path(cluster == NULL)) { return NULL; @@ -545,10 +530,9 @@ njs_mp_alloc_cluster(njs_mp_t *mp) cluster->size = mp->cluster_size; - cluster->start = mp->proto->align(mp->mem, mp->page_alignment, - mp->cluster_size); + cluster->start = njs_memalign(mp->page_alignment, mp->cluster_size); if (njs_slow_path(cluster->start == NULL)) { - mp->proto->free(mp->mem, cluster); + njs_free(cluster); return NULL; } @@ -585,14 +569,14 @@ njs_mp_alloc_large(njs_mp_t *mp, size_t } if (njs_is_power_of_two(size)) { - block = mp->proto->alloc(mp->mem, sizeof(njs_mp_block_t)); + block = njs_malloc(sizeof(njs_mp_block_t)); if (njs_slow_path(block == NULL)) { return NULL; } - p = mp->proto->align(mp->mem, alignment, size); + p = njs_memalign(alignment, size); if (njs_slow_path(p == NULL)) { - mp->proto->free(mp->mem, block); + njs_free(block); return NULL; } @@ -601,9 +585,7 @@ njs_mp_alloc_large(njs_mp_t *mp, size_t } else { aligned_size = njs_align_size(size, sizeof(uintptr_t)); - p = mp->proto->align(mp->mem, alignment, - aligned_size + sizeof(njs_mp_block_t)); - + p = njs_memalign(alignment, aligned_size + sizeof(njs_mp_block_t)); if (njs_slow_path(p == NULL)) { return NULL; } @@ -640,9 +622,7 @@ njs_mp_free(njs_mp_t *mp, void *p) const char *err; njs_mp_block_t *block; - if (mp->proto->trace != NULL) { - mp->proto->trace(mp->trace, "mem cache free %p", p); - } + njs_debug_alloc("mp free: @%p\n", p); block = njs_mp_find_block(&mp->blocks, p); @@ -659,24 +639,22 @@ njs_mp_free(njs_mp_t *mp, void *p) njs_rbtree_delete(&mp->blocks, &block->node); if (block->type == NJS_MP_DISCRETE_BLOCK) { - mp->proto->free(mp->mem, block); + njs_free(block); } - mp->proto->free(mp->mem, p); + njs_free(p); return; } else { - err = "freed pointer points to middle of block: %p"; + err = "freed pointer points to middle of block: %p\n"; } } else { - err = "freed pointer is out of mp: %p"; + err = "freed pointer is out of mp: %p\n"; } - if (mp->proto->alert != NULL) { - mp->proto->alert(mp->trace, err, p); - } + njs_debug_alloc(err, p); } @@ -810,8 +788,8 @@ njs_mp_chunk_free(njs_mp_t *mp, njs_mp_b p = cluster->start; - mp->proto->free(mp->mem, cluster); - mp->proto->free(mp->mem, p); + njs_free(cluster); + njs_free(p); return NULL; } diff -r 7356d868d2cd -r 84f4da1e7d96 src/njs_mp.h --- a/src/njs_mp.h Thu Aug 01 18:49:29 2019 +0300 +++ b/src/njs_mp.h Thu Aug 01 21:01:16 2019 +0300 @@ -11,13 +11,10 @@ typedef struct njs_mp_s njs_mp_t; -NJS_EXPORT njs_mp_t *njs_mp_create(const njs_mem_proto_t *proto, void *mem, - void *trace, size_t cluster_size, size_t page_alignment, size_t page_size, - size_t min_chunk_size) - NJS_MALLOC_LIKE; -NJS_EXPORT njs_mp_t * njs_mp_fast_create(const njs_mem_proto_t *proto, - void *mem, void *trace, size_t cluster_size, size_t page_alignment, - size_t page_size, size_t min_chunk_size) +NJS_EXPORT njs_mp_t *njs_mp_create(size_t cluster_size, size_t page_alignment, + size_t page_size, size_t min_chunk_size) NJS_MALLOC_LIKE; +NJS_EXPORT njs_mp_t * njs_mp_fast_create(size_t cluster_size, + size_t page_alignment, size_t page_size, size_t min_chunk_size) NJS_MALLOC_LIKE; NJS_EXPORT njs_bool_t njs_mp_is_empty(njs_mp_t *mp); NJS_EXPORT void njs_mp_destroy(njs_mp_t *mp); @@ -34,4 +31,15 @@ NJS_EXPORT void *njs_mp_zalign(njs_mp_t NJS_EXPORT void njs_mp_free(njs_mp_t *mp, void *p); +#if (NJS_ALLOC_DEBUG) +#define njs_debug_alloc(...) \ + njs_stderror(__VA_ARGS__) + +#else + +#define njs_debug_alloc(...) + +#endif + + #endif /* _NJS_MP_H_INCLUDED_ */ diff -r 7356d868d2cd -r 84f4da1e7d96 src/njs_vm.c --- a/src/njs_vm.c Thu Aug 01 18:49:29 2019 +0300 +++ b/src/njs_vm.c Thu Aug 01 21:01:16 2019 +0300 @@ -21,53 +21,6 @@ const njs_str_t njs_entry_anonymous = static void * -njs_alloc(void *mem, size_t size) -{ - return njs_malloc(size); -} - - -static void * -njs_zalloc(void *mem, size_t size) -{ - void *p; - - p = njs_malloc(size); - - if (p != NULL) { - njs_memzero(p, size); - } - - return p; -} - - -static void * -njs_align(void *mem, size_t alignment, size_t size) -{ - return njs_memalign(alignment, size); -} - - -static void -njs_free2(void *mem, void *p) -{ - njs_free(p); -} - - -const njs_mem_proto_t njs_vm_mp_proto = { - njs_alloc, - njs_zalloc, - njs_align, - NULL, - njs_free2, - NULL, - NULL, -}; - - -static void * njs_array_mem_alloc(void *mem, size_t size) { return njs_mp_alloc(mem, size); @@ -101,8 +54,7 @@ njs_vm_create(njs_vm_opt_t *options) njs_arr_t *debug; njs_regexp_pattern_t *pattern; - mp = njs_mp_create(&njs_vm_mp_proto, NULL, NULL, 2 * njs_pagesize(), - 128, 512, 16); + mp = njs_mp_fast_create(2 * njs_pagesize(), 128, 512, 16); if (njs_slow_path(mp == NULL)) { return NULL; } @@ -325,8 +277,7 @@ njs_vm_clone(njs_vm_t *vm, njs_external_ return NULL; } - nmp = njs_mp_create(&njs_vm_mp_proto, NULL, NULL, 2 * njs_pagesize(), - 128, 512, 16); + nmp = njs_mp_fast_create(2 * njs_pagesize(), 128, 512, 16); if (njs_slow_path(nmp == NULL)) { return NULL; } diff -r 7356d868d2cd -r 84f4da1e7d96 src/test/lvlhsh_unit_test.c --- a/src/test/lvlhsh_unit_test.c Thu Aug 01 18:49:29 2019 +0300 +++ b/src/test/lvlhsh_unit_test.c Thu Aug 01 21:01:16 2019 +0300 @@ -129,67 +129,6 @@ lvlhsh_unit_test_delete(njs_lvlhsh_t *lh } -static void * -lvlhsh_malloc(void *mem, size_t size) -{ - return njs_malloc(size); -} - - -static void * -lvlhsh_zalloc(void *mem, size_t size) -{ - void *p; - - p = njs_malloc(size); - - if (p != NULL) { - njs_memzero(p, size); - } - - return p; -} - - -static void * -lvlhsh_align(void *mem, size_t alignment, size_t size) -{ - return njs_memalign(alignment, size); -} - - -static void -lvlhsh_free(void *mem, void *p) -{ - njs_free(p); -} - - -static void -lvlhsh_alert(void *mem, const char *fmt, ...) -{ - u_char buf[1024], *p; - va_list args; - - va_start(args, fmt); - p = njs_sprintf(buf, buf + sizeof(buf), fmt, args); - va_end(args); - - (void) njs_stderror("alert: \"%*s\"\n", p - buf, buf); -} - - -static const njs_mem_proto_t lvl_mp_proto = { - lvlhsh_malloc, - lvlhsh_zalloc, - lvlhsh_align, - NULL, - lvlhsh_free, - lvlhsh_alert, - NULL, -}; - - static njs_int_t lvlhsh_unit_test(njs_uint_t n) { @@ -204,8 +143,8 @@ lvlhsh_unit_test(njs_uint_t n) const size_t page_alignment = 128; const size_t cluster_size = 4096; - pool = njs_mp_create(&lvl_mp_proto, NULL, NULL, cluster_size, - page_alignment, page_size, min_chunk_size); + pool = njs_mp_create(cluster_size, page_alignment, page_size, + min_chunk_size); if (pool == NULL) { return NJS_ERROR; } From xeioex at nginx.com Fri Aug 2 09:32:09 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 09:32:09 +0000 Subject: [njs] Removing njs_stub.h. Message-ID: details: https://hg.nginx.org/njs/rev/81b272f75471 branches: changeset: 1094:81b272f75471 user: Dmitry Volyntsev date: Fri Aug 02 12:12:35 2019 +0300 description: Removing njs_stub.h. diffstat: src/njs.h | 1 - src/njs_clang.h | 6 ++++++ src/njs_djb_hash.c | 1 - src/njs_lvlhsh.c | 1 - src/njs_main.h | 1 - src/njs_mp.c | 1 - src/njs_pcre.c | 1 - src/njs_sprintf.c | 1 - src/njs_stub.h | 34 ---------------------------------- src/njs_trace.h | 6 ++++++ src/njs_types.h | 7 +++++++ src/njs_unix.h | 3 +++ src/test/lvlhsh_unit_test.c | 1 - src/test/random_unit_test.c | 1 - src/test/rbtree_unit_test.c | 1 - src/test/utf8_unit_test.c | 1 - 16 files changed, 22 insertions(+), 45 deletions(-) diffs (221 lines): diff -r aaec532e9d08 -r 81b272f75471 src/njs.h --- a/src/njs.h Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs.h Fri Aug 02 12:12:35 2019 +0300 @@ -17,7 +17,6 @@ #include #include #include -#include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_clang.h --- a/src/njs_clang.h Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_clang.h Fri Aug 02 12:12:35 2019 +0300 @@ -24,6 +24,12 @@ #define njs_nitems(x) \ (sizeof(x) / sizeof((x)[0])) +#define njs_max(val1, val2) \ + ((val1 < val2) ? (val2) : (val1)) + +#define njs_min(val1, val2) \ + ((val1 < val2) ? (val1) : (val2)) + #if (NJS_HAVE_BUILTIN_EXPECT) #define njs_expect(c, x) __builtin_expect((long) (x), (c)) diff -r aaec532e9d08 -r 81b272f75471 src/njs_djb_hash.c --- a/src/njs_djb_hash.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_djb_hash.c Fri Aug 02 12:12:35 2019 +0300 @@ -8,7 +8,6 @@ #include #include #include -#include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_lvlhsh.c --- a/src/njs_lvlhsh.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_lvlhsh.c Fri Aug 02 12:12:35 2019 +0300 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_main.h --- a/src/njs_main.h Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_main.h Fri Aug 02 12:12:35 2019 +0300 @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_mp.c --- a/src/njs_mp.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_mp.c Fri Aug 02 12:12:35 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_pcre.c --- a/src/njs_pcre.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_pcre.c Fri Aug 02 12:12:35 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_sprintf.c --- a/src/njs_sprintf.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_sprintf.c Fri Aug 02 12:12:35 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/njs_stub.h --- a/src/njs_stub.h Fri Aug 02 12:12:30 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NJS_STUB_H_INCLUDED_ -#define _NJS_STUB_H_INCLUDED_ - - -#define njs_max(val1, val2) \ - ((val1 < val2) ? (val2) : (val1)) - -#define njs_min(val1, val2) \ - ((val1 < val2) ? (val1) : (val2)) - - -#define NJS_OK 0 -#define NJS_ERROR (-1) -#define NJS_AGAIN (-2) -#define NJS_DECLINED (-3) -#define NJS_DONE (-4) - - -#define njs_thread_log_alert(...) -#define njs_thread_log_error(...) -#define njs_log_error(...) -#define njs_thread_log_debug(...) - -#include -#define njs_pagesize() getpagesize() - - -#endif /* _NJS_STUB_H_INCLUDED_ */ diff -r aaec532e9d08 -r 81b272f75471 src/njs_trace.h --- a/src/njs_trace.h Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_trace.h Fri Aug 02 12:12:35 2019 +0300 @@ -61,6 +61,12 @@ struct njs_trace_s { } while (0) +#define njs_thread_log_alert(...) +#define njs_thread_log_error(...) +#define njs_log_error(...) +#define njs_thread_log_debug(...) + + NJS_EXPORT void njs_trace_handler(njs_trace_t *trace, uint32_t level, const char *fmt, ...); diff -r aaec532e9d08 -r 81b272f75471 src/njs_types.h --- a/src/njs_types.h Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_types.h Fri Aug 02 12:12:35 2019 +0300 @@ -8,6 +8,13 @@ #define _NJS_TYPES_H_INCLUDED_ +#define NJS_OK 0 +#define NJS_ERROR (-1) +#define NJS_AGAIN (-2) +#define NJS_DECLINED (-3) +#define NJS_DONE (-4) + + /* * off_t is 32 bit on Linux, Solaris and HP-UX by default. * Must be before . diff -r aaec532e9d08 -r 81b272f75471 src/njs_unix.h --- a/src/njs_unix.h Fri Aug 02 12:12:30 2019 +0300 +++ b/src/njs_unix.h Fri Aug 02 12:12:35 2019 +0300 @@ -8,6 +8,9 @@ #ifndef _NJS_UNIX_H_INCLUDED_ #define _NJS_UNIX_H_INCLUDED_ +#include +#define njs_pagesize() getpagesize() + #if (NJS_LINUX) #ifdef _FORTIFY_SOURCE diff -r aaec532e9d08 -r 81b272f75471 src/test/lvlhsh_unit_test.c --- a/src/test/lvlhsh_unit_test.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/test/lvlhsh_unit_test.c Fri Aug 02 12:12:35 2019 +0300 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/test/random_unit_test.c --- a/src/test/random_unit_test.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/test/random_unit_test.c Fri Aug 02 12:12:35 2019 +0300 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/test/rbtree_unit_test.c --- a/src/test/rbtree_unit_test.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/test/rbtree_unit_test.c Fri Aug 02 12:12:35 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff -r aaec532e9d08 -r 81b272f75471 src/test/utf8_unit_test.c --- a/src/test/utf8_unit_test.c Fri Aug 02 12:12:30 2019 +0300 +++ b/src/test/utf8_unit_test.c Fri Aug 02 12:12:35 2019 +0300 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include From xeioex at nginx.com Fri Aug 2 09:32:09 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 09:32:09 +0000 Subject: [njs] Refactored njs_arr_t API. Message-ID: details: https://hg.nginx.org/njs/rev/aaec532e9d08 branches: changeset: 1093:aaec532e9d08 user: Dmitry Volyntsev date: Fri Aug 02 12:12:30 2019 +0300 description: Refactored njs_arr_t API. 1) const njs_mem_proto_t *proto is removed from arguments. 2) njs_mp_t *mp is passed during array creation. diffstat: src/njs.h | 2 - src/njs_arr.c | 121 ++++++++++++++++++++++++++------------------------- src/njs_arr.h | 49 +++++++++----------- src/njs_builtin.c | 8 +-- src/njs_extern.c | 3 +- src/njs_generator.c | 12 ++--- src/njs_json.c | 17 +++--- src/njs_main.h | 2 +- src/njs_module.c | 5 +- src/njs_parser.c | 3 +- src/njs_string.c | 26 ++++------ src/njs_stub.h | 11 ---- src/njs_variable.c | 5 +- src/njs_vm.c | 47 +++---------------- src/njs_vm.h | 2 +- 15 files changed, 127 insertions(+), 186 deletions(-) diffs (768 lines): diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs.h --- a/src/njs.h Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs.h Fri Aug 02 12:12:30 2019 +0300 @@ -18,7 +18,6 @@ #include #include #include -#include #include @@ -225,7 +224,6 @@ NJS_EXPORT njs_external_ptr_t njs_vm_ext const njs_value_t *value); NJS_EXPORT void njs_disassembler(njs_vm_t *vm); -NJS_EXPORT njs_arr_t *njs_vm_completions(njs_vm_t *vm, njs_str_t *expression); NJS_EXPORT const njs_value_t *njs_vm_value(njs_vm_t *vm, const njs_str_t *name); NJS_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, const njs_str_t *name); diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_arr.c --- a/src/njs_arr.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_arr.c Fri Aug 02 12:12:30 2019 +0300 @@ -7,98 +7,99 @@ #include #include #include -#include +#include #include #include #include njs_arr_t * -njs_arr_create(uint32_t items, uint32_t item_size, - const njs_mem_proto_t *proto, void *pool) +njs_arr_create(njs_mp_t *mp, njs_uint_t n, size_t size) { - njs_arr_t *array; - - array = proto->alloc(pool, sizeof(njs_arr_t) + items * item_size); + njs_arr_t *arr; - if (njs_fast_path(array != NULL)) { - array->start = (char *) array + sizeof(njs_arr_t); - array->items = 0; - array->item_size = item_size; - array->avalaible = items; - array->pointer = 1; - array->separate = 1; + arr = njs_mp_alloc(mp, sizeof(njs_arr_t) + n * size); + if (njs_slow_path(arr == NULL)) { + return NULL; } - return array; + arr->start = (char *) arr + sizeof(njs_arr_t); + arr->items = 0; + arr->item_size = size; + arr->avalaible = n; + arr->pointer = 1; + arr->separate = 1; + arr->mem_pool = mp; + + return arr; } void * -njs_arr_init(njs_arr_t *array, void *start, uint32_t items, - uint32_t item_size, const njs_mem_proto_t *proto, void *pool) +njs_arr_init(njs_mp_t *mp, njs_arr_t *arr, void *start, njs_uint_t n, + size_t size) { - array->start = start; - array->items = items; - array->item_size = item_size; - array->avalaible = items; - array->pointer = 0; - array->separate = 0; + arr->start = start; + arr->items = n; + arr->item_size = size; + arr->avalaible = n; + arr->pointer = 0; + arr->separate = 0; + arr->mem_pool = mp; - if (array->start == NULL) { - array->separate = 1; - array->items = 0; + if (arr->start == NULL) { + arr->separate = 1; + arr->items = 0; - array->start = proto->alloc(pool, items * item_size); + arr->start = njs_mp_alloc(mp, n * size); } - return array->start; + return arr->start; } void -njs_arr_destroy(njs_arr_t *array, const njs_mem_proto_t *proto, void *pool) +njs_arr_destroy(njs_arr_t *arr) { - if (array->separate) { - proto->free(pool, array->start); + if (arr->separate) { + njs_mp_free(arr->mem_pool, arr->start); #if (NJS_DEBUG) - array->start = NULL; - array->items = 0; - array->avalaible = 0; + arr->start = NULL; + arr->items = 0; + arr->avalaible = 0; #endif } - if (array->pointer) { - proto->free(pool, array); + if (arr->pointer) { + njs_mp_free(arr->mem_pool, arr); } } void * -njs_arr_add(njs_arr_t *array, const njs_mem_proto_t *proto, void *pool) +njs_arr_add(njs_arr_t *arr) { - return njs_arr_add_multiple(array, proto, pool, 1); + return njs_arr_add_multiple(arr, 1); } void * -njs_arr_add_multiple(njs_arr_t *array, const njs_mem_proto_t *proto, - void *pool, uint32_t items) +njs_arr_add_multiple(njs_arr_t *arr, njs_uint_t items) { void *item, *start, *old; uint32_t n; - n = array->avalaible; - items += array->items; + n = arr->avalaible; + items += arr->items; if (items >= n) { if (n < 16) { - /* Allocate new array twice as much as current. */ + /* Allocate new arr twice as much as current. */ n *= 2; } else { - /* Allocate new array half as much as current. */ + /* Allocate new arr half as much as current. */ n += n / 2; } @@ -106,42 +107,42 @@ njs_arr_add_multiple(njs_arr_t *array, c n = items; } - start = proto->alloc(pool, n * array->item_size); + start = njs_mp_alloc(arr->mem_pool, n * arr->item_size); if (njs_slow_path(start == NULL)) { return NULL; } - array->avalaible = n; - old = array->start; - array->start = start; + arr->avalaible = n; + old = arr->start; + arr->start = start; - memcpy(start, old, (uint32_t) array->items * array->item_size); + memcpy(start, old, (uint32_t) arr->items * arr->item_size); - if (array->separate == 0) { - array->separate = 1; + if (arr->separate == 0) { + arr->separate = 1; } else { - proto->free(pool, old); + njs_mp_free(arr->mem_pool, old); } } - item = (char *) array->start + (uint32_t) array->items * array->item_size; + item = (char *) arr->start + (uint32_t) arr->items * arr->item_size; - array->items = items; + arr->items = items; return item; } void * -njs_arr_zero_add(njs_arr_t *array, const njs_mem_proto_t *proto, void *pool) +njs_arr_zero_add(njs_arr_t *arr) { void *item; - item = njs_arr_add(array, proto, pool); + item = njs_arr_add(arr); if (njs_fast_path(item != NULL)) { - njs_memzero(item, array->item_size); + njs_memzero(item, arr->item_size); } return item; @@ -149,13 +150,13 @@ njs_arr_zero_add(njs_arr_t *array, const void -njs_arr_remove(njs_arr_t *array, void *item) +njs_arr_remove(njs_arr_t *arr, void *item) { u_char *next, *last, *end; uint32_t item_size; - item_size = array->item_size; - end = (u_char *) array->start + item_size * array->items; + item_size = arr->item_size; + end = (u_char *) arr->start + item_size * arr->items; last = end - item_size; if (item != last) { @@ -164,5 +165,5 @@ njs_arr_remove(njs_arr_t *array, void *i memmove(item, next, end - next); } - array->items--; + arr->items--; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_arr.h --- a/src/njs_arr.h Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_arr.h Fri Aug 02 12:12:30 2019 +0300 @@ -20,47 +20,44 @@ typedef struct { uint8_t pointer; uint8_t separate; + njs_mp_t *mem_pool; } njs_arr_t; -NJS_EXPORT njs_arr_t *njs_arr_create(uint32_t items, uint32_t item_size, - const njs_mem_proto_t *proto, void *pool); -NJS_EXPORT void *njs_arr_init(njs_arr_t *array, void *start, uint32_t items, - uint32_t item_size, const njs_mem_proto_t *proto, void *pool); -NJS_EXPORT void njs_arr_destroy(njs_arr_t *array, - const njs_mem_proto_t *proto, void *pool); -NJS_EXPORT void *njs_arr_add(njs_arr_t *array, const njs_mem_proto_t *proto, - void *pool); -NJS_EXPORT void *njs_arr_add_multiple(njs_arr_t *array, - const njs_mem_proto_t *proto, void *pool, uint32_t items); -NJS_EXPORT void *njs_arr_zero_add(njs_arr_t *array, - const njs_mem_proto_t *proto, void *pool); -NJS_EXPORT void njs_arr_remove(njs_arr_t *array, void *item); +NJS_EXPORT njs_arr_t *njs_arr_create(njs_mp_t *mp, njs_uint_t n, + size_t size); +NJS_EXPORT void *njs_arr_init(njs_mp_t *mp, njs_arr_t *arr, void *start, + njs_uint_t n, size_t size); +NJS_EXPORT void njs_arr_destroy(njs_arr_t *arr); +NJS_EXPORT void *njs_arr_add(njs_arr_t *arr); +NJS_EXPORT void *njs_arr_add_multiple(njs_arr_t *arr, njs_uint_t n); +NJS_EXPORT void *njs_arr_zero_add(njs_arr_t *arr); +NJS_EXPORT void njs_arr_remove(njs_arr_t *arr, void *item); -#define njs_arr_item(array, i) \ - ((void *) ((char *) (array)->start + (array)->item_size * (i))) +#define njs_arr_item(arr, i) \ + ((void *) ((char *) (arr)->start + (arr)->item_size * (i))) -#define njs_arr_last(array) \ - ((void *) \ - ((char *) (array)->start \ - + (array)->item_size * ((array)->items - 1))) +#define njs_arr_last(arr) \ + ((void *) \ + ((char *) (arr)->start \ + + (arr)->item_size * ((arr)->items - 1))) -#define njs_arr_reset(array) \ - (array)->items = 0; +#define njs_arr_reset(arr) \ + (arr)->items = 0; -#define njs_arr_is_empty(array) \ - ((array)->items == 0) +#define njs_arr_is_empty(arr) \ + ((arr)->items == 0) njs_inline void * -njs_arr_remove_last(njs_arr_t *array) +njs_arr_remove_last(njs_arr_t *arr) { - array->items--; - return (char *) array->start + array->item_size * array->items; + arr->items--; + return (char *) arr->start + arr->item_size * arr->items; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_builtin.c --- a/src/njs_builtin.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_builtin.c Fri Aug 02 12:12:30 2019 +0300 @@ -772,9 +772,7 @@ njs_vm_completions(njs_vm_t *vm, njs_str if (expression == NULL) { size = njs_builtin_completions_size(vm); - completions = njs_arr_create(size, sizeof(njs_str_t), - &njs_array_mem_proto, vm->mem_pool); - + completions = njs_arr_create(vm->mem_pool, size, sizeof(njs_str_t)); if (njs_slow_path(completions == NULL)) { return NULL; } @@ -897,9 +895,7 @@ njs_object_completions(njs_vm_t *vm, njs } while (o != NULL); - completions = njs_arr_create(size, sizeof(njs_str_t), - &njs_array_mem_proto, vm->mem_pool); - + completions = njs_arr_create(vm->mem_pool, size, sizeof(njs_str_t)); if (njs_slow_path(completions == NULL)) { return NULL; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_extern.c --- a/src/njs_extern.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_extern.c Fri Aug 02 12:12:30 2019 +0300 @@ -178,8 +178,7 @@ njs_vm_external_create(njs_vm_t *vm, njs return NJS_ERROR; } - obj = njs_arr_add(vm->external_objects, &njs_array_mem_proto, - vm->mem_pool); + obj = njs_arr_add(vm->external_objects); if (njs_slow_path(obj == NULL)) { return NJS_ERROR; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_generator.c --- a/src/njs_generator.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_generator.c Fri Aug 02 12:12:30 2019 +0300 @@ -2432,14 +2432,13 @@ njs_generate_scope(njs_vm_t *vm, njs_gen } if (vm->codes == NULL) { - vm->codes = njs_arr_create(4, sizeof(njs_vm_code_t), - &njs_array_mem_proto, vm->mem_pool); + vm->codes = njs_arr_create(vm->mem_pool, 4, sizeof(njs_vm_code_t)); if (njs_slow_path(vm->codes == NULL)) { return NJS_ERROR; } } - code = njs_arr_add(vm->codes, &njs_array_mem_proto, vm->mem_pool); + code = njs_arr_add(vm->codes); if (njs_slow_path(code == NULL)) { return NJS_ERROR; } @@ -3265,8 +3264,7 @@ njs_generate_index_release(njs_vm_t *vm, cache = generator->index_cache; if (cache == NULL) { - cache = njs_arr_create(4, sizeof(njs_value_t *), - &njs_array_mem_proto, vm->mem_pool); + cache = njs_arr_create(vm->mem_pool, 4, sizeof(njs_value_t *)); if (njs_slow_path(cache == NULL)) { return NJS_ERROR; } @@ -3274,7 +3272,7 @@ njs_generate_index_release(njs_vm_t *vm, generator->index_cache = cache; } - last = njs_arr_add(cache, &njs_array_mem_proto, vm->mem_pool); + last = njs_arr_add(cache); if (njs_fast_path(last != NULL)) { *last = index; return NJS_OK; @@ -3317,7 +3315,7 @@ njs_generate_function_debug(njs_vm_t *vm { njs_function_debug_t *debug; - debug = njs_arr_add(vm->debug, &njs_array_mem_proto, vm->mem_pool); + debug = njs_arr_add(vm->debug); if (njs_slow_path(debug == NULL)) { return NJS_ERROR; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_json.c --- a/src/njs_json.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_json.c Fri Aug 02 12:12:30 2019 +0300 @@ -208,8 +208,8 @@ njs_json_parse(njs_vm_t *vm, njs_value_t parse->function = njs_function(reviver); - if (njs_arr_init(&parse->stack, NULL, 4, sizeof(njs_json_state_t), - &njs_array_mem_proto, vm->mem_pool) + if (njs_arr_init(vm->mem_pool, &parse->stack, NULL, 4, + sizeof(njs_json_state_t)) == NULL) { goto memory_error; @@ -305,8 +305,8 @@ njs_json_stringify(njs_vm_t *vm, njs_val } } - if (njs_arr_init(&stringify->stack, NULL, 4, sizeof(njs_json_state_t), - &njs_array_mem_proto, vm->mem_pool) + if (njs_arr_init(vm->mem_pool, &stringify->stack, NULL, 4, + sizeof(njs_json_state_t)) == NULL) { goto memory_error; @@ -1103,7 +1103,7 @@ njs_json_push_parse_state(njs_vm_t *vm, { njs_json_state_t *state; - state = njs_arr_add(&parse->stack, &njs_array_mem_proto, vm->mem_pool); + state = njs_arr_add(&parse->stack); if (state != NULL) { state = njs_arr_last(&parse->stack); state->value = *value; @@ -1693,8 +1693,7 @@ njs_json_push_stringify_state(njs_vm_t * return NULL; } - state = njs_arr_add(&stringify->stack, &njs_array_mem_proto, - vm->mem_pool); + state = njs_arr_add(&stringify->stack); if (njs_slow_path(state == NULL)) { njs_memory_error(vm); return NULL; @@ -2419,8 +2418,8 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ njs_memset(stringify->space.start, ' ', indent); - if (njs_arr_init(&stringify->stack, NULL, 4, sizeof(njs_json_state_t), - &njs_array_mem_proto, vm->mem_pool) + if (njs_arr_init(vm->mem_pool, &stringify->stack, NULL, 4, + sizeof(njs_json_state_t)) == NULL) { goto memory_error; diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_main.h --- a/src/njs_main.h Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_main.h Fri Aug 02 12:12:30 2019 +0300 @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include #include #include diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_module.c --- a/src/njs_module.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_module.c Fri Aug 02 12:12:30 2019 +0300 @@ -492,14 +492,13 @@ njs_module_insert(njs_vm_t *vm, njs_modu } if (vm->modules == NULL) { - vm->modules = njs_arr_create(4, sizeof(njs_module_t *), - &njs_array_mem_proto, vm->mem_pool); + vm->modules = njs_arr_create(vm->mem_pool, 4, sizeof(njs_module_t *)); if (njs_slow_path(vm->modules == NULL)) { return NJS_ERROR; } } - value = njs_arr_add(vm->modules, &njs_array_mem_proto, vm->mem_pool); + value = njs_arr_add(vm->modules); if (njs_slow_path(value == NULL)) { return NJS_ERROR; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_parser.c --- a/src/njs_parser.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_parser.c Fri Aug 02 12:12:30 2019 +0300 @@ -218,8 +218,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs values = NULL; if (scope->type < NJS_SCOPE_BLOCK) { - values = njs_arr_create(4, sizeof(njs_value_t), &njs_array_mem_proto, - vm->mem_pool); + values = njs_arr_create(vm->mem_pool, 4, sizeof(njs_value_t)); if (njs_slow_path(values == NULL)) { return NJS_ERROR; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_string.c --- a/src/njs_string.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_string.c Fri Aug 02 12:12:30 2019 +0300 @@ -3112,9 +3112,8 @@ njs_string_prototype_replace(njs_vm_t *v } /* This cannot fail. */ - r->part = njs_arr_init(&r->parts, &r->array, - 3, sizeof(njs_string_replace_part_t), - &njs_array_mem_proto, vm->mem_pool); + r->part = njs_arr_init(vm->mem_pool, &r->parts, &r->array, + 3, sizeof(njs_string_replace_part_t)); r->substitutions = NULL; r->function = NULL; @@ -3222,14 +3221,12 @@ njs_string_replace_regexp(njs_vm_t *vm, } if (r->part != r->parts.start) { - r->part = njs_arr_add(&r->parts, &njs_array_mem_proto, - vm->mem_pool); + r->part = njs_arr_add(&r->parts); if (njs_slow_path(r->part == NULL)) { return NJS_ERROR; } - r->part = njs_arr_add(&r->parts, &njs_array_mem_proto, - vm->mem_pool); + r->part = njs_arr_add(&r->parts); if (njs_slow_path(r->part == NULL)) { return NJS_ERROR; } @@ -3297,7 +3294,7 @@ njs_string_replace_regexp(njs_vm_t *vm, njs_regex_match_data_free(r->match_data, vm->regex_context); - njs_arr_destroy(&r->parts, &njs_array_mem_proto, vm->mem_pool); + njs_arr_destroy(&r->parts); njs_string_copy(&vm->retval, &args[0]); @@ -3513,8 +3510,8 @@ njs_string_replace_parse(njs_vm_t *vm, n uint32_t type; njs_string_subst_t *s; - r->substitutions = njs_arr_create(4, sizeof(njs_string_subst_t), - &njs_array_mem_proto, vm->mem_pool); + r->substitutions = njs_arr_create(vm->mem_pool, 4, + sizeof(njs_string_subst_t)); if (njs_slow_path(r->substitutions == NULL)) { return NJS_ERROR; @@ -3529,7 +3526,7 @@ njs_string_replace_parse(njs_vm_t *vm, n copy: if (s == NULL) { - s = njs_arr_add(r->substitutions, &njs_array_mem_proto, vm->mem_pool); + s = njs_arr_add(r->substitutions); if (njs_slow_path(s == NULL)) { return NJS_ERROR; } @@ -3593,7 +3590,7 @@ skip: goto copy; } - s = njs_arr_add(r->substitutions, &njs_array_mem_proto, vm->mem_pool); + s = njs_arr_add(r->substitutions); if (njs_slow_path(s == NULL)) { return NJS_ERROR; } @@ -3621,8 +3618,7 @@ njs_string_replace_substitute(njs_vm_t * last = r->substitutions->items; end = r->part[0].start + r->part[0].size; - part = njs_arr_add_multiple(&r->parts, &njs_array_mem_proto, vm->mem_pool, - last + 1); + part = njs_arr_add_multiple(&r->parts, last + 1); if (njs_slow_path(part == NULL)) { return NJS_ERROR; } @@ -3801,7 +3797,7 @@ njs_string_replace_join(njs_vm_t *vm, nj /* GC: release valid values. */ } - njs_arr_destroy(&r->parts, &njs_array_mem_proto, vm->mem_pool); + njs_arr_destroy(&r->parts); return NJS_OK; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_stub.h --- a/src/njs_stub.h Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_stub.h Fri Aug 02 12:12:30 2019 +0300 @@ -22,17 +22,6 @@ #define NJS_DONE (-4) -typedef struct { - void *(*alloc)(void *mem, size_t size); - void *(*zalloc)(void *mem, size_t size); - void *(*align)(void *mem, size_t alignment, size_t size); - void *(*zalign)(void *mem, size_t alignment, size_t size); - void (*free)(void *mem, void *p); - void (*alert)(void *trace, const char *fmt, ...); - void njs_cdecl (*trace)(void *trace, const char *fmt, ...); -} njs_mem_proto_t; - - #define njs_thread_log_alert(...) #define njs_thread_log_error(...) #define njs_log_error(...) diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_variable.c --- a/src/njs_variable.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_variable.c Fri Aug 02 12:12:30 2019 +0300 @@ -564,8 +564,7 @@ njs_scope_next_index(njs_vm_t *vm, njs_p values = scope->values[scope_index]; if (values == NULL) { - values = njs_arr_create(4, sizeof(njs_value_t), - &njs_array_mem_proto, vm->mem_pool); + values = njs_arr_create(vm->mem_pool, 4, sizeof(njs_value_t)); if (njs_slow_path(values == NULL)) { return NJS_INDEX_ERROR; } @@ -573,7 +572,7 @@ njs_scope_next_index(njs_vm_t *vm, njs_p scope->values[scope_index] = values; } - value = njs_arr_add(values, &njs_array_mem_proto, vm->mem_pool); + value = njs_arr_add(values); if (njs_slow_path(value == NULL)) { return NJS_INDEX_ERROR; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_vm.c --- a/src/njs_vm.c Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_vm.c Fri Aug 02 12:12:30 2019 +0300 @@ -20,31 +20,6 @@ const njs_str_t njs_entry_unknown = const njs_str_t njs_entry_anonymous = njs_str("anonymous"); -static void * -njs_array_mem_alloc(void *mem, size_t size) -{ - return njs_mp_alloc(mem, size); -} - - -static void -njs_array_mem_free(void *mem, void *p) -{ - njs_mp_free(mem, p); -} - - -const njs_mem_proto_t njs_array_mem_proto = { - njs_array_mem_alloc, - NULL, - NULL, - NULL, - njs_array_mem_free, - NULL, - NULL, -}; - - njs_vm_t * njs_vm_create(njs_vm_opt_t *options) { @@ -111,9 +86,7 @@ njs_vm_create(njs_vm_opt_t *options) vm->external = options->external; - vm->external_objects = njs_arr_create(4, sizeof(void *), - &njs_array_mem_proto, - vm->mem_pool); + vm->external_objects = njs_arr_create(vm->mem_pool, 4, sizeof(void *)); if (njs_slow_path(vm->external_objects == NULL)) { return NULL; } @@ -127,8 +100,8 @@ njs_vm_create(njs_vm_opt_t *options) vm->trace.data = vm; if (options->backtrace) { - debug = njs_arr_create(4, sizeof(njs_function_debug_t), - &njs_array_mem_proto, vm->mem_pool); + debug = njs_arr_create(vm->mem_pool, 4, + sizeof(njs_function_debug_t)); if (njs_slow_path(debug == NULL)) { return NULL; } @@ -302,9 +275,8 @@ njs_vm_clone(njs_vm_t *vm, njs_external_ nvm->external_prototypes_hash = vm->external_prototypes_hash; items = vm->external_objects->items; - externals = njs_arr_create(items + 4, sizeof(void *), - &njs_array_mem_proto, nvm->mem_pool); + externals = njs_arr_create(nvm->mem_pool, items + 4, sizeof(void *)); if (njs_slow_path(externals == NULL)) { return NULL; } @@ -393,8 +365,8 @@ njs_vm_init(njs_vm_t *vm) njs_queue_init(&vm->posted_events); if (vm->debug != NULL) { - backtrace = njs_arr_create(4, sizeof(njs_backtrace_entry_t), - &njs_array_mem_proto, vm->mem_pool); + backtrace = njs_arr_create(vm->mem_pool, 4, + sizeof(njs_backtrace_entry_t)); if (njs_slow_path(backtrace == NULL)) { return NJS_ERROR; } @@ -634,14 +606,13 @@ njs_vm_add_path(njs_vm_t *vm, const njs_ njs_str_t *item; if (vm->paths == NULL) { - vm->paths = njs_arr_create(4, sizeof(njs_str_t), - &njs_array_mem_proto, vm->mem_pool); + vm->paths = njs_arr_create(vm->mem_pool, 4, sizeof(njs_str_t)); if (njs_slow_path(vm->paths == NULL)) { return NJS_ERROR; } } - item = njs_arr_add(vm->paths, &njs_array_mem_proto, vm->mem_pool); + item = njs_arr_add(vm->paths); if (njs_slow_path(item == NULL)) { return NJS_ERROR; } @@ -1088,7 +1059,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, native_frame = &frame->native; function = native_frame->function; - be = njs_arr_add(vm->backtrace, &njs_array_mem_proto, vm->mem_pool); + be = njs_arr_add(vm->backtrace); if (njs_slow_path(be == NULL)) { return NJS_ERROR; } diff -r 84f4da1e7d96 -r aaec532e9d08 src/njs_vm.h --- a/src/njs_vm.h Thu Aug 01 21:01:16 2019 +0300 +++ b/src/njs_vm.h Fri Aug 02 12:12:30 2019 +0300 @@ -348,6 +348,7 @@ njs_int_t njs_builtin_match_native_funct njs_function_t *function, njs_str_t *name); njs_arr_t *njs_vm_backtrace(njs_vm_t *vm); +njs_arr_t *njs_vm_completions(njs_vm_t *vm, njs_str_t *expression); void *njs_lvlhsh_alloc(void *data, size_t size); void njs_lvlhsh_free(void *data, void *p, size_t size); @@ -359,7 +360,6 @@ extern const njs_str_t njs_entry_nati extern const njs_str_t njs_entry_unknown; extern const njs_str_t njs_entry_anonymous; -extern const njs_mem_proto_t njs_array_mem_proto; extern const njs_lvlhsh_proto_t njs_object_hash_proto; From xeioex at nginx.com Fri Aug 2 09:32:09 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 09:32:09 +0000 Subject: [njs] Moving all common headers into njs_main.h. Message-ID: details: https://hg.nginx.org/njs/rev/835b3e817b93 branches: changeset: 1095:835b3e817b93 user: Dmitry Volyntsev date: Fri Aug 02 12:12:36 2019 +0300 description: Moving all common headers into njs_main.h. diffstat: src/njs_arr.c | 9 ++------- src/njs_array.c | 3 +-- src/njs_boolean.c | 1 + src/njs_builtin.c | 10 +--------- src/njs_crypto.c | 7 +------ src/njs_date.c | 5 +---- src/njs_disassembler.c | 1 + src/njs_diyfp.c | 5 ++--- src/njs_djb_hash.c | 7 ++----- src/njs_dtoa.c | 9 ++------- src/njs_error.c | 3 +-- src/njs_event.c | 2 +- src/njs_extern.c | 2 +- src/njs_file.c | 7 +------ src/njs_fs.c | 6 +----- src/njs_function.c | 2 +- src/njs_generator.c | 2 +- src/njs_json.c | 5 +---- src/njs_lexer.c | 2 +- src/njs_lexer_keyword.c | 2 +- src/njs_lvlhsh.c | 8 ++------ src/njs_main.h | 23 ++++++++++++++++++++++- src/njs_malloc.c | 10 +--------- src/njs_math.c | 2 +- src/njs_md5.c | 7 +------ src/njs_module.c | 9 +-------- src/njs_mp.c | 13 ++----------- src/njs_murmur_hash.c | 6 ++---- src/njs_number.c | 4 +--- src/njs_object.c | 2 +- src/njs_parser.c | 3 +-- src/njs_parser_expression.c | 2 +- src/njs_parser_terminal.c | 3 +-- src/njs_pcre.c | 9 ++------- src/njs_queue.c | 6 ++---- src/njs_random.c | 8 +------- src/njs_rbtree.c | 6 ++---- src/njs_regexp.c | 5 +---- src/njs_sha1.c | 7 +------ src/njs_sha2.c | 7 +------ src/njs_shell.c | 10 ---------- src/njs_sprintf.c | 15 ++++----------- src/njs_string.c | 4 +--- src/njs_strtod.c | 5 +---- src/njs_time.c | 8 ++------ src/njs_timer.c | 3 +-- src/njs_trace.c | 8 ++------ src/njs_unix.h | 18 +++++++++++++++++- src/njs_utf8.c | 6 ++---- src/njs_value.c | 2 +- src/njs_variable.c | 2 +- src/njs_vm.c | 3 +-- src/njs_vmcode.c | 3 +-- 53 files changed, 105 insertions(+), 212 deletions(-) diffs (944 lines): diff -r 81b272f75471 -r 835b3e817b93 src/njs_arr.c --- a/src/njs_arr.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_arr.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,13 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include + +#include njs_arr_t * diff -r 81b272f75471 -r 835b3e817b93 src/njs_array.c --- a/src/njs_array.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_array.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include static njs_int_t njs_array_prototype_slice_copy(njs_vm_t *vm, diff -r 81b272f75471 -r 835b3e817b93 src/njs_boolean.c --- a/src/njs_boolean.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_boolean.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,6 +4,7 @@ * Copyright (C) NGINX, Inc. */ + #include diff -r 81b272f75471 -r 835b3e817b93 src/njs_builtin.c --- a/src/njs_builtin.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_builtin.c Fri Aug 02 12:12:36 2019 +0300 @@ -5,16 +5,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include typedef struct { diff -r 81b272f75471 -r 835b3e817b93 src/njs_crypto.c --- a/src/njs_crypto.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_crypto.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,13 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include -#include -#include -#include typedef void (*njs_hash_init)(void *ctx); diff -r 81b272f75471 -r 835b3e817b93 src/njs_date.c --- a/src/njs_date.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_date.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,11 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include -#include /* diff -r 81b272f75471 -r 835b3e817b93 src/njs_disassembler.c --- a/src/njs_disassembler.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_disassembler.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,6 +4,7 @@ * Copyright (C) NGINX, Inc. */ + #include diff -r 81b272f75471 -r 835b3e817b93 src/njs_diyfp.c --- a/src/njs_diyfp.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_diyfp.c Fri Aug 02 12:12:36 2019 +0300 @@ -8,9 +8,8 @@ * and accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243. */ -#include -#include -#include + +#include #include diff -r 81b272f75471 -r 835b3e817b93 src/njs_djb_hash.c --- a/src/njs_djb_hash.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_djb_hash.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,11 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include + +#include uint32_t diff -r 81b272f75471 -r 835b3e817b93 src/njs_dtoa.c --- a/src/njs_dtoa.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_dtoa.c Fri Aug 02 12:12:36 2019 +0300 @@ -33,16 +33,11 @@ * THE SOFTWARE. */ -#include -#include -#include -#include + +#include #include #include -#include -#include - njs_inline void njs_grisu2_round(char *start, size_t len, uint64_t delta, uint64_t rest, diff -r 81b272f75471 -r 835b3e817b93 src/njs_error.c --- a/src/njs_error.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_error.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include static const njs_value_t njs_error_message_string = njs_string("message"); diff -r 81b272f75471 -r 835b3e817b93 src/njs_event.c --- a/src/njs_event.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_event.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include static njs_int_t njs_event_hash_test(njs_lvlhsh_query_t *lhq, void *data); diff -r 81b272f75471 -r 835b3e817b93 src/njs_extern.c --- a/src/njs_extern.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_extern.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include typedef struct njs_extern_part_s njs_extern_part_t; diff -r 81b272f75471 -r 835b3e817b93 src/njs_file.c --- a/src/njs_file.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_file.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,13 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include +#include void diff -r 81b272f75471 -r 835b3e817b93 src/njs_fs.c --- a/src/njs_fs.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_fs.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,12 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include -#include -#include typedef struct { diff -r 81b272f75471 -r 835b3e817b93 src/njs_function.c --- a/src/njs_function.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_function.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include static njs_function_t *njs_function_copy(njs_vm_t *vm, diff -r 81b272f75471 -r 835b3e817b93 src/njs_generator.c --- a/src/njs_generator.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_generator.c Fri Aug 02 12:12:36 2019 +0300 @@ -5,8 +5,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include typedef struct njs_generator_patch_s njs_generator_patch_t; diff -r 81b272f75471 -r 835b3e817b93 src/njs_json.c --- a/src/njs_json.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_json.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,11 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include -#include typedef struct { diff -r 81b272f75471 -r 835b3e817b93 src/njs_lexer.c --- a/src/njs_lexer.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_lexer.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include typedef struct njs_lexer_multi_s njs_lexer_multi_t; diff -r 81b272f75471 -r 835b3e817b93 src/njs_lexer_keyword.c --- a/src/njs_lexer_keyword.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_lexer_keyword.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include static const njs_keyword_t njs_keywords[] = { diff -r 81b272f75471 -r 835b3e817b93 src/njs_lvlhsh.c --- a/src/njs_lvlhsh.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_lvlhsh.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,12 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include + +#include /* diff -r 81b272f75471 -r 835b3e817b93 src/njs_main.h --- a/src/njs_main.h Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_main.h Fri Aug 02 12:12:36 2019 +0300 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,27 +26,47 @@ #include #include #include +#include #include #include #include +#include +#include +#include + #include #include + #include #include #include #include #include #include -#include + #include #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include #include #include #include diff -r 81b272f75471 -r 835b3e817b93 src/njs_malloc.c --- a/src/njs_malloc.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_malloc.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,13 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include +#include void * @@ -47,9 +42,6 @@ njs_memalign(size_t alignment, size_t si return p; } - // STUB - //njs_errno_set(err); - return NULL; } diff -r 81b272f75471 -r 835b3e817b93 src/njs_math.c --- a/src/njs_math.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_math.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include static njs_int_t diff -r 81b272f75471 -r 835b3e817b93 src/njs_md5.c --- a/src/njs_md5.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_md5.c Fri Aug 02 12:12:36 2019 +0300 @@ -6,12 +6,7 @@ */ -#include -#include -#include -#include -#include -#include +#include static const u_char *njs_md5_body(njs_md5_t *ctx, const u_char *data, diff -r 81b272f75471 -r 835b3e817b93 src/njs_module.c --- a/src/njs_module.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_module.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,15 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include -#include -#include -#include -#include -#include typedef struct { diff -r 81b272f75471 -r 835b3e817b93 src/njs_mp.c --- a/src/njs_mp.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_mp.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,17 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include /* diff -r 81b272f75471 -r 835b3e817b93 src/njs_murmur_hash.c --- a/src/njs_murmur_hash.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_murmur_hash.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,10 +4,8 @@ * released to the public domain. */ -#include -#include -#include -#include + +#include uint32_t diff -r 81b272f75471 -r 835b3e817b93 src/njs_number.c --- a/src/njs_number.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_number.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,10 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include /* diff -r 81b272f75471 -r 835b3e817b93 src/njs_object.c --- a/src/njs_object.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_object.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include static njs_int_t njs_object_hash_test(njs_lvlhsh_query_t *lhq, void *data); diff -r 81b272f75471 -r 835b3e817b93 src/njs_parser.c --- a/src/njs_parser.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_parser.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include static njs_int_t njs_parser_scope_begin(njs_vm_t *vm, njs_parser_t *parser, diff -r 81b272f75471 -r 835b3e817b93 src/njs_parser_expression.c --- a/src/njs_parser_expression.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_parser_expression.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include typedef struct { diff -r 81b272f75471 -r 835b3e817b93 src/njs_parser_terminal.c --- a/src/njs_parser_terminal.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_parser_terminal.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include static njs_parser_node_t *njs_parser_reference(njs_vm_t *vm, diff -r 81b272f75471 -r 835b3e817b93 src/njs_pcre.c --- a/src/njs_pcre.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_pcre.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,14 +4,9 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include + +#include #include -#include static void *njs_pcre_malloc(size_t size); diff -r 81b272f75471 -r 835b3e817b93 src/njs_queue.c --- a/src/njs_queue.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_queue.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,10 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include + +#include /* diff -r 81b272f75471 -r 835b3e817b93 src/njs_random.c --- a/src/njs_random.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_random.c Fri Aug 02 12:12:36 2019 +0300 @@ -5,13 +5,7 @@ */ -#include -#include -#include -#include -#include -#include -#include +#include #if (NJS_HAVE_GETRANDOM) #include #elif (NJS_HAVE_LINUX_SYS_GETRANDOM) diff -r 81b272f75471 -r 835b3e817b93 src/njs_rbtree.c --- a/src/njs_rbtree.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_rbtree.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,10 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include + +#include /* diff -r 81b272f75471 -r 835b3e817b93 src/njs_regexp.c --- a/src/njs_regexp.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_regexp.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,11 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include - -#include struct njs_regexp_group_s { diff -r 81b272f75471 -r 835b3e817b93 src/njs_sha1.c --- a/src/njs_sha1.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_sha1.c Fri Aug 02 12:12:36 2019 +0300 @@ -7,12 +7,7 @@ */ -#include -#include -#include -#include -#include -#include +#include static const u_char *njs_sha1_body(njs_sha1_t *ctx, const u_char *data, diff -r 81b272f75471 -r 835b3e817b93 src/njs_sha2.c --- a/src/njs_sha2.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_sha2.c Fri Aug 02 12:12:36 2019 +0300 @@ -7,12 +7,7 @@ */ -#include -#include -#include -#include -#include -#include +#include static const u_char *njs_sha2_body(njs_sha2_t *ctx, const u_char *data, diff -r 81b272f75471 -r 835b3e817b93 src/njs_shell.c --- a/src/njs_shell.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_shell.c Fri Aug 02 12:12:36 2019 +0300 @@ -6,17 +6,7 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include #include - -#include #if (NJS_HAVE_EDITLINE) #include #elif (NJS_HAVE_EDIT_READLINE) diff -r 81b272f75471 -r 835b3e817b93 src/njs_sprintf.c --- a/src/njs_sprintf.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_sprintf.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,15 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include +#include /* @@ -80,7 +73,7 @@ typedef struct { static u_char *njs_integer(njs_sprintf_t *spf, u_char *buf, uint64_t ui64); -static u_char *njs_number(njs_sprintf_t *spf, u_char *buf, double n); +static u_char *njs_float(njs_sprintf_t *spf, u_char *buf, double n); /* A right way of "f == 0.0". */ @@ -340,7 +333,7 @@ njs_vsprintf(u_char *buf, u_char *end, c } } - buf = njs_number(&spf, buf, i); + buf = njs_float(&spf, buf, i); if (spf.frac_width > 0) { @@ -546,7 +539,7 @@ njs_integer(njs_sprintf_t *spf, u_char * static u_char * -njs_number(njs_sprintf_t *spf, u_char *buf, double n) +njs_float(njs_sprintf_t *spf, u_char *buf, double n) { u_char *p, *end; size_t length; diff -r 81b272f75471 -r 835b3e817b93 src/njs_string.c --- a/src/njs_string.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_string.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,10 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include -#include #define NJS_TRIM_START 1 diff -r 81b272f75471 -r 835b3e817b93 src/njs_strtod.c --- a/src/njs_strtod.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_strtod.c Fri Aug 02 12:12:36 2019 +0300 @@ -7,11 +7,8 @@ * that can be found in the LICENSE file. */ -#include -#include -#include +#include #include -#include /* * Max double: 1.7976931348623157 x 10^308 diff -r 81b272f75471 -r 835b3e817b93 src/njs_time.c --- a/src/njs_time.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_time.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,13 +4,9 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include +#include + uint64_t njs_time(void) diff -r 81b272f75471 -r 835b3e817b93 src/njs_timer.c --- a/src/njs_timer.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_timer.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include static njs_int_t diff -r 81b272f75471 -r 835b3e817b93 src/njs_trace.c --- a/src/njs_trace.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_trace.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,12 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include + +#include static u_char * diff -r 81b272f75471 -r 835b3e817b93 src/njs_unix.h --- a/src/njs_unix.h Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_unix.h Fri Aug 02 12:12:36 2019 +0300 @@ -8,7 +8,6 @@ #ifndef _NJS_UNIX_H_INCLUDED_ #define _NJS_UNIX_H_INCLUDED_ -#include #define njs_pagesize() getpagesize() #if (NJS_LINUX) @@ -23,4 +22,21 @@ #endif /* NJS_LINUX */ +#include +#include +#include /* offsetof() */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + #endif /* _NJS_UNIX_H_INCLUDED_ */ diff -r 81b272f75471 -r 835b3e817b93 src/njs_utf8.c --- a/src/njs_utf8.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_utf8.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,10 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include + +#include /* * The njs_unicode_lower_case.h and njs_unicode_upper_case.h files are diff -r 81b272f75471 -r 835b3e817b93 src/njs_value.c --- a/src/njs_value.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_value.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,8 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include const njs_value_t njs_value_null = njs_value(NJS_NULL, 0, 0.0); diff -r 81b272f75471 -r 835b3e817b93 src/njs_variable.c --- a/src/njs_variable.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_variable.c Fri Aug 02 12:12:36 2019 +0300 @@ -5,8 +5,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include static njs_variable_t *njs_variable_scope_add(njs_vm_t *vm, diff -r 81b272f75471 -r 835b3e817b93 src/njs_vm.c --- a/src/njs_vm.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_vm.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include static njs_int_t njs_vm_init(njs_vm_t *vm); diff -r 81b272f75471 -r 835b3e817b93 src/njs_vmcode.c --- a/src/njs_vmcode.c Fri Aug 02 12:12:35 2019 +0300 +++ b/src/njs_vmcode.c Fri Aug 02 12:12:36 2019 +0300 @@ -4,9 +4,8 @@ * Copyright (C) NGINX, Inc. */ + #include -#include -#include struct njs_property_next_s { From xeioex at nginx.com Fri Aug 2 13:07:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 13:07:11 +0000 Subject: [njs] Adding default target as dependency for make all. Message-ID: details: https://hg.nginx.org/njs/rev/8e24114bc575 branches: changeset: 1096:8e24114bc575 user: Dmitry Volyntsev date: Fri Aug 02 15:41:21 2019 +0300 description: Adding default target as dependency for make all. diffstat: auto/make | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r 835b3e817b93 -r 8e24114bc575 auto/make --- a/auto/make Fri Aug 02 12:12:36 2019 +0300 +++ b/auto/make Fri Aug 02 15:41:21 2019 +0300 @@ -166,7 +166,8 @@ cat << END >> $NJS_MAKEFILE @echo @exit 1 -all: $NJS_BUILD_DIR/njs_auto_config.h test lib_test benchmark +all: $NJS_BUILD_DIR/njs_auto_config.h \\ + $NJS_DEFAULT_TARGET test lib_test benchmark njs: $NJS_BUILD_DIR/njs_auto_config.h $NJS_BUILD_DIR/njs From xeioex at nginx.com Fri Aug 2 13:07:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 13:07:11 +0000 Subject: [njs] Headers cleanup in src/test missed in 835b3e817b93. Message-ID: details: https://hg.nginx.org/njs/rev/219a6024c4c8 branches: changeset: 1097:219a6024c4c8 user: Dmitry Volyntsev date: Fri Aug 02 16:05:44 2019 +0300 description: Headers cleanup in src/test missed in 835b3e817b93. diffstat: src/test/lvlhsh_unit_test.c | 12 ++---------- src/test/njs_benchmark.c | 3 ++- src/test/njs_interactive_test.c | 3 ++- src/test/njs_unit_test.c | 8 -------- src/test/random_unit_test.c | 10 ++-------- src/test/rbtree_unit_test.c | 11 ++--------- src/test/utf8_unit_test.c | 9 ++------- 7 files changed, 12 insertions(+), 44 deletions(-) diffs (131 lines): diff -r 8e24114bc575 -r 219a6024c4c8 src/test/lvlhsh_unit_test.c --- a/src/test/lvlhsh_unit_test.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/lvlhsh_unit_test.c Fri Aug 02 16:05:44 2019 +0300 @@ -4,16 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include static njs_int_t diff -r 8e24114bc575 -r 219a6024c4c8 src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/njs_benchmark.c Fri Aug 02 16:05:44 2019 +0300 @@ -5,9 +5,10 @@ */ #include +#include + #include #include -#include #include #include diff -r 8e24114bc575 -r 219a6024c4c8 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/njs_interactive_test.c Fri Aug 02 16:05:44 2019 +0300 @@ -5,8 +5,9 @@ */ #include +#include + #include -#include #include #include diff -r 8e24114bc575 -r 219a6024c4c8 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/njs_unit_test.c Fri Aug 02 16:05:44 2019 +0300 @@ -4,16 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include #include -#include -#include -#include -#include -#include -#include -#include typedef struct { diff -r 8e24114bc575 -r 219a6024c4c8 src/test/random_unit_test.c --- a/src/test/random_unit_test.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/random_unit_test.c Fri Aug 02 16:05:44 2019 +0300 @@ -4,14 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include + +#include static njs_int_t diff -r 8e24114bc575 -r 219a6024c4c8 src/test/rbtree_unit_test.c --- a/src/test/rbtree_unit_test.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/rbtree_unit_test.c Fri Aug 02 16:05:44 2019 +0300 @@ -4,15 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include typedef struct { diff -r 8e24114bc575 -r 219a6024c4c8 src/test/utf8_unit_test.c --- a/src/test/utf8_unit_test.c Fri Aug 02 15:41:21 2019 +0300 +++ b/src/test/utf8_unit_test.c Fri Aug 02 16:05:44 2019 +0300 @@ -4,13 +4,8 @@ * Copyright (C) NGINX, Inc. */ -#include -#include -#include -#include -#include -#include -#include + +#include #define NJS_UTF8_START_TEST 0xC2 From careygister at outlook.com Fri Aug 2 15:33:06 2019 From: careygister at outlook.com (Carey Gister) Date: Fri, 2 Aug 2019 15:33:06 +0000 Subject: RTMP with multiple worker processes and rtmp_auto_push In-Reply-To: References: Message-ID: Bump. Can anyone explain what changed that had this feature stop working? Thanks, Carey Gister 415-310-5304 ________________________________ From: Carey Gister Sent: Friday, July 26, 2019 11:08 To: 'nginx-devel at nginx.org' Subject: RTMP with multiple worker processes and rtmp_auto_push Hi, I hope someone can help illuminate some background information related to this module. I understand that the rtmp_auto_push directive worked with multiple workers through nginx 1.7.x and then something changed in the nginx internals and it stopped working and was no longer supported for multiple workers. Can someone provide background on what changed that had this feature stop working? My manager has tasked me with getting this feature to work, if possible. Thanks, Carey Gister 415-310-5304 -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Fri Aug 2 17:12:21 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 17:12:21 +0000 Subject: [njs] Removed vm->count. Message-ID: details: https://hg.nginx.org/njs/rev/e592647bdb12 branches: changeset: 1098:e592647bdb12 user: Dmitry Volyntsev date: Fri Aug 02 20:12:01 2019 +0300 description: Removed vm->count. Previously it was used to catch infinite recursion. This is redundant, because NJS_MAX_STACK_SIZE is used for the same purpose. diffstat: src/njs_vm.h | 4 +--- src/njs_vmcode.c | 23 ++++------------------- src/test/njs_unit_test.c | 4 ++++ 3 files changed, 9 insertions(+), 22 deletions(-) diffs (116 lines): diff -r 219a6024c4c8 -r e592647bdb12 src/njs_vm.h --- a/src/njs_vm.h Fri Aug 02 16:05:44 2019 +0300 +++ b/src/njs_vm.h Fri Aug 02 20:12:01 2019 +0300 @@ -8,7 +8,7 @@ #define _NJS_VM_H_INCLUDED_ -#define NJS_MAX_STACK_SIZE (16 * 1024 * 1024) +#define NJS_MAX_STACK_SIZE (256 * 1024) /* @@ -229,8 +229,6 @@ struct njs_vm_s { /* njs_vm_t must be aligned to njs_value_t due to scratch value. */ njs_value_t retval; - njs_uint_t count; - njs_arr_t *paths; u_char *start; diff -r 219a6024c4c8 -r e592647bdb12 src/njs_vmcode.c --- a/src/njs_vmcode.c Fri Aug 02 16:05:44 2019 +0300 +++ b/src/njs_vmcode.c Fri Aug 02 20:12:01 2019 +0300 @@ -105,13 +105,6 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c njs_vmcode_try_return_t *try_return; njs_vmcode_function_frame_t *function_frame; - if (njs_slow_path(vm->count > 128)) { - njs_range_error(vm, "Maximum call stack size exceeded"); - return NJS_ERROR; - } - - vm->count++; - next: for ( ;; ) { @@ -588,8 +581,7 @@ next: value2 = njs_vmcode_operand(vm, value2); vm->retval = *value2; - ret = NJS_OK; - goto done; + return NJS_OK; case NJS_VMCODE_JUMP: ret = (njs_jump_off_t) value2; @@ -671,8 +663,7 @@ next: njs_function_frame_free(vm, &frame->native); - ret = NJS_OK; - goto done; + return NJS_OK; case NJS_VMCODE_FUNCTION_FRAME: function_frame = (njs_vmcode_function_frame_t *) pc; @@ -800,7 +791,7 @@ next: switch (ret) { case NJS_OK: - goto done; + return NJS_OK; case NJS_ERROR: goto error; } @@ -822,8 +813,6 @@ next: error: - ret = NJS_ERROR; - for ( ;; ) { frame = (njs_frame_t *) vm->top_frame; @@ -864,11 +853,7 @@ error: } } -done: - - vm->count--; - - return ret; + return NJS_ERROR; } diff -r 219a6024c4c8 -r e592647bdb12 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Aug 02 16:05:44 2019 +0300 +++ b/src/test/njs_unit_test.c Fri Aug 02 20:12:01 2019 +0300 @@ -4154,10 +4154,12 @@ static njs_unit_test_t njs_test[] = "Array.prototype.fill.call(o, 2).a"), njs_str("4") }, +#if (!NJS_HAVE_MEMORY_SANITIZER) /* MSAN limits stack size */ { njs_str("var o = Object({length: 3});" "Object.defineProperty(o, '0', {set: function(v){this[0] = 2 * v}});" "Array.prototype.fill.call(o, 2)"), njs_str("RangeError: Maximum call stack size exceeded") }, +#endif { njs_str("var a = [];" "a.filter(function(v, i, a) { return v > 1 })"), @@ -6410,8 +6412,10 @@ static njs_unit_test_t njs_test[] = { njs_str("{ function f() {} { var f }}"), njs_str("SyntaxError: \"f\" has already been declared in 1") }, +#if (!NJS_HAVE_MEMORY_SANITIZER) /* MSAN limits stack size */ { njs_str("function f() { return f() } f()"), njs_str("RangeError: Maximum call stack size exceeded") }, +#endif { njs_str("function () { } f()"), njs_str("SyntaxError: Unexpected token \"(\" in 1") }, From xeioex at nginx.com Fri Aug 2 17:34:10 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Aug 2019 17:34:10 +0000 Subject: [njs] Refactored njs_object_property.c. Message-ID: details: https://hg.nginx.org/njs/rev/ca8ce2161d0c branches: changeset: 1099:ca8ce2161d0c user: hongzhidao date: Fri Aug 02 23:36:42 2019 +0800 description: Refactored njs_object_property.c. 1) Moving generic function to njs_value.c: njs_property_query(), njs_value_property(), njs_value_property_set(). 2) Moving rest of the functions to njs_object_prop.c. diffstat: auto/sources | 2 +- src/njs_object.h | 76 -- src/njs_object_prop.c | 714 ++++++++++++++++++++++ src/njs_object_property.c | 1404 --------------------------------------------- src/njs_value.c | 690 ++++++++++++++++++++++ src/njs_value.h | 77 ++ 6 files changed, 1482 insertions(+), 1481 deletions(-) diffs (truncated from 3043 to 1000 lines): diff -r e592647bdb12 -r ca8ce2161d0c auto/sources --- a/auto/sources Fri Aug 02 20:12:01 2019 +0300 +++ b/auto/sources Fri Aug 02 23:36:42 2019 +0800 @@ -26,7 +26,7 @@ NJS_LIB_SRCS=" \ src/njs_number.c \ src/njs_string.c \ src/njs_object.c \ - src/njs_object_property.c \ + src/njs_object_prop.c \ src/njs_array.c \ src/njs_json.c \ src/njs_function.c \ diff -r e592647bdb12 -r ca8ce2161d0c src/njs_object.h --- a/src/njs_object.h Fri Aug 02 20:12:01 2019 +0300 +++ b/src/njs_object.h Fri Aug 02 23:36:42 2019 +0800 @@ -8,45 +8,6 @@ #define _NJS_OBJECT_H_INCLUDED_ -typedef enum { - NJS_PROPERTY = 0, - NJS_PROPERTY_REF, - NJS_METHOD, - NJS_PROPERTY_HANDLER, - NJS_WHITEOUT, -} njs_object_prop_type_t; - - -/* - * Attributes are generally used as Boolean values. - * The UNSET value is can be seen: - * for newly created property descriptors in njs_define_property(), - * for writable attribute of accessor descriptors (desc->writable - * cannot be used as a boolean value). - */ -typedef enum { - NJS_ATTRIBUTE_FALSE = 0, - NJS_ATTRIBUTE_TRUE = 1, - NJS_ATTRIBUTE_UNSET, -} njs_object_attribute_t; - - -typedef struct { - /* Must be aligned to njs_value_t. */ - njs_value_t value; - njs_value_t name; - njs_value_t getter; - njs_value_t setter; - - /* TODO: get rid of types */ - njs_object_prop_type_t type:8; /* 3 bits */ - - njs_object_attribute_t writable:8; /* 2 bits */ - njs_object_attribute_t enumerable:8; /* 2 bits */ - njs_object_attribute_t configurable:8; /* 2 bits */ -} njs_object_prop_t; - - #define njs_is_data_descriptor(prop) \ ((prop)->writable != NJS_ATTRIBUTE_UNSET || njs_is_valid(&(prop)->value)) @@ -59,37 +20,6 @@ typedef struct { (!njs_is_data_descriptor(prop) && !njs_is_accessor_descriptor(prop)) -typedef struct { - njs_lvlhsh_query_t lhq; - - /* scratch is used to get the value of an NJS_PROPERTY_HANDLER property. */ - njs_object_prop_t scratch; - - /* These three fields are used for NJS_EXTERNAL setters. */ - uintptr_t ext_data; - const njs_extern_t *ext_proto; - uint32_t ext_index; - - njs_value_t value; - njs_object_t *prototype; - njs_object_prop_t *own_whiteout; - uint8_t query; - uint8_t shared; - uint8_t own; -} njs_property_query_t; - - -#define njs_property_query_init(pq, _query, _own) \ - do { \ - (pq)->lhq.key.length = 0; \ - (pq)->lhq.value = NULL; \ - (pq)->own_whiteout = NULL; \ - (pq)->query = _query; \ - (pq)->shared = 0; \ - (pq)->own = _own; \ - } while (0) - - struct njs_object_init_s { njs_str_t name; const njs_object_prop_t *properties; @@ -124,12 +54,6 @@ njs_value_t *njs_property_constructor_cr njs_int_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); -njs_int_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_value_t *object, njs_value_t *property); -njs_int_t njs_value_property(njs_vm_t *vm, njs_value_t *value, - njs_value_t *property, njs_value_t *retval); -njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - njs_value_t *property, njs_value_t *value); njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, const njs_value_t *value, uint8_t attributes); njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj, diff -r e592647bdb12 -r ca8ce2161d0c src/njs_object_prop.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/njs_object_prop.c Fri Aug 02 23:36:42 2019 +0800 @@ -0,0 +1,714 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + + +#include + + +static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm, + const njs_value_t *name, const njs_object_t *descriptor); + + +njs_object_prop_t * +njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, + const njs_value_t *value, uint8_t attributes) +{ + njs_object_prop_t *prop; + + prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), + sizeof(njs_object_prop_t)); + + if (njs_fast_path(prop != NULL)) { + /* GC: retain. */ + prop->value = *value; + + /* GC: retain. */ + prop->name = *name; + + prop->type = NJS_PROPERTY; + prop->writable = attributes; + prop->enumerable = attributes; + prop->configurable = attributes; + + prop->getter = njs_value_invalid; + prop->setter = njs_value_invalid; + + return prop; + } + + njs_memory_error(vm); + + return NULL; +} + + +njs_object_prop_t * +njs_object_property(njs_vm_t *vm, const njs_object_t *object, + njs_lvlhsh_query_t *lhq) +{ + njs_int_t ret; + + lhq->proto = &njs_object_hash_proto; + + do { + ret = njs_lvlhsh_find(&object->hash, lhq); + + if (njs_fast_path(ret == NJS_OK)) { + return lhq->value; + } + + ret = njs_lvlhsh_find(&object->shared_hash, lhq); + + if (njs_fast_path(ret == NJS_OK)) { + return lhq->value; + } + + object = object->__proto__; + + } while (object != NULL); + + return NULL; +} + + +/* + * ES5.1, 8.12.9: [[DefineOwnProperty]] + * Limited support of special descriptors like length and array index + * (values can be set, but without property flags support). + */ +njs_int_t +njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, + njs_value_t *name, njs_value_t *value) +{ + njs_int_t ret; + njs_object_prop_t *prop, *prev; + njs_property_query_t pq; + + njs_string_get(name, &pq.lhq.key); + pq.lhq.key_hash = njs_djb_hash(pq.lhq.key.start, pq.lhq.key.length); + pq.lhq.proto = &njs_object_hash_proto; + + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 1); + + ret = njs_property_query(vm, &pq, object, name); + + if (ret != NJS_OK && ret != NJS_DECLINED) { + return ret; + } + + prop = njs_descriptor_prop(vm, name, njs_object(value)); + if (njs_slow_path(prop == NULL)) { + return NJS_ERROR; + } + + if (njs_fast_path(ret == NJS_DECLINED)) { + + /* 6.2.5.6 CompletePropertypropriptor */ + + if (njs_is_accessor_descriptor(prop)) { + if (!njs_is_valid(&prop->getter)) { + prop->getter = njs_value_undefined; + } + + if (!njs_is_valid(&prop->setter)) { + prop->setter = njs_value_undefined; + } + + } else { + if (prop->writable == NJS_ATTRIBUTE_UNSET) { + prop->writable = 0; + } + + if (!njs_is_valid(&prop->value)) { + prop->value = njs_value_undefined; + } + } + + if (prop->enumerable == NJS_ATTRIBUTE_UNSET) { + prop->enumerable = 0; + } + + if (prop->configurable == NJS_ATTRIBUTE_UNSET) { + prop->configurable = 0; + } + + if (njs_slow_path(pq.lhq.value != NULL)) { + prev = pq.lhq.value; + + if (njs_slow_path(prev->type == NJS_WHITEOUT)) { + /* Previously deleted property. */ + *prev = *prop; + } + + } else { + pq.lhq.value = prop; + pq.lhq.replace = 0; + pq.lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(njs_object_hash(object), &pq.lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + } + + return NJS_OK; + } + + /* Updating existing prop. */ + + if (njs_slow_path(pq.shared)) { + ret = njs_prop_private_copy(vm, &pq); + + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + prev = pq.lhq.value; + + switch (prev->type) { + case NJS_METHOD: + case NJS_PROPERTY: + case NJS_PROPERTY_HANDLER: + break; + + case NJS_PROPERTY_REF: + if (njs_is_valid(&prop->value)) { + *prev->value.data.u.value = prop->value; + } else { + *prev->value.data.u.value = njs_value_undefined; + } + + return NJS_OK; + + default: + njs_internal_error(vm, "unexpected property type \"%s\" " + "while defining property", + njs_prop_type_string(prev->type)); + + return NJS_ERROR; + } + + /* 9.1.6.3 ValidateAndApplyPropertyDescriptor */ + + if (!prev->configurable) { + + if (prop->configurable == NJS_ATTRIBUTE_TRUE) { + goto exception; + } + + if (prop->enumerable != NJS_ATTRIBUTE_UNSET + && prev->enumerable != prop->enumerable) + { + goto exception; + } + } + + if (njs_is_generic_descriptor(prop)) { + goto done; + } + + if (njs_is_data_descriptor(prev) != njs_is_data_descriptor(prop)) { + if (!prev->configurable) { + goto exception; + } + + /* + * 6.b-c Preserve the existing values of the converted property's + * [[Configurable]] and [[Enumerable]] attributes and set the rest of + * the property's attributes to their default values. + */ + + if (njs_is_data_descriptor(prev)) { + prev->getter = njs_value_undefined; + prev->setter = njs_value_undefined; + + prev->value = njs_value_invalid; + prev->writable = NJS_ATTRIBUTE_UNSET; + + } else { + prev->value = njs_value_undefined; + prev->writable = NJS_ATTRIBUTE_FALSE; + + prev->getter = njs_value_invalid; + prev->setter = njs_value_invalid; + } + + + } else if (njs_is_data_descriptor(prev) + && njs_is_data_descriptor(prop)) + { + if (!prev->configurable && !prev->writable) { + if (prop->writable == NJS_ATTRIBUTE_TRUE) { + goto exception; + } + + if (njs_is_valid(&prop->value) + && prev->type != NJS_PROPERTY_HANDLER + && !njs_values_strict_equal(&prop->value, &prev->value)) + { + goto exception; + } + } + + } else { + if (!prev->configurable) { + if (njs_is_valid(&prop->getter) + && !njs_values_strict_equal(&prop->getter, &prev->getter)) + { + goto exception; + } + + if (njs_is_valid(&prop->setter) + && !njs_values_strict_equal(&prop->setter, &prev->setter)) + { + goto exception; + } + } + } + +done: + + /* + * 9. For each field of Desc that is present, set the corresponding + * attribute of the property named P of object O to the value of the field. + */ + + if (njs_is_valid(&prop->getter)) { + prev->getter = prop->getter; + } + + if (njs_is_valid(&prop->setter)) { + prev->setter = prop->setter; + } + + if (njs_is_valid(&prop->value)) { + if (prev->type == NJS_PROPERTY_HANDLER) { + if (njs_is_data_descriptor(prev) && prev->writable) { + ret = prev->value.data.u.prop_handler(vm, object, + &prop->value, + &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + } else { + prev->value = prop->value; + } + } + + if (prop->writable != NJS_ATTRIBUTE_UNSET) { + prev->writable = prop->writable; + } + + if (prop->enumerable != NJS_ATTRIBUTE_UNSET) { + prev->enumerable = prop->enumerable; + } + + if (prop->configurable != NJS_ATTRIBUTE_UNSET) { + prev->configurable = prop->configurable; + } + + return NJS_OK; + +exception: + + njs_type_error(vm, "Cannot redefine property: \"%V\"", &pq.lhq.key); + + return NJS_ERROR; +} + + +static njs_object_prop_t * +njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, + const njs_object_t *desc) +{ + njs_bool_t data, accessor; + njs_object_prop_t *prop, *pr; + const njs_value_t *setter, *getter; + njs_lvlhsh_query_t pq; + + data = 0; + accessor = 0; + + prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, + NJS_ATTRIBUTE_UNSET); + if (njs_slow_path(prop == NULL)) { + return NULL; + } + + getter = &njs_value_invalid; + pq.key = njs_str_value("get"); + pq.key_hash = NJS_GET_HASH; + + pr = njs_object_property(vm, desc, &pq); + if (pr != NULL) { + if (!njs_is_undefined(&pr->value) && !njs_is_function(&pr->value)) { + njs_type_error(vm, "Getter must be a function"); + return NULL; + } + + accessor = 1; + getter = &pr->value; + } + + prop->getter = *getter; + + setter = &njs_value_invalid; + pq.key = njs_str_value("set"); + pq.key_hash = NJS_SET_HASH; + + pr = njs_object_property(vm, desc, &pq); + if (pr != NULL) { + if (!njs_is_undefined(&pr->value) && !njs_is_function(&pr->value)) { + njs_type_error(vm, "Setter must be a function"); + return NULL; + } + + accessor = 1; + setter = &pr->value; + } + + prop->setter = *setter; + + pq.key = njs_str_value("value"); + pq.key_hash = NJS_VALUE_HASH; + + pr = njs_object_property(vm, desc, &pq); + if (pr != NULL) { + data = 1; + prop->value = pr->value; + } + + pq.key = njs_str_value("writable"); + pq.key_hash = NJS_WRITABABLE_HASH; + + pr = njs_object_property(vm, desc, &pq); + if (pr != NULL) { + data = 1; + prop->writable = pr->value.data.truth; + } + + pq.key = njs_str_value("enumerable"); + pq.key_hash = NJS_ENUMERABLE_HASH; + + pr = njs_object_property(vm, desc, &pq); + if (pr != NULL) { + prop->enumerable = pr->value.data.truth; + } + + pq.key = njs_str_value("configurable"); + pq.key_hash = NJS_CONFIGURABLE_HASH; + + pr = njs_object_property(vm, desc, &pq); + if (pr != NULL) { + prop->configurable = pr->value.data.truth; + } + + if (accessor && data) { + njs_type_error(vm, "Cannot both specify accessors " + "and a value or writable attribute"); + return NULL; + } + + return prop; +} + + +static const njs_value_t njs_object_value_string = njs_string("value"); +static const njs_value_t njs_object_get_string = njs_string("get"); +static const njs_value_t njs_object_set_string = njs_string("set"); +static const njs_value_t njs_object_writable_string = + njs_string("writable"); +static const njs_value_t njs_object_enumerable_string = + njs_string("enumerable"); +static const njs_value_t njs_object_configurable_string = + njs_string("configurable"); + + +njs_int_t +njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, + njs_value_t *value, njs_value_t *property) +{ + njs_int_t ret; + njs_object_t *desc; + njs_object_prop_t *pr, *prop; + const njs_value_t *setval; + njs_lvlhsh_query_t lhq; + njs_property_query_t pq; + + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); + + ret = njs_property_query(vm, &pq, value, property); + + switch (ret) { + case NJS_OK: + break; + + case NJS_DECLINED: + *dest = njs_value_undefined; + return NJS_OK; + + case NJS_ERROR: + default: + return ret; + } + + prop = pq.lhq.value; + + switch (prop->type) { + case NJS_PROPERTY: + break; + + case NJS_PROPERTY_HANDLER: + pq.scratch = *prop; + prop = &pq.scratch; + ret = prop->value.data.u.prop_handler(vm, value, NULL, &prop->value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + break; + + case NJS_METHOD: + if (pq.shared) { + ret = njs_prop_private_copy(vm, &pq); + + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + prop = pq.lhq.value; + } + + break; + + default: + njs_type_error(vm, "unexpected property type: %s", + njs_prop_type_string(prop->type)); + return NJS_ERROR; + } + + desc = njs_object_alloc(vm); + if (njs_slow_path(desc == NULL)) { + return NJS_ERROR; + } + + lhq.proto = &njs_object_hash_proto; + lhq.replace = 0; + lhq.pool = vm->mem_pool; + + if (njs_is_data_descriptor(prop)) { + + lhq.key = njs_str_value("value"); + lhq.key_hash = NJS_VALUE_HASH; + + pr = njs_object_prop_alloc(vm, &njs_object_value_string, &prop->value, + 1); + if (njs_slow_path(pr == NULL)) { + return NJS_ERROR; + } + + lhq.value = pr; + + ret = njs_lvlhsh_insert(&desc->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + lhq.key = njs_str_value("writable"); + lhq.key_hash = NJS_WRITABABLE_HASH; + + setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false; + + pr = njs_object_prop_alloc(vm, &njs_object_writable_string, setval, 1); + if (njs_slow_path(pr == NULL)) { + return NJS_ERROR; + } + + lhq.value = pr; + + ret = njs_lvlhsh_insert(&desc->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + } else { + + lhq.key = njs_str_value("get"); + lhq.key_hash = NJS_GET_HASH; + + pr = njs_object_prop_alloc(vm, &njs_object_get_string, &prop->getter, + 1); + if (njs_slow_path(pr == NULL)) { + return NJS_ERROR; + } + + lhq.value = pr; + + ret = njs_lvlhsh_insert(&desc->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + lhq.key = njs_str_value("set"); + lhq.key_hash = NJS_SET_HASH; + + pr = njs_object_prop_alloc(vm, &njs_object_set_string, &prop->setter, + 1); + if (njs_slow_path(pr == NULL)) { + return NJS_ERROR; + } + + lhq.value = pr; + + ret = njs_lvlhsh_insert(&desc->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + } + + lhq.key = njs_str_value("enumerable"); + lhq.key_hash = NJS_ENUMERABLE_HASH; + + setval = (prop->enumerable == 1) ? &njs_value_true : &njs_value_false; + + pr = njs_object_prop_alloc(vm, &njs_object_enumerable_string, setval, 1); + if (njs_slow_path(pr == NULL)) { + return NJS_ERROR; + } + + lhq.value = pr; + + ret = njs_lvlhsh_insert(&desc->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + lhq.key = njs_str_value("configurable"); + lhq.key_hash = NJS_CONFIGURABLE_HASH; + + setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false; + + pr = njs_object_prop_alloc(vm, &njs_object_configurable_string, setval, 1); + if (njs_slow_path(pr == NULL)) { + return NJS_ERROR; + } + + lhq.value = pr; + + ret = njs_lvlhsh_insert(&desc->hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + njs_set_object(dest, desc); + + return NJS_OK; +} + + +njs_int_t +njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) +{ + njs_int_t ret; + njs_function_t *function; + njs_object_prop_t *prop, *shared, *name; + njs_lvlhsh_query_t lhq; + + static const njs_value_t name_string = njs_string("name"); + + prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), + sizeof(njs_object_prop_t)); + if (njs_slow_path(prop == NULL)) { + njs_memory_error(vm); + return NJS_ERROR; + } + + shared = pq->lhq.value; + *prop = *shared; + + pq->lhq.replace = 0; + pq->lhq.value = prop; + pq->lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + if (!njs_is_function(&prop->value)) { + return NJS_OK; + } + + function = njs_function_value_copy(vm, &prop->value); + if (njs_slow_path(function == NULL)) { + return NJS_ERROR; + } + + if (function->ctor) { + function->object.shared_hash = vm->shared->function_instance_hash; + + } else { + function->object.shared_hash = vm->shared->arrow_instance_hash; + } + + name = njs_object_prop_alloc(vm, &name_string, &prop->name, 0); + if (njs_slow_path(name == NULL)) { + return NJS_ERROR; + } + + name->configurable = 1; + + lhq.key_hash = NJS_NAME_HASH; + lhq.key = njs_str_value("name"); + lhq.replace = 0; + lhq.value = name; + lhq.proto = &njs_object_hash_proto; + lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(&function->object.hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + return NJS_OK; +} + + +const char * +njs_prop_type_string(njs_object_prop_type_t type) +{ + switch (type) { + case NJS_PROPERTY_REF: + return "property_ref"; + + case NJS_METHOD: + return "method"; + + case NJS_PROPERTY_HANDLER: + return "property handler"; + + case NJS_WHITEOUT: + return "whiteout"; + + case NJS_PROPERTY: + return "property"; + + default: + return "unknown"; + } +} diff -r e592647bdb12 -r ca8ce2161d0c src/njs_object_property.c --- a/src/njs_object_property.c Fri Aug 02 20:12:01 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1404 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#include -#include - - -static njs_int_t njs_object_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_object_t *object, - const njs_value_t *property); -static njs_int_t njs_array_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_array_t *array, uint32_t index); -static njs_int_t njs_string_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_value_t *object, uint32_t index); -static njs_int_t njs_external_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_value_t *object); -static njs_int_t njs_external_property_set(njs_vm_t *vm, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval); -static njs_int_t njs_external_property_delete(njs_vm_t *vm, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval); -static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm, - const njs_value_t *name, const njs_object_t *descriptor); - - -/* - * ES5.1, 8.12.1: [[GetOwnProperty]], [[GetProperty]]. - * The njs_property_query() returns values - * NJS_OK property has been found in object, - * retval of type njs_object_prop_t * is in pq->lhq.value. - * in NJS_PROPERTY_QUERY_GET - * prop->type is NJS_PROPERTY, NJS_METHOD or NJS_PROPERTY_HANDLER. - * in NJS_PROPERTY_QUERY_SET, NJS_PROPERTY_QUERY_DELETE - * prop->type is NJS_PROPERTY, NJS_PROPERTY_REF, NJS_METHOD or - * NJS_PROPERTY_HANDLER. - * NJS_DECLINED property was not found in object, - * if pq->lhq.value != NULL it contains retval of type - * njs_object_prop_t * where prop->type is NJS_WHITEOUT - * NJS_ERROR exception has been thrown. - * - * TODO: - * Object.defineProperty([1,2], '1', {configurable:false}) - */ - -njs_int_t -njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, - njs_value_t *property) -{ - uint32_t index; - njs_int_t ret; - njs_object_t *obj; - njs_value_t prop; - njs_function_t *function; - - if (njs_slow_path(!njs_is_primitive(property))) { - ret = njs_value_to_string(vm, &prop, property); - if (ret != NJS_OK) { - return ret; - } - - property = ∝ - } - - switch (object->type) { - - case NJS_BOOLEAN: - case NJS_NUMBER: - index = njs_primitive_prototype_index(object->type); - obj = &vm->prototypes[index].object; - break; - - case NJS_STRING: - if (njs_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { - index = njs_value_to_index(property); - - if (njs_fast_path(index < NJS_STRING_MAX_LENGTH)) { - return njs_string_property_query(vm, pq, object, index); - } - } - - obj = &vm->string_object; - break; - - case NJS_OBJECT: - case NJS_ARRAY: - case NJS_OBJECT_BOOLEAN: - case NJS_OBJECT_NUMBER: - case NJS_OBJECT_STRING: - case NJS_REGEXP: - case NJS_DATE: - case NJS_OBJECT_ERROR: - case NJS_OBJECT_EVAL_ERROR: - case NJS_OBJECT_INTERNAL_ERROR: - case NJS_OBJECT_RANGE_ERROR: - case NJS_OBJECT_REF_ERROR: - case NJS_OBJECT_SYNTAX_ERROR: - case NJS_OBJECT_TYPE_ERROR: - case NJS_OBJECT_URI_ERROR: - case NJS_OBJECT_VALUE: - obj = njs_object(object); - break; - - case NJS_FUNCTION: - function = njs_function_value_copy(vm, object); - if (njs_slow_path(function == NULL)) { - return NJS_ERROR; - } - - obj = &function->object; - break; - - case NJS_EXTERNAL: - obj = NULL; - break; - - case NJS_UNDEFINED: - case NJS_NULL: - default: - ret = njs_primitive_value_to_string(vm, &pq->value, property); - - if (njs_fast_path(ret == NJS_OK)) { - njs_string_get(&pq->value, &pq->lhq.key); - njs_type_error(vm, "cannot get property \"%V\" of undefined", - &pq->lhq.key); - return NJS_ERROR; - } - - njs_type_error(vm, "cannot get property \"unknown\" of undefined"); - - return NJS_ERROR; - } - - ret = njs_primitive_value_to_string(vm, &pq->value, property); - - if (njs_fast_path(ret == NJS_OK)) { - - njs_string_get(&pq->value, &pq->lhq.key); - pq->lhq.key_hash = njs_djb_hash(pq->lhq.key.start, pq->lhq.key.length); - - if (obj == NULL) { - pq->own = 1; - return njs_external_property_query(vm, pq, object); - } - - return njs_object_property_query(vm, pq, obj, property); - } - - return ret; -} - - -static njs_int_t -njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_object_t *object, const njs_value_t *property) -{ - uint32_t index; - njs_int_t ret; - njs_bool_t own; - njs_array_t *array; - njs_object_t *proto; - njs_object_prop_t *prop; - njs_object_value_t *ov; - - pq->lhq.proto = &njs_object_hash_proto; From hucong.c at foxmail.com Mon Aug 5 11:46:02 2019 From: hucong.c at foxmail.com (=?utf-8?B?6IOh6IGqIChodWNjKQ==?=) Date: Mon, 5 Aug 2019 19:46:02 +0800 Subject: RTMP with multiple worker processes and rtmp_auto_push Message-ID: On Friday, July 26, 2019 11:08, Carey Gister wrote: >Hi, > >I hope someone can help illuminate some background information related to this >module. I understand that the rtmp_auto_push directive worked with multiple >workers through nginx 1.7.x and then something changed in the nginx internals >and it stopped working and was no longer supported for multiple workers. > >Can someone provide background on what changed that had this feature stop >working? My manager has tasked me with getting this feature to work, if possible. > >Thanks, > >Carey Gister >415-310-5304 The following patch may solve your problem. diff --git a/ngx_rtmp_auto_push_module.c b/ngx_rtmp_auto_push_module.c index 60c85d7..436b176 100644 --- a/ngx_rtmp_auto_push_module.c +++ b/ngx_rtmp_auto_push_module.c @@ -140,6 +140,8 @@ ngx_rtmp_auto_push_init_process(ngx_cycle_t *cycle) return NGX_OK; } + ngx_rtmp_auto_push_module.ctx_index = 0; + apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_rtmp_auto_push_module); if (apcf->auto_push == 0) { From xeioex at nginx.com Mon Aug 5 12:53:05 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 12:53:05 +0000 Subject: [njs] Fixed njs_builtin_match(). Message-ID: details: https://hg.nginx.org/njs/rev/08505f72a3e4 branches: changeset: 1100:08505f72a3e4 user: hongzhidao date: Sun Aug 04 04:06:30 2019 -0400 description: Fixed njs_builtin_match(). Previously native functions were identified by comparing pointers to njs_function_t. This is not correct because njs_function_t maybe copied from shared prototypes. Instead pointers to native functions should be compared. diffstat: src/njs_builtin.c | 25 ++++++++++++++----------- src/test/njs_interactive_test.c | 5 +++++ 2 files changed, 19 insertions(+), 11 deletions(-) diffs (71 lines): diff -r ca8ce2161d0c -r 08505f72a3e4 src/njs_builtin.c --- a/src/njs_builtin.c Fri Aug 02 23:36:42 2019 +0800 +++ b/src/njs_builtin.c Sun Aug 04 04:06:30 2019 -0400 @@ -954,6 +954,7 @@ njs_builtin_match(const njs_object_init_ const njs_object_prop_t **prop, const njs_object_init_t **object) { njs_uint_t i; + njs_function_t *fun; const njs_object_init_t *o, **p; const njs_object_prop_t *pr; @@ -967,7 +968,9 @@ njs_builtin_match(const njs_object_init_ continue; } - if (function != njs_function(&pr->value)) { + fun = njs_function(&pr->value); + + if (function->u.native != fun->u.native) { continue; } @@ -993,6 +996,16 @@ njs_builtin_match_native_function(njs_vm const njs_object_prop_t *prop; const njs_function_init_t *fun; + fun = njs_native_functions; + + for (p = njs_function_init; *p != NULL; p++, fun++) { + if (function->u.native == fun->native) { + *name = (*p)->name; + + return NJS_OK; + } + } + middle = njs_str_value("."); ret = njs_builtin_match(njs_object_init, function, &prop, &obj); @@ -1014,16 +1027,6 @@ njs_builtin_match_native_function(njs_vm goto found; } - fun = njs_native_functions; - - for (p = njs_function_init; *p != NULL; p++, fun++) { - if (function->u.native == fun->native) { - *name = (*p)->name; - - return NJS_OK; - } - } - ret = njs_builtin_match(njs_module_init, function, &prop, &obj); if (ret == NJS_OK) { diff -r ca8ce2161d0c -r 08505f72a3e4 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Fri Aug 02 23:36:42 2019 +0800 +++ b/src/test/njs_interactive_test.c Sun Aug 04 04:06:30 2019 -0400 @@ -160,6 +160,11 @@ static njs_interactive_test_t njs_test[ " at Math.log (native)\n" " at main (native)\n") }, + { njs_str("var bound = Math.max.bind(null, {toString(){return {}}}); bound(1)" ENTER), + njs_str("TypeError: Cannot convert object to primitive value\n" + " at Math.max (native)\n" + " at main (native)\n") }, + { njs_str("eval()" ENTER), njs_str("InternalError: Not implemented\n" " at eval (native)\n" From xeioex at nginx.com Mon Aug 5 12:53:05 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 12:53:05 +0000 Subject: [njs] Added getter support for method frame calls. Message-ID: details: https://hg.nginx.org/njs/rev/04d7a5d93ae6 branches: changeset: 1101:04d7a5d93ae6 user: hongzhidao date: Sun Aug 04 04:13:02 2019 -0400 description: Added getter support for method frame calls. diffstat: src/njs_vmcode.c | 113 +++++++++------------------------------ src/test/njs_interactive_test.c | 4 + src/test/njs_unit_test.c | 5 + 3 files changed, 36 insertions(+), 86 deletions(-) diffs (184 lines): diff -r 08505f72a3e4 -r 04d7a5d93ae6 src/njs_vmcode.c --- a/src/njs_vmcode.c Sun Aug 04 04:06:30 2019 -0400 +++ b/src/njs_vmcode.c Sun Aug 04 04:13:02 2019 -0400 @@ -38,8 +38,6 @@ static njs_jump_off_t njs_vmcode_instanc static njs_jump_off_t njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld); -static njs_jump_off_t njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, - njs_value_t *method, u_char *pc); static njs_jump_off_t njs_vmcode_return(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval); @@ -85,6 +83,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c double num, exponent; int32_t i32; uint32_t u32; + njs_str_t string; njs_uint_t hint; njs_bool_t valid, lambda_call; njs_value_t *retval, *value1, *value2, *src, *s1, *s2; @@ -103,6 +102,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c njs_vmcode_test_jump_t *test_jump; njs_vmcode_equal_jump_t *equal; njs_vmcode_try_return_t *try_return; + njs_vmcode_method_frame_t *method_frame; njs_vmcode_function_frame_t *function_frame; next: @@ -683,11 +683,35 @@ next: break; case NJS_VMCODE_METHOD_FRAME: - ret = njs_vmcode_method_frame(vm, value1, value2, pc); + method_frame = (njs_vmcode_method_frame_t *) pc; + + ret = njs_value_property(vm, value1, value2, &dst); if (njs_slow_path(ret == NJS_ERROR)) { goto error; } + if (njs_slow_path(!njs_is_function(&dst))) { + ret = njs_value_to_string(vm, value2, value2); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_string_get(value2, &string); + njs_type_error(vm, + "(intermediate value)[\"%V\"] is not a function", + &string); + goto error; + } + + ret = njs_function_frame_create(vm, &dst, value1, + method_frame->nargs, + method_frame->ctor); + + if (njs_slow_path(ret != NJS_OK)) { + goto error; + } + + ret = sizeof(njs_vmcode_method_frame_t); break; case NJS_VMCODE_FUNCTION_CALL: @@ -1723,89 +1747,6 @@ njs_function_new_object(njs_vm_t *vm, nj static njs_jump_off_t -njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name, - u_char *pc) -{ - njs_str_t string; - njs_value_t *value; - njs_jump_off_t ret; - njs_object_prop_t *prop; - njs_property_query_t pq; - njs_vmcode_method_frame_t *method; - - value = NULL; - method = (njs_vmcode_method_frame_t *) pc; - - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - - ret = njs_property_query(vm, &pq, object, name); - - switch (ret) { - - case NJS_OK: - prop = pq.lhq.value; - - switch (prop->type) { - case NJS_PROPERTY: - case NJS_METHOD: - break; - - case NJS_PROPERTY_HANDLER: - pq.scratch = *prop; - prop = &pq.scratch; - ret = prop->value.data.u.prop_handler(vm, object, NULL, - &prop->value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - break; - - default: - njs_internal_error(vm, "unexpected property type \"%s\" " - "while getting method", - njs_prop_type_string(prop->type)); - - return NJS_ERROR; - } - - value = &prop->value; - - break; - - case NJS_DECLINED: - break; - - case NJS_ERROR: - default: - - return ret; - } - - if (value == NULL || !njs_is_function(value)) { - ret = njs_value_to_string(vm, name, name); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - - njs_string_get(name, &string); - njs_type_error(vm, "(intermediate value)[\"%V\"] is not a function", - &string); - return NJS_ERROR; - } - - ret = njs_function_frame_create(vm, value, object, method->nargs, - method->ctor); - - if (njs_fast_path(ret == NJS_OK)) { - return sizeof(njs_vmcode_method_frame_t); - } - - return ret; -} - - -static njs_jump_off_t njs_vmcode_return(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) { njs_value_t *value; diff -r 08505f72a3e4 -r 04d7a5d93ae6 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Sun Aug 04 04:06:30 2019 -0400 +++ b/src/test/njs_interactive_test.c Sun Aug 04 04:13:02 2019 -0400 @@ -165,6 +165,10 @@ static njs_interactive_test_t njs_test[ " at Math.max (native)\n" " at main (native)\n") }, + { njs_str("Object.prototype()" ENTER), + njs_str("TypeError: (intermediate value)[\"prototype\"] is not a function\n" + " at main (native)\n") }, + { njs_str("eval()" ENTER), njs_str("InternalError: Not implemented\n" " at eval (native)\n" diff -r 08505f72a3e4 -r 04d7a5d93ae6 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Sun Aug 04 04:06:30 2019 -0400 +++ b/src/test/njs_unit_test.c Sun Aug 04 04:13:02 2019 -0400 @@ -8559,6 +8559,11 @@ static njs_unit_test_t njs_test[] = "[] instanceof Function.prototype"), njs_str("Error: Oops") }, + { njs_str("var o = {};" + "Object.defineProperty(o, 'foo', { get: function() {return () => 1} });" + "o.foo()"), + njs_str("1") }, + /* global this. */ { njs_str("this"), From xeioex at nginx.com Mon Aug 5 15:18:06 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 15:18:06 +0000 Subject: [njs] Fixed Error() constructor with no arguments. Message-ID: details: https://hg.nginx.org/njs/rev/88ff9dfa847e branches: changeset: 1103:88ff9dfa847e user: hongzhidao date: Sun Aug 04 03:59:42 2019 -0400 description: Fixed Error() constructor with no arguments. diffstat: src/njs_error.c | 10 +++------- src/njs_value.h | 4 ++++ src/test/njs_unit_test.c | 5 +++++ 3 files changed, 12 insertions(+), 7 deletions(-) diffs (50 lines): diff -r a07dc8b56fd3 -r 88ff9dfa847e src/njs_error.c --- a/src/njs_error.c Mon Aug 05 17:36:09 2019 +0300 +++ b/src/njs_error.c Sun Aug 04 03:59:42 2019 -0400 @@ -133,14 +133,10 @@ njs_error_create(njs_vm_t *vm, njs_value njs_object_t *error; const njs_value_t *value; - if (nargs == 1) { - value = &njs_string_empty; + value = njs_arg(args, nargs, 1); - } else { - value = &args[1]; - } - - error = njs_error_alloc(vm, type, NULL, value); + error = njs_error_alloc(vm, type, NULL, + njs_is_defined(value) ? value : NULL); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } diff -r a07dc8b56fd3 -r 88ff9dfa847e src/njs_value.h --- a/src/njs_value.h Mon Aug 05 17:36:09 2019 +0300 +++ b/src/njs_value.h Sun Aug 04 03:59:42 2019 -0400 @@ -425,6 +425,10 @@ typedef struct { ((value)->type == NJS_UNDEFINED) +#define njs_is_defined(value) \ + ((value)->type != NJS_UNDEFINED) + + #define njs_is_null_or_undefined(value) \ ((value)->type <= NJS_UNDEFINED) diff -r a07dc8b56fd3 -r 88ff9dfa847e src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Aug 05 17:36:09 2019 +0300 +++ b/src/test/njs_unit_test.c Sun Aug 04 03:59:42 2019 -0400 @@ -7865,6 +7865,11 @@ static njs_unit_test_t njs_test[] = { njs_str("Error().__proto__.__proto__ == Object.prototype"), njs_str("true") }, + { njs_str("Error.prototype.message = 'm';" + "Error.prototype.name = 'n';" + "new Error()"), + njs_str("n: m") }, + { njs_str("EvalError('e')"), njs_str("EvalError: e") }, From xeioex at nginx.com Mon Aug 5 15:18:06 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 15:18:06 +0000 Subject: [njs] Separating private from public headers. Message-ID: details: https://hg.nginx.org/njs/rev/a07dc8b56fd3 branches: changeset: 1102:a07dc8b56fd3 user: Dmitry Volyntsev date: Mon Aug 05 17:36:09 2019 +0300 description: Separating private from public headers. diffstat: src/njs.h | 2 ++ src/njs_clang.h | 1 - src/njs_diyfp.h | 3 --- src/njs_main.h | 3 +++ src/njs_malloc.h | 10 ---------- src/njs_math.h | 3 --- src/njs_number.h | 4 ---- src/njs_pcre.c | 1 - src/njs_regexp_pattern.h | 3 --- src/njs_string.h | 1 - src/njs_types.h | 2 +- src/njs_unix.h | 13 ++++++++++--- src/njs_value.h | 10 ---------- src/test/njs_benchmark.c | 1 - src/test/njs_interactive_test.c | 1 - 15 files changed, 16 insertions(+), 42 deletions(-) diffs (220 lines): diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs.h --- a/src/njs.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs.h Mon Aug 05 17:36:09 2019 +0300 @@ -14,10 +14,12 @@ #define NJS_VERSION "0.3.4" +#include /* STDOUT_FILENO, STDERR_FILENO */ #include #include #include #include +#include typedef uintptr_t njs_index_t; diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_clang.h --- a/src/njs_clang.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_clang.h Mon Aug 05 17:36:09 2019 +0300 @@ -10,7 +10,6 @@ #include #include /* offsetof(). */ -#include /* NULL. */ #define njs_inline static inline __attribute__((always_inline)) diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_diyfp.h --- a/src/njs_diyfp.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_diyfp.h Mon Aug 05 17:36:09 2019 +0300 @@ -11,9 +11,6 @@ #ifndef _NJS_DIYFP_H_INCLUDED_ #define _NJS_DIYFP_H_INCLUDED_ -#include -#include - typedef struct { uint64_t significand; diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_main.h --- a/src/njs_main.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_main.h Mon Aug 05 17:36:09 2019 +0300 @@ -31,6 +31,9 @@ #include #include +#include +#include + #include #include #include diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_malloc.h --- a/src/njs_malloc.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_malloc.h Mon Aug 05 17:36:09 2019 +0300 @@ -7,16 +7,6 @@ #ifndef _NJS_MALLOC_H_INCLUDED_ #define _NJS_MALLOC_H_INCLUDED_ -#include - -/* - * alloca() is defined in stdlib.h in Linux, FreeBSD and MacOSX - * and in alloca.h in Linux, Solaris and MacOSX. - */ -#if (NJS_SOLARIS) -#include -#endif - #define njs_malloc(size) malloc(size) #define njs_free(p) free(p) diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_math.h --- a/src/njs_math.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_math.h Mon Aug 05 17:36:09 2019 +0300 @@ -8,9 +8,6 @@ #define _NJS_MATH_H_INCLUDED_ -#include - - extern const njs_object_init_t njs_math_object_init; diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_number.h --- a/src/njs_number.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_number.h Mon Aug 05 17:36:09 2019 +0300 @@ -8,10 +8,6 @@ #define _NJS_NUMBER_H_INCLUDED_ -#include -#include - - uint32_t njs_value_to_index(const njs_value_t *value); double njs_number_dec_parse(const u_char **start, const u_char *end); uint64_t njs_number_oct_parse(const u_char **start, const u_char *end); diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_pcre.c --- a/src/njs_pcre.c Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_pcre.c Mon Aug 05 17:36:09 2019 +0300 @@ -6,7 +6,6 @@ #include -#include static void *njs_pcre_malloc(size_t size); diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_regexp_pattern.h --- a/src/njs_regexp_pattern.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_regexp_pattern.h Mon Aug 05 17:36:09 2019 +0300 @@ -7,9 +7,6 @@ #ifndef _NJS_REGEXP_PATTERN_H_INCLUDED_ #define _NJS_REGEXP_PATTERN_H_INCLUDED_ -#include -#include - typedef enum { NJS_REGEXP_BYTE = 0, diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_string.h --- a/src/njs_string.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_string.h Mon Aug 05 17:36:09 2019 +0300 @@ -7,7 +7,6 @@ #ifndef _NJS_STRING_H_INCLUDED_ #define _NJS_STRING_H_INCLUDED_ -#include /* * nJSVM supports two string variants: diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_types.h --- a/src/njs_types.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_types.h Mon Aug 05 17:36:09 2019 +0300 @@ -23,7 +23,7 @@ /* u_char, u_int, int8_t, int32_t, int64_t, size_t, off_t. */ #include -#include +#include #if (__LP64__) diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_unix.h --- a/src/njs_unix.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_unix.h Mon Aug 05 17:36:09 2019 +0300 @@ -22,17 +22,24 @@ #endif /* NJS_LINUX */ + #include -#include -#include /* offsetof() */ +#include #include -#include #include #include #include #include #include +/* + * alloca() is defined in stdlib.h in Linux, FreeBSD and MacOSX + * and in alloca.h in Linux, Solaris and MacOSX. + */ +#if (NJS_SOLARIS) +#include +#endif + #include #include #include diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/njs_value.h --- a/src/njs_value.h Sun Aug 04 04:13:02 2019 -0400 +++ b/src/njs_value.h Mon Aug 05 17:36:09 2019 +0300 @@ -8,16 +8,6 @@ #define _NJS_VALUE_H_INCLUDED_ -#include -#include -#include -#include -#include -#include - -#include - - /* * The order of the enum is used in njs_vmcode_typeof() * and njs_object_prototype_to_string(). diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Sun Aug 04 04:13:02 2019 -0400 +++ b/src/test/njs_benchmark.c Mon Aug 05 17:36:09 2019 +0300 @@ -5,7 +5,6 @@ */ #include -#include #include #include diff -r 04d7a5d93ae6 -r a07dc8b56fd3 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Sun Aug 04 04:13:02 2019 -0400 +++ b/src/test/njs_interactive_test.c Mon Aug 05 17:36:09 2019 +0300 @@ -5,7 +5,6 @@ */ #include -#include #include #include From xeioex at nginx.com Mon Aug 5 15:18:07 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 15:18:07 +0000 Subject: [njs] Using njs_is_defined() where appropriate. Message-ID: details: https://hg.nginx.org/njs/rev/8eb80902c862 branches: changeset: 1104:8eb80902c862 user: Dmitry Volyntsev date: Mon Aug 05 18:17:15 2019 +0300 description: Using njs_is_defined() where appropriate. diffstat: src/njs_array.c | 4 ++-- src/njs_json.c | 2 +- src/njs_object_prop.c | 4 ++-- src/njs_regexp.c | 2 +- src/njs_string.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diffs (73 lines): diff -r 88ff9dfa847e -r 8eb80902c862 src/njs_array.c --- a/src/njs_array.c Sun Aug 04 03:59:42 2019 -0400 +++ b/src/njs_array.c Mon Aug 05 18:17:15 2019 +0300 @@ -434,8 +434,8 @@ njs_array_prototype_slice(njs_vm_t *vm, length = 0; } else { - if (!njs_is_undefined(njs_arg(args, nargs, 2))) { - end = njs_primitive_value_to_integer(&args[2]); + if (njs_is_defined(njs_arg(args, nargs, 2))) { + end = njs_primitive_value_to_integer(njs_argument(args, 2)); } else { end = length; diff -r 88ff9dfa847e -r 8eb80902c862 src/njs_json.c --- a/src/njs_json.c Sun Aug 04 03:59:42 2019 -0400 +++ b/src/njs_json.c Mon Aug 05 18:17:15 2019 +0300 @@ -1408,7 +1408,7 @@ start: break; case NJS_JSON_ARRAY_TO_JSON_REPLACED: - if (!njs_is_undefined(&stringify->retval) + if (njs_is_defined(&stringify->retval) && njs_is_function(&stringify->replacer)) { ret = njs_json_stringify_replacer(vm, stringify, NULL, diff -r 88ff9dfa847e -r 8eb80902c862 src/njs_object_prop.c --- a/src/njs_object_prop.c Sun Aug 04 03:59:42 2019 -0400 +++ b/src/njs_object_prop.c Mon Aug 05 18:17:15 2019 +0300 @@ -348,7 +348,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { - if (!njs_is_undefined(&pr->value) && !njs_is_function(&pr->value)) { + if (njs_is_defined(&pr->value) && !njs_is_function(&pr->value)) { njs_type_error(vm, "Getter must be a function"); return NULL; } @@ -365,7 +365,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { - if (!njs_is_undefined(&pr->value) && !njs_is_function(&pr->value)) { + if (njs_is_defined(&pr->value) && !njs_is_function(&pr->value)) { njs_type_error(vm, "Setter must be a function"); return NULL; } diff -r 88ff9dfa847e -r 8eb80902c862 src/njs_regexp.c --- a/src/njs_regexp.c Sun Aug 04 03:59:42 2019 -0400 +++ b/src/njs_regexp.c Mon Aug 05 18:17:15 2019 +0300 @@ -148,7 +148,7 @@ njs_regexp_constructor(njs_vm_t *vm, njs pattern = &source; } - if (!njs_is_undefined(flags)) { + if (njs_is_defined(flags)) { ret = njs_primitive_value_to_string(vm, &flags_string, flags); if (njs_slow_path(ret != NJS_OK)) { return ret; diff -r 88ff9dfa847e -r 8eb80902c862 src/njs_string.c --- a/src/njs_string.c Sun Aug 04 03:59:42 2019 -0400 +++ b/src/njs_string.c Mon Aug 05 18:17:15 2019 +0300 @@ -1290,8 +1290,8 @@ njs_string_slice_args(njs_slice_prop_t * length = 0; } else { - if (!njs_is_undefined(njs_arg(args, nargs, 2))) { - value = njs_arg(args, nargs, 2); + if (njs_is_defined(njs_arg(args, nargs, 2))) { + value = njs_argument(args, 2); end = njs_number(value); } else { From xeioex at nginx.com Mon Aug 5 15:18:07 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 15:18:07 +0000 Subject: [njs] Fixed njs_error_new() for UTF8 messages. Message-ID: details: https://hg.nginx.org/njs/rev/bfdf58ec9116 branches: changeset: 1105:bfdf58ec9116 user: Dmitry Volyntsev date: Mon Aug 05 17:10:59 2019 +0300 description: Fixed njs_error_new() for UTF8 messages. diffstat: src/njs_error.c | 15 +++++++++++---- 1 files changed, 11 insertions(+), 4 deletions(-) diffs (35 lines): diff -r 8eb80902c862 -r bfdf58ec9116 src/njs_error.c --- a/src/njs_error.c Mon Aug 05 18:17:15 2019 +0300 +++ b/src/njs_error.c Mon Aug 05 17:10:59 2019 +0300 @@ -16,20 +16,27 @@ void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, u_char *start, size_t size) { + ssize_t length; njs_int_t ret; njs_value_t string; njs_object_t *error; - ret = njs_string_new(vm, &string, start, size, size); + length = njs_utf8_length(start, size); + if (njs_slow_path(length < 0)) { + length = 0; + } + + ret = njs_string_new(vm, &string, start, size, length); if (njs_slow_path(ret != NJS_OK)) { return; } error = njs_error_alloc(vm, type, NULL, &string); + if (njs_slow_path(error == NULL)) { + return; + } - if (njs_fast_path(error != NULL)) { - njs_set_type_object(dst, error, type); - } + njs_set_type_object(dst, error, type); } From xeioex at nginx.com Mon Aug 5 16:02:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 16:02:46 +0000 Subject: [njs] Removed obsolete commentaries for njs_value_property() and friends. Message-ID: details: https://hg.nginx.org/njs/rev/439e2f67acf8 branches: changeset: 1107:439e2f67acf8 user: Dmitry Volyntsev date: Mon Aug 05 19:02:17 2019 +0300 description: Removed obsolete commentaries for njs_value_property() and friends. After NJS_TRAP and NJS_APPLIED was eliminanted they are mostly useless. diffstat: src/njs_value.c | 13 ------------- 1 files changed, 0 insertions(+), 13 deletions(-) diffs (30 lines): diff -r 1acb3acb1059 -r 439e2f67acf8 src/njs_value.c --- a/src/njs_value.c Sun Aug 04 11:17:48 2019 -0400 +++ b/src/njs_value.c Mon Aug 05 19:02:17 2019 +0300 @@ -911,15 +911,6 @@ njs_external_property_delete(njs_vm_t *v } -/* - * ES5.1, 8.12.3: [[Get]]. - * NJS_OK property has been found in object, - * retval will contain the property's value - * - * NJS_DECLINED property was not found in object - * NJS_ERROR exception has been thrown. - * retval will contain undefined - */ njs_int_t njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, njs_value_t *retval) @@ -1004,10 +995,6 @@ njs_value_property(njs_vm_t *vm, njs_val } -/* - * NJS_OK property has been set successfully - * NJS_ERROR exception has been thrown. - */ njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, njs_value_t *setval) From xeioex at nginx.com Mon Aug 5 16:02:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 16:02:46 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/1acb3acb1059 branches: changeset: 1106:1acb3acb1059 user: hongzhidao date: Sun Aug 04 11:17:48 2019 -0400 description: Style. Renaming arguments of the functions as follows: 1) "property" -> "key". 2) if function handles values of any type, its main argument is named "value". diffstat: src/njs_object.h | 2 +- src/njs_object_prop.c | 4 +- src/njs_value.c | 72 +++++++++++++++++++++++++------------------------- src/njs_value.h | 8 ++-- src/njs_vmcode.c | 47 ++++++++++++++++----------------- 5 files changed, 66 insertions(+), 67 deletions(-) diffs (468 lines): diff -r bfdf58ec9116 -r 1acb3acb1059 src/njs_object.h --- a/src/njs_object.h Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_object.h Sun Aug 04 11:17:48 2019 -0400 @@ -61,7 +61,7 @@ njs_object_prop_t *njs_object_property(n njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, njs_value_t *name, njs_value_t *value); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, - njs_value_t *value, njs_value_t *property); + njs_value_t *value, njs_value_t *setval); njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); const char *njs_prop_type_string(njs_object_prop_type_t type); diff -r bfdf58ec9116 -r 1acb3acb1059 src/njs_object_prop.c --- a/src/njs_object_prop.c Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_object_prop.c Sun Aug 04 11:17:48 2019 -0400 @@ -433,7 +433,7 @@ static const njs_value_t njs_object_con njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, - njs_value_t *value, njs_value_t *property) + njs_value_t *value, njs_value_t *key) { njs_int_t ret; njs_object_t *desc; @@ -444,7 +444,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); - ret = njs_property_query(vm, &pq, value, property); + ret = njs_property_query(vm, &pq, value, key); switch (ret) { case NJS_OK: diff -r bfdf58ec9116 -r 1acb3acb1059 src/njs_value.c --- a/src/njs_value.c Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_value.c Sun Aug 04 11:17:48 2019 -0400 @@ -10,7 +10,7 @@ static njs_int_t njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_object_t *object, - const njs_value_t *property); + const njs_value_t *key); static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_array_t *array, uint32_t index); static njs_int_t njs_string_property_query(njs_vm_t *vm, @@ -487,8 +487,8 @@ njs_value_is_function(const njs_value_t */ njs_int_t -njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, - njs_value_t *property) +njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, + njs_value_t *key) { uint32_t index; njs_int_t ret; @@ -496,29 +496,29 @@ njs_property_query(njs_vm_t *vm, njs_pro njs_value_t prop; njs_function_t *function; - if (njs_slow_path(!njs_is_primitive(property))) { - ret = njs_value_to_string(vm, &prop, property); + if (njs_slow_path(!njs_is_primitive(key))) { + ret = njs_value_to_string(vm, &prop, key); if (ret != NJS_OK) { return ret; } - property = ∝ + key = ∝ } - switch (object->type) { + switch (value->type) { case NJS_BOOLEAN: case NJS_NUMBER: - index = njs_primitive_prototype_index(object->type); + index = njs_primitive_prototype_index(value->type); obj = &vm->prototypes[index].object; break; case NJS_STRING: - if (njs_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { - index = njs_value_to_index(property); + if (njs_fast_path(!njs_is_null_or_undefined_or_boolean(key))) { + index = njs_value_to_index(key); if (njs_fast_path(index < NJS_STRING_MAX_LENGTH)) { - return njs_string_property_query(vm, pq, object, index); + return njs_string_property_query(vm, pq, value, index); } } @@ -541,11 +541,11 @@ njs_property_query(njs_vm_t *vm, njs_pro case NJS_OBJECT_TYPE_ERROR: case NJS_OBJECT_URI_ERROR: case NJS_OBJECT_VALUE: - obj = njs_object(object); + obj = njs_object(value); break; case NJS_FUNCTION: - function = njs_function_value_copy(vm, object); + function = njs_function_value_copy(vm, value); if (njs_slow_path(function == NULL)) { return NJS_ERROR; } @@ -560,7 +560,7 @@ njs_property_query(njs_vm_t *vm, njs_pro case NJS_UNDEFINED: case NJS_NULL: default: - ret = njs_primitive_value_to_string(vm, &pq->value, property); + ret = njs_primitive_value_to_string(vm, &pq->value, key); if (njs_fast_path(ret == NJS_OK)) { njs_string_get(&pq->value, &pq->lhq.key); @@ -574,7 +574,7 @@ njs_property_query(njs_vm_t *vm, njs_pro return NJS_ERROR; } - ret = njs_primitive_value_to_string(vm, &pq->value, property); + ret = njs_primitive_value_to_string(vm, &pq->value, key); if (njs_fast_path(ret == NJS_OK)) { @@ -583,10 +583,10 @@ njs_property_query(njs_vm_t *vm, njs_pro if (obj == NULL) { pq->own = 1; - return njs_external_property_query(vm, pq, object); + return njs_external_property_query(vm, pq, value); } - return njs_object_property_query(vm, pq, obj, property); + return njs_object_property_query(vm, pq, obj, key); } return ret; @@ -595,7 +595,7 @@ njs_property_query(njs_vm_t *vm, njs_pro static njs_int_t njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_object_t *object, const njs_value_t *property) + njs_object_t *object, const njs_value_t *key) { uint32_t index; njs_int_t ret; @@ -615,10 +615,10 @@ njs_object_property_query(njs_vm_t *vm, do { pq->prototype = proto; - if (!njs_is_null_or_undefined_or_boolean(property)) { + if (!njs_is_null_or_undefined_or_boolean(key)) { switch (proto->type) { case NJS_ARRAY: - index = njs_value_to_index(property); + index = njs_value_to_index(key); if (njs_fast_path(index < NJS_ARRAY_MAX_INDEX)) { array = (njs_array_t *) proto; return njs_array_property_query(vm, pq, array, index); @@ -627,7 +627,7 @@ njs_object_property_query(njs_vm_t *vm, break; case NJS_OBJECT_STRING: - index = njs_value_to_index(property); + index = njs_value_to_index(key); if (njs_fast_path(index < NJS_STRING_MAX_LENGTH)) { ov = (njs_object_value_t *) proto; ret = njs_string_property_query(vm, pq, &ov->value, index); @@ -921,7 +921,7 @@ njs_external_property_delete(njs_vm_t *v * retval will contain undefined */ njs_int_t -njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *property, +njs_value_property(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, njs_value_t *retval) { njs_int_t ret; @@ -930,7 +930,7 @@ njs_value_property(njs_vm_t *vm, njs_val njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - ret = njs_property_query(vm, &pq, value, property); + ret = njs_property_query(vm, &pq, value, key); switch (ret) { @@ -1009,16 +1009,16 @@ njs_value_property(njs_vm_t *vm, njs_val * NJS_ERROR exception has been thrown. */ njs_int_t -njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - njs_value_t *property, njs_value_t *value) +njs_value_property_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, + njs_value_t *setval) { njs_int_t ret; njs_object_prop_t *prop, *shared; njs_property_query_t pq; - if (njs_is_primitive(object)) { + if (njs_is_primitive(value)) { njs_type_error(vm, "property set on primitive %s type", - njs_type_string(object->type)); + njs_type_string(value->type)); return NJS_ERROR; } @@ -1026,7 +1026,7 @@ njs_value_property_set(njs_vm_t *vm, njs njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0); - ret = njs_property_query(vm, &pq, object, property); + ret = njs_property_query(vm, &pq, value, key); switch (ret) { @@ -1037,24 +1037,24 @@ njs_value_property_set(njs_vm_t *vm, njs if (!prop->writable) { njs_type_error(vm, "Cannot assign to read-only property \"%V\" of %s", - &pq.lhq.key, njs_type_string(object->type)); + &pq.lhq.key, njs_type_string(value->type)); return NJS_ERROR; } } else { if (njs_is_function(&prop->setter)) { return njs_function_call(vm, njs_function(&prop->setter), - object, value, 1, &vm->retval); + value, setval, 1, &vm->retval); } njs_type_error(vm, "Cannot set property \"%V\" of %s which has only a getter", - &pq.lhq.key, njs_type_string(object->type)); + &pq.lhq.key, njs_type_string(value->type)); return NJS_ERROR; } if (prop->type == NJS_PROPERTY_HANDLER) { - ret = prop->value.data.u.prop_handler(vm, object, value, + ret = prop->value.data.u.prop_handler(vm, value, setval, &vm->retval); if (ret != NJS_DECLINED) { return ret; @@ -1073,7 +1073,7 @@ njs_value_property_set(njs_vm_t *vm, njs goto found; case NJS_PROPERTY_REF: - *prop->value.data.u.value = *value; + *prop->value.data.u.value = *setval; return NJS_OK; default: @@ -1110,7 +1110,7 @@ njs_value_property_set(njs_vm_t *vm, njs return ret; } - if (njs_slow_path(!njs_object(object)->extensible)) { + if (njs_slow_path(!njs_object(value)->extensible)) { njs_type_error(vm, "Cannot add property \"%V\", " "object is not extensible", &pq.lhq.key); return NJS_ERROR; @@ -1130,7 +1130,7 @@ njs_value_property_set(njs_vm_t *vm, njs pq.lhq.value = prop; pq.lhq.pool = vm->mem_pool; - ret = njs_lvlhsh_insert(njs_object_hash(object), &pq.lhq); + ret = njs_lvlhsh_insert(njs_object_hash(value), &pq.lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NJS_ERROR; @@ -1138,7 +1138,7 @@ njs_value_property_set(njs_vm_t *vm, njs found: - prop->value = *value; + prop->value = *setval; return NJS_OK; } diff -r bfdf58ec9116 -r 1acb3acb1059 src/njs_value.h --- a/src/njs_value.h Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_value.h Sun Aug 04 11:17:48 2019 -0400 @@ -822,11 +822,11 @@ double njs_string_to_number(const njs_va njs_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2); njs_int_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_value_t *object, njs_value_t *property); + njs_value_t *value, njs_value_t *key); njs_int_t njs_value_property(njs_vm_t *vm, njs_value_t *value, - njs_value_t *property, njs_value_t *retval); -njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - njs_value_t *property, njs_value_t *value); + njs_value_t *key, njs_value_t *retval); +njs_int_t njs_value_property_set(njs_vm_t *vm, njs_value_t *value, + njs_value_t *key, njs_value_t *setval); njs_inline njs_int_t diff -r bfdf58ec9116 -r 1acb3acb1059 src/njs_vmcode.c --- a/src/njs_vmcode.c Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_vmcode.c Sun Aug 04 11:17:48 2019 -0400 @@ -24,11 +24,11 @@ static njs_jump_off_t njs_vmcode_object_ njs_value_t *invld); static njs_jump_off_t njs_vmcode_property_init(njs_vm_t *vm, - njs_value_t *object, njs_value_t *property, njs_value_t *retval); + njs_value_t *value, njs_value_t *key, njs_value_t *retval); static njs_jump_off_t njs_vmcode_property_in(njs_vm_t *vm, - njs_value_t *property, njs_value_t *object); + njs_value_t *value, njs_value_t *key); static njs_jump_off_t njs_vmcode_property_delete(njs_vm_t *vm, - njs_value_t *object, njs_value_t *property); + njs_value_t *value, njs_value_t *key); static njs_jump_off_t njs_vmcode_property_foreach(njs_vm_t *vm, njs_value_t *object, njs_value_t *invld, u_char *pc); static njs_jump_off_t njs_vmcode_property_next(njs_vm_t *vm, @@ -1077,27 +1077,27 @@ njs_vmcode_object_copy(njs_vm_t *vm, njs static njs_jump_off_t -njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *object, - njs_value_t *property, njs_value_t *init) +njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, + njs_value_t *init) { uint32_t index, size; njs_array_t *array; - njs_value_t *value, name; + njs_value_t *val, name; njs_object_t *obj; njs_jump_off_t ret; njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; - switch (object->type) { + switch (value->type) { case NJS_ARRAY: - index = njs_value_to_index(property); + index = njs_value_to_index(key); if (njs_slow_path(index == NJS_ARRAY_INVALID_INDEX)) { njs_internal_error(vm, "invalid index while property initialization"); return NJS_ERROR; } - array = object->data.u.array; + array = value->data.u.array; if (index >= array->length) { size = index - array->length; @@ -1107,11 +1107,11 @@ njs_vmcode_property_init(njs_vm_t *vm, n return ret; } - value = &array->start[array->length]; + val = &array->start[array->length]; while (size != 0) { - njs_set_invalid(value); - value++; + njs_set_invalid(val); + val++; size--; } @@ -1124,7 +1124,7 @@ njs_vmcode_property_init(njs_vm_t *vm, n break; case NJS_OBJECT: - ret = njs_value_to_string(vm, &name, property); + ret = njs_value_to_string(vm, &name, key); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1134,14 +1134,14 @@ njs_vmcode_property_init(njs_vm_t *vm, n lhq.proto = &njs_object_hash_proto; lhq.pool = vm->mem_pool; - obj = njs_object(object); + obj = njs_object(value); ret = njs_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); if (ret == NJS_OK) { prop = lhq.value; if (prop->type == NJS_PROPERTY_HANDLER) { - ret = prop->value.data.u.prop_handler(vm, object, init, + ret = prop->value.data.u.prop_handler(vm, value, init, &vm->retval); if (njs_slow_path(ret != NJS_OK)) { return ret; @@ -1170,7 +1170,7 @@ njs_vmcode_property_init(njs_vm_t *vm, n default: njs_internal_error(vm, "unexpected object type \"%s\" " "while property initialization", - njs_type_string(object->type)); + njs_type_string(value->type)); return NJS_ERROR; } @@ -1180,7 +1180,7 @@ njs_vmcode_property_init(njs_vm_t *vm, n static njs_jump_off_t -njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *object, njs_value_t *property) +njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key) { njs_jump_off_t ret; njs_object_prop_t *prop; @@ -1191,7 +1191,7 @@ njs_vmcode_property_in(njs_vm_t *vm, njs njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - ret = njs_property_query(vm, &pq, object, property); + ret = njs_property_query(vm, &pq, value, key); switch (ret) { @@ -1206,7 +1206,7 @@ njs_vmcode_property_in(njs_vm_t *vm, njs break; case NJS_DECLINED: - if (!njs_is_object(object) && !njs_is_external(object)) { + if (!njs_is_object(value) && !njs_is_external(value)) { njs_type_error(vm, "property in on a primitive value"); return NJS_ERROR; @@ -1227,8 +1227,7 @@ njs_vmcode_property_in(njs_vm_t *vm, njs static njs_jump_off_t -njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *object, - njs_value_t *property) +njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *value, njs_value_t *key) { njs_jump_off_t ret; njs_object_prop_t *prop, *whipeout; @@ -1236,7 +1235,7 @@ njs_vmcode_property_delete(njs_vm_t *vm, njs_property_query_init(&pq, NJS_PROPERTY_QUERY_DELETE, 1); - ret = njs_property_query(vm, &pq, object, property); + ret = njs_property_query(vm, &pq, value, key); switch (ret) { @@ -1245,7 +1244,7 @@ njs_vmcode_property_delete(njs_vm_t *vm, if (njs_slow_path(!prop->configurable)) { njs_type_error(vm, "Cannot delete property \"%V\" of %s", - &pq.lhq.key, njs_type_string(object->type)); + &pq.lhq.key, njs_type_string(value->type)); return NJS_ERROR; } @@ -1284,7 +1283,7 @@ njs_vmcode_property_delete(njs_vm_t *vm, goto done; case NJS_PROPERTY_HANDLER: - ret = prop->value.data.u.prop_handler(vm, object, NULL, NULL); + ret = prop->value.data.u.prop_handler(vm, value, NULL, NULL); if (njs_slow_path(ret != NJS_OK)) { return ret; } From xeioex at nginx.com Mon Aug 5 18:17:52 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 05 Aug 2019 18:17:52 +0000 Subject: [njs] Fixed "in" operator for values with accessor descriptors. Message-ID: details: https://hg.nginx.org/njs/rev/dda649936723 branches: changeset: 1108:dda649936723 user: Dmitry Volyntsev date: Mon Aug 05 21:17:27 2019 +0300 description: Fixed "in" operator for values with accessor descriptors. diffstat: src/njs_vmcode.c | 38 ++++++++++++++++---------------------- src/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 25 insertions(+), 22 deletions(-) diffs (84 lines): diff -r 439e2f67acf8 -r dda649936723 src/njs_vmcode.c --- a/src/njs_vmcode.c Mon Aug 05 19:02:17 2019 +0300 +++ b/src/njs_vmcode.c Mon Aug 05 21:17:27 2019 +0300 @@ -1182,45 +1182,39 @@ njs_vmcode_property_init(njs_vm_t *vm, n static njs_jump_off_t njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key) { - njs_jump_off_t ret; + njs_int_t ret; + njs_bool_t found; njs_object_prop_t *prop; - const njs_value_t *retval; njs_property_query_t pq; - retval = &njs_value_false; + found = 0; njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); ret = njs_property_query(vm, &pq, value, key); - - switch (ret) { - - case NJS_OK: - prop = pq.lhq.value; + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } - if (!njs_is_valid(&prop->value)) { - break; - } - - retval = &njs_value_true; - break; - - case NJS_DECLINED: + if (ret == NJS_DECLINED) { if (!njs_is_object(value) && !njs_is_external(value)) { njs_type_error(vm, "property in on a primitive value"); return NJS_ERROR; } - break; + } else { + prop = pq.lhq.value; - case NJS_ERROR: - default: - - return ret; + if (/* !njs_is_data_descriptor(prop) */ + prop->writable == NJS_ATTRIBUTE_UNSET + || njs_is_valid(&prop->value)) + { + found = 1; + } } - vm->retval = *retval; + njs_set_boolean(&vm->retval, found); return sizeof(njs_vmcode_3addr_t); } diff -r 439e2f67acf8 -r dda649936723 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Aug 05 19:02:17 2019 +0300 +++ b/src/test/njs_unit_test.c Mon Aug 05 21:17:27 2019 +0300 @@ -3309,6 +3309,15 @@ static njs_unit_test_t njs_test[] = { njs_str("'a' in {a:1}"), njs_str("true") }, + { njs_str("'1' in [0,,2]"), + njs_str("false") }, + + { njs_str("var o = {}; Object.defineProperty(o, 'a', {get:()=>und}); 'a' in o"), + njs_str("true") }, + + { njs_str("var o = {}; Object.defineProperty(o, 'a', {value:1}); ({toString(){return 'a'}}) in o"), + njs_str("true") }, + { njs_str("'a' in Object.create({a:1})"), njs_str("true") }, From careygister at outlook.com Tue Aug 6 00:50:42 2019 From: careygister at outlook.com (Carey Gister) Date: Tue, 6 Aug 2019 00:50:42 +0000 Subject: RTMP with multiple worker processes and rtmp_auto_push In-Reply-To: References: Message-ID: Hi Hucc, No, that did not work. Are you missing something from your patch? I implemented your patch, ran two workers and set rtmp_auto_push on. The results were actually worse: my server did not send data to my one connected test client. Carey Gister 415-310-5304 ________________________________ From: nginx-devel on behalf of ?? (hucc) Sent: Monday, August 5, 2019 04:46 To: nginx-devel Subject: Re: RTMP with multiple worker processes and rtmp_auto_push On Friday, July 26, 2019 11:08, Carey Gister wrote: >Hi, > >I hope someone can help illuminate some background information related to this >module. I understand that the rtmp_auto_push directive worked with multiple >workers through nginx 1.7.x and then something changed in the nginx internals >and it stopped working and was no longer supported for multiple workers. > >Can someone provide background on what changed that had this feature stop >working? My manager has tasked me with getting this feature to work, if possible. > >Thanks, > >Carey Gister >415-310-5304 The following patch may solve your problem. diff --git a/ngx_rtmp_auto_push_module.c b/ngx_rtmp_auto_push_module.c index 60c85d7..436b176 100644 --- a/ngx_rtmp_auto_push_module.c +++ b/ngx_rtmp_auto_push_module.c @@ -140,6 +140,8 @@ ngx_rtmp_auto_push_init_process(ngx_cycle_t *cycle) return NGX_OK; } + ngx_rtmp_auto_push_module.ctx_index = 0; + apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_rtmp_auto_push_module); if (apcf->auto_push == 0) { _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmailman.nginx.org%2Fmailman%2Flistinfo%2Fnginx-devel&data=02%7C01%7C%7C991bf848d945422f176608d7199a89da%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637006023836677306&sdata=iP7Iu6r0igRQ00L1P3X9fN%2FYU7YKPBaE61kQghGdDrs%3D&reserved=0 -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Aug 6 14:59:10 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Aug 2019 14:59:10 +0000 Subject: [njs] Cleanup of njs_property_query() usage. Message-ID: details: https://hg.nginx.org/njs/rev/9dab7c4514e3 branches: changeset: 1109:9dab7c4514e3 user: Dmitry Volyntsev date: Tue Aug 06 17:58:37 2019 +0300 description: Cleanup of njs_property_query() usage. diffstat: src/njs_object_prop.c | 6 +----- src/njs_value.c | 14 +++++++------- src/njs_value.h | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diffs (82 lines): diff -r dda649936723 -r 9dab7c4514e3 src/njs_object_prop.c --- a/src/njs_object_prop.c Mon Aug 05 21:17:27 2019 +0300 +++ b/src/njs_object_prop.c Tue Aug 06 17:58:37 2019 +0300 @@ -87,15 +87,11 @@ njs_object_prop_define(njs_vm_t *vm, njs njs_object_prop_t *prop, *prev; njs_property_query_t pq; - njs_string_get(name, &pq.lhq.key); - pq.lhq.key_hash = njs_djb_hash(pq.lhq.key.start, pq.lhq.key.length); - pq.lhq.proto = &njs_object_hash_proto; - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 1); ret = njs_property_query(vm, &pq, object, name); - if (ret != NJS_OK && ret != NJS_DECLINED) { + if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff -r dda649936723 -r 9dab7c4514e3 src/njs_value.c --- a/src/njs_value.c Mon Aug 05 21:17:27 2019 +0300 +++ b/src/njs_value.c Tue Aug 06 17:58:37 2019 +0300 @@ -560,10 +560,10 @@ njs_property_query(njs_vm_t *vm, njs_pro case NJS_UNDEFINED: case NJS_NULL: default: - ret = njs_primitive_value_to_string(vm, &pq->value, key); + ret = njs_primitive_value_to_string(vm, &pq->key, key); if (njs_fast_path(ret == NJS_OK)) { - njs_string_get(&pq->value, &pq->lhq.key); + njs_string_get(&pq->key, &pq->lhq.key); njs_type_error(vm, "cannot get property \"%V\" of undefined", &pq->lhq.key); return NJS_ERROR; @@ -574,11 +574,11 @@ njs_property_query(njs_vm_t *vm, njs_pro return NJS_ERROR; } - ret = njs_primitive_value_to_string(vm, &pq->value, key); + ret = njs_primitive_value_to_string(vm, &pq->key, key); if (njs_fast_path(ret == NJS_OK)) { - njs_string_get(&pq->value, &pq->lhq.key); + njs_string_get(&pq->key, &pq->lhq.key); pq->lhq.key_hash = njs_djb_hash(pq->lhq.key.start, pq->lhq.key.length); if (obj == NULL) { @@ -765,8 +765,8 @@ njs_string_property_query(njs_vm_t *vm, if (pq->query != NJS_PROPERTY_QUERY_GET) { /* pq->lhq.key is used by NJS_VMCODE_PROPERTY_SET for TypeError */ - njs_uint32_to_string(&pq->value, index); - njs_string_get(&pq->value, &pq->lhq.key); + njs_uint32_to_string(&pq->key, index); + njs_string_get(&pq->key, &pq->lhq.key); } return NJS_OK; @@ -1103,7 +1103,7 @@ njs_value_property_set(njs_vm_t *vm, njs return NJS_ERROR; } - prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_undefined, 1); + prop = njs_object_prop_alloc(vm, &pq.key, &njs_value_undefined, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } diff -r dda649936723 -r 9dab7c4514e3 src/njs_value.h --- a/src/njs_value.h Mon Aug 05 21:17:27 2019 +0300 +++ b/src/njs_value.h Tue Aug 06 17:58:37 2019 +0300 @@ -348,7 +348,7 @@ typedef struct { const njs_extern_t *ext_proto; uint32_t ext_index; - njs_value_t value; + njs_value_t key; njs_object_t *prototype; njs_object_prop_t *own_whiteout; uint8_t query; From xeioex at nginx.com Tue Aug 6 16:46:08 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Aug 2019 16:46:08 +0000 Subject: [njs] Simplified njs_property_query() API by eliminating pq->shared. Message-ID: details: https://hg.nginx.org/njs/rev/df385232d2af branches: changeset: 1110:df385232d2af user: Dmitry Volyntsev date: Tue Aug 06 18:46:50 2019 +0300 description: Simplified njs_property_query() API by eliminating pq->shared. Making copy of shared property in object's hash at the first access. It simplifies njs_property_query() API and speeds up next access to the property. diffstat: src/njs_builtin.c | 4 +- src/njs_function.c | 2 - src/njs_object.c | 8 ++-- src/njs_object.h | 1 - src/njs_object_prop.c | 92 +-------------------------------------------------- src/njs_value.c | 92 +++++++++++++++++++++++++++++++++++++++----------- src/njs_value.h | 2 - src/njs_vmcode.c | 43 ++++++----------------- 8 files changed, 90 insertions(+), 154 deletions(-) diffs (416 lines): diff -r 9dab7c4514e3 -r df385232d2af src/njs_builtin.c --- a/src/njs_builtin.c Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_builtin.c Tue Aug 06 18:46:50 2019 +0300 @@ -1172,7 +1172,7 @@ njs_process_object_argv(njs_vm_t *vm, nj lhq.value = prop; lhq.key_hash = NJS_ARGV_HASH; lhq.key = njs_str_value("argv"); - lhq.replace = 0; + lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; @@ -1270,7 +1270,7 @@ njs_process_object_env(njs_vm_t *vm, njs njs_set_object(&prop->value, env); - lhq.replace = 0; + lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; lhq.value = prop; diff -r 9dab7c4514e3 -r df385232d2af src/njs_function.c --- a/src/njs_function.c Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_function.c Tue Aug 06 18:46:50 2019 +0300 @@ -815,13 +815,11 @@ njs_function_property_prototype_create(n njs_function_t *function; prototype = njs_object_alloc(vm); - if (njs_slow_path(prototype == NULL)) { return NULL; } function = njs_function_value_copy(vm, value); - if (njs_slow_path(function == NULL)) { return NULL; } diff -r 9dab7c4514e3 -r df385232d2af src/njs_object.c --- a/src/njs_object.c Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_object.c Tue Aug 06 18:46:50 2019 +0300 @@ -1611,9 +1611,9 @@ njs_value_t * njs_property_prototype_create(njs_vm_t *vm, njs_lvlhsh_t *hash, njs_object_t *prototype) { - njs_int_t ret; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_object_prop_t *prop; + njs_lvlhsh_query_t lhq; static const njs_value_t proto_string = njs_string("prototype"); @@ -1629,7 +1629,7 @@ njs_property_prototype_create(njs_vm_t * lhq.value = prop; lhq.key_hash = NJS_PROTOTYPE_HASH; lhq.key = njs_str_value("prototype"); - lhq.replace = 0; + lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; diff -r 9dab7c4514e3 -r df385232d2af src/njs_object.h --- a/src/njs_object.h Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_object.h Tue Aug 06 18:46:50 2019 +0300 @@ -62,7 +62,6 @@ njs_int_t njs_object_prop_define(njs_vm_ njs_value_t *name, njs_value_t *value); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_value_t *value, njs_value_t *setval); -njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); const char *njs_prop_type_string(njs_object_prop_type_t type); extern const njs_object_init_t njs_object_constructor_init; diff -r 9dab7c4514e3 -r df385232d2af src/njs_object_prop.c --- a/src/njs_object_prop.c Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_object_prop.c Tue Aug 06 18:46:50 2019 +0300 @@ -156,14 +156,6 @@ njs_object_prop_define(njs_vm_t *vm, njs /* Updating existing prop. */ - if (njs_slow_path(pq.shared)) { - ret = njs_prop_private_copy(vm, &pq); - - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - prev = pq.lhq.value; switch (prev->type) { @@ -458,6 +450,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, prop = pq.lhq.value; switch (prop->type) { + case NJS_METHOD: case NJS_PROPERTY: break; @@ -471,19 +464,6 @@ njs_object_prop_descriptor(njs_vm_t *vm, break; - case NJS_METHOD: - if (pq.shared) { - ret = njs_prop_private_copy(vm, &pq); - - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - prop = pq.lhq.value; - } - - break; - default: njs_type_error(vm, "unexpected property type: %s", njs_prop_type_string(prop->type)); @@ -615,76 +595,6 @@ njs_object_prop_descriptor(njs_vm_t *vm, } -njs_int_t -njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) -{ - njs_int_t ret; - njs_function_t *function; - njs_object_prop_t *prop, *shared, *name; - njs_lvlhsh_query_t lhq; - - static const njs_value_t name_string = njs_string("name"); - - prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_object_prop_t)); - if (njs_slow_path(prop == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; - } - - shared = pq->lhq.value; - *prop = *shared; - - pq->lhq.replace = 0; - pq->lhq.value = prop; - pq->lhq.pool = vm->mem_pool; - - ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } - - if (!njs_is_function(&prop->value)) { - return NJS_OK; - } - - function = njs_function_value_copy(vm, &prop->value); - if (njs_slow_path(function == NULL)) { - return NJS_ERROR; - } - - if (function->ctor) { - function->object.shared_hash = vm->shared->function_instance_hash; - - } else { - function->object.shared_hash = vm->shared->arrow_instance_hash; - } - - name = njs_object_prop_alloc(vm, &name_string, &prop->name, 0); - if (njs_slow_path(name == NULL)) { - return NJS_ERROR; - } - - name->configurable = 1; - - lhq.key_hash = NJS_NAME_HASH; - lhq.key = njs_str_value("name"); - lhq.replace = 0; - lhq.value = name; - lhq.proto = &njs_object_hash_proto; - lhq.pool = vm->mem_pool; - - ret = njs_lvlhsh_insert(&function->object.hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } - - return NJS_OK; -} - - const char * njs_prop_type_string(njs_object_prop_type_t type) { diff -r 9dab7c4514e3 -r df385232d2af src/njs_value.c --- a/src/njs_value.c Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_value.c Tue Aug 06 18:46:50 2019 +0300 @@ -11,6 +11,7 @@ static njs_int_t njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_object_t *object, const njs_value_t *key); +static njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_array_t *array, uint32_t index); static njs_int_t njs_string_property_query(njs_vm_t *vm, @@ -659,9 +660,7 @@ njs_object_property_query(njs_vm_t *vm, ret = njs_lvlhsh_find(&proto->shared_hash, &pq->lhq); if (ret == NJS_OK) { - pq->shared = 1; - - return ret; + return njs_prop_private_copy(vm, pq); } } @@ -679,6 +678,76 @@ njs_object_property_query(njs_vm_t *vm, static njs_int_t +njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) +{ + njs_int_t ret; + njs_function_t *function; + njs_object_prop_t *prop, *shared, *name; + njs_lvlhsh_query_t lhq; + + static const njs_value_t name_string = njs_string("name"); + + prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), + sizeof(njs_object_prop_t)); + if (njs_slow_path(prop == NULL)) { + njs_memory_error(vm); + return NJS_ERROR; + } + + shared = pq->lhq.value; + *prop = *shared; + + pq->lhq.replace = 0; + pq->lhq.value = prop; + pq->lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + if (!njs_is_function(&prop->value)) { + return NJS_OK; + } + + function = njs_function_value_copy(vm, &prop->value); + if (njs_slow_path(function == NULL)) { + return NJS_ERROR; + } + + if (function->ctor) { + function->object.shared_hash = vm->shared->function_instance_hash; + + } else { + function->object.shared_hash = vm->shared->arrow_instance_hash; + } + + name = njs_object_prop_alloc(vm, &name_string, &prop->name, 0); + if (njs_slow_path(name == NULL)) { + return NJS_ERROR; + } + + name->configurable = 1; + + lhq.key_hash = NJS_NAME_HASH; + lhq.key = njs_str_value("name"); + lhq.replace = 0; + lhq.value = name; + lhq.proto = &njs_object_hash_proto; + lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(&function->object.hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + return NJS_OK; +} + + +static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_array_t *array, uint32_t index) { @@ -931,18 +1000,6 @@ njs_value_property(njs_vm_t *vm, njs_val switch (prop->type) { case NJS_METHOD: - if (pq.shared) { - ret = njs_prop_private_copy(vm, &pq); - - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - prop = pq.lhq.value; - } - - /* Fall through. */ - case NJS_PROPERTY: if (njs_is_data_descriptor(prop)) { *retval = prop->value; @@ -1052,11 +1109,6 @@ njs_value_property_set(njs_vm_t *vm, njs switch (prop->type) { case NJS_PROPERTY: case NJS_METHOD: - if (njs_slow_path(pq.shared)) { - shared = prop; - break; - } - goto found; case NJS_PROPERTY_REF: diff -r 9dab7c4514e3 -r df385232d2af src/njs_value.h --- a/src/njs_value.h Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_value.h Tue Aug 06 18:46:50 2019 +0300 @@ -352,7 +352,6 @@ typedef struct { njs_object_t *prototype; njs_object_prop_t *own_whiteout; uint8_t query; - uint8_t shared; uint8_t own; } njs_property_query_t; @@ -799,7 +798,6 @@ njs_set_object_value(njs_value_t *value, (pq)->lhq.value = NULL; \ (pq)->own_whiteout = NULL; \ (pq)->query = _query; \ - (pq)->shared = 0; \ (pq)->own = _own; \ } while (0) diff -r 9dab7c4514e3 -r df385232d2af src/njs_vmcode.c --- a/src/njs_vmcode.c Tue Aug 06 17:58:37 2019 +0300 +++ b/src/njs_vmcode.c Tue Aug 06 18:46:50 2019 +0300 @@ -1224,7 +1224,7 @@ static njs_jump_off_t njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *value, njs_value_t *key) { njs_jump_off_t ret; - njs_object_prop_t *prop, *whipeout; + njs_object_prop_t *prop; njs_property_query_t pq; njs_property_query_init(&pq, NJS_PROPERTY_QUERY_DELETE, 1); @@ -1242,32 +1242,19 @@ njs_vmcode_property_delete(njs_vm_t *vm, return NJS_ERROR; } - if (njs_slow_path(pq.shared)) { - whipeout = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_object_prop_t)); - if (njs_slow_path(whipeout == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; + switch (prop->type) { + case NJS_PROPERTY_HANDLER: + if (njs_is_external(value)) { + ret = prop->value.data.u.prop_handler(vm, value, NULL, NULL); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + goto done; } - njs_set_invalid(&whipeout->value); - whipeout->name = prop->name; - whipeout->type = NJS_WHITEOUT; - - pq.lhq.replace = 0; - pq.lhq.value = whipeout; - pq.lhq.pool = vm->mem_pool; + /* Fall through. */ - ret = njs_lvlhsh_insert(&pq.prototype->hash, &pq.lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } - - break; - } - - switch (prop->type) { case NJS_PROPERTY: case NJS_METHOD: break; @@ -1276,14 +1263,6 @@ njs_vmcode_property_delete(njs_vm_t *vm, njs_set_invalid(prop->value.data.u.value); goto done; - case NJS_PROPERTY_HANDLER: - ret = prop->value.data.u.prop_handler(vm, value, NULL, NULL); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - goto done; - default: njs_internal_error(vm, "unexpected property type \"%s\" " "while deleting", From xeioex at nginx.com Tue Aug 6 16:46:09 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Aug 2019 16:46:09 +0000 Subject: [njs] Eliminating redundant NJS_METHOD type. Message-ID: details: https://hg.nginx.org/njs/rev/30b1199acaaf branches: changeset: 1111:30b1199acaaf user: Dmitry Volyntsev date: Tue Aug 06 19:45:23 2019 +0300 description: Eliminating redundant NJS_METHOD type. Previously, NJS_METHOD was the same as NJS_PROPERTY with function value type. diffstat: src/njs_array.c | 52 ++++++++++++++-------------- src/njs_boolean.c | 4 +- src/njs_builtin.c | 4 +- src/njs_crypto.c | 16 ++++---- src/njs_date.c | 92 +++++++++++++++++++++++++------------------------- src/njs_error.c | 6 +- src/njs_fs.c | 12 +++--- src/njs_function.c | 6 +- src/njs_json.c | 4 +- src/njs_math.c | 70 +++++++++++++++++++------------------- src/njs_number.c | 16 ++++---- src/njs_object.c | 42 +++++++++++----------- src/njs_object_prop.c | 5 -- src/njs_regexp.c | 6 +- src/njs_string.c | 66 ++++++++++++++++++------------------ src/njs_value.c | 6 +-- src/njs_value.h | 1 - src/njs_vmcode.c | 1 - 18 files changed, 200 insertions(+), 209 deletions(-) diffs (truncated from 1906 to 1000 lines): diff -r df385232d2af -r 30b1199acaaf src/njs_array.c --- a/src/njs_array.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_array.c Tue Aug 06 19:45:23 2019 +0300 @@ -280,7 +280,7 @@ static const njs_object_prop_t njs_arra /* Array.isArray(). */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("isArray"), .value = njs_native_function(njs_array_is_array, 0), .writable = 1, @@ -290,7 +290,7 @@ static const njs_object_prop_t njs_arra /* ES6. */ /* Array.of(). */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("of"), .value = njs_native_function(njs_array_of, 0), .writable = 1, @@ -1975,7 +1975,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("slice"), .value = njs_native_function(njs_array_prototype_slice, NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), @@ -1984,7 +1984,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("push"), .value = njs_native_function(njs_array_prototype_push, 0), .writable = 1, @@ -1992,7 +1992,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("pop"), .value = njs_native_function(njs_array_prototype_pop, 0), .writable = 1, @@ -2000,7 +2000,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("unshift"), .value = njs_native_function(njs_array_prototype_unshift, 0), .writable = 1, @@ -2008,7 +2008,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("shift"), .value = njs_native_function(njs_array_prototype_shift, 0), .writable = 1, @@ -2016,7 +2016,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("splice"), .value = njs_native_function(njs_array_prototype_splice, NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), @@ -2025,7 +2025,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("reverse"), .value = njs_native_function(njs_array_prototype_reverse, NJS_OBJECT_ARG), @@ -2034,7 +2034,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_array_prototype_to_string, 0), .writable = 1, @@ -2042,7 +2042,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("join"), .value = njs_native_function(njs_array_prototype_join, NJS_OBJECT_ARG, NJS_STRING_ARG), @@ -2051,7 +2051,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("concat"), .value = njs_native_function(njs_array_prototype_concat, 0), .writable = 1, @@ -2059,7 +2059,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("indexOf"), .value = njs_native_function(njs_array_prototype_index_of, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), @@ -2068,7 +2068,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("lastIndexOf"), .value = njs_native_function(njs_array_prototype_last_index_of, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), @@ -2078,7 +2078,7 @@ static const njs_object_prop_t njs_arra /* ES7. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("includes"), .value = njs_native_function(njs_array_prototype_includes, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), @@ -2087,7 +2087,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("forEach"), .value = njs_native_function(njs_array_prototype_for_each, 0), .writable = 1, @@ -2095,7 +2095,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("some"), .value = njs_native_function(njs_array_prototype_some, 0), .writable = 1, @@ -2103,7 +2103,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("every"), .value = njs_native_function(njs_array_prototype_every, 0), .writable = 1, @@ -2112,7 +2112,7 @@ static const njs_object_prop_t njs_arra /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("fill"), .value = njs_native_function(njs_array_prototype_fill, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG, @@ -2122,7 +2122,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("filter"), .value = njs_native_function(njs_array_prototype_filter, 0), .writable = 1, @@ -2131,7 +2131,7 @@ static const njs_object_prop_t njs_arra /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("find"), .value = njs_native_function(njs_array_prototype_find, 0), .writable = 1, @@ -2140,7 +2140,7 @@ static const njs_object_prop_t njs_arra /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("findIndex"), .value = njs_native_function(njs_array_prototype_find_index, 0), .writable = 1, @@ -2148,7 +2148,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("map"), .value = njs_native_function(njs_array_prototype_map, 0), .writable = 1, @@ -2156,7 +2156,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("reduce"), .value = njs_native_function(njs_array_prototype_reduce, 0), .writable = 1, @@ -2164,7 +2164,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("reduceRight"), .value = njs_native_function(njs_array_prototype_reduce_right, 0), .writable = 1, @@ -2172,7 +2172,7 @@ static const njs_object_prop_t njs_arra }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("sort"), .value = njs_native_function(njs_array_prototype_sort, 0), .writable = 1, diff -r df385232d2af -r 30b1199acaaf src/njs_boolean.c --- a/src/njs_boolean.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_boolean.c Tue Aug 06 19:45:23 2019 +0300 @@ -143,7 +143,7 @@ static const njs_object_prop_t njs_bool }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("valueOf"), .value = njs_native_function(njs_boolean_prototype_value_of, 0), .writable = 1, @@ -151,7 +151,7 @@ static const njs_object_prop_t njs_bool }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_boolean_prototype_to_string, 0), .writable = 1, diff -r df385232d2af -r 30b1199acaaf src/njs_builtin.c --- a/src/njs_builtin.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_builtin.c Tue Aug 06 19:45:23 2019 +0300 @@ -964,7 +964,7 @@ njs_builtin_match(const njs_object_init_ for (i = 0; i < o->items; i++) { pr = &o->properties[i]; - if (pr->type != NJS_METHOD) { + if (pr->type != NJS_PROPERTY || !njs_is_function(&pr->value)) { continue; } @@ -1116,7 +1116,7 @@ static const njs_object_prop_t njs_njs_ }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("dump"), .value = njs_native_function(njs_dump_value, NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG), diff -r df385232d2af -r 30b1199acaaf src/njs_crypto.c --- a/src/njs_crypto.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_crypto.c Tue Aug 06 19:45:23 2019 +0300 @@ -321,7 +321,7 @@ static const njs_object_prop_t njs_hash }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_hash_prototype_to_string, 0), .writable = 1, @@ -329,7 +329,7 @@ static const njs_object_prop_t njs_hash }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("update"), .value = njs_native_function(njs_hash_prototype_update, NJS_OBJECT_ARG, NJS_SKIP_ARG), @@ -338,7 +338,7 @@ static const njs_object_prop_t njs_hash }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("digest"), .value = njs_native_function(njs_hash_prototype_digest, NJS_OBJECT_ARG, NJS_SKIP_ARG), @@ -583,7 +583,7 @@ static const njs_object_prop_t njs_hmac }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_hmac_prototype_to_string, 0), .writable = 1, @@ -591,7 +591,7 @@ static const njs_object_prop_t njs_hmac }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("update"), .value = njs_native_function(njs_hmac_prototype_update, NJS_OBJECT_ARG, NJS_SKIP_ARG), @@ -600,7 +600,7 @@ static const njs_object_prop_t njs_hmac }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("digest"), .value = njs_native_function(njs_hmac_prototype_digest, NJS_OBJECT_ARG, NJS_SKIP_ARG), @@ -648,7 +648,7 @@ static const njs_object_prop_t njs_cryp }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("createHash"), .value = njs_native_function(njs_crypto_create_hash, NJS_SKIP_ARG), @@ -657,7 +657,7 @@ static const njs_object_prop_t njs_cryp }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("createHmac"), .value = njs_native_function(njs_crypto_create_hmac, NJS_SKIP_ARG), diff -r df385232d2af -r 30b1199acaaf src/njs_date.c --- a/src/njs_date.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_date.c Tue Aug 06 19:45:23 2019 +0300 @@ -912,7 +912,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("UTC"), .value = njs_native_function(njs_date_utc, 0), .writable = 1, @@ -920,7 +920,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("now"), .value = njs_native_function(njs_date_now, 0), .writable = 1, @@ -928,7 +928,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("parse"), .value = njs_native_function(njs_date_parse, NJS_SKIP_ARG, NJS_STRING_ARG), @@ -1936,7 +1936,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("valueOf"), .value = njs_native_function(njs_date_prototype_value_of, NJS_DATE_ARG), .writable = 1, @@ -1944,7 +1944,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_date_prototype_to_string, NJS_DATE_ARG), @@ -1953,7 +1953,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toDateString"), .value = njs_native_function(njs_date_prototype_to_date_string, NJS_DATE_ARG), @@ -1962,7 +1962,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toTimeString"), .value = njs_native_function(njs_date_prototype_to_time_string, NJS_DATE_ARG), @@ -1971,7 +1971,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toLocaleString"), .value = njs_native_function(njs_date_prototype_to_string, NJS_DATE_ARG), @@ -1980,7 +1980,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("toLocaleDateString"), .value = njs_native_function(njs_date_prototype_to_date_string, NJS_DATE_ARG), @@ -1989,7 +1989,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("toLocaleTimeString"), .value = njs_native_function(njs_date_prototype_to_time_string, NJS_DATE_ARG), @@ -1998,7 +1998,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toUTCString"), .value = njs_native_function(njs_date_prototype_to_utc_string, NJS_DATE_ARG), @@ -2007,7 +2007,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toISOString"), .value = njs_native_function(njs_date_prototype_to_iso_string, NJS_DATE_ARG), @@ -2016,7 +2016,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getTime"), .value = njs_native_function(njs_date_prototype_value_of, NJS_DATE_ARG), .writable = 1, @@ -2024,7 +2024,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getFullYear"), .value = njs_native_function(njs_date_prototype_get_full_year, NJS_DATE_ARG), @@ -2033,7 +2033,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCFullYear"), .value = njs_native_function(njs_date_prototype_get_utc_full_year, NJS_DATE_ARG), @@ -2042,7 +2042,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getMonth"), .value = njs_native_function(njs_date_prototype_get_month, NJS_DATE_ARG), @@ -2051,7 +2051,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCMonth"), .value = njs_native_function(njs_date_prototype_get_utc_month, NJS_DATE_ARG), @@ -2060,7 +2060,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getDate"), .value = njs_native_function(njs_date_prototype_get_date, NJS_DATE_ARG), @@ -2069,7 +2069,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCDate"), .value = njs_native_function(njs_date_prototype_get_utc_date, NJS_DATE_ARG), @@ -2078,7 +2078,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getDay"), .value = njs_native_function(njs_date_prototype_get_day, NJS_DATE_ARG), .writable = 1, @@ -2086,7 +2086,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCDay"), .value = njs_native_function(njs_date_prototype_get_utc_day, NJS_DATE_ARG), @@ -2095,7 +2095,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getHours"), .value = njs_native_function(njs_date_prototype_get_hours, NJS_DATE_ARG), @@ -2104,7 +2104,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCHours"), .value = njs_native_function(njs_date_prototype_get_utc_hours, NJS_DATE_ARG), @@ -2113,7 +2113,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getMinutes"), .value = njs_native_function(njs_date_prototype_get_minutes, NJS_DATE_ARG), @@ -2122,7 +2122,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCMinutes"), .value = njs_native_function(njs_date_prototype_get_utc_minutes, NJS_DATE_ARG), @@ -2131,7 +2131,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getSeconds"), .value = njs_native_function(njs_date_prototype_get_seconds, NJS_DATE_ARG), @@ -2140,7 +2140,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("getUTCSeconds"), .value = njs_native_function(njs_date_prototype_get_seconds, NJS_DATE_ARG), @@ -2149,7 +2149,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("getMilliseconds"), .value = njs_native_function(njs_date_prototype_get_milliseconds, NJS_DATE_ARG), @@ -2158,7 +2158,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("getUTCMilliseconds"), .value = njs_native_function(njs_date_prototype_get_milliseconds, NJS_DATE_ARG), @@ -2167,7 +2167,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("getTimezoneOffset"), .value = njs_native_function(njs_date_prototype_get_timezone_offset, NJS_DATE_ARG), @@ -2176,7 +2176,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setTime"), .value = njs_native_function(njs_date_prototype_set_time, NJS_DATE_ARG, NJS_NUMBER_ARG), @@ -2185,7 +2185,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("setMilliseconds"), .value = njs_native_function(njs_date_prototype_set_milliseconds, NJS_DATE_ARG, NJS_NUMBER_ARG), @@ -2194,7 +2194,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_long_string("setUTCMilliseconds"), .value = njs_native_function(njs_date_prototype_set_milliseconds, NJS_DATE_ARG, NJS_NUMBER_ARG), @@ -2203,7 +2203,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setSeconds"), .value = njs_native_function(njs_date_prototype_set_seconds, NJS_DATE_ARG, NJS_NUMBER_ARG), @@ -2212,7 +2212,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setUTCSeconds"), .value = njs_native_function(njs_date_prototype_set_seconds, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), @@ -2221,7 +2221,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setMinutes"), .value = njs_native_function(njs_date_prototype_set_minutes, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, @@ -2231,7 +2231,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setUTCMinutes"), .value = njs_native_function(njs_date_prototype_set_utc_minutes, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, @@ -2241,7 +2241,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setHours"), .value = njs_native_function(njs_date_prototype_set_hours, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, @@ -2251,7 +2251,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setUTCHours"), .value = njs_native_function(njs_date_prototype_set_utc_hours, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, @@ -2261,7 +2261,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setDate"), .value = njs_native_function(njs_date_prototype_set_date, NJS_DATE_ARG, NJS_NUMBER_ARG), @@ -2270,7 +2270,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setUTCDate"), .value = njs_native_function(njs_date_prototype_set_utc_date, NJS_DATE_ARG, NJS_NUMBER_ARG), @@ -2279,7 +2279,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setMonth"), .value = njs_native_function(njs_date_prototype_set_month, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), @@ -2288,7 +2288,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setUTCMonth"), .value = njs_native_function(njs_date_prototype_set_utc_month, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), @@ -2297,7 +2297,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setFullYear"), .value = njs_native_function(njs_date_prototype_set_full_year, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, @@ -2307,7 +2307,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("setUTCFullYear"), .value = njs_native_function(njs_date_prototype_set_utc_full_year, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, @@ -2317,7 +2317,7 @@ static const njs_object_prop_t njs_date }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toJSON"), .value = njs_native_function(njs_date_prototype_to_json, 0), .writable = 1, diff -r df385232d2af -r 30b1199acaaf src/njs_error.c --- a/src/njs_error.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_error.c Tue Aug 06 19:45:23 2019 +0300 @@ -711,7 +711,7 @@ static const njs_object_prop_t njs_erro }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("valueOf"), .value = njs_native_function(njs_error_prototype_value_of, 0), .writable = 1, @@ -719,7 +719,7 @@ static const njs_object_prop_t njs_erro }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_error_prototype_to_string, 0), .writable = 1, @@ -793,7 +793,7 @@ static const njs_object_prop_t njs_inte }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("toString"), .value = njs_native_function(njs_internal_error_prototype_to_string, 0), .writable = 1, diff -r df385232d2af -r 30b1199acaaf src/njs_fs.c --- a/src/njs_fs.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_fs.c Tue Aug 06 19:45:23 2019 +0300 @@ -1017,7 +1017,7 @@ static const njs_object_prop_t njs_fs_o }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("readFile"), .value = njs_native_function(njs_fs_read_file, 0), .writable = 1, @@ -1025,7 +1025,7 @@ static const njs_object_prop_t njs_fs_o }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("readFileSync"), .value = njs_native_function(njs_fs_read_file_sync, 0), .writable = 1, @@ -1033,7 +1033,7 @@ static const njs_object_prop_t njs_fs_o }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("appendFile"), .value = njs_native_function(njs_fs_append_file, 0), .writable = 1, @@ -1041,7 +1041,7 @@ static const njs_object_prop_t njs_fs_o }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("appendFileSync"), .value = njs_native_function(njs_fs_append_file_sync, 0), .writable = 1, @@ -1049,7 +1049,7 @@ static const njs_object_prop_t njs_fs_o }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("writeFile"), .value = njs_native_function(njs_fs_write_file, 0), .writable = 1, @@ -1057,7 +1057,7 @@ static const njs_object_prop_t njs_fs_o }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("writeFileSync"), .value = njs_native_function(njs_fs_write_file_sync, 0), .writable = 1, diff -r df385232d2af -r 30b1199acaaf src/njs_function.c --- a/src/njs_function.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_function.c Tue Aug 06 19:45:23 2019 +0300 @@ -1152,7 +1152,7 @@ static const njs_object_prop_t njs_func }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("call"), .value = njs_native_function(njs_function_prototype_call, 0), .writable = 1, @@ -1160,7 +1160,7 @@ static const njs_object_prop_t njs_func }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("apply"), .value = njs_native_function(njs_function_prototype_apply, 0), .writable = 1, @@ -1168,7 +1168,7 @@ static const njs_object_prop_t njs_func }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("bind"), .value = njs_native_function(njs_function_prototype_bind, 0), .writable = 1, diff -r df385232d2af -r 30b1199acaaf src/njs_json.c --- a/src/njs_json.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_json.c Tue Aug 06 19:45:23 2019 +0300 @@ -2082,7 +2082,7 @@ static const njs_object_prop_t njs_json { /* JSON.parse(). */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("parse"), .value = njs_native_function(njs_json_parse, NJS_SKIP_ARG, NJS_STRING_ARG, @@ -2093,7 +2093,7 @@ static const njs_object_prop_t njs_json /* JSON.stringify(). */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("stringify"), .value = njs_native_function(njs_json_stringify, NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_SKIP_ARG, diff -r df385232d2af -r 30b1199acaaf src/njs_math.c --- a/src/njs_math.c Tue Aug 06 18:46:50 2019 +0300 +++ b/src/njs_math.c Tue Aug 06 19:45:23 2019 +0300 @@ -831,7 +831,7 @@ static const njs_object_prop_t njs_math }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("abs"), .value = njs_native_function(njs_object_math_abs, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -840,7 +840,7 @@ static const njs_object_prop_t njs_math }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("acos"), .value = njs_native_function(njs_object_math_acos, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -850,7 +850,7 @@ static const njs_object_prop_t njs_math /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("acosh"), .value = njs_native_function(njs_object_math_acosh, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -859,7 +859,7 @@ static const njs_object_prop_t njs_math }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("asin"), .value = njs_native_function(njs_object_math_asin, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -869,7 +869,7 @@ static const njs_object_prop_t njs_math /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("asinh"), .value = njs_native_function(njs_object_math_asinh, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -878,7 +878,7 @@ static const njs_object_prop_t njs_math }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("atan"), .value = njs_native_function(njs_object_math_atan, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -887,7 +887,7 @@ static const njs_object_prop_t njs_math }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("atan2"), .value = njs_native_function(njs_object_math_atan2, NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), @@ -897,7 +897,7 @@ static const njs_object_prop_t njs_math /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("atanh"), .value = njs_native_function(njs_object_math_atanh, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -907,7 +907,7 @@ static const njs_object_prop_t njs_math /* ES6. */ { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("cbrt"), .value = njs_native_function(njs_object_math_cbrt, NJS_SKIP_ARG, NJS_NUMBER_ARG), @@ -916,7 +916,7 @@ static const njs_object_prop_t njs_math }, { - .type = NJS_METHOD, + .type = NJS_PROPERTY, .name = njs_string("ceil"), From xeioex at nginx.com Wed Aug 7 12:37:23 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 07 Aug 2019 12:37:23 +0000 Subject: [njs] Removed dead code in njs_value_property_set() after df385232d2af. Message-ID: details: https://hg.nginx.org/njs/rev/90b8adf370d4 branches: changeset: 1112:90b8adf370d4 user: Dmitry Volyntsev date: Wed Aug 07 15:17:57 2019 +0300 description: Removed dead code in njs_value_property_set() after df385232d2af. Found by Coverity Scan (CID 1452240). diffstat: src/njs_value.c | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-) diffs (33 lines): diff -r 30b1199acaaf -r 90b8adf370d4 src/njs_value.c --- a/src/njs_value.c Tue Aug 06 19:45:23 2019 +0300 +++ b/src/njs_value.c Wed Aug 07 15:17:57 2019 +0300 @@ -1056,7 +1056,7 @@ njs_value_property_set(njs_vm_t *vm, njs njs_value_t *setval) { njs_int_t ret; - njs_object_prop_t *prop, *shared; + njs_object_prop_t *prop; njs_property_query_t pq; if (njs_is_primitive(value)) { @@ -1065,8 +1065,6 @@ njs_value_property_set(njs_vm_t *vm, njs return NJS_ERROR; } - shared = NULL; - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0); ret = njs_property_query(vm, &pq, value, key); @@ -1158,11 +1156,6 @@ njs_value_property_set(njs_vm_t *vm, njs return NJS_ERROR; } - if (njs_slow_path(shared != NULL)) { - prop->enumerable = shared->enumerable; - prop->configurable = shared->configurable; - } - pq.lhq.replace = 0; pq.lhq.value = prop; pq.lhq.pool = vm->mem_pool; From xeioex at nginx.com Wed Aug 7 15:06:47 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 07 Aug 2019 15:06:47 +0000 Subject: [njs] Fixed Object.defineProperty() for non-boolean descriptor props. Message-ID: details: https://hg.nginx.org/njs/rev/05fb6e4fdb36 branches: changeset: 1113:05fb6e4fdb36 user: Dmitry Volyntsev date: Wed Aug 07 17:23:47 2019 +0300 description: Fixed Object.defineProperty() for non-boolean descriptor props. diffstat: src/njs_object_prop.c | 6 +++--- src/test/njs_unit_test.c | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diffs (45 lines): diff -r 90b8adf370d4 -r 05fb6e4fdb36 src/njs_object_prop.c --- a/src/njs_object_prop.c Wed Aug 07 15:17:57 2019 +0300 +++ b/src/njs_object_prop.c Wed Aug 07 17:23:47 2019 +0300 @@ -378,7 +378,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { data = 1; - prop->writable = pr->value.data.truth; + prop->writable = njs_is_true(&pr->value); } pq.key = njs_str_value("enumerable"); @@ -386,7 +386,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { - prop->enumerable = pr->value.data.truth; + prop->enumerable = njs_is_true(&pr->value); } pq.key = njs_str_value("configurable"); @@ -394,7 +394,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { - prop->configurable = pr->value.data.truth; + prop->configurable = njs_is_true(&pr->value); } if (accessor && data) { diff -r 90b8adf370d4 -r 05fb6e4fdb36 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Aug 07 15:17:57 2019 +0300 +++ b/src/test/njs_unit_test.c Wed Aug 07 17:23:47 2019 +0300 @@ -9545,6 +9545,11 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = {}; Object.defineProperty(o, 'a', Object.create({value:1})); o.a"), njs_str("1") }, + { njs_str("var o = {}; Object.defineProperty(o, 'a', {writable:'x', enumerable:'y', configurable:'z'});" + "var d = Object.getOwnPropertyDescriptor(o, 'a');" + "d.writable && d.enumerable && d.configurable"), + njs_str("true") }, + { njs_str("var o = {a:1, c:2}; Object.defineProperty(o, 'b', {});" "Object.keys(o)"), njs_str("a,c") }, From xeioex at nginx.com Wed Aug 7 18:28:57 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 07 Aug 2019 18:28:57 +0000 Subject: [njs] Added property getter support for njs_object_property(). Message-ID: details: https://hg.nginx.org/njs/rev/b9d9f2813d9a branches: changeset: 1114:b9d9f2813d9a user: hongzhidao date: Tue Aug 06 22:54:13 2019 -0400 description: Added property getter support for njs_object_property(). diffstat: src/njs_array.c | 22 +++-- src/njs_date.c | 22 +++-- src/njs_error.c | 29 +++--- src/njs_json.c | 18 ++-- src/njs_object.h | 12 ++- src/njs_object_prop.c | 202 +++++++++++++++++++++++++++++----------------- src/njs_value.c | 33 +++--- src/test/njs_unit_test.c | 37 ++++++++ 8 files changed, 239 insertions(+), 136 deletions(-) diffs (600 lines): diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_array.c --- a/src/njs_array.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_array.c Tue Aug 06 22:54:13 2019 -0400 @@ -825,18 +825,22 @@ static njs_int_t njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_object_prop_t *prop; + njs_int_t ret; + njs_value_t value; njs_lvlhsh_query_t lhq; if (njs_is_object(&args[0])) { - lhq.key_hash = NJS_JOIN_HASH; - lhq.key = njs_str_value("join"); - - prop = njs_object_property(vm, njs_object(&args[0]), &lhq); - - if (njs_fast_path(prop != NULL && njs_is_function(&prop->value))) { - return njs_function_apply(vm, njs_function(&prop->value), args, - nargs, &vm->retval); + njs_object_property_init(&lhq, "join", NJS_JOIN_HASH); + + ret = njs_object_property(vm, &args[0], &lhq, &value); + + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (njs_is_function(&value)) { + return njs_function_apply(vm, njs_function(&value), args, nargs, + &vm->retval); } } diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_date.c --- a/src/njs_date.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_date.c Tue Aug 06 22:54:13 2019 -0400 @@ -1896,18 +1896,22 @@ static njs_int_t njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t retval) { - njs_object_prop_t *prop; + njs_int_t ret; + njs_value_t value; njs_lvlhsh_query_t lhq; if (njs_is_object(&args[0])) { - lhq.key_hash = NJS_TO_ISO_STRING_HASH; - lhq.key = njs_str_value("toISOString"); - - prop = njs_object_property(vm, njs_object(&args[0]), &lhq); - - if (njs_fast_path(prop != NULL && njs_is_function(&prop->value))) { - return njs_function_apply(vm, njs_function(&prop->value), args, - nargs, &vm->retval); + njs_object_property_init(&lhq, "toISOString", NJS_TO_ISO_STRING_HASH); + + ret = njs_object_property(vm, &args[0], &lhq, &value); + + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (njs_is_function(&value)) { + return njs_function_apply(vm, njs_function(&value), args, nargs, + &vm->retval); } } diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_error.c --- a/src/njs_error.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_error.c Tue Aug 06 22:54:13 2019 -0400 @@ -619,39 +619,36 @@ njs_error_to_string(njs_vm_t *vm, njs_va { size_t size; u_char *p; + njs_int_t ret; njs_str_t name, message; + njs_value_t value1, value2; const njs_value_t *name_value, *message_value; - njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; static const njs_value_t default_name = njs_string("Error"); - lhq.key_hash = NJS_NAME_HASH; - lhq.key = njs_str_value("name"); - lhq.proto = &njs_object_hash_proto; + njs_object_property_init(&lhq, "name", NJS_NAME_HASH); - prop = njs_object_property(vm, njs_object(error), &lhq); + ret = njs_object_property(vm, error, &lhq, &value1); - if (prop != NULL) { - name_value = &prop->value; + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } - } else { - name_value = &default_name; - } + name_value = (ret == NJS_OK) ? &value1 : &default_name; njs_string_get(name_value, &name); lhq.key_hash = NJS_MESSAGE_HASH; lhq.key = njs_str_value("message"); - prop = njs_object_property(vm, njs_object(error), &lhq); + ret = njs_object_property(vm, error, &lhq, &value2); - if (prop != NULL) { - message_value = &prop->value; + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } - } else { - message_value = &njs_string_empty; - } + message_value = (ret == NJS_OK) ? &value2 : &njs_string_empty; njs_string_get(message_value, &message); diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_json.c --- a/src/njs_json.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_json.c Tue Aug 06 22:54:13 2019 -0400 @@ -1497,19 +1497,19 @@ memory_error: static njs_function_t * njs_object_to_json_function(njs_vm_t *vm, njs_value_t *value) { - njs_object_prop_t *prop; + njs_int_t ret; + njs_value_t retval; njs_lvlhsh_query_t lhq; - lhq.key_hash = NJS_TO_JSON_HASH; - lhq.key = njs_str_value("toJSON"); - - prop = njs_object_property(vm, njs_object(value), &lhq); - - if (prop != NULL && njs_is_function(&prop->value)) { - return njs_function(&prop->value); + njs_object_property_init(&lhq, "toJSON", NJS_TO_JSON_HASH); + + ret = njs_object_property(vm, value, &lhq, &retval); + + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; } - return NULL; + return njs_is_function(&retval) ? njs_function(&retval) : NULL; } diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_object.h --- a/src/njs_object.h Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_object.h Tue Aug 06 22:54:13 2019 -0400 @@ -20,6 +20,14 @@ (!njs_is_data_descriptor(prop) && !njs_is_accessor_descriptor(prop)) +#define njs_object_property_init(lhq, _key, hash) \ + do { \ + (lhq)->proto = &njs_object_hash_proto; \ + (lhq)->key_hash = hash; \ + (lhq)->key = njs_str_value(_key); \ + } while (0) + + struct njs_object_init_s { njs_str_t name; const njs_object_prop_t *properties; @@ -56,8 +64,8 @@ njs_int_t njs_object_prototype_to_string njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, const njs_value_t *value, uint8_t attributes); -njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj, - njs_lvlhsh_query_t *lhq); +njs_int_t njs_object_property(njs_vm_t *vm, const njs_value_t *value, + njs_lvlhsh_query_t *lhq, njs_value_t *retval); njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, njs_value_t *name, njs_value_t *value); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_object_prop.c --- a/src/njs_object_prop.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_object_prop.c Tue Aug 06 22:54:13 2019 -0400 @@ -9,7 +9,7 @@ static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm, - const njs_value_t *name, const njs_object_t *descriptor); + const njs_value_t *name, const njs_value_t *desc); njs_object_prop_t * @@ -45,32 +45,53 @@ njs_object_prop_alloc(njs_vm_t *vm, cons } -njs_object_prop_t * -njs_object_property(njs_vm_t *vm, const njs_object_t *object, - njs_lvlhsh_query_t *lhq) +njs_int_t +njs_object_property(njs_vm_t *vm, const njs_value_t *value, + njs_lvlhsh_query_t *lhq, njs_value_t *retval) { - njs_int_t ret; + njs_int_t ret; + njs_object_t *object; + njs_object_prop_t *prop; - lhq->proto = &njs_object_hash_proto; + object = njs_object(value); do { ret = njs_lvlhsh_find(&object->hash, lhq); if (njs_fast_path(ret == NJS_OK)) { - return lhq->value; + goto found; } ret = njs_lvlhsh_find(&object->shared_hash, lhq); if (njs_fast_path(ret == NJS_OK)) { - return lhq->value; + goto found; } object = object->__proto__; } while (object != NULL); - return NULL; + *retval = njs_value_undefined; + + return NJS_DECLINED; + +found: + + prop = lhq->value; + + if (njs_is_data_descriptor(prop)) { + *retval = prop->value; + return NJS_OK; + } + + if (njs_is_undefined(&prop->getter)) { + *retval = njs_value_undefined; + return NJS_OK; + } + + return njs_function_apply(vm, njs_function(&prop->getter), value, + 1, retval); } @@ -95,7 +116,7 @@ njs_object_prop_define(njs_vm_t *vm, njs return ret; } - prop = njs_descriptor_prop(vm, name, njs_object(value)); + prop = njs_descriptor_prop(vm, name, value); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -313,12 +334,13 @@ exception: static njs_object_prop_t * njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, - const njs_object_t *desc) + const njs_value_t *desc) { + njs_int_t ret; njs_bool_t data, accessor; - njs_object_prop_t *prop, *pr; - const njs_value_t *setter, *getter; - njs_lvlhsh_query_t pq; + njs_value_t value; + njs_object_prop_t *prop; + njs_lvlhsh_query_t lhq; data = 0; accessor = 0; @@ -329,72 +351,103 @@ njs_descriptor_prop(njs_vm_t *vm, const return NULL; } - getter = &njs_value_invalid; - pq.key = njs_str_value("get"); - pq.key_hash = NJS_GET_HASH; + njs_object_property_init(&lhq, "get", NJS_GET_HASH); + + ret = njs_object_property(vm, desc, &lhq, &value); - pr = njs_object_property(vm, desc, &pq); - if (pr != NULL) { - if (njs_is_defined(&pr->value) && !njs_is_function(&pr->value)) { + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; + } + + if (ret == NJS_OK) { + if (njs_is_defined(&value) && !njs_is_function(&value)) { njs_type_error(vm, "Getter must be a function"); return NULL; } accessor = 1; - getter = &pr->value; + prop->getter = value; + + } else { + /* NJS_DECLINED */ + prop->getter = njs_value_invalid; } - prop->getter = *getter; + lhq.key = njs_str_value("set"); + lhq.key_hash = NJS_SET_HASH; + + ret = njs_object_property(vm, desc, &lhq, &value); - setter = &njs_value_invalid; - pq.key = njs_str_value("set"); - pq.key_hash = NJS_SET_HASH; + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; + } - pr = njs_object_property(vm, desc, &pq); - if (pr != NULL) { - if (njs_is_defined(&pr->value) && !njs_is_function(&pr->value)) { + if (ret == NJS_OK) { + if (njs_is_defined(&value) && !njs_is_function(&value)) { njs_type_error(vm, "Setter must be a function"); return NULL; } accessor = 1; - setter = &pr->value; + prop->setter = value; + + } else { + /* NJS_DECLINED */ + prop->setter = njs_value_invalid; } - prop->setter = *setter; + lhq.key = njs_str_value("value"); + lhq.key_hash = NJS_VALUE_HASH; - pq.key = njs_str_value("value"); - pq.key_hash = NJS_VALUE_HASH; + ret = njs_object_property(vm, desc, &lhq, &value); + + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; + } - pr = njs_object_property(vm, desc, &pq); - if (pr != NULL) { + if (ret == NJS_OK) { data = 1; - prop->value = pr->value; + prop->value = value; + } + + lhq.key = njs_str_value("writable"); + lhq.key_hash = NJS_WRITABABLE_HASH; + + ret = njs_object_property(vm, desc, &lhq, &value); + + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; } - pq.key = njs_str_value("writable"); - pq.key_hash = NJS_WRITABABLE_HASH; + if (ret == NJS_OK) { + data = 1; + prop->writable = njs_is_true(&value); + } - pr = njs_object_property(vm, desc, &pq); - if (pr != NULL) { - data = 1; - prop->writable = njs_is_true(&pr->value); + lhq.key = njs_str_value("enumerable"); + lhq.key_hash = NJS_ENUMERABLE_HASH; + + ret = njs_object_property(vm, desc, &lhq, &value); + + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; } - pq.key = njs_str_value("enumerable"); - pq.key_hash = NJS_ENUMERABLE_HASH; - - pr = njs_object_property(vm, desc, &pq); - if (pr != NULL) { - prop->enumerable = njs_is_true(&pr->value); + if (ret == NJS_OK) { + prop->enumerable = njs_is_true(&value); } - pq.key = njs_str_value("configurable"); - pq.key_hash = NJS_CONFIGURABLE_HASH; + lhq.key = njs_str_value("configurable"); + lhq.key_hash = NJS_CONFIGURABLE_HASH; + + ret = njs_object_property(vm, desc, &lhq, &value); - pr = njs_object_property(vm, desc, &pq); - if (pr != NULL) { - prop->configurable = njs_is_true(&pr->value); + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; + } + + if (ret == NJS_OK) { + prop->configurable = njs_is_true(&value); } if (accessor && data) { @@ -435,6 +488,29 @@ njs_object_prop_descriptor(njs_vm_t *vm, switch (ret) { case NJS_OK: + prop = pq.lhq.value; + + switch (prop->type) { + case NJS_PROPERTY: + break; + + case NJS_PROPERTY_HANDLER: + pq.scratch = *prop; + prop = &pq.scratch; + ret = prop->value.data.u.prop_handler(vm, value, NULL, + &prop->value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + break; + + default: + njs_type_error(vm, "unexpected property type: %s", + njs_prop_type_string(prop->type)); + return NJS_ERROR; + } + break; case NJS_DECLINED: @@ -446,28 +522,6 @@ njs_object_prop_descriptor(njs_vm_t *vm, return ret; } - prop = pq.lhq.value; - - switch (prop->type) { - case NJS_PROPERTY: - break; - - case NJS_PROPERTY_HANDLER: - pq.scratch = *prop; - prop = &pq.scratch; - ret = prop->value.data.u.prop_handler(vm, value, NULL, &prop->value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - break; - - default: - njs_type_error(vm, "unexpected property type: %s", - njs_prop_type_string(prop->type)); - return NJS_ERROR; - } - desc = njs_object_alloc(vm); if (njs_slow_path(desc == NULL)) { return NJS_ERROR; diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/njs_value.c --- a/src/njs_value.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/njs_value.c Tue Aug 06 22:54:13 2019 -0400 @@ -122,8 +122,7 @@ njs_value_to_primitive(njs_vm_t *vm, njs { njs_int_t ret; njs_uint_t tries; - njs_value_t retval; - njs_object_prop_t *prop; + njs_value_t method, retval; njs_lvlhsh_query_t lhq; static const uint32_t hashes[] = { @@ -144,6 +143,7 @@ njs_value_to_primitive(njs_vm_t *vm, njs } tries = 0; + lhq.proto = &njs_object_hash_proto; for ( ;; ) { ret = NJS_ERROR; @@ -154,28 +154,27 @@ njs_value_to_primitive(njs_vm_t *vm, njs lhq.key_hash = hashes[hint]; lhq.key = names[hint]; - prop = njs_object_property(vm, njs_object(value), &lhq); + ret = njs_object_property(vm, value, &lhq, &method); - if (prop == NULL || !njs_is_function(&prop->value)) { - /* Try the second method. */ - continue; + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; } - ret = njs_function_apply(vm, njs_function(&prop->value), value, 1, - &retval); + if (njs_is_function(&method)) { + ret = njs_function_apply(vm, njs_function(&method), value, 1, + &retval); - if (njs_fast_path(ret == NJS_OK)) { + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + if (njs_is_primitive(&retval)) { break; - } + } + } - /* Try the second method. */ - continue; - } - - /* NJS_ERROR */ - - return ret; + /* Try the second method. */ + continue; } njs_type_error(vm, "Cannot convert object to primitive value"); diff -r 05fb6e4fdb36 -r b9d9f2813d9a src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Aug 07 17:23:47 2019 +0300 +++ b/src/test/njs_unit_test.c Tue Aug 06 22:54:13 2019 -0400 @@ -9811,6 +9811,43 @@ static njs_unit_test_t njs_test[] = { njs_str("var arr = [0, 1]; Object.defineProperty(arr, 'length', {value:3}); arr.length"), njs_str("3") }, + { njs_str("Object.defineProperty(Array.prototype, 'toString', { get: function() {return () => 1}});" + "'a' + []"), + njs_str("a1") }, + + { njs_str("Object.defineProperty(Array.prototype, 'toJSON', { get: function() {return () => 1}});" + "JSON.stringify([])"), + njs_str("1") }, + + { njs_str("Object.defineProperty(Array.prototype, 'join', { get: function() {return () => 1}});" + "([]).toString()"), + njs_str("1") }, + + { njs_str("var o = {}, desc = {};" + "Object.defineProperty(desc, 'get', { get() { return () => 1 } });" + "Object.defineProperty(o, 'a', desc); o.a"), + njs_str("1") }, + + { njs_str("Object.defineProperty(Error.prototype, 'message', { get() {return 'm'}});" + "Object.defineProperty(Error.prototype, 'name', { get() {return 'n'}});" + "Error()"), + njs_str("n: m") }, + + { njs_str("var o = {}, desc = {};" + "Object.defineProperty(desc, 'value', { get() { return 'x'}});" + "Object.defineProperty(o, 'a', desc); o.a"), + njs_str("x") }, + + { njs_str("var o = {}, desc = {};" + "Object.defineProperty(desc, 'value', { get() { return 'x'}});" + "Object.defineProperty(desc, 'enumerable', { get() { return !NaN}});" + "Object.defineProperty(desc, 'writable', { get() { return 'x'}});" + "Object.defineProperty(desc, 'configurable', { get() { return 1}});" + "Object.defineProperty(o, 'a', desc);" + "var d = Object.getOwnPropertyDescriptor(o, 'a');" + "d.enumerable && d.writable && d.configurable"), + njs_str("true") }, + { njs_str("Object.defineProperties()"), njs_str("TypeError: cannot convert undefined argument to object") }, From xeioex at nginx.com Wed Aug 7 18:28:58 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 07 Aug 2019 18:28:58 +0000 Subject: [njs] Fixed Error.prototype.toString(). Message-ID: details: https://hg.nginx.org/njs/rev/e47f82b5f2ca branches: changeset: 1115:e47f82b5f2ca user: Dmitry Volyntsev date: Mon Aug 05 17:10:59 2019 +0300 description: Fixed Error.prototype.toString(). 1) with UTF8 string properties. 1) with non-string values for "name" and "message" properties. This closes #199 issue on Github. diffstat: src/njs_error.c | 50 +++++++++++++++++++++++++++++++++++------------ src/test/njs_unit_test.c | 27 ++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 14 deletions(-) diffs (137 lines): diff -r b9d9f2813d9a -r e47f82b5f2ca src/njs_error.c --- a/src/njs_error.c Tue Aug 06 22:54:13 2019 -0400 +++ b/src/njs_error.c Mon Aug 05 17:10:59 2019 +0300 @@ -617,12 +617,12 @@ njs_error_prototype_to_string(njs_vm_t * njs_int_t njs_error_to_string(njs_vm_t *vm, njs_value_t *retval, const njs_value_t *error) { - size_t size; + size_t length; u_char *p; njs_int_t ret; - njs_str_t name, message; njs_value_t value1, value2; - const njs_value_t *name_value, *message_value; + njs_value_t *name_value, *message_value; + njs_string_prop_t name, message; njs_lvlhsh_query_t lhq; static const njs_value_t default_name = njs_string("Error"); @@ -635,9 +635,18 @@ njs_error_to_string(njs_vm_t *vm, njs_va return ret; } - name_value = (ret == NJS_OK) ? &value1 : &default_name; + name_value = (ret == NJS_OK) ? &value1 : njs_value_arg(&default_name); - njs_string_get(name_value, &name); + if (njs_slow_path(!njs_is_string(name_value))) { + ret = njs_value_to_string(vm, &value1, name_value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + name_value = &value1; + } + + (void) njs_string_prop(&name, name_value); lhq.key_hash = NJS_MESSAGE_HASH; lhq.key = njs_str_value("message"); @@ -648,29 +657,44 @@ njs_error_to_string(njs_vm_t *vm, njs_va return ret; } - message_value = (ret == NJS_OK) ? &value2 : &njs_string_empty; + message_value = (ret == NJS_OK) ? &value2 + : njs_value_arg(&njs_string_empty); - njs_string_get(message_value, &message); + if (njs_slow_path(!njs_is_string(message_value))) { + ret = njs_value_to_string(vm, &value2, message_value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } - if (name.length == 0) { + message_value = &value2; + } + + (void) njs_string_prop(&message, message_value); + + if (name.size == 0) { *retval = *message_value; return NJS_OK; } - if (message.length == 0) { + if (message.size == 0) { *retval = *name_value; return NJS_OK; } - size = name.length + message.length + 2; + if (name.length != 0 && message.length != 0) { + length = name.length + message.length + 2; - p = njs_string_alloc(vm, retval, size, size); + } else { + length = 0; + } + + p = njs_string_alloc(vm, retval, name.size + message.size + 2, length); if (njs_fast_path(p != NULL)) { - p = njs_cpymem(p, name.start, name.length); + p = njs_cpymem(p, name.start, name.size); *p++ = ':'; *p++ = ' '; - memcpy(p, message.start, message.length); + memcpy(p, message.start, message.size); return NJS_OK; } diff -r b9d9f2813d9a -r e47f82b5f2ca src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 06 22:54:13 2019 -0400 +++ b/src/test/njs_unit_test.c Mon Aug 05 17:10:59 2019 +0300 @@ -7835,7 +7835,25 @@ static njs_unit_test_t njs_test[] = { njs_str("Error('e')"), njs_str("Error: e") }, - { njs_str("var e = Error('e'); e.name = 'E'; e"), + { njs_str("Error(123)"), + njs_str("Error: 123") }, + + { njs_str("Error({toString(){return 'e'}})"), + njs_str("Error: e") }, + + { njs_str("Error([1,'?'])"), + njs_str("Error: 1,?") }, + + { njs_str("var e = TypeError(Error('e')); e"), + njs_str("TypeError: Error: e") }, + + { njs_str("Error('?'.repeat(33)).toString().length"), + njs_str("40") }, + + { njs_str("var e = Error('e'); e.name = {toString(){return 'E'}}; e"), + njs_str("E: e") }, + + { njs_str("var e = Error('e'); Object.defineProperty(e, 'name', {get(){return 'E'}}); e"), njs_str("E: e") }, { njs_str("var e = Error('e'); e.name = ''; e"), @@ -7850,6 +7868,13 @@ static njs_unit_test_t njs_test[] = { njs_str("Error('e').name + ': ' + Error('e').message"), njs_str("Error: e") }, + { njs_str("Error(String.bytesFrom(Array(1).fill(0x9d))).toString().length"), + njs_str("8") }, + + { njs_str("var e = Error('?'); e.name = String.bytesFrom(Array(1).fill(0x9d)); " + "e.toString().length"), + njs_str("5") }, + { njs_str("Error(1)"), njs_str("Error: 1") }, From xeioex at nginx.com Thu Aug 8 11:20:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 08 Aug 2019 11:20:11 +0000 Subject: [njs] Fixed njs_is_accessor_descriptor(). Message-ID: details: https://hg.nginx.org/njs/rev/6caf4d7c0846 branches: changeset: 1116:6caf4d7c0846 user: Dmitry Volyntsev date: Thu Aug 08 14:19:54 2019 +0300 description: Fixed njs_is_accessor_descriptor(). diffstat: src/njs_object.h | 3 ++- src/njs_value.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletions(-) diffs (27 lines): diff -r e47f82b5f2ca -r 6caf4d7c0846 src/njs_object.h --- a/src/njs_object.h Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_object.h Thu Aug 08 14:19:54 2019 +0300 @@ -13,7 +13,8 @@ #define njs_is_accessor_descriptor(prop) \ - (njs_is_valid(&(prop)->getter) || njs_is_valid(&(prop)->setter)) + (njs_is_function_or_undefined(&(prop)->getter) \ + || njs_is_function_or_undefined(&(prop)->setter)) #define njs_is_generic_descriptor(prop) \ diff -r e47f82b5f2ca -r 6caf4d7c0846 src/njs_value.h --- a/src/njs_value.h Mon Aug 05 17:10:59 2019 +0300 +++ b/src/njs_value.h Thu Aug 08 14:19:54 2019 +0300 @@ -537,6 +537,10 @@ typedef struct { ((value)->type == NJS_FUNCTION) +#define njs_is_function_or_undefined(value) \ + ((value)->type == NJS_FUNCTION || (value)->type == NJS_UNDEFINED) + + #define njs_is_regexp(value) \ ((value)->type == NJS_REGEXP) From xeioex at nginx.com Thu Aug 8 11:20:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 08 Aug 2019 11:20:11 +0000 Subject: [njs] Added support for accessor property descriptors in njs.dump(). Message-ID: details: https://hg.nginx.org/njs/rev/fd09c657f97d branches: changeset: 1117:fd09c657f97d user: Dmitry Volyntsev date: Thu Aug 08 14:19:55 2019 +0300 description: Added support for accessor property descriptors in njs.dump(). diffstat: src/njs_json.c | 17 +++++++++++++++++ src/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 26 insertions(+), 0 deletions(-) diffs (53 lines): diff -r 6caf4d7c0846 -r fd09c657f97d src/njs_json.c --- a/src/njs_json.c Thu Aug 08 14:19:54 2019 +0300 +++ b/src/njs_json.c Thu Aug 08 14:19:55 2019 +0300 @@ -2381,6 +2381,10 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ njs_lvlhsh_query_t lhq; njs_json_stringify_t *stringify; + const njs_value_t string_get = njs_string("[Getter]"); + const njs_value_t string_set = njs_string("[Setter]"); + const njs_value_t string_get_set = njs_long_string("[Getter/Setter]"); + if (njs_vm_backtrace(vm) != NULL) { goto exception; } @@ -2486,6 +2490,19 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ if (prop->type == NJS_WHITEOUT || !prop->enumerable) { break; } + + if (njs_is_accessor_descriptor(prop)) { + if (njs_is_defined(&prop->getter)) { + if (njs_is_defined(&prop->setter)) { + val = njs_value_arg(&string_get_set); + } else { + val = njs_value_arg(&string_get); + } + + } else { + val = njs_value_arg(&string_set); + } + } } if (state->written) { diff -r 6caf4d7c0846 -r fd09c657f97d src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Aug 08 14:19:54 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Aug 08 14:19:55 2019 +0300 @@ -12893,6 +12893,15 @@ static njs_unit_test_t njs_test[] = { njs_str("njs.dump(Array.prototype.slice.call({'1':'b', length:2}))"), njs_str("[,'b']") }, + { njs_str("var o = Object.defineProperty({}, 'a', { get: () => 1, enumerable: true }); njs.dump(o)"), + njs_str("{a:'[Getter]'}") }, + + { njs_str("var o = Object.defineProperty({}, 'a', { get: () => 1, set(){}, enumerable: true }); njs.dump(o)"), + njs_str("{a:'[Getter/Setter]'}") }, + + { njs_str("var o = Object.defineProperty({}, 'a', { set(){}, enumerable: true }); njs.dump(o)"), + njs_str("{a:'[Setter]'}") }, + { njs_str("njs.dump($r.props)"), njs_str("{a:{type:\"property\",props:[\"getter\"]},b:{type:\"property\",props:[\"getter\"]}}") }, From xeioex at nginx.com Thu Aug 8 11:20:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 08 Aug 2019 11:20:11 +0000 Subject: [njs] Added support for accessor properties in JSON.stringify(). Message-ID: details: https://hg.nginx.org/njs/rev/239f3511397b branches: changeset: 1118:239f3511397b user: Dmitry Volyntsev date: Thu Aug 08 14:19:56 2019 +0300 description: Added support for accessor properties in JSON.stringify(). This closes #203 issue on Github. diffstat: src/njs_json.c | 27 ++++++++++++++++++++++----- src/test/njs_unit_test.c | 8 ++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diffs (62 lines): diff -r fd09c657f97d -r 239f3511397b src/njs_json.c --- a/src/njs_json.c Thu Aug 08 14:19:55 2019 +0300 +++ b/src/njs_json.c Thu Aug 08 14:19:56 2019 +0300 @@ -1214,7 +1214,7 @@ njs_json_stringify_iterator(njs_vm_t *vm njs_value_t *key, *value; njs_function_t *to_json; njs_json_state_t *state; - njs_object_prop_t *prop; + njs_object_prop_t *prop, scratch; njs_lvlhsh_query_t lhq; start: @@ -1255,10 +1255,27 @@ start: prop = lhq.value; - if (!prop->enumerable - || njs_is_undefined(&prop->value) - || !njs_is_valid(&prop->value) - || njs_is_function(&prop->value)) + if (!prop->enumerable) { + break; + } + + if (njs_is_accessor_descriptor(prop) + && njs_is_function(&prop->getter)) + { + scratch = *prop; + prop = &scratch; + + ret = njs_function_apply(vm, njs_function(&prop->getter), + &state->value, 1, &prop->value); + + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + if (njs_is_undefined(&prop->value) + || njs_is_function(&prop->value) + || !njs_is_valid(&prop->value)) { break; } diff -r fd09c657f97d -r 239f3511397b src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Aug 08 14:19:55 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Aug 08 14:19:56 2019 +0300 @@ -12766,6 +12766,14 @@ static njs_unit_test_t njs_test[] = { njs_str("JSON.stringify([{a:1,b:{c:2}},1], undefined, new Date())"), njs_str("[{\"a\":1,\"b\":{\"c\":2}},1]") }, + { njs_str("var o = Object.defineProperty({}, 'a', { get() { return ()=> 1}, enumerable: true });" + "JSON.stringify(o)"), + njs_str("{}") }, + + { njs_str("var o = Object.defineProperty({}, 'a', { get: () => ({b:1, c:2}), enumerable: true });" + "JSON.stringify(o)"), + njs_str("{\"a\":{\"b\":1,\"c\":2}}") }, + { njs_str("JSON.stringify({toJSON:function(k){}})"), njs_str("undefined") }, From balus at foxmail.com Sun Aug 11 09:48:55 2019 From: balus at foxmail.com (=?gb18030?B?SmlhbnlvbmcgQ2hlbg==?=) Date: Sun, 11 Aug 2019 17:48:55 +0800 Subject: [Patch] flv: add support for time offset Message-ID: Hi, I have been reading nginx source code recently and found that flv module is too simple, more specifically, it lacks support for time offset unlike mp4 module does. However, in real life, the demand for time offset is more common than it for byte offset, especially in CDN field. In addition to CDN, many video players use time offset to implement drag function. But the original module only supports byte offset, so I think it is necessary to add this feature and I have finished it. To support time offset, I had to parse the metadata, but I haven?t found an efficient and elegant solution, so I referred to the nginx-rtmp module in this part(Thanks, Roman Arutyunyan). As for byte offset, I just kept it consistent with the original module. I published the project in GitHub, and here is the address: https://github.com/BalusChen/nginx-flv-module, where you can find more detail. By the way, does anyone have interest in aligning keyframes for mp4 module? I'm willing to do this job. And Maxim Dounin, could you please give me some comments or suggestions? I'll appreciate it. Here is the patch: # HG changeset patch # User Jianyong Chen # Date 1565510616 -28800 # Sun Aug 11 16:03:36 2019 +0800 # Node ID 739f513ab47fa70c8691cf38a22b27767dd2939b # Parent fcd92ad76b7bb04b46c4b8fdfe14b6065acadf7d HTTP: add support for time offset. Add support for time offset to ngx_http_flv_module and keep consistent with the original module while handling byte offset. diff -r fcd92ad76b7b -r 739f513ab47f src/http/modules/ngx_http_flv_module.c --- a/src/http/modules/ngx_http_flv_module.c Thu Aug 01 13:50:07 2019 +0300 +++ b/src/http/modules/ngx_http_flv_module.c Sun Aug 11 16:03:36 2019 +0800 @@ -1,6 +1,7 @@ /* * Copyright (C) Igor Sysoev + * Copyright (C) Roman Arutyunyan * Copyright (C) Nginx, Inc. */ @@ -8,8 +9,243 @@ #include #include +#define NGX_FLV_HEADER_SIGVER 0x464c5601 + +#define NGX_FLV_HEADER_VIDEO 0x01 +#define NGX_FLV_HEADER_AUDIO 0x04 + +#define NGX_FLV_TAG_TYPE_AUDIO 0x08 +#define NGX_FLV_TAG_TYPE_VIDEO 0x09 +#define NGX_FLV_TAG_TYPE_META 0x12 +#define NGX_FLV_TAG_TYPE_MASK 0x1f + +#define NGX_FLV_PACKET_AVC 0x07 +#define NGX_FLV_PACKET_AAC 0x0a + +#define NGX_FLV_AUDIO_CODECID_MASK 0xf0 +#define NGX_FLV_VIDEO_CODECID_MASK 0x0f +#define NGX_FLV_VIDEO_FRAMETYPE_MASK 0xf0 + + +typedef struct { + u_char signature[3]; /* "FLV" */ + u_char version[1]; /* 0x01 [version 1] */ + u_char av_flags[1]; /* 0b00000 1[a] 0 1[v] */ + u_char length[4]; /* 0x00000009 */ + u_char tag_size[4]; /* 0x00000000 */ +} ngx_flv_header_t; + + +typedef struct { + u_char type[1]; /* 0b00 0[filter] 00000[type] */ + u_char size[3]; /* message length */ + u_char timestamp[3]; /* pts in milliseconds */ + u_char timestamp_ext[1]; /* upper 8 bits of timestamp */ + u_char stream_id[3]; /* 0x000000 */ + + /* Audio: 0b0000[codec_id] 00[rate] 0[size] 0[type] + * Video: 0b0000[type] 0000[codec_id] */ + u_char av_header[1]; + + /* Audio or Video: 0x00 is sequence_header */ + u_char av_type[1]; +} ngx_flv_tag_header_t; + + +#define NGX_FLV_HEADER_SIZE sizeof(ngx_flv_header_t) +#define NGX_FLV_PREV_TAG_SIZE 4 +#define NGX_FLV_TAG_HEADER_SIZE 11 +#define NGX_FLV_HEADER_LENGTH (NGX_FLV_HEADER_SIZE - NGX_FLV_PREV_TAG_SIZE) + +#define ngx_flv_get_tag_size(p) \ + ( ((uint32_t) ((u_char *) (p))[0] << 16) \ + + ( ((u_char *) (p))[1] << 8) \ + + ( ((u_char *) (p))[2]) ) + +#define ngx_flv_get_timestamp(p) \ + ( ((uint32_t) ((u_char *) (p))[3] << 24) \ + + ( ((u_char *) (p))[0] << 16) \ + + ( ((u_char *) (p))[1] << 8) \ + + ( ((u_char *) (p))[2]) ) + +#define ngx_flv_get_32value(p) \ + ( ((uint32_t) ((u_char *) (p))[0] << 24) \ + + ( ((u_char *) (p))[1] << 16) \ + + ( ((u_char *) (p))[2] << 8) \ + + ( ((u_char *) (p))[3]) ) + +#define ngx_flv_get_64value(p) \ + ( ((uint64_t) ((u_char *) (p))[0] << 56) \ + + ((uint64_t) ((u_char *) (p))[1] << 48) \ + + ((uint64_t) ((u_char *) (p))[2] << 40) \ + + ((uint64_t) ((u_char *) (p))[3] << 32) \ + + ((uint64_t) ((u_char *) (p))[4] << 24) \ + + ( ((u_char *) (p))[5] << 16) \ + + ( ((u_char *) (p))[6] << 8) \ + + ( ((u_char *) (p))[7]) ) + +#define ngx_flv_header_has_signature_version(p) \ + (ngx_flv_get_32value(p) == NGX_FLV_HEADER_SIGVER) + +#define ngx_flv_header_has_audio(p) \ + (((u_char *) (p))[0] & NGX_FLV_HEADER_AUDIO) + +#define ngx_flv_header_has_video(p) \ + (((u_char *) (p))[0] & NGX_FLV_HEADER_VIDEO) + +#define ngx_flv_tag_type(p) \ + (((u_char *) (p))[0] & NGX_FLV_TAG_TYPE_MASK) + +#define ngx_flv_tag_is_video(p) \ + (ngx_flv_tag_type(p) == NGX_FLV_TAG_TYPE_VIDEO) + +#define ngx_flv_tag_is_audio(p) \ + (ngx_flv_tag_type(p) == NGX_FLV_TAG_TYPE_AUDIO) + +#define ngx_flv_tag_is_meta(p) \ + (ngx_flv_tag_type(p) == NGX_FLV_TAG_TYPE_META) + +#define ngx_flv_is_sequence_header(p) (((u_char *) (p))[0] == 0x00) + +#define ngx_flv_codec_is_avc(p) \ + ((((u_char *) (p))[0] & NGX_FLV_VIDEO_CODECID_MASK) == NGX_FLV_PACKET_AVC) + +#define ngx_flv_video_frametype(p) \ + ((((u_char *) (p))[0] & NGX_FLV_VIDEO_FRAMETYPE_MASK) >> 4) + +#define ngx_flv_video_is_keyframe(p) (ngx_flv_video_frametype(p) == 0x01) + +#define ngx_flv_codec_is_aac(p) \ + (((((u_char *) (p))[0] & NGX_FLV_AUDIO_CODECID_MASK) >> 4) \ + == NGX_FLV_PACKET_AAC) + +/* basic types */ +#define NGX_FLV_AMF_NUMBER 0x00 +#define NGX_FLV_AMF_BOOLEAN 0x01 +#define NGX_FLV_AMF_STRING 0x02 +#define NGX_FLV_AMF_OBJECT 0x03 +#define NGX_FLV_AMF_NULL 0x05 +#define NGX_FLV_AMF_ARRAY_NULL 0x06 +#define NGX_FLV_AMF_MIXED_ARRAY 0x08 +#define NGX_FLV_AMF_END 0x09 +#define NGX_FLV_AMF_ARRAY 0x0a + +/* extended types */ +#define NGX_FLV_AMF_INT8 0x0100 +#define NGX_FLV_AMF_INT16 0x0101 +#define NGX_FLV_AMF_INT32 0x0102 +#define NGX_FLV_AMF_VARIANT_ 0x0103 + +/* r/w flags */ +#define NGX_FLV_AMF_OPTIONAL 0x1000 +#define NGX_FLV_AMF_TYPELESS 0x2000 +#define NGX_FLV_AMF_CONTEXT 0x4000 + + +static ngx_inline double +ngx_flv_get_amf_number(u_char *p) +{ + union { + uint64_t i; + double f; + } uint2double; + + uint2double.i = ngx_flv_get_64value(p); + + return uint2double.f; +} + + +typedef struct { + ngx_int_t type; + ngx_str_t name; + void *data; + size_t len; +} ngx_flv_amf_elt_t; + + +typedef struct { + size_t buffer_size; + size_t max_buffer_size; + ngx_flag_t time_offset; + ngx_flag_t with_metadata; +} ngx_http_flv_conf_t; + + +typedef struct { + ngx_file_t file; + ngx_http_request_t *request; + + u_char *buffer; + u_char *buffer_start; + u_char *buffer_pos; + u_char *buffer_end; + size_t buffer_size; + + off_t offset; + off_t file_end; + off_t sequence_end; + off_t necessary_len; + off_t start_offset; + off_t end_offset; + ngx_uint_t start; + ngx_uint_t end; + + unsigned has_audio:1; + unsigned has_video:1; + unsigned met_audio:1; + unsigned met_video:1; + unsigned aac_audio:1; + unsigned avc_video:1; + unsigned with_metadata:1; + + ngx_chain_t *necessary; + ngx_chain_t metadata; + ngx_chain_t audio_sequence_header; + ngx_chain_t video_sequence_header; + + ngx_buf_t metadata_buf; + ngx_buf_t audio_sequence_buf; + ngx_buf_t video_sequence_buf; + + u_char *filepositions; + u_char *times; + uint32_t filepositions_nelts; + uint32_t times_nelts; +} ngx_http_flv_file_t; + + +#define ngx_http_flv_tag_next(flv, n) \ + flv->buffer_pos += (size_t) n; \ + flv->offset += n + + +static ngx_int_t ngx_http_flv_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_flv_atofp(u_char *line, size_t n, size_t point); + +static ngx_int_t ngx_http_flv_process(ngx_http_flv_file_t *flv); +static ngx_int_t ngx_http_flv_read(ngx_http_flv_file_t *flv, size_t size); +static ngx_int_t ngx_http_flv_read_header(ngx_http_flv_file_t *flv); +static ngx_int_t ngx_http_flv_read_metadata(ngx_http_flv_file_t *flv); +static ngx_int_t ngx_http_flv_read_tags(ngx_http_flv_file_t *flv); +static ngx_int_t ngx_http_flv_parse_metadata(ngx_http_flv_file_t *flv); +static off_t ngx_http_flv_timestamp_to_offset(ngx_http_flv_file_t *flv, + ngx_uint_t timestamp, ngx_uint_t start); + +static void *ngx_flv_amf_reverse_copy(void *dst, void *src, size_t len); +static ngx_int_t ngx_flv_amf_is_compatible_type(uint8_t t1, uint8_t t2); +static ngx_int_t ngx_flv_amf_get(ngx_http_flv_file_t *flv, void *p, size_t n); +static ngx_int_t ngx_flv_amf_read(ngx_http_flv_file_t *flv, + ngx_flv_amf_elt_t *elts, size_t nelts); +static ngx_int_t ngx_flv_amf_read_object(ngx_http_flv_file_t *flv, + ngx_flv_amf_elt_t *elts, size_t nelts); +static ngx_int_t ngx_flv_amf_read_array(ngx_http_flv_file_t *flv, + ngx_flv_amf_elt_t *elts, size_t nelts); static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static void *ngx_http_flv_create_conf(ngx_conf_t *cf); +static char *ngx_http_flv_merge_conf(ngx_conf_t *cf, void *parent, void *child); + static ngx_command_t ngx_http_flv_commands[] = { @@ -20,13 +256,38 @@ 0, NULL }, + { ngx_string("flv_time_offset"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_flv_conf_t, time_offset), + NULL }, + + { ngx_string("flv_with_metadata"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_flv_conf_t, with_metadata), + NULL }, + + { ngx_string("flv_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_flv_conf_t, buffer_size), + NULL }, + + { ngx_string("flv_max_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_flv_conf_t, max_buffer_size), + NULL }, + ngx_null_command }; -static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0"; - - static ngx_http_module_t ngx_http_flv_module_ctx = { NULL, /* preconfiguration */ NULL, /* postconfiguration */ @@ -37,8 +298,8 @@ NULL, /* create server configuration */ NULL, /* merge server configuration */ - NULL, /* create location configuration */ - NULL /* merge location configuration */ + ngx_http_flv_create_conf, /* create location configuration */ + ngx_http_flv_merge_conf /* merge location configuration */ }; @@ -58,18 +319,23 @@ }; +static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0"; + + static ngx_int_t ngx_http_flv_handler(ngx_http_request_t *r) { + off_t start, end, len; u_char *last; - off_t start, len; size_t root; - ngx_int_t rc; - ngx_uint_t level, i; ngx_str_t path, value; ngx_log_t *log; ngx_buf_t *b; + ngx_int_t rc, time_start, time_end; + ngx_uint_t level, i, time_offset; ngx_chain_t out[2]; + ngx_http_flv_file_t *flv; + ngx_http_flv_conf_t *conf; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; @@ -167,24 +433,114 @@ r->root_tested = !r->error_page; + conf = ngx_http_get_module_loc_conf(r, ngx_http_flv_module); + time_offset = (ngx_uint_t) conf->time_offset; + time_start = -1; + time_end = 0; start = 0; + end = of.size; len = of.size; i = 1; + flv = NULL; if (r->args.len) { + if (ngx_http_arg(r, (u_char *) "time_offset", 11, &value) == NGX_OK) { + time_offset = 1; + } + if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { - start = ngx_atoof(value.data, value.len); + if (time_offset) { + time_start = ngx_http_flv_atofp(value.data, value.len, 3); + + } else { + start = ngx_atoof(value.data, value.len); + + if (start == NGX_ERROR || start >= len) { + start = 0; + } + + if (start) { + len = sizeof(ngx_flv_header) - 1 + len - start; + i = 0; + } + } + } + + /* + * To keep consistent with the original module, + * we just skip the 'end' argument while handling byte offset. + */ + + if (time_offset + && ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) + { + time_end = ngx_http_flv_atofp(value.data, value.len, 3); - if (start == NGX_ERROR || start >= len) { - start = 0; + if (time_end >= 0 && time_start < 0) { + time_start = 0; + } + } + } + + if (time_start >= 0) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, + "http flv time_offset time_start=%i time_end=%i", + time_start, time_end); + + if (time_end < time_start) { + + /* denotes the file end */ + + time_end = NGX_MAX_INT_T_VALUE; + } + + flv = ngx_pcalloc(r->pool, sizeof(ngx_http_flv_file_t)); + if (flv == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + flv->file.fd = of.fd; + flv->file.name = path; + flv->file.log = r->connection->log; + flv->file_end = of.size; + flv->buffer_size = conf->buffer_size; + flv->with_metadata = conf->with_metadata; + flv->start = time_start; + flv->end = time_end; + flv->request = r; + + switch (ngx_http_flv_process(flv)) { + + case NGX_DECLINED: + if (flv->buffer) { + ngx_pfree(r->pool, flv->buffer); } - if (start) { - len = sizeof(ngx_flv_header) - 1 + len - start; + ngx_pfree(r->pool, flv); + flv = NULL; + + break; + + case NGX_OK: + start = flv->start_offset; + end = flv->end_offset; + len = end - start; + if (start > 0) { + len += sizeof(ngx_flv_header) - 1 + flv->necessary_len; i = 0; } + + break; + + default: /* NGX_ERROR */ + if (flv->buffer) { + ngx_pfree(r->pool, flv->buffer); + } + + ngx_pfree(r->pool, flv); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; } } @@ -214,6 +570,14 @@ out[0].buf = b; out[0].next = &out[1]; + + if (flv && flv->necessary) { + out[0].next = flv->necessary; + while (flv->necessary->next) { + flv->necessary= flv->necessary->next; + } + flv->necessary->next = &out[1]; + } } @@ -236,7 +600,7 @@ } b->file_pos = start; - b->file_last = of.size; + b->file_last = end; b->in_file = b->file_last ? 1: 0; b->last_buf = (r == r->main) ? 1 : 0; @@ -254,6 +618,739 @@ } +static ngx_int_t +ngx_http_flv_atofp(u_char *line, size_t n, size_t point) +{ + ngx_int_t value, cutoff, cutlim; + ngx_uint_t dot; + + if (n == 0) { + return NGX_ERROR; + } + + cutoff = NGX_MAX_INT_T_VALUE / 10; + cutlim = NGX_MAX_INT_T_VALUE % 10; + + dot = 0; + + for (value = 0; n--; line++) { + + if (*line == '.') { + if (dot) { + return NGX_ERROR; + } + + dot = 1; + continue; + } + + if (*line < '0' || *line > '9') { + return NGX_ERROR; + } + + if (dot && point == 0) { + continue; + } + + if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) { + return NGX_ERROR; + } + + value = value * 10 + (*line - '0'); + point -= dot; + } + + while (point--) { + if (value > cutoff) { + return NGX_ERROR; + } + + value = value * 10; + } + + return value; +} + + +static ngx_int_t +ngx_http_flv_process(ngx_http_flv_file_t *flv) +{ + ngx_int_t rc; + ngx_chain_t **prev; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, + "flv start:%ui, end:%ui", flv->start, flv->end); + + rc = ngx_http_flv_read_header(flv); + if (rc != NGX_OK) { + return rc; + } + + rc = ngx_http_flv_read_metadata(flv); + if (rc != NGX_OK) { + return rc; + } + + rc = ngx_http_flv_read_tags(flv); + if (rc != NGX_OK) { + return rc; + } + + rc = ngx_http_flv_parse_metadata(flv); + if (rc != NGX_OK) { + return rc; + } + + flv->start_offset = ngx_http_flv_timestamp_to_offset(flv, flv->start, 1); + flv->end_offset = ngx_http_flv_timestamp_to_offset(flv, flv->end, 0); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, + "flv start_offset:%O end_offset:%O", + flv->start_offset, flv->end_offset); + + if (flv->end_offset <= flv->start_offset) { + return NGX_DECLINED; + } + + prev = &flv->necessary; + + if (flv->with_metadata && flv->metadata.buf) { + *prev = &flv->metadata; + prev = &flv->metadata.next; + flv->necessary_len += ngx_buf_size(flv->metadata.buf); + } + + if (flv->audio_sequence_header.buf) { + *prev = &flv->audio_sequence_header; + prev = &flv->audio_sequence_header.next; + flv->necessary_len += ngx_buf_size(flv->audio_sequence_header.buf); + } + + if (flv->video_sequence_header.buf) { + *prev = &flv->video_sequence_header; + flv->necessary_len += ngx_buf_size(flv->video_sequence_header.buf); + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_flv_read(ngx_http_flv_file_t *flv, size_t size) +{ + ssize_t n; + + if (flv->buffer_pos + size <= flv->buffer_end) { + return NGX_OK; + } + + if (flv->offset + (off_t) flv->buffer_size > flv->file_end) { + flv->buffer_size = (size_t) (flv->file_end - flv->offset); + } + + if (flv->buffer_size < size) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "\"%s\" flv file truncated", flv->file.name.data); + return NGX_ERROR; + } + + if (flv->buffer == NULL) { + flv->buffer = ngx_palloc(flv->request->pool, flv->buffer_size); + if (flv->buffer == NULL) { + return NGX_ERROR; + } + + flv->buffer_start = flv->buffer; + } + + n = ngx_read_file(&flv->file, flv->buffer_start, flv->buffer_size, + flv->offset); + + if (n == NGX_ERROR) { + return NGX_ERROR; + } + + if ((size_t) n != flv->buffer_size) { + ngx_log_error(NGX_LOG_CRIT, flv->file.log, 0, + ngx_read_file_n " read only %z of %z from \"%s\"", + n, flv->buffer_size, flv->file.name.data); + return NGX_ERROR; + } + + flv->buffer_pos = flv->buffer_start; + flv->buffer_end = flv->buffer_start + flv->buffer_size; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_flv_read_header(ngx_http_flv_file_t *flv) +{ + ngx_flv_header_t *hdr; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, "flv header"); + + if (ngx_http_flv_read(flv, NGX_FLV_HEADER_SIZE) != NGX_OK) { + return NGX_ERROR; + } + + if (!ngx_flv_header_has_signature_version(flv->buffer_pos)) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv wrong signature or version"); + return NGX_ERROR; + } + + hdr = (ngx_flv_header_t *) flv->buffer_pos; + + if (ngx_flv_get_32value(hdr->length) != NGX_FLV_HEADER_LENGTH) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv wrong header length"); + return NGX_ERROR; + } + + if (ngx_flv_get_32value(hdr->tag_size) != 0) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv wrong header prev_tag size"); + return NGX_ERROR; + } + + flv->has_video = ngx_flv_header_has_video(hdr->av_flags); + flv->has_audio = ngx_flv_header_has_audio(hdr->av_flags); + + ngx_http_flv_tag_next(flv, NGX_FLV_HEADER_SIZE); + + return NGX_OK; +} + + +/* + * Small excess buffer to process tags after metadata. + */ +#define NGX_HTTP_FLV_META_BUFFER_EXCESS (16 * 1024) + +static ngx_int_t +ngx_http_flv_read_metadata(ngx_http_flv_file_t *flv) +{ + uint32_t size; + ngx_buf_t *buf; + ngx_http_flv_conf_t *conf; + ngx_flv_tag_header_t *tag; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, "flv metadata tag"); + + if (ngx_http_flv_read(flv, NGX_FLV_HEADER_SIZE) != NGX_OK) { + return NGX_ERROR; + } + + tag = (ngx_flv_tag_header_t *) flv->buffer_pos; + size = NGX_FLV_TAG_HEADER_SIZE + ngx_flv_get_tag_size(tag->size) + + NGX_FLV_PREV_TAG_SIZE; + + if (!ngx_flv_tag_is_meta(tag->type)) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv first tag is not metadata"); + return NGX_DECLINED; + } + + if (size + NGX_HTTP_FLV_META_BUFFER_EXCESS > flv->buffer_size) { + conf = ngx_http_get_module_loc_conf(flv->request, ngx_http_flv_module); + + if (size > conf->max_buffer_size) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "\"%s\" flv metadata tag is too large:%D, " + "you may want to increase flv_max_buffer_size", + flv->file.name.data, size); + return NGX_ERROR; + } + + ngx_pfree(flv->request->pool, flv->buffer); + flv->buffer = NULL; + flv->buffer_pos = NULL; + flv->buffer_end = NULL; + + flv->buffer_size = (size_t) size + NGX_HTTP_FLV_META_BUFFER_EXCESS; + } + + if (ngx_http_flv_read(flv, (size_t) size) != NGX_OK) { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, + "flv metadata_len:%D", size); + + buf = &flv->metadata_buf; + buf->temporary = 1; + buf->pos = flv->buffer_pos; + buf->last = flv->buffer_pos + size; + buf->start = buf->pos; + buf->end = buf->last; + + flv->metadata.buf = buf; + + ngx_http_flv_tag_next(flv, size); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_flv_read_tags(ngx_http_flv_file_t *flv) +{ + uint32_t size; + ngx_buf_t *buf; + ngx_flv_tag_header_t *tag; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, "flv av tag"); + + while (flv->buffer_pos + NGX_FLV_HEADER_SIZE < flv->buffer_end) { + + if (ngx_http_flv_read(flv, NGX_FLV_HEADER_SIZE) != NGX_OK) { + return NGX_ERROR; + } + + tag = (ngx_flv_tag_header_t *) flv->buffer_pos; + size = NGX_FLV_TAG_HEADER_SIZE + ngx_flv_get_tag_size(tag->size) + + NGX_FLV_PREV_TAG_SIZE; + + if (flv->buffer_pos + size > flv->buffer_end) { + break; + } + + switch ngx_flv_tag_type(tag->type) { + + case NGX_FLV_TAG_TYPE_AUDIO: + if (flv->met_audio) { + break; + } + flv->met_audio = 1; + flv->aac_audio = ngx_flv_codec_is_aac(tag->av_header); + if (!flv->aac_audio) { + break; + } + if (!ngx_flv_is_sequence_header(tag->av_type)) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv first audio tag is not sequence header"); + return NGX_ERROR; + } + flv->sequence_end = flv->offset + size; + + buf = &flv->audio_sequence_buf; + buf->temporary = 1; + buf->pos = flv->buffer_pos; + buf->last = flv->buffer_pos + size; + + flv->audio_sequence_header.buf = buf; + break; + + case NGX_FLV_TAG_TYPE_VIDEO: + if (flv->met_video) { + break; + } + flv->met_video = 1; + flv->avc_video = ngx_flv_codec_is_avc(tag->av_header); + if (!flv->avc_video) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv does not support time offset, avc required"); + return NGX_DECLINED; + } + if (!ngx_flv_is_sequence_header(tag->av_type)) { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv first video tag is not sequence header"); + return NGX_ERROR; + } + flv->sequence_end = flv->offset + size; + + buf = &flv->video_sequence_buf; + buf->temporary = 1; + buf->pos = flv->buffer_pos; + buf->last = flv->buffer_pos + size; + + flv->video_sequence_header.buf = buf; + break; + + default: + break; + } + + if (flv->met_audio && flv->met_video) { + return NGX_OK; + } + + ngx_http_flv_tag_next(flv, size); + } + + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv no a/v tag found within %DB after metadata", + NGX_HTTP_FLV_META_BUFFER_EXCESS); + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_http_flv_parse_metadata(ngx_http_flv_file_t *flv) +{ + static u_char *filepositions_pos; + static u_char *times_pos; + + static ngx_flv_amf_elt_t in_keyframes[] = { + + { NGX_FLV_AMF_ARRAY | NGX_FLV_AMF_CONTEXT, + ngx_string("filepositions"), + &filepositions_pos, 0 }, + + { NGX_FLV_AMF_ARRAY | NGX_FLV_AMF_CONTEXT, + ngx_string("times"), + ×_pos, 0 } + }; + + static ngx_flv_amf_elt_t in_inf[] = { + + { NGX_FLV_AMF_OBJECT, + ngx_string("keyframes"), + in_keyframes, sizeof(in_keyframes) }, + }; + + static ngx_flv_amf_elt_t in_elts[] = { + + { NGX_FLV_AMF_STRING, + ngx_null_string, + NULL, 0 }, + + { NGX_FLV_AMF_OBJECT, + ngx_null_string, + in_inf, sizeof(in_inf) } + }; + + times_pos = NULL; + filepositions_pos = NULL; + flv->metadata.buf->pos += NGX_FLV_TAG_HEADER_SIZE; + + if (ngx_flv_amf_read(flv, in_elts, sizeof(in_elts) / sizeof(in_elts[0])) + != NGX_OK) + { + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv metadata has no necessary element like keyframes"); + return NGX_DECLINED; + } + + if (times_pos != NULL) { + flv->times_nelts = ngx_flv_get_32value(times_pos); + flv->times = times_pos + 4; + } + + if (filepositions_pos != NULL) { + flv->filepositions_nelts = ngx_flv_get_32value(filepositions_pos); + flv->filepositions = filepositions_pos + 4; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, flv->file.log, 0, "flv keyframes," + " times_nelts:%D filepositions_nelts:%D", + flv->times_nelts, flv->filepositions_nelts); + + if (!flv->times_nelts || flv->times_nelts != flv->filepositions_nelts) { + return NGX_DECLINED; + } + + flv->metadata.buf->pos = flv->metadata.buf->start; + + return NGX_OK; +} + + +static off_t +ngx_http_flv_timestamp_to_offset(ngx_http_flv_file_t *flv, ngx_uint_t timestamp, + ngx_uint_t start) +{ + off_t offset; + u_char *times, *filepositions; + ngx_int_t left, right, middle; + ngx_uint_t rv, first, last; + + times = flv->times; + right = flv->times_nelts - 1; + left = 0; + + first = (ngx_uint_t) (1000 * ngx_flv_get_amf_number(×[left*9 + 1])); + last = (ngx_uint_t) (1000 * ngx_flv_get_amf_number(×[right*9 + 1])); + + if (timestamp <= first || timestamp >= last) { + + if (start) { + return 0; + + } else { + return flv->file_end; + } + } + + rv = 0; + middle = 0; + + while (left <= right) { + middle = (left + right) / 2; + + rv = (ngx_uint_t) (1000 * ngx_flv_get_amf_number(×[middle*9 + 1])); + + if (rv > timestamp) { + right = middle - 1; + + } else if (rv < timestamp) { + left = middle + 1; + + } else { + break; + } + } + + if (middle > 0 && timestamp < rv) { + middle--; + } + + filepositions = flv->filepositions; + offset = (off_t) ngx_flv_get_amf_number(&filepositions[middle*9 + 1]); + + if (start && offset <= flv->sequence_end) { + return 0; + } + + return offset; +} + + +static ngx_inline void * +ngx_flv_amf_reverse_copy(void *dst, void *src, size_t len) +{ + size_t k; + + if (dst == NULL || src == NULL) { + return NULL; + } + + for (k = 0; k < len; ++k) { + ((u_char*)dst)[k] = ((u_char*)src)[len - 1 - k]; + } + + return dst; +} + + +static ngx_int_t +ngx_flv_amf_is_compatible_type(uint8_t t1, uint8_t t2) +{ + return t1 == t2 + || (t1 == NGX_FLV_AMF_OBJECT && t2 == NGX_FLV_AMF_MIXED_ARRAY) + || (t2 == NGX_FLV_AMF_OBJECT && t1 == NGX_FLV_AMF_MIXED_ARRAY); +} + + +static ngx_int_t +ngx_flv_amf_get(ngx_http_flv_file_t *flv, void *p, size_t n) +{ + u_char *data; + + if (flv->metadata.buf->pos + n > flv->metadata.buf->last) { + return NGX_ERROR; + } + + data = flv->metadata.buf->pos; + if (p != NULL) { + ngx_cpymem(p, data, n); + } + flv->metadata.buf->pos += n; + + return NGX_OK; +} + + +static ngx_int_t +ngx_flv_amf_read(ngx_http_flv_file_t *flv, ngx_flv_amf_elt_t *elts, + size_t nelts) +{ + void *data; + u_char buf[8]; + size_t n; + uint8_t type8; + uint16_t len; + uint32_t max_index; + ngx_uint_t type; + + for (n = 0; n < nelts; n++) { + + if (ngx_flv_amf_get(flv, &type8, 1) != NGX_OK) { + return NGX_ERROR; + } + + type = type8; + data = (elts && + ngx_flv_amf_is_compatible_type((uint8_t) (elts->type & 0xFF), + (uint8_t) type)) + ? elts->data + : NULL; + + if (elts && (elts->type & NGX_FLV_AMF_CONTEXT)) { + if (data) { + * ((u_char **) data) = flv->metadata.buf->pos; + } + data = NULL; + } + + switch (type) { + + case NGX_FLV_AMF_NUMBER: + if (ngx_flv_amf_get(flv, buf, 8) != NGX_OK) { + return NGX_ERROR; + } + + ngx_flv_amf_reverse_copy(data, buf, 8); + + break; + + case NGX_FLV_AMF_BOOLEAN: + if (ngx_flv_amf_get(flv, data, 1) != NGX_OK) { + return NGX_ERROR; + } + + break; + + case NGX_FLV_AMF_STRING: + if (ngx_flv_amf_get(flv, buf, 2) != NGX_OK) { + return NGX_ERROR; + } + ngx_flv_amf_reverse_copy(&len, buf, 2); + + if (ngx_flv_amf_get(flv, data, len) != NGX_OK) { + return NGX_ERROR; + } + + break; + + case NGX_FLV_AMF_MIXED_ARRAY: + if (ngx_flv_amf_get(flv, &max_index, 4) != NGX_OK) { + return NGX_ERROR; + } + /* fall through */ + + case NGX_FLV_AMF_OBJECT: + if (ngx_flv_amf_read_object(flv, data, + data && elts ? elts->len / sizeof(elts[0]) : 0 + ) != NGX_OK) + { + return NGX_ERROR; + } + + break; + + case NGX_FLV_AMF_ARRAY: + if (ngx_flv_amf_read_array(flv, data, + data && elts ? elts->len / sizeof(elts[0]) : 0 + ) != NGX_OK) + { + return NGX_ERROR; + } + + break; + + default: + ngx_log_error(NGX_LOG_ERR, flv->file.log, 0, + "flv unknown amf type %d in \"%s\"", + type, flv->file.name.data); + return NGX_ERROR; + } + + if (elts) { + elts++; + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_flv_amf_read_object(ngx_http_flv_file_t *flv, ngx_flv_amf_elt_t *elts, + size_t nelts) +{ + u_char buf[2]; + size_t n, namelen, maxlen; + uint8_t type; + uint16_t len; + + maxlen = 0; + for (n = 0; n < nelts; ++n) { + namelen = elts[n].name.len; + if (namelen > maxlen) { + maxlen = namelen; + } + } + + for ( ;; ) { + +#if !(NGX_WIN32) + char name[maxlen]; +#else + char name[1024]; + if (maxlen > sizeof(name)) { + return NGX_ERROR; + } +#endif + + if (ngx_flv_amf_get(flv, buf, 2) != NGX_OK) { + return NGX_ERROR; + } + ngx_flv_amf_reverse_copy(&len, buf, 2); + + if (len == 0) { + break; + } + + if (ngx_flv_amf_get(flv, name, len) != NGX_OK) { + return NGX_ERROR; + } + + for (n = 0; n < nelts + && (len != elts[n].name.len + || ngx_strncmp(name, elts[n].name.data, len) != 0); + ++n); + + if (ngx_flv_amf_read(flv, n < nelts ? &elts[n] : NULL, 1) != NGX_OK) { + return NGX_ERROR; + } + } + + if (ngx_flv_amf_get(flv, &type, 1) != NGX_OK || type != NGX_FLV_AMF_END) { + return NGX_ERROR; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_flv_amf_read_array(ngx_http_flv_file_t *flv, ngx_flv_amf_elt_t *elts, + size_t nelts) +{ + u_char buf[4]; + size_t n; + uint32_t len; + + if (ngx_flv_amf_get(flv, buf, 4) != NGX_OK) { + return NGX_ERROR; + } + + ngx_flv_amf_reverse_copy(&len, buf, 4); + + for (n = 0; n < len; ++n) { + if (ngx_flv_amf_read(flv, n < nelts ? &elts[n] : NULL, 1) != NGX_OK) { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + static char * ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -264,3 +1361,38 @@ return NGX_CONF_OK; } + + +static void * +ngx_http_flv_create_conf(ngx_conf_t *cf) +{ + ngx_http_flv_conf_t *conf; + + conf = ngx_palloc(cf->pool, sizeof(ngx_http_flv_conf_t)); + if (conf == NULL) { + return NULL; + } + + conf->buffer_size = NGX_CONF_UNSET_SIZE; + conf->max_buffer_size = NGX_CONF_UNSET_SIZE; + conf->time_offset = NGX_CONF_UNSET; + conf->with_metadata = NGX_CONF_UNSET; + + return conf; +} + + +static char * +ngx_http_flv_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_flv_conf_t *prev = parent; + ngx_http_flv_conf_t *conf = child; + + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024); + ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size, + 2 * 1024 * 1024); + ngx_conf_merge_value(conf->time_offset, prev->time_offset, 0); + ngx_conf_merge_value(conf->with_metadata, prev->with_metadata, 0); + + return NGX_CONF_OK; +} From winshining at 163.com Mon Aug 12 11:06:15 2019 From: winshining at 163.com (winshining) Date: Mon, 12 Aug 2019 19:06:15 +0800 (CST) Subject: [Patch] flv: add support for time offset In-Reply-To: References: Message-ID: <144aebff.12a0e.16c8581d94c.Coremail.winshining@163.com> Hi, balus I think the second parameter of ngx_http_flv_read in ngx_http_flv_read_metadata and ngx_http_flv_read_tags is incorrect, it should be NGX_FLV_TAG_HEADER_SIZE. Besides, 'keyframes' is a non-standard object in metadata, there is no description about it in official tech document, you can refer to https://www.adobe.com/devnet/f4v.html for details. Therefore, if a FLV file without the 'keyframes' object in metadata is played, the member 'times' of structure ngx_http_flv_file_t will be NULL, ngx_http_flv_timestamp_to_offset will crash then. -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Aug 12 11:33:08 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 12 Aug 2019 14:33:08 +0300 Subject: [Patch] flv: add support for time offset In-Reply-To: References: Message-ID: <20190812113308.GE1877@mdounin.ru> Hello! On Sun, Aug 11, 2019 at 05:48:55PM +0800, Jianyong Chen wrote: > I have been reading nginx source code recently and found that flv module is too > simple, more specifically, it lacks support for time offset unlike mp4 module does. > > However, in real life, the demand for time offset is more common than it for > byte offset, especially in CDN field. In addition to CDN, many video players use > time offset to implement drag function. But the original module only supports > byte offset, so I think it is necessary to add this feature and I have finished it. > > To support time offset, I had to parse the metadata, but I haven?t found an > efficient and elegant solution, so I referred to the nginx-rtmp module in this > part(Thanks, Roman Arutyunyan). As for byte offset, I just kept it consistent > with the original module. > > I published the project in GitHub, and here is the address: > https://github.com/BalusChen/nginx-flv-module, where you can find more detail. > > By the way, does anyone have interest in aligning keyframes for mp4 module? > I'm willing to do this job. > > And Maxim Dounin, could you please give me some comments or suggestions? > I'll appreciate it. One of the main benefits of the FLV format is that it doesn't require parsing on the server side, and all known FLV players are able to provide byte offsets. Trying to add time offsets does not look like an improvement to me - parsing complex formats is not something a web server should do. Note well that the fact that MP4 cannot work with byte offsets and instead requires time offsets is not a feature of the MP4 module, but rather a limitation of the format and players available. Fortunately, modern brosers are able to use range requests with MP4 files, potentially making the MP4 module unneeded in the future. [...] -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Mon Aug 12 13:13:07 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 12 Aug 2019 13:13:07 +0000 Subject: [njs] Fixed njs_vmcode_property_init(). Message-ID: details: https://hg.nginx.org/njs/rev/e22663f2defe branches: changeset: 1119:e22663f2defe user: Dmitry Volyntsev date: Mon Aug 12 14:54:46 2019 +0300 description: Fixed njs_vmcode_property_init(). Function assumed obj->__proto__ is never NULL, whereas it can become NULL after __proto__: null assignment. diffstat: src/njs_vmcode.c | 23 +++++++++++++---------- src/test/njs_unit_test.c | 6 ++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diffs (51 lines): diff -r 239f3511397b -r e22663f2defe src/njs_vmcode.c --- a/src/njs_vmcode.c Thu Aug 08 14:19:56 2019 +0300 +++ b/src/njs_vmcode.c Mon Aug 12 14:54:46 2019 +0300 @@ -1136,18 +1136,21 @@ njs_vmcode_property_init(njs_vm_t *vm, n obj = njs_object(value); - ret = njs_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); - if (ret == NJS_OK) { - prop = lhq.value; + if (obj->__proto__ != NULL) { + /* obj->__proto__ can be NULL after __proto__: null assignment */ + ret = njs_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); + if (ret == NJS_OK) { + prop = lhq.value; - if (prop->type == NJS_PROPERTY_HANDLER) { - ret = prop->value.data.u.prop_handler(vm, value, init, - &vm->retval); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + if (prop->type == NJS_PROPERTY_HANDLER) { + ret = prop->value.data.u.prop_handler(vm, value, init, + &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + break; } - - break; } } diff -r 239f3511397b -r e22663f2defe src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Aug 08 14:19:56 2019 +0300 +++ b/src/test/njs_unit_test.c Mon Aug 12 14:54:46 2019 +0300 @@ -8776,6 +8776,12 @@ static njs_unit_test_t njs_test[] = { njs_str("({}).__proto__ = null"), njs_str("null") }, + { njs_str("({__proto__:null}).__proto__"), + njs_str("undefined") }, + + { njs_str("({__proto__:null, a:1}).a"), + njs_str("1") }, + { njs_str("({__proto__: []}) instanceof Array"), njs_str("true") }, From xeioex at nginx.com Mon Aug 12 13:13:08 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 12 Aug 2019 13:13:08 +0000 Subject: [njs] Added getter/setter literal support. Message-ID: details: https://hg.nginx.org/njs/rev/33c4966abdda branches: changeset: 1120:33c4966abdda user: hongzhidao date: Thu Aug 08 03:52:18 2019 -0400 description: Added getter/setter literal support. This closes #118 issue on Github. diffstat: src/njs_disassembler.c | 31 ++++- src/njs_generator.c | 49 ++++++++ src/njs_lexer.h | 2 + src/njs_lexer_keyword.c | 2 + src/njs_object.c | 6 +- src/njs_object.h | 9 +- src/njs_object_prop.c | 66 +++++++---- src/njs_parser_terminal.c | 257 +++++++++++++++++++++++++++++++++------------ src/njs_vmcode.c | 29 ++++- src/njs_vmcode.h | 10 + src/test/njs_unit_test.c | 55 +++++++++ 11 files changed, 411 insertions(+), 105 deletions(-) diffs (885 lines): diff -r e22663f2defe -r 33c4966abdda src/njs_disassembler.c --- a/src/njs_disassembler.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_disassembler.c Thu Aug 08 03:52:18 2019 -0400 @@ -36,15 +36,15 @@ static njs_code_name_t code_names[] = { njs_str("OBJECT COPY ") }, { NJS_VMCODE_PROPERTY_GET, sizeof(njs_vmcode_prop_get_t), - njs_str("PROPERTY GET ") }, + njs_str("PROP GET ") }, { NJS_VMCODE_PROPERTY_INIT, sizeof(njs_vmcode_prop_set_t), - njs_str("PROPERTY INIT ") }, + njs_str("PROP INIT ") }, { NJS_VMCODE_PROPERTY_SET, sizeof(njs_vmcode_prop_set_t), - njs_str("PROPERTY SET ") }, + njs_str("PROP SET ") }, { NJS_VMCODE_PROPERTY_IN, sizeof(njs_vmcode_3addr_t), - njs_str("PROPERTY IN ") }, + njs_str("PROP IN ") }, { NJS_VMCODE_PROPERTY_DELETE, sizeof(njs_vmcode_3addr_t), - njs_str("PROPERTY DELETE ") }, + njs_str("PROP DELETE ") }, { NJS_VMCODE_INSTANCE_OF, sizeof(njs_vmcode_instance_of_t), njs_str("INSTANCE OF ") }, @@ -178,6 +178,7 @@ njs_disassemble(u_char *start, u_char *e njs_vmcode_equal_jump_t *equal; njs_vmcode_prop_foreach_t *prop_foreach; njs_vmcode_method_frame_t *method; + njs_vmcode_prop_accessor_t *prop_accessor; njs_vmcode_try_trampoline_t *try_tramp; njs_vmcode_function_frame_t *function; @@ -305,7 +306,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_PROPERTY_FOREACH) { prop_foreach = (njs_vmcode_prop_foreach_t *) p; - njs_printf("%05uz PROPERTY FOREACH %04Xz %04Xz +%uz\n", + njs_printf("%05uz PROP FOREACH %04Xz %04Xz +%uz\n", p - start, (size_t) prop_foreach->next, (size_t) prop_foreach->object, (size_t) prop_foreach->offset); @@ -317,7 +318,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_PROPERTY_NEXT) { prop_next = (njs_vmcode_prop_next_t *) p; - njs_printf("%05uz PROPERTY NEXT %04Xz %04Xz %04Xz %uz\n", + njs_printf("%05uz PROP NEXT %04Xz %04Xz %04Xz %uz\n", p - start, (size_t) prop_next->retval, (size_t) prop_next->object, (size_t) prop_next->next, (size_t) prop_next->offset); @@ -327,6 +328,22 @@ njs_disassemble(u_char *start, u_char *e continue; } + if (operation == NJS_VMCODE_PROPERTY_ACCESSOR) { + prop_accessor = (njs_vmcode_prop_accessor_t *) p; + + njs_printf("%05uz PROP %s ACCESSOR %04Xz %04Xz %04Xz\n", + p - start, + (prop_accessor->type == NJS_OBJECT_PROP_GETTER) + ? "GET" : "SET", + (size_t) prop_accessor->value, + (size_t) prop_accessor->object, + (size_t) prop_accessor->property); + + p += sizeof(njs_vmcode_prop_accessor_t); + + continue; + } + if (operation == NJS_VMCODE_TRY_START) { try_start = (njs_vmcode_try_start_t *) p; diff -r e22663f2defe -r 33c4966abdda src/njs_generator.c --- a/src/njs_generator.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_generator.c Thu Aug 08 03:52:18 2019 -0400 @@ -119,6 +119,8 @@ static njs_int_t njs_generate_operation_ njs_generator_t *generator, njs_parser_node_t *node); static njs_int_t njs_generate_object(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); +static njs_int_t njs_generate_property_accessor(njs_vm_t *vm, + njs_generator_t *generator, njs_parser_node_t *node); static njs_int_t njs_generate_array(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); static njs_int_t njs_generate_function(njs_vm_t *vm, njs_generator_t *generator, @@ -398,6 +400,10 @@ njs_generator(njs_vm_t *vm, njs_generato case NJS_TOKEN_OBJECT: return njs_generate_object(vm, generator, node); + case NJS_TOKEN_PROPERTY_GETTER: + case NJS_TOKEN_PROPERTY_SETTER: + return njs_generate_property_accessor(vm, generator, node); + case NJS_TOKEN_ARRAY: return njs_generate_array(vm, generator, node); @@ -1896,6 +1902,49 @@ njs_generate_object(njs_vm_t *vm, njs_ge static njs_int_t +njs_generate_property_accessor(njs_vm_t *vm, njs_generator_t *generator, + njs_parser_node_t *node) +{ + njs_int_t ret; + njs_parser_node_t *lvalue, *function, *object, *property; + njs_vmcode_prop_accessor_t *accessor; + + lvalue = node->left; + function = node->right; + + object = lvalue->left; + + ret = njs_generator(vm, generator, object); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + property = lvalue->right; + + ret = njs_generator(vm, generator, property); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_generator(vm, generator, function); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_generate_code(generator, njs_vmcode_prop_accessor_t, accessor, + NJS_VMCODE_PROPERTY_ACCESSOR, 3); + + accessor->value = function->index; + accessor->object = object->index; + accessor->property = property->index; + accessor->type = (node->token == NJS_TOKEN_PROPERTY_GETTER) + ? NJS_OBJECT_PROP_GETTER : NJS_OBJECT_PROP_SETTER; + + return NJS_OK; +} + + +static njs_int_t njs_generate_array(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { diff -r e22663f2defe -r 33c4966abdda src/njs_lexer.h --- a/src/njs_lexer.h Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_lexer.h Thu Aug 08 03:52:18 2019 -0400 @@ -125,6 +125,8 @@ typedef enum { NJS_TOKEN_PROPERTY, NJS_TOKEN_PROPERTY_INIT, NJS_TOKEN_PROPERTY_DELETE, + NJS_TOKEN_PROPERTY_GETTER, + NJS_TOKEN_PROPERTY_SETTER, NJS_TOKEN_ARRAY, diff -r e22663f2defe -r 33c4966abdda src/njs_lexer_keyword.c --- a/src/njs_lexer_keyword.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_lexer_keyword.c Thu Aug 08 03:52:18 2019 -0400 @@ -186,6 +186,8 @@ njs_lexer_keyword(njs_lexer_t *lexer, nj lhq.key = lt->text; lhq.proto = &njs_keyword_hash_proto; + lexer->keyword = 0; + if (njs_lvlhsh_find(&lexer->keywords_hash, &lhq) == NJS_OK) { keyword = lhq.value; lt->token = keyword->token; diff -r e22663f2defe -r 33c4966abdda src/njs_object.c --- a/src/njs_object.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_object.c Thu Aug 08 03:52:18 2019 -0400 @@ -1112,7 +1112,8 @@ njs_object_define_property(njs_vm_t *vm, name = njs_arg(args, nargs, 2); - ret = njs_object_prop_define(vm, value, name, desc); + ret = njs_object_prop_define(vm, value, name, desc, + NJS_OBJECT_PROP_DESCRIPTOR); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1165,7 +1166,8 @@ njs_object_define_properties(njs_vm_t *v } if (prop->enumerable && njs_is_object(&prop->value)) { - ret = njs_object_prop_define(vm, value, &prop->name, &prop->value); + ret = njs_object_prop_define(vm, value, &prop->name, &prop->value, + NJS_OBJECT_PROP_DESCRIPTOR); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; diff -r e22663f2defe -r 33c4966abdda src/njs_object.h --- a/src/njs_object.h Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_object.h Thu Aug 08 03:52:18 2019 -0400 @@ -29,6 +29,13 @@ } while (0) +typedef enum { + NJS_OBJECT_PROP_DESCRIPTOR, + NJS_OBJECT_PROP_GETTER, + NJS_OBJECT_PROP_SETTER, +} njs_object_prop_define_t; + + struct njs_object_init_s { njs_str_t name; const njs_object_prop_t *properties; @@ -68,7 +75,7 @@ njs_object_prop_t *njs_object_prop_alloc njs_int_t njs_object_property(njs_vm_t *vm, const njs_value_t *value, njs_lvlhsh_query_t *lhq, njs_value_t *retval); njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - njs_value_t *name, njs_value_t *value); + njs_value_t *name, njs_value_t *value, njs_object_prop_define_t type); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_value_t *value, njs_value_t *setval); const char *njs_prop_type_string(njs_object_prop_type_t type); diff -r e22663f2defe -r 33c4966abdda src/njs_object_prop.c --- a/src/njs_object_prop.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_object_prop.c Thu Aug 08 03:52:18 2019 -0400 @@ -8,8 +8,8 @@ #include -static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm, - const njs_value_t *name, const njs_value_t *desc); +static njs_int_t njs_descriptor_prop(njs_vm_t *vm, + njs_object_prop_t *prop, const njs_value_t *desc); njs_object_prop_t * @@ -102,7 +102,7 @@ found: */ njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - njs_value_t *name, njs_value_t *value) + njs_value_t *name, njs_value_t *value, njs_object_prop_define_t type) { njs_int_t ret; njs_object_prop_t *prop, *prev; @@ -116,11 +116,38 @@ njs_object_prop_define(njs_vm_t *vm, njs return ret; } - prop = njs_descriptor_prop(vm, name, value); + prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, + NJS_ATTRIBUTE_UNSET); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } + switch (type) { + + case NJS_OBJECT_PROP_DESCRIPTOR: + if (njs_descriptor_prop(vm, prop, value) != NJS_OK) { + return NJS_ERROR; + } + + break; + + case NJS_OBJECT_PROP_GETTER: + prop->getter = *value; + prop->setter = njs_value_invalid; + prop->enumerable = NJS_ATTRIBUTE_TRUE; + prop->configurable = NJS_ATTRIBUTE_TRUE; + + break; + + case NJS_OBJECT_PROP_SETTER: + prop->setter = *value; + prop->getter = njs_value_invalid; + prop->enumerable = NJS_ATTRIBUTE_TRUE; + prop->configurable = NJS_ATTRIBUTE_TRUE; + + break; + } + if (njs_fast_path(ret == NJS_DECLINED)) { /* 6.2.5.6 CompletePropertypropriptor */ @@ -332,37 +359,30 @@ exception: } -static njs_object_prop_t * -njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, +static njs_int_t +njs_descriptor_prop(njs_vm_t *vm, njs_object_prop_t *prop, const njs_value_t *desc) { njs_int_t ret; njs_bool_t data, accessor; njs_value_t value; - njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; data = 0; accessor = 0; - prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, - NJS_ATTRIBUTE_UNSET); - if (njs_slow_path(prop == NULL)) { - return NULL; - } - njs_object_property_init(&lhq, "get", NJS_GET_HASH); ret = njs_object_property(vm, desc, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + return NJS_ERROR; } if (ret == NJS_OK) { if (njs_is_defined(&value) && !njs_is_function(&value)) { njs_type_error(vm, "Getter must be a function"); - return NULL; + return NJS_ERROR; } accessor = 1; @@ -379,13 +399,13 @@ njs_descriptor_prop(njs_vm_t *vm, const ret = njs_object_property(vm, desc, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + return ret; } if (ret == NJS_OK) { if (njs_is_defined(&value) && !njs_is_function(&value)) { njs_type_error(vm, "Setter must be a function"); - return NULL; + return NJS_ERROR; } accessor = 1; @@ -402,7 +422,7 @@ njs_descriptor_prop(njs_vm_t *vm, const ret = njs_object_property(vm, desc, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + return ret; } if (ret == NJS_OK) { @@ -416,7 +436,7 @@ njs_descriptor_prop(njs_vm_t *vm, const ret = njs_object_property(vm, desc, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + return ret; } if (ret == NJS_OK) { @@ -430,7 +450,7 @@ njs_descriptor_prop(njs_vm_t *vm, const ret = njs_object_property(vm, desc, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + return ret; } if (ret == NJS_OK) { @@ -443,7 +463,7 @@ njs_descriptor_prop(njs_vm_t *vm, const ret = njs_object_property(vm, desc, &lhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + return ret; } if (ret == NJS_OK) { @@ -453,10 +473,10 @@ njs_descriptor_prop(njs_vm_t *vm, const if (accessor && data) { njs_type_error(vm, "Cannot both specify accessors " "and a value or writable attribute"); - return NULL; + return NJS_ERROR; } - return prop; + return NJS_OK; } diff -r e22663f2defe -r 33c4966abdda src/njs_parser_terminal.c --- a/src/njs_parser_terminal.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_parser_terminal.c Thu Aug 08 03:52:18 2019 -0400 @@ -19,6 +19,10 @@ static njs_token_t njs_parser_object(njs static njs_int_t njs_parser_object_property(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *parent, njs_parser_node_t *property, njs_parser_node_t *value); +static njs_int_t njs_parser_property_accessor(njs_vm_t *vm, + njs_parser_t *parser, njs_parser_node_t *parent, + njs_parser_node_t *property, njs_parser_node_t *value, + njs_token_t accessor); static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *array); static njs_int_t njs_parser_array_item(njs_vm_t *vm, njs_parser_t *parser, @@ -467,31 +471,23 @@ njs_parser_builtin(njs_vm_t *vm, njs_par } -/* - * ES6: 12.2.6 Object Initializer - * Supported syntax: - * PropertyDefinition: - * PropertyName : AssignmentExpression - * IdentifierReference - * PropertyName: - * IdentifierName, StringLiteral, NumericLiteral. - */ static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) { uint32_t hash, token_line; njs_int_t ret; njs_str_t name; - njs_token_t token, prop_token; + njs_token_t token, accessor; njs_lexer_t *lexer; njs_parser_node_t *object, *property, *expression; njs_function_lambda_t *lambda; lexer = parser->lexer; - /* GCC and Clang complain about uninitialized hash. */ + /* GCC and Clang complain about uninitialized values. */ hash = 0; token_line = 0; + property = NULL; object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); if (njs_slow_path(object == NULL)) { @@ -501,16 +497,46 @@ njs_parser_object(njs_vm_t *vm, njs_pars object->u.object = obj; for ( ;; ) { - prop_token = njs_parser_token(vm, parser); - if (njs_slow_path(prop_token <= NJS_TOKEN_ILLEGAL)) { - return prop_token; + token = njs_parser_token(vm, parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; } + accessor = 0; njs_memzero(&name, sizeof(njs_str_t)); - switch (prop_token) { + if (token == NJS_TOKEN_NAME || lexer->keyword) { + name = *njs_parser_text(parser); + hash = njs_parser_key_hash(parser); + token_line = njs_parser_token_line(parser); + + property = njs_parser_node_string(vm, parser); + if (njs_slow_path(property == NULL)) { + return NJS_TOKEN_ERROR; + } + + if (token == NJS_TOKEN_NAME && name.length == 3 + && (memcmp(name.start, "get", 3) == 0 + || memcmp(name.start, "set", 3) == 0)) + { + accessor = (name.start[0] == 'g') ? NJS_TOKEN_PROPERTY_GETTER + : NJS_TOKEN_PROPERTY_SETTER; + + token = njs_parser_token(vm, parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + } + } + + switch (token) { case NJS_TOKEN_CLOSE_BRACE: + if (accessor) { + accessor = 0; + break; + } + goto done; case NJS_TOKEN_OPEN_BRACKET: @@ -530,13 +556,14 @@ njs_parser_object(njs_vm_t *vm, njs_pars property = parser->node; - token = njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_BRACKET); + token = njs_parser_match(vm, parser, token, + NJS_TOKEN_CLOSE_BRACKET); break; case NJS_TOKEN_NUMBER: case NJS_TOKEN_STRING: case NJS_TOKEN_ESCAPE_STRING: - token = njs_parser_terminal(vm, parser, prop_token); + token = njs_parser_terminal(vm, parser, token); if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -545,58 +572,27 @@ njs_parser_object(njs_vm_t *vm, njs_pars break; default: - if (prop_token != NJS_TOKEN_NAME && !lexer->keyword) { - return NJS_TOKEN_ILLEGAL; + if (token != NJS_TOKEN_NAME && !lexer->keyword) { + if (name.length == 0) { + return NJS_TOKEN_ILLEGAL; + } + + accessor = 0; + break; } - property = njs_parser_node_string(vm, parser); - if (njs_slow_path(property == NULL)) { - return NJS_TOKEN_ERROR; + if (accessor) { + property = njs_parser_node_string(vm, parser); + if (njs_slow_path(property == NULL)) { + return NJS_TOKEN_ERROR; + } } - name = *njs_parser_text(parser); - hash = njs_parser_key_hash(parser); - token_line = njs_parser_token_line(parser); - token = njs_parser_token(vm, parser); break; } - switch (token) { - - case NJS_TOKEN_COMMA: - case NJS_TOKEN_CLOSE_BRACE: - - if (name.length == 0 - || prop_token == NJS_TOKEN_THIS - || prop_token == NJS_TOKEN_GLOBAL_THIS) - { - return NJS_TOKEN_ILLEGAL; - } - - expression = njs_parser_reference(vm, parser, prop_token, &name, - hash, token_line); - if (njs_slow_path(expression == NULL)) { - return NJS_TOKEN_ERROR; - } - - break; - - case NJS_TOKEN_COLON: - token = njs_parser_token(vm, parser); - if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - token = njs_parser_assignment_expression(vm, parser, token); - if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - expression = parser->node; - break; - - case NJS_TOKEN_OPEN_PARENTHESIS: + if (accessor) { expression = njs_parser_node_new(vm, parser, NJS_TOKEN_FUNCTION_EXPRESSION); if (njs_slow_path(expression == NULL)) { @@ -606,7 +602,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars expression->token_line = njs_parser_token_line(parser); parser->node = expression; - lambda = njs_function_lambda_alloc(vm, 0); + lambda = njs_mp_zalloc(vm->mem_pool, sizeof(njs_function_lambda_t)); if (njs_slow_path(lambda == NULL)) { return NJS_TOKEN_ERROR; } @@ -618,15 +614,95 @@ njs_parser_object(njs_vm_t *vm, njs_pars return token; } - break; + if (accessor == NJS_TOKEN_PROPERTY_GETTER) { + if (lambda->nargs != 0) { + njs_parser_syntax_error(vm, parser, + "Getter must not have any formal parameters"); + return NJS_TOKEN_ILLEGAL; + } + + } else { + if (lambda->nargs != 1) { + njs_parser_syntax_error(vm, parser, + "Setter must have exactly one formal parameter"); + return NJS_TOKEN_ILLEGAL; + } + } + + ret = njs_parser_property_accessor(vm, parser, obj, property, + expression, accessor); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_TOKEN_ERROR; + } + + } else { + switch (token) { + + case NJS_TOKEN_COMMA: + case NJS_TOKEN_CLOSE_BRACE: + + if (name.length == 0 + || lexer->prev_token == NJS_TOKEN_THIS + || lexer->prev_token == NJS_TOKEN_GLOBAL_THIS) + { + return NJS_TOKEN_ILLEGAL; + } + + expression = njs_parser_reference(vm, parser, lexer->prev_token, + &name, hash, token_line); + if (njs_slow_path(expression == NULL)) { + return NJS_TOKEN_ERROR; + } + + break; - default: - return NJS_TOKEN_ILLEGAL; - } + case NJS_TOKEN_COLON: + token = njs_parser_token(vm, parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_assignment_expression(vm, parser, token); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + expression = parser->node; + break; + + case NJS_TOKEN_OPEN_PARENTHESIS: + expression = njs_parser_node_new(vm, parser, + NJS_TOKEN_FUNCTION_EXPRESSION); + if (njs_slow_path(expression == NULL)) { + return NJS_TOKEN_ERROR; + } + + expression->token_line = njs_parser_token_line(parser); + parser->node = expression; - ret = njs_parser_object_property(vm, parser, obj, property, expression); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_TOKEN_ERROR; + lambda = njs_function_lambda_alloc(vm, 0); + if (njs_slow_path(lambda == NULL)) { + return NJS_TOKEN_ERROR; + } + + expression->u.value.data.u.lambda = lambda; + + token = njs_parser_function_lambda(vm, parser, lambda, token); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + break; + + default: + return NJS_TOKEN_ILLEGAL; + } + + ret = njs_parser_object_property(vm, parser, obj, property, + expression); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_TOKEN_ERROR; + } } if (token == NJS_TOKEN_CLOSE_BRACE) { @@ -690,6 +766,49 @@ njs_parser_object_property(njs_vm_t *vm, } +static njs_int_t +njs_parser_property_accessor(njs_vm_t *vm, njs_parser_t *parser, + njs_parser_node_t *parent, njs_parser_node_t *property, + njs_parser_node_t *value, njs_token_t accessor) +{ + njs_parser_node_t *node, *stmt, *object, *propref; + + object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); + if (njs_slow_path(object == NULL)) { + return NJS_TOKEN_ERROR; + } + + object->u.object = parent; + + propref = njs_parser_node_new(vm, parser, 0); + if (njs_slow_path(propref == NULL)) { + return NJS_ERROR; + } + + propref->left = object; + propref->right = property; + + node = njs_parser_node_new(vm, parser, accessor); + if (njs_slow_path(node == NULL)) { + return NJS_ERROR; + } + + node->left = propref; + node->right = value; + + stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); + if (njs_slow_path(stmt == NULL)) { + return NJS_ERROR; + } + + stmt->right = node; + stmt->left = parent->left; + parent->left = stmt; + + return NJS_OK; +} + + static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *array) { diff -r e22663f2defe -r 33c4966abdda src/njs_vmcode.c --- a/src/njs_vmcode.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_vmcode.c Thu Aug 08 03:52:18 2019 -0400 @@ -86,9 +86,10 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c njs_str_t string; njs_uint_t hint; njs_bool_t valid, lambda_call; - njs_value_t *retval, *value1, *value2, *src, *s1, *s2; - njs_value_t numeric1, numeric2, primitive1, primitive2, - dst; + njs_value_t *retval, *value1, *value2; + njs_value_t *src, *s1, *s2, dst; + njs_value_t *function, name; + njs_value_t numeric1, numeric2, primitive1, primitive2; njs_frame_t *frame; njs_jump_off_t ret; njs_vmcode_this_t *this; @@ -103,6 +104,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c njs_vmcode_equal_jump_t *equal; njs_vmcode_try_return_t *try_return; njs_vmcode_method_frame_t *method_frame; + njs_vmcode_prop_accessor_t *accessor; njs_vmcode_function_frame_t *function_frame; next: @@ -599,6 +601,27 @@ next: ret = sizeof(njs_vmcode_prop_set_t); break; + case NJS_VMCODE_PROPERTY_ACCESSOR: + accessor = (njs_vmcode_prop_accessor_t *) pc; + function = njs_vmcode_operand(vm, accessor->value); + + ret = njs_value_to_string(vm, &name, value2); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "failed conversion of type \"%s\" " + "to string while property define", + njs_type_string(value2->type)); + return NJS_ERROR; + } + + ret = njs_object_prop_define(vm, value1, &name, function, + accessor->type); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = sizeof(njs_vmcode_prop_accessor_t); + break; + case NJS_VMCODE_IF_TRUE_JUMP: case NJS_VMCODE_IF_FALSE_JUMP: ret = njs_is_true(value1); diff -r e22663f2defe -r 33c4966abdda src/njs_vmcode.h --- a/src/njs_vmcode.h Mon Aug 12 14:54:46 2019 +0300 +++ b/src/njs_vmcode.h Thu Aug 08 03:52:18 2019 -0400 @@ -40,6 +40,7 @@ typedef uint8_t #define NJS_VMCODE_STOP VMCODE0(0) #define NJS_VMCODE_JUMP VMCODE0(1) #define NJS_VMCODE_PROPERTY_SET VMCODE0(2) +#define NJS_VMCODE_PROPERTY_ACCESSOR VMCODE0(3) #define NJS_VMCODE_IF_TRUE_JUMP VMCODE0(4) #define NJS_VMCODE_IF_FALSE_JUMP VMCODE0(5) #define NJS_VMCODE_IF_EQUAL_JUMP VMCODE0(6) @@ -261,6 +262,15 @@ typedef struct { typedef struct { njs_vmcode_t code; + njs_index_t value; + njs_index_t object; + njs_index_t property; + uint8_t type; +} njs_vmcode_prop_accessor_t; + + +typedef struct { + njs_vmcode_t code; njs_index_t next; njs_index_t object; njs_jump_off_t offset; diff -r e22663f2defe -r 33c4966abdda src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Aug 12 14:54:46 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Aug 08 03:52:18 2019 -0400 @@ -10096,6 +10096,61 @@ static njs_unit_test_t njs_test[] = "JSON.stringify(Object.getOwnPropertyDescriptor(o, 'a')).set"), njs_str("undefined") }, + { njs_str("var get = 'get'; var o = { get }; o.get"), + njs_str("get") }, + + { njs_str("var o = { get foo() { return 'bar'; } }; o.foo"), + njs_str("bar") }, + + { njs_str("var o = { get get() { return 'bar'; } }; o.get"), + njs_str("bar") }, + + { njs_str("var o = { get() { return 'bar'; } }; o.get()"), + njs_str("bar") }, + + { njs_str("var o = { get lazy() { delete this.lazy; return this.lazy = Math.pow(2,3)} };o.lazy"), + njs_str("8") }, + + { njs_str("var o = { get lazy() { delete this.lazy; return this.lazy = Math.pow(2,3)} }; o.lazy;" + "Object.getOwnPropertyDescriptor(o, 'lazy').value"), + njs_str("8") }, + + { njs_str("var expr = 'foo'; var o = { get [expr]() { return 'bar'; } }; o.foo"), + njs_str("bar") }, + + { njs_str("var o = { get [{toString(){return 'get'}}]() { return 'bar'; } }; o.get"), + njs_str("bar") }, + + { njs_str("var o = { get [{toString(){return {} }}]() { return 'bar'; } }; o.get"), + njs_str("InternalError: failed conversion of type \"object\" to string while property define") }, + + { njs_str("var o = { get foo(v1, v2) { return 'bar'; } }; o.foo"), + njs_str("SyntaxError: Getter must not have any formal parameters in 1") }, + + { njs_str("var o = { baz: 'bar', set foo(v) { this.baz = v; } }; o.foo = 'baz'; o.baz"), + njs_str("baz") }, + + { njs_str("var o = { baz: 'bar', set set(v) { this.baz = v; } }; o.set = 'baz'; o.baz"), + njs_str("baz") }, + + { njs_str("var expr = 'foo'; var o = { baz: 'bar', set [expr](v) { this.baz = v; } }; o.foo = 'baz'; o.baz"), + njs_str("baz") }, + + { njs_str("var o = { baz: 'bar', set foo(v1, v2) { this.baz = v; } }; o.foo = 'baz'; o.baz"), + njs_str("SyntaxError: Setter must have exactly one formal parameter in 1") }, + + { njs_str("var o = { get foo() { return 'bar'; }, set foo(v) { this.baz = v; } }; o.foo"), + njs_str("bar") }, + + { njs_str("var expr = 'foo'; var o = { get [expr]() { return 'bar'; }, set [expr](v) { this.baz = v; } }; o.foo"), + njs_str("bar") }, + + { njs_str("Object.getOwnPropertyDescriptor({get foo() {}}, 'foo').enumerable"), + njs_str("true") }, + + { njs_str("Object.getOwnPropertyDescriptor({get foo() {}}, 'foo').configurable"), + njs_str("true") }, + { njs_str("var p = { a:5 }; var o = Object.create(p);" "Object.getPrototypeOf(o) === p"), njs_str("true") }, From balus at foxmail.com Mon Aug 12 14:01:13 2019 From: balus at foxmail.com (Jianyong Chen) Date: Mon, 12 Aug 2019 22:01:13 +0800 Subject: [Patch] flv: add support for time offset In-Reply-To: <144aebff.12a0e.16c8581d94c.Coremail.winshining@163.com> References: <144aebff.12a0e.16c8581d94c.Coremail.winshining@163.com> Message-ID: > On Aug 12, 2019, at 7:06 PM, winshining wrote: > > Hi, balus > I think the second parameter of ngx_http_flv_read in ngx_http_flv_read_metadata and ngx_http_flv_read_tags is incorrect, it should be NGX_FLV_TAG_HEADER_SIZE. > Besides, 'keyframes' is a non-standard object in metadata, there is no description about it in official tech document, you can refer to https://www.adobe.com/devnet/f4v.html for details. Therefore, if a FLV file without the 'keyframes' object in metadata is played, the member 'times' of structure ngx_http_flv_file_t will be NULL, ngx_http_flv_timestamp_to_offset will crash then. > > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel Thanks for reading my code! The first problem is a little confusing indeed. Notice that NGX_FLV_HEADER_SIZE == NGX_FLV_TAG_HEADER_SIZE + NGX_FLV_PREV_TAG_SIZE? and when I read a tag, I actually read tag_header + tag_data + prev_tag_size, thus NGX_FLV_HEADER_SIZE is just what I need. Anyway, this is my fault, I should have unified the two macros. The second probelm has been carefully considered in the code. If there is no ?keyframes? object found in metadata, ngx_http_flv_parse_metadata() will return NGX_DECLINED, which means to send the whole file, and therefore ngx_http_flv_timestamp_to_offset() won?t be called and thus won?t crash. -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon Aug 12 18:05:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 12 Aug 2019 18:05:16 +0000 Subject: [njs] Fixed fs.readFile() and fs.readFileSync() for files with 0 size. Message-ID: details: https://hg.nginx.org/njs/rev/355028822e48 branches: changeset: 1121:355028822e48 user: Dmitry Volyntsev date: Mon Aug 12 21:03:24 2019 +0300 description: Fixed fs.readFile() and fs.readFileSync() for files with 0 size. diffstat: src/njs_fs.c | 183 +++++++++++++++++++++++++++++++++++----------- test/njs_expect_test.exp | 21 +++++ 2 files changed, 160 insertions(+), 44 deletions(-) diffs (282 lines): diff -r 33c4966abdda -r 355028822e48 src/njs_fs.c --- a/src/njs_fs.c Thu Aug 08 03:52:18 2019 -0400 +++ b/src/njs_fs.c Mon Aug 12 21:03:24 2019 +0300 @@ -31,6 +31,8 @@ static njs_int_t njs_fs_write_file_inter static njs_int_t njs_fs_write_file_sync_internal(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, int default_flags); +static njs_int_t njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, + njs_str_t *data); static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description, njs_value_t *path, int errn, njs_value_t *retval); static int njs_fs_flags(njs_str_t *value); @@ -70,9 +72,10 @@ njs_fs_read_file(njs_vm_t *vm, njs_value njs_index_t unused) { int fd, errn, flags; - u_char *p, *start, *end; - ssize_t n, length; - njs_str_t flag, encoding; + u_char *start; + size_t size; + ssize_t length; + njs_str_t flag, encoding, data; njs_int_t ret; const char *path, *syscall, *description; struct stat sb; @@ -209,32 +212,46 @@ njs_fs_read_file(njs_vm_t *vm, njs_value length = 0; } - start = njs_string_alloc(vm, &arguments[2], sb.st_size, length); - if (njs_slow_path(start == NULL)) { - goto fail; - } + size = sb.st_size; - p = start; - end = p + sb.st_size; + if (njs_fast_path(size != 0)) { - while (p < end) { - n = read(fd, p, end - p); - if (njs_slow_path(n == -1)) { - if (errno == EINTR) { - continue; - } + start = njs_string_alloc(vm, &arguments[2], size, length); + if (njs_slow_path(start == NULL)) { + goto fail; + } - errn = errno; - description = strerror(errno); - syscall = "read"; - goto done; + data.start = start; + data.length = size; + + ret = njs_fs_fd_read(vm, &args[1], fd, &data); + if (ret != NJS_OK) { + goto fail; } - p += n; + start = data.start; + + } else { + /* size of the file is not known in advance. */ + + data.length = 0; + + ret = njs_fs_fd_read(vm, &args[1], fd, &data); + if (ret != NJS_OK) { + goto fail; + } + + size = data.length; + start = data.start; + + ret = njs_string_new(vm, &arguments[2], start, size, length); + if (njs_slow_path(ret != NJS_OK)) { + goto fail; + } } if (encoding.length != 0) { - length = njs_utf8_length(start, sb.st_size); + length = njs_utf8_length(start, size); if (length >= 0) { njs_string_length_set(&arguments[2], length); @@ -295,9 +312,10 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ njs_index_t unused) { int fd, errn, flags; - u_char *p, *start, *end; - ssize_t n, length; - njs_str_t flag, encoding; + u_char *start; + size_t size; + ssize_t length; + njs_str_t flag, encoding, data; njs_int_t ret; const char *path, *syscall, *description; struct stat sb; @@ -418,32 +436,46 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ length = 0; } - start = njs_string_alloc(vm, &vm->retval, sb.st_size, length); - if (njs_slow_path(start == NULL)) { - goto fail; - } + size = sb.st_size; - p = start; - end = p + sb.st_size; + if (njs_fast_path(size != 0)) { - while (p < end) { - n = read(fd, p, end - p); - if (njs_slow_path(n == -1)) { - if (errno == EINTR) { - continue; - } + start = njs_string_alloc(vm, &vm->retval, size, length); + if (njs_slow_path(start == NULL)) { + goto fail; + } - errn = errno; - description = strerror(errno); - syscall = "read"; - goto done; + data.start = start; + data.length = size; + + ret = njs_fs_fd_read(vm, &args[1], fd, &data); + if (ret != NJS_OK) { + goto fail; } - p += n; + start = data.start; + + } else { + /* size of the file is not known in advance. */ + + data.length = 0; + + ret = njs_fs_fd_read(vm, &args[1], fd, &data); + if (ret != NJS_OK) { + goto fail; + } + + size = data.length; + start = data.start; + + ret = njs_string_new(vm, &vm->retval, start, size, length); + if (njs_slow_path(ret != NJS_OK)) { + goto fail; + } } if (encoding.length != 0) { - length = njs_utf8_length(start, sb.st_size); + length = njs_utf8_length(start, size); if (length >= 0) { njs_string_length_set(&vm->retval, length); @@ -872,8 +904,71 @@ done: } -static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall, - const char *description, njs_value_t *path, int errn, njs_value_t *retval) +static njs_int_t +njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, njs_str_t *data) +{ + u_char *p, *end, *start; + size_t size; + ssize_t n; + + size = data->length; + + if (size == 0) { + size = 4096; + + data->start = njs_mp_alloc(vm->mem_pool, size); + if (data->start == NULL) { + njs_memory_error(vm); + return NJS_ERROR; + } + } + + p = data->start; + end = p + size; + + for ( ;; ) { + n = read(fd, p, end - p); + + if (njs_slow_path(n < 0)) { + (void) njs_fs_error(vm, "read", strerror(errno), path, errno, + &vm->retval); + return NJS_ERROR; + } + + p += n; + + if (n == 0) { + break; + } + + if (end - p < 2048) { + size *= 2; + + start = njs_mp_alloc(vm->mem_pool, size); + if (start == NULL) { + njs_memory_error(vm); + return NJS_ERROR; + } + + memcpy(start, data->start, p - data->start); + + njs_mp_free(vm->mem_pool, data->start); + + p = start + (p - data->start); + end = start + size; + data->start = start; + } + } + + data->length = p - data->start; + + return NJS_OK; +} + + +static njs_int_t +njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description, + njs_value_t *path, int errn, njs_value_t *retval) { size_t size; njs_int_t ret; diff -r 33c4966abdda -r 355028822e48 test/njs_expect_test.exp --- a/test/njs_expect_test.exp Thu Aug 08 03:52:18 2019 -0400 +++ b/test/njs_expect_test.exp Mon Aug 12 21:03:24 2019 +0300 @@ -442,6 +442,15 @@ njs_test { "Error: No such file or directory\r\nundefined\r\n>> "} } +njs_test { + {"var fs = require('fs')\r\n" + "undefined\r\n>> "} + {"fs.readFile('/proc/version', (e, data) => {console.log(e || data.slice(0,5) == 'Linux')})\r\n" + "true\r\nundefined\r\n>> "} + {"fs.readFile('/proc/cpuinfo', (e, data) => {console.log(e || data.slice(0,9) == 'processor')})\r\n" + "true\r\nundefined\r\n>> "} +} + # require('fs').readFileSync() njs_test { @@ -500,6 +509,18 @@ njs_test { "Error: Non-UTF8 file, convertion is not implemented"} } +njs_test { + {"var fs = require('fs'), file\r\n" + "undefined\r\n>> "} + {"try { file = fs.readFileSync('/proc/version')} catch (e) {}\r\n" + "undefined"} + {"(!file || file.slice(0,5) == 'Linux')\r\n" + "true"} + {"try { file = fs.readFileSync('/proc/cpuinfo')} catch (e) {}\r\n" + "undefined"} + {"(!file || file.slice(0,9) == 'processor')\r\n" + "true"} +} # require('fs').writeFile() From xeioex at nginx.com Mon Aug 12 18:05:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 12 Aug 2019 18:05:16 +0000 Subject: [njs] Added fs.renameSync(). Message-ID: details: https://hg.nginx.org/njs/rev/e861b6f6bcae branches: changeset: 1122:e861b6f6bcae user: Dmitry Volyntsev date: Mon Aug 12 21:04:49 2019 +0300 description: Added fs.renameSync(). This closes #198 issue on Github. diffstat: src/njs_fs.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ src/test/njs_unit_test.c | 10 +++++++++ test/njs_expect_test.exp | 22 ++++++++++++++++++++ 3 files changed, 83 insertions(+), 0 deletions(-) diffs (127 lines): diff -r 355028822e48 -r e861b6f6bcae src/njs_fs.c --- a/src/njs_fs.c Mon Aug 12 21:03:24 2019 +0300 +++ b/src/njs_fs.c Mon Aug 12 21:04:49 2019 +0300 @@ -30,6 +30,8 @@ static njs_int_t njs_fs_write_file_inter njs_uint_t nargs, int default_flags); static njs_int_t njs_fs_write_file_sync_internal(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, int default_flags); +static njs_int_t njs_fs_rename_sync(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused); static njs_int_t njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, njs_str_t *data); @@ -905,6 +907,46 @@ done: static njs_int_t +njs_fs_rename_sync(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + int ret; + const char *old_path, *new_path; + + if (njs_slow_path(!njs_is_string(njs_arg(args, nargs, 1)))) { + njs_type_error(vm, "oldPath must be a string"); + return NJS_ERROR; + } + + if (njs_slow_path(!njs_is_string(njs_arg(args, nargs, 2)))) { + njs_type_error(vm, "newPath must be a string"); + return NJS_ERROR; + } + + old_path = (const char *) njs_string_to_c_string(vm, njs_argument(args, 1)); + if (njs_slow_path(old_path == NULL)) { + return NJS_ERROR; + } + + new_path = (const char *) njs_string_to_c_string(vm, njs_argument(args, 2)); + if (njs_slow_path(new_path == NULL)) { + return NJS_ERROR; + } + + ret = rename(old_path, new_path); + if (njs_slow_path(ret != 0)) { + ret = njs_fs_error(vm, "rename", strerror(errno), NULL, errno, + &vm->retval); + return NJS_ERROR; + } + + njs_set_undefined(&vm->retval); + + return NJS_OK; +} + + +static njs_int_t njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, njs_str_t *data) { u_char *p, *end, *start; @@ -1159,6 +1201,15 @@ static const njs_object_prop_t njs_fs_o .configurable = 1, }, + { + .type = NJS_PROPERTY, + .name = njs_string("renameSync"), + .value = njs_native_function(njs_fs_rename_sync, NJS_STRING_ARG, + NJS_STRING_ARG, 0), + .writable = 1, + .configurable = 1, + }, + }; diff -r 355028822e48 -r e861b6f6bcae src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Aug 12 21:03:24 2019 +0300 +++ b/src/test/njs_unit_test.c Mon Aug 12 21:04:49 2019 +0300 @@ -13156,6 +13156,16 @@ static njs_unit_test_t njs_test[] = "fs.writeFileSync('/njs_unknown_path', '', true)"), njs_str("TypeError: Unknown options type (a string or object required)") }, + /* require('fs').writeFileSync() */ + + { njs_str("var fs = require('fs');" + "fs.renameSync()"), + njs_str("TypeError: oldPath must be a string") }, + + { njs_str("var fs = require('fs');" + "fs.renameSync({toString(){return '/path/1'}})"), + njs_str("TypeError: newPath must be a string") }, + /* require('crypto').createHash() */ { njs_str("require('crypto').createHash('sha1')"), diff -r 355028822e48 -r e861b6f6bcae test/njs_expect_test.exp --- a/test/njs_expect_test.exp Mon Aug 12 21:03:24 2019 +0300 +++ b/test/njs_expect_test.exp Mon Aug 12 21:04:49 2019 +0300 @@ -646,6 +646,28 @@ njs_test { "'ABCABC'\r\n>> "} } +# require('fs').renameSync() + +njs_test { + {"var fs = require('fs'), mktemp = ()=> `/tmp/njs_${Math.round(Math.random() * 1000000)}`\r\n" + "undefined\r\n>> "} + {"var fn1 = mktemp(), fn2 = mktemp();\r\n" + "undefined\r\n>> "} + {"fs.writeFileSync(fn1, 'ABC')\r\n" + "undefined\r\n>> "} + {"fs.renameSync(fn1, fn2)\r\n" + "undefined\r\n>> "} + {"fs.readFileSync(fn2)\r\n" + "'ABC'\r\n>> "} +} + +njs_test { + {"var fs = require('fs')\r\n" + "undefined\r\n>> "} + {"fs.renameSync('build/test/file2', 'test/fs/')\r\n" + "Error: Not a directory*"} +} + # Modules njs_run {"-p" "test/module/libs" "./test/module/normal.js"} \ From xeioex at nginx.com Mon Aug 12 18:05:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 12 Aug 2019 18:05:16 +0000 Subject: [njs] Improved njs_string_to_c_string() prototype. Message-ID: details: https://hg.nginx.org/njs/rev/03008af6253b branches: changeset: 1123:03008af6253b user: Dmitry Volyntsev date: Mon Aug 12 21:04:49 2019 +0300 description: Improved njs_string_to_c_string() prototype. To avoid excessive casts. diffstat: src/njs_fs.c | 12 ++++++------ src/njs_string.c | 6 +++--- src/njs_string.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diffs (96 lines): diff -r e861b6f6bcae -r 03008af6253b src/njs_fs.c --- a/src/njs_fs.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_fs.c Mon Aug 12 21:04:49 2019 +0300 @@ -156,7 +156,7 @@ njs_fs_read_file(njs_vm_t *vm, njs_value return NJS_ERROR; } - path = (char *) njs_string_to_c_string(vm, &args[1]); + path = njs_string_to_c_string(vm, &args[1]); if (njs_slow_path(path == NULL)) { return NJS_ERROR; } @@ -380,7 +380,7 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ return NJS_ERROR; } - path = (char *) njs_string_to_c_string(vm, &args[1]); + path = njs_string_to_c_string(vm, &args[1]); if (njs_slow_path(path == NULL)) { return NJS_ERROR; } @@ -660,7 +660,7 @@ static njs_int_t njs_fs_write_file_inter md = 0666; } - path = (char *) njs_string_to_c_string(vm, &args[1]); + path = njs_string_to_c_string(vm, &args[1]); if (njs_slow_path(path == NULL)) { return NJS_ERROR; } @@ -837,7 +837,7 @@ njs_fs_write_file_sync_internal(njs_vm_t md = 0666; } - path = (char *) njs_string_to_c_string(vm, &args[1]); + path = njs_string_to_c_string(vm, &args[1]); if (njs_slow_path(path == NULL)) { return NJS_ERROR; } @@ -923,12 +923,12 @@ njs_fs_rename_sync(njs_vm_t *vm, njs_val return NJS_ERROR; } - old_path = (const char *) njs_string_to_c_string(vm, njs_argument(args, 1)); + old_path = njs_string_to_c_string(vm, njs_argument(args, 1)); if (njs_slow_path(old_path == NULL)) { return NJS_ERROR; } - new_path = (const char *) njs_string_to_c_string(vm, njs_argument(args, 2)); + new_path = njs_string_to_c_string(vm, njs_argument(args, 2)); if (njs_slow_path(new_path == NULL)) { return NJS_ERROR; } diff -r e861b6f6bcae -r 03008af6253b src/njs_string.c --- a/src/njs_string.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_string.c Mon Aug 12 21:04:49 2019 +0300 @@ -3984,7 +3984,7 @@ njs_string_to_index(const njs_value_t *v * is returned as is, otherwise the new copy is allocated with * the terminating zero byte. */ -const u_char * +const char * njs_string_to_c_string(njs_vm_t *vm, njs_value_t *value) { u_char *p, *data, *start; @@ -3996,7 +3996,7 @@ njs_string_to_c_string(njs_vm_t *vm, njs if (size < NJS_STRING_SHORT) { start[size] = '\0'; - return start; + return (const char *) start; } } else { @@ -4013,7 +4013,7 @@ njs_string_to_c_string(njs_vm_t *vm, njs p = njs_cpymem(data, start, size); *p++ = '\0'; - return data; + return (const char *) data; } diff -r e861b6f6bcae -r 03008af6253b src/njs_string.h --- a/src/njs_string.h Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_string.h Mon Aug 12 21:04:49 2019 +0300 @@ -177,7 +177,7 @@ const u_char *njs_string_offset(const u_ uint32_t njs_string_index(njs_string_prop_t *string, uint32_t offset); void njs_string_offset_map_init(const u_char *start, size_t size); double njs_string_to_index(const njs_value_t *value); -const u_char *njs_string_to_c_string(njs_vm_t *vm, njs_value_t *value); +const char *njs_string_to_c_string(njs_vm_t *vm, njs_value_t *value); njs_int_t njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); njs_int_t njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args, From xeioex at nginx.com Mon Aug 12 18:05:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 12 Aug 2019 18:05:17 +0000 Subject: [njs] Using njs_set_undefined() and njs_set_invalid() where appropriate. Message-ID: details: https://hg.nginx.org/njs/rev/5f2162f7c3df branches: changeset: 1124:5f2162f7c3df user: Dmitry Volyntsev date: Mon Aug 12 21:04:50 2019 +0300 description: Using njs_set_undefined() and njs_set_invalid() where appropriate. diffstat: src/njs_array.c | 14 +++++++------- src/njs_builtin.c | 2 +- src/njs_fs.c | 16 ++++++++-------- src/njs_function.c | 2 +- src/njs_generator.c | 2 +- src/njs_json.c | 6 +++--- src/njs_object.c | 4 ++-- src/njs_object_prop.c | 40 ++++++++++++++++++++-------------------- src/njs_parser.c | 2 +- src/njs_parser_terminal.c | 4 ++-- src/njs_regexp.c | 2 +- src/njs_shell.c | 10 +++++----- src/njs_string.c | 4 ++-- src/njs_timer.c | 4 ++-- src/njs_value.c | 4 ++-- src/njs_vm.c | 4 ++-- src/njs_vmcode.c | 4 ++-- src/test/njs_unit_test.c | 2 +- 18 files changed, 63 insertions(+), 63 deletions(-) diffs (562 lines): diff -r 03008af6253b -r 5f2162f7c3df src/njs_array.c --- a/src/njs_array.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_array.c Mon Aug 12 21:04:50 2019 +0300 @@ -543,7 +543,7 @@ njs_array_prototype_slice_copy(njs_vm_t ret = njs_value_property(vm, this, &name, value); if (ret != NJS_OK) { - *value = njs_value_invalid; + njs_set_invalid(value); } length--; @@ -556,7 +556,7 @@ njs_array_prototype_slice_copy(njs_vm_t value = array->start; do { - *value++ = njs_value_invalid; + njs_set_invalid(value++); length--; } while (length != 0); } @@ -1398,7 +1398,7 @@ njs_array_prototype_for_each(njs_vm_t *v length = njs_min(length, njs_array_len(array)); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -1576,7 +1576,7 @@ njs_array_prototype_find(njs_vm_t *vm, n value = njs_array_start(array)[i]; if (!njs_is_valid(&value)) { - value = njs_value_undefined; + njs_set_undefined(&value); } ret = njs_array_iterator_call(vm, function, this_arg, &value, i, array); @@ -1624,7 +1624,7 @@ njs_array_prototype_find_index(njs_vm_t value = njs_array_start(array)[i]; if (!njs_is_valid(&value)) { - value = njs_value_undefined; + njs_set_undefined(&value); } ret = njs_array_iterator_call(vm, function, this_arg, &value, i, array); @@ -1712,7 +1712,7 @@ njs_array_iterator_reduce(njs_vm_t *vm, /* GC: array elt, array */ - arguments[0] = njs_value_undefined; + njs_set_undefined(&arguments[0]); arguments[1] = *accumulator; arguments[2] = *value; njs_set_number(&arguments[3], n); @@ -1924,7 +1924,7 @@ start: if (njs_is_valid(&start[n])) { if (njs_is_valid(&start[n - 1])) { - arguments[0] = njs_value_undefined; + njs_set_undefined(&arguments[0]); /* GC: array elt, array */ arguments[1] = start[n - 1]; diff -r 03008af6253b -r 5f2162f7c3df src/njs_builtin.c --- a/src/njs_builtin.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_builtin.c Mon Aug 12 21:04:50 2019 +0300 @@ -415,7 +415,7 @@ static njs_int_t njs_prototype_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } diff -r 03008af6253b -r 5f2162f7c3df src/njs_fs.c --- a/src/njs_fs.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_fs.c Mon Aug 12 21:04:50 2019 +0300 @@ -280,13 +280,13 @@ done: return NJS_ERROR; } - arguments[2] = njs_value_undefined; + njs_set_undefined(&arguments[2]); } else { - arguments[1] = njs_value_undefined; + njs_set_undefined(&arguments[1]); } - arguments[0] = njs_value_undefined; + njs_set_undefined(&arguments[0]); ret = njs_function_apply(vm, njs_function(callback), arguments, 3, &vm->retval); @@ -295,7 +295,7 @@ done: return ret; } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; @@ -722,10 +722,10 @@ done: } } else { - arguments[1] = njs_value_undefined; + njs_set_undefined(&arguments[1]); } - arguments[0] = njs_value_undefined; + njs_set_undefined(&arguments[0]); ret = njs_function_apply(vm, njs_function(callback), arguments, 2, &vm->retval); @@ -734,7 +734,7 @@ done: return ret; } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -899,7 +899,7 @@ done: } } else { - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); } return NJS_OK; diff -r 03008af6253b -r 5f2162f7c3df src/njs_function.c --- a/src/njs_function.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_function.c Mon Aug 12 21:04:50 2019 +0300 @@ -399,7 +399,7 @@ njs_function_lambda_frame(njs_vm_t *vm, } while (max_args != 0) { - *value++ = njs_value_undefined; + njs_set_undefined(value++); max_args--; } diff -r 03008af6253b -r 5f2162f7c3df src/njs_generator.c --- a/src/njs_generator.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_generator.c Mon Aug 12 21:04:50 2019 +0300 @@ -2477,7 +2477,7 @@ njs_generate_scope(njs_vm_t *vm, njs_gen value = (njs_value_t *) (p + size); for (n = scope_size - size; n != 0; n -= sizeof(njs_value_t)) { - *value++ = njs_value_undefined; + njs_set_undefined(value++); } if (vm->codes == NULL) { diff -r 03008af6253b -r 5f2162f7c3df src/njs_json.c --- a/src/njs_json.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_json.c Mon Aug 12 21:04:50 2019 +0300 @@ -271,7 +271,7 @@ njs_json_stringify(njs_vm_t *vm, njs_val } } else { - stringify->replacer = njs_value_undefined; + njs_set_undefined(&stringify->replacer); } stringify->space.length = 0; @@ -1470,7 +1470,7 @@ done: * An empty object means empty result. */ if (str.length <= njs_length("{\n\n}")) { - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); goto release; } @@ -2417,7 +2417,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ stringify->nodes = NULL; stringify->last = NULL; stringify->stack.items = 0; - stringify->replacer = njs_value_undefined; + njs_set_undefined(&stringify->replacer); if (!njs_dump_is_object(value)) { ret = njs_dump_value(stringify, value, console); diff -r 03008af6253b -r 5f2162f7c3df src/njs_object.c --- a/src/njs_object.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_object.c Mon Aug 12 21:04:50 2019 +0300 @@ -1327,7 +1327,7 @@ njs_object_freeze(njs_vm_t *vm, njs_valu value = njs_arg(args, nargs, 1); if (!njs_is_object(value)) { - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -1902,7 +1902,7 @@ njs_object_prototype_proto(njs_vm_t *vm, } } - *retval = njs_value_undefined; + njs_set_undefined(retval); return NJS_OK; } diff -r 03008af6253b -r 5f2162f7c3df src/njs_object_prop.c --- a/src/njs_object_prop.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_object_prop.c Mon Aug 12 21:04:50 2019 +0300 @@ -33,8 +33,8 @@ njs_object_prop_alloc(njs_vm_t *vm, cons prop->enumerable = attributes; prop->configurable = attributes; - prop->getter = njs_value_invalid; - prop->setter = njs_value_invalid; + njs_set_invalid(&prop->getter); + njs_set_invalid(&prop->setter); return prop; } @@ -72,7 +72,7 @@ njs_object_property(njs_vm_t *vm, const } while (object != NULL); - *retval = njs_value_undefined; + njs_set_undefined(retval); return NJS_DECLINED; @@ -86,7 +86,7 @@ found: } if (njs_is_undefined(&prop->getter)) { - *retval = njs_value_undefined; + njs_set_undefined(retval); return NJS_OK; } @@ -133,7 +133,7 @@ njs_object_prop_define(njs_vm_t *vm, njs case NJS_OBJECT_PROP_GETTER: prop->getter = *value; - prop->setter = njs_value_invalid; + njs_set_invalid(&prop->setter); prop->enumerable = NJS_ATTRIBUTE_TRUE; prop->configurable = NJS_ATTRIBUTE_TRUE; @@ -141,7 +141,7 @@ njs_object_prop_define(njs_vm_t *vm, njs case NJS_OBJECT_PROP_SETTER: prop->setter = *value; - prop->getter = njs_value_invalid; + njs_set_invalid(&prop->getter); prop->enumerable = NJS_ATTRIBUTE_TRUE; prop->configurable = NJS_ATTRIBUTE_TRUE; @@ -150,15 +150,15 @@ njs_object_prop_define(njs_vm_t *vm, njs if (njs_fast_path(ret == NJS_DECLINED)) { - /* 6.2.5.6 CompletePropertypropriptor */ + /* 6.2.5.6 CompletePropertyDescriptor */ if (njs_is_accessor_descriptor(prop)) { if (!njs_is_valid(&prop->getter)) { - prop->getter = njs_value_undefined; + njs_set_undefined(&prop->getter); } if (!njs_is_valid(&prop->setter)) { - prop->setter = njs_value_undefined; + njs_set_undefined(&prop->setter); } } else { @@ -167,7 +167,7 @@ njs_object_prop_define(njs_vm_t *vm, njs } if (!njs_is_valid(&prop->value)) { - prop->value = njs_value_undefined; + njs_set_undefined(&prop->value); } } @@ -215,7 +215,7 @@ njs_object_prop_define(njs_vm_t *vm, njs if (njs_is_valid(&prop->value)) { *prev->value.data.u.value = prop->value; } else { - *prev->value.data.u.value = njs_value_undefined; + njs_set_undefined(prev->value.data.u.value); } return NJS_OK; @@ -259,18 +259,18 @@ njs_object_prop_define(njs_vm_t *vm, njs */ if (njs_is_data_descriptor(prev)) { - prev->getter = njs_value_undefined; - prev->setter = njs_value_undefined; + njs_set_undefined(&prev->getter); + njs_set_undefined(&prev->setter); - prev->value = njs_value_invalid; + njs_set_invalid(&prev->value); prev->writable = NJS_ATTRIBUTE_UNSET; } else { - prev->value = njs_value_undefined; + njs_set_undefined(&prev->value); prev->writable = NJS_ATTRIBUTE_FALSE; - prev->getter = njs_value_invalid; - prev->setter = njs_value_invalid; + njs_set_invalid(&prev->getter); + njs_set_invalid(&prev->setter); } @@ -390,7 +390,7 @@ njs_descriptor_prop(njs_vm_t *vm, njs_ob } else { /* NJS_DECLINED */ - prop->getter = njs_value_invalid; + njs_set_invalid(&prop->getter); } lhq.key = njs_str_value("set"); @@ -413,7 +413,7 @@ njs_descriptor_prop(njs_vm_t *vm, njs_ob } else { /* NJS_DECLINED */ - prop->setter = njs_value_invalid; + njs_set_invalid(&prop->setter); } lhq.key = njs_str_value("value"); @@ -534,7 +534,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, break; case NJS_DECLINED: - *dest = njs_value_undefined; + njs_set_undefined(dest); return NJS_OK; case NJS_ERROR: diff -r 03008af6253b -r 5f2162f7c3df src/njs_parser.c --- a/src/njs_parser.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_parser.c Mon Aug 12 21:04:50 2019 +0300 @@ -510,7 +510,7 @@ njs_parser_variable_node(njs_vm_t *vm, n switch (type) { case NJS_VARIABLE_VAR: - var->value = njs_value_undefined; + njs_set_undefined(&var->value); break; default: diff -r 03008af6253b -r 5f2162f7c3df src/njs_parser_terminal.c --- a/src/njs_parser_terminal.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_parser_terminal.c Mon Aug 12 21:04:50 2019 +0300 @@ -227,7 +227,7 @@ njs_parser_reference(njs_vm_t *vm, njs_p case NJS_TOKEN_UNDEFINED: njs_thread_log_debug("JS: undefined"); - node->u.value = njs_value_undefined; + njs_set_undefined(&node->u.value); break; case NJS_TOKEN_THIS: @@ -264,7 +264,7 @@ njs_parser_reference(njs_vm_t *vm, njs_p node->token = NJS_TOKEN_GLOBAL_THIS; if (vm->options.module) { - node->u.value = njs_value_undefined; + njs_set_undefined(&node->u.value); break; } diff -r 03008af6253b -r 5f2162f7c3df src/njs_regexp.c --- a/src/njs_regexp.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_regexp.c Mon Aug 12 21:04:50 2019 +0300 @@ -994,7 +994,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs } } else { - array->start[i] = njs_value_undefined; + njs_set_undefined(&array->start[i]); } } diff -r 03008af6253b -r 5f2162f7c3df src/njs_shell.c --- a/src/njs_shell.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_shell.c Mon Aug 12 21:04:50 2019 +0300 @@ -989,7 +989,7 @@ njs_ext_console_log(njs_vm_t *vm, njs_va njs_printf("\n"); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -1021,7 +1021,7 @@ njs_ext_console_dump(njs_vm_t *vm, njs_v njs_printf("\n"); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -1052,7 +1052,7 @@ njs_ext_console_help(njs_vm_t *vm, njs_v njs_printf("\n"); - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -1076,7 +1076,7 @@ njs_ext_console_time(njs_vm_t *vm, njs_v console->time = njs_time(); - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -1116,7 +1116,7 @@ njs_ext_console_time_end(njs_vm_t *vm, n njs_printf("Timer \"default\" doesn?t exist.\n"); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } diff -r 03008af6253b -r 5f2162f7c3df src/njs_string.c --- a/src/njs_string.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_string.c Mon Aug 12 21:04:50 2019 +0300 @@ -3318,7 +3318,7 @@ njs_string_replace_regexp_function(njs_v return NJS_ERROR; } - arguments[0] = njs_value_undefined; + njs_set_undefined(&arguments[0]); /* Matched substring and parenthesized submatch strings. */ for (k = 0, i = 1; i <= n; i++) { @@ -3460,7 +3460,7 @@ njs_string_replace_search_function(njs_v njs_value_t string; njs_value_t arguments[4]; - arguments[0] = njs_value_undefined; + njs_set_undefined(&arguments[0]); /* GC, args[0], args[1] */ diff -r 03008af6253b -r 5f2162f7c3df src/njs_timer.c --- a/src/njs_timer.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_timer.c Mon Aug 12 21:04:50 2019 +0300 @@ -104,7 +104,7 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu njs_lvlhsh_query_t lhq; if (njs_fast_path(nargs < 2) || !njs_is_number(&args[1])) { - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } @@ -123,7 +123,7 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu njs_del_event(vm, event, NJS_EVENT_RELEASE | NJS_EVENT_DELETE); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } diff -r 03008af6253b -r 5f2162f7c3df src/njs_value.c --- a/src/njs_value.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_value.c Mon Aug 12 21:04:50 2019 +0300 @@ -1005,7 +1005,7 @@ njs_value_property(njs_vm_t *vm, njs_val } if (njs_is_undefined(&prop->getter)) { - *retval = njs_value_undefined; + njs_set_undefined(retval); break; } @@ -1036,7 +1036,7 @@ njs_value_property(njs_vm_t *vm, njs_val break; case NJS_DECLINED: - *retval = njs_value_undefined; + njs_set_undefined(retval); return NJS_DECLINED; diff -r 03008af6253b -r 5f2162f7c3df src/njs_vm.c --- a/src/njs_vm.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_vm.c Mon Aug 12 21:04:50 2019 +0300 @@ -180,7 +180,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st njs_arr_reset(vm->backtrace); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); ret = njs_parser(vm, parser, prev); if (njs_slow_path(ret != NJS_OK)) { @@ -374,7 +374,7 @@ njs_vm_init(njs_vm_t *vm) } if (njs_is_null(&vm->retval)) { - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); } return NJS_OK; diff -r 03008af6253b -r 5f2162f7c3df src/njs_vmcode.c --- a/src/njs_vmcode.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/njs_vmcode.c Mon Aug 12 21:04:50 2019 +0300 @@ -552,7 +552,7 @@ next: break; case NJS_VMCODE_VOID: - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); ret = sizeof(njs_vmcode_2addr_t); break; @@ -1436,7 +1436,7 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs retval = &njs_value_false; if (njs_is_object(object)) { - value = njs_value_undefined; + njs_set_undefined(&value); ret = njs_value_property(vm, constructor, &prototype_string, &value); if (njs_slow_path(ret == NJS_ERROR)) { diff -r 03008af6253b -r 5f2162f7c3df src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Aug 12 21:04:49 2019 +0300 +++ b/src/test/njs_unit_test.c Mon Aug 12 21:04:50 2019 +0300 @@ -13940,7 +13940,7 @@ njs_unit_test_method_external(njs_vm_t * r->uri.length); } - vm->retval = njs_value_undefined; + njs_set_undefined(&vm->retval); return NJS_OK; } From balus at foxmail.com Tue Aug 13 03:10:23 2019 From: balus at foxmail.com (Jianyong Chen) Date: Tue, 13 Aug 2019 11:10:23 +0800 Subject: [Patch] flv: add support for time offset In-Reply-To: <20190812113308.GE1877@mdounin.ru> References: <20190812113308.GE1877@mdounin.ru> Message-ID: <2FB294E0-7884-4F03-B3A9-F3C7A6D2A935@foxmail.com> Thank you for your reply and detailed explanation. However, as for the flv module, parsing metadata is not that complex for nginx, cause we just need the two arrays, moreover, in this module we just store the offsets of them. Most importantly, in CDN field, time offset is a necessity and I believe many CDN companies will implement time offset and we could offer this missing functionality. I hope you can give it a second thought. > On Aug 12, 2019, at 7:33 PM, Maxim Dounin wrote: > > Hello! > > On Sun, Aug 11, 2019 at 05:48:55PM +0800, Jianyong Chen wrote: > >> I have been reading nginx source code recently and found that flv module is too >> simple, more specifically, it lacks support for time offset unlike mp4 module does. >> >> However, in real life, the demand for time offset is more common than it for >> byte offset, especially in CDN field. In addition to CDN, many video players use >> time offset to implement drag function. But the original module only supports >> byte offset, so I think it is necessary to add this feature and I have finished it. >> >> To support time offset, I had to parse the metadata, but I haven?t found an >> efficient and elegant solution, so I referred to the nginx-rtmp module in this >> part(Thanks, Roman Arutyunyan). As for byte offset, I just kept it consistent >> with the original module. >> >> I published the project in GitHub, and here is the address: >> https://github.com/BalusChen/nginx-flv-module, where you can find more detail. >> >> By the way, does anyone have interest in aligning keyframes for mp4 module? >> I'm willing to do this job. >> >> And Maxim Dounin, could you please give me some comments or suggestions? >> I'll appreciate it. > > One of the main benefits of the FLV format is that it doesn't > require parsing on the server side, and all known FLV players are > able to provide byte offsets. Trying to add time offsets does not > look like an improvement to me - parsing complex formats is not > something a web server should do. > > Note well that the fact that MP4 cannot work with byte offsets and > instead requires time offsets is not a feature of the MP4 module, > but rather a limitation of the format and players available. > Fortunately, modern brosers are able to use range requests with > MP4 files, potentially making the MP4 module unneeded in the > future. > > [...] > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From lihb2113 at outlook.com Tue Aug 13 03:31:19 2019 From: lihb2113 at outlook.com (=?gb2312?B?wOgguuyyqA==?=) Date: Tue, 13 Aug 2019 03:31:19 +0000 Subject: Add patch in ngx_http_request_body.c which enhances the request body filter module Message-ID: Hello, I found the Nginx is not considered completely for request body filter. So I submit my patch. I hope my patch could be accepted and merged under your careful consideration. Thank you! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: request-body-filter.patch Type: application/octet-stream Size: 1197 bytes Desc: request-body-filter.patch URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Note.md Type: application/octet-stream Size: 696 bytes Desc: Note.md URL: From xeioex at nginx.com Tue Aug 13 13:14:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 13 Aug 2019 13:14:11 +0000 Subject: [njs] Fixed dead store assignment in njs_fs_rename_sync(). Message-ID: details: https://hg.nginx.org/njs/rev/21b7a2d31852 branches: changeset: 1125:21b7a2d31852 user: Dmitry Volyntsev date: Tue Aug 13 15:15:42 2019 +0300 description: Fixed dead store assignment in njs_fs_rename_sync(). Found by clang static analyzer. diffstat: src/njs_fs.c | 38 +++++++++++--------------------------- 1 files changed, 11 insertions(+), 27 deletions(-) diffs (92 lines): diff -r 5f2162f7c3df -r 21b7a2d31852 src/njs_fs.c --- a/src/njs_fs.c Mon Aug 12 21:04:50 2019 +0300 +++ b/src/njs_fs.c Tue Aug 13 15:15:42 2019 +0300 @@ -273,12 +273,8 @@ done: } if (description != 0) { - ret = njs_fs_error(vm, syscall, description, &args[1], errn, - &arguments[1]); - - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + (void) njs_fs_error(vm, syscall, description, &args[1], errn, + &arguments[1]); njs_set_undefined(&arguments[2]); @@ -497,10 +493,8 @@ done: } if (description != 0) { - (void) njs_fs_error(vm, syscall, description, &args[1], errn, + return njs_fs_error(vm, syscall, description, &args[1], errn, &vm->retval); - - return NJS_ERROR; } return NJS_OK; @@ -714,12 +708,8 @@ done: } if (description != 0) { - ret = njs_fs_error(vm, syscall, description, &args[1], errn, - &arguments[1]); - - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + (void) njs_fs_error(vm, syscall, description, &args[1], errn, + &arguments[1]); } else { njs_set_undefined(&arguments[1]); @@ -891,12 +881,8 @@ done: } if (description != 0) { - ret = njs_fs_error(vm, syscall, description, &args[1], errn, - &vm->retval); - - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + return njs_fs_error(vm, syscall, description, &args[1], errn, + &vm->retval); } else { njs_set_undefined(&vm->retval); @@ -935,9 +921,8 @@ njs_fs_rename_sync(njs_vm_t *vm, njs_val ret = rename(old_path, new_path); if (njs_slow_path(ret != 0)) { - ret = njs_fs_error(vm, "rename", strerror(errno), NULL, errno, - &vm->retval); - return NJS_ERROR; + return njs_fs_error(vm, "rename", strerror(errno), NULL, errno, + &vm->retval); } njs_set_undefined(&vm->retval); @@ -972,9 +957,8 @@ njs_fs_fd_read(njs_vm_t *vm, njs_value_t n = read(fd, p, end - p); if (njs_slow_path(n < 0)) { - (void) njs_fs_error(vm, "read", strerror(errno), path, errno, + return njs_fs_error(vm, "read", strerror(errno), path, errno, &vm->retval); - return NJS_ERROR; } p += n; @@ -1101,7 +1085,7 @@ njs_fs_error(njs_vm_t *vm, const char *s njs_set_type_object(retval, error, NJS_OBJECT_ERROR); - return NJS_OK; + return NJS_ERROR; } From xeioex at nginx.com Tue Aug 13 13:14:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 13 Aug 2019 13:14:11 +0000 Subject: [njs] Added detection of address sanitizer. Message-ID: details: https://hg.nginx.org/njs/rev/ab443df0d924 branches: changeset: 1126:ab443df0d924 user: Dmitry Volyntsev date: Tue Aug 13 16:04:10 2019 +0300 description: Added detection of address sanitizer. diffstat: auto/clang | 20 ++++++++++++++++++++ src/test/njs_unit_test.c | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diffs (51 lines): diff -r 21b7a2d31852 -r ab443df0d924 auto/clang --- a/auto/clang Tue Aug 13 15:15:42 2019 +0300 +++ b/auto/clang Tue Aug 13 16:04:10 2019 +0300 @@ -291,6 +291,26 @@ njs_feature_test="int n __attribute__ (( . auto/feature +njs_feature="Address sanitizer" +njs_feature_name=NJS_HAVE_ADDRESS_SANITIZER +njs_feature_run=no +njs_feature_path= +njs_feature_libs= +njs_feature_test="int main(void) { + return + #ifdef __SANITIZE_ADDRESS__ + 0; + #else + #if defined(__has_feature) + #if __has_feature(address_sanitizer) + 0; + #endif + #endif + #endif + }" +. auto/feature + + njs_feature="Memory sanitizer" njs_feature_name=NJS_HAVE_MEMORY_SANITIZER njs_feature_run=yes diff -r 21b7a2d31852 -r ab443df0d924 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 13 15:15:42 2019 +0300 +++ b/src/test/njs_unit_test.c Tue Aug 13 16:04:10 2019 +0300 @@ -4163,7 +4163,7 @@ static njs_unit_test_t njs_test[] = "Array.prototype.fill.call(o, 2).a"), njs_str("4") }, -#if (!NJS_HAVE_MEMORY_SANITIZER) /* MSAN limits stack size */ +#if (!NJS_HAVE_ADDRESS_SANITIZER && !NJS_HAVE_MEMORY_SANITIZER) /* limited stack size */ { njs_str("var o = Object({length: 3});" "Object.defineProperty(o, '0', {set: function(v){this[0] = 2 * v}});" "Array.prototype.fill.call(o, 2)"), @@ -6421,7 +6421,7 @@ static njs_unit_test_t njs_test[] = { njs_str("{ function f() {} { var f }}"), njs_str("SyntaxError: \"f\" has already been declared in 1") }, -#if (!NJS_HAVE_MEMORY_SANITIZER) /* MSAN limits stack size */ +#if (!NJS_HAVE_ADDRESS_SANITIZER && !NJS_HAVE_MEMORY_SANITIZER) /* limited stack size */ { njs_str("function f() { return f() } f()"), njs_str("RangeError: Maximum call stack size exceeded") }, #endif From xeioex at nginx.com Tue Aug 13 13:14:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 13 Aug 2019 13:14:11 +0000 Subject: [njs] Version 0.3.4. Message-ID: details: https://hg.nginx.org/njs/rev/8eadbb3a7c7b branches: changeset: 1127:8eadbb3a7c7b user: Dmitry Volyntsev date: Tue Aug 13 16:13:28 2019 +0300 description: Version 0.3.4. diffstat: CHANGES | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 79 insertions(+), 0 deletions(-) diffs (86 lines): diff -r ab443df0d924 -r 8eadbb3a7c7b CHANGES --- a/CHANGES Tue Aug 13 16:04:10 2019 +0300 +++ b/CHANGES Tue Aug 13 16:13:28 2019 +0300 @@ -1,3 +1,82 @@ + +Changes with njs 0.3.4 13 Aug 2019 + + Core: + *) Feature: added Object shorthand methods and computed property + names. Thanks to ??? (Hong Zhi Dao) and Artem S. Povalyukhin. + + *) Feature: added getter/setter literal support. + Thanks to ??? (Hong Zhi Dao) and Artem S. Povalyukhin. + + *) Feature: added fs.renameSync(). + + *) Feature: added String.prototype.trimStart() and + String.prototype.trimEnd(). + + *) Improvement: added memory-sanitizer support. + + *) Improvement: Unicode case tables updated to version 12.1. + + *) Improvement: added UTF8 validation for string literals. + + *) Bugfix: fixed reading files with zero size in fs.readFileSync(). + + *) Bugfix: extended the list of space separators in + String.prototype.trim(). + + *) Bugfix: fixed using of uninitialized value in + String.prototype.padStart(). + + *) Bugfix: fixed String.prototype.replace() for '$0' and '$&' + replacement string. + + *) Bugfix: fixed String.prototype.replace() for byte strings with + regex argument. + + *) Bugfix: fixed global match in String.prototype.replace() + with regexp argument. + + *) Bugfix: fixed Array.prototype.slice() for primitive types. + + *) Bugfix: fixed heap-buffer-overflow while importing module. + + *) Bugfix: fixed UTF-8 character escaping. + + *) Bugfix: fixed Object.values() and Object.entries() for shared + objects. + + *) Bugfix: fixed uninitialized memory access in + String.prototype.match(). + + *) Bugfix: fixed String.prototype.match() for byte strings with + regex argument. + + *) Bugfix: fixed Array.prototype.lastIndexOf() with undefined + arguments. + + *) Bugfix: fixed String.prototype.substring() with empty substring. + + *) Bugfix: fixed invalid memory access in + String.prototype.substring(). + + *) Bugfix: fixed String.fromCharCode() for code points > 65535 + and NaN. + + *) Bugfix: fixed String.prototype.toLowerCase() and + String.prototype.toUpperCase(). + + *) Bugfix: fixed Error() constructor with no arguments. + + *) Bugfix: fixed "in" operator for values with accessor descriptors. + + *) Bugfix: fixed Object.defineProperty() for non-boolean descriptor + props. + + *) Bugfix: fixed Error.prototype.toString() with UTF8 string + properties. + + *) Bugfix: fixed Error.prototype.toString() with non-string values + for "name" and "message". Changes with njs 0.3.3 25 Jun 2019 From xeioex at nginx.com Tue Aug 13 13:14:12 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 13 Aug 2019 13:14:12 +0000 Subject: [njs] Added tag 0.3.4 for changeset 8eadbb3a7c7b Message-ID: details: https://hg.nginx.org/njs/rev/b55b9f92036f branches: changeset: 1128:b55b9f92036f user: Dmitry Volyntsev date: Tue Aug 13 16:13:53 2019 +0300 description: Added tag 0.3.4 for changeset 8eadbb3a7c7b diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 8eadbb3a7c7b -r b55b9f92036f .hgtags --- a/.hgtags Tue Aug 13 16:13:28 2019 +0300 +++ b/.hgtags Tue Aug 13 16:13:53 2019 +0300 @@ -27,3 +27,4 @@ 1935ab4643fdaec5b4a8c36070f4d2cb8e3799d7 ebfbdb8d8fe2f640d880359575657cb53e38328f 0.3.1 82101d50fff6e4c7a92c0542a3d6026ff7e462fb 0.3.2 c65a4be9867d434ca449a18d868305d5dcd5b91b 0.3.3 +8eadbb3a7c7b7c3426f73adabfa251cd9d296752 0.3.4 From mdounin at mdounin.ru Tue Aug 13 17:00:53 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:00:53 +0000 Subject: [nginx] HTTP/2: reject zero length headers with PROTOCOL_ERROR. Message-ID: details: https://hg.nginx.org/nginx/rev/4f4b83f00cf1 branches: changeset: 7547:4f4b83f00cf1 user: Sergey Kandaurov date: Tue Aug 13 15:43:32 2019 +0300 description: HTTP/2: reject zero length headers with PROTOCOL_ERROR. Fixed uncontrolled memory growth if peer sends a stream of headers with a 0-length header name and 0-length header value. Fix is to reject headers with zero name length. diffstat: src/http/v2/ngx_http_v2.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diffs (29 lines): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -1546,6 +1546,14 @@ ngx_http_v2_state_process_header(ngx_htt header->name.len = h2c->state.field_end - h2c->state.field_start; header->name.data = h2c->state.field_start; + if (header->name.len == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent zero header name length"); + + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_PROTOCOL_ERROR); + } + return ngx_http_v2_state_field_len(h2c, pos, end); } @@ -3249,10 +3257,6 @@ ngx_http_v2_validate_header(ngx_http_req ngx_uint_t i; ngx_http_core_srv_conf_t *cscf; - if (header->name.len == 0) { - return NGX_ERROR; - } - r->invalid_header = 0; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); From mdounin at mdounin.ru Tue Aug 13 17:00:54 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:00:54 +0000 Subject: [nginx] HTTP/2: limited number of DATA frames. Message-ID: details: https://hg.nginx.org/nginx/rev/99257b06b0bd branches: changeset: 7548:99257b06b0bd user: Ruslan Ermilov date: Tue Aug 13 15:43:36 2019 +0300 description: HTTP/2: limited number of DATA frames. Fixed excessive memory growth and CPU usage if stream windows are manipulated in a way that results in generating many small DATA frames. Fix is to limit the number of simultaneously allocated DATA frames. diffstat: src/http/v2/ngx_http_v2.c | 2 ++ src/http/v2/ngx_http_v2.h | 2 ++ src/http/v2/ngx_http_v2_filter_module.c | 22 +++++++++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) diffs (67 lines): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -4369,6 +4369,8 @@ ngx_http_v2_close_stream(ngx_http_v2_str */ pool = stream->pool; + h2c->frames -= stream->frames; + ngx_http_free_request(stream->request, rc); if (pool != h2c->state.pool) { diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -192,6 +192,8 @@ struct ngx_http_v2_stream_s { ngx_buf_t *preread; + ngx_uint_t frames; + ngx_http_v2_out_frame_t *free_frames; ngx_chain_t *free_frame_headers; ngx_chain_t *free_bufs; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -1669,22 +1669,34 @@ static ngx_http_v2_out_frame_t * ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, size_t len, ngx_chain_t *first, ngx_chain_t *last) { - u_char flags; - ngx_buf_t *buf; - ngx_chain_t *cl; - ngx_http_v2_out_frame_t *frame; + u_char flags; + ngx_buf_t *buf; + ngx_chain_t *cl; + ngx_http_v2_out_frame_t *frame; + ngx_http_v2_connection_t *h2c; frame = stream->free_frames; + h2c = stream->connection; if (frame) { stream->free_frames = frame->next; - } else { + } else if (h2c->frames < 10000) { frame = ngx_palloc(stream->request->pool, sizeof(ngx_http_v2_out_frame_t)); if (frame == NULL) { return NULL; } + + stream->frames++; + h2c->frames++; + + } else { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "http2 flood detected"); + + h2c->connection->error = 1; + return NULL; } flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0; From mdounin at mdounin.ru Tue Aug 13 17:00:56 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:00:56 +0000 Subject: [nginx] HTTP/2: limited number of PRIORITY frames. Message-ID: details: https://hg.nginx.org/nginx/rev/45415228990b branches: changeset: 7549:45415228990b user: Ruslan Ermilov date: Tue Aug 13 15:43:40 2019 +0300 description: HTTP/2: limited number of PRIORITY frames. Fixed excessive CPU usage caused by a peer that continuously shuffles priority of streams. Fix is to limit the number of PRIORITY frames. diffstat: src/http/v2/ngx_http_v2.c | 10 ++++++++++ src/http/v2/ngx_http_v2.h | 1 + 2 files changed, 11 insertions(+), 0 deletions(-) diffs (45 lines): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -273,6 +273,7 @@ ngx_http_v2_init(ngx_event_t *rev) h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); h2c->concurrent_pushes = h2scf->concurrent_pushes; + h2c->priority_limit = h2scf->concurrent_streams; h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); if (h2c->pool == NULL) { @@ -1804,6 +1805,13 @@ ngx_http_v2_state_priority(ngx_http_v2_c return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); } + if (--h2c->priority_limit == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent too many PRIORITY frames"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); + } + if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) { return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_priority); @@ -3120,6 +3128,8 @@ ngx_http_v2_create_stream(ngx_http_v2_co h2c->processing++; } + h2c->priority_limit += h2scf->concurrent_streams; + return stream; } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -122,6 +122,7 @@ struct ngx_http_v2_connection_s { ngx_uint_t processing; ngx_uint_t frames; ngx_uint_t idle; + ngx_uint_t priority_limit; ngx_uint_t pushing; ngx_uint_t concurrent_pushes; From mdounin at mdounin.ru Tue Aug 13 17:00:58 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:00:58 +0000 Subject: [nginx] nginx-1.17.3-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/ed4303aa1b31 branches: changeset: 7550:ed4303aa1b31 user: Maxim Dounin date: Tue Aug 13 15:45:56 2019 +0300 description: nginx-1.17.3-RELEASE diffstat: docs/xml/nginx/changes.xml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-) diffs (50 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,46 @@ + + + + +??? ????????????? HTTP/2 ?????? ??? ??????? +?????????? ??????????? ?????? ? ???????? ?????????? +(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516). + + +when using HTTP/2 a client might cause +excessive memory consumption and CPU usage +(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516). + + + + + +??? ????????????? ?????? ? ????? ????? ?????????? ????????? "zero size buf"; +?????? ????????? ? 1.17.2. + + +"zero size buf" alerts might appear in logs when using gzipping; +the bug had appeared in 1.17.2. + + + + + +??? ????????????? ????????? resolver ? SMTP ??????-??????? +? ??????? ???????? ??? ????????? segmentation fault. + + +a segmentation fault might occur in a worker process +if the "resolver" directive was used in SMTP proxy. + + + + + + From mdounin at mdounin.ru Tue Aug 13 17:00:59 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:00:59 +0000 Subject: [nginx] release-1.17.3 tag Message-ID: details: https://hg.nginx.org/nginx/rev/d30b1a99fcd0 branches: changeset: 7551:d30b1a99fcd0 user: Maxim Dounin date: Tue Aug 13 15:45:57 2019 +0300 description: release-1.17.3 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -441,3 +441,4 @@ 0130ca3d58437b3c7c707cdddd813d530c68da9a 054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0 7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1 2fc9f853a6b7cd29dc84e0af2ed3cf78e0da6ca8 release-1.17.2 +ed4303aa1b31a9aad5440640c0840d9d0af45fed release-1.17.3 From mdounin at mdounin.ru Tue Aug 13 17:01:01 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:01 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/9eede9b069f5 branches: stable-1.16 changeset: 7552:9eede9b069f5 user: Maxim Dounin date: Tue Aug 13 15:48:39 2019 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1016000 -#define NGINX_VERSION "1.16.0" +#define nginx_version 1016001 +#define NGINX_VERSION "1.16.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Tue Aug 13 17:01:03 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:03 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: https://hg.nginx.org/nginx/rev/9544d6ed9017 branches: stable-1.16 changeset: 7553:9544d6ed9017 user: Maxim Dounin date: Tue Jun 25 04:47:43 2019 +0300 description: Updated OpenSSL used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -6,7 +6,7 @@ TEMP = tmp CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.1.1b +OPENSSL = openssl-1.1.1c ZLIB = zlib-1.2.11 PCRE = pcre-8.43 From mdounin at mdounin.ru Tue Aug 13 17:01:05 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:05 +0000 Subject: [nginx] HTTP/2: reject zero length headers with PROTOCOL_ERROR. Message-ID: details: https://hg.nginx.org/nginx/rev/b19cd299f37c branches: stable-1.16 changeset: 7554:b19cd299f37c user: Sergey Kandaurov date: Tue Aug 13 15:43:32 2019 +0300 description: HTTP/2: reject zero length headers with PROTOCOL_ERROR. Fixed uncontrolled memory growth if peer sends a stream of headers with a 0-length header name and 0-length header value. Fix is to reject headers with zero name length. diffstat: src/http/v2/ngx_http_v2.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diffs (29 lines): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -1546,6 +1546,14 @@ ngx_http_v2_state_process_header(ngx_htt header->name.len = h2c->state.field_end - h2c->state.field_start; header->name.data = h2c->state.field_start; + if (header->name.len == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent zero header name length"); + + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_PROTOCOL_ERROR); + } + return ngx_http_v2_state_field_len(h2c, pos, end); } @@ -3249,10 +3257,6 @@ ngx_http_v2_validate_header(ngx_http_req ngx_uint_t i; ngx_http_core_srv_conf_t *cscf; - if (header->name.len == 0) { - return NGX_ERROR; - } - r->invalid_header = 0; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); From mdounin at mdounin.ru Tue Aug 13 17:01:06 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:06 +0000 Subject: [nginx] HTTP/2: limited number of DATA frames. Message-ID: details: https://hg.nginx.org/nginx/rev/99b6733876c4 branches: stable-1.16 changeset: 7555:99b6733876c4 user: Ruslan Ermilov date: Tue Aug 13 15:43:36 2019 +0300 description: HTTP/2: limited number of DATA frames. Fixed excessive memory growth and CPU usage if stream windows are manipulated in a way that results in generating many small DATA frames. Fix is to limit the number of simultaneously allocated DATA frames. diffstat: src/http/v2/ngx_http_v2.c | 2 ++ src/http/v2/ngx_http_v2.h | 2 ++ src/http/v2/ngx_http_v2_filter_module.c | 22 +++++++++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) diffs (67 lines): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -4369,6 +4369,8 @@ ngx_http_v2_close_stream(ngx_http_v2_str */ pool = stream->pool; + h2c->frames -= stream->frames; + ngx_http_free_request(stream->request, rc); if (pool != h2c->state.pool) { diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -192,6 +192,8 @@ struct ngx_http_v2_stream_s { ngx_buf_t *preread; + ngx_uint_t frames; + ngx_http_v2_out_frame_t *free_frames; ngx_chain_t *free_frame_headers; ngx_chain_t *free_bufs; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -1663,22 +1663,34 @@ static ngx_http_v2_out_frame_t * ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, size_t len, ngx_chain_t *first, ngx_chain_t *last) { - u_char flags; - ngx_buf_t *buf; - ngx_chain_t *cl; - ngx_http_v2_out_frame_t *frame; + u_char flags; + ngx_buf_t *buf; + ngx_chain_t *cl; + ngx_http_v2_out_frame_t *frame; + ngx_http_v2_connection_t *h2c; frame = stream->free_frames; + h2c = stream->connection; if (frame) { stream->free_frames = frame->next; - } else { + } else if (h2c->frames < 10000) { frame = ngx_palloc(stream->request->pool, sizeof(ngx_http_v2_out_frame_t)); if (frame == NULL) { return NULL; } + + stream->frames++; + h2c->frames++; + + } else { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "http2 flood detected"); + + h2c->connection->error = 1; + return NULL; } flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0; From mdounin at mdounin.ru Tue Aug 13 17:01:08 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:08 +0000 Subject: [nginx] HTTP/2: limited number of PRIORITY frames. Message-ID: details: https://hg.nginx.org/nginx/rev/a23a7e6edac4 branches: stable-1.16 changeset: 7556:a23a7e6edac4 user: Ruslan Ermilov date: Tue Aug 13 15:43:40 2019 +0300 description: HTTP/2: limited number of PRIORITY frames. Fixed excessive CPU usage caused by a peer that continuously shuffles priority of streams. Fix is to limit the number of PRIORITY frames. diffstat: src/http/v2/ngx_http_v2.c | 10 ++++++++++ src/http/v2/ngx_http_v2.h | 1 + 2 files changed, 11 insertions(+), 0 deletions(-) diffs (45 lines): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -273,6 +273,7 @@ ngx_http_v2_init(ngx_event_t *rev) h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); h2c->concurrent_pushes = h2scf->concurrent_pushes; + h2c->priority_limit = h2scf->concurrent_streams; h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); if (h2c->pool == NULL) { @@ -1804,6 +1805,13 @@ ngx_http_v2_state_priority(ngx_http_v2_c return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); } + if (--h2c->priority_limit == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent too many PRIORITY frames"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); + } + if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) { return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_priority); @@ -3120,6 +3128,8 @@ ngx_http_v2_create_stream(ngx_http_v2_co h2c->processing++; } + h2c->priority_limit += h2scf->concurrent_streams; + return stream; } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -122,6 +122,7 @@ struct ngx_http_v2_connection_s { ngx_uint_t processing; ngx_uint_t frames; ngx_uint_t idle; + ngx_uint_t priority_limit; ngx_uint_t pushing; ngx_uint_t concurrent_pushes; From mdounin at mdounin.ru Tue Aug 13 17:01:10 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:10 +0000 Subject: [nginx] nginx-1.16.1-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/123647025f4a branches: stable-1.16 changeset: 7557:123647025f4a user: Maxim Dounin date: Tue Aug 13 15:51:42 2019 +0300 description: nginx-1.16.1-RELEASE diffstat: docs/xml/nginx/changes.xml | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diffs (28 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,24 @@ + + + + +??? ????????????? HTTP/2 ?????? ??? ??????? +?????????? ??????????? ?????? ? ???????? ?????????? +(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516). + + +when using HTTP/2 a client might cause +excessive memory consumption and CPU usage +(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516). + + + + + + From mdounin at mdounin.ru Tue Aug 13 17:01:12 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Aug 2019 17:01:12 +0000 Subject: [nginx] release-1.16.1 tag Message-ID: details: https://hg.nginx.org/nginx/rev/f65ceadcbb2b branches: stable-1.16 changeset: 7558:f65ceadcbb2b user: Maxim Dounin date: Tue Aug 13 15:51:43 2019 +0300 description: release-1.16.1 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -439,3 +439,4 @@ 75f5c7f628411c79c7044102049f7ab4f7a246e7 5155d0296a5ef9841f035920527ffdb771076b44 release-1.15.11 0130ca3d58437b3c7c707cdddd813d530c68da9a release-1.15.12 abd40ce603fa49b2b8b1cca622c96093b1e14275 release-1.16.0 +123647025f4a0d3e8c0f869c1ab1f61b924d59e3 release-1.16.1 From mdounin at mdounin.ru Wed Aug 14 13:09:57 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 14 Aug 2019 16:09:57 +0300 Subject: Add patch in ngx_http_request_body.c which enhances the request body filter module In-Reply-To: References: Message-ID: <20190814130957.GD1877@mdounin.ru> Hello! On Tue, Aug 13, 2019 at 03:31:19AM +0000, ? ?? wrote: > Hello, I found the Nginx is not considered completely for request body filter. So I submit my patch. I hope my patch could be accepted and merged under your careful consideration. > > Thank you! > # HG changeset patch > # User Hongbo Li > # Date 1565599828 -28800 > # Mon Aug 12 16:50:28 2019 +0800 > # Node ID 21e669b708e8e35a1f2d3d3cf72eb62cada0a347 > # Parent fcd92ad76b7bb04b46c4b8fdfe14b6065acadf7d > Allowed self-defined request body filter module return AGAIN. > > When adding self-defined request body filter module, such as upload limit module, Nginx will return NGX_HTTP_INTERNAL_SERVER_ERROR if the added request body filter module return AGAIN at the same time all request body only in buffer (with request_body_no_buffering is 0). This will cause reading request body repeatedly until timeout. We should judge whether it is the last part of request body. > > diff -r fcd92ad76b7b -r 21e669b708e8 src/http/ngx_http_request_body.c > --- a/src/http/ngx_http_request_body.c Thu Aug 01 13:50:07 2019 +0300 > +++ b/src/http/ngx_http_request_body.c Mon Aug 12 16:50:28 2019 +0800 > @@ -306,6 +306,10 @@ > } > } > > + if (rb->rest == 0) { > + break; > + } > + > if (rb->busy != NULL) { > if (r->request_body_no_buffering) { > if (c->read->timer_set) { Request body filters are not allowed to return NGX_AGAIN, and doing so will break things. While your patch might somewhat improve things, it certainly doesn't make it possible for request body filters to return NGX_AGAIN: for example, HTTP/2 code simply doesn't tolerate anything but NGX_OK. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Wed Aug 14 17:24:14 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 14 Aug 2019 17:24:14 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/7361a69324ec branches: changeset: 1129:7361a69324ec user: Dmitry Volyntsev date: Wed Aug 14 20:22:20 2019 +0300 description: Version bump. diffstat: src/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r b55b9f92036f -r 7361a69324ec src/njs.h --- a/src/njs.h Tue Aug 13 16:13:53 2019 +0300 +++ b/src/njs.h Wed Aug 14 20:22:20 2019 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.4" +#define NJS_VERSION "0.3.5" #include /* STDOUT_FILENO, STDERR_FILENO */ From xeioex at nginx.com Wed Aug 14 17:24:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 14 Aug 2019 17:24:15 +0000 Subject: [njs] Fixed [[SetPrototypeOf]]. Message-ID: details: https://hg.nginx.org/njs/rev/857ecc6fbd25 branches: changeset: 1130:857ecc6fbd25 user: Dmitry Volyntsev date: Wed Aug 14 20:22:26 2019 +0300 description: Fixed [[SetPrototypeOf]]. diffstat: src/njs_object.c | 21 ++++++++++++--------- src/test/njs_unit_test.c | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diffs (102 lines): diff -r 7361a69324ec -r 857ecc6fbd25 src/njs_object.c --- a/src/njs_object.c Wed Aug 14 20:22:20 2019 +0300 +++ b/src/njs_object.c Wed Aug 14 20:22:26 2019 +0300 @@ -1846,27 +1846,30 @@ const njs_object_init_t njs_object_cons /* * ES6, 9.1.2: [[SetPrototypeOf]]. */ -static njs_bool_t +static njs_int_t njs_object_set_prototype_of(njs_vm_t *vm, njs_object_t *object, const njs_value_t *value) { const njs_object_t *proto; - proto = njs_is_object(value) ? njs_object(value)->__proto__ - : NULL; + proto = njs_object(value); if (njs_slow_path(object->__proto__ == proto)) { - return 1; + return NJS_OK; + } + + if (!object->extensible) { + return NJS_DECLINED; } if (njs_slow_path(proto == NULL)) { object->__proto__ = NULL; - return 1; + return NJS_OK; } do { if (proto == object) { - return 0; + return NJS_ERROR; } proto = proto->__proto__; @@ -1875,7 +1878,7 @@ njs_object_set_prototype_of(njs_vm_t *vm object->__proto__ = njs_object(value); - return 1; + return NJS_OK; } @@ -1883,7 +1886,7 @@ njs_int_t njs_object_prototype_proto(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { - njs_bool_t ret; + njs_int_t ret; njs_object_t *proto, *object; if (!njs_is_object(value)) { @@ -1896,7 +1899,7 @@ njs_object_prototype_proto(njs_vm_t *vm, if (setval != NULL) { if (njs_is_object(setval) || njs_is_null(setval)) { ret = njs_object_set_prototype_of(vm, object, setval); - if (njs_slow_path(!ret)) { + if (njs_slow_path(ret == NJS_ERROR)) { njs_type_error(vm, "Cyclic __proto__ value"); return NJS_ERROR; } diff -r 7361a69324ec -r 857ecc6fbd25 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Aug 14 20:22:20 2019 +0300 +++ b/src/test/njs_unit_test.c Wed Aug 14 20:22:26 2019 +0300 @@ -8782,9 +8782,31 @@ static njs_unit_test_t njs_test[] = { njs_str("({__proto__:null, a:1}).a"), njs_str("1") }, + { njs_str("Object.getPrototypeOf({__proto__:null})"), + njs_str("null") }, + + { njs_str("Object.getPrototypeOf({__proto__:1}) === Object.prototype"), + njs_str("true") }, + + { njs_str("Object.getPrototypeOf({__proto__:Array.prototype}) === Array.prototype"), + njs_str("true") }, + { njs_str("({__proto__: []}) instanceof Array"), njs_str("true") }, + { njs_str("({__proto__: Array.prototype}) instanceof Array"), + njs_str("true") }, + + { njs_str("var o = {};" + "o.__proto__ = Array.prototype;" + "Object.getPrototypeOf(o) === Array.prototype"), + njs_str("true") }, + + { njs_str("var o = Object.preventExtensions({});" + "o.__proto__ = Array.prototype;" + "Object.getPrototypeOf(o) === Object.prototype"), + njs_str("true") }, + { njs_str("({}).__proto__.constructor === Object"), njs_str("true") }, From xeioex at nginx.com Wed Aug 14 17:24:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 14 Aug 2019 17:24:15 +0000 Subject: [njs] Fixed handling of NJS_DECLINED returned by NJS_PROPERTY_HANDLER. Message-ID: details: https://hg.nginx.org/njs/rev/8b2f303ab48a branches: changeset: 1131:8b2f303ab48a user: Dmitry Volyntsev date: Wed Aug 14 20:22:32 2019 +0300 description: Fixed handling of NJS_DECLINED returned by NJS_PROPERTY_HANDLER. diffstat: src/njs_array.c | 5 +++-- src/njs_object_prop.c | 9 ++++----- src/njs_value.c | 5 +++-- src/njs_value.h | 3 ++- src/njs_vmcode.c | 10 +++++++--- src/test/njs_unit_test.c | 3 +++ 6 files changed, 22 insertions(+), 13 deletions(-) diffs (130 lines): diff -r 857ecc6fbd25 -r 8b2f303ab48a src/njs_array.c --- a/src/njs_array.c Wed Aug 14 20:22:26 2019 +0300 +++ b/src/njs_array.c Wed Aug 14 20:22:32 2019 +0300 @@ -331,8 +331,8 @@ njs_array_length(njs_vm_t *vm, njs_value } while (proto != NULL); if (njs_slow_path(proto == NULL)) { - njs_internal_error(vm, "no array in proto chain"); - return NJS_ERROR; + njs_set_undefined(retval); + return NJS_DECLINED; } array = (njs_array_t *) proto; @@ -342,6 +342,7 @@ njs_array_length(njs_vm_t *vm, njs_value } if (proto->type != NJS_ARRAY) { + njs_set_undefined(retval); return NJS_DECLINED; } diff -r 857ecc6fbd25 -r 8b2f303ab48a src/njs_object_prop.c --- a/src/njs_object_prop.c Wed Aug 14 20:22:26 2019 +0300 +++ b/src/njs_object_prop.c Wed Aug 14 20:22:32 2019 +0300 @@ -324,10 +324,9 @@ done: if (njs_is_valid(&prop->value)) { if (prev->type == NJS_PROPERTY_HANDLER) { if (njs_is_data_descriptor(prev) && prev->writable) { - ret = prev->value.data.u.prop_handler(vm, object, - &prop->value, - &vm->retval); - if (njs_slow_path(ret != NJS_OK)) { + ret = prev->value.data.u.prop_handler(vm, object, &prop->value, + &vm->retval); + if (njs_slow_path(ret == NJS_ERROR)) { return ret; } } @@ -519,7 +518,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, prop = &pq.scratch; ret = prop->value.data.u.prop_handler(vm, value, NULL, &prop->value); - if (njs_slow_path(ret != NJS_OK)) { + if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff -r 857ecc6fbd25 -r 8b2f303ab48a src/njs_value.c --- a/src/njs_value.c Wed Aug 14 20:22:26 2019 +0300 +++ b/src/njs_value.c Wed Aug 14 20:22:32 2019 +0300 @@ -1018,11 +1018,12 @@ njs_value_property(njs_vm_t *vm, njs_val ret = prop->value.data.u.prop_handler(vm, value, NULL, &prop->value); - if (njs_slow_path(ret != NJS_OK)) { + if (njs_slow_path(ret == NJS_ERROR)) { return ret; } *retval = prop->value; + break; default: @@ -1096,7 +1097,7 @@ njs_value_property_set(njs_vm_t *vm, njs if (prop->type == NJS_PROPERTY_HANDLER) { ret = prop->value.data.u.prop_handler(vm, value, setval, &vm->retval); - if (ret != NJS_DECLINED) { + if (njs_slow_path(ret != NJS_DECLINED)) { return ret; } } diff -r 857ecc6fbd25 -r 8b2f303ab48a src/njs_value.h --- a/src/njs_value.h Wed Aug 14 20:22:26 2019 +0300 +++ b/src/njs_value.h Wed Aug 14 20:22:32 2019 +0300 @@ -85,7 +85,8 @@ typedef enum { * njs_prop_handler_t is expected to return: * NJS_OK - handler executed successfully; * NJS_ERROR - some error, vm->retval contains appropriate exception; - * NJS_DECLINED - handler was applied to inappropriate object. + * NJS_DECLINED - handler was applied to inappropriate object, vm->retval + * contains undefined value. */ typedef njs_int_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); diff -r 857ecc6fbd25 -r 8b2f303ab48a src/njs_vmcode.c --- a/src/njs_vmcode.c Wed Aug 14 20:22:26 2019 +0300 +++ b/src/njs_vmcode.c Wed Aug 14 20:22:32 2019 +0300 @@ -1168,11 +1168,15 @@ njs_vmcode_property_init(njs_vm_t *vm, n if (prop->type == NJS_PROPERTY_HANDLER) { ret = prop->value.data.u.prop_handler(vm, value, init, &vm->retval); - if (njs_slow_path(ret != NJS_OK)) { + if (njs_slow_path(ret == NJS_ERROR)) { return ret; } - break; + if (ret == NJS_OK) { + break; + } + + /* NJS_DECLINED */ } } } @@ -1273,7 +1277,7 @@ njs_vmcode_property_delete(njs_vm_t *vm, if (njs_is_external(value)) { ret = prop->value.data.u.prop_handler(vm, value, NULL, NULL); if (njs_slow_path(ret != NJS_OK)) { - return ret; + return NJS_ERROR; } goto done; diff -r 857ecc6fbd25 -r 8b2f303ab48a src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Aug 14 20:22:26 2019 +0300 +++ b/src/test/njs_unit_test.c Wed Aug 14 20:22:32 2019 +0300 @@ -8807,6 +8807,9 @@ static njs_unit_test_t njs_test[] = "Object.getPrototypeOf(o) === Object.prototype"), njs_str("true") }, + { njs_str("var o = {__proto__: Array.prototype, length:3}; o.fill('a')[2]"), + njs_str("a") }, + { njs_str("({}).__proto__.constructor === Object"), njs_str("true") }, From dob-devel at dob.sk Thu Aug 15 16:25:09 2019 From: dob-devel at dob.sk (Samuel Behan) Date: Thu, 15 Aug 2019 18:25:09 +0200 Subject: [PATCH] xslt: return http status code from XSLT via variable Message-ID: # HG changeset patch # User Samuel Behan # Date 1565880799 -7200 # Thu Aug 15 16:53:19 2019 +0200 # Node ID bd497930fa90aee4a5c3d90917c6706fe93b73be # Parent d30b1a99fcd053def84517d47654767548c827c9 xslt: return http status code from XSLT via variable This patch introduces possibility to modify http status code of the response using xslt variable named HTTP_STATUS_CODE. This is usefull ie. when processing results from some search engine (SOLR in my case) and when 0 matching results has been found the page is able to return 'hard' 404 response. Example usage: diff -r d30b1a99fcd0 -r bd497930fa90 src/http/modules/ngx_http_xslt_filter_module.c --- a/src/http/modules/ngx_http_xslt_filter_module.c Tue Aug 13 15:45:57 2019 +0300 +++ b/src/http/modules/ngx_http_xslt_filter_module.c Thu Aug 15 16:53:19 2019 +0200 @@ -491,9 +491,11 @@ int len, rc, doc_type; u_char *type, *encoding; ngx_buf_t *b; + ngx_int_t status; ngx_uint_t i; - xmlChar *buf; + xmlChar *buf, *status_str; xmlDocPtr doc, res; + xmlXPathObjectPtr obj; ngx_http_xslt_sheet_t *sheet; ngx_http_xslt_filter_loc_conf_t *conf; @@ -536,6 +538,31 @@ ctx->params.elts, NULL, NULL, ctx->transform); + obj = xsltVariableLookup(ctx->transform, + (const xmlChar *) "HTTP_STATUS_CODE", + NULL); + if (obj) { + status_str = xmlXPathCastToString(obj); + xmlXPathFreeObject(obj); + + if (status_str) { + status = strtol((const char *) status_str, NULL, 10); + xmlFree(status_str); + + if (status <= 99 + || status >= 1000) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "xslt response var HTTP_STATUS_CODE value invalid"); + return NULL; + + } else if (r->headers_out.status != (ngx_uint_t) status) { + r->headers_out.status = (ngx_uint_t) status; + r->headers_out.status_line.len = 0; + } + } + } + xsltFreeTransformContext(ctx->transform); xmlFreeDoc(doc); From xeioex at nginx.com Thu Aug 15 16:37:35 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 15 Aug 2019 16:37:35 +0000 Subject: [njs] Fixed module importing using require(). Message-ID: details: https://hg.nginx.org/njs/rev/b79a22d6d7f3 branches: changeset: 1132:b79a22d6d7f3 user: Dmitry Volyntsev date: Thu Aug 15 19:22:01 2019 +0300 description: Fixed module importing using require(). Previously, require() did not make a mutable copy of imported module. As a result, cloned VMs could change a shared module object making module.object->hash inconsistent. Before 04d7a5d93ae6, the problem manifested itself only in "PROP GET" operations, for example, using "require('fs').renameSync", because njs_value_property() makes a mutable copy of shared methods in module.object->hash. After 04d7a5d93ae6, "METHOD CALL" operations, such as "require('fs').renameSync()", now have the same problem as in "PROP GET". Importing modules using "import" statement is not affected, because for it "OBJECT COPY" instruction is generated, which makes a mutable copy of imported module object. The fix is to make a mutable copy of a shared module in require(). This closes #206 issue on Github. diffstat: src/njs_module.c | 18 ++++++++++++--- src/test/njs_unit_test.c | 52 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 58 insertions(+), 12 deletions(-) diffs (134 lines): diff -r 8b2f303ab48a -r b79a22d6d7f3 src/njs_module.c --- a/src/njs_module.c Wed Aug 14 20:22:32 2019 +0300 +++ b/src/njs_module.c Thu Aug 15 19:22:01 2019 +0300 @@ -503,9 +503,10 @@ njs_module_insert(njs_vm_t *vm, njs_modu njs_int_t -njs_module_require(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused) +njs_module_require(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) { + njs_object_t *object; njs_module_t *module; njs_lvlhsh_query_t lhq; @@ -520,9 +521,18 @@ njs_module_require(njs_vm_t *vm, njs_val if (njs_lvlhsh_find(&vm->modules_hash, &lhq) == NJS_OK) { module = lhq.value; - module->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object; - njs_set_object(&vm->retval, &module->object); + object = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_t)); + if (njs_slow_path(object == NULL)) { + njs_memory_error(vm); + return NJS_ERROR; + } + + *object = module->object; + object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT].object; + object->shared = 0; + + njs_set_object(&vm->retval, object); return NJS_OK; } diff -r 8b2f303ab48a -r b79a22d6d7f3 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Aug 14 20:22:32 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Aug 15 19:22:01 2019 +0300 @@ -13489,6 +13489,22 @@ static njs_unit_test_t njs_module_test[ }; +static njs_unit_test_t njs_shared_test[] = +{ + { njs_str("var cr = require('crypto'); cr.createHash"), + njs_str("[object Function]") }, + + { njs_str("var cr = require('crypto'); cr.createHash('md5')"), + njs_str("[object Hash]") }, + + { njs_str("import cr from 'crypto'; cr.createHash"), + njs_str("[object Function]") }, + + { njs_str("import cr from 'crypto'; cr.createHash('md5')"), + njs_str("[object Hash]") }, +}; + + static njs_unit_test_t njs_tz_test[] = { { njs_str("var d = new Date(1); d = d + ''; d.slice(0, 33)"), @@ -14278,6 +14294,7 @@ typedef struct { njs_bool_t disassemble; njs_bool_t verbose; njs_bool_t module; + njs_uint_t repeat; } njs_opts_t; @@ -14308,7 +14325,7 @@ njs_unit_test(njs_unit_test_t tests[], s njs_vm_t *vm, *nvm; njs_int_t ret; njs_str_t s; - njs_uint_t i; + njs_uint_t i, repeat; njs_stat_t prev; njs_bool_t success; njs_vm_opt_t options; @@ -14350,13 +14367,21 @@ njs_unit_test(njs_unit_test_t tests[], s njs_disassembler(vm); } - nvm = njs_vm_clone(vm, NULL); - if (nvm == NULL) { - njs_printf("njs_vm_clone() failed\n"); - goto done; - } - - ret = njs_vm_start(nvm); + repeat = opts->repeat; + + do { + if (nvm != NULL) { + njs_vm_destroy(nvm); + } + + nvm = njs_vm_clone(vm, NULL); + if (nvm == NULL) { + njs_printf("njs_vm_clone() failed\n"); + goto done; + } + + ret = njs_vm_start(nvm); + } while (--repeat != 0); if (njs_vm_retval_string(nvm, &s) != NJS_OK) { njs_printf("njs_vm_retval_string() failed\n"); @@ -14844,6 +14869,8 @@ main(int argc, char **argv) njs_memzero(&stat, sizeof(njs_stat_t)); + opts.repeat = 1; + ret = njs_unit_test(njs_test, njs_nitems(njs_test), "script tests", &opts, &stat); if (ret != NJS_OK) { @@ -14878,6 +14905,15 @@ main(int argc, char **argv) return ret; } + opts.module = 0; + opts.repeat = 128; + + ret = njs_unit_test(njs_shared_test, njs_nitems(njs_shared_test), + "shared tests", &opts, &stat); + if (ret != NJS_OK) { + return ret; + } + njs_printf("TOTAL: %s [%ui/%ui]\n", stat.failed ? "FAILED" : "PASSED", stat.passed, stat.passed + stat.failed); From xeioex at nginx.com Thu Aug 15 16:37:35 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 15 Aug 2019 16:37:35 +0000 Subject: [njs] Version 0.3.5. Message-ID: details: https://hg.nginx.org/njs/rev/b7fa83f27f1b branches: changeset: 1133:b7fa83f27f1b user: Dmitry Volyntsev date: Thu Aug 15 19:36:39 2019 +0300 description: Version 0.3.5. diffstat: CHANGES | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diffs (14 lines): diff -r b79a22d6d7f3 -r b7fa83f27f1b CHANGES --- a/CHANGES Thu Aug 15 19:22:01 2019 +0300 +++ b/CHANGES Thu Aug 15 19:36:39 2019 +0300 @@ -1,3 +1,10 @@ + +Changes with njs 0.3.5 15 Aug 2019 + Core: + *) Bugfix: fixed module importing using require(). The bug was + introduced in 0.3.4. + + *) Bugfix: fixed [[SetPrototypeOf]]. Changes with njs 0.3.4 13 Aug 2019 From xeioex at nginx.com Thu Aug 15 16:37:35 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 15 Aug 2019 16:37:35 +0000 Subject: [njs] Added tag 0.3.5 for changeset b7fa83f27f1b Message-ID: details: https://hg.nginx.org/njs/rev/5e77219b529a branches: changeset: 1134:5e77219b529a user: Dmitry Volyntsev date: Thu Aug 15 19:36:57 2019 +0300 description: Added tag 0.3.5 for changeset b7fa83f27f1b diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r b7fa83f27f1b -r 5e77219b529a .hgtags --- a/.hgtags Thu Aug 15 19:36:39 2019 +0300 +++ b/.hgtags Thu Aug 15 19:36:57 2019 +0300 @@ -28,3 +28,4 @@ ebfbdb8d8fe2f640d880359575657cb53e38328f 82101d50fff6e4c7a92c0542a3d6026ff7e462fb 0.3.2 c65a4be9867d434ca449a18d868305d5dcd5b91b 0.3.3 8eadbb3a7c7b7c3426f73adabfa251cd9d296752 0.3.4 +b7fa83f27f1b64443b88c990e1851f59583b2182 0.3.5 From arut at nginx.com Fri Aug 16 14:24:31 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 16 Aug 2019 17:24:31 +0300 Subject: cache: move open to thread pool In-Reply-To: References: <9aef70ef-db5f-d3af-bb09-44848477fab2@nginx.com> <20190722140523.GU61550@Romans-MacBook-Air.local> Message-ID: <20190816142431.GH61550@Romans-MacBook-Air.local> Hi, On Wed, Jul 24, 2019 at 11:47:19AM +0800, ??? wrote: > Hi, I found an issue with the patch. > > 1. Reproduce > (/usr/local/nginx/html/5M.txt, Just making `ngx_http_set_write_handler` be > called.) > > telnet localhost 80 > GET /5M.txt HTTP/1.1 > HOST: 1.1.1.1 > > -- response-- > > GET /5M.txt HTTP/1.1 > HOST: 1.1.1.1 > > --50 error-- /* happened in keepalive */ Thanks for reporting this. > 2. Reason > It happens in the case of keepalive. > Since `ngx_http_set_write_handler` is called, c->write is active and ready, > after receiving http request: > ngx_http_static_handler is called > { > ngx_http_static_send(); // task has been added thread pool, but its > event is not complete. > r->write_event_handler = ngx_http_static_write_event_handler; > } > And the epoll write event is triggered. So > ngx_http_static_write_event_handler is called again. > But task->event.active is true. ngx_thread_task_post() will fail. > Throws "task #%ui already active". The problem only manifests itself with epoll. After both EPOLLIN and EPOLLOUT for the same socket are registered in epoll, EPOLLOUT is reported along with EPOLLIN despite the fact that only the read state of the socket changed but the write state didn't (socket was and is writable). This is not a problem by itself, but it helped to find the problem with this patch. While thread task is in progress, calling ngx_http_static_write_event_handler() resulted in posting the task again, which produced the error. > 3. Early patch. > ``` > diff -r bd11e3399021 src/http/modules/ngx_http_static_module.c > --- a/src/http/modules/ngx_http_static_module.c Tue Oct 30 15:00:49 2018 > +0300 > +++ b/src/http/modules/ngx_http_static_module.c Tue Jul 23 23:46:22 2019 > -0400 > @@ -318,6 +318,12 @@ ngx_http_static_write_event_handler(ngx_ > { > ngx_int_t rc; > > + if (r->open_file_info.thread_task != NULL > + && r->open_file_info.thread_task->event.complete == 0) > + { > + return; > + } > + > rc = ngx_http_static_send(r); > > if (rc != NGX_DONE) { Similar problem in thread read is prevented by checking the flag r->aio. I did the same for thread open (see attachment). > ``` > > Thanks. > > > On Mon, Jul 22, 2019 at 10:05 PM Roman Arutyunyan wrote: > > > Hi, > > > > On Sat, Jul 20, 2019 at 09:44:25AM +0800, ??? wrote: > > > > The patch wasn't updated since that but I suspect it could be still > > > applied to nginx, maybe with some minor tweaks. > > > > > > We still appreciate your work. > > > > > > BTW, are the patches in the attachment up to date? > > > If not, can you share the latest patch? > > > > We had no patches since november 1, 2018. The last patch is in this > > message: > > > > http://mailman.nginx.org/pipermail/nginx-devel/2018-November/011538.html > > > > > We are happy to apply it and feedback if possible. > > > When there are many static files and accesses, do you think it will works > > > very well? > > > > We didn't have much feedback so far. So we would definitely appreciate > > your > > contribution to testing it. > > > > > On Sat, Jul 20, 2019 at 2:42 AM Maxim Konovalov wrote: > > > > > > > Hi hongzhidao, > > > > > > > > The patch wasn't merged as we didn't see much interest and real > > > > technical feedback from potential testers. > > > > > > > > The code adds additional complexity to the nginx core with all > > > > associated costs of maintaining the code virtually forever. In the > > > > same time at this point it brings no measurable value to the > > > > community. At least, we haven't seen any proofs that it does. > > > > > > > > The patch wasn't updated since that but I suspect it could be still > > > > applied to nginx, maybe with some minor tweaks. > > > > > > > > Maxim > > > > > > > > On 19/07/2019 18:26, ??? wrote: > > > > > Hi. > > > > > Will this patch be merged into the main branch? > > > > > What is the latest patch? We can help with the test. > > > > > Thanks. > > > > > > > > > > On Sat, Feb 9, 2019 at 6:40 AM Ka-Hing Cheung via nginx-devel > > > > > > wrote: > > > > > > > > > > Unfortunately our test colo is not setup to do performance > > testing > > > > > (the traffic it receives varies too much). We do intend to merge > > > > > this > > > > > to our production colos but there's no timeline yet. > > > > > > > > > > Yuchen (CC'ed) will be the main contact from now on as today is > > my > > > > > last day at Cloudflare. > > > > > > > > > > - Ka-Hing > > > > > > > > > > On Thu, Feb 7, 2019 at 5:39 AM Maxim Konovalov > > > > > wrote: > > > > > > > > > > > > Great. Thanks for the testing! > > > > > > > > > > > > Did you see any measurable perf. metrics changes comparing to > > your > > > > > > aio open implementation or comparing to nginx without aio open > > > > > support? > > > > > > > > > > > > We are still waiting for additional input from another tester, > > who > > > > > > expressed interest before. > > > > > > > > > > > > Thanks, > > > > > > > > > > > > Maxim > > > > > > > > > > > > On 07/02/2019 00:19, Ka-Hing Cheung wrote: > > > > > > > This has been running in our test colo for the past week > > > > > with no ill effects. > > > > > > > > > > > > > > On Wed, Jan 23, 2019 at 4:39 AM Maxim Konovalov > > > > > > wrote: > > > > > > >> > > > > > > >> Hi Ka-Hing, > > > > > > >> > > > > > > >> Roman told me that the delta is because of your changes. > > > > > > >> > > > > > > >> Thanks for your time on that. Waiting for your testing > > > > > results. > > > > > > >> > > > > > > >> Maxim > > > > > > >> > > > > > > >> On 22/01/2019 22:34, Ka-Hing Cheung via nginx-devel wrote: > > > > > > >>> I spoke too soon, just realized our test colo is running > > > > > the patches > > > > > > >>> without aio_open on. Flipping that switch now. > > > > > > >>> > > > > > > >>> Also, including the patch that we applied on top in > > > > > addition to the > > > > > > >>> massaging we did to resolve conflicts. I haven't dug too > > > > > deep to see > > > > > > >>> if stock nginx also requires similar changes or they are > > only > > > > > > >>> necessary because of our other nginx changes: > > > > > > >>> > > > > > > >> [...] > > > > > > >> > > > > > > >> -- > > > > > > >> Maxim Konovalov > > > > > > > > > > > > > > > > > > -- > > > > > > Maxim Konovalov > > > > > _______________________________________________ > > > > > nginx-devel mailing list > > > > > nginx-devel at nginx.org > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > > > > > > > > _______________________________________________ > > > > > nginx-devel mailing list > > > > > nginx-devel at nginx.org > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > > > > > > > > > > -- > > > > Maxim Konovalov > > > > > > > > > _______________________________________________ > > > nginx-devel mailing list > > > nginx-devel at nginx.org > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > -- > > Roman Arutyunyan > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman Arutyunyan -------------- next part -------------- diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -318,6 +318,10 @@ ngx_http_static_write_event_handler(ngx_ { ngx_int_t rc; + if (r->aio) { + return; + } + rc = ngx_http_static_send(r); if (rc != NGX_DONE) { From hongzhidao at gmail.com Fri Aug 16 14:50:53 2019 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Fri, 16 Aug 2019 22:50:53 +0800 Subject: cache: move open to thread pool In-Reply-To: <20190816142431.GH61550@Romans-MacBook-Air.local> References: <9aef70ef-db5f-d3af-bb09-44848477fab2@nginx.com> <20190722140523.GU61550@Romans-MacBook-Air.local> <20190816142431.GH61550@Romans-MacBook-Air.local> Message-ID: Great job, the patch works well. On Fri, Aug 16, 2019 at 10:24 PM Roman Arutyunyan wrote: > Hi, > > On Wed, Jul 24, 2019 at 11:47:19AM +0800, ??? wrote: > > Hi, I found an issue with the patch. > > > > 1. Reproduce > > (/usr/local/nginx/html/5M.txt, Just making `ngx_http_set_write_handler` > be > > called.) > > > > telnet localhost 80 > > GET /5M.txt HTTP/1.1 > > HOST: 1.1.1.1 > > > > -- response-- > > > > GET /5M.txt HTTP/1.1 > > HOST: 1.1.1.1 > > > > --50 error-- /* happened in keepalive */ > > Thanks for reporting this. > > > 2. Reason > > It happens in the case of keepalive. > > Since `ngx_http_set_write_handler` is called, c->write is active and > ready, > > after receiving http request: > > ngx_http_static_handler is called > > { > > ngx_http_static_send(); // task has been added thread pool, but its > > event is not complete. > > r->write_event_handler = ngx_http_static_write_event_handler; > > } > > And the epoll write event is triggered. So > > ngx_http_static_write_event_handler is called again. > > But task->event.active is true. ngx_thread_task_post() will fail. > > Throws "task #%ui already active". > > The problem only manifests itself with epoll. After both EPOLLIN and > EPOLLOUT > for the same socket are registered in epoll, EPOLLOUT is reported along > with > EPOLLIN despite the fact that only the read state of the socket changed > but the > write state didn't (socket was and is writable). This is not a problem by > itself, but it helped to find the problem with this patch. > > While thread task is in progress, calling > ngx_http_static_write_event_handler() > resulted in posting the task again, which produced the error. > > > 3. Early patch. > > ``` > > diff -r bd11e3399021 src/http/modules/ngx_http_static_module.c > > --- a/src/http/modules/ngx_http_static_module.c Tue Oct 30 15:00:49 2018 > > +0300 > > +++ b/src/http/modules/ngx_http_static_module.c Tue Jul 23 23:46:22 2019 > > -0400 > > @@ -318,6 +318,12 @@ ngx_http_static_write_event_handler(ngx_ > > { > > ngx_int_t rc; > > > > + if (r->open_file_info.thread_task != NULL > > + && r->open_file_info.thread_task->event.complete == 0) > > + { > > + return; > > + } > > + > > rc = ngx_http_static_send(r); > > > > if (rc != NGX_DONE) { > > Similar problem in thread read is prevented by checking the flag r->aio. > I did the same for thread open (see attachment). > > > ``` > > > > Thanks. > > > > > > On Mon, Jul 22, 2019 at 10:05 PM Roman Arutyunyan > wrote: > > > > > Hi, > > > > > > On Sat, Jul 20, 2019 at 09:44:25AM +0800, ??? wrote: > > > > > The patch wasn't updated since that but I suspect it could be still > > > > applied to nginx, maybe with some minor tweaks. > > > > > > > > We still appreciate your work. > > > > > > > > BTW, are the patches in the attachment up to date? > > > > If not, can you share the latest patch? > > > > > > We had no patches since november 1, 2018. The last patch is in this > > > message: > > > > > > > http://mailman.nginx.org/pipermail/nginx-devel/2018-November/011538.html > > > > > > > We are happy to apply it and feedback if possible. > > > > When there are many static files and accesses, do you think it will > works > > > > very well? > > > > > > We didn't have much feedback so far. So we would definitely appreciate > > > your > > > contribution to testing it. > > > > > > > On Sat, Jul 20, 2019 at 2:42 AM Maxim Konovalov > wrote: > > > > > > > > > Hi hongzhidao, > > > > > > > > > > The patch wasn't merged as we didn't see much interest and real > > > > > technical feedback from potential testers. > > > > > > > > > > The code adds additional complexity to the nginx core with all > > > > > associated costs of maintaining the code virtually forever. In the > > > > > same time at this point it brings no measurable value to the > > > > > community. At least, we haven't seen any proofs that it does. > > > > > > > > > > The patch wasn't updated since that but I suspect it could be still > > > > > applied to nginx, maybe with some minor tweaks. > > > > > > > > > > Maxim > > > > > > > > > > On 19/07/2019 18:26, ??? wrote: > > > > > > Hi. > > > > > > Will this patch be merged into the main branch? > > > > > > What is the latest patch? We can help with the test. > > > > > > Thanks. > > > > > > > > > > > > On Sat, Feb 9, 2019 at 6:40 AM Ka-Hing Cheung via nginx-devel > > > > > > > wrote: > > > > > > > > > > > > Unfortunately our test colo is not setup to do performance > > > testing > > > > > > (the traffic it receives varies too much). We do intend to > merge > > > > > > this > > > > > > to our production colos but there's no timeline yet. > > > > > > > > > > > > Yuchen (CC'ed) will be the main contact from now on as today > is > > > my > > > > > > last day at Cloudflare. > > > > > > > > > > > > - Ka-Hing > > > > > > > > > > > > On Thu, Feb 7, 2019 at 5:39 AM Maxim Konovalov < > maxim at nginx.com > > > > > > > wrote: > > > > > > > > > > > > > > Great. Thanks for the testing! > > > > > > > > > > > > > > Did you see any measurable perf. metrics changes comparing > to > > > your > > > > > > > aio open implementation or comparing to nginx without aio > open > > > > > > support? > > > > > > > > > > > > > > We are still waiting for additional input from another > tester, > > > who > > > > > > > expressed interest before. > > > > > > > > > > > > > > Thanks, > > > > > > > > > > > > > > Maxim > > > > > > > > > > > > > > On 07/02/2019 00:19, Ka-Hing Cheung wrote: > > > > > > > > This has been running in our test colo for the past week > > > > > > with no ill effects. > > > > > > > > > > > > > > > > On Wed, Jan 23, 2019 at 4:39 AM Maxim Konovalov > > > > > > > wrote: > > > > > > > >> > > > > > > > >> Hi Ka-Hing, > > > > > > > >> > > > > > > > >> Roman told me that the delta is because of your changes. > > > > > > > >> > > > > > > > >> Thanks for your time on that. Waiting for your testing > > > > > > results. > > > > > > > >> > > > > > > > >> Maxim > > > > > > > >> > > > > > > > >> On 22/01/2019 22:34, Ka-Hing Cheung via nginx-devel > wrote: > > > > > > > >>> I spoke too soon, just realized our test colo is > running > > > > > > the patches > > > > > > > >>> without aio_open on. Flipping that switch now. > > > > > > > >>> > > > > > > > >>> Also, including the patch that we applied on top in > > > > > > addition to the > > > > > > > >>> massaging we did to resolve conflicts. I haven't dug > too > > > > > > deep to see > > > > > > > >>> if stock nginx also requires similar changes or they > are > > > only > > > > > > > >>> necessary because of our other nginx changes: > > > > > > > >>> > > > > > > > >> [...] > > > > > > > >> > > > > > > > >> -- > > > > > > > >> Maxim Konovalov > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > Maxim Konovalov > > > > > > _______________________________________________ > > > > > > nginx-devel mailing list > > > > > > nginx-devel at nginx.org > > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > > nginx-devel mailing list > > > > > > nginx-devel at nginx.org > > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > > > > > > > > > > > > > > -- > > > > > Maxim Konovalov > > > > > > > > > > > > _______________________________________________ > > > > nginx-devel mailing list > > > > nginx-devel at nginx.org > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > > -- > > > Roman Arutyunyan > > > _______________________________________________ > > > nginx-devel mailing list > > > nginx-devel at nginx.org > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > -- > Roman Arutyunyan > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Fri Aug 16 16:21:16 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 16 Aug 2019 16:21:16 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/26281dcecfbc branches: changeset: 7559:26281dcecfbc user: Maxim Dounin date: Fri Aug 16 18:16:14 2019 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1017003 -#define NGINX_VERSION "1.17.3" +#define nginx_version 1017004 +#define NGINX_VERSION "1.17.4" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Fri Aug 16 16:21:18 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 16 Aug 2019 16:21:18 +0000 Subject: [nginx] SSL: lowered log level for WSAECONNABORTED errors on Windows. Message-ID: details: https://hg.nginx.org/nginx/rev/2432a687e789 branches: changeset: 7560:2432a687e789 user: Maxim Dounin date: Fri Aug 16 18:16:21 2019 +0300 description: SSL: lowered log level for WSAECONNABORTED errors on Windows. Winsock uses ECONNABORTED instead of ECONNRESET in some cases. For non-SSL connections this is already handled since baad3036086e. Reported at http://mailman.nginx.org/pipermail/nginx-ru/2019-August/062363.html. diffstat: src/event/ngx_event_openssl.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -2814,6 +2814,9 @@ ngx_ssl_connection_error(ngx_connection_ if (sslerr == SSL_ERROR_SYSCALL) { if (err == NGX_ECONNRESET +#if (NGX_WIN32) + || err == NGX_ECONNABORTED +#endif || err == NGX_EPIPE || err == NGX_ENOTCONN || err == NGX_ETIMEDOUT From pluknet at nginx.com Mon Aug 19 14:45:36 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 19 Aug 2019 14:45:36 +0000 Subject: [nginx] HTTP/2: discard remaining request body after redirect. Message-ID: details: https://hg.nginx.org/nginx/rev/9f1f9d6e056a branches: changeset: 7561:9f1f9d6e056a user: Sergey Kandaurov date: Mon Aug 19 15:16:06 2019 +0300 description: HTTP/2: discard remaining request body after redirect. Previously, if unbuffered request body reading wasn't finished before the request was redirected to a different location using error_page or X-Accel-Redirect, and the request body is read again, this could lead to disastrous effects, such as a duplicate post_handler call or "http request count is zero" alert followed by a segmentation fault. This happened in the following configuration (ticket #1819): location / { proxy_request_buffering off; proxy_pass http://bad; proxy_intercept_errors on; error_page 502 = /error; } location /error { proxy_pass http://backend; } diffstat: src/http/v2/ngx_http_v2.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diffs (28 lines): diff -r 2432a687e789 -r 9f1f9d6e056a src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Fri Aug 16 18:16:21 2019 +0300 +++ b/src/http/v2/ngx_http_v2.c Mon Aug 19 15:16:06 2019 +0300 @@ -947,6 +947,15 @@ ngx_http_v2_state_read_data(ngx_http_v2_ return ngx_http_v2_state_skip_padded(h2c, pos, end); } + r = stream->request; + + if (r->reading_body && !r->request_body_no_buffering) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "skipping http2 DATA frame"); + + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + size = end - pos; if (size >= h2c->state.length) { @@ -954,8 +963,6 @@ ngx_http_v2_state_read_data(ngx_http_v2_ stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; } - r = stream->request; - if (r->request_body) { rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); From xeioex at nginx.com Tue Aug 20 17:51:52 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Aug 2019 17:51:52 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/e848c0ee1238 branches: changeset: 1135:e848c0ee1238 user: Dmitry Volyntsev date: Tue Aug 20 20:51:33 2019 +0300 description: Version bump. diffstat: src/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5e77219b529a -r e848c0ee1238 src/njs.h --- a/src/njs.h Thu Aug 15 19:36:57 2019 +0300 +++ b/src/njs.h Tue Aug 20 20:51:33 2019 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.5" +#define NJS_VERSION "0.3.6" #include /* STDOUT_FILENO, STDERR_FILENO */ From xeioex at nginx.com Tue Aug 20 17:51:53 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Aug 2019 17:51:53 +0000 Subject: [njs] Using "printf" instead of "echo -n" for portability. Message-ID: details: https://hg.nginx.org/njs/rev/7b1a00168b25 branches: changeset: 1136:7b1a00168b25 user: Dmitry Volyntsev date: Tue Aug 20 20:51:39 2019 +0300 description: Using "printf" instead of "echo -n" for portability. This closes #205 issue on Github. diffstat: auto/cc | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ auto/clang | 162 --------------------------------------------------------- auto/deps | 12 ++-- auto/echo | 12 ---- auto/expect | 10 +- auto/feature | 24 ++++---- auto/make | 16 ++-- auto/os | 10 +--- auto/pcre | 8 +- auto/readline | 2 +- configure | 1 + 11 files changed, 202 insertions(+), 219 deletions(-) diffs (635 lines): diff -r e848c0ee1238 -r 7b1a00168b25 auto/cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/cc Tue Aug 20 20:51:39 2019 +0300 @@ -0,0 +1,164 @@ + +# Copyright (C) Igor Sysoev +# Copyright (C) NGINX, Inc. + + +echo checking for C compiler: $CC +cat << END >> $NJS_AUTOCONF_ERR +---------------------------------------- +checking for C compiler: $CC +END + + +# Allow error exit status. +set +e + +if [ -z `which $CC` ]; then + echo + echo $0: error: $CC not found. + echo + exit 1; +fi + + +if `/bin/sh -c "($CC -v)" 2>&1 | grep "gcc version" >> $NJS_AUTOCONF_ERR 2>&1` +then + NJS_CC_NAME=gcc + echo " + using GNU C compiler" + NJS_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "gcc version" 2>&1` + echo " + $NJS_CC_VERSION" + +else +if `/bin/sh -c "($CC -v)" 2>&1 | grep "clang version" >> $NJS_AUTOCONF_ERR 2>&1` +then + NJS_CC_NAME=clang + echo " + using Clang C compiler" + NJS_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "clang version" 2>&1` + echo " + $NJS_CC_VERSION" + +else +if `/bin/sh -c "($CC -v)" 2>&1 \ + | grep "Apple LLVM version" >> $NJS_AUTOCONF_ERR 2>&1` +then + NJS_CC_NAME=clang + echo " + using Clang C compiler" + NJS_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "Apple LLVM version" 2>&1` + echo " + $NJS_CC_VERSION" + +else +if `/bin/sh -c "($CC -V)" 2>&1 | grep "Sun C" >> $NJS_AUTOCONF_ERR 2>&1` +then + NJS_CC_NAME=SunC + echo " + using Sun C compiler" + NJS_CC_VERSION=`/bin/sh -c "($CC -V)" 2>&1 | grep "Sun C" 2>&1` + echo " + $NJS_CC_VERSION" + +fi # SunC +fi # Apple LLVM clang +fi # clang +fi # gcc + + +case $NJS_CC_NAME in + + gcc) + njs_define=NJS_GCC . auto/define + + NJS_CFLAGS="$NJS_CFLAGS -pipe" + NJS_CFLAGS="$NJS_CFLAGS -fPIC" + + # Do not export symbols except explicitly marked with NJS_EXPORT. + NJS_CFLAGS="$NJS_CFLAGS -fvisibility=hidden" + + # c99/gnu99 conflict with Solaris XOPEN. + #NJS_CFLAGS="$NJS_CFLAGS -std=gnu99" + + NJS_CFLAGS="$NJS_CFLAGS -O" + #NJS_CFLAGS="$NJS_CFLAGS -O0" + NJS_CFLAGS="$NJS_CFLAGS -W -Wall -Wextra" + + #NJS_CFLAGS="$NJS_CFLAGS -Wunused-result" + NJS_CFLAGS="$NJS_CFLAGS -Wno-unused-parameter" + #NJS_CFLAGS="$NJS_CFLAGS -Wshorten-64-to-32" + NJS_CFLAGS="$NJS_CFLAGS -Wwrite-strings" + + # -O2 enables -fstrict-aliasing and -fstrict-overflow. + #NJS_CFLAGS="$NJS_CFLAGS -O2" + #NJS_CFLAGS="$NJS_CFLAGS -Wno-strict-aliasing" + + #NJS_CFLAGS="$NJS_CFLAGS -fomit-frame-pointer" + #NJS_CFLAGS="$NJS_CFLAGS -momit-leaf-frame-pointer" + + # -Wstrict-overflow is supported by GCC 4.2+. + #NJS_CFLAGS="$NJS_CFLAGS -Wstrict-overflow=5" + + NJS_CFLAGS="$NJS_CFLAGS -Wmissing-prototypes" + + # Stop on warning. + NJS_CFLAGS="$NJS_CFLAGS -Werror" + + # Debug. + NJS_CFLAGS="$NJS_CFLAGS -g" + ;; + + clang) + njs_define=NJS_CLANG . auto/define + + NJS_CFLAGS="$NJS_CFLAGS -pipe" + NJS_CFLAGS="$NJS_CFLAGS -fPIC" + + # Do not export symbols except explicitly marked with NJS_EXPORT. + NJS_CFLAGS="$NJS_CFLAGS -fvisibility=hidden" + + NJS_CFLAGS="$NJS_CFLAGS -O" + #NJS_CFLAGS="$NJS_CFLAGS -O0" + NJS_CFLAGS="$NJS_CFLAGS -W -Wall -Wextra" + + #NJS_CFLAGS="$NJS_CFLAGS -Wunused-result" + NJS_CFLAGS="$NJS_CFLAGS -Wno-unused-parameter" + #NJS_CFLAGS="$NJS_CFLAGS -Wshorten-64-to-32" + NJS_CFLAGS="$NJS_CFLAGS -Wwrite-strings" + #NJS_CFLAGS="$NJS_CFLAGS -O2" + #NJS_CFLAGS="$NJS_CFLAGS -fomit-frame-pointer" + NJS_CFLAGS="$NJS_CFLAGS -fstrict-aliasing" + NJS_CFLAGS="$NJS_CFLAGS -Wstrict-overflow=5" + + NJS_CFLAGS="$NJS_CFLAGS -Wmissing-prototypes" + + # Stop on warning. + NJS_CFLAGS="$NJS_CFLAGS -Werror" + + # Debug. + + if [ "$NJS_SYSTEM_PLATFORM" != "powerpc" ]; then + # "-g" flag causes the "unknown pseudo-op: `.cfi_sections'" + # error on PowerPC Clang. + NJS_CFLAGS="$NJS_CFLAGS -g" + fi + ;; + + SunC) + njs_define=NJS_SUNC . auto/define + + NJS_CFLAGS="$NJS_CFLAGS -fPIC" + # Optimization. + NJS_CFLAGS="$NJS_CFLAGS -O -fast" + # Stop on warning. + NJS_CFLAGS="$NJS_CFLAGS -errwarn=%all" + # Debug. + NJS_CFLAGS="$NJS_CFLAGS -g" + ;; + + *) + ;; + +esac + +# Stop on error exit status again. +set -e + +cat << END >> $NJS_MAKEFILE + +NJS_CC = ${CC} +NJS_CFLAGS = ${NJS_CFLAGS} ${CFLAGS} +END diff -r e848c0ee1238 -r 7b1a00168b25 auto/clang --- a/auto/clang Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/clang Tue Aug 20 20:51:39 2019 +0300 @@ -2,168 +2,6 @@ # Copyright (C) Igor Sysoev # Copyright (C) NGINX, Inc. - -$echo checking for C compiler: $CC -cat << END >> $NJS_AUTOCONF_ERR ----------------------------------------- -checking for C compiler: $CC -END - - -# Allow error exit status. -set +e - -if [ -z `which $CC` ]; then - $echo - $echo $0: error: $CC not found. - $echo - exit 1; -fi - - -if `/bin/sh -c "($CC -v)" 2>&1 | grep "gcc version" >> $NJS_AUTOCONF_ERR 2>&1` -then - NJS_CC_NAME=gcc - $echo " + using GNU C compiler" - NJS_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "gcc version" 2>&1` - $echo " + $NJS_CC_VERSION" - -else -if `/bin/sh -c "($CC -v)" 2>&1 | grep "clang version" >> $NJS_AUTOCONF_ERR 2>&1` -then - NJS_CC_NAME=clang - $echo " + using Clang C compiler" - NJS_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "clang version" 2>&1` - $echo " + $NJS_CC_VERSION" - -else -if `/bin/sh -c "($CC -v)" 2>&1 \ - | grep "Apple LLVM version" >> $NJS_AUTOCONF_ERR 2>&1` -then - NJS_CC_NAME=clang - $echo " + using Clang C compiler" - NJS_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "Apple LLVM version" 2>&1` - $echo " + $NJS_CC_VERSION" - -else -if `/bin/sh -c "($CC -V)" 2>&1 | grep "Sun C" >> $NJS_AUTOCONF_ERR 2>&1` -then - NJS_CC_NAME=SunC - $echo " + using Sun C compiler" - NJS_CC_VERSION=`/bin/sh -c "($CC -V)" 2>&1 | grep "Sun C" 2>&1` - $echo " + $NJS_CC_VERSION" - -fi # SunC -fi # Apple LLVM clang -fi # clang -fi # gcc - - -case $NJS_CC_NAME in - - gcc) - njs_define=NJS_GCC . auto/define - - NJS_CFLAGS="$NJS_CFLAGS -pipe" - NJS_CFLAGS="$NJS_CFLAGS -fPIC" - - # Do not export symbols except explicitly marked with NJS_EXPORT. - NJS_CFLAGS="$NJS_CFLAGS -fvisibility=hidden" - - # c99/gnu99 conflict with Solaris XOPEN. - #NJS_CFLAGS="$NJS_CFLAGS -std=gnu99" - - NJS_CFLAGS="$NJS_CFLAGS -O" - #NJS_CFLAGS="$NJS_CFLAGS -O0" - NJS_CFLAGS="$NJS_CFLAGS -W -Wall -Wextra" - - #NJS_CFLAGS="$NJS_CFLAGS -Wunused-result" - NJS_CFLAGS="$NJS_CFLAGS -Wno-unused-parameter" - #NJS_CFLAGS="$NJS_CFLAGS -Wshorten-64-to-32" - NJS_CFLAGS="$NJS_CFLAGS -Wwrite-strings" - - # -O2 enables -fstrict-aliasing and -fstrict-overflow. - #NJS_CFLAGS="$NJS_CFLAGS -O2" - #NJS_CFLAGS="$NJS_CFLAGS -Wno-strict-aliasing" - - #NJS_CFLAGS="$NJS_CFLAGS -fomit-frame-pointer" - #NJS_CFLAGS="$NJS_CFLAGS -momit-leaf-frame-pointer" - - # -Wstrict-overflow is supported by GCC 4.2+. - #NJS_CFLAGS="$NJS_CFLAGS -Wstrict-overflow=5" - - NJS_CFLAGS="$NJS_CFLAGS -Wmissing-prototypes" - - # Stop on warning. - NJS_CFLAGS="$NJS_CFLAGS -Werror" - - # Debug. - NJS_CFLAGS="$NJS_CFLAGS -g" - ;; - - clang) - njs_define=NJS_CLANG . auto/define - - NJS_CFLAGS="$NJS_CFLAGS -pipe" - NJS_CFLAGS="$NJS_CFLAGS -fPIC" - - # Do not export symbols except explicitly marked with NJS_EXPORT. - NJS_CFLAGS="$NJS_CFLAGS -fvisibility=hidden" - - NJS_CFLAGS="$NJS_CFLAGS -O" - #NJS_CFLAGS="$NJS_CFLAGS -O0" - NJS_CFLAGS="$NJS_CFLAGS -W -Wall -Wextra" - - #NJS_CFLAGS="$NJS_CFLAGS -Wunused-result" - NJS_CFLAGS="$NJS_CFLAGS -Wno-unused-parameter" - #NJS_CFLAGS="$NJS_CFLAGS -Wshorten-64-to-32" - NJS_CFLAGS="$NJS_CFLAGS -Wwrite-strings" - #NJS_CFLAGS="$NJS_CFLAGS -O2" - #NJS_CFLAGS="$NJS_CFLAGS -fomit-frame-pointer" - NJS_CFLAGS="$NJS_CFLAGS -fstrict-aliasing" - NJS_CFLAGS="$NJS_CFLAGS -Wstrict-overflow=5" - - NJS_CFLAGS="$NJS_CFLAGS -Wmissing-prototypes" - - # Stop on warning. - NJS_CFLAGS="$NJS_CFLAGS -Werror" - - # Debug. - - if [ "$NJS_SYSTEM_PLATFORM" != "powerpc" ]; then - # "-g" flag causes the "unknown pseudo-op: `.cfi_sections'" - # error on PowerPC Clang. - NJS_CFLAGS="$NJS_CFLAGS -g" - fi - ;; - - SunC) - njs_define=NJS_SUNC . auto/define - - NJS_CFLAGS="$NJS_CFLAGS -fPIC" - # Optimization. - NJS_CFLAGS="$NJS_CFLAGS -O -fast" - # Stop on warning. - NJS_CFLAGS="$NJS_CFLAGS -errwarn=%all" - # Debug. - NJS_CFLAGS="$NJS_CFLAGS -g" - ;; - - *) - ;; - -esac - -# Stop on error exit status again. -set -e - -cat << END >> $NJS_MAKEFILE - -NJS_CC = ${CC} -NJS_CFLAGS = ${NJS_CFLAGS} ${CFLAGS} -END - - # C language features. njs_feature="GCC unsigned __int128" diff -r e848c0ee1238 -r 7b1a00168b25 auto/deps --- a/auto/deps Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/deps Tue Aug 20 20:51:39 2019 +0300 @@ -7,23 +7,23 @@ case "$NJS_CC_NAME" in SunC): njs_gen_dep_flags() { - $echo "-xMMD -xMF $NJS_BUILD_DIR/$1.tmp" + echo "-xMMD -xMF $NJS_BUILD_DIR/$1.tmp" } njs_gen_dep_post() { - $echo -n "@sed -e 's#^.*:#$NJS_BUILD_DIR/$2:#' " - $echo -n "$NJS_BUILD_DIR/$1.tmp > $NJS_BUILD_DIR/$1" - $echo " && rm -f $NJS_BUILD_DIR/$1.tmp" + printf "@sed -e 's#^.*:#$NJS_BUILD_DIR/$2:#' " + printf "$NJS_BUILD_DIR/$1.tmp > $NJS_BUILD_DIR/$1" + echo " && rm -f $NJS_BUILD_DIR/$1.tmp" } ;; *) njs_gen_dep_flags() { - $echo "-MMD -MF $NJS_BUILD_DIR/$1 -MT $NJS_BUILD_DIR/$2" + echo "-MMD -MF $NJS_BUILD_DIR/$1 -MT $NJS_BUILD_DIR/$2" } njs_gen_dep_post() { - $echo "" + echo "" } ;; esac diff -r e848c0ee1238 -r 7b1a00168b25 auto/echo --- a/auto/echo Tue Aug 20 20:51:33 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) NGINX, Inc. - - -if [ "x$1" = x-n ]; then - shift - echo "$*\c" - -else - echo "$*" -fi diff -r e848c0ee1238 -r 7b1a00168b25 auto/expect --- a/auto/expect Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/expect Tue Aug 20 20:51:39 2019 +0300 @@ -3,18 +3,18 @@ # Copyright (C) NGINX, Inc. njs_found=no -$echo -n "checking for expect ..." +printf "checking for expect ..." if /bin/sh -c "(expect -v)" >> $NJS_AUTOCONF_ERR 2>&1; then njs_found=yes fi if [ $njs_found = yes ]; then - $echo " found" - $echo " + Expect version: `expect -v`" + echo " found" + echo " + Expect version: `expect -v`" else - $echo " not found" + echo " not found" fi if [ $njs_found = yes -a $NJS_HAVE_READLINE = YES ]; then @@ -26,7 +26,7 @@ expect_test: njs test/njs_expect_test.ex END else - $echo " - expect tests are disabled" + echo " - expect tests are disabled" cat << END >> $NJS_MAKEFILE diff -r e848c0ee1238 -r 7b1a00168b25 auto/feature --- a/auto/feature Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/feature Tue Aug 20 20:51:39 2019 +0300 @@ -3,7 +3,7 @@ # Copyright (C) NGINX, Inc. -$echo -n "checking for $njs_feature ..." +printf "checking for $njs_feature ..." cat << END >> $NJS_AUTOCONF_ERR ---------------------------------------- @@ -52,10 +52,10 @@ if [ -x $NJS_AUTOTEST ]; then value) if /bin/sh -c "($NJS_AUTOTEST)" >> $NJS_AUTOCONF_ERR 2>&1; then - $echo >> $NJS_AUTOCONF_ERR + echo >> $NJS_AUTOCONF_ERR njs_found=yes njs_feature_value=`$NJS_AUTOTEST` - $echo " $njs_feature_value" + echo " $njs_feature_value" if [ -n "$njs_feature_name" ]; then cat << END >> $NJS_AUTO_CONFIG_H @@ -66,13 +66,13 @@ if [ -x $NJS_AUTOTEST ]; then END fi else - $echo " not found" + echo " not found" fi ;; yes) if /bin/sh -c "($NJS_AUTOTEST)" >> $NJS_AUTOCONF_ERR 2>&1; then - $echo " found" + echo " found" njs_found=yes cat << END >> $NJS_AUTO_CONFIG_H @@ -82,12 +82,12 @@ END END else - $echo " found but is not working" + echo " found but is not working" fi ;; *) - $echo " found" + echo " found" njs_found=yes cat << END >> $NJS_AUTO_CONFIG_H @@ -100,13 +100,13 @@ END esac else - $echo " not found" + echo " not found" - $echo "----------" >> $NJS_AUTOCONF_ERR + echo "----------" >> $NJS_AUTOCONF_ERR cat $NJS_AUTOTEST.c >> $NJS_AUTOCONF_ERR - $echo "----------" >> $NJS_AUTOCONF_ERR - $echo $njs_test >> $NJS_AUTOCONF_ERR - $echo "----------" >> $NJS_AUTOCONF_ERR + echo "----------" >> $NJS_AUTOCONF_ERR + echo $njs_test >> $NJS_AUTOCONF_ERR + echo "----------" >> $NJS_AUTOCONF_ERR fi rm -rf $NJS_AUTOTEST* diff -r e848c0ee1238 -r 7b1a00168b25 auto/make --- a/auto/make Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/make Tue Aug 20 20:51:39 2019 +0300 @@ -4,7 +4,7 @@ . auto/deps -$echo "creating $NJS_MAKEFILE" +echo "creating $NJS_MAKEFILE" mkdir -p $NJS_BUILD_DIR/src mkdir -p $NJS_BUILD_DIR/test @@ -24,29 +24,29 @@ END # The include paths list. -$echo -n "NJS_LIB_INCS =" >> $NJS_MAKEFILE +printf "NJS_LIB_INCS =" >> $NJS_MAKEFILE for njs_inc in src $NJS_BUILD_DIR do - $echo -n " -I$njs_inc" >> $NJS_MAKEFILE + printf " -I$njs_inc" >> $NJS_MAKEFILE done -$echo >> $NJS_MAKEFILE -$echo >> $NJS_MAKEFILE +echo >> $NJS_MAKEFILE +echo >> $NJS_MAKEFILE # The njs object files list. -$echo "NJS_LIB_OBJS = \\" >> $NJS_MAKEFILE +echo "NJS_LIB_OBJS = \\" >> $NJS_MAKEFILE for njs_src in $NJS_LIB_SRCS do fname=$(basename $njs_src) njs_obj="src/${fname%.c}.o" - $echo " $NJS_BUILD_DIR/$njs_obj \\" >> $NJS_MAKEFILE + echo " $NJS_BUILD_DIR/$njs_obj \\" >> $NJS_MAKEFILE done -$echo >> $NJS_MAKEFILE +echo >> $NJS_MAKEFILE # The njs static library. diff -r e848c0ee1238 -r 7b1a00168b25 auto/os --- a/auto/os Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/os Tue Aug 20 20:51:39 2019 +0300 @@ -13,7 +13,6 @@ case "$NJS_SYSTEM" in NJS_SYSTEM_VERSION=`uname -r 2>/dev/null` # Linux uname -p can return "unknown". NJS_SYSTEM_PLATFORM=`uname -m 2>/dev/null` - echo=echo CC=${CC:-cc} # NAN and INFINITY require _GNU_SOURCE on old Linux. @@ -23,7 +22,6 @@ case "$NJS_SYSTEM" in FreeBSD | NetBSD | OpenBSD) NJS_SYSTEM_VERSION=`uname -r 2>/dev/null` NJS_SYSTEM_PLATFORM=`uname -m 2>/dev/null` - echo=echo CC=${CC:-cc} ;; @@ -31,27 +29,21 @@ case "$NJS_SYSTEM" in njs_define=NJS_SOLARIS . auto/define NJS_SYSTEM_VERSION=`uname -r 2>/dev/null` NJS_SYSTEM_PLATFORM=`uname -p 2>/dev/null` - # Solaris /bin/sh and /bin/echo do not support "-n" option. - echo=auto/echo CC=${CC:-gcc} ;; Darwin) NJS_SYSTEM_VERSION=`uname -r 2>/dev/null` NJS_SYSTEM_PLATFORM=`uname -m 2>/dev/null` - # MacOSX /bin/sh is bash and its embedded "echo" command - # does not support "-n" option. - echo=/bin/echo CC=${CC:-cc} ;; *) NJS_SYSTEM_VERSION=`uname -r 2>/dev/null` NJS_SYSTEM_PLATFORM=`uname -p 2>/dev/null` - echo=echo CC=${CC:-gcc} ;; esac -$echo configuring for $NJS_SYSTEM $NJS_SYSTEM_VERSION $NJS_SYSTEM_PLATFORM +echo configuring for $NJS_SYSTEM $NJS_SYSTEM_VERSION $NJS_SYSTEM_PLATFORM diff -r e848c0ee1238 -r 7b1a00168b25 auto/pcre --- a/auto/pcre Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/pcre Tue Aug 20 20:51:39 2019 +0300 @@ -32,10 +32,10 @@ if /bin/sh -c "(pcre-config --version)" fi if [ $njs_found = no ]; then - $echo - $echo $0: error: no PCRE library found. - $echo + echo + echo $0: error: no PCRE library found. + echo exit 1; fi -$echo " + PCRE version: `pcre-config --version`" +echo " + PCRE version: `pcre-config --version`" diff -r e848c0ee1238 -r 7b1a00168b25 auto/readline --- a/auto/readline Tue Aug 20 20:51:33 2019 +0300 +++ b/auto/readline Tue Aug 20 20:51:39 2019 +0300 @@ -77,5 +77,5 @@ if [ $njs_found = yes ]; then else NJS_HAVE_READLINE=NO - $echo " - building interactive shell is not possible" + echo " - building interactive shell is not possible" fi diff -r e848c0ee1238 -r 7b1a00168b25 configure --- a/configure Tue Aug 20 20:51:33 2019 +0300 +++ b/configure Tue Aug 20 20:51:39 2019 +0300 @@ -47,6 +47,7 @@ END NJS_LIBRT= . auto/os +. auto/cc . auto/clang . auto/time . auto/memalign From xeioex at nginx.com Tue Aug 20 17:51:53 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Aug 2019 17:51:53 +0000 Subject: [njs] Fixed prototype mutation for object literals. Message-ID: details: https://hg.nginx.org/njs/rev/13161c0357e4 branches: changeset: 1137:13161c0357e4 user: Dmitry Volyntsev date: Tue Aug 20 20:51:39 2019 +0300 description: Fixed prototype mutation for object literals. diffstat: src/njs_disassembler.c | 2 + src/njs_generator.c | 13 ++++++- src/njs_lexer.h | 1 + src/njs_object_hash.h | 13 +++++++ src/njs_parser_terminal.c | 41 +++++++++++++++++++--- src/njs_vmcode.c | 84 +++++++++++++++++++++++++++++++--------------- src/njs_vmcode.h | 1 + src/test/njs_unit_test.c | 27 +++++++++++++++ 8 files changed, 146 insertions(+), 36 deletions(-) diffs (367 lines): diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_disassembler.c --- a/src/njs_disassembler.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_disassembler.c Tue Aug 20 20:51:39 2019 +0300 @@ -39,6 +39,8 @@ static njs_code_name_t code_names[] = { njs_str("PROP GET ") }, { NJS_VMCODE_PROPERTY_INIT, sizeof(njs_vmcode_prop_set_t), njs_str("PROP INIT ") }, + { NJS_VMCODE_PROTO_INIT, sizeof(njs_vmcode_prop_set_t), + njs_str("PROTO INIT ") }, { NJS_VMCODE_PROPERTY_SET, sizeof(njs_vmcode_prop_set_t), njs_str("PROP SET ") }, { NJS_VMCODE_PROPERTY_IN, sizeof(njs_vmcode_3addr_t), diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_generator.c --- a/src/njs_generator.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_generator.c Tue Aug 20 20:51:39 2019 +0300 @@ -1741,10 +1741,19 @@ njs_generate_assignment(njs_vm_t *vm, nj return ret; } - if (lvalue->token == NJS_TOKEN_PROPERTY_INIT) { + switch (lvalue->token) { + case NJS_TOKEN_PROPERTY_INIT: njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, NJS_VMCODE_PROPERTY_INIT, 3); - } else { + break; + + case NJS_TOKEN_PROTO_INIT: + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, + NJS_VMCODE_PROTO_INIT, 3); + break; + + default: + /* NJS_VMCODE_PROPERTY_SET */ njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, NJS_VMCODE_PROPERTY_SET, 3); } diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_lexer.h --- a/src/njs_lexer.h Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_lexer.h Tue Aug 20 20:51:39 2019 +0300 @@ -127,6 +127,7 @@ typedef enum { NJS_TOKEN_PROPERTY_DELETE, NJS_TOKEN_PROPERTY_GETTER, NJS_TOKEN_PROPERTY_SETTER, + NJS_TOKEN_PROTO_INIT, NJS_TOKEN_ARRAY, diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_object_hash.h --- a/src/njs_object_hash.h Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_object_hash.h Tue Aug 20 20:51:39 2019 +0300 @@ -8,6 +8,19 @@ #define _NJS_OBJECT_HASH_H_INCLUDED_ +#define NJS___PROTO___HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + '_'), '_'), 'p'), 'r'), 'o'), 't'), 'o'), '_'), '_') + + #define NJS_ARGV_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \ diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_parser_terminal.c --- a/src/njs_parser_terminal.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_parser_terminal.c Tue Aug 20 20:51:39 2019 +0300 @@ -18,7 +18,7 @@ static njs_token_t njs_parser_object(njs njs_parser_node_t *obj); static njs_int_t njs_parser_object_property(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *parent, njs_parser_node_t *property, - njs_parser_node_t *value); + njs_parser_node_t *value, njs_bool_t proto_init); static njs_int_t njs_parser_property_accessor(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *parent, njs_parser_node_t *property, njs_parser_node_t *value, @@ -475,18 +475,22 @@ static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) { uint32_t hash, token_line; - njs_int_t ret; + njs_int_t ret, __proto__; njs_str_t name; + njs_bool_t computed, proto_init; njs_token_t token, accessor; njs_lexer_t *lexer; njs_parser_node_t *object, *property, *expression; njs_function_lambda_t *lambda; + const njs_str_t proto_string = njs_str("__proto__"); + lexer = parser->lexer; /* GCC and Clang complain about uninitialized values. */ hash = 0; token_line = 0; + __proto__ = 0; property = NULL; object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); @@ -503,6 +507,8 @@ njs_parser_object(njs_vm_t *vm, njs_pars } accessor = 0; + computed = 0; + proto_init = 0; njs_memzero(&name, sizeof(njs_str_t)); if (token == NJS_TOKEN_NAME || lexer->keyword) { @@ -558,6 +564,9 @@ njs_parser_object(njs_vm_t *vm, njs_pars token = njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_BRACKET); + + computed = 1; + break; case NJS_TOKEN_NUMBER: @@ -657,6 +666,23 @@ njs_parser_object(njs_vm_t *vm, njs_pars break; case NJS_TOKEN_COLON: + if (!computed) { + if (njs_is_string(&property->u.value)) { + njs_string_get(&property->u.value, &name); + } + + if (njs_slow_path(njs_strstr_eq(&name, &proto_string))) { + if (++__proto__ > 1) { + njs_parser_syntax_error(vm, parser, + "Duplicate __proto__ fields are not allowed " + "in object literals"); + return NJS_TOKEN_ILLEGAL; + } + + proto_init = 1; + } + } + token = njs_parser_token(vm, parser); if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; @@ -699,7 +725,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars } ret = njs_parser_object_property(vm, parser, obj, property, - expression); + expression, proto_init); if (njs_slow_path(ret != NJS_OK)) { return NJS_TOKEN_ERROR; } @@ -725,8 +751,9 @@ done: static njs_int_t njs_parser_object_property(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *parent, njs_parser_node_t *property, - njs_parser_node_t *value) + njs_parser_node_t *value, njs_bool_t proto_init) { + njs_token_t token; njs_parser_node_t *stmt, *assign, *object, *propref; object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); @@ -736,7 +763,9 @@ njs_parser_object_property(njs_vm_t *vm, object->u.object = parent; - propref = njs_parser_node_new(vm, parser, NJS_TOKEN_PROPERTY_INIT); + token = proto_init ? NJS_TOKEN_PROTO_INIT : NJS_TOKEN_PROPERTY_INIT; + + propref = njs_parser_node_new(vm, parser, token); if (njs_slow_path(propref == NULL)) { return NJS_ERROR; } @@ -870,7 +899,7 @@ njs_parser_array_item(njs_vm_t *vm, njs_ njs_set_number(&number->u.value, array->u.length); - ret = njs_parser_object_property(vm, parser, array, number, value); + ret = njs_parser_object_property(vm, parser, array, number, value, 0); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_vmcode.c --- a/src/njs_vmcode.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_vmcode.c Tue Aug 20 20:51:39 2019 +0300 @@ -23,8 +23,10 @@ static njs_jump_off_t njs_vmcode_templat static njs_jump_off_t njs_vmcode_object_copy(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld); -static njs_jump_off_t njs_vmcode_property_init(njs_vm_t *vm, - njs_value_t *value, njs_value_t *key, njs_value_t *retval); +static njs_jump_off_t njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, + njs_value_t *key, njs_value_t *retval); +static njs_jump_off_t njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, + njs_value_t *key, njs_value_t *retval); static njs_jump_off_t njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key); static njs_jump_off_t njs_vmcode_property_delete(njs_vm_t *vm, @@ -786,6 +788,16 @@ next: break; + case NJS_VMCODE_PROTO_INIT: + set = (njs_vmcode_prop_set_t *) pc; + retval = njs_vmcode_operand(vm, set->value); + ret = njs_vmcode_proto_init(vm, value1, value2, retval); + if (njs_slow_path(ret == NJS_ERROR)) { + goto error; + } + + break; + case NJS_VMCODE_TRY_START: ret = njs_vmcode_try_start(vm, value1, value2, pc); if (njs_slow_path(ret == NJS_ERROR)) { @@ -1106,7 +1118,6 @@ njs_vmcode_property_init(njs_vm_t *vm, n uint32_t index, size; njs_array_t *array; njs_value_t *val, name; - njs_object_t *obj; njs_jump_off_t ret; njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; @@ -1157,30 +1168,6 @@ njs_vmcode_property_init(njs_vm_t *vm, n lhq.proto = &njs_object_hash_proto; lhq.pool = vm->mem_pool; - obj = njs_object(value); - - if (obj->__proto__ != NULL) { - /* obj->__proto__ can be NULL after __proto__: null assignment */ - ret = njs_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); - if (ret == NJS_OK) { - prop = lhq.value; - - if (prop->type == NJS_PROPERTY_HANDLER) { - ret = prop->value.data.u.prop_handler(vm, value, init, - &vm->retval); - if (njs_slow_path(ret == NJS_ERROR)) { - return ret; - } - - if (ret == NJS_OK) { - break; - } - - /* NJS_DECLINED */ - } - } - } - prop = njs_object_prop_alloc(vm, &name, init, 1); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; @@ -1189,7 +1176,7 @@ njs_vmcode_property_init(njs_vm_t *vm, n lhq.value = prop; lhq.replace = 1; - ret = njs_lvlhsh_insert(&obj->hash, &lhq); + ret = njs_lvlhsh_insert(njs_object_hash(value), &lhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "lvlhsh insert/replace failed"); return NJS_ERROR; @@ -1210,6 +1197,47 @@ njs_vmcode_property_init(njs_vm_t *vm, n static njs_jump_off_t +njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *unused, + njs_value_t *init) +{ + njs_object_t *obj; + njs_jump_off_t ret; + njs_object_prop_t *prop; + njs_lvlhsh_query_t lhq; + + lhq.key = njs_str_value("__proto__"); + lhq.key_hash = NJS___PROTO___HASH; + lhq.proto = &njs_object_hash_proto; + lhq.pool = vm->mem_pool; + + obj = njs_object(value); + + ret = njs_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + goto fail; + } + + prop = lhq.value; + + if (prop->type != NJS_PROPERTY_HANDLER) { + goto fail; + } + + ret = prop->value.data.u.prop_handler(vm, value, init, &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + goto fail; + } + + return sizeof(njs_vmcode_prop_set_t); + +fail: + + njs_internal_error(vm, "\"__proto__\" init failed"); + return NJS_ERROR; +} + + +static njs_jump_off_t njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key) { njs_int_t ret; diff -r 7b1a00168b25 -r 13161c0357e4 src/njs_vmcode.h --- a/src/njs_vmcode.h Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_vmcode.h Tue Aug 20 20:51:39 2019 +0300 @@ -52,6 +52,7 @@ typedef uint8_t #define NJS_VMCODE_PROPERTY_NEXT VMCODE0(16) #define NJS_VMCODE_THIS VMCODE0(17) #define NJS_VMCODE_ARGUMENTS VMCODE0(18) +#define NJS_VMCODE_PROTO_INIT VMCODE0(19) #define NJS_VMCODE_TRY_START VMCODE0(32) #define NJS_VMCODE_THROW VMCODE0(33) diff -r 7b1a00168b25 -r 13161c0357e4 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/test/njs_unit_test.c Tue Aug 20 20:51:39 2019 +0300 @@ -8810,6 +8810,33 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = {__proto__: Array.prototype, length:3}; o.fill('a')[2]"), njs_str("a") }, + { njs_str("({__proto__:null, __proto__: null})"), + njs_str("SyntaxError: Duplicate __proto__ fields are not allowed in object literals in 1") }, + + { njs_str("({__proto__:null, '__proto__': null})"), + njs_str("SyntaxError: Duplicate __proto__ fields are not allowed in object literals in 1") }, + + { njs_str("({__proto__:null, '\\x5f_proto__': null})"), + njs_str("SyntaxError: Duplicate __proto__ fields are not allowed in object literals in 1") }, + + { njs_str("var __proto__ = 'a'; ({__proto__}).__proto__"), + njs_str("a") }, + + { njs_str("var __proto__ = 'a'; ({__proto__, '__proto__':'b'}).__proto__"), + njs_str("a") }, + + { njs_str("var __proto__ = 'a'; ({__proto__:null, __proto__}).__proto__"), + njs_str("a") }, + + { njs_str("({__proto__:null, ['__proto__']:'a'}).__proto__"), + njs_str("a") }, + + { njs_str("({__proto__() { return 123; }}).__proto__()"), + njs_str("123") }, + + { njs_str("({['__prot' + 'o__']: 123}).__proto__"), + njs_str("123") }, + { njs_str("({}).__proto__.constructor === Object"), njs_str("true") }, From xeioex at nginx.com Wed Aug 21 13:32:24 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 21 Aug 2019 13:32:24 +0000 Subject: [njs] Introduced njs_variables_copy(). Message-ID: details: https://hg.nginx.org/njs/rev/91e3f7345e47 branches: changeset: 1139:91e3f7345e47 user: hongzhidao date: Tue Aug 20 23:03:26 2019 -0400 description: Introduced njs_variables_copy(). diffstat: src/njs_parser.c | 38 +++++++------------------------------- src/njs_variable.c | 36 ++++++++++++++++++++++++++++++++++++ src/njs_variable.h | 2 ++ 3 files changed, 45 insertions(+), 31 deletions(-) diffs (113 lines): diff -r 4cc08cb772a2 -r 91e3f7345e47 src/njs_parser.c --- a/src/njs_parser.c Tue Aug 20 22:59:38 2019 -0400 +++ b/src/njs_parser.c Tue Aug 20 23:03:26 2019 -0400 @@ -76,13 +76,9 @@ static njs_token_t njs_parser_grouping_e njs_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) { - njs_int_t ret; - njs_token_t token; - njs_lvlhsh_t *variables, *prev_variables; - njs_variable_t *var; - njs_parser_node_t *node; - njs_lvlhsh_each_t lhe; - njs_lvlhsh_query_t lhq; + njs_int_t ret; + njs_token_t token; + njs_parser_node_t *node; ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_GLOBAL); if (njs_slow_path(ret != NJS_OK)) { @@ -94,30 +90,10 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p * Copy the global scope variables from the previous * iteration of the accumulative mode. */ - njs_lvlhsh_each_init(&lhe, &njs_variables_hash_proto); - - lhq.proto = &njs_variables_hash_proto; - lhq.replace = 0; - lhq.pool = vm->mem_pool; - - variables = &parser->scope->variables; - prev_variables = &prev->scope->variables; - - for ( ;; ) { - var = njs_lvlhsh_each(prev_variables, &lhe); - - if (var == NULL) { - break; - } - - lhq.value = var; - lhq.key = var->name; - lhq.key_hash = njs_djb_hash(var->name.start, var->name.length); - - ret = njs_lvlhsh_insert(variables, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } + ret = njs_variables_copy(vm, &parser->scope->variables, + &prev->scope->variables); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } } diff -r 4cc08cb772a2 -r 91e3f7345e47 src/njs_variable.c --- a/src/njs_variable.c Tue Aug 20 22:59:38 2019 -0400 +++ b/src/njs_variable.c Tue Aug 20 23:03:26 2019 -0400 @@ -80,6 +80,42 @@ njs_variable_add(njs_vm_t *vm, njs_parse } +njs_int_t +njs_variables_copy(njs_vm_t *vm, njs_lvlhsh_t *variables, + njs_lvlhsh_t *prev_variables) +{ + njs_int_t ret; + njs_variable_t *var; + njs_lvlhsh_each_t lhe; + njs_lvlhsh_query_t lhq; + + njs_lvlhsh_each_init(&lhe, &njs_variables_hash_proto); + + lhq.proto = &njs_variables_hash_proto; + lhq.replace = 0; + lhq.pool = vm->mem_pool; + + for ( ;; ) { + var = njs_lvlhsh_each(prev_variables, &lhe); + + if (var == NULL) { + break; + } + + lhq.value = var; + lhq.key = var->name; + lhq.key_hash = njs_djb_hash(var->name.start, var->name.length); + + ret = njs_lvlhsh_insert(variables, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } + + return NJS_OK; +} + + static njs_variable_t * njs_variable_scope_add(njs_vm_t *vm, njs_parser_scope_t *scope, njs_lvlhsh_query_t *lhq, njs_variable_type_t type) diff -r 4cc08cb772a2 -r 91e3f7345e47 src/njs_variable.h --- a/src/njs_variable.h Tue Aug 20 22:59:38 2019 -0400 +++ b/src/njs_variable.h Tue Aug 20 23:03:26 2019 -0400 @@ -51,6 +51,8 @@ typedef struct { njs_variable_t *njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, njs_str_t *name, uint32_t hash, njs_variable_type_t type); +njs_int_t njs_variables_copy(njs_vm_t *vm, njs_lvlhsh_t *variables, + njs_lvlhsh_t *prev_variables); njs_variable_t * njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, njs_str_t *name, uint32_t hash); njs_variable_t *njs_label_find(njs_vm_t *vm, njs_parser_scope_t *scope, From xeioex at nginx.com Wed Aug 21 13:32:23 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 21 Aug 2019 13:32:23 +0000 Subject: [njs] Fixed division token in lexer. Message-ID: details: https://hg.nginx.org/njs/rev/4cc08cb772a2 branches: changeset: 1138:4cc08cb772a2 user: hongzhidao date: Tue Aug 20 22:59:38 2019 -0400 description: Fixed division token in lexer. diffstat: src/njs_lexer.c | 11 +++++++---- src/test/njs_unit_test.c | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diffs (50 lines): diff -r 13161c0357e4 -r 4cc08cb772a2 src/njs_lexer.c --- a/src/njs_lexer.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/njs_lexer.c Tue Aug 20 22:59:38 2019 -0400 @@ -504,7 +504,7 @@ njs_lexer_next_token(njs_lexer_t *lexer, token = njs_lexer_division(lexer, token); if (token != NJS_TOKEN_AGAIN) { - return token; + goto done; } continue; @@ -557,8 +557,7 @@ njs_lexer_next_token(njs_lexer_t *lexer, /* Fall through. */ default: - lt->text.length = lexer->start - lt->text.start; - return token; + goto done; } multi: @@ -566,9 +565,13 @@ njs_lexer_next_token(njs_lexer_t *lexer, return njs_lexer_multi(lexer, lt, token, n, multi); } + token = NJS_TOKEN_END; + +done: + lt->text.length = lexer->start - lt->text.start; - return NJS_TOKEN_END; + return token; } diff -r 13161c0357e4 -r 4cc08cb772a2 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 20 20:51:39 2019 +0300 +++ b/src/test/njs_unit_test.c Tue Aug 20 22:59:38 2019 -0400 @@ -66,6 +66,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var \n a, \n b; b"), njs_str("undefined") }, + { njs_str("var a / ="), + njs_str("SyntaxError: Unexpected token \"/\" in 1") }, + { njs_str("var a = 1; var b; a"), njs_str("1") }, From vinaya2008067 at gmail.com Thu Aug 22 12:40:01 2019 From: vinaya2008067 at gmail.com (Vinaya Kumar B) Date: Thu, 22 Aug 2019 18:10:01 +0530 Subject: Custom certificate checks Message-ID: Hello, I have a question relating to HTTPS support configuration in nginx. With below configuration I was able to achieve mutual TLS between client and server applications. *File*: /etc/nginx/conf.d/default.conf upstream backend { server localhost:8180 weight=1; } server { listen 8280 ssl; ssl_protocols TLSv1.2; ssl_certificate /home/ssl/server.crt; ssl_certificate_key /home/ssl/server.key; ssl_verify_client on; ssl_client_certificate /home/ssl/ca.pem; location / { proxy_pass http://backend; } server_name localhost; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } In addition to mutual TLS, I want to perform further custom certificate checks (e.g. validate MAC address embedded in the client certificate). How can I achieve this use case with nginx? Does nginx support a synthetic header which has TLS session info detail (containing peer certificates) that can be used by the proxy?d server to perform necessary custom checks? Or, is there way to plugin some custom code nginx https module to perform any additional checks? Thanks in advance! Kind regards, Vinaya -------------- next part -------------- An HTML attachment was scrubbed... URL: From eran.kornblau at kaltura.com Thu Aug 22 14:11:18 2019 From: eran.kornblau at kaltura.com (Eran Kornblau) Date: Thu, 22 Aug 2019 14:11:18 +0000 Subject: Persistent buffers allocation Message-ID: Hi all, I noticed today that I'm missing something basic... I wanted to allocate some buffers that will live throughout the lifetime of the process = not associated with any specific request. I believe I've already done something like that in the past, and I used the cycle pool for that. However, after digging a bit in the code, I found that in single process mode, if nginx is reloaded, a new cycle is created and the old one destroyed. If my understanding is correct, this has many implications far exceeding the simple question I started with... For example, since the configuration is allocated on the cycle pool, it means that modules should not read the configuration of the request in any asynchronous callback, because there is a chance that the configuration was already freed since the request object was created. I then found this issue - https://trac.nginx.org/nginx/ticket/945 so I guess that this problem is known and ignored because 'master_process off' is only for dev, and no need to support reload there... So, back to my original question... is using ngx_cycle->pool the correct way to allocate such "persistent" buffers? Another option is to use ngx_alloc directly (if the process quits, it doesn't matter...), but cycle pool sounds a bit more elegant (and won't have valgrind report leaks...) Thank you! Eran -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Thu Aug 22 15:34:36 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Aug 2019 15:34:36 +0000 Subject: [njs] Making "prototype" property of function instances writable. Message-ID: details: https://hg.nginx.org/njs/rev/6923d5ac84bc branches: changeset: 1140:6923d5ac84bc user: Dmitry Volyntsev date: Thu Aug 22 18:27:34 2019 +0300 description: Making "prototype" property of function instances writable. This closes #40 issue on Github. diffstat: src/njs_function.c | 93 ++++++++++++++++++++++++++++++++---------------- src/njs_function.h | 2 - src/njs_vmcode.c | 60 +++++++++++++----------------- src/test/njs_unit_test.c | 39 +++++++++++++++++++- 4 files changed, 125 insertions(+), 69 deletions(-) diffs (311 lines): diff -r 91e3f7345e47 -r 6923d5ac84bc src/njs_function.c --- a/src/njs_function.c Tue Aug 20 23:03:26 2019 -0400 +++ b/src/njs_function.c Thu Aug 22 18:27:34 2019 +0300 @@ -780,6 +780,42 @@ njs_function_frame_free(njs_vm_t *vm, nj } +static njs_value_t * +njs_function_property_prototype_create(njs_vm_t *vm, njs_lvlhsh_t *hash, + njs_value_t *prototype) +{ + njs_int_t ret; + njs_object_prop_t *prop; + njs_lvlhsh_query_t lhq; + + const njs_value_t proto_string = njs_string("prototype"); + + prop = njs_object_prop_alloc(vm, &proto_string, prototype, 0); + if (njs_slow_path(prop == NULL)) { + return NULL; + } + + prop->writable = 1; + + lhq.value = prop; + lhq.key_hash = NJS_PROTOTYPE_HASH; + lhq.key = njs_str_value("prototype"); + lhq.replace = 1; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + ret = njs_lvlhsh_insert(hash, &lhq); + + if (njs_fast_path(ret == NJS_OK)) { + return &prop->value; + } + + njs_internal_error(vm, "lvlhsh insert failed"); + + return NULL; +} + + /* * The "prototype" property of user defined functions is created on * demand in private hash of the functions by the "prototype" getter. @@ -794,49 +830,43 @@ njs_int_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { - njs_value_t *proto; - - proto = njs_function_property_prototype_create(vm, value); - - if (njs_fast_path(proto != NULL)) { - *retval = *proto; - return NJS_OK; - } - - return NJS_ERROR; -} - - -njs_value_t * -njs_function_property_prototype_create(njs_vm_t *vm, njs_value_t *value) -{ - njs_value_t *proto, *cons; + njs_value_t *proto, proto_value, *cons; njs_object_t *prototype; njs_function_t *function; - prototype = njs_object_alloc(vm); - if (njs_slow_path(prototype == NULL)) { - return NULL; + if (setval == NULL) { + prototype = njs_object_alloc(vm); + if (njs_slow_path(prototype == NULL)) { + return NJS_ERROR; + } + + njs_set_object(&proto_value, prototype); + + setval = &proto_value; } function = njs_function_value_copy(vm, value); if (njs_slow_path(function == NULL)) { - return NULL; + return NJS_ERROR; + } + + proto = njs_function_property_prototype_create(vm, &function->object.hash, + setval); + if (njs_slow_path(proto == NULL)) { + return NJS_ERROR; } - proto = njs_property_prototype_create(vm, &function->object.hash, - prototype); - if (njs_slow_path(proto == NULL)) { - return NULL; + if (njs_is_object(proto)) { + cons = njs_property_constructor_create(vm, njs_object_hash(proto), + value); + if (njs_slow_path(cons == NULL)) { + return NJS_ERROR; + } } - cons = njs_property_constructor_create(vm, &prototype->hash, value); + *retval = *proto; - if (njs_fast_path(cons != NULL)) { - return proto; - } - - return NULL; + return NJS_OK; } @@ -1197,6 +1227,7 @@ const njs_object_prop_t njs_function_in .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), .value = njs_prop_handler(njs_function_prototype_create), + .writable = 1 }, }; diff -r 91e3f7345e47 -r 6923d5ac84bc src/njs_function.h --- a/src/njs_function.h Tue Aug 20 23:03:26 2019 -0400 +++ b/src/njs_function.h Thu Aug 22 18:27:34 2019 +0300 @@ -118,8 +118,6 @@ njs_int_t njs_function_rest_parameters_i njs_native_frame_t *frame); njs_int_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -njs_value_t *njs_function_property_prototype_create(njs_vm_t *vm, - njs_value_t *value); njs_int_t njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); njs_int_t njs_function_native_frame(njs_vm_t *vm, njs_function_t *function, diff -r 91e3f7345e47 -r 6923d5ac84bc src/njs_vmcode.c --- a/src/njs_vmcode.c Tue Aug 20 23:03:26 2019 -0400 +++ b/src/njs_vmcode.c Thu Aug 22 18:27:34 2019 +0300 @@ -70,7 +70,8 @@ static njs_jump_off_t njs_primitive_valu static njs_jump_off_t njs_function_frame_create(njs_vm_t *vm, njs_value_t *value, const njs_value_t *this, uintptr_t nargs, njs_bool_t ctor); -static njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *value); +static njs_object_t *njs_function_new_object(njs_vm_t *vm, + njs_value_t *constructor); /* * The nJSVM is optimized for an ABIs where the first several arguments @@ -1458,10 +1459,10 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs njs_jump_off_t ret; const njs_value_t *retval; - static njs_value_t prototype_string = njs_string("prototype"); + const njs_value_t prototype_string = njs_string("prototype"); if (!njs_is_function(constructor)) { - njs_type_error(vm, "right argument is not a function"); + njs_type_error(vm, "right argument is not callable"); return NJS_ERROR; } @@ -1469,16 +1470,17 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs if (njs_is_object(object)) { njs_set_undefined(&value); - ret = njs_value_property(vm, constructor, &prototype_string, &value); + ret = njs_value_property(vm, constructor, + njs_value_arg(&prototype_string), &value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } if (njs_fast_path(ret == NJS_OK)) { - if (njs_slow_path(!njs_is_object(&value))) { - njs_internal_error(vm, "prototype is not an object"); + njs_type_error(vm, "Function has non-object prototype " + "in instanceof"); return NJS_ERROR; } @@ -1737,41 +1739,31 @@ njs_function_frame_create(njs_vm_t *vm, static njs_object_t * -njs_function_new_object(njs_vm_t *vm, njs_value_t *value) +njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor) { - njs_value_t *proto; - njs_object_t *object; - njs_jump_off_t ret; - njs_function_t *function; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; + njs_value_t proto; + njs_object_t *object; + njs_jump_off_t ret; + + const njs_value_t prototype_string = njs_string("prototype"); object = njs_object_alloc(vm); - - if (njs_fast_path(object != NULL)) { + if (njs_slow_path(object == NULL)) { + return NULL; + } - lhq.key_hash = NJS_PROTOTYPE_HASH; - lhq.key = njs_str_value("prototype"); - lhq.proto = &njs_object_hash_proto; - function = njs_function(value); - - ret = njs_lvlhsh_find(&function->object.hash, &lhq); + ret = njs_value_property(vm, constructor, njs_value_arg(&prototype_string), + &proto); - if (ret == NJS_OK) { - prop = lhq.value; - proto = &prop->value; - - } else { - proto = njs_function_property_prototype_create(vm, value); - } + if (njs_slow_path(ret == NJS_ERROR)) { + return NULL; + } - if (njs_fast_path(proto != NULL)) { - object->__proto__ = njs_object(proto); - return object; - } - } + if (njs_fast_path(njs_is_object(&proto))) { + object->__proto__ = njs_object(&proto); + } - return NULL; + return object; } diff -r 91e3f7345e47 -r 6923d5ac84bc src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 20 23:03:26 2019 -0400 +++ b/src/test/njs_unit_test.c Thu Aug 22 18:27:34 2019 +0300 @@ -7233,6 +7233,41 @@ static njs_unit_test_t njs_test[] = { njs_str("var F = function (){}; typeof F.prototype"), njs_str("object") }, + { njs_str("var F = function (){}; F.prototype = NaN; ({}) instanceof F"), + njs_str("TypeError: Function has non-object prototype in instanceof") }, + + { njs_str("var F = function() {};" + "[F, F].map((x)=>Object.getOwnPropertyDescriptor(x, 'prototype').writable)" + ".every((x)=> x === true)"), + njs_str("true") }, + + { njs_str("var F = function() {}, a = {t: 1}, b = {t: 2}, x, y; " + "F.prototype = a; x = new F();" + "F.prototype = b; y = new F();" + "x.t == 1 && y.t == 2"), + njs_str("true") }, + + { njs_str("var x = {}, y = function() {}, z; y.prototype = x; z = new y();" + "(z instanceof y) && (z.__proto__ == y.prototype) && (x.isPrototypeOf(z))"), + njs_str("true") }, + + { njs_str("var x = {}, y = function() {}, z; y.prototype = x; z = new y();" + "(z instanceof y) && (z.__proto__ == y.prototype) && (x.isPrototypeOf(z))"), + njs_str("true") }, + + { njs_str("[undefined, null, false, NaN, '']" + ".map((x) => { var f = function() {}; f.prototype = x; " + " return Object.getPrototypeOf(new f()); })" + ".every((x) => x == Object.prototype)"), + njs_str("true") }, + + { njs_str("[undefined, null, false, NaN, '']" + ".map((x) => { var f = function() {}; f.prototype = x; return f; })" + ".map((x) => { try { return ({} instanceof x) ? 1 : 2; } " + " catch (e) { return (e instanceof TypeError) ? 3 : 4; } })" + ".every((x) => x == 3)"), + njs_str("true")}, + { njs_str("new decodeURI('%00')"), njs_str("TypeError: function is not a constructor")}, @@ -8579,7 +8614,7 @@ static njs_unit_test_t njs_test[] = njs_str("true") }, { njs_str("[] instanceof []"), - njs_str("TypeError: right argument is not a function") }, + njs_str("TypeError: right argument is not callable") }, { njs_str("[] instanceof Array"), njs_str("true") }, @@ -8651,7 +8686,7 @@ static njs_unit_test_t njs_test[] = njs_str("TypeError: object is not a function") }, { njs_str("var ex; try {({}) instanceof this} catch (e) {ex = e}; ex"), - njs_str("TypeError: right argument is not a function") }, + njs_str("TypeError: right argument is not callable") }, { njs_str("Function.call(this, 'var x / = 1;')"), njs_str("InternalError: Not implemented") }, From devnexen at gmail.com Thu Aug 22 17:06:25 2019 From: devnexen at gmail.com (David CARLIER) Date: Thu, 22 Aug 2019 18:06:25 +0100 Subject: [PATCH] nginx : shmem tagging anonymous pages on macOS Message-ID: Hi, Here a little change proposal to be able to monitor pages via vmmap command line. Hope it is good enough. Kind regards. -------------- next part -------------- A non-text attachment was scrubbed... Name: ngx-darwin.diff Type: application/octet-stream Size: 2305 bytes Desc: not available URL: From devnexen at gmail.com Fri Aug 23 05:00:29 2019 From: devnexen at gmail.com (David Carlier) Date: Fri, 23 Aug 2019 06:00:29 +0100 Subject: [PATCH] Core: monitoring anonymous map on Darwin platform Message-ID: # HG changeset patch # User David Carlier # Date 1566493379 -3600 # Thu Aug 22 18:02:59 2019 +0100 # Node ID adc68231e590554860b11ee851b293e46ba652db # Parent 9f1f9d6e056a4f85907957ef263f78a426ae4f9c Core: monitoring anonymous map on Darwin platform. Allows to highligh those pages from nginx process with this identifier. diff -r 9f1f9d6e056a -r adc68231e590 auto/os/darwin --- a/auto/os/darwin Mon Aug 19 15:16:06 2019 +0300 +++ b/auto/os/darwin Thu Aug 22 18:02:59 2019 +0100 @@ -118,3 +118,21 @@ ngx_feature_test="int32_t lock = 0; if (!OSAtomicCompareAndSwap32Barrier(0, 1, &lock)) return 1" . auto/feature + +# Darwin can tag anonymous pages to be tracked +# with tools like vmmap +# free ID are guaranteed to be free from 240 to 255 +# for userland applications + +ngx_feature="Darwin tags anonymous pages" +ngx_feature_name=NGX_HAVE_MAP_ANON_TAG +ngx_feature_run=yes +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="void *p = mmap(NULL, 16, PROT_READ, MAP_PRIVATE|MAP_ANON, VM_MAKE_TAG(240), 0); + if (p == MAP_FAILED) return 1; + munmap(p, 16)" + +. auto/feature diff -r 9f1f9d6e056a -r adc68231e590 src/os/unix/ngx_darwin_config.h --- a/src/os/unix/ngx_darwin_config.h Mon Aug 19 15:16:06 2019 +0300 +++ b/src/os/unix/ngx_darwin_config.h Thu Aug 22 18:02:59 2019 +0100 @@ -76,6 +76,10 @@ #include #endif +#if (NGX_HAVE_MAP_ANON_TAG) +#include +#endif + #define NGX_LISTEN_BACKLOG -1 diff -r 9f1f9d6e056a -r adc68231e590 src/os/unix/ngx_shmem.c --- a/src/os/unix/ngx_shmem.c Mon Aug 19 15:16:06 2019 +0300 +++ b/src/os/unix/ngx_shmem.c Thu Aug 22 18:02:59 2019 +0100 @@ -14,9 +14,16 @@ ngx_int_t ngx_shm_alloc(ngx_shm_t *shm) { + ngx_fd_t fd; + +#if (NGX_HAVE_MAP_ANON_TAG) + fd = VM_MAKE_TAG(246); +#else + fd = -1; +#endif shm->addr = (u_char *) mmap(NULL, shm->size, PROT_READ|PROT_WRITE, - MAP_ANON|MAP_SHARED, -1, 0); + MAP_ANON|MAP_SHARED, fd, 0); if (shm->addr == MAP_FAILED) { ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, From xeioex at nginx.com Fri Aug 23 16:10:22 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 23 Aug 2019 16:10:22 +0000 Subject: [njs] Limiting recursion depth while compiling. Message-ID: details: https://hg.nginx.org/njs/rev/8057f3ad56c1 branches: changeset: 1141:8057f3ad56c1 user: Dmitry Volyntsev date: Fri Aug 23 15:13:45 2019 +0300 description: Limiting recursion depth while compiling. This closes #146 issue on Github. diffstat: src/njs_generator.c | 20 +++++++++++++++++++- src/njs_generator.h | 2 ++ src/njs_parser.c | 10 ++++++++++ src/njs_parser.h | 13 +++++++++++++ src/njs_parser_expression.c | 14 ++++++++++++++ 5 files changed, 58 insertions(+), 1 deletions(-) diffs (148 lines): diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_generator.c --- a/src/njs_generator.c Thu Aug 22 18:27:34 2019 +0300 +++ b/src/njs_generator.c Fri Aug 23 15:13:45 2019 +0300 @@ -257,7 +257,7 @@ static const njs_str_t undef_label = { static njs_int_t -njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) +njs_generate(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { if (node == NULL) { return NJS_OK; @@ -508,6 +508,24 @@ njs_generator(njs_vm_t *vm, njs_generato } +njs_inline njs_int_t +njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) +{ + njs_int_t ret; + + if (njs_slow_path(generator->count++ > 1024)) { + njs_range_error(vm, "Maximum call stack size exceeded"); + return NJS_ERROR; + } + + ret = njs_generate(vm, generator, node); + + generator->count--; + + return ret; +} + + static u_char * njs_generate_reserve(njs_vm_t *vm, njs_generator_t *generator, size_t size) { diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_generator.h --- a/src/njs_generator.h Thu Aug 22 18:27:34 2019 +0300 +++ b/src/njs_generator.h Fri Aug 23 15:13:45 2019 +0300 @@ -24,6 +24,8 @@ struct njs_generator_s { /* Parsing Function() or eval(). */ uint8_t runtime; /* 1 bit */ + + njs_uint_t count; }; diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_parser.c --- a/src/njs_parser.c Thu Aug 22 18:27:34 2019 +0300 +++ b/src/njs_parser.c Fri Aug 23 15:13:45 2019 +0300 @@ -127,6 +127,11 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p node->token = NJS_TOKEN_END; + if (njs_slow_path(parser->count != 0)) { + njs_internal_error(vm, "parser->count != 0"); + return NJS_ERROR; + } + return NJS_OK; } @@ -249,7 +254,12 @@ njs_parser_statement_chain(njs_vm_t *vm, last = *child; + njs_parser_enter(vm, parser); + token = njs_parser_statement(vm, parser, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return njs_parser_unexpected_token(vm, parser, token); } diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_parser.h --- a/src/njs_parser.h Thu Aug 22 18:27:34 2019 +0300 +++ b/src/njs_parser.h Fri Aug 23 15:13:45 2019 +0300 @@ -73,6 +73,7 @@ struct njs_parser_s { njs_lexer_t *lexer; njs_parser_node_t *node; njs_parser_scope_t *scope; + njs_uint_t count; }; @@ -113,6 +114,18 @@ void njs_parser_node_error(njs_vm_t *vm, njs_value_type_t type, const char *fmt, ...); +#define njs_parser_enter(vm, parser) \ + do { \ + if (njs_slow_path((parser)->count++ > 1024)) { \ + njs_range_error(vm, "Maximum call stack size exceeded"); \ + return NJS_TOKEN_ERROR; \ + } \ + } while (0) + + +#define njs_parser_leave(parser) ((parser)->count--) + + #define njs_parser_is_lvalue(node) \ ((node)->token == NJS_TOKEN_NAME || (node)->token == NJS_TOKEN_PROPERTY) diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_parser_expression.c --- a/src/njs_parser_expression.c Thu Aug 22 18:27:34 2019 +0300 +++ b/src/njs_parser_expression.c Fri Aug 23 15:13:45 2019 +0300 @@ -744,7 +744,11 @@ njs_parser_call_expression(njs_vm_t *vm, token = njs_parser_new_expression(vm, parser, token); } else { + njs_parser_enter(vm, parser); + token = njs_parser_terminal(vm, parser, token); + + njs_parser_leave(parser); } if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { @@ -761,7 +765,12 @@ njs_parser_call_expression(njs_vm_t *vm, return token; } + njs_parser_enter(vm, parser); + token = njs_parser_call(vm, parser, token, 0); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -863,7 +872,12 @@ njs_parser_new_expression(njs_vm_t *vm, token = njs_parser_new_expression(vm, parser, token); } else { + njs_parser_enter(vm, parser); + token = njs_parser_terminal(vm, parser, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } From rian at alum.mit.edu Fri Aug 23 18:00:41 2019 From: rian at alum.mit.edu (Rian Hunter) Date: Fri, 23 Aug 2019 11:00:41 -0700 Subject: Potential bug in ngx_event.c Message-ID: <797fde8d89aa12a26a84dfd52428a8f5@thelig.ht> Hello, While browsing the source I noticed something that seemed wrong, even though I haven't observed any buggy behavior or have reproduced this bug myself. In ngx_event.c there is a line: if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) shared, cycle->lock_file.data) != NGX_OK) { return NGX_ERROR; } ngx_shmtx_create() is passed &ngx_accept_mutex, but this must be a pointer to a shared memory region otherwise the sem_wait()/sem_post() calls in ngx_shmtx.c will not function correctly. &ngx_accept_mutex is a pointer to BSS, ngx_accept_mutex_ptr is a pointer to shared memory. Is this intentional? Rian From xeioex at nginx.com Fri Aug 23 18:50:04 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 23 Aug 2019 18:50:04 +0000 Subject: [njs] Increased max function nesting. Message-ID: details: https://hg.nginx.org/njs/rev/a3e8a7a51161 branches: changeset: 1142:a3e8a7a51161 user: Dmitry Volyntsev date: Fri Aug 23 20:00:40 2019 +0300 description: Increased max function nesting. diffstat: src/njs_parser.c | 2 +- src/njs_vm.h | 4 ++-- src/test/njs_unit_test.c | 21 ++++++++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diffs (58 lines): diff -r 8057f3ad56c1 -r a3e8a7a51161 src/njs_parser.c --- a/src/njs_parser.c Fri Aug 23 15:13:45 2019 +0300 +++ b/src/njs_parser.c Fri Aug 23 20:00:40 2019 +0300 @@ -153,7 +153,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs if (scope->type == NJS_SCOPE_FUNCTION) { nesting = scope->nesting + 1; - if (nesting <= NJS_MAX_NESTING) { + if (nesting < NJS_MAX_NESTING) { break; } diff -r 8057f3ad56c1 -r a3e8a7a51161 src/njs_vm.h --- a/src/njs_vm.h Fri Aug 23 15:13:45 2019 +0300 +++ b/src/njs_vm.h Fri Aug 23 20:00:40 2019 +0300 @@ -59,9 +59,9 @@ typedef enum { /* * The maximum possible function nesting level is (16 - NJS_SCOPE_CLOSURE), - * that is 11. The 5 is reasonable limit. + * that is 11. The 8 is reasonable limit. */ -#define NJS_MAX_NESTING 5 +#define NJS_MAX_NESTING 8 #define NJS_SCOPES (NJS_SCOPE_CLOSURE + NJS_MAX_NESTING) diff -r 8057f3ad56c1 -r a3e8a7a51161 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Aug 23 15:13:45 2019 +0300 +++ b/src/test/njs_unit_test.c Fri Aug 23 20:00:40 2019 +0300 @@ -6559,9 +6559,24 @@ static njs_unit_test_t njs_test[] = { njs_str("function x(a) { while (a < 2) a++; return a + 1 } x(1) "), njs_str("3") }, - { njs_str("(function(){(function(){(function(){(function(){" - "(function(){(function(){(function(){})})})})})})})"), - njs_str("SyntaxError: The maximum function nesting level is \"5\" in 1") }, + { njs_str("(function(){" + "(function(){" + "(function(){" + "(function(){" + "(function(){" + "(function(){" + "(function(){" + "(function(){" + "(function(){})" + "})" + "})" + "})" + "})" + "})" + "})" + "})" + "})"), + njs_str("SyntaxError: The maximum function nesting level is \"8\" in 1") }, { njs_str("Function.prototype.toString = function () {return 'X'};" "eval"), From xeioex at nginx.com Mon Aug 26 16:00:29 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 26 Aug 2019 16:00:29 +0000 Subject: [njs] Fixed heap-buffer-overflow while parsing regexp literals. Message-ID: details: https://hg.nginx.org/njs/rev/12e9519e7eb4 branches: changeset: 1143:12e9519e7eb4 user: Dmitry Volyntsev date: Mon Aug 26 19:00:13 2019 +0300 description: Fixed heap-buffer-overflow while parsing regexp literals. This closes #174 issue on Github. diffstat: src/njs_regexp.c | 14 +++++++++++--- src/test/njs_unit_test.c | 12 ++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diffs (69 lines): diff -r a3e8a7a51161 -r 12e9519e7eb4 src/njs_regexp.c --- a/src/njs_regexp.c Fri Aug 23 20:00:40 2019 +0300 +++ b/src/njs_regexp.c Mon Aug 26 19:00:13 2019 +0300 @@ -333,14 +333,22 @@ njs_regexp_literal(njs_vm_t *vm, njs_par goto failed; case '[': - while (++p < lexer->end && *p != ']') { + while (1) { + if (++p >= lexer->end) { + goto failed; + } + + if (*p == ']') { + break; + } + switch (*p) { case '\n': case '\r': goto failed; case '\\': - if (++p < lexer->end && (*p == '\n' || *p == '\r')) { + if (++p >= lexer->end || *p == '\n' || *p == '\r') { goto failed; } @@ -351,7 +359,7 @@ njs_regexp_literal(njs_vm_t *vm, njs_par break; case '\\': - if (++p < lexer->end && (*p == '\n' || *p == '\r')) { + if (++p >= lexer->end || *p == '\n' || *p == '\r') { goto failed; } diff -r a3e8a7a51161 -r 12e9519e7eb4 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Aug 23 20:00:40 2019 +0300 +++ b/src/test/njs_unit_test.c Mon Aug 26 19:00:13 2019 +0300 @@ -5877,9 +5877,18 @@ static njs_unit_test_t njs_test[] = { njs_str("/]/"), njs_str("/\\]/") }, + { njs_str("/["), + njs_str("SyntaxError: Unterminated RegExp \"/[\" in 1") }, + + { njs_str("/[\\"), + njs_str("SyntaxError: Unterminated RegExp \"/[\\\" in 1") }, + { njs_str("RegExp(']')"), njs_str("/\\]/") }, + { njs_str("RegExp('[\\\\')"), + njs_str("SyntaxError: pcre_compile(\"[\\\") failed: \\ at end of pattern") }, + { njs_str("RegExp('[\\\\\\\\]]')"), njs_str("/[\\\\]\\]/") }, @@ -7859,6 +7868,9 @@ static njs_unit_test_t njs_test[] = { njs_str("new RegExp('[')"), njs_str("SyntaxError: pcre_compile(\"[\") failed: missing terminating ] for character class") }, + { njs_str("new RegExp('['.repeat(16))"), + njs_str("SyntaxError: pcre_compile(\"[[[[[[[[[[[[[[[[\") failed: missing terminating ] for character class") }, + { njs_str("new RegExp('\\\\')"), njs_str("SyntaxError: pcre_compile(\"\\\") failed: \\ at end of pattern") }, From xeioex at nginx.com Tue Aug 27 14:15:27 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 27 Aug 2019 14:15:27 +0000 Subject: [njs] Limiting recursion depth while compiling unary expressions. Message-ID: details: https://hg.nginx.org/njs/rev/4fd921f02096 branches: changeset: 1144:4fd921f02096 user: Dmitry Volyntsev date: Tue Aug 27 16:31:00 2019 +0300 description: Limiting recursion depth while compiling unary expressions. This extends 8057f3ad56c1 and is related to #146 issue on Github. diffstat: src/njs_parser_expression.c | 40 ++++++++++++++++++++++++++++++---------- 1 files changed, 30 insertions(+), 10 deletions(-) diffs (106 lines): diff -r 12e9519e7eb4 -r 4fd921f02096 src/njs_parser_expression.c --- a/src/njs_parser_expression.c Mon Aug 26 19:00:13 2019 +0300 +++ b/src/njs_parser_expression.c Tue Aug 27 16:31:00 2019 +0300 @@ -225,7 +225,12 @@ njs_parser_assignment_expression(njs_vm_ njs_parser_node_t *node; njs_vmcode_operation_t operation; + njs_parser_enter(vm, parser); + token = njs_parser_conditional_expression(vm, parser, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -332,7 +337,12 @@ njs_parser_assignment_expression(njs_vm_ return token; } + njs_parser_enter(vm, parser); + token = njs_parser_assignment_expression(vm, parser, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -494,7 +504,12 @@ njs_parser_exponential_expression(njs_vm return token; } + njs_parser_enter(vm, parser); + token = njs_parser_exponential_expression(vm, parser, NULL, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -558,7 +573,12 @@ njs_parser_unary_expression(njs_vm_t *vm return next; } + njs_parser_enter(vm, parser); + next = njs_parser_unary_expression(vm, parser, NULL, next); + + njs_parser_leave(parser); + if (njs_slow_path(next <= NJS_TOKEN_ILLEGAL)) { return next; } @@ -740,16 +760,16 @@ static njs_token_t njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { + njs_parser_enter(vm, parser); + if (token == NJS_TOKEN_NEW) { token = njs_parser_new_expression(vm, parser, token); } else { - njs_parser_enter(vm, parser); + token = njs_parser_terminal(vm, parser, token); + } - token = njs_parser_terminal(vm, parser, token); - - njs_parser_leave(parser); - } + njs_parser_leave(parser); if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; @@ -868,23 +888,23 @@ njs_parser_new_expression(njs_vm_t *vm, return token; } + njs_parser_enter(vm, parser); + if (token == NJS_TOKEN_NEW) { token = njs_parser_new_expression(vm, parser, token); } else { - njs_parser_enter(vm, parser); - token = njs_parser_terminal(vm, parser, token); - - njs_parser_leave(parser); - if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + njs_parser_leave(parser); return token; } token = njs_parser_property_expression(vm, parser, token); } + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } From xeioex at nginx.com Wed Aug 28 16:10:24 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 28 Aug 2019 16:10:24 +0000 Subject: [njs] Fixed integer-overflow while parsing exponent of number literals. Message-ID: details: https://hg.nginx.org/njs/rev/949a244b6b2c branches: changeset: 1145:949a244b6b2c user: Dmitry Volyntsev date: Tue Aug 27 18:58:43 2019 +0300 description: Fixed integer-overflow while parsing exponent of number literals. diffstat: src/njs_strtod.c | 13 ++++++++----- src/njs_unix.h | 1 + src/test/njs_unit_test.c | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diffs (80 lines): diff -r 4fd921f02096 -r 949a244b6b2c src/njs_strtod.c --- a/src/njs_strtod.c Tue Aug 27 16:31:00 2019 +0300 +++ b/src/njs_strtod.c Tue Aug 27 18:58:43 2019 +0300 @@ -251,6 +251,7 @@ njs_diyfp_strtod(const u_char *start, si static double njs_strtod_internal(const u_char *start, size_t length, int exp) { + int shift; size_t left, right; const u_char *p, *e, *b; @@ -291,17 +292,17 @@ njs_strtod_internal(const u_char *start, return 0.0; } - exp += (int) (left - right); + shift = (int) (left - right); - if (exp + (int) length - 1 >= NJS_DECIMAL_POWER_MAX) { + if (exp >= NJS_DECIMAL_POWER_MAX - shift - (int) length + 1) { return INFINITY; } - if (exp + (int) length <= NJS_DECIMAL_POWER_MIN) { + if (exp <= NJS_DECIMAL_POWER_MIN - shift - (int) length) { return 0.0; } - return njs_diyfp_strtod(start, length, exp); + return njs_diyfp_strtod(start, length, exp + shift); } @@ -386,7 +387,9 @@ njs_strtod(const u_char **start, const u break; } - exp = exp * 10 + c; + if (exp < (INT_MAX - 9) / 10) { + exp = exp * 10 + c; + } } exponent += minus ? -exp : exp; diff -r 4fd921f02096 -r 949a244b6b2c src/njs_unix.h --- a/src/njs_unix.h Tue Aug 27 16:31:00 2019 +0300 +++ b/src/njs_unix.h Tue Aug 27 18:58:43 2019 +0300 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff -r 4fd921f02096 -r 949a244b6b2c src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 27 16:31:00 2019 +0300 +++ b/src/test/njs_unit_test.c Tue Aug 27 18:58:43 2019 +0300 @@ -12366,6 +12366,21 @@ static njs_unit_test_t njs_test[] = { njs_str("parseFloat('12345abc')"), njs_str("12345") }, + { njs_str("parseFloat('1e2147483647')"), + njs_str("Infinity") }, + + { njs_str("parseFloat('1e-2147483647')"), + njs_str("0") }, + + { njs_str("parseFloat('1e-2147483648')"), + njs_str("0") }, + + { njs_str("parseFloat('1e' + '5'.repeat(16))"), + njs_str("Infinity") }, + + { njs_str("parseFloat('1e-' + '5'.repeat(16))"), + njs_str("0") }, + { njs_str("parseFloat('0x')"), njs_str("0") }, From xeioex at nginx.com Wed Aug 28 16:10:24 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 28 Aug 2019 16:10:24 +0000 Subject: [njs] Fixed parseFloat(). Message-ID: details: https://hg.nginx.org/njs/rev/719c79b0f07d branches: changeset: 1146:719c79b0f07d user: Dmitry Volyntsev date: Wed Aug 28 19:10:01 2019 +0300 description: Fixed parseFloat(). diffstat: src/njs_number.h | 2 +- src/njs_string.c | 11 +++++++---- src/njs_strtod.c | 4 ++++ src/test/njs_unit_test.c | 22 ++++++++++++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) diffs (105 lines): diff -r 949a244b6b2c -r 719c79b0f07d src/njs_number.h --- a/src/njs_number.h Tue Aug 27 18:58:43 2019 +0300 +++ b/src/njs_number.h Wed Aug 28 19:10:01 2019 +0300 @@ -139,7 +139,7 @@ njs_primitive_value_to_number(const njs_ return njs_number(value); } - return njs_string_to_number(value, 1); + return njs_string_to_number(value, 0); } diff -r 949a244b6b2c -r 719c79b0f07d src/njs_string.c --- a/src/njs_string.c Tue Aug 27 18:58:43 2019 +0300 +++ b/src/njs_string.c Wed Aug 28 19:10:01 2019 +0300 @@ -3866,6 +3866,7 @@ njs_string_to_number(const njs_value_t * { double num; size_t size; + uint32_t u; njs_bool_t minus; const u_char *p, *start, *end; @@ -3884,15 +3885,17 @@ njs_string_to_number(const njs_value_t * end = p + size; while (p < end) { - if (*p != ' ' && *p != '\t') { + start = p; + u = njs_utf8_decode(&p, end); + + if (!njs_utf8_is_whitespace(u)) { + p = start; break; } - - p++; } if (p == end) { - return 0.0; + return parse_float ? NAN : 0.0; } minus = 0; diff -r 949a244b6b2c -r 719c79b0f07d src/njs_strtod.c --- a/src/njs_strtod.c Tue Aug 27 18:58:43 2019 +0300 +++ b/src/njs_strtod.c Wed Aug 28 19:10:01 2019 +0300 @@ -358,6 +358,10 @@ njs_strtod(const u_char **start, const u } } + if (pos == data) { + return NAN; + } + e = p + 1; if (e < end && (*p == 'e' || *p == 'E')) { diff -r 949a244b6b2c -r 719c79b0f07d src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Aug 27 18:58:43 2019 +0300 +++ b/src/test/njs_unit_test.c Wed Aug 28 19:10:01 2019 +0300 @@ -547,6 +547,9 @@ static njs_unit_test_t njs_test[] = { njs_str("5 - '\t 0x2 \t'"), njs_str("3") }, + { njs_str("5 - '\t\\u000c0x2 \t'"), + njs_str("3") }, + { njs_str("5 - '0x2 z'"), njs_str("NaN") }, @@ -4152,6 +4155,10 @@ static njs_unit_test_t njs_test[] = "Array.prototype.slice.call(Array.prototype.fill.call(o, 1))"), njs_str("1,1") }, + { njs_str("var o = {}; Object.defineProperty(o, 'length', {get:()=>'0x0002'}); " + "Array.prototype.slice.call(Array.prototype.fill.call(o, 1))"), + njs_str("1,1") }, + { njs_str("var o = {}; Object.defineProperty(o, 'length', {get:()=> {throw TypeError('Boom')}}); " "Array.prototype.fill.call(o, 1)"), njs_str("TypeError: Boom") }, @@ -12366,6 +12373,21 @@ static njs_unit_test_t njs_test[] = { njs_str("parseFloat('12345abc')"), njs_str("12345") }, + { njs_str("parseFloat('')"), + njs_str("NaN") }, + + { njs_str("parseFloat(' \t')"), + njs_str("NaN") }, + + { njs_str("parseFloat('\\u20281')"), + njs_str("1") }, + + { njs_str("parseFloat('e11')"), + njs_str("NaN") }, + + { njs_str("parseFloat({toString(){return ' 1'}})"), + njs_str("1") }, + { njs_str("parseFloat('1e2147483647')"), njs_str("Infinity") }, From alexander.borisov at nginx.com Wed Aug 28 16:21:14 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Wed, 28 Aug 2019 16:21:14 +0000 Subject: [njs] Fixed Array prototype functions according to the specification. Message-ID: details: https://hg.nginx.org/njs/rev/50fded8ccee5 branches: changeset: 1147:50fded8ccee5 user: Alexander Borisov date: Wed Aug 28 14:59:28 2019 +0300 description: Fixed Array prototype functions according to the specification. The following fuctions were fixed: every, filter, find, findIndex, forEach, map, reduce, some. diffstat: src/njs_array.c | 789 ++++++++++++++++++++++++++++++---------------- src/njs_object.c | 27 + src/njs_object.h | 1 + src/njs_value.c | 22 + src/njs_value.h | 9 + src/test/njs_unit_test.c | 114 ++++++- 6 files changed, 685 insertions(+), 277 deletions(-) diffs (truncated from 1267 to 1000 lines): diff -r 719c79b0f07d -r 50fded8ccee5 src/njs_array.c --- a/src/njs_array.c Wed Aug 28 19:10:01 2019 +0300 +++ b/src/njs_array.c Wed Aug 28 14:59:28 2019 +0300 @@ -8,6 +8,19 @@ #include +typedef struct { + njs_function_t *function; + njs_value_t *this_arg; + njs_value_t *value; + + njs_array_t *array; +} njs_array_interator_args_t; + + +typedef njs_int_t (*njs_array_iterator_handler_t)(njs_vm_t *vm, + njs_array_interator_args_t *args, njs_value_t *entry, uint32_t n); + + static njs_int_t njs_array_prototype_slice_copy(njs_vm_t *vm, njs_value_t *this, int64_t start, int64_t length); static njs_value_t *njs_array_copy(njs_value_t *dst, njs_value_t *src); @@ -1349,54 +1362,194 @@ njs_array_prototype_fill(njs_vm_t *vm, n njs_inline njs_int_t -njs_array_iterator_call(njs_vm_t *vm, njs_function_t *function, - const njs_value_t *this_arg, const njs_value_t *value, uint32_t n, - const njs_value_t *array) +njs_array_iterator_call(njs_vm_t *vm, njs_array_interator_args_t *args, + const njs_value_t *entry, uint32_t n) { njs_value_t arguments[3]; /* GC: array elt, array */ - arguments[0] = *value; + arguments[0] = *entry; njs_set_number(&arguments[1], n); - arguments[2] = *array; - - return njs_function_call(vm, function, this_arg, arguments, 3, + arguments[2] = *args->value; + + return njs_function_call(vm, args->function, args->this_arg, arguments, 3, &vm->retval); } +njs_inline njs_int_t +njs_array_iterator(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_array_iterator_handler_t handler, uint32_t length) +{ + uint32_t i; + njs_int_t ret; + njs_value_t *entry, *value, character, index, string_obj, prop; + njs_object_t *object; + const u_char *p, *end, *pos; + njs_string_prop_t string_prop; + + value = args->value; + + if (njs_is_array(value)) { + if (njs_slow_path(!njs_object_hash_is_empty(value))) { + goto process_object; + } + + length = njs_array_len(value); + + for (i = 0; i < length; i++) { + entry = &njs_array_start(value)[i]; + + ret = handler(vm, args, entry, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret > 0) { + return NJS_DECLINED; + } + + return NJS_ERROR; + } + + length = njs_min(length, njs_array_len(value)); + } + + return NJS_OK; + } + + if (njs_is_string(value) || njs_is_object_string(value)) { + + if (njs_is_string(value)) { + object = njs_object_value_alloc(vm, value, NJS_STRING); + if (njs_slow_path(object == NULL)) { + return NJS_ERROR; + } + + njs_set_type_object(&string_obj, object, NJS_OBJECT_STRING); + + args->value = &string_obj; + } + else { + value = njs_object_value(value); + } + + length = (uint32_t) njs_string_prop(&string_prop, value); + + p = string_prop.start; + end = p + string_prop.size; + + if (length == string_prop.size) { + /* Byte or ASCII string. */ + + for (i = 0; i < length; i++) { + /* This cannot fail. */ + (void) njs_string_new(vm, &character, p++, 1, 1); + + ret = handler(vm, args, &character, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret > 0) { + return NJS_DECLINED; + } + + return NJS_ERROR; + } + } + + } else { + /* UTF-8 string. */ + + for (i = 0; i < length; i++) { + pos = njs_utf8_next(p, end); + + /* This cannot fail. */ + (void) njs_string_new(vm, &character, p, pos - p, 1); + + ret = handler(vm, args, &character, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret > 0) { + return NJS_DECLINED; + } + + return NJS_ERROR; + } + + p = pos; + } + } + + return NJS_OK; + } + + if (!njs_is_object(value)) { + return NJS_OK; + } + +process_object: + + if (length > NJS_ARRAY_MAX_LENGTH) { + ret = njs_object_length(vm, value, &length); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } + + for (i = 0; i < length; i++) { + njs_uint32_to_string(&index, i); + + ret = njs_value_property(vm, value, &index, &prop); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret != NJS_DECLINED) { + ret = handler(vm, args, &prop, i); + if (njs_slow_path(ret != NJS_OK)) { + if (ret > 0) { + return NJS_DECLINED; + } + + return NJS_ERROR; + } + } + } + + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_for_each(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + if (njs_is_valid(entry)) { + return njs_array_iterator_call(vm, args, entry, n); + } + + return NJS_OK; +} + + static njs_int_t njs_array_prototype_for_each(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_value_t *array, *value, *this_arg; - njs_function_t *function; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - for (i = 0; i < length; i++) { - value = &njs_array_start(array)[i]; - - if (njs_is_valid(value)) { - ret = njs_array_iterator_call(vm, function, this_arg, value, i, - array); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - length = njs_min(length, njs_array_len(array)); + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + ret = njs_array_iterator(vm, &iargs, njs_array_handler_for_each, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } njs_set_undefined(&vm->retval); @@ -1406,48 +1559,79 @@ njs_array_prototype_for_each(njs_vm_t *v static njs_int_t +njs_array_handler_some(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + + if (njs_is_valid(entry)) { + ret = njs_array_iterator_call(vm, args, entry, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_is_true(&vm->retval)) { + vm->retval = njs_value_true; + + return 1; + } + } + + return NJS_OK; +} + + +static njs_int_t njs_array_prototype_some(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_value_t *array, *value, *this_arg; - njs_function_t *function; - const njs_value_t *retval; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - retval = &njs_value_false; - - for (i = 0; i < length; i++) { - value = &njs_array_start(array)[i]; - - if (njs_is_valid(value)) { - ret = njs_array_iterator_call(vm, function, this_arg, value, i, - array); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (njs_is_true(&vm->retval)) { - retval = &njs_value_true; - break; - } + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + ret = njs_array_iterator(vm, &iargs, njs_array_handler_some, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret != NJS_DECLINED) { + vm->retval = njs_value_false; + } + + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_every(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + + if (njs_is_valid(entry)) { + ret = njs_array_iterator_call(vm, args, entry, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - length = njs_min(length, njs_array_len(array)); + if (!njs_is_true(&vm->retval)) { + vm->retval = njs_value_false; + + return 1; + } } - vm->retval = *retval; - return NJS_OK; } @@ -1456,45 +1640,58 @@ static njs_int_t njs_array_prototype_every(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_value_t *array, *value, *this_arg; - njs_function_t *function; - const njs_value_t *retval; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - retval = &njs_value_true; - - for (i = 0; i < length; i++) { - value = &njs_array_start(array)[i]; - - if (njs_is_valid(value)) { - ret = njs_array_iterator_call(vm, function, this_arg, value, i, - array); + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + ret = njs_array_iterator(vm, &iargs, njs_array_handler_every, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret != NJS_DECLINED) { + vm->retval = njs_value_true; + } + + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_filter(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + njs_value_t copy; + + if (njs_is_valid(entry)) { + copy = *entry; + + ret = njs_array_iterator_call(vm, args, ©, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_is_true(&vm->retval)) { + + ret = njs_array_add(vm, args->array, ©); if (njs_slow_path(ret != NJS_OK)) { return ret; } - - if (!njs_is_true(&vm->retval)) { - retval = &njs_value_false; - break; - } } - - length = njs_min(length, njs_array_len(array)); } - vm->retval = *retval; - return NJS_OK; } @@ -1503,49 +1700,61 @@ static njs_int_t njs_array_prototype_filter(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_array_t *retval; - njs_value_t *array, value, *this_arg; - njs_function_t *function; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - retval = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE); - if (njs_slow_path(retval == NULL)) { + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + iargs.array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE); + if (njs_slow_path(iargs.array == NULL)) { return NJS_ERROR; } - for (i = 0; i < length; i++) { - value = njs_array_start(array)[i]; - - if (njs_is_valid(&value)) { - ret = njs_array_iterator_call(vm, function, this_arg, &value, i, - array); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (njs_is_true(&vm->retval)) { - ret = njs_array_add(vm, retval, &value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - } - - length = njs_min(length, njs_array_len(array)); + ret = njs_array_iterator(vm, &iargs, njs_array_handler_filter, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - njs_set_array(&vm->retval, retval); + njs_set_array(&vm->retval, iargs.array); + + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_find(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + njs_value_t copy; + + if (njs_is_valid(entry)) { + copy = *entry; + + } else { + njs_set_undefined(©); + } + + ret = njs_array_iterator_call(vm, args, ©, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_is_true(&vm->retval)) { + vm->retval = copy; + + return 1; + } return NJS_OK; } @@ -1555,45 +1764,58 @@ static njs_int_t njs_array_prototype_find(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_value_t *array, value, *this_arg; - njs_function_t *function; - const njs_value_t *retval; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - retval = &njs_value_undefined; - - for (i = 0; i < length; i++) { - value = njs_array_start(array)[i]; - - if (!njs_is_valid(&value)) { - njs_set_undefined(&value); - } - - ret = njs_array_iterator_call(vm, function, this_arg, &value, i, array); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (njs_is_true(&vm->retval)) { - retval = &value; - break; - } - - length = njs_min(length, njs_array_len(array)); + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + ret = njs_array_iterator(vm, &iargs, njs_array_handler_find, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret != NJS_DECLINED) { + vm->retval = njs_value_undefined; } - vm->retval = *retval; + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_find_index(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + njs_value_t copy; + + if (njs_is_valid(entry)) { + copy = *entry; + + } else { + njs_set_undefined(©); + } + + ret = njs_array_iterator_call(vm, args, ©, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_is_true(&vm->retval)) { + njs_set_number(&vm->retval, n); + + return 1; + } return NJS_OK; } @@ -1603,46 +1825,56 @@ static njs_int_t njs_array_prototype_find_index(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double index; - uint32_t i, length; - njs_int_t ret; - njs_value_t *array, value, *this_arg; - njs_function_t *function; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - index = -1; - - for (i = 0; i < length; i++) { - value = njs_array_start(array)[i]; - - if (!njs_is_valid(&value)) { - njs_set_undefined(&value); - } - - ret = njs_array_iterator_call(vm, function, this_arg, &value, i, array); + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + ret = njs_array_iterator(vm, &iargs, njs_array_handler_find_index, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret != NJS_DECLINED) { + njs_set_number(&vm->retval, -1); + } + + return NJS_OK; +} + + +static njs_int_t +njs_array_handler_map(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + njs_array_t *retval; + + retval = args->array; + + njs_set_invalid(&retval->start[n]); + + if (njs_is_valid(entry)) { + ret = njs_array_iterator_call(vm, args, entry, n); if (njs_slow_path(ret != NJS_OK)) { return ret; } - if (njs_is_true(&vm->retval)) { - index = i; - break; + if (njs_is_valid(&vm->retval)) { + retval->start[n] = vm->retval; } - - length = njs_min(length, njs_array_len(array)); } - njs_set_number(&vm->retval, index); - return NJS_OK; } @@ -1651,75 +1883,93 @@ static njs_int_t njs_array_prototype_map(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length, size; - njs_int_t ret; - njs_array_t *retval; - njs_value_t *array, *value, *this_arg; - njs_function_t *function; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + uint32_t length, i; + njs_int_t ret; + njs_array_t *array; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - this_arg = njs_arg(args, nargs, 2); - - size = length; - - retval = njs_array_alloc(vm, length, 0); - if (njs_slow_path(retval == NULL)) { + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = njs_arg(args, nargs, 2); + + ret = njs_value_length(vm, iargs.value, &length); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + iargs.array = njs_array_alloc(vm, length, 0); + if (njs_slow_path(iargs.array == NULL)) { return NJS_ERROR; } - for (i = 0; i < length; i++) { - njs_set_invalid(&retval->start[i]); - - value = &njs_array_start(array)[i]; - - if (njs_is_valid(value)) { - ret = njs_array_iterator_call(vm, function, this_arg, value, i, - array); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (njs_is_valid(&vm->retval)) { - retval->start[i] = vm->retval; + if (length > 0) { + ret = njs_array_iterator(vm, &iargs, njs_array_handler_map, length); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (njs_is_array(iargs.value) + && njs_object_hash_is_empty(iargs.value)) + { + array = iargs.array; + + for (i = njs_array_len(iargs.value); i < length; i++) { + njs_set_invalid(&array->start[i]); } } - - length = njs_min(length, njs_array_len(array)); } - for ( ; i < size; i++) { - njs_set_invalid(&retval->start[i]); - } - - njs_set_array(&vm->retval, retval); + njs_set_array(&vm->retval, iargs.array); return NJS_OK; } njs_inline njs_int_t -njs_array_iterator_reduce(njs_vm_t *vm, njs_function_t *function, - njs_value_t *accumulator, njs_value_t *value, uint32_t n, - njs_value_t *array) +njs_array_iterator_reduce(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) { njs_value_t arguments[5]; /* GC: array elt, array */ njs_set_undefined(&arguments[0]); - arguments[1] = *accumulator; - arguments[2] = *value; + arguments[1] = *args->this_arg; + arguments[2] = *entry; njs_set_number(&arguments[3], n); - arguments[4] = *array; - - return njs_function_apply(vm, function, arguments, 5, accumulator); + arguments[4] = *args->value; + + return njs_function_apply(vm, args->function, arguments, 5, args->this_arg); +} + + +static njs_int_t +njs_array_handler_reduce(njs_vm_t *vm, njs_array_interator_args_t *args, + njs_value_t *entry, uint32_t n) +{ + njs_int_t ret; + + if (njs_is_valid(entry)) { + + if (!njs_is_valid(args->this_arg)) { + *(args->this_arg) = *entry; + return NJS_OK; + } + + ret = njs_array_iterator_reduce(vm, args, entry, n); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + } + + return NJS_OK; } @@ -1727,44 +1977,31 @@ static njs_int_t njs_array_prototype_reduce(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint32_t i, length; - njs_int_t ret; - njs_value_t accumulator, *array, *value; - njs_function_t *function; - - if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { + njs_int_t ret; + njs_value_t accumulator; + njs_array_interator_args_t iargs; + + if (njs_is_null_or_undefined(njs_arg(args, nargs, 0)) + || !njs_is_function(njs_arg(args, nargs, 1))) + { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); - njs_set_invalid(&accumulator); if (nargs > 2) { - accumulator = args[2]; + accumulator = *njs_argument(args, 2); } - for (i = 0; i < length; i++) { - value = &njs_array_start(array)[i]; - - if (njs_is_valid(value)) { - - if (!njs_is_valid(&accumulator)) { - accumulator = njs_array_start(array)[i]; - continue; - } - - ret = njs_array_iterator_reduce(vm, function, &accumulator, value, - i, array); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - length = njs_min(length, njs_array_len(array)); + iargs.value = njs_argument(args, 0); + iargs.function = njs_function(&args[1]); + iargs.this_arg = &accumulator; + + ret = njs_array_iterator(vm, &iargs, njs_array_handler_reduce, + NJS_ARRAY_MAX_LENGTH + 1); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } if (!njs_is_valid(&accumulator)) { @@ -1782,20 +2019,19 @@ static njs_int_t njs_array_prototype_reduce_right(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int32_t i; - uint32_t length; - njs_int_t ret; - njs_value_t accumulator, *array, *value; - njs_function_t *function; + int32_t i; + uint32_t length; + njs_int_t ret; + njs_value_t accumulator, *value, *entry; + njs_array_interator_args_t iter; if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) { njs_type_error(vm, "unexpected iterator arguments"); return NJS_ERROR; } - array = &args[0]; - length = njs_array_len(array); - function = njs_function(&args[1]); + value = &args[0]; + length = njs_array_len(value); njs_set_invalid(&accumulator); @@ -1803,24 +2039,27 @@ njs_array_prototype_reduce_right(njs_vm_ accumulator = args[2]; } + iter.value = value; + iter.function = njs_function(&args[1]); + iter.this_arg = &accumulator; + for (i = length - 1; i >= 0; i--) { - value = &njs_array_start(array)[i]; - - if (njs_is_valid(value)) { + entry = &njs_array_start(value)[i]; + + if (njs_is_valid(entry)) { if (!njs_is_valid(&accumulator)) { - accumulator = njs_array_start(array)[i]; + accumulator = njs_array_start(value)[i]; continue; } - ret = njs_array_iterator_reduce(vm, function, &accumulator, value, - i, array); + ret = njs_array_iterator_reduce(vm, &iter, entry, i); if (njs_slow_path(ret != NJS_OK)) { return ret; } } - length = njs_min(length, njs_array_len(array)); + length = njs_min(length, njs_array_len(value)); } if (!njs_is_valid(&accumulator)) { diff -r 719c79b0f07d -r 50fded8ccee5 src/njs_object.c --- a/src/njs_object.c Wed Aug 28 19:10:01 2019 +0300 +++ b/src/njs_object.c Wed Aug 28 14:59:28 2019 +0300 @@ -2297,3 +2297,30 @@ const njs_object_init_t njs_object_prot njs_object_prototype_properties, njs_nitems(njs_object_prototype_properties), }; + + +njs_int_t +njs_object_length(njs_vm_t *vm, njs_value_t *value, uint32_t *length) +{ + njs_int_t ret; + njs_value_t value_length; + + const njs_value_t string_length = njs_string("length"); From xeioex at nginx.com Thu Aug 29 16:19:07 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Aug 2019 16:19:07 +0000 Subject: [njs] Postponing copying of not-configurable PROPERTY_HANDLER properties. Message-ID: details: https://hg.nginx.org/njs/rev/ac633d007ac5 branches: changeset: 1154:ac633d007ac5 user: Dmitry Volyntsev date: Thu Aug 29 19:18:53 2019 +0300 description: Postponing copying of not-configurable PROPERTY_HANDLER properties. Since df385232d2af a shared property is copied to object hash on the first access. It simplified changing of configurable shared properties. Since 50fded8ccee5 Array.prototype functions treat empty array hash as a sign that array instance is simple (without property getters and non-numerical properties) to iterate over array values optimally. Accessing "length" property made a copy in array hash. As a result next iterations over array became not optimized. The fix is to postpone making a mutable copy of not-configurable NJS_PROPERTY_HANDLER properties until they are really required to change. This closes #220 issue on Github. diffstat: src/njs_object.h | 1 + src/njs_object_prop.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ src/njs_value.c | 81 +++++---------------------------------------- src/njs_value.h | 2 + src/test/njs_unit_test.c | 8 ++++ 5 files changed, 105 insertions(+), 71 deletions(-) diffs (254 lines): diff -r 8609f5316ff1 -r ac633d007ac5 src/njs_object.h --- a/src/njs_object.h Thu Aug 29 17:11:41 2019 +0300 +++ b/src/njs_object.h Thu Aug 29 19:18:53 2019 +0300 @@ -71,6 +71,7 @@ njs_int_t njs_object_prototype_to_string njs_uint_t nargs, njs_index_t unused); njs_int_t njs_object_length(njs_vm_t *vm, njs_value_t *value, uint32_t *dest); +njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, const njs_value_t *value, uint8_t attributes); njs_int_t njs_object_property(njs_vm_t *vm, const njs_value_t *value, diff -r 8609f5316ff1 -r ac633d007ac5 src/njs_object_prop.c --- a/src/njs_object_prop.c Thu Aug 29 17:11:41 2019 +0300 +++ b/src/njs_object_prop.c Thu Aug 29 19:18:53 2019 +0300 @@ -241,6 +241,20 @@ njs_object_prop_define(njs_vm_t *vm, njs { goto exception; } + + if (pq.shared) { + /* + * shared non-configurable NJS_PROPERTY_HANDLER are not copied + * by njs_object_property_query(). + */ + + ret = njs_prop_private_copy(vm, &pq); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + prev = pq.lhq.value; + } } if (njs_is_generic_descriptor(prop)) { @@ -358,6 +372,76 @@ exception: } +njs_int_t +njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) +{ + njs_int_t ret; + njs_function_t *function; + njs_object_prop_t *prop, *shared, *name; + njs_lvlhsh_query_t lhq; + + static const njs_value_t name_string = njs_string("name"); + + prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), + sizeof(njs_object_prop_t)); + if (njs_slow_path(prop == NULL)) { + njs_memory_error(vm); + return NJS_ERROR; + } + + shared = pq->lhq.value; + *prop = *shared; + + pq->lhq.replace = 0; + pq->lhq.value = prop; + pq->lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + if (!njs_is_function(&prop->value)) { + return NJS_OK; + } + + function = njs_function_value_copy(vm, &prop->value); + if (njs_slow_path(function == NULL)) { + return NJS_ERROR; + } + + if (function->ctor) { + function->object.shared_hash = vm->shared->function_instance_hash; + + } else { + function->object.shared_hash = vm->shared->arrow_instance_hash; + } + + name = njs_object_prop_alloc(vm, &name_string, &prop->name, 0); + if (njs_slow_path(name == NULL)) { + return NJS_ERROR; + } + + name->configurable = 1; + + lhq.key_hash = NJS_NAME_HASH; + lhq.key = njs_str_value("name"); + lhq.replace = 0; + lhq.value = name; + lhq.proto = &njs_object_hash_proto; + lhq.pool = vm->mem_pool; + + ret = njs_lvlhsh_insert(&function->object.hash, &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NJS_ERROR; + } + + return NJS_OK; +} + + static njs_int_t njs_descriptor_prop(njs_vm_t *vm, njs_object_prop_t *prop, const njs_value_t *desc) diff -r 8609f5316ff1 -r ac633d007ac5 src/njs_value.c --- a/src/njs_value.c Thu Aug 29 17:11:41 2019 +0300 +++ b/src/njs_value.c Thu Aug 29 19:18:53 2019 +0300 @@ -11,7 +11,6 @@ static njs_int_t njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_object_t *object, const njs_value_t *key); -static njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_array_t *array, uint32_t index); static njs_int_t njs_string_property_query(njs_vm_t *vm, @@ -681,6 +680,16 @@ njs_object_property_query(njs_vm_t *vm, ret = njs_lvlhsh_find(&proto->shared_hash, &pq->lhq); if (ret == NJS_OK) { + prop = pq->lhq.value; + + if (!prop->configurable + && prop->type == NJS_PROPERTY_HANDLER) + { + /* Postpone making a mutable NJS_PROPERTY_HANDLER copy. */ + pq->shared = 1; + return ret; + } + return njs_prop_private_copy(vm, pq); } } @@ -699,76 +708,6 @@ njs_object_property_query(njs_vm_t *vm, static njs_int_t -njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) -{ - njs_int_t ret; - njs_function_t *function; - njs_object_prop_t *prop, *shared, *name; - njs_lvlhsh_query_t lhq; - - static const njs_value_t name_string = njs_string("name"); - - prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_object_prop_t)); - if (njs_slow_path(prop == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; - } - - shared = pq->lhq.value; - *prop = *shared; - - pq->lhq.replace = 0; - pq->lhq.value = prop; - pq->lhq.pool = vm->mem_pool; - - ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } - - if (!njs_is_function(&prop->value)) { - return NJS_OK; - } - - function = njs_function_value_copy(vm, &prop->value); - if (njs_slow_path(function == NULL)) { - return NJS_ERROR; - } - - if (function->ctor) { - function->object.shared_hash = vm->shared->function_instance_hash; - - } else { - function->object.shared_hash = vm->shared->arrow_instance_hash; - } - - name = njs_object_prop_alloc(vm, &name_string, &prop->name, 0); - if (njs_slow_path(name == NULL)) { - return NJS_ERROR; - } - - name->configurable = 1; - - lhq.key_hash = NJS_NAME_HASH; - lhq.key = njs_str_value("name"); - lhq.replace = 0; - lhq.value = name; - lhq.proto = &njs_object_hash_proto; - lhq.pool = vm->mem_pool; - - ret = njs_lvlhsh_insert(&function->object.hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } - - return NJS_OK; -} - - -static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_array_t *array, uint32_t index) { diff -r 8609f5316ff1 -r ac633d007ac5 src/njs_value.h --- a/src/njs_value.h Thu Aug 29 17:11:41 2019 +0300 +++ b/src/njs_value.h Thu Aug 29 19:18:53 2019 +0300 @@ -352,6 +352,7 @@ typedef struct { njs_object_t *prototype; njs_object_prop_t *own_whiteout; uint8_t query; + uint8_t shared; uint8_t own; } njs_property_query_t; @@ -810,6 +811,7 @@ njs_set_object_value(njs_value_t *value, (pq)->lhq.value = NULL; \ (pq)->own_whiteout = NULL; \ (pq)->query = _query; \ + (pq)->shared = 0; \ (pq)->own = _own; \ } while (0) diff -r 8609f5316ff1 -r ac633d007ac5 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Aug 29 17:11:41 2019 +0300 +++ b/src/test/njs_unit_test.c Thu Aug 29 19:18:53 2019 +0300 @@ -3729,6 +3729,14 @@ static njs_unit_test_t njs_test[] = { njs_str("var a = [1,2]; a[100] = 100; a[100] +' '+ a.length"), njs_str("100 101") }, + { njs_str("var a = []; Object.defineProperty(a, 'length', {writable:0});" + "Object.getOwnPropertyDescriptor(a, 'length').writable"), + njs_str("false") }, + + { njs_str("var a = []; Object.defineProperty(a, 'length', {writable:0});" + "Object.defineProperty(a, 'length', {writable:true})"), + njs_str("TypeError: Cannot redefine property: \"length\"") }, + { njs_str("Array.prototype.slice(1)"), njs_str("") }, From guillaume-nginx at outters.eu Thu Aug 29 06:04:41 2019 From: guillaume-nginx at outters.eu (Guillaume Outters) Date: Thu, 29 Aug 2019 08:04:41 +0200 Subject: [PATCH] ngx_conf_file: "include ./" acts relative to currently parsed file Message-ID: <704100d8a8772a4bc2fa.1567058681@bas> Hello, as an Nginx user, I regularly discover new features that prove useful if not game changers. However I stay puzzled (nearly since I started using it) on why the config include system does not allow relative paths, that is, relative to the currently parsed file. This would allow for simple modular config designs, where a "main" server config file can embed the snippets that are deployed next to it. The only tips I see on the forums and so is "hey, just use a templating system to absolutize every include at deployment time", which takes us away from Nginx' KISS philosophy. In an ideal world, my production nginx.conf would only include /var/www/*/app.conf, and I could drop my "blorp" web app (that I developed on /home/gui/www/blorp) in /var/www and have it running at the next nginx reload, with it correctly loading every location /xxx { include inc/phpfpm.conf; } of its app.conf. For now, I either have to centralize the snippets in /etc/nginx/inc/phpfpm.conf (thus when a new rule has to be added my developer has to tell my system operator to apply the change to the centralized file), or inline the snippets in the (then monolithic) app.conf (hey, duplication!), or hardcode the snippet's path as /var/www/blorp/inc/phpfpm.conf (and symlink it on my dev machine so that prod and dev config files are shared?), or better make the app.conf a template and fill absolute paths at deployment, so that if I want to run my shiny new version of blorp as blorp-ng along blorp it does not include the old version's phpfpm.conf erronously. The following patch adds a simple heuristic to include: if the includee starts with "./", it is considered relative to the current file. If not, the current heuristic applies (paths stay relative to the prefix). I would be interested in learning the flaws or drawbacks in this (bad?) idea. I first thought "security", (disallowing relative includes keeps included files under control in config's root), but anyhow, either you keep total control on the config (and are on your responsibility to not include anything out of the conf tree) or give the web app's developer a hook to load its app-required snippets, and then nothing prevents him to include whatever he wants. -- Guillaume # HG changeset patch # User Guillaume Outters # Date 1567058353 -7200 # Thu Aug 29 07:59:13 2019 +0200 # Node ID 704100d8a8772a4bc2faaef9abcc0308316e580c # Parent 9f1f9d6e056a4f85907957ef263f78a426ae4f9c ngx_conf_file: "include ./" acts relative to currently parsed file Allow configuration files to include relatively to them instead of to prefix. Eases modular configurations, where includees do not need to know their absolute path to reach helper config files next to them. diff -r 9f1f9d6e056a -r 704100d8a877 src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c Mon Aug 19 15:16:06 2019 +0300 +++ b/src/core/ngx_conf_file.c Thu Aug 29 12:59:13 2019 +0200 @@ -15,6 +15,7 @@ static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf); static void ngx_conf_flush_files(ngx_cycle_t *cycle); +ngx_int_t ngx_conf_full_name_rel(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix, ngx_str_t *current); static ngx_command_t ngx_conf_commands[] = { @@ -830,7 +831,7 @@ ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); - if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { + if (ngx_conf_full_name_rel(cf->cycle, &file, 1, &cf->conf_file->file.name) != NGX_OK) { return NGX_CONF_ERROR; } @@ -884,16 +885,39 @@ ngx_int_t -ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix) +ngx_conf_full_name_rel(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix, ngx_str_t *current) { ngx_str_t *prefix; + ngx_str_t local_prefix; - prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix; + /* + * Path starting with literal ./ is interpreted relative to current's + * directory instead of prefix. + */ + if (name->len >= 2 && name->data[0] == '.' && name->data[1] == '/' && current && current->len && current->data[0] == '/') { + name->len -= 2; + name->data += 2; + + local_prefix.data = current->data; + for (local_prefix.len = current->len; local_prefix.data[--local_prefix.len] != '/'; /* void */ ) /* void */ ; + ++local_prefix.len; + prefix = &local_prefix; + + } else { + prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix; + } return ngx_get_full_name(cycle->pool, prefix, name); } +ngx_int_t +ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix) +{ + return ngx_conf_full_name_rel(cycle, name, conf_prefix, NULL); +} + + ngx_open_file_t * ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name) { From mdounin at mdounin.ru Fri Aug 30 14:02:22 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 30 Aug 2019 17:02:22 +0300 Subject: [PATCH] ngx_conf_file: "include ./" acts relative to currently parsed file In-Reply-To: <704100d8a8772a4bc2fa.1567058681@bas> References: <704100d8a8772a4bc2fa.1567058681@bas> Message-ID: <20190830140221.GK1877@mdounin.ru> Hello! On Thu, Aug 29, 2019 at 08:04:41AM +0200, Guillaume Outters wrote: > Hello, > > as an Nginx user, I regularly discover new features that prove > useful if not game changers. > > However I stay puzzled (nearly since I started using it) on why > the config include system does not allow relative paths, that > is, relative to the currently parsed file. This would allow for > simple modular config designs, where a "main" server config file > can embed the snippets that are deployed next to it. > The only tips I see on the forums and so is "hey, just use a > templating system to absolutize every include at deployment > time", which takes us away from Nginx' KISS philosophy. > > In an ideal world, my production nginx.conf would only include > /var/www/*/app.conf, and I could drop my "blorp" web app (that I > developed on /home/gui/www/blorp) in /var/www and have it > running at the next nginx reload, with it correctly loading > every location /xxx { include inc/phpfpm.conf; } of its > app.conf. > For now, I either have to centralize the snippets in > /etc/nginx/inc/phpfpm.conf (thus when a new rule has to be added > my developer has to tell my system operator to apply the change > to the centralized file), or inline the snippets in the (then > monolithic) app.conf (hey, duplication!), or hardcode the > snippet's path as /var/www/blorp/inc/phpfpm.conf (and symlink it > on my dev machine so that prod and dev config files are > shared?), or better make the app.conf a template and fill > absolute paths at deployment, so that if I want to run my shiny > new version of blorp as blorp-ng along blorp it does not include > the old version's phpfpm.conf erronously. While this may be a counter-intuitive and not very convenient in some cases, this is how it currently works: paths to configuration files are resolved from the conf prefix, that is, from the path to nginx.conf. You can think of it as if contents of included files are imported into nginx.conf itself, and processed afterwards. Changing this to resolve relative paths from the current included file instead is possible, but would be a major change - I suspect it will break a lot of configurations. Not sure we are going to do this. > The following patch adds a simple heuristic to include: if the > includee starts with "./", it is considered relative to the > current file. If not, the current heuristic applies (paths stay > relative to the prefix). > > I would be interested in learning the flaws or drawbacks in this > (bad?) idea. I first thought "security", (disallowing relative > includes keeps included files under control in config's root), > but anyhow, either you keep total control on the config (and are > on your responsibility to not include anything out of the conf > tree) or give the web app's developer a hook to load its > app-required snippets, and then nothing prevents him to include > whatever he wants. Certainly I'm against this approach, as it breaks POLA. The "include ./example.conf;" construct shouldn't be handled differently from "include example.conf", these are clearly the same thing. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Fri Aug 30 14:19:29 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 30 Aug 2019 17:19:29 +0300 Subject: Potential bug in ngx_event.c In-Reply-To: <797fde8d89aa12a26a84dfd52428a8f5@thelig.ht> References: <797fde8d89aa12a26a84dfd52428a8f5@thelig.ht> Message-ID: <20190830141929.GL1877@mdounin.ru> Hello! On Fri, Aug 23, 2019 at 11:00:41AM -0700, Rian Hunter wrote: > While browsing the source I noticed something that seemed wrong, even > though I haven't observed any buggy behavior or have reproduced this bug > myself. In ngx_event.c there is a line: > > if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) shared, > cycle->lock_file.data) > != NGX_OK) > { > return NGX_ERROR; > } > > ngx_shmtx_create() is passed &ngx_accept_mutex, but this must be a > pointer to a shared memory region otherwise the sem_wait()/sem_post() > calls in ngx_shmtx.c will not function correctly. &ngx_accept_mutex is a > pointer to BSS, ngx_accept_mutex_ptr is a pointer to shared memory. Is > this intentional? Yes, this is intentional. The first agument of the ngx_shmtx_create() function is a pointer to the ngx_shmtx_t structure, which is not expected to be shared between processes. Copy of the structure as created by fork() is enough. Only ngx_shmtx_sh_t - which is used to store atomic variables with lock and wait counter - needs to be shared. And it is shared, as "(ngx_shmtx_sh_t *) shared" is used as the second argument. -- Maxim Dounin http://mdounin.ru/ From guillaume-nginx at outters.eu Fri Aug 30 14:28:00 2019 From: guillaume-nginx at outters.eu (Guillaume Outters) Date: Fri, 30 Aug 2019 16:28:00 +0200 Subject: [PATCH] ngx_conf_file: "include ./" acts relative to currently parsed file In-Reply-To: <20190830140221.GK1877@mdounin.ru> References: <704100d8a8772a4bc2fa.1567058681@bas> <20190830140221.GK1877@mdounin.ru> Message-ID: Le 2019-08-30 16:02, Maxim Dounin a ?crit : > Changing this to resolve relative paths from the current included > file instead is possible, but would be a major change - I suspect > it will break a lot of configurations. Not sure we are going to > do this. > > On Thu, Aug 29, 2019 at 08:04:41AM +0200, Guillaume Outters wrote: > >> The following patch adds a simple heuristic to include: if the >> includee starts with "./", it is considered relative to the >> current file. If not, the current heuristic applies [?] > > Certainly I'm against this approach, as it breaks POLA. The > "include ./example.conf;" construct shouldn't be handled > differently from "include example.conf", these are clearly the > same thing. Hmm, you're right. Perhaps an unused diacritical would be better there, as: include @example.conf; or an explicit flag: include example.conf local; include example.conf -l; # Hmm, maybe too Apache-styled? include example.conf relative; include example.conf from_there; This would be even better than the diacritical: prevents crash of existing configurations who use strangely- at -prefixed names, more explicit, and more respectful of nginx' config principles (optional flags go at the end). On the other hand, this is longer to type, would make config reading more prone to missing the keyword (from my point of view, as I tend to read left-to-right and lazily stop when I have gathered what I was looking for) and? looks more complex to implement (this patch was my first peak ever at nginx' source). But even to me, the "pros" seems to overthrow the "cons". I would be glad to know what you think of this last solution (and which keyword you would choose then). -- Guillaume From thibaultcha at fastmail.com Fri Aug 30 19:43:40 2019 From: thibaultcha at fastmail.com (Thibault Charbonnier) Date: Fri, 30 Aug 2019 12:43:40 -0700 Subject: [PATCH] Upstream keepalive: keepalive_pool_key directive. Message-ID: <055db56d-11f3-2d1f-1115-3fb788b4829c@fastmail.com> # HG changeset patch # User Thibault Charbonnier # Date 1567193727 25200 # Fri Aug 30 12:35:27 2019 -0700 # Node ID 40abd582aafbd22c2435afed5fd3311333ca99bd # Parent a31ec2b79f9f208fecbc92020d12edb2a5207480 Upstream keepalive: keepalive_pool_key directive. This directive gives control to the user as to how they wish upstream connection pools be created and used. By default, each upstream block maintains a unique connection pool per IP/port tuple specified via the `server` directive. With this change, if the `keepalive_pool_key` directive is specified in an upstream block, the connection pools will be further segmented according to the IP/port/pool_key combination. Each connection pool will still have up to as many connections as specified in the `keepalive` directive. * When `keepalive_pool_key` evaluates to an empty string, the pool_key behavior is disabled (as if only `keepalive` was specified). * When the pool_key behavior is in effect, SSL session reuse will be disabled out of the box (as if `proxy_ssl_session_reuse off;` was specified). * Two new variables `$keepalive_pool_key` and `$keepalive_pool_key_raw` can be accessed to read the value of the current pool_key (if set). The former will compile the value, while the later will return it as specified by the user. This solves existing limitations of the upstream block such as detailed in the following tickets: * https://trac.nginx.org/nginx/ticket/1340 * https://trac.nginx.org/nginx/ticket/1593 For example, let's consider a use-case similar to #1340, in which different SNIs are intended to open different connections: upstream upstream.domain.com { server 1.1.1.1:443; keepalive 60; keepalive_pool_key $upstream_sni; } http { server { ... location /proxy { set $upstream_sni $host; proxy_ssl_name $upstream_sni; proxy_ssl_server_name on; proxy_http_version 1.1; proxy_set_header Connection ''; proxy_pass https://upstream.domain.com; } } } Without the above `keepalive_pool_key`, the same connection would be reused even when different SNIs should be used. Since `keepalive_pool_key` supports variables, users can use more granular connection pooling rules, such as distinguishing client certificates: keepalive_pool_key $ssl_client_cert_cn; or preferred protocols: keepalive_pool_key $ssl_client_protocols; or other properties of the request, connection, or TLS handshake. Note that while the above examples are built with variables that must be initialized by the users themselves as of today, nothing prevents future releases from adding these variables (or others), and supporting such use-cases out of the box. diff -r a31ec2b79f9f -r 40abd582aafb src/http/modules/ngx_http_upstream_keepalive_module.c --- a/src/http/modules/ngx_http_upstream_keepalive_module.c Tue Apr 02 14:45:52 2019 -0700 +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c Fri Aug 30 12:35:27 2019 -0700 @@ -21,6 +21,8 @@ ngx_http_upstream_init_pt original_init_upstream; ngx_http_upstream_init_peer_pt original_init_peer; + ngx_http_complex_value_t pool_key; + } ngx_http_upstream_keepalive_srv_conf_t; @@ -33,6 +35,8 @@ socklen_t socklen; ngx_sockaddr_t sockaddr; + uint32_t pool_key_crc32; + } ngx_http_upstream_keepalive_cache_t; @@ -51,6 +55,8 @@ ngx_event_save_peer_session_pt original_save_session; #endif + uint32_t pool_key_crc32; + } ngx_http_upstream_keepalive_peer_data_t; @@ -75,6 +81,11 @@ static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf); static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_upstream_keepalive_pool_key(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +static ngx_int_t ngx_http_upstream_keepalive_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_http_upstream_keepalive_pool_key_var_get( + ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_command_t ngx_http_upstream_keepalive_commands[] = { @@ -100,12 +111,33 @@ offsetof(ngx_http_upstream_keepalive_srv_conf_t, requests), NULL }, + { ngx_string("keepalive_pool_key"), + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, + ngx_http_upstream_keepalive_pool_key, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + ngx_null_command }; +static ngx_http_variable_t ngx_http_upstream_keepalive_vars[] = { + + { ngx_string("keepalive_pool_key"), NULL, + ngx_http_upstream_keepalive_pool_key_var_get, + 1, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("keepalive_pool_key_raw"), NULL, + ngx_http_upstream_keepalive_pool_key_var_get, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + ngx_http_null_variable +}; + + static ngx_http_module_t ngx_http_upstream_keepalive_module_ctx = { - NULL, /* preconfiguration */ + ngx_http_upstream_keepalive_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -186,6 +218,7 @@ { ngx_http_upstream_keepalive_peer_data_t *kp; ngx_http_upstream_keepalive_srv_conf_t *kcf; + ngx_str_t pool_key; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "init keepalive peer"); @@ -202,6 +235,25 @@ return NGX_ERROR; } + if (kcf->pool_key.value.data) { + if (ngx_http_complex_value(r, &kcf->pool_key, &pool_key) != NGX_OK) { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "keepalive peer pool_key: \"%V\"", &pool_key); + + } else { + pool_key.len = 0; + } + + if (pool_key.len > 0) { + kp->pool_key_crc32 = ngx_crc32_long(pool_key.data, pool_key.len); + + } else { + kp->pool_key_crc32 = 0; + } + kp->conf = kcf; kp->upstream = r->upstream; kp->data = r->upstream->peer.data; @@ -256,8 +308,9 @@ c = item->connection; if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr, - item->socklen, pc->socklen) - == 0) + item->socklen, pc->socklen) == 0 + && (item->pool_key_crc32 == 0 + || item->pool_key_crc32 == kp->pool_key_crc32)) { ngx_queue_remove(q); ngx_queue_insert_head(&kp->conf->free, q); @@ -386,6 +439,8 @@ item->socklen = pc->socklen; ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); + item->pool_key_crc32 = kp->pool_key_crc32; + if (c->read->ready) { ngx_http_upstream_keepalive_close_handler(c->read); } @@ -477,6 +532,10 @@ { ngx_http_upstream_keepalive_peer_data_t *kp = data; + if (kp->pool_key_crc32 != 0) { + return NGX_OK; + } + return kp->original_set_session(pc, kp->data); } @@ -486,7 +545,10 @@ { ngx_http_upstream_keepalive_peer_data_t *kp = data; - kp->original_save_session(pc, kp->data); + if (kp->pool_key_crc32 == 0) { + kp->original_save_session(pc, kp->data); + } + return; } @@ -509,6 +571,7 @@ * * conf->original_init_upstream = NULL; * conf->original_init_peer = NULL; + * conf->pool_key = NULL; * conf->max_cached = 0; */ @@ -559,3 +622,94 @@ return NGX_CONF_OK; } + + +static char * +ngx_http_upstream_keepalive_pool_key(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_upstream_keepalive_srv_conf_t *kcf = conf; + ngx_str_t *value; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + if (kcf->pool_key.value.data) { + return "is duplicate"; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &kcf->pool_key; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_upstream_keepalive_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_upstream_keepalive_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + *var = *v; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_keepalive_pool_key_var_get(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_flag_t compile = data; + ngx_str_t pool_key; + ngx_http_upstream_t *u; + ngx_http_upstream_srv_conf_t *uscf; + ngx_http_upstream_keepalive_srv_conf_t *kcf; + + u = r->upstream; + if (u == NULL) { + goto not_found; + } + + uscf = u->conf->upstream; + + kcf = ngx_http_conf_upstream_srv_conf(uscf, + ngx_http_upstream_keepalive_module); + + if (compile) { + if (ngx_http_complex_value(r, &kcf->pool_key, &pool_key) != NGX_OK) { + goto not_found; + } + + } else { + pool_key = kcf->pool_key.value; + } + + v->valid = 1; + v->not_found = 0; + v->no_cacheable = 1; + v->data = pool_key.data; + v->len = pool_key.len; + + return NGX_OK; + +not_found: + + v->not_found = 1; + + return NGX_OK; +} -------------- next part -------------- A non-text attachment was scrubbed... Name: upstream_keepalive_pool_key.patch Type: text/x-patch Size: 10017 bytes Desc: not available URL: From rian at alum.mit.edu Sat Aug 31 01:26:57 2019 From: rian at alum.mit.edu (Rian Hunter) Date: Fri, 30 Aug 2019 18:26:57 -0700 Subject: Potential bug in ngx_event.c In-Reply-To: <20190830141929.GL1877@mdounin.ru> References: <797fde8d89aa12a26a84dfd52428a8f5@thelig.ht> <20190830141929.GL1877@mdounin.ru> Message-ID: <6fc40c129d36c08bb56fde854f4ffc91@thelig.ht> On 2019-08-30 07:19, Maxim Dounin wrote: > Hello! > > On Fri, Aug 23, 2019 at 11:00:41AM -0700, Rian Hunter wrote: > >> While browsing the source I noticed something that seemed wrong, even >> though I haven't observed any buggy behavior or have reproduced this >> bug >> myself. In ngx_event.c there is a line: >> >> if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) >> shared, >> cycle->lock_file.data) >> != NGX_OK) >> { >> return NGX_ERROR; >> } >> >> ngx_shmtx_create() is passed &ngx_accept_mutex, but this must be a >> pointer to a shared memory region otherwise the sem_wait()/sem_post() >> calls in ngx_shmtx.c will not function correctly. &ngx_accept_mutex is >> a >> pointer to BSS, ngx_accept_mutex_ptr is a pointer to shared memory. Is >> this intentional? > > Yes, this is intentional. > > The first agument of the ngx_shmtx_create() function is a pointer > to the ngx_shmtx_t structure, which is not expected to be shared > between processes. Copy of the structure as created by fork() is > enough. The POSIX sem_t member (called "sem") needs to reside in shared memory if sem_wait()/sem_post() are to have an effect across processes. Memory copied across fork is not sufficient. > Only ngx_shmtx_sh_t - which is used to store atomic variables with > lock and wait counter - needs to be shared. And it is shared, as > "(ngx_shmtx_sh_t *) shared" is used as the second argument. Yes, the atomic modifications to the variable stored in that memory is correct and will be shared across processes but the sem_wait()/sem_post() calls within ngx_shmtx.c have no effect since the "sem" member of ngx_shmtx_t is not shared. The end result will be that ngx_shmtx_wakeup() (amongst others) has no effect. From mdounin at mdounin.ru Sat Aug 31 18:28:22 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 31 Aug 2019 21:28:22 +0300 Subject: Potential bug in ngx_event.c In-Reply-To: <6fc40c129d36c08bb56fde854f4ffc91@thelig.ht> References: <797fde8d89aa12a26a84dfd52428a8f5@thelig.ht> <20190830141929.GL1877@mdounin.ru> <6fc40c129d36c08bb56fde854f4ffc91@thelig.ht> Message-ID: <20190831182822.GM1877@mdounin.ru> Hello! On Fri, Aug 30, 2019 at 06:26:57PM -0700, Rian Hunter wrote: > On 2019-08-30 07:19, Maxim Dounin wrote: > > Hello! > > > > On Fri, Aug 23, 2019 at 11:00:41AM -0700, Rian Hunter wrote: > > > >> While browsing the source I noticed something that seemed wrong, even > >> though I haven't observed any buggy behavior or have reproduced this > >> bug > >> myself. In ngx_event.c there is a line: > >> > >> if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) > >> shared, > >> cycle->lock_file.data) > >> != NGX_OK) > >> { > >> return NGX_ERROR; > >> } > >> > >> ngx_shmtx_create() is passed &ngx_accept_mutex, but this must be a > >> pointer to a shared memory region otherwise the sem_wait()/sem_post() > >> calls in ngx_shmtx.c will not function correctly. &ngx_accept_mutex is > >> a > >> pointer to BSS, ngx_accept_mutex_ptr is a pointer to shared memory. Is > >> this intentional? > > > > Yes, this is intentional. > > > > The first agument of the ngx_shmtx_create() function is a pointer > > to the ngx_shmtx_t structure, which is not expected to be shared > > between processes. Copy of the structure as created by fork() is > > enough. > > The POSIX sem_t member (called "sem") needs to reside in shared memory > if sem_wait()/sem_post() are to have an effect across processes. Memory > copied across fork is not sufficient. No, fork() is explicitly documented to preserve semaphores (http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html): : Any semaphores that are open in the parent process shall also be : open in the child process. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sat Aug 31 18:35:37 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 31 Aug 2019 21:35:37 +0300 Subject: [PATCH] Upstream keepalive: keepalive_pool_key directive. In-Reply-To: <055db56d-11f3-2d1f-1115-3fb788b4829c@fastmail.com> References: <055db56d-11f3-2d1f-1115-3fb788b4829c@fastmail.com> Message-ID: <20190831183537.GN1877@mdounin.ru> Hello! On Fri, Aug 30, 2019 at 12:43:40PM -0700, Thibault Charbonnier wrote: > # HG changeset patch > # User Thibault Charbonnier > # Date 1567193727 25200 > # Fri Aug 30 12:35:27 2019 -0700 > # Node ID 40abd582aafbd22c2435afed5fd3311333ca99bd > # Parent a31ec2b79f9f208fecbc92020d12edb2a5207480 > Upstream keepalive: keepalive_pool_key directive. > > This directive gives control to the user as to how they wish upstream > connection pools be created and used. > > By default, each upstream block maintains a unique connection pool per > IP/port tuple specified via the `server` directive. > > With this change, if the `keepalive_pool_key` directive is specified in > an upstream block, the connection pools will be further segmented > according to the IP/port/pool_key combination. Each connection pool will > still have up to as many connections as specified in the `keepalive` > directive. > > * When `keepalive_pool_key` evaluates to an empty string, the pool_key > behavior is disabled (as if only `keepalive` was specified). > * When the pool_key behavior is in effect, SSL session reuse will be > disabled out of the box (as if `proxy_ssl_session_reuse off;` was > specified). > * Two new variables `$keepalive_pool_key` and `$keepalive_pool_key_raw` > can be accessed to read the value of the current pool_key (if set). > The former will compile the value, while the later will return it as > specified by the user. > > This solves existing limitations of the upstream block such as > detailed in the following tickets: > > * https://trac.nginx.org/nginx/ticket/1340 > * https://trac.nginx.org/nginx/ticket/1593 > > For example, let's consider a use-case similar to #1340, in which > different SNIs are intended to open different connections: > > upstream upstream.domain.com { > server 1.1.1.1:443; > > keepalive 60; > keepalive_pool_key $upstream_sni; > } [...] No, thank you. The issues as observed in the tickets linked should be resolved by using distinct upstream blocks instead. -- Maxim Dounin http://mdounin.ru/