From franksinankaya at gmail.com Mon Jun 3 16:04:37 2019 From: franksinankaya at gmail.com (Sinan Kaya) Date: Mon, 3 Jun 2019 12:04:37 -0400 Subject: RFC for Compiling Nginx as a Library Message-ID: Hi, I have been using Nginx as a static library to embed into my application for some time. I'm interested in upstreaming the patches. I wanted to ask if there would be any interest in merging this feature. Sinan -------------- next part -------------- An HTML attachment was scrubbed... URL: From naidilepn at gmail.com Mon Jun 3 17:27:45 2019 From: naidilepn at gmail.com (naidile.pn) Date: Mon, 3 Jun 2019 22:57:45 +0530 Subject: NJS - API Calls Message-ID: Hi Team, Can you please let me know how to make external API calls within the JS method. I actually want to make API calls and modify the request before proxy passing th e request to a up stream server. Thanks, Naidile -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon Jun 3 17:39:41 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 3 Jun 2019 20:39:41 +0300 Subject: NJS - API Calls In-Reply-To: References: Message-ID: On 03.06.2019 20:27, naidile.pn wrote: > Hi Team, > > Can you please let me know how to make external API calls within the JS > method. Hi Naidile, what do you mean by external API calls? > I actually want to make API calls and modify the request before proxy > passing th e request to a up stream server. It is considered to a bad practice to modify client request directly. Instead you can create a subrequest (http://nginx.org/en/docs/njs/reference.html#subrequest) and modify it in a sublocation. See as an example https://github.com/xeioex/njs-examples#subrequests-join > > Thanks, > Naidile > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From mdounin at mdounin.ru Mon Jun 3 17:41:10 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Jun 2019 20:41:10 +0300 Subject: RFC for Compiling Nginx as a Library In-Reply-To: References: Message-ID: <20190603174110.GV1877@mdounin.ru> Hello! On Mon, Jun 03, 2019 at 12:04:37PM -0400, Sinan Kaya wrote: > I have been using Nginx as a static library to embed into my application > for some time. > I'm interested in upstreaming the patches. > > I wanted to ask if there would be any interest in merging this feature. This isn't intended use case for nginx, and patches solely dedicated to compiling nginx as a library are unlikely to be accepted. We will, however, consider patches generally improving nginx code, if there are any. -- Maxim Dounin http://mdounin.ru/ From naidilepn at gmail.com Mon Jun 3 17:43:46 2019 From: naidilepn at gmail.com (naidile.pn) Date: Mon, 3 Jun 2019 23:13:46 +0530 Subject: NJS - API Calls In-Reply-To: References: Message-ID: Thanks Dmitry. I want to make a REST API call which is on a different server to fetch a property. And add the property to the request from client and proxy it On Mon, Jun 3, 2019 at 11:09 PM Dmitry Volyntsev wrote: > > > On 03.06.2019 20:27, naidile.pn wrote: > > Hi Team, > > > > Can you please let me know how to make external API calls within the JS > > method. > > > Hi Naidile, > > what do you mean by external API calls? > > > > I actually want to make API calls and modify the request before proxy > > passing th e request to a up stream server. > > > It is considered to a bad practice to modify client request directly. > Instead you can create a subrequest > (http://nginx.org/en/docs/njs/reference.html#subrequest) and modify it > in a sublocation. See as an example > https://github.com/xeioex/njs-examples#subrequests-join > > > > > Thanks, > > Naidile > > > > _______________________________________________ > > 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 naidilepn at gmail.com Mon Jun 3 17:46:38 2019 From: naidilepn at gmail.com (naidile.pn) Date: Mon, 3 Jun 2019 23:16:38 +0530 Subject: NJS - API Calls In-Reply-To: References: Message-ID: Adding, Basically a HTTP ajax call in JS On Mon, Jun 3, 2019 at 11:13 PM naidile.pn wrote: > Thanks Dmitry. > > I want to make a REST API call which is on a different server to fetch a > property. > > And add the property to the request from client and proxy it > > On Mon, Jun 3, 2019 at 11:09 PM Dmitry Volyntsev wrote: > >> >> >> On 03.06.2019 20:27, naidile.pn wrote: >> > Hi Team, >> > >> > Can you please let me know how to make external API calls within the JS >> > method. >> >> >> Hi Naidile, >> >> what do you mean by external API calls? >> >> >> > I actually want to make API calls and modify the request before proxy >> > passing th e request to a up stream server. >> >> >> It is considered to a bad practice to modify client request directly. >> Instead you can create a subrequest >> (http://nginx.org/en/docs/njs/reference.html#subrequest) and modify it >> in a sublocation. See as an example >> https://github.com/xeioex/njs-examples#subrequests-join >> >> > >> > Thanks, >> > Naidile >> > >> > _______________________________________________ >> > 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 xeioex at nginx.com Mon Jun 3 18:03:13 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 3 Jun 2019 21:03:13 +0300 Subject: NJS - API Calls In-Reply-To: References: Message-ID: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> On 03.06.2019 20:43, naidile.pn wrote: > > I want to make a REST API call which is on a different server to fetch a > property. > > And add the property to the request from client and proxy it Currently you can do it using two sublocations with proxy_pass directives (http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass). -------------------- function js_content(r) { r.subrequest("/property", reply => { if (reply.status != 200) { r.return(500, "prop failed"); return; } r.subrequest('/backend', res => { ... }) }) } ------------------ We plan to add a Promise object this year, so in the future it will be less cumbersome. From naidilepn at gmail.com Mon Jun 3 18:07:33 2019 From: naidilepn at gmail.com (naidile.pn) Date: Mon, 3 Jun 2019 23:37:33 +0530 Subject: NJS - API Calls In-Reply-To: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> Message-ID: Thanks, I'll check it out. Will get back to you in case of any queries. Additionally, I would like like to know the performance of NJS as we will be using this in production, Which one has more performance - Lua or NJS ? Please suggest here. On Mon, Jun 3, 2019 at 11:33 PM Dmitry Volyntsev wrote: > > > On 03.06.2019 20:43, naidile.pn wrote: > > > > I want to make a REST API call which is on a different server to fetch a > > property. > > > > And add the property to the request from client and proxy it > > > Currently you can do it using two sublocations with proxy_pass > directives > (http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass). > > -------------------- > function js_content(r) { > > r.subrequest("/property", reply => { > > if (reply.status != 200) { r.return(500, "prop failed"); return; } > > r.subrequest('/backend', res => { > ... > }) > }) > } > > ------------------ > > We plan to add a Promise object this year, so in the future it will be > less cumbersome. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon Jun 3 18:15:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 3 Jun 2019 21:15:17 +0300 Subject: NJS - API Calls In-Reply-To: References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> Message-ID: On 03.06.2019 21:07, naidile.pn wrote: > Which one has more performance - Lua or NJS ? In benchmarks I did, I saw no big differences (njs was slightly better (< 5%)). Because, in real case scenarios not the interpreter is the bottleneck (If you do not do too much math heavy lifting). From naidilepn at gmail.com Mon Jun 3 18:19:55 2019 From: naidilepn at gmail.com (naidile.pn) Date: Mon, 3 Jun 2019 23:49:55 +0530 Subject: NJS - API Calls In-Reply-To: References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> Message-ID: Thanks a lot! On Mon, Jun 3, 2019 at 11:45 PM Dmitry Volyntsev wrote: > > > On 03.06.2019 21:07, naidile.pn wrote: > > Which one has more performance - Lua or NJS ? > > > In benchmarks I did, I saw no big differences (njs was slightly better > (< 5%)). Because, in real case scenarios not the interpreter is the > bottleneck (If you do not do too much math heavy lifting). > -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Tue Jun 4 08:56:31 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 04 Jun 2019 08:56:31 +0000 Subject: [nginx] Upstream: background cache update before cache send (ticket #1782). Message-ID: details: https://hg.nginx.org/nginx/rev/319242d2ddc9 branches: changeset: 7514:319242d2ddc9 user: Roman Arutyunyan date: Mon Jun 03 20:33:26 2019 +0300 description: Upstream: background cache update before cache send (ticket #1782). In case of filter finalization, essential request fields like r->uri, r->args etc could be changed, which affected the cache update subrequest. Also, after filter finalization r->cache could be set to NULL, leading to null pointer dereference in ngx_http_upstream_cache_background_update(). The fix is to create background cache update subrequest before sending the cached response. Since initial introduction in 1aeaae6e9446 (1.11.10) background cache update subrequest was created after sending the cached response because otherwise it blocked the parent request output. In 9552758a786e (1.13.1) background subrequests were introduced to eliminate the delay before sending the final part of the cached response. This also made it possible to create the background cache update subrequest before sending the response. Note that creating the subrequest earlier does not change the fact that in case of filter finalization the background cache update subrequest will likely not have enough time to successfully update the cache entry. Filter finalization leads to the main request termination as soon the current iteration of request processing is complete. diffstat: src/http/ngx_http_upstream.c | 19 ++++++++----------- 1 files changed, 8 insertions(+), 11 deletions(-) diffs (43 lines): diff -r d964b0aee8e7 -r 319242d2ddc9 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu May 23 16:49:22 2019 +0300 +++ b/src/http/ngx_http_upstream.c Mon Jun 03 20:33:26 2019 +0300 @@ -597,10 +597,6 @@ ngx_http_upstream_init_request(ngx_http_ u->cache_status = NGX_HTTP_CACHE_MISS; u->request_sent = 1; } - - if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) { - rc = NGX_ERROR; - } } if (rc != NGX_DECLINED) { @@ -902,9 +898,14 @@ ngx_http_upstream_cache(ngx_http_request || c->stale_updating) && !r->background && u->conf->cache_background_update) { - r->cache->background = 1; - u->cache_status = rc; - rc = NGX_OK; + if (ngx_http_upstream_cache_background_update(r, u) == NGX_OK) { + r->cache->background = 1; + u->cache_status = rc; + rc = NGX_OK; + + } else { + rc = NGX_ERROR; + } } break; @@ -1106,10 +1107,6 @@ ngx_http_upstream_cache_background_updat { ngx_http_request_t *sr; - if (!r->cached || !r->cache->background) { - return NGX_OK; - } - if (r == r->main) { r->preserve_body = 1; } From naidilepn at gmail.com Tue Jun 4 09:11:36 2019 From: naidilepn at gmail.com (naidile.pn) Date: Tue, 4 Jun 2019 14:41:36 +0530 Subject: NJS - API Calls In-Reply-To: References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> Message-ID: Hi Dmitry, Could you please help me in understanding the difference between js_content and js_preread with usecases. Regards, Naidile On Mon, Jun 3, 2019 at 11:49 PM naidile.pn wrote: > Thanks a lot! > > On Mon, Jun 3, 2019 at 11:45 PM Dmitry Volyntsev wrote: > >> >> >> On 03.06.2019 21:07, naidile.pn wrote: >> > Which one has more performance - Lua or NJS ? >> >> >> In benchmarks I did, I saw no big differences (njs was slightly better >> (< 5%)). Because, in real case scenarios not the interpreter is the >> bottleneck (If you do not do too much math heavy lifting). >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Jun 4 09:31:40 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 4 Jun 2019 12:31:40 +0300 Subject: NJS - API Calls In-Reply-To: References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> Message-ID: <1AE3A282-4411-44F4-93B9-4B850410BE70@nginx.com> > On 4 Jun 2019, at 12:11, naidile.pn wrote: > > Hi Dmitry, > > Could you please help me in understanding the difference between js_content and js_preread with usecases. js_content is a directive of http njs module (http://nginx.org/en/docs/http/ngx_http_js_module.html#js_content ). It sets an njs function as a location content handler (The requests are processed in phases, see http://nginx.org/en/docs/dev/development_guide.html#http_phases NGX_HTTP_CONTENT_PHASE). The function is invoked once per each request. In it you are responsible for generating complete http responses. The NGX_HTTP_CONTENT_PHASE is not finished until you have pending actions (active subrequests or timers). The only way to make "external http calls? is to make a subrequest to a separate location with proxy_pass directive (here you can use variables to make subrequests to different endpoints). js_preread is a directive of stream njs module, it works on tcp level (http://nginx.org/en/docs/stream/ngx_stream_js_module.html#js_preread ). The function is invoked once per each tcp connection. To wait for more data asynchronously you have s.on(?upload?, function (data, flags) {?}) and s.done([code]) to move to the next phase. > > Regards, > Naidile > > On Mon, Jun 3, 2019 at 11:49 PM naidile.pn > wrote: > Thanks a lot! > > On Mon, Jun 3, 2019 at 11:45 PM Dmitry Volyntsev > wrote: > > > On 03.06.2019 21:07, naidile.pn wrote: > > Which one has more performance - Lua or NJS ? > > > In benchmarks I did, I saw no big differences (njs was slightly better > (< 5%)). Because, in real case scenarios not the interpreter is the > bottleneck (If you do not do too much math heavy lifting). -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Jun 4 09:45:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 04 Jun 2019 09:45:46 +0000 Subject: [njs] Escaping lone closing square brackets in RegExp() constructor. Message-ID: details: https://hg.nginx.org/njs/rev/2054b8410a28 branches: changeset: 997:2054b8410a28 user: Dmitry Volyntsev date: Thu May 30 20:05:14 2019 +0300 description: Escaping lone closing square brackets in RegExp() constructor. This correctly fixes #157. As in 88263426432d this was done only for regexp literals. diffstat: njs/njs_regexp.c | 134 +++++++++++++++++++++++++++------------------- njs/test/njs_unit_test.c | 15 +++++ 2 files changed, 92 insertions(+), 57 deletions(-) diffs (252 lines): diff -r 1041e3241457 -r 2054b8410a28 njs/njs_regexp.c --- a/njs/njs_regexp.c Fri May 31 15:11:39 2019 +0300 +++ b/njs/njs_regexp.c Thu May 30 20:05:14 2019 +0300 @@ -206,56 +206,93 @@ njs_regexp_create(njs_vm_t *vm, njs_valu } -nxt_inline njs_ret_t -njs_regexp_escape_bracket(njs_vm_t *vm, nxt_str_t *text, size_t count) -{ - size_t length, diff; - u_char *p, *dst, *start, *end; +/* + * PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with + * lone closing square brackets as invalid. Whereas according + * to ES6: 11.8.5 it is a valid regexp expression. + * + * Escaping it here as a workaround. + */ - length = text->length + count; - - dst = nxt_mp_alloc(vm->mem_pool, length); - if (nxt_slow_path(dst == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; - } +nxt_inline njs_ret_t +njs_regexp_escape(njs_vm_t *vm, nxt_str_t *text) +{ + size_t brackets; + u_char *p, *dst, *start, *end; + nxt_bool_t in; start = text->start; end = text->start + text->length; + in = 0; + brackets = 0; + for (p = start; p < end; p++) { switch (*p) { case '[': - while (++p < end && *p != ']') { - if (*p == '\\') { - p++; - } - } - + in = 1; break; case ']': - diff = p - start; - dst = nxt_cpymem(dst, start, diff); - dst = nxt_cpymem(dst, "\\]", 2); + if (!in) { + brackets++; + } - start = p + 1; + in = 0; break; case '\\': p++; - break; } } - diff = p - start; - memcpy(dst, start, diff); + if (!brackets) { + return NXT_OK; + } + + text->length = text->length + brackets; + + text->start = nxt_mp_alloc(vm->mem_pool, text->length); + if (nxt_slow_path(text->start == NULL)) { + njs_memory_error(vm); + return NXT_ERROR; + } + + in = 0; + dst = text->start; + + for (p = start; p < end; p++) { + + switch (*p) { + case '[': + in = 1; + break; - text->start = dst - (length - diff); - text->length = length; + case ']': + if (!in) { + *dst++ = '\\'; + } + + in = 0; + break; + + case '\\': + *dst++ = *p++; - return NJS_OK; + if (p == end) { + goto done; + } + } + + *dst++ = *p; + } + +done: + + text->length = dst - text->start; + + return NXT_OK; } @@ -263,14 +300,11 @@ njs_token_t njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value) { u_char *p; - size_t closing_brackets; nxt_str_t text; - njs_ret_t ret; njs_lexer_t *lexer; njs_regexp_flags_t flags; njs_regexp_pattern_t *pattern; - closing_brackets = 0; lexer = parser->lexer; for (p = lexer->start; p < lexer->end; p++) { @@ -298,10 +332,6 @@ njs_regexp_literal(njs_vm_t *vm, njs_par break; - case ']': - closing_brackets++; - break; - case '\\': if (++p < lexer->end && (*p == '\n' || *p == '\r')) { goto failed; @@ -327,28 +357,9 @@ njs_regexp_literal(njs_vm_t *vm, njs_par lexer->start = p; - if (closing_brackets != 0) { - /* - * PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with - * lone closing square brackets as invalid. Whereas according - * to ES6: 11.8.5 it is a valid regexp expression. - * - * Escaping it here as a workaround. - */ - - ret = njs_regexp_escape_bracket(vm, &text, closing_brackets); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ILLEGAL; - } - } - pattern = njs_regexp_pattern_create(vm, text.start, text.length, flags); - if (closing_brackets != 0) { - nxt_mp_free(vm->mem_pool, text.start); - } - if (nxt_slow_path(pattern == NULL)) { return NJS_TOKEN_ILLEGAL; } @@ -440,6 +451,7 @@ njs_regexp_pattern_create(njs_vm_t *vm, int options, ret; u_char *p, *end; size_t size; + nxt_str_t text; nxt_uint_t n; nxt_regex_t *regex; njs_regexp_group_t *group; @@ -450,8 +462,16 @@ njs_regexp_pattern_create(njs_vm_t *vm, size += ((flags & NJS_REGEXP_IGNORE_CASE) != 0); size += ((flags & NJS_REGEXP_MULTILINE) != 0); + text.start = start; + text.length = length; + + ret = njs_regexp_escape(vm, &text); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + pattern = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_regexp_pattern_t) + 1 - + length + size + 1); + + text.length + size + 1); if (nxt_slow_path(pattern == NULL)) { njs_memory_error(vm); return NULL; @@ -463,8 +483,8 @@ njs_regexp_pattern_create(njs_vm_t *vm, pattern->source = p; *p++ = '/'; - p = memcpy(p, start, length); - p += length; + p = memcpy(p, text.start, text.length); + p += text.length; end = p; *p++ = '\0'; diff -r 1041e3241457 -r 2054b8410a28 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Fri May 31 15:11:39 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 30 20:05:14 2019 +0300 @@ -5540,9 +5540,21 @@ static njs_unit_test_t njs_test[] = { nxt_string("/]/"), nxt_string("/\\]/") }, + { nxt_string("RegExp(']')"), + nxt_string("/\\]/") }, + + { nxt_string("RegExp('[\\\\\\\\]]')"), + nxt_string("/[\\\\]\\]/") }, + + { nxt_string("/[\\\\]]/"), + nxt_string("/[\\\\]\\]/") }, + { nxt_string("/\\]/"), nxt_string("/\\]/") }, + { nxt_string("RegExp('\\]')"), + nxt_string("/\\]/") }, + { nxt_string("/ab]cd/"), nxt_string("/ab\\]cd/") }, @@ -7441,6 +7453,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("new RegExp('[')"), nxt_string("SyntaxError: pcre_compile(\"[\") failed: missing terminating ] for character class") }, + { nxt_string("new RegExp('\\\\')"), + nxt_string("SyntaxError: pcre_compile(\"\\\") failed: \\ at end of pattern") }, + { nxt_string("[0].map(RegExp().toString)"), nxt_string("TypeError: \"this\" argument is not a regexp") }, From xeioex at nginx.com Tue Jun 4 09:45:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 04 Jun 2019 09:45:46 +0000 Subject: [njs] Handling zero byte characters inside RegExp pattern strings. Message-ID: details: https://hg.nginx.org/njs/rev/f57cf6b5233a branches: changeset: 998:f57cf6b5233a user: Dmitry Volyntsev date: Tue Jun 04 12:45:06 2019 +0300 description: Handling zero byte characters inside RegExp pattern strings. Fixed heap-buffer-overflow in RegExp.prototype.source. This closes #168 issue on Github. diffstat: njs/njs_regexp.c | 31 +++++++++++++++++++++++++++---- njs/test/njs_unit_test.c | 24 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diffs (118 lines): diff -r 2054b8410a28 -r f57cf6b5233a njs/njs_regexp.c --- a/njs/njs_regexp.c Thu May 30 20:05:14 2019 +0300 +++ b/njs/njs_regexp.c Tue Jun 04 12:45:06 2019 +0300 @@ -207,17 +207,19 @@ njs_regexp_create(njs_vm_t *vm, njs_valu /* - * PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with + * 1) PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with * lone closing square brackets as invalid. Whereas according * to ES6: 11.8.5 it is a valid regexp expression. * + * 2) escaping zero byte characters as "\u0000". + * * Escaping it here as a workaround. */ nxt_inline njs_ret_t njs_regexp_escape(njs_vm_t *vm, nxt_str_t *text) { - size_t brackets; + size_t brackets, zeros; u_char *p, *dst, *start, *end; nxt_bool_t in; @@ -225,6 +227,7 @@ njs_regexp_escape(njs_vm_t *vm, nxt_str_ end = text->start + text->length; in = 0; + zeros = 0; brackets = 0; for (p = start; p < end; p++) { @@ -244,14 +247,24 @@ njs_regexp_escape(njs_vm_t *vm, nxt_str_ case '\\': p++; + + if (p == end || *p != '\0') { + break; + } + + /* Fall through. */ + + case '\0': + zeros++; + break; } } - if (!brackets) { + if (!brackets && !zeros) { return NXT_OK; } - text->length = text->length + brackets; + text->length = text->length + brackets + zeros * nxt_length("\\u0000"); text->start = nxt_mp_alloc(vm->mem_pool, text->length); if (nxt_slow_path(text->start == NULL)) { @@ -283,6 +296,16 @@ njs_regexp_escape(njs_vm_t *vm, nxt_str_ if (p == end) { goto done; } + + if (*p != '\0') { + break; + } + + /* Fall through. */ + + case '\0': + dst = nxt_cpymem(dst, "\\u0000", 6); + continue; } *dst++ = *p; diff -r 2054b8410a28 -r f57cf6b5233a njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 30 20:05:14 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue Jun 04 12:45:06 2019 +0300 @@ -5564,6 +5564,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("/]cd/"), nxt_string("/\\]cd/") }, + { nxt_string("RegExp('\\\\0').source[1]"), + nxt_string("0") }, + { nxt_string("']'.match(/]/)"), nxt_string("]") }, @@ -12812,6 +12815,27 @@ static njs_unit_test_t njs_regexp_test[ { nxt_string("/[\\uFDE0-\\uFFFD]/g; export default 1"), nxt_string("SyntaxError: Illegal export statement in 1") }, + + { nxt_string("RegExp(RegExp('\x00]]')).test('\x00]]')"), + nxt_string("true") }, + + { nxt_string("RegExp('\0').test('\0')"), + nxt_string("true") }, + + { nxt_string("RegExp('\x00').test('\0')"), + nxt_string("true") }, + + { nxt_string("RegExp('\x00\\\\x00').source"), + nxt_string("\\u0000\\x00") }, + + { nxt_string("/\\\0/"), + nxt_string("/\\\\u0000/") }, + + { nxt_string("RegExp('\\\\\\0').source"), + nxt_string("\\\\u0000") }, + + { nxt_string("RegExp('[\0]').test('\0')"), + nxt_string("true") }, }; From xeioex at nginx.com Tue Jun 4 12:55:38 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 4 Jun 2019 15:55:38 +0300 Subject: NJS - API Calls In-Reply-To: References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> <1AE3A282-4411-44F4-93B9-4B850410BE70@nginx.com> Message-ID: <4ff1e2b9-f3ca-abe3-7f65-b3adbf804263@nginx.com> On 04.06.2019 14:00, naidile.pn wrote: > What does api write=on; mean ? Could you please explain. > api is a plus-only nginx module (http://nginx.org/en/docs/http/ngx_http_api_module.html). You do not need this to make subrequests. > On Tue, Jun 4, 2019 at 4:26 PM naidile.pn > > wrote: > > Hi?Dmitry, > > I tried subrequest. But it doesn't work. Nginx is trying find the > API within?/var/www/html folder. Can you elaborate more what are you trying to do? See the config below as an example: ----------------- http { js_include proxy.js; js_set $summary summary; js_set $prop prop; # proxy server server { listen 8080; server_name localhost; location / { js_content proxy; } location = /_prop { internal; proxy_pass http://127.0.0.1:8090; } location = /_proxy { internal; proxy_set_header Prop $prop; proxy_pass http://127.0.0.1:8070$request_uri; } } # prop server server { listen 8090; location / { return 200 '{"prop": "WAKA"}'; } } # dest server server { listen 8070; location / { return 200 $summary; } } } ----------------- function proxy(r) { r.subrequest("/_prop", reply => { if (reply.status != 200) { r.return(500); return; } r.variables.prop = JSON.parse(reply.responseBody).prop; r.subrequest("/_proxy", res => { r.return(res.status != 200 ? 500 : 200, res.responseBody); }) }); } function summary(r) { var s = "JS summary\n\n"; s += "Method: " + r.method + "\n"; s += "HTTP version: " + r.httpVersion + "\n"; s += "Host: " + r.headersIn.host + "\n"; s += "Remote Address: " + r.remoteAddress + "\n"; s += "URI: " + r.uri + "\n"; s += "Headers:\n"; for (var h in r.headersIn) { s += " header '" + h + "' is '" + r.headersIn[h] + "'\n"; } return s; } var prop = (r) => r.variables.prop; ----------------- curl http://127.0.0.1:8080/test JS summary Method: GET HTTP version: 1.0 Host: 127.0.0.1:8070 Remote Address: 127.0.0.1 URI: /test Headers: header 'Prop' is 'WAKA' header 'Host' is '127.0.0.1:8070' header 'Connection' is 'close' header 'User-Agent' is 'curl/7.64.0' header 'Accept' is '*/*' ----------------- > > And, with proxy_pass within subrequest, I'm not able to pass the > request headers and body. Kindly help here. From xeioex at nginx.com Tue Jun 4 13:49:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 04 Jun 2019 13:49:16 +0000 Subject: [njs] HTTP: support for null as a second argument of r.subrequest(). Message-ID: details: https://hg.nginx.org/njs/rev/deef19f6498a branches: changeset: 999:deef19f6498a user: Dmitry Volyntsev date: Tue Jun 04 16:07:14 2019 +0300 description: HTTP: support for null as a second argument of r.subrequest(). This closes #173 issue on Github. diffstat: nginx/ngx_http_js_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r f57cf6b5233a -r deef19f6498a nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Jun 04 12:45:06 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Jun 04 16:07:14 2019 +0300 @@ -1808,7 +1808,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } else if (njs_value_is_object(arg)) { options = arg; - } else if (!njs_value_is_undefined(arg)) { + } else if (!njs_value_is_null_or_undefined(arg)) { njs_vm_error(vm, "failed to convert args"); return NJS_ERROR; } From eran.kornblau at kaltura.com Tue Jun 4 15:20:35 2019 From: eran.kornblau at kaltura.com (Eran Kornblau) Date: Tue, 4 Jun 2019 15:20:35 +0000 Subject: Nginx coding conventions validator Message-ID: Hi all, Does anyone happen to have some tool/script that can validate source files against nginx coding conventions? I believe some of the conventions can be fairly easy to automate (e.g. 80 chars width, spacing etc.), and was wondering whether anyone already took the time to implement something like that... Thanks! Eran -------------- next part -------------- An HTML attachment was scrubbed... URL: From dedok.mad at gmail.com Tue Jun 4 15:27:07 2019 From: dedok.mad at gmail.com (Vasily Soshnikov) Date: Tue, 4 Jun 2019 18:27:07 +0300 Subject: Nginx coding conventions validator In-Reply-To: References: Message-ID: Hi, I never hear about suck tools, but I can suggest you use cppcheck[1] for having some validations. But you have to configure this tool. I hope that help you. [1] http://cppcheck.sourceforge.net On Tue, 4 Jun 2019 at 18:20, Eran Kornblau wrote: > Hi all, > > > > Does anyone happen to have some tool/script that can validate source files > against nginx coding conventions? > I believe some of the conventions can be fairly easy to automate (e.g. 80 > chars width, spacing etc.), > and was wondering whether anyone already took the time to implement > something like that? > > > > Thanks! > > > > Eran > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- *Regard,Soshnikov Vasily mailto:dedok.mad at gmail.com * -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Jun 4 16:49:05 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 04 Jun 2019 16:49:05 +0000 Subject: [njs] Fixed Object.defineProperty() for shared descriptors. Message-ID: details: https://hg.nginx.org/njs/rev/8b27db801cd3 branches: changeset: 1000:8b27db801cd3 user: Dmitry Volyntsev date: Tue Jun 04 19:38:50 2019 +0300 description: Fixed Object.defineProperty() for shared descriptors. This closes #172 issue on Github. diffstat: njs/njs_object.c | 33 ++++++++++++++++++++++++++------- njs/njs_object.h | 2 +- njs/njs_vm.c | 2 +- njs/test/njs_unit_test.c | 12 ++++++++++++ 4 files changed, 40 insertions(+), 9 deletions(-) diffs (121 lines): diff -r deef19f6498a -r 8b27db801cd3 njs/njs_object.c --- a/njs/njs_object.c Tue Jun 04 16:07:14 2019 +0300 +++ b/njs/njs_object.c Tue Jun 04 19:38:50 2019 +0300 @@ -708,7 +708,7 @@ njs_external_property_delete(njs_vm_t *v njs_ret_t -njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq) +njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) { nxt_int_t ret; njs_function_t *function; @@ -727,6 +727,20 @@ njs_method_private_copy(njs_vm_t *vm, nj shared = pq->lhq.value; *prop = *shared; + pq->lhq.replace = 0; + pq->lhq.value = prop; + pq->lhq.pool = vm->mem_pool; + + ret = nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + + if (!njs_is_function(&prop->value)) { + return NXT_OK; + } + function = njs_function_value_copy(vm, &prop->value); if (nxt_slow_path(function == NULL)) { return NXT_ERROR; @@ -759,11 +773,7 @@ njs_method_private_copy(njs_vm_t *vm, nj return NXT_ERROR; } - pq->lhq.replace = 0; - pq->lhq.value = prop; - pq->lhq.pool = vm->mem_pool; - - return nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); + return NXT_OK; } @@ -1900,10 +1910,19 @@ njs_define_property(njs_vm_t *vm, njs_va /* Updating existing prop. */ + if (nxt_slow_path(pq.shared)) { + ret = njs_prop_private_copy(vm, &pq); + + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + } + current = pq.lhq.value; switch (current->type) { case NJS_PROPERTY: + case NJS_METHOD: break; case NJS_PROPERTY_REF: @@ -2043,7 +2062,7 @@ njs_object_property_descriptor(njs_vm_t case NJS_METHOD: if (pq.shared) { - ret = njs_method_private_copy(vm, &pq); + ret = njs_prop_private_copy(vm, &pq); if (nxt_slow_path(ret != NXT_OK)) { return ret; diff -r deef19f6498a -r 8b27db801cd3 njs/njs_object.h --- a/njs/njs_object.h Tue Jun 04 16:07:14 2019 +0300 +++ b/njs/njs_object.h Tue Jun 04 19:38:50 2019 +0300 @@ -115,7 +115,7 @@ njs_value_t *njs_property_constructor_cr njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); -njs_ret_t njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq); +njs_ret_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); const char * njs_prop_type_string(njs_object_property_type_t type); extern const njs_object_init_t njs_object_constructor_init; diff -r deef19f6498a -r 8b27db801cd3 njs/njs_vm.c --- a/njs/njs_vm.c Tue Jun 04 16:07:14 2019 +0300 +++ b/njs/njs_vm.c Tue Jun 04 19:38:50 2019 +0300 @@ -3069,7 +3069,7 @@ njs_value_property(njs_vm_t *vm, const n case NJS_METHOD: if (pq.shared) { - ret = njs_method_private_copy(vm, &pq); + ret = njs_prop_private_copy(vm, &pq); if (nxt_slow_path(ret != NXT_OK)) { return ret; diff -r deef19f6498a -r 8b27db801cd3 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Jun 04 16:07:14 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue Jun 04 19:38:50 2019 +0300 @@ -9320,6 +9320,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = {}; Object.defineProperty(o)"), nxt_string("TypeError: descriptor is not an object") }, + { nxt_string("Object.defineProperty(Function.prototype, 'name', {value:'x'}).name"), + nxt_string("x") }, + + { nxt_string("Object.defineProperty(Function.prototype, 'xxx', {value:'x'}).xxx"), + nxt_string("x") }, + + { nxt_string("Object.defineProperty(Object, 'name', {value:'x'}).name"), + nxt_string("x") }, + + { nxt_string("Object.defineProperty(Object.prototype, 'toString', {value:1}).toString"), + nxt_string("1") }, + { nxt_string("var o = Object.defineProperties({}, {a:{value:1}}); o.a"), nxt_string("1") }, From teward at thomas-ward.net Tue Jun 4 17:10:38 2019 From: teward at thomas-ward.net (Thomas Ward) Date: Tue, 4 Jun 2019 13:10:38 -0400 Subject: Patch Submission Rules? Message-ID: I know it comes up many times, but is there a specific document where submitting a patch for consideration via the mailing list exists?? We discovered a nasty evil race condition with pidfiles and how NGINX handles them vs. SystemD downstream in Ubuntu with single-core containers and VMs and systems where the nginx service has some fail-to-run problems due to some PIDfile headaches, and the one who wrote the patch wants to submit it for consideration or at least to spark some discussion on potentially handling the fixes. Thomas -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue Jun 4 18:08:40 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Jun 2019 21:08:40 +0300 Subject: Patch Submission Rules? In-Reply-To: References: Message-ID: <20190604180840.GD1877@mdounin.ru> Hello! On Tue, Jun 04, 2019 at 01:10:38PM -0400, Thomas Ward wrote: > I know it comes up many times, but is there a specific document where > submitting a patch for consideration via the mailing list exists?? We http://nginx.org/en/docs/contributing_changes.html? > discovered a nasty evil race condition with pidfiles and how NGINX > handles them vs. SystemD downstream in Ubuntu with single-core > containers and VMs and systems where the nginx service has some > fail-to-run problems due to some PIDfile headaches, and the one who > wrote the patch wants to submit it for consideration or at least to > spark some discussion on potentially handling the fixes. Likely discussed in this thread (in Russian): http://mailman.nginx.org/pipermail/nginx-ru/2017-November/060604.html TL;DR: the "systemd: PID file ... not readable (yet?) after start" messages are harmless and can be safely ignored. Some patches can be seen here: http://mailman.nginx.org/pipermail/nginx-ru/2017-November/060628.html http://mailman.nginx.org/pipermail/nginx-devel/2017-November/010658.html Both rejected. -- Maxim Dounin http://mdounin.ru/ From naidilepn at gmail.com Tue Jun 4 18:44:55 2019 From: naidilepn at gmail.com (naidile.pn) Date: Wed, 5 Jun 2019 00:14:55 +0530 Subject: NJS - API Calls In-Reply-To: <4ff1e2b9-f3ca-abe3-7f65-b3adbf804263@nginx.com> References: <7cf2a39d-4c1e-6a36-360a-9f6e46be2030@nginx.com> <1AE3A282-4411-44F4-93B9-4B850410BE70@nginx.com> <4ff1e2b9-f3ca-abe3-7f65-b3adbf804263@nginx.com> Message-ID: Thanks a lot! It's working. I had underscore in header which was causing unexpected behavior as such headers get ignored. On Tue, Jun 4, 2019 at 6:25 PM Dmitry Volyntsev wrote: > > > On 04.06.2019 14:00, naidile.pn wrote: > > What does api write=on; mean ? Could you please explain. > > > > > api is a plus-only nginx module > (http://nginx.org/en/docs/http/ngx_http_api_module.html). > > You do not need this to make subrequests. > > > > On Tue, Jun 4, 2019 at 4:26 PM naidile.pn > > > wrote: > > > > Hi Dmitry, > > > > I tried subrequest. But it doesn't work. Nginx is trying find the > > API within /var/www/html folder. > > > Can you elaborate more what are you trying to do? > > See the config below as an example: > > ----------------- > http { > js_include proxy.js; > js_set $summary summary; > js_set $prop prop; > > # proxy server > > server { > listen 8080; > server_name localhost; > > location / { > js_content proxy; > } > > location = /_prop { > internal; > proxy_pass http://127.0.0.1:8090; > } > > location = /_proxy { > internal; > proxy_set_header Prop $prop; > proxy_pass http://127.0.0.1:8070$request_uri; > } > } > > # prop server > > server { > listen 8090; > > location / { > return 200 '{"prop": "WAKA"}'; > } > } > > # dest server > > server { > listen 8070; > > location / { > return 200 $summary; > } > } > } > > ----------------- > function proxy(r) { > r.subrequest("/_prop", reply => { > if (reply.status != 200) { > r.return(500); > return; > } > > r.variables.prop = JSON.parse(reply.responseBody).prop; > r.subrequest("/_proxy", res => { > r.return(res.status != 200 ? 500 : 200, > res.responseBody); > }) > }); > } > > function summary(r) { > var s = "JS summary\n\n"; > > s += "Method: " + r.method + "\n"; > s += "HTTP version: " + r.httpVersion + "\n"; > s += "Host: " + r.headersIn.host + "\n"; > s += "Remote Address: " + r.remoteAddress + "\n"; > s += "URI: " + r.uri + "\n"; > > s += "Headers:\n"; > > for (var h in r.headersIn) { > s += " header '" + h + "' is '" + r.headersIn[h] + "'\n"; > } > > return s; > } > > var prop = (r) => r.variables.prop; > ----------------- > curl http://127.0.0.1:8080/test > JS summary > > Method: GET > HTTP version: 1.0 > Host: 127.0.0.1:8070 > Remote Address: 127.0.0.1 > URI: /test > Headers: > header 'Prop' is 'WAKA' > header 'Host' is '127.0.0.1:8070' > header 'Connection' is 'close' > header 'User-Agent' is 'curl/7.64.0' > header 'Accept' is '*/*' > > ----------------- > > > > > And, with proxy_pass within subrequest, I'm not able to pass the > > request headers and body. Kindly help here. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Wed Jun 5 15:44:41 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 05 Jun 2019 15:44:41 +0000 Subject: [njs] Improved object property attributes. Message-ID: details: https://hg.nginx.org/njs/rev/6d5c457a298d branches: changeset: 1001:6d5c457a298d user: hongzhidao date: Wed Jun 05 22:13:47 2019 +0800 description: Improved object property attributes. diffstat: njs/njs_object.c | 166 +++++++++++++++++++++++++--------------------- njs/njs_object.h | 8 +- njs/test/njs_unit_test.c | 6 +- 3 files changed, 97 insertions(+), 83 deletions(-) diffs (366 lines): diff -r 8b27db801cd3 -r 6d5c457a298d njs/njs_object.c --- a/njs/njs_object.c Tue Jun 04 19:38:50 2019 +0300 +++ b/njs/njs_object.c Wed Jun 05 22:13:47 2019 +0800 @@ -223,9 +223,10 @@ njs_object_prop_alloc(njs_vm_t *vm, cons prop->name = *name; prop->type = NJS_PROPERTY; + prop->writable = attributes; prop->enumerable = attributes; - prop->writable = attributes; prop->configurable = attributes; + return prop; } @@ -520,9 +521,9 @@ njs_array_property_query(njs_vm_t *vm, n prop->type = NJS_PROPERTY_REF; } - prop->configurable = 1; + prop->writable = 1; prop->enumerable = 1; - prop->writable = 1; + prop->configurable = 1; pq->lhq.value = prop; @@ -550,10 +551,11 @@ njs_string_property_query(njs_vm_t *vm, * so the function cannot fail. */ (void) njs_string_slice(vm, &prop->value, &string, &slice); + prop->type = NJS_PROPERTY; + prop->writable = 0; + prop->enumerable = 1; prop->configurable = 0; - prop->enumerable = 1; - prop->writable = 0; pq->lhq.value = prop; @@ -583,9 +585,9 @@ njs_external_property_query(njs_vm_t *vm prop = &pq->scratch; prop->type = NJS_PROPERTY; - prop->configurable = 0; + prop->writable = 0; prop->enumerable = 1; - prop->writable = 0; + prop->configurable = 0; ext_proto = object->external.proto; @@ -1798,54 +1800,49 @@ njs_object_define_properties(njs_vm_t *v } -static uint8_t -njs_descriptor_attribute(njs_vm_t *vm, const njs_object_t *descriptor, - nxt_lvlhsh_query_t *pq, nxt_bool_t unset) -{ - njs_object_prop_t *prop; - - prop = njs_object_property(vm, descriptor, pq); - if (prop != NULL) { - return prop->value.data.truth; - } - - return unset ? NJS_ATTRIBUTE_UNSET : 0; -} - - static njs_object_prop_t * njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, - const njs_object_t *descriptor, nxt_bool_t unset) + const njs_object_t *descriptor) { - const njs_value_t *value; njs_object_prop_t *prop, *pr; nxt_lvlhsh_query_t pq; - value = unset ? &njs_value_invalid : &njs_value_undefined; - prop = njs_object_prop_alloc(vm, name, value, 0); + prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, + NJS_ATTRIBUTE_UNSET); if (nxt_slow_path(prop == NULL)) { return NULL; } + pq.key = nxt_string_value("value"); + pq.key_hash = NJS_VALUE_HASH; + + pr = njs_object_property(vm, descriptor, &pq); + if (pr != NULL) { + prop->value = pr->value; + } + + pq.key = nxt_string_value("writable"); + pq.key_hash = NJS_WRITABABLE_HASH; + + pr = njs_object_property(vm, descriptor, &pq); + if (pr != NULL) { + prop->writable = pr->value.data.truth; + } + + pq.key = nxt_string_value("enumerable"); + pq.key_hash = NJS_ENUMERABLE_HASH; + + pr = njs_object_property(vm, descriptor, &pq); + if (pr != NULL) { + prop->enumerable = pr->value.data.truth; + } + pq.key = nxt_string_value("configurable"); pq.key_hash = NJS_CONFIGURABLE_HASH; - prop->configurable = njs_descriptor_attribute(vm, descriptor, &pq, unset); - - pq.key = nxt_string_value("enumerable"); - pq.key_hash = NJS_ENUMERABLE_HASH; - prop->enumerable = njs_descriptor_attribute(vm, descriptor, &pq, unset); - - pq.key = nxt_string_value("writable"); - pq.key_hash = NJS_WRITABABLE_HASH; - prop->writable = njs_descriptor_attribute(vm, descriptor, &pq, unset); - - pq.key = nxt_string_value("value"); - pq.key_hash = NJS_VALUE_HASH; - pq.proto = &njs_object_hash_proto; pr = njs_object_property(vm, descriptor, &pq); if (pr != NULL) { - prop->value = pr->value; + prop->configurable = pr->value.data.truth; } return prop; @@ -1862,7 +1859,6 @@ njs_define_property(njs_vm_t *vm, njs_va const njs_object_t *descriptor) { nxt_int_t ret; - nxt_bool_t unset; njs_object_prop_t *desc, *current; njs_property_query_t pq; @@ -1878,13 +1874,29 @@ njs_define_property(njs_vm_t *vm, njs_va return ret; } - unset = (ret == NXT_OK); - desc = njs_descriptor_prop(vm, name, descriptor, unset); + desc = njs_descriptor_prop(vm, name, descriptor); if (nxt_slow_path(desc == NULL)) { return NXT_ERROR; } if (nxt_fast_path(ret == NXT_DECLINED)) { + + if (!njs_is_valid(&desc->value)) { + desc->value = njs_value_undefined; + } + + if (desc->writable == NJS_ATTRIBUTE_UNSET) { + desc->writable = 0; + } + + if (desc->enumerable == NJS_ATTRIBUTE_UNSET) { + desc->enumerable = 0; + } + + if (desc->configurable == NJS_ATTRIBUTE_UNSET) { + desc->configurable = 0; + } + if (nxt_slow_path(pq.lhq.value != NULL)) { current = pq.lhq.value; @@ -1955,12 +1967,10 @@ njs_define_property(njs_vm_t *vm, njs_va } if (!current->configurable) { - if (desc->configurable == NJS_ATTRIBUTE_TRUE) { - goto exception; - } - - if (desc->enumerable != NJS_ATTRIBUTE_UNSET - && current->enumerable != desc->enumerable) + + if (njs_is_valid(&desc->value) + && current->writable == NJS_ATTRIBUTE_FALSE + && !njs_values_strict_equal(&desc->value, ¤t->value)) { goto exception; } @@ -1971,28 +1981,31 @@ njs_define_property(njs_vm_t *vm, njs_va goto exception; } - if (njs_is_valid(&desc->value) - && current->writable == NJS_ATTRIBUTE_FALSE - && !njs_values_strict_equal(&desc->value, ¤t->value)) + if (desc->enumerable != NJS_ATTRIBUTE_UNSET + && current->enumerable != desc->enumerable) { goto exception; } + + if (desc->configurable == NJS_ATTRIBUTE_TRUE) { + goto exception; + } } - if (desc->configurable != NJS_ATTRIBUTE_UNSET) { - current->configurable = desc->configurable; + if (njs_is_valid(&desc->value)) { + current->value = desc->value; + } + + if (desc->writable != NJS_ATTRIBUTE_UNSET) { + current->writable = desc->writable; } if (desc->enumerable != NJS_ATTRIBUTE_UNSET) { current->enumerable = desc->enumerable; } - if (desc->writable != NJS_ATTRIBUTE_UNSET) { - current->writable = desc->writable; - } - - if (njs_is_valid(&desc->value)) { - current->value = desc->value; + if (desc->configurable != NJS_ATTRIBUTE_UNSET) { + current->configurable = desc->configurable; } return NXT_OK; @@ -2006,12 +2019,12 @@ exception: static const njs_value_t njs_object_value_string = njs_string("value"); +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"); -static const njs_value_t njs_object_enumerable_string = - njs_string("enumerable"); -static const njs_value_t njs_object_writable_string = - njs_string("writable"); static njs_ret_t @@ -2087,7 +2100,6 @@ njs_object_property_descriptor(njs_vm_t lhq.proto = &njs_object_hash_proto; lhq.replace = 0; lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; lhq.key = nxt_string_value("value"); lhq.key_hash = NJS_VALUE_HASH; @@ -2105,12 +2117,12 @@ njs_object_property_descriptor(njs_vm_t return NXT_ERROR; } - lhq.key = nxt_string_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); + lhq.key = nxt_string_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 (nxt_slow_path(pr == NULL)) { return NXT_ERROR; } @@ -2141,12 +2153,12 @@ njs_object_property_descriptor(njs_vm_t return NXT_ERROR; } - lhq.key = nxt_string_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); + lhq.key = nxt_string_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 (nxt_slow_path(pr == NULL)) { return NXT_ERROR; } diff -r 8b27db801cd3 -r 6d5c457a298d njs/njs_object.h --- a/njs/njs_object.h Tue Jun 04 19:38:50 2019 +0300 +++ b/njs/njs_object.h Wed Jun 05 22:13:47 2019 +0800 @@ -27,6 +27,7 @@ typedef enum { NJS_ATTRIBUTE_UNSET, } njs_object_attribute_t; + typedef struct { /* Must be aligned to njs_value_t. */ njs_value_t value; @@ -34,8 +35,8 @@ typedef struct { njs_object_property_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 writable:8; /* 2 bits */ njs_object_attribute_t configurable:8; /* 2 bits */ } njs_object_prop_t; @@ -99,7 +100,7 @@ nxt_int_t njs_object_hash_create(njs_vm_ njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); 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); + const njs_value_t *value, uint8_t attributes); njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value, @@ -116,9 +117,10 @@ njs_ret_t njs_object_prototype_to_string nxt_uint_t nargs, njs_index_t unused); njs_ret_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); -const char * njs_prop_type_string(njs_object_property_type_t type); +const char *njs_prop_type_string(njs_object_property_type_t type); extern const njs_object_init_t njs_object_constructor_init; extern const njs_object_init_t njs_object_prototype_init; + #endif /* _NJS_OBJECT_H_INCLUDED_ */ diff -r 8b27db801cd3 -r 6d5c457a298d njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Jun 04 19:38:50 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed Jun 05 22:13:47 2019 +0800 @@ -9598,7 +9598,7 @@ static njs_unit_test_t njs_test[] = nxt_string("undefined") }, { nxt_string("JSON.stringify(Object.getOwnPropertyDescriptor([3,4], 'length'))"), - nxt_string("{\"value\":2,\"configurable\":false,\"enumerable\":false,\"writable\":true}") }, + nxt_string("{\"value\":2,\"writable\":true,\"enumerable\":false,\"configurable\":false}") }, { nxt_string("Object.getOwnPropertyDescriptor(Array.of, 'length').value"), nxt_string("0") }, @@ -9614,10 +9614,10 @@ static njs_unit_test_t njs_test[] = nxt_string("1") }, { nxt_string("JSON.stringify(Object.getOwnPropertyDescriptor('????', '2'))"), - nxt_string("{\"value\":\"?\",\"configurable\":false,\"enumerable\":true,\"writable\":false}") }, + nxt_string("{\"value\":\"?\",\"writable\":false,\"enumerable\":true,\"configurable\":false}") }, { nxt_string("JSON.stringify(Object.getOwnPropertyDescriptor(new String('abc'), 'length'))"), - nxt_string("{\"value\":3,\"configurable\":false,\"enumerable\":false,\"writable\":false}") }, + nxt_string("{\"value\":3,\"writable\":false,\"enumerable\":false,\"configurable\":false}") }, { nxt_string("Object.getOwnPropertyDescriptor(1, '0')"), nxt_string("undefined") }, From arut at nginx.com Wed Jun 5 17:33:58 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Wed, 05 Jun 2019 17:33:58 +0000 Subject: [nginx] Limit req: limit_req_dry_run directive. Message-ID: details: https://hg.nginx.org/nginx/rev/2db68852d6a0 branches: changeset: 7515:2db68852d6a0 user: Roman Arutyunyan date: Wed Jun 05 19:55:27 2019 +0300 description: Limit req: limit_req_dry_run directive. A new directive limit_req_dry_run allows enabling the dry run mode. In this mode requests are neither rejected nor delayed, but reject/delay status is logged as usual. diffstat: src/http/modules/ngx_http_limit_req_module.c | 29 ++++++++++++++++++++++++--- 1 files changed, 25 insertions(+), 4 deletions(-) diffs (83 lines): diff -r 319242d2ddc9 -r 2db68852d6a0 src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c Mon Jun 03 20:33:26 2019 +0300 +++ b/src/http/modules/ngx_http_limit_req_module.c Wed Jun 05 19:55:27 2019 +0300 @@ -53,6 +53,7 @@ typedef struct { ngx_uint_t limit_log_level; ngx_uint_t delay_log_level; ngx_uint_t status_code; + ngx_flag_t dry_run; } ngx_http_limit_req_conf_t; @@ -118,6 +119,13 @@ static ngx_command_t ngx_http_limit_req offsetof(ngx_http_limit_req_conf_t, status_code), &ngx_http_limit_req_status_bounds }, + { ngx_string("limit_req_dry_run"), + 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_limit_req_conf_t, dry_run), + NULL }, + ngx_null_command }; @@ -230,9 +238,10 @@ ngx_http_limit_req_handler(ngx_http_requ if (rc == NGX_BUSY) { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, - "limiting requests, excess: %ui.%03ui by zone \"%V\"", - excess / 1000, excess % 1000, - &limit->shm_zone->shm.name); + "limiting requests%s, excess: %ui.%03ui by zone \"%V\"", + lrcf->dry_run ? ", dry run" : "", + excess / 1000, excess % 1000, + &limit->shm_zone->shm.name); } while (n--) { @@ -251,6 +260,10 @@ ngx_http_limit_req_handler(ngx_http_requ ctx->node = NULL; } + if (lrcf->dry_run) { + return NGX_DECLINED; + } + return lrcf->status_code; } @@ -267,9 +280,14 @@ ngx_http_limit_req_handler(ngx_http_requ } ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, - "delaying request, excess: %ui.%03ui, by zone \"%V\"", + "delaying request%s, excess: %ui.%03ui, by zone \"%V\"", + lrcf->dry_run ? ", dry run" : "", excess / 1000, excess % 1000, &limit->shm_zone->shm.name); + if (lrcf->dry_run) { + return NGX_DECLINED; + } + if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -711,6 +729,7 @@ ngx_http_limit_req_create_conf(ngx_conf_ conf->limit_log_level = NGX_CONF_UNSET_UINT; conf->status_code = NGX_CONF_UNSET_UINT; + conf->dry_run = NGX_CONF_UNSET; return conf; } @@ -735,6 +754,8 @@ ngx_http_limit_req_merge_conf(ngx_conf_t ngx_conf_merge_uint_value(conf->status_code, prev->status_code, NGX_HTTP_SERVICE_UNAVAILABLE); + ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0); + return NGX_CONF_OK; } From eran.kornblau at kaltura.com Thu Jun 6 13:06:38 2019 From: eran.kornblau at kaltura.com (Eran Kornblau) Date: Thu, 6 Jun 2019 13:06:38 +0000 Subject: Question about ngx_chain_writer Message-ID: Hi all, Looking at ngx_chain_writer, there's something that looks a bit off to me, this line seems redundant - https://github.com/nginx/nginx/blob/master/src/core/ngx_output_chain.c#L728 The first loop in the function adds the input chain (in) to the end of ctx->out. The second loop in the function calculates the total size of ctx->out, so it will add the size of the 'in' buffers again. I verified in gdb that size is indeed x2 the size of the chain. This isn't causing any problem since size is only compared to zero, but seems a bit confusing... It may have been better to leave the 'size += ngx_buf_size(in->buf);' but reverse the order of the 2 loops, so that the input buffers will be validated only once. Does this make sense or did I get something wrong? Thanks Eran -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Jun 6 18:09:39 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 6 Jun 2019 21:09:39 +0300 Subject: Question about ngx_chain_writer In-Reply-To: References: Message-ID: <20190606180939.GM1877@mdounin.ru> Hello! On Thu, Jun 06, 2019 at 01:06:38PM +0000, Eran Kornblau wrote: > Hi all, > > Looking at ngx_chain_writer, there's something that looks a bit off to me, this line seems redundant - > https://github.com/nginx/nginx/blob/master/src/core/ngx_output_chain.c#L728 > > The first loop in the function adds the input chain (in) to the end of ctx->out. > The second loop in the function calculates the total size of ctx->out, so it will add the size of the 'in' buffers again. > I verified in gdb that size is indeed x2 the size of the chain. > > This isn't causing any problem since size is only compared to zero, but seems a bit confusing... > It may have been better to leave the 'size += ngx_buf_size(in->buf);' but reverse the order of the 2 loops, > so that the input buffers will be validated only once. > > Does this make sense or did I get something wrong? Yes, ngx_chain_writer() function was written to work with very few buffers, and isn't optimal. A better though similar code can be seen in ngx_http_write_filter(). -- Maxim Dounin http://mdounin.ru/ From rnickb731 at gmail.com Fri Jun 7 19:54:22 2019 From: rnickb731 at gmail.com (Ryan Burn) Date: Fri, 7 Jun 2019 12:54:22 -0700 Subject: Any way to get timestamps for upstream-downstream events? Message-ID: Hello everyone, I work on a module that provides distributed tracing for NGINX (https://github.com/opentracing-contrib/nginx-opentracing). If possible, I would like to include in the tracing data timestamps for the following events: * When the last byte from a downstream request was read * When the first byte of an upstream request was sent * When the last byte of an upstream request was sent * When the first byte of an upstream response was read * When the last byte of an upstream response was read * When the first byte of a downstream response was sent * When the last byte of a downstream response was sent I recently added similar data to Envoy's tracing (https://github.com/envoyproxy/envoy/pull/5915), but I'm having trouble finding out how to access this data from an NGINX module. Anyone know if it's possible? Thanks, Ryan From careygister at outlook.com Sat Jun 8 00:44:29 2019 From: careygister at outlook.com (Carey Gister) Date: Sat, 8 Jun 2019 00:44:29 +0000 Subject: ngx_module_order directive Message-ID: Hello, I'm writing a new module and I want to place in a specific order in the module list as defined in ngx_modules.c. If my module name is x_module and I want it to run after ngx_http_slice_filter_module I tried: ngx_module_order=x_module ngx_http_slice_filter_module and I am informed during configuration that 'ngx_http_slice_filter_module does not exist. What is the correct syntax for this directive? Carey Gister 415-310-5304 -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Jun 10 12:55:23 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 10 Jun 2019 15:55:23 +0300 Subject: ngx_module_order directive In-Reply-To: References: Message-ID: <20190610125523.GU1877@mdounin.ru> Hello! On Sat, Jun 08, 2019 at 12:44:29AM +0000, Carey Gister wrote: > I'm writing a new module and I want to place in a specific order in the module list as defined in ngx_modules.c. > > If my module name is x_module and I want it to run after ngx_http_slice_filter_module I tried: > > ngx_module_order=x_module ngx_http_slice_filter_module > > and I am informed during configuration that 'ngx_http_slice_filter_module does not exist. > > What is the correct syntax for this directive? The config file is a shell script, and expected to follow POSIX shell syntax. That is, to define a variable with a space in it you have to use double quotes: ngx_module_order="x_module ngx_http_slice_filter_module" Note well that it is generally a bad idea to explicitly define module order unless you know what are you doing and why. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon Jun 10 13:40:51 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 10 Jun 2019 16:40:51 +0300 Subject: Any way to get timestamps for upstream-downstream events? In-Reply-To: References: Message-ID: <20190610134051.GV1877@mdounin.ru> Hello! On Fri, Jun 07, 2019 at 12:54:22PM -0700, Ryan Burn wrote: > Hello everyone, > > I work on a module that provides distributed tracing for NGINX > (https://github.com/opentracing-contrib/nginx-opentracing). If > possible, I would like to include in the tracing data timestamps for > the following events: > > * When the last byte from a downstream request was read This information isn't generally available. If you need it, you can record this in your own module. > * When the first byte of an upstream request was sent This is more or less the same as the time connect was finished. For each peer tried during request processing related information can be found in the $upstream_connect_time variable. Note that, much like other upstream-related variables, these timings are a) per upstream connection attempt, so there can be many for a given request, and b) not absolute, and instead specify duration of appropriate operations. > * When the last byte of an upstream request was sent This information isn't generally available. > * When the first byte of an upstream response was read Closest information available is $upstream_header_time. > * When the last byte of an upstream response was read Check $upstream_response_time. > * When the first byte of a downstream response was sent This information is not generally available. > * When the last byte of a downstream response was sent Check $response_time. Alternatively, you can record this information in your own module. -- Maxim Dounin http://mdounin.ru/ From Elliot.Thomas at bbc.co.uk Tue Jun 11 10:28:19 2019 From: Elliot.Thomas at bbc.co.uk (Elliot Thomas) Date: Tue, 11 Jun 2019 10:28:19 +0000 Subject: [PATCH] Apply cache locking behaviour to stale cache entries. In-Reply-To: <20190117132401.GJ99070@mdounin.ru> References: <20181210190717.GV99070@mdounin.ru> <20190117132401.GJ99070@mdounin.ru> Message-ID: Hello! On 17/01/2019, 13:24, Maxim Dounin wrote: > >Sorry, I'm a bit busy with other tasks now. Hopefully I'll >be able to look again at the patch later this month. Just a gentle nudge regarding the "proxy cache lock" patch. I?ve tested it out. The patch still applies to Nginx master and works as expected. If there are any other improvements needed, I'd be happy to do them. Regards, Elliot --- Please ignore the following disclaimer, it?s a bit silly. I have read the contribution guide, and am fine with it. > -------------- next part -------------- A non-text attachment was scrubbed... Name: proxy-cache-lock-on-stale-v2.patch Type: application/octet-stream Size: 3263 bytes Desc: proxy-cache-lock-on-stale-v2.patch URL: From xeioex at nginx.com Tue Jun 11 14:35:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 11 Jun 2019 14:35:15 +0000 Subject: [njs] Fixed truth value of JSON numbers in JSON.parse(). Message-ID: details: https://hg.nginx.org/njs/rev/028277f5c551 branches: changeset: 1004:028277f5c551 user: Dmitry Volyntsev date: Tue Jun 11 17:34:59 2019 +0300 description: Fixed truth value of JSON numbers in JSON.parse(). This closes #180 issue on Github. diffstat: njs/njs_json.c | 3 ++- njs/test/njs_unit_test.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletions(-) diffs (48 lines): diff -r c46dca06edb1 -r 028277f5c551 njs/njs_json.c --- a/njs/njs_json.c Mon Jun 10 21:40:11 2019 -0400 +++ b/njs/njs_json.c Tue Jun 11 17:34:59 2019 +0300 @@ -876,8 +876,9 @@ njs_json_parse_number(njs_json_parse_ctx start = p; num = njs_number_dec_parse(&p, ctx->end); if (p != start) { - *value = njs_value_zero; value->data.u.number = sign * num; + value->type = NJS_NUMBER; + value->data.truth = njs_is_number_true(num); return p; } diff -r c46dca06edb1 -r 028277f5c551 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon Jun 10 21:40:11 2019 -0400 +++ b/njs/test/njs_unit_test.c Tue Jun 11 17:34:59 2019 +0300 @@ -11724,6 +11724,30 @@ static njs_unit_test_t njs_test[] = "o.b = 3; o.b"), nxt_string("3") }, + { nxt_string("JSON.parse('2') || 10"), + nxt_string("2") }, + + { nxt_string("JSON.parse('0') || 10"), + nxt_string("10") }, + + { nxt_string("JSON.parse('-0') || 10"), + nxt_string("10") }, + + { nxt_string("JSON.parse('\"a\"') || 10"), + nxt_string("a") }, + + { nxt_string("JSON.parse('\"\"') || 10"), + nxt_string("10") }, + + { nxt_string("JSON.parse('true') || 10"), + nxt_string("true") }, + + { nxt_string("JSON.parse('false') || 10"), + nxt_string("10") }, + + { nxt_string("JSON.parse('null') || 10"), + nxt_string("10") }, + { nxt_string("var o = JSON.parse('{}', function(k, v) {return v;}); o"), nxt_string("[object Object]") }, From xeioex at nginx.com Tue Jun 11 14:35:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 11 Jun 2019 14:35:15 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/c46dca06edb1 branches: changeset: 1003:c46dca06edb1 user: hongzhidao date: Mon Jun 10 21:40:11 2019 -0400 description: Style. diffstat: njs/njs_object.c | 8 ++++---- njs/njs_object.h | 10 +++++----- njs/njs_object_property.c | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diffs (108 lines): diff -r 81ae2f4a1686 -r c46dca06edb1 njs/njs_object.c --- a/njs/njs_object.c Mon Jun 10 21:30:29 2019 -0400 +++ b/njs/njs_object.c Mon Jun 10 21:40:11 2019 -0400 @@ -1142,7 +1142,7 @@ njs_object_define_property(njs_vm_t *vm, name = njs_arg(args, nargs, 2); - ret = njs_define_property(vm, value, name, descriptor->data.u.object); + ret = njs_object_prop_define(vm, value, name, descriptor->data.u.object); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -1196,7 +1196,7 @@ njs_object_define_properties(njs_vm_t *v } if (prop->enumerable && njs_is_object(&prop->value)) { - ret = njs_define_property(vm, value, &prop->name, + ret = njs_object_prop_define(vm, value, &prop->name, prop->value.data.u.object); if (nxt_slow_path(ret != NXT_OK)) { @@ -1227,7 +1227,7 @@ njs_object_get_own_property_descriptor(n property = njs_arg(args, nargs, 2); - return njs_object_property_descriptor(vm, &vm->retval, value, property); + return njs_object_prop_descriptor(vm, &vm->retval, value, property); } @@ -1271,7 +1271,7 @@ njs_object_get_own_property_descriptors( for (i = 0; i < length; i++) { key = &names->start[i]; - ret = njs_object_property_descriptor(vm, &descriptor, value, key); + ret = njs_object_prop_descriptor(vm, &descriptor, value, key); if (nxt_slow_path(ret != NXT_OK)) { return ret; } diff -r 81ae2f4a1686 -r c46dca06edb1 njs/njs_object.h --- a/njs/njs_object.h Mon Jun 10 21:30:29 2019 -0400 +++ b/njs/njs_object.h Mon Jun 10 21:40:11 2019 -0400 @@ -14,7 +14,7 @@ typedef enum { NJS_METHOD, NJS_PROPERTY_HANDLER, NJS_WHITEOUT, -} njs_object_property_type_t; +} njs_object_prop_type_t; /* @@ -33,7 +33,7 @@ typedef struct { njs_value_t value; njs_value_t name; - njs_object_property_type_t type:8; /* 3 bits */ + 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 */ @@ -116,12 +116,12 @@ njs_object_prop_t *njs_object_prop_alloc const njs_value_t *value, uint8_t attributes); njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj, nxt_lvlhsh_query_t *lhq); -njs_ret_t njs_define_property(njs_vm_t *vm, njs_value_t *object, +njs_ret_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, const njs_value_t *name, const njs_object_t *descriptor); -njs_ret_t njs_object_property_descriptor(njs_vm_t *vm, njs_value_t *dest, +njs_ret_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, const njs_value_t *value, const njs_value_t *property); njs_ret_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); -const char *njs_prop_type_string(njs_object_property_type_t type); +const char *njs_prop_type_string(njs_object_prop_type_t type); extern const njs_object_init_t njs_object_constructor_init; extern const njs_object_init_t njs_object_prototype_init; diff -r 81ae2f4a1686 -r c46dca06edb1 njs/njs_object_property.c --- a/njs/njs_object_property.c Mon Jun 10 21:30:29 2019 -0400 +++ b/njs/njs_object_property.c Mon Jun 10 21:40:11 2019 -0400 @@ -748,8 +748,8 @@ njs_object_property(njs_vm_t *vm, const * (values can be set, but without property flags support). */ njs_ret_t -njs_define_property(njs_vm_t *vm, njs_value_t *object, const njs_value_t *name, - const njs_object_t *descriptor) +njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, + const njs_value_t *name, const njs_object_t *descriptor) { nxt_int_t ret; njs_object_prop_t *desc, *current; @@ -970,7 +970,7 @@ static const njs_value_t njs_object_con njs_ret_t -njs_object_property_descriptor(njs_vm_t *vm, njs_value_t *dest, +njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, const njs_value_t *value, const njs_value_t *property) { nxt_int_t ret; @@ -1192,7 +1192,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_ const char * -njs_prop_type_string(njs_object_property_type_t type) +njs_prop_type_string(njs_object_prop_type_t type) { switch (type) { case NJS_PROPERTY_REF: From xeioex at nginx.com Tue Jun 11 14:35:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 11 Jun 2019 14:35:15 +0000 Subject: [njs] Moving object property methods to njs_object_property.c. Message-ID: details: https://hg.nginx.org/njs/rev/81ae2f4a1686 branches: changeset: 1002:81ae2f4a1686 user: hongzhidao date: Mon Jun 10 21:30:29 2019 -0400 description: Moving object property methods to njs_object_property.c. diffstat: auto/sources | 1 + njs/njs_object.c | 997 +------------------------------------ njs/njs_object.h | 24 +- njs/njs_object_property.c | 1216 +++++++++++++++++++++++++++++++++++++++++++++ njs/njs_vm.c | 214 ------- 5 files changed, 1233 insertions(+), 1219 deletions(-) diffs (truncated from 2539 to 1000 lines): diff -r 6d5c457a298d -r 81ae2f4a1686 auto/sources --- a/auto/sources Wed Jun 05 22:13:47 2019 +0800 +++ b/auto/sources Mon Jun 10 21:30:29 2019 -0400 @@ -35,6 +35,7 @@ NJS_LIB_SRCS=" \ njs/njs_number.c \ njs/njs_string.c \ njs/njs_object.c \ + njs/njs_object_property.c \ njs/njs_array.c \ njs/njs_json.c \ njs/njs_function.c \ diff -r 6d5c457a298d -r 81ae2f4a1686 njs/njs_object.c --- a/njs/njs_object.c Wed Jun 05 22:13:47 2019 +0800 +++ b/njs/njs_object.c Mon Jun 10 21:30:29 2019 -0400 @@ -9,22 +9,6 @@ static nxt_int_t njs_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data); -static njs_ret_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_ret_t njs_array_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_array_t *array, uint32_t index); -static njs_ret_t njs_string_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_value_t *object, uint32_t index); -static njs_ret_t njs_external_property_query(njs_vm_t *vm, - njs_property_query_t *pq, njs_value_t *object); -static njs_ret_t njs_external_property_set(njs_vm_t *vm, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval); -static njs_ret_t njs_external_property_delete(njs_vm_t *vm, njs_value_t *value, - njs_value_t *setval, njs_value_t *retval); -static njs_ret_t njs_define_property(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *name, const njs_object_t *descriptor); - static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin, const njs_object_t *end, nxt_lvlhsh_query_t *lhq); static uint32_t njs_object_enumerate_array_length(const njs_object_t *object); @@ -206,579 +190,6 @@ njs_object_hash_test(nxt_lvlhsh_query_t } -nxt_noinline 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 = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_object_prop_t)); - - if (nxt_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; - - return prop; - } - - njs_memory_error(vm); - - return NULL; -} - - -nxt_noinline njs_object_prop_t * -njs_object_property(njs_vm_t *vm, const njs_object_t *object, - nxt_lvlhsh_query_t *lhq) -{ - nxt_int_t ret; - - lhq->proto = &njs_object_hash_proto; - - do { - ret = nxt_lvlhsh_find(&object->hash, lhq); - - if (nxt_fast_path(ret == NXT_OK)) { - return lhq->value; - } - - ret = nxt_lvlhsh_find(&object->shared_hash, lhq); - - if (nxt_fast_path(ret == NXT_OK)) { - return lhq->value; - } - - object = object->__proto__; - - } while (object != NULL); - - return NULL; -} - - -/* - * ES5.1, 8.12.1: [[GetOwnProperty]], [[GetProperty]]. - * The njs_property_query() returns values - * NXT_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. - * NXT_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_TRAP the property trap must be called, - * NXT_ERROR exception has been thrown. - * - * TODO: - * Object.defineProperty([1,2], '1', {configurable:false}) - */ - -njs_ret_t -njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, - const njs_value_t *property) -{ - uint32_t index; - uint32_t (*hash)(const void *, size_t); - njs_ret_t ret; - njs_object_t *obj; - njs_function_t *function; - - if (nxt_slow_path(!njs_is_primitive(property))) { - return njs_trap(vm, NJS_TRAP_PROPERTY); - } - - hash = nxt_djb_hash; - - 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 (nxt_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { - index = njs_value_to_index(property); - - if (nxt_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 = object->data.u.object; - break; - - case NJS_FUNCTION: - function = njs_function_value_copy(vm, object); - if (nxt_slow_path(function == NULL)) { - return NXT_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 (nxt_fast_path(ret == NXT_OK)) { - njs_string_get(&pq->value, &pq->lhq.key); - njs_type_error(vm, "cannot get property \"%V\" of undefined", - &pq->lhq.key); - return NXT_ERROR; - } - - njs_type_error(vm, "cannot get property \"unknown\" of undefined"); - - return NXT_ERROR; - } - - ret = njs_primitive_value_to_string(vm, &pq->value, property); - - if (nxt_fast_path(ret == NXT_OK)) { - - njs_string_get(&pq->value, &pq->lhq.key); - pq->lhq.key_hash = 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_ret_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_ret_t ret; - nxt_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; - - own = pq->own; - pq->own = 1; - - proto = object; - - do { - pq->prototype = proto; - - if (!njs_is_null_or_undefined_or_boolean(property)) { - switch (proto->type) { - case NJS_ARRAY: - index = njs_value_to_index(property); - if (nxt_fast_path(index < NJS_ARRAY_MAX_INDEX)) { - array = (njs_array_t *) proto; - return njs_array_property_query(vm, pq, array, index); - } - - break; - - case NJS_OBJECT_STRING: - index = njs_value_to_index(property); - if (nxt_fast_path(index < NJS_STRING_MAX_LENGTH)) { - ov = (njs_object_value_t *) proto; - ret = njs_string_property_query(vm, pq, &ov->value, index); - - if (nxt_fast_path(ret != NXT_DECLINED)) { - return ret; - } - } - - default: - break; - } - } - - ret = nxt_lvlhsh_find(&proto->hash, &pq->lhq); - - if (ret == NXT_OK) { - prop = pq->lhq.value; - - if (prop->type != NJS_WHITEOUT) { - return ret; - } - - if (pq->own) { - pq->own_whiteout = prop; - } - - } else { - ret = nxt_lvlhsh_find(&proto->shared_hash, &pq->lhq); - - if (ret == NXT_OK) { - pq->shared = 1; - - return ret; - } - } - - if (own) { - return NXT_DECLINED; - } - - pq->own = 0; - proto = proto->__proto__; - - } while (proto != NULL); - - return NXT_DECLINED; -} - - -static njs_ret_t -njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_array_t *array, uint32_t index) -{ - uint32_t size; - njs_ret_t ret; - njs_value_t *value; - njs_object_prop_t *prop; - - if (index >= array->length) { - if (pq->query != NJS_PROPERTY_QUERY_SET) { - return NXT_DECLINED; - } - - size = index - array->length; - - ret = njs_array_expand(vm, array, 0, size + 1); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - - value = &array->start[array->length]; - - while (size != 0) { - njs_set_invalid(value); - value++; - size--; - } - - array->length = index + 1; - } - - prop = &pq->scratch; - - if (pq->query == NJS_PROPERTY_QUERY_GET) { - if (!njs_is_valid(&array->start[index])) { - return NXT_DECLINED; - } - - prop->value = array->start[index]; - prop->type = NJS_PROPERTY; - - } else { - prop->value.data.u.value = &array->start[index]; - prop->type = NJS_PROPERTY_REF; - } - - prop->writable = 1; - prop->enumerable = 1; - prop->configurable = 1; - - pq->lhq.value = prop; - - return NXT_OK; -} - - -static njs_ret_t -njs_string_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_value_t *object, uint32_t index) -{ - njs_slice_prop_t slice; - njs_object_prop_t *prop; - njs_string_prop_t string; - - prop = &pq->scratch; - - slice.start = index; - slice.length = 1; - slice.string_length = njs_string_prop(&string, object); - - if (slice.start < slice.string_length) { - /* - * A single codepoint string fits in retval - * so the function cannot fail. - */ - (void) njs_string_slice(vm, &prop->value, &string, &slice); - - prop->type = NJS_PROPERTY; - prop->writable = 0; - prop->enumerable = 1; - prop->configurable = 0; - - pq->lhq.value = prop; - - 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); - } - - return NXT_OK; - } - - return NXT_DECLINED; -} - - -static njs_ret_t -njs_external_property_query(njs_vm_t *vm, njs_property_query_t *pq, - njs_value_t *object) -{ - void *obj; - njs_ret_t ret; - uintptr_t data; - njs_object_prop_t *prop; - const njs_extern_t *ext_proto; - - prop = &pq->scratch; - - prop->type = NJS_PROPERTY; - prop->writable = 0; - prop->enumerable = 1; - prop->configurable = 0; - - ext_proto = object->external.proto; - - pq->lhq.proto = &njs_extern_hash_proto; - ret = nxt_lvlhsh_find(&ext_proto->hash, &pq->lhq); - - if (ret == NXT_OK) { - ext_proto = pq->lhq.value; - - prop->value.type = NJS_EXTERNAL; - prop->value.data.truth = 1; - prop->value.external.proto = ext_proto; - prop->value.external.index = object->external.index; - - if ((ext_proto->type & NJS_EXTERN_OBJECT) != 0) { - goto done; - } - - data = ext_proto->data; - - } else { - data = (uintptr_t) &pq->lhq.key; - } - - switch (pq->query) { - - case NJS_PROPERTY_QUERY_GET: - if (ext_proto->get != NULL) { - obj = njs_extern_object(vm, object); - ret = ext_proto->get(vm, &prop->value, obj, data); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - } - - break; - - case NJS_PROPERTY_QUERY_SET: - case NJS_PROPERTY_QUERY_DELETE: - - prop->type = NJS_PROPERTY_HANDLER; - prop->name = *object; - - if (pq->query == NJS_PROPERTY_QUERY_SET) { - prop->writable = (ext_proto->set != NULL); - prop->value.data.u.prop_handler = njs_external_property_set; - - } else { - prop->configurable = (ext_proto->find != NULL); - prop->value.data.u.prop_handler = njs_external_property_delete; - } - - pq->ext_data = data; - pq->ext_proto = ext_proto; - pq->ext_index = object->external.index; - - pq->lhq.value = prop; - - vm->stash = (uintptr_t) pq; - - return NXT_OK; - } - -done: - - if (ext_proto->type == NJS_EXTERN_METHOD) { - prop->value.type = NJS_FUNCTION; - prop->value.data.u.function = ext_proto->function; - prop->value.data.truth = 1; - } - - pq->lhq.value = prop; - - return ret; -} - - -static njs_ret_t -njs_external_property_set(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval) -{ - void *obj; - njs_ret_t ret; - nxt_str_t s; - njs_property_query_t *pq; - - pq = (njs_property_query_t *) vm->stash; - - if (!njs_is_null_or_undefined(setval)) { - ret = njs_vm_value_to_ext_string(vm, &s, setval, 0); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - - } else { - s = nxt_string_value(""); - } - - *retval = *setval; - - obj = njs_extern_index(vm, pq->ext_index); - - return pq->ext_proto->set(vm, obj, pq->ext_data, &s); -} - - -static njs_ret_t -njs_external_property_delete(njs_vm_t *vm, njs_value_t *value, - njs_value_t *unused, njs_value_t *unused2) -{ - void *obj; - njs_property_query_t *pq; - - pq = (njs_property_query_t *) vm->stash; - - obj = njs_extern_index(vm, pq->ext_index); - - return pq->ext_proto->find(vm, obj, pq->ext_data, 1); -} - - -njs_ret_t -njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq) -{ - nxt_int_t ret; - njs_function_t *function; - njs_object_prop_t *prop, *shared, *name; - nxt_lvlhsh_query_t lhq; - - static const njs_value_t name_string = njs_string("name"); - - prop = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_object_prop_t)); - if (nxt_slow_path(prop == NULL)) { - njs_memory_error(vm); - return NXT_ERROR; - } - - shared = pq->lhq.value; - *prop = *shared; - - pq->lhq.replace = 0; - pq->lhq.value = prop; - pq->lhq.pool = vm->mem_pool; - - ret = nxt_lvlhsh_insert(&pq->prototype->hash, &pq->lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } - - if (!njs_is_function(&prop->value)) { - return NXT_OK; - } - - function = njs_function_value_copy(vm, &prop->value); - if (nxt_slow_path(function == NULL)) { - return NXT_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 (nxt_slow_path(name == NULL)) { - return NXT_ERROR; - } - - name->configurable = 1; - - lhq.key_hash = NJS_NAME_HASH; - lhq.key = nxt_string_value("name"); - lhq.replace = 0; - lhq.value = name; - lhq.proto = &njs_object_hash_proto; - lhq.pool = vm->mem_pool; - - ret = nxt_lvlhsh_insert(&function->object.hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } - - return NXT_OK; -} - - njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -902,7 +313,7 @@ njs_object_keys(njs_vm_t *vm, njs_value_ static njs_ret_t njs_object_values(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) - { +{ njs_array_t *array; const njs_value_t *value; @@ -931,7 +342,7 @@ njs_object_values(njs_vm_t *vm, njs_valu static njs_ret_t njs_object_entries(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) - { +{ njs_array_t *array; const njs_value_t *value; @@ -1800,385 +1211,6 @@ njs_object_define_properties(njs_vm_t *v } -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 *prop, *pr; - nxt_lvlhsh_query_t pq; - - prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, - NJS_ATTRIBUTE_UNSET); - if (nxt_slow_path(prop == NULL)) { - return NULL; - } - - pq.key = nxt_string_value("value"); - pq.key_hash = NJS_VALUE_HASH; - - pr = njs_object_property(vm, descriptor, &pq); - if (pr != NULL) { - prop->value = pr->value; - } - - pq.key = nxt_string_value("writable"); - pq.key_hash = NJS_WRITABABLE_HASH; - - pr = njs_object_property(vm, descriptor, &pq); - if (pr != NULL) { - prop->writable = pr->value.data.truth; - } - - pq.key = nxt_string_value("enumerable"); - pq.key_hash = NJS_ENUMERABLE_HASH; - - pr = njs_object_property(vm, descriptor, &pq); - if (pr != NULL) { - prop->enumerable = pr->value.data.truth; - } - - pq.key = nxt_string_value("configurable"); - pq.key_hash = NJS_CONFIGURABLE_HASH; - - pr = njs_object_property(vm, descriptor, &pq); - if (pr != NULL) { - prop->configurable = pr->value.data.truth; - } - - return prop; -} - - -/* - * 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). - */ -static njs_ret_t -njs_define_property(njs_vm_t *vm, njs_value_t *object, const njs_value_t *name, - const njs_object_t *descriptor) -{ - nxt_int_t ret; - njs_object_prop_t *desc, *current; - njs_property_query_t pq; - - njs_string_get(name, &pq.lhq.key); - pq.lhq.key_hash = nxt_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 != NXT_OK && ret != NXT_DECLINED) { - return ret; - } - - desc = njs_descriptor_prop(vm, name, descriptor); - if (nxt_slow_path(desc == NULL)) { - return NXT_ERROR; - } - - if (nxt_fast_path(ret == NXT_DECLINED)) { - - if (!njs_is_valid(&desc->value)) { - desc->value = njs_value_undefined; - } - - if (desc->writable == NJS_ATTRIBUTE_UNSET) { - desc->writable = 0; - } - - if (desc->enumerable == NJS_ATTRIBUTE_UNSET) { - desc->enumerable = 0; - } - - if (desc->configurable == NJS_ATTRIBUTE_UNSET) { - desc->configurable = 0; - } - - if (nxt_slow_path(pq.lhq.value != NULL)) { - current = pq.lhq.value; - - if (nxt_slow_path(current->type == NJS_WHITEOUT)) { - /* Previously deleted property. */ - *current = *desc; - } - - } else { - pq.lhq.value = desc; - pq.lhq.replace = 0; - pq.lhq.pool = vm->mem_pool; - - ret = nxt_lvlhsh_insert(&object->data.u.object->hash, &pq.lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } - } - - return NXT_OK; - } - - /* Updating existing prop. */ - - if (nxt_slow_path(pq.shared)) { - ret = njs_prop_private_copy(vm, &pq); - - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - } - - current = pq.lhq.value; - - switch (current->type) { - case NJS_PROPERTY: - case NJS_METHOD: - break; - - case NJS_PROPERTY_REF: - if (njs_is_valid(&desc->value)) { - *current->value.data.u.value = desc->value; - } else { - *current->value.data.u.value = njs_value_undefined; - } - - return NXT_OK; - - case NJS_PROPERTY_HANDLER: - if (current->writable && njs_is_valid(&desc->value)) { - ret = current->value.data.u.prop_handler(vm, object, &desc->value, - &vm->retval); - - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - } - - return NXT_OK; - - default: - njs_internal_error(vm, "unexpected property type \"%s\" " - "while defining property", - njs_prop_type_string(current->type)); - - return NXT_ERROR; - } - - if (!current->configurable) { - - if (njs_is_valid(&desc->value) - && current->writable == NJS_ATTRIBUTE_FALSE - && !njs_values_strict_equal(&desc->value, ¤t->value)) - { - goto exception; - } - - if (desc->writable == NJS_ATTRIBUTE_TRUE - && current->writable == NJS_ATTRIBUTE_FALSE) - { - goto exception; - } - - if (desc->enumerable != NJS_ATTRIBUTE_UNSET - && current->enumerable != desc->enumerable) - { - goto exception; - } - - if (desc->configurable == NJS_ATTRIBUTE_TRUE) { - goto exception; - } - } - - if (njs_is_valid(&desc->value)) { - current->value = desc->value; - } - - if (desc->writable != NJS_ATTRIBUTE_UNSET) { - current->writable = desc->writable; - } - - if (desc->enumerable != NJS_ATTRIBUTE_UNSET) { - current->enumerable = desc->enumerable; - } - - if (desc->configurable != NJS_ATTRIBUTE_UNSET) { - current->configurable = desc->configurable; - } - - return NXT_OK; - -exception: - - njs_type_error(vm, "Cannot redefine property: \"%V\"", &pq.lhq.key); - - return NXT_ERROR; -} - - -static const njs_value_t njs_object_value_string = njs_string("value"); -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"); - - -static njs_ret_t -njs_object_property_descriptor(njs_vm_t *vm, njs_value_t *dest, - const njs_value_t *value, const njs_value_t *property) -{ - nxt_int_t ret; - njs_object_t *descriptor; - njs_object_prop_t *pr, *prop; - const njs_value_t *setval; - nxt_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, (njs_value_t *) value, property); - - switch (ret) { - case NXT_OK: - break; - - case NXT_DECLINED: - *dest = njs_value_undefined; - return NXT_OK; - - case NJS_TRAP: - case NXT_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, (njs_value_t *) value, - NULL, &prop->value); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - - break; - - case NJS_METHOD: - if (pq.shared) { - ret = njs_prop_private_copy(vm, &pq); - - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - - prop = pq.lhq.value; - } - - break; - - default: - njs_type_error(vm, "unexpected property type: %s", - njs_prop_type_string(prop->type)); - return NXT_ERROR; - } - - descriptor = njs_object_alloc(vm); - if (nxt_slow_path(descriptor == NULL)) { - return NXT_ERROR; - } - - lhq.proto = &njs_object_hash_proto; - lhq.replace = 0; - lhq.pool = vm->mem_pool; - - lhq.key = nxt_string_value("value"); - lhq.key_hash = NJS_VALUE_HASH; - - pr = njs_object_prop_alloc(vm, &njs_object_value_string, &prop->value, 1); - if (nxt_slow_path(pr == NULL)) { - return NXT_ERROR; - } - - lhq.value = pr; - - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } - - lhq.key = nxt_string_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 (nxt_slow_path(pr == NULL)) { - return NXT_ERROR; - } - - lhq.value = pr; - - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } - - lhq.key = nxt_string_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 (nxt_slow_path(pr == NULL)) { - return NXT_ERROR; - } - - lhq.value = pr; - - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } - - lhq.key = nxt_string_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 (nxt_slow_path(pr == NULL)) { - return NXT_ERROR; From careygister at outlook.com Tue Jun 11 17:56:11 2019 From: careygister at outlook.com (Carey Gister) Date: Tue, 11 Jun 2019 17:56:11 +0000 Subject: ngx_module_order directive In-Reply-To: <20190610125523.GU1877@mdounin.ru> References: , <20190610125523.GU1877@mdounin.ru> Message-ID: Hi Maxim, Thanks for your reply. I tried with and without quotes. The same result. My module is inserted in front of the copy filter module. I am writing a drop in replacement for the slice module. I want my module to be in front of the stream module. I build without specifying --with-http_slice_module. Here is my config file: config ngx_module_type=HTTP_AUX_FILTER ngx_module_name=ngx_http_my_new_slice_filter_module ngx_module_srcs="$ngx_addon_dir/ngx_http_my_new_slice_filter_module.c" ngx_module_order="$ngx_module_name ngx_stream_module" . auto/module ngx_addon_name=$ngx_module_name I've tried both HTTP_AUX_FILTER and HTTP_FILTER as ngx_module_type. Thoughts? Carey Gister 415-310-5304 ________________________________ From: nginx-devel on behalf of Maxim Dounin Sent: Monday, June 10, 2019 05:55 To: nginx-devel at nginx.org Subject: Re: ngx_module_order directive Hello! On Sat, Jun 08, 2019 at 12:44:29AM +0000, Carey Gister wrote: > I'm writing a new module and I want to place in a specific order in the module list as defined in ngx_modules.c. > > If my module name is x_module and I want it to run after ngx_http_slice_filter_module I tried: > > ngx_module_order=x_module ngx_http_slice_filter_module > > and I am informed during configuration that 'ngx_http_slice_filter_module does not exist. > > What is the correct syntax for this directive? The config file is a shell script, and expected to follow POSIX shell syntax. That is, to define a variable with a space in it you have to use double quotes: ngx_module_order="x_module ngx_http_slice_filter_module" Note well that it is generally a bad idea to explicitly define module order unless you know what are you doing and why. -- Maxim Dounin http://mdounin.ru/ _______________________________________________ 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 Okaya at kernel.org Wed Jun 12 03:24:21 2019 From: Okaya at kernel.org (Sinan Kaya) Date: Tue, 11 Jun 2019 23:24:21 -0400 Subject: RFC for Compiling Nginx as a Library In-Reply-To: References: Message-ID: <4ad3ddf0-992f-f5bd-6b6b-0ff897f9bb3a@kernel.org> On 6/3/2019 12:04 PM, Sinan Kaya wrote: > Hi, > > I have been using Nginx as a static library to embed into my application > for some time. > I'm interested in upstreaming the patches. > > I wanted to ask if there would be any interest in merging this feature. > > Sinan I couldn't locate Maxim Dounin email but let me reply here with issues that we have seen during testing. There are two issues that we hit so far. The first issue is about wait(-1) in nginx code. It prevents nginx modules to use fork() API directly to do some external work. I was wondering if we could replace wait(-1) with an actual list of worker process PIDs. The second issue that we hit is about timer_create(). Again, we are unable to call timer_create() in our nginx module. Would it be possible to relieve some of the nginx API enforcement. I understand the desire to use nginx API in general but if someone is porting an exiting code to nginx, they will most probably use POSIX API for existing code. From mdounin at mdounin.ru Wed Jun 12 14:42:24 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 12 Jun 2019 17:42:24 +0300 Subject: ngx_module_order directive In-Reply-To: References: <20190610125523.GU1877@mdounin.ru> Message-ID: <20190612144224.GY1877@mdounin.ru> Hello! On Tue, Jun 11, 2019 at 05:56:11PM +0000, Carey Gister wrote: > I tried with and without quotes. The same result. My module is inserted in front of the copy filter module. I am writing a drop in replacement for the slice module. I want my module to be in front of the stream module. > I build without specifying --with-http_slice_module. Obviously enough, if you don't have the slice module compiled in, trying to use module order relative to it won't work - because there is no slice module. You have to configure order related to other modules as well. Another problem is that ngx_module_order is only used for dynamic loading. If you are trying to build a static module, ngx_module_order won't work for you. And since the slice module is a low-level module specifically positioned in the filter chain, there is no equivalent module type. -- Maxim Dounin http://mdounin.ru/ From Okaya at kernel.org Fri Jun 14 01:08:56 2019 From: Okaya at kernel.org (Sinan Kaya) Date: Thu, 13 Jun 2019 21:08:56 -0400 Subject: RFC on C Library Safety in Nginx Module Callback Message-ID: <32a3de11-61ee-72c0-76da-f72693b33a47@kernel.org> I wanted to hear opinions on this surprising observation while developing an nginx module. We hit this issue while developing an nginx module. During nginx module's startup process, it starts up nginx but also does a lot of other work, some of which involves using glibc's implementation of timer_create, a posix function. https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/timer_create.c.html https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/timer_routines.c.html#__active_timer_sigev_thread_lock Looking at the glibc source code for timer_create, we can see it has a global mutex named __active_timer_sigev_thread_lock. If nginx happens to call fork() while the rest of the nginx module code is calling timer_create, the fork() will make a copy of global memory which includes the global mutex as being owned by some other thread. In the newly-forked process, that thread will not exist, and the mutex will always be owned by a non-existent thread. I'm pasting in a GDB trace showing this below the rest of my explanatory text. This thread is blocked on timer_create. It is trying to enter a pthread_mutex_t which is a global named __active_timer_sigev_thread_lock. (gdb) bt #0 0x0000ff02aab1634c in __lll_lock_wait ( futex=futex at entry=0xff02aaaee2c8 <__active_timer_sigev_thread_lock>, private=0) at /usr/src/debug/glibc/2.27-r0/git/nptl/lowlevellock.c:46 #1 0x0000ff02aab0f648 in __GI___pthread_mutex_lock ( mutex=mutex at entry=0xff02aaaee2c8 <__active_timer_sigev_thread_lock>) at /usr/src/debug/glibc/2.27-r0/git/nptl/pthread_mutex_lock.c:78 #2 0x0000ff02aaadbb20 in timer_create (clock_id=, evp=0xff02a9e181a8, timerid=0xff02a41e43a0) at /usr/src/debug/glibc/2.27-r0/git/sysdeps/unix/sysv/linux/timer_create.c:159 ... #16 0x0000000000695db0 in ngx_thread_pool_cycle (data=0xff02a0027700) at /usr/src/debug/nginx-staticdev/1.14.2-r0/nginx-1.14.2/src/core/ngx_thread_pool.c:342 #17 0x0000ff02aab0cf78 in start_thread (arg=0xff02a8e160d6) at /usr/src/debug/glibc/2.27-r0/git/nptl/pthread_create.c:463 #18 0x0000ff02aa2efe2c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78 By looking at this link below, almost majority of the C library functions are unsafe when called inside the nginx callback. One way to work around the issue is use using exec() functions so that each child process gets a fresh copy of the parent rather than getting a copy. https://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them "Library functions Problem with mutexes and critical code sections implies another non-obvious issue. It's theoretically possible to write your code executed in threads so that you are sure it's safe to call fork when such threads run but in practice there is one big problem: library functions. You're never sure if a library function you are using doesn't use global data. Even if it is thread safe, it may be achieved using mutexes internally. You are never sure. Even system library functions that are thread-safe may use locks internally." From ranier.vf at gmail.com Fri Jun 14 12:51:02 2019 From: ranier.vf at gmail.com (Ranier Vf) Date: Fri, 14 Jun 2019 09:51:02 -0300 Subject: RFC on C Library Safety in Nginx Module Callback In-Reply-To: <32a3de11-61ee-72c0-76da-f72693b33a47@kernel.org> References: <32a3de11-61ee-72c0-76da-f72693b33a47@kernel.org> Message-ID: Hi, Maybe this help. http://www.doublersolutions.com/docs/dce/osfdocs/htmls/develop/appdev/Appde193.htm "One solution to the problem of calling *fork( )* in a multithreaded environment exists. (Note that this method will not work for server application code or any other application code that is invoked by a callback from a library.) Before an application performs a *fork( )* followed by something other than *exec( )*, it must cancel all of the other threads. After it joins the canceled threads, it can safely *fork( )* because it is the only thread in existence. This means that libraries that create threads must establish cancel handlers that propagate the cancel to the created threads and join them. The application should save enough state so that the threads can be recreated and restarted after the *fork( )* processing completes. " Best regards, Ranier Vilela Em qui, 13 de jun de 2019 ?s 22:09, Sinan Kaya escreveu: > I wanted to hear opinions on this surprising observation while > developing an nginx module. > > We hit this issue while developing an nginx module. During nginx > module's startup process, it starts up nginx but also does a lot of > other work, some of which involves using glibc's implementation of > timer_create, a posix function. > > > https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/timer_create.c.html > > https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/timer_routines.c.html#__active_timer_sigev_thread_lock > > > Looking at the glibc source code for timer_create, we can see it has a > global mutex named __active_timer_sigev_thread_lock. If nginx happens > to call fork() while the rest of the nginx module code is calling > timer_create, the fork() will make a copy of global memory which > includes the global mutex as being owned by some other thread. In the > newly-forked process, that thread will not exist, and the mutex will > always be owned by a non-existent thread. I'm pasting in a GDB trace > showing this below the rest of my explanatory text. > > > This thread is blocked on timer_create. It is trying to enter a > pthread_mutex_t which is a global named __active_timer_sigev_thread_lock. > > (gdb) bt > > #0 0x0000ff02aab1634c in __lll_lock_wait ( > futex=futex at entry=0xff02aaaee2c8 <__active_timer_sigev_thread_lock>, > private=0) at /usr/src/debug/glibc/2.27-r0/git/nptl/lowlevellock.c:46 > > #1 0x0000ff02aab0f648 in __GI___pthread_mutex_lock ( > mutex=mutex at entry=0xff02aaaee2c8 <__active_timer_sigev_thread_lock>) > at /usr/src/debug/glibc/2.27-r0/git/nptl/pthread_mutex_lock.c:78 > > #2 0x0000ff02aaadbb20 in timer_create (clock_id=, > evp=0xff02a9e181a8, timerid=0xff02a41e43a0) > at > /usr/src/debug/glibc/2.27-r0/git/sysdeps/unix/sysv/linux/timer_create.c:159 > > ... > > #16 0x0000000000695db0 in ngx_thread_pool_cycle (data=0xff02a0027700) > at > > /usr/src/debug/nginx-staticdev/1.14.2-r0/nginx-1.14.2/src/core/ngx_thread_pool.c:342 > #17 0x0000ff02aab0cf78 in start_thread (arg=0xff02a8e160d6) > at /usr/src/debug/glibc/2.27-r0/git/nptl/pthread_create.c:463 > > #18 0x0000ff02aa2efe2c in thread_start () > at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78 > > > By looking at this link below, almost majority of the C library > functions are unsafe when called inside the nginx callback. > > One way to work around the issue is use using exec() functions so that > each child process gets a fresh copy of the parent rather than getting > a copy. > > > https://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them > > "Library functions > > Problem with mutexes and critical code sections implies another > non-obvious issue. It's theoretically possible to write your code > executed in threads so that you are sure it's safe to call fork when > such threads run but in practice there is one big problem: library > functions. You're never sure if a library function you are using doesn't > use global data. Even if it is thread safe, it may be achieved using > mutexes internally. You are never sure. Even system library functions > that are thread-safe may use locks internally." > _______________________________________________ > 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 xeioex at nginx.com Fri Jun 14 18:20:50 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 14 Jun 2019 18:20:50 +0000 Subject: [njs] Improved njs_object_own_enumerate(). Message-ID: details: https://hg.nginx.org/njs/rev/fb9621798309 branches: changeset: 1005:fb9621798309 user: Dmitry Volyntsev date: Fri Jun 14 21:19:52 2019 +0300 description: Improved njs_object_own_enumerate(). Enumerating enumerable shared_hash entries even if all is false. diffstat: njs/njs_builtin.c | 2 + njs/njs_json.c | 11 ++++- njs/njs_object.c | 88 ++++++++++++++++++++++------------------------- njs/test/njs_unit_test.c | 3 + 4 files changed, 55 insertions(+), 49 deletions(-) diffs (160 lines): diff -r 028277f5c551 -r fb9621798309 njs/njs_builtin.c --- a/njs/njs_builtin.c Tue Jun 11 17:34:59 2019 +0300 +++ b/njs/njs_builtin.c Fri Jun 14 21:19:52 2019 +0300 @@ -1081,6 +1081,8 @@ static const njs_object_prop_t njs_njs_ .type = NJS_PROPERTY, .name = njs_string("version"), .value = njs_string(NJS_VERSION), + .configurable = 1, + .enumerable = 1, }, { diff -r 028277f5c551 -r fb9621798309 njs/njs_json.c --- a/njs/njs_json.c Tue Jun 11 17:34:59 2019 +0300 +++ b/njs/njs_json.c Fri Jun 14 21:19:52 2019 +0300 @@ -2354,6 +2354,7 @@ njs_vm_value_dump(njs_vm_t *vm, nxt_str_ njs_ret_t ret; nxt_str_t str; njs_value_t *key, *val, ext_val; + njs_object_t *object; njs_json_state_t *state; njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; @@ -2446,11 +2447,15 @@ njs_vm_value_dump(njs_vm_t *vm, nxt_str_ val = &ext_val; } else { + object = state->value.data.u.object; lhq.proto = &njs_object_hash_proto; - ret = nxt_lvlhsh_find(&state->value.data.u.object->hash, &lhq); - if (nxt_slow_path(ret == NXT_DECLINED)) { - break; + ret = nxt_lvlhsh_find(&object->hash, &lhq); + if (ret == NXT_DECLINED) { + ret = nxt_lvlhsh_find(&object->shared_hash, &lhq); + if (nxt_slow_path(ret == NXT_DECLINED)) { + break; + } } prop = lhq.value; diff -r 028277f5c551 -r fb9621798309 njs/njs_object.c --- a/njs/njs_object.c Tue Jun 11 17:34:59 2019 +0300 +++ b/njs/njs_object.c Fri Jun 14 21:19:52 2019 +0300 @@ -667,29 +667,27 @@ njs_object_own_enumerate_object_length(c } } - if (nxt_slow_path(all)) { - nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &object->shared_hash; - - for ( ;; ) { - prop = nxt_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { - break; - } - - lhq.key_hash = lhe.key_hash; - njs_string_get(&prop->name, &lhq.key); - - lhq.proto = &njs_object_hash_proto; - ret = nxt_lvlhsh_find(&object->hash, &lhq); - - if (ret != NXT_OK) { - ext_prop = njs_object_exist_in_proto(parent, object, &lhq); - - if (ext_prop == NULL) { - length++; - } + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + hash = &object->shared_hash; + + for ( ;; ) { + prop = nxt_lvlhsh_each(hash, &lhe); + + if (prop == NULL) { + break; + } + + lhq.key_hash = lhe.key_hash; + njs_string_get(&prop->name, &lhq.key); + + lhq.proto = &njs_object_hash_proto; + ret = nxt_lvlhsh_find(&object->hash, &lhq); + + if (ret != NXT_OK) { + ext_prop = njs_object_exist_in_proto(parent, object, &lhq); + + if (ext_prop == NULL && (prop->enumerable || all)) { + length++; } } } @@ -949,29 +947,27 @@ njs_object_own_enumerate_object(njs_vm_t } } - if (nxt_slow_path(all)) { - nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &object->shared_hash; - - for ( ;; ) { - prop = nxt_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { - break; - } - - lhq.key_hash = lhe.key_hash; - njs_string_get(&prop->name, &lhq.key); - - lhq.proto = &njs_object_hash_proto; - ret = nxt_lvlhsh_find(&object->hash, &lhq); - - if (ret != NXT_OK) { - ext_prop = njs_object_exist_in_proto(parent, object, &lhq); - - if (ext_prop == NULL) { - njs_string_copy(item++, &prop->name); - } + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + hash = &object->shared_hash; + + for ( ;; ) { + prop = nxt_lvlhsh_each(hash, &lhe); + + if (prop == NULL) { + break; + } + + lhq.key_hash = lhe.key_hash; + njs_string_get(&prop->name, &lhq.key); + + lhq.proto = &njs_object_hash_proto; + ret = nxt_lvlhsh_find(&object->hash, &lhq); + + if (ret != NXT_OK) { + ext_prop = njs_object_exist_in_proto(parent, object, &lhq); + + if (ext_prop == NULL && (prop->enumerable || all)) { + njs_string_copy(item++, &prop->name); } } } diff -r 028277f5c551 -r fb9621798309 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Jun 11 17:34:59 2019 +0300 +++ b/njs/test/njs_unit_test.c Fri Jun 14 21:19:52 2019 +0300 @@ -12278,6 +12278,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("njs.dump($r.header)"), nxt_string("{type:\"object\",props:[\"getter\",\"foreach\",\"next\"]}") }, + { nxt_string("njs.dump(njs) == `{version:'${njs.version}'}`"), + nxt_string("true") }, + /* Built-in methods name. */ { nxt_string( From xeioex at nginx.com Fri Jun 14 18:20:50 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 14 Jun 2019 18:20:50 +0000 Subject: [njs] Fixed njs_run expect tests. Message-ID: details: https://hg.nginx.org/njs/rev/c3a70f0f6cdc branches: changeset: 1006:c3a70f0f6cdc user: Dmitry Volyntsev date: Fri Jun 14 21:20:25 2019 +0300 description: Fixed njs_run expect tests. Using exec instead of spawn to get the njs output synchronously. diffstat: njs/njs_shell.c | 2 +- njs/test/njs_expect_test.exp | 35 +++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 17 deletions(-) diffs (97 lines): diff -r fb9621798309 -r c3a70f0f6cdc njs/njs_shell.c --- a/njs/njs_shell.c Fri Jun 14 21:19:52 2019 +0300 +++ b/njs/njs_shell.c Fri Jun 14 21:20:25 2019 +0300 @@ -327,7 +327,7 @@ njs_get_options(njs_opts_t *opts, int ar switch (*p) { case '?': case 'h': - (void) write(STDIN_FILENO, help, nxt_length(help)); + (void) write(STDOUT_FILENO, help, nxt_length(help)); return ret; case 'c': diff -r fb9621798309 -r c3a70f0f6cdc njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Fri Jun 14 21:19:52 2019 +0300 +++ b/njs/test/njs_expect_test.exp Fri Jun 14 21:20:25 2019 +0300 @@ -42,9 +42,11 @@ type console.help() for more information expect eof } -proc njs_run {opts output} { - eval spawn -nottycopy njs $opts - expect -re $output +proc njs_run {opts expected_re} { + catch {exec njs {*}$opts} out + if {[regexp $expected_re $out match] == 0} { + return -code error "njs_run: unexpected output '$out' vs '$expected_re'" + } } njs_test { @@ -625,35 +627,36 @@ njs_test { # Modules -njs_run "-p njs/test/module/libs ./njs/test/module/normal.js" \ +njs_run {"-p" "njs/test/module/libs" "./njs/test/module/normal.js"} \ "passed!" -njs_run "-p njs/test/module/libs/ ./njs/test/module/normal.js" \ +njs_run {"-p" "njs/test/module/libs/" "./njs/test/module/normal.js"} \ "passed!" -njs_run "-p njs/test/module -p njs/test/module/libs ./njs/test/module/normal.js" \ +njs_run {"-p" "njs/test/module" "-p" "njs/test/module/libs" "./njs/test/module/normal.js"} \ "passed!" -njs_run "./njs/test/module/normal.js" \ +njs_run {"./njs/test/module/normal.js"} \ "SyntaxError: Cannot find module \"hash.js\" in sub2.js:5" -njs_run "-p njs/test/module/libs ./njs/test/module/exception.js" \ - "at error \\(sub1.js:5\\)\r\n at exception \\(lib3.js:5\\)" +njs_run {"-p" "njs/test/module/libs" "./njs/test/module/exception.js"} \ + "at error \\(sub1.js:5\\)" -njs_run "-p njs/test/module ./njs/test/module/recursive.js" \ +njs_run {"-p" "njs/test/module" "./njs/test/module/recursive.js"} \ "SyntaxError: Cannot import itself \"./recursive.js\" in recursive.js:3" # CLI OPTIONS # help -njs_run "-h" "Interactive njs shell.\r\n\r\nOptions:" +njs_run {"-h"} "Options" # command -njs_run "-c 'console.log(\"a b c\")'" "a b c" +njs_run {"-c" "console.log(\"a b c\")"} "a b c" -njs_run "-c 'console.log('" "SyntaxError: Unexpected token \"\" in string:1" +njs_run {"-c" "console.log("} "SyntaxError: Unexpected end of input in string:1" + # disassemble @@ -720,10 +723,10 @@ njs_test { "12\r\n"} } "-p njs/test/module/" -njs_run "-q ./njs/test/module/normal.js" \ +njs_run {"-q" "./njs/test/module/normal.js"} \ "SyntaxError: Cannot find module \"hash.js\" in 5" -njs_run "-p njs/test/module/libs/ -d ./njs/test/module/normal.js" \ +njs_run {"-p" "njs/test/module/libs/" "-d" "./njs/test/module/normal.js"} \ "passed!" # sandboxing @@ -756,5 +759,5 @@ njs_test { # version -njs_run "-v" "\\d+\.\\d+\.\\d+" +njs_run {"-v"} "\\d+\.\\d+\.\\d+" From Okaya at kernel.org Fri Jun 14 18:35:28 2019 From: Okaya at kernel.org (Sinan Kaya) Date: Fri, 14 Jun 2019 14:35:28 -0400 Subject: RFC on C Library Safety in Nginx Module Callback In-Reply-To: References: <32a3de11-61ee-72c0-76da-f72693b33a47@kernel.org> Message-ID: <5c28d803-f923-d38e-9e05-dcd23feb0bc3@kernel.org> On 6/14/2019 8:51 AM, Ranier Vf wrote: > Maybe this help. > http://www.doublersolutions.com/docs/dce/osfdocs/htmls/develop/appdev/Appde193.htm > > "One solution to the problem of calling *fork( )* in a multithreaded > environment exists. (Note that this method will not work for server > application code or any other application code that is invoked by a > callback from a library.) Before an application performs a *fork( )* > followed by something other than *exec( )*, it must cancel all of the > other threads. After it joins the canceled threads, it can safely *fork( > )* because it is the only thread in existence. This means that libraries > that create threads must establish cancel handlers that propagate the > cancel to the created threads and join them. The application should save > enough state so that the threads can be recreated and restarted after > the *fork( )* processing completes. " Yes, this helps. As long as nginx has been designed to honor these rules, we can make our application do the same thing. From mdounin at mdounin.ru Mon Jun 17 13:07:20 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 17 Jun 2019 16:07:20 +0300 Subject: RFC on C Library Safety in Nginx Module Callback In-Reply-To: <32a3de11-61ee-72c0-76da-f72693b33a47@kernel.org> References: <32a3de11-61ee-72c0-76da-f72693b33a47@kernel.org> Message-ID: <20190617130719.GB1877@mdounin.ru> Hello! On Thu, Jun 13, 2019 at 09:08:56PM -0400, Sinan Kaya wrote: > I wanted to hear opinions on this surprising observation while > developing an nginx module. > > We hit this issue while developing an nginx module. During nginx > module's startup process, it starts up nginx but also does a lot of > other work, some of which involves using glibc's implementation of > timer_create, a posix function. > > https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/timer_create.c.html > https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/timer_routines.c.html#__active_timer_sigev_thread_lock > > > Looking at the glibc source code for timer_create, we can see it has a > global mutex named __active_timer_sigev_thread_lock. If nginx happens > to call fork() while the rest of the nginx module code is calling > timer_create, the fork() will make a copy of global memory which > includes the global mutex as being owned by some other thread. In the > newly-forked process, that thread will not exist, and the mutex will > always be owned by a non-existent thread. I'm pasting in a GDB trace > showing this below the rest of my explanatory text. [...] > By looking at this link below, almost majority of the C library > functions are unsafe when called inside the nginx callback. Almost all C library functions are safe when called inside nginx callbacks. The only (or at least most obvious) exceptions are creating threads (you shouldn't, this is highly likely to cause problems described in your message) and processes (you'll end up confusing nginx process management code). As long as you don't create your own threads, everything is expected to be fine. If you don't create your own threads but still see the deadlock as shown in your trace - please provide more details. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon Jun 17 18:38:52 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 17 Jun 2019 18:38:52 +0000 Subject: [nginx] Perl: disabled not_modified filter (ticket #1786). Message-ID: details: https://hg.nginx.org/nginx/rev/36c52a0f6ded branches: changeset: 7516:36c52a0f6ded user: Maxim Dounin date: Mon Jun 17 19:48:56 2019 +0300 description: Perl: disabled not_modified filter (ticket #1786). Embedded perl does not set any request fields needed for conditional requests processing. Further, filter finalization in the not_modified filter can cause segmentation faults due to cleared ctx as in ticket #1786. Before 5fb1e57c758a (1.7.3) the not_modified filter was implicitly disabled for perl responses, as r->headers_out.last_modified_time was -1. This change restores this behaviour by using the explicit r->disable_not_modified flag. Note that this patch doesn't try to address perl module robustness against filter finalization and other errors returned from filter chains. It should be eventually reworked to handle errors instead of ignoring them. diffstat: src/http/modules/perl/nginx.xs | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -147,6 +147,8 @@ send_http_header(r, ...) } } + r->disable_not_modified = 1; + (void) ngx_http_send_header(r); From xeioex at nginx.com Tue Jun 18 14:57:57 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jun 2019 14:57:57 +0000 Subject: [njs] Fixed uninitialized field in njs_vm_value_dump(). Message-ID: details: https://hg.nginx.org/njs/rev/2cb51aab7e78 branches: changeset: 1007:2cb51aab7e78 user: Dmitry Volyntsev date: Tue Jun 18 17:57:22 2019 +0300 description: Fixed uninitialized field in njs_vm_value_dump(). MemorySanitizer: use-of-uninitialized-value in njs_json_push_stringify_state(). diffstat: njs/njs_json.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r c3a70f0f6cdc -r 2cb51aab7e78 njs/njs_json.c --- a/njs/njs_json.c Fri Jun 14 21:20:25 2019 +0300 +++ b/njs/njs_json.c Tue Jun 18 17:57:22 2019 +0300 @@ -2375,6 +2375,7 @@ njs_vm_value_dump(njs_vm_t *vm, nxt_str_ stringify->nodes = NULL; stringify->last = NULL; stringify->stack.items = 0; + stringify->replacer = njs_value_undefined; if (!njs_dump_is_object(value)) { ret = njs_dump_value(stringify, value, console); From xeioex at nginx.com Tue Jun 18 14:57:57 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jun 2019 14:57:57 +0000 Subject: [njs] Added process global object. Message-ID: details: https://hg.nginx.org/njs/rev/e18ee27ce760 branches: changeset: 1008:e18ee27ce760 user: Dmitry Volyntsev date: Tue Jun 18 17:57:38 2019 +0300 description: Added process global object. process object properties: argv - an array containing the command line arguments env - an object containing the user environment pid - process PID ppid - process parent PID This closes #84 issue on Github. diffstat: nginx/ngx_http_js_module.c | 2 + nginx/ngx_stream_js_module.c | 2 + njs/njs.h | 3 + njs/njs_builtin.c | 274 +++++++++++++++++++++++++++++++++++++++--- njs/njs_generator.c | 1 + njs/njs_lexer.h | 1 + njs/njs_lexer_keyword.c | 1 + njs/njs_object_hash.h | 15 ++ njs/njs_parser_terminal.c | 1 + njs/njs_shell.c | 2 + njs/njs_vm.h | 2 + njs/test/njs_expect_test.exp | 14 ++ 12 files changed, 298 insertions(+), 20 deletions(-) diffs (497 lines): diff -r 2cb51aab7e78 -r e18ee27ce760 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Jun 18 17:57:22 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Jun 18 17:57:38 2019 +0300 @@ -2283,6 +2283,8 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ options.backtrace = 1; options.ops = &ngx_http_js_ops; + options.argv = ngx_argv; + options.argc = ngx_argc; file = value[1]; options.file.start = file.data; diff -r 2cb51aab7e78 -r e18ee27ce760 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Tue Jun 18 17:57:22 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Tue Jun 18 17:57:38 2019 +0300 @@ -1473,6 +1473,8 @@ ngx_stream_js_include(ngx_conf_t *cf, ng options.backtrace = 1; options.ops = &ngx_stream_js_ops; + options.argv = ngx_argv; + options.argc = ngx_argc; file = value[1]; options.file.start = file.data; diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs.h --- a/njs/njs.h Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs.h Tue Jun 18 17:57:38 2019 +0300 @@ -143,6 +143,9 @@ typedef struct { njs_vm_ops_t *ops; nxt_str_t file; + char **argv; + nxt_uint_t argc; + uint8_t trailer; /* 1 bit */ uint8_t init; /* 1 bit */ uint8_t accumulative; /* 1 bit */ diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_builtin.c --- a/njs/njs_builtin.c Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_builtin.c Tue Jun 18 17:57:38 2019 +0300 @@ -28,17 +28,21 @@ static njs_ret_t njs_prototype_function( static nxt_array_t *njs_vm_expression_completions(njs_vm_t *vm, nxt_str_t *expression); static nxt_array_t *njs_object_completions(njs_vm_t *vm, njs_object_t *object); +static nxt_int_t njs_env_hash_init(njs_vm_t *vm, nxt_lvlhsh_t *hash, + char **environment); +const njs_object_init_t njs_global_this_init; const njs_object_init_t njs_njs_object_init; -const njs_object_init_t njs_global_this_init; +const njs_object_init_t njs_process_object_init; const njs_object_init_t *njs_object_init[] = { - &njs_global_this_init, /* global this */ - &njs_njs_object_init, /* global njs object */ - &njs_math_object_init, /* Math */ - &njs_json_object_init, /* JSON */ + &njs_global_this_init, + &njs_njs_object_init, + &njs_process_object_init, + &njs_math_object_init, + &njs_json_object_init, NULL }; @@ -214,6 +218,9 @@ const njs_object_prototype_t njs_protot }; +extern char **environ; + + nxt_inline nxt_int_t njs_object_hash_init(njs_vm_t *vm, nxt_lvlhsh_t *hash, const njs_object_init_t *init) @@ -229,8 +236,8 @@ njs_builtin_objects_create(njs_vm_t *vm) njs_module_t *module; njs_object_t *object, *string_object; njs_function_t *func; + njs_vm_shared_t *shared; nxt_lvlhsh_query_t lhq; - njs_vm_shared_t *shared; njs_object_prototype_t *prototype; const njs_object_init_t *obj, **p; const njs_function_init_t *f; @@ -285,6 +292,11 @@ njs_builtin_objects_create(njs_vm_t *vm) object++; } + ret = njs_env_hash_init(vm, &shared->env_hash, environ); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + lhq.replace = 0; lhq.pool = vm->mem_pool; @@ -1075,6 +1087,35 @@ njs_dump_value(njs_vm_t *vm, njs_value_t } +static const njs_object_prop_t njs_global_this_object_properties[] = +{ + { + .type = NJS_PROPERTY, + .name = njs_string("NaN"), + .value = njs_value(NJS_NUMBER, 0, NAN), + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("Infinity"), + .value = njs_value(NJS_NUMBER, 0, INFINITY), + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("undefined"), + .value = njs_value(NJS_UNDEFINED, 0, NAN), + }, +}; + + +const njs_object_init_t njs_global_this_init = { + nxt_string("this"), + njs_global_this_object_properties, + nxt_nitems(njs_global_this_object_properties) +}; + + static const njs_object_prop_t njs_njs_object_properties[] = { { @@ -1102,30 +1143,223 @@ const njs_object_init_t njs_njs_object_ }; -static const njs_object_prop_t njs_global_this_object_properties[] = +static njs_ret_t +njs_process_object_argv(njs_vm_t *vm, njs_value_t *process, + njs_value_t *unused, njs_value_t *retval) +{ + char **arg; + nxt_int_t ret; + nxt_uint_t i; + njs_array_t *argv; + njs_object_prop_t *prop; + nxt_lvlhsh_query_t lhq; + + static const njs_value_t argv_string = njs_string("argv"); + + if (nxt_slow_path(vm->options.argv == NULL)) { + njs_internal_error(vm, "argv was not provided by host environment"); + return NXT_ERROR; + } + + argv = njs_array_alloc(vm, vm->options.argc, 0); + if (nxt_slow_path(argv == NULL)) { + return NXT_ERROR; + } + + i = 0; + + for (arg = vm->options.argv; i < vm->options.argc; arg++) { + njs_string_set(vm, &argv->start[i++], (u_char *) *arg, + nxt_strlen(*arg)); + } + + prop = njs_object_prop_alloc(vm, &argv_string, &njs_value_undefined, 1); + if (nxt_slow_path(prop == NULL)) { + return NJS_ERROR; + } + + prop->value.data.u.array = argv; + prop->value.type = NJS_ARRAY; + prop->value.data.truth = 1; + + lhq.value = prop; + lhq.key_hash = NJS_ARGV_HASH; + lhq.key = nxt_string_value("argv"); + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + ret = nxt_lvlhsh_insert(&process->data.u.object->hash, &lhq); + + if (nxt_fast_path(ret == NXT_OK)) { + *retval = prop->value; + return NXT_OK; + } + + njs_internal_error(vm, "lvlhsh insert failed"); + + return NXT_ERROR; +} + + +static nxt_int_t +njs_env_hash_init(njs_vm_t *vm, nxt_lvlhsh_t *hash, char **environment) +{ + char **ep; + u_char *val, *entry; + nxt_int_t ret; + njs_object_prop_t *prop; + nxt_lvlhsh_query_t lhq; + + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + ep = environment; + + while (*ep != NULL) { + prop = njs_object_prop_alloc(vm, &njs_value_undefined, + &njs_value_undefined, 1); + if (nxt_slow_path(prop == NULL)) { + return NXT_ERROR; + } + + entry = (u_char *) *ep++; + + val = nxt_strchr(entry, '='); + if (nxt_slow_path(val == NULL)) { + continue; + } + + ret = njs_string_set(vm, &prop->name, entry, val - entry); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + val++; + + ret = njs_string_set(vm, &prop->value, val, nxt_strlen(val)); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + lhq.value = prop; + njs_string_get(&prop->name, &lhq.key); + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + + ret = nxt_lvlhsh_insert(hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + } + + return NXT_OK; +} + + +static njs_ret_t +njs_process_object_env(njs_vm_t *vm, njs_value_t *process, + njs_value_t *unused, njs_value_t *retval) +{ + nxt_int_t ret; + njs_object_t *env; + njs_object_prop_t *prop; + nxt_lvlhsh_query_t lhq; + + static const njs_value_t env_string = njs_string("env"); + + env = njs_object_alloc(vm); + if (nxt_slow_path(env == NULL)) { + return NXT_ERROR; + } + + env->shared_hash = vm->shared->env_hash; + + prop = njs_object_prop_alloc(vm, &env_string, &njs_value_undefined, 1); + if (nxt_slow_path(prop == NULL)) { + return NXT_ERROR; + } + + prop->value.data.u.object = env; + prop->value.type = NJS_OBJECT; + prop->value.data.truth = 1; + + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + lhq.value = prop; + lhq.key = nxt_string_value("env"); + lhq.key_hash = NJS_ENV_HASH; + + ret = nxt_lvlhsh_insert(&process->data.u.object->hash, &lhq); + + if (nxt_fast_path(ret == NXT_OK)) { + *retval = prop->value; + return NXT_OK; + } + + njs_internal_error(vm, "lvlhsh insert failed"); + + return NXT_ERROR; +} + + +static njs_ret_t +njs_process_object_pid(njs_vm_t *vm, njs_value_t *unused, + njs_value_t *unused2, njs_value_t *retval) +{ + retval->data.u.number = getpid(); + retval->type = NJS_NUMBER; + retval->data.truth = njs_is_number_true(retval->data.u.number); + + return NJS_OK; +} + + +static njs_ret_t +njs_process_object_ppid(njs_vm_t *vm, njs_value_t *unused, + njs_value_t *unused2, njs_value_t *retval) +{ + retval->data.u.number = getppid(); + retval->type = NJS_NUMBER; + retval->data.truth = njs_is_number_true(retval->data.u.number); + + return NJS_OK; +} + + +static const njs_object_prop_t njs_process_object_properties[] = { { - .type = NJS_PROPERTY, - .name = njs_string("NaN"), - .value = njs_value(NJS_NUMBER, 0, NAN), + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("argv"), + .value = njs_prop_handler(njs_process_object_argv), }, { - .type = NJS_PROPERTY, - .name = njs_string("Infinity"), - .value = njs_value(NJS_NUMBER, 0, INFINITY), + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("env"), + .value = njs_prop_handler(njs_process_object_env), + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("pid"), + .value = njs_prop_handler(njs_process_object_pid), }, { - .type = NJS_PROPERTY, - .name = njs_string("undefined"), - .value = njs_value(NJS_UNDEFINED, 0, NAN), + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("ppid"), + .value = njs_prop_handler(njs_process_object_ppid), }, + }; -const njs_object_init_t njs_global_this_init = { - nxt_string("this"), - njs_global_this_object_properties, - nxt_nitems(njs_global_this_object_properties) +const njs_object_init_t njs_process_object_init = { + nxt_string("process"), + njs_process_object_properties, + nxt_nitems(njs_process_object_properties), }; diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_generator.c --- a/njs/njs_generator.c Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_generator.c Tue Jun 18 17:57:38 2019 +0300 @@ -451,6 +451,7 @@ njs_generator(njs_vm_t *vm, njs_generato /* Fall through. */ case NJS_TOKEN_NJS: + case NJS_TOKEN_PROCESS: case NJS_TOKEN_MATH: case NJS_TOKEN_JSON: case NJS_TOKEN_EVAL: diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_lexer.h --- a/njs/njs_lexer.h Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_lexer.h Tue Jun 18 17:57:38 2019 +0300 @@ -171,6 +171,7 @@ typedef enum { NJS_TOKEN_GLOBAL_THIS, NJS_TOKEN_NJS, + NJS_TOKEN_PROCESS, NJS_TOKEN_MATH, NJS_TOKEN_JSON, diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_lexer_keyword.c Tue Jun 18 17:57:38 2019 +0300 @@ -55,6 +55,7 @@ static const njs_keyword_t njs_keywords { nxt_string("this"), NJS_TOKEN_THIS, 0 }, { nxt_string("arguments"), NJS_TOKEN_ARGUMENTS, 0 }, { nxt_string("njs"), NJS_TOKEN_NJS, 0 }, + { nxt_string("process"), NJS_TOKEN_PROCESS, 0 }, { nxt_string("Math"), NJS_TOKEN_MATH, 0 }, { nxt_string("JSON"), NJS_TOKEN_JSON, 0 }, diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_object_hash.h --- a/njs/njs_object_hash.h Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_object_hash.h Tue Jun 18 17:57:38 2019 +0300 @@ -8,6 +8,14 @@ #define _NJS_OBJECT_HASH_H_INCLUDED_ +#define NJS_ARGV_HASH \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add(NXT_DJB_HASH_INIT, \ + 'a'), 'r'), 'g'), 'v') + + #define NJS_CONFIGURABLE_HASH \ nxt_djb_hash_add( \ nxt_djb_hash_add( \ @@ -74,6 +82,13 @@ 'e'), 'n'), 'c'), 'o'), 'd'), 'i'), 'n'), 'g') +#define NJS_ENV_HASH \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add(NXT_DJB_HASH_INIT, \ + 'e'), 'n'), 'v') + + #define NJS_FLAG_HASH \ nxt_djb_hash_add( \ nxt_djb_hash_add( \ diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_parser_terminal.c --- a/njs/njs_parser_terminal.c Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_parser_terminal.c Tue Jun 18 17:57:38 2019 +0300 @@ -270,6 +270,7 @@ njs_parser_reference(njs_vm_t *vm, njs_p /* Fall through. */ case NJS_TOKEN_NJS: + case NJS_TOKEN_PROCESS: case NJS_TOKEN_MATH: case NJS_TOKEN_JSON: ret = njs_parser_builtin(vm, parser, node, NJS_OBJECT, name, hash); diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_shell.c --- a/njs/njs_shell.c Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_shell.c Tue Jun 18 17:57:38 2019 +0300 @@ -265,6 +265,8 @@ main(int argc, char **argv) vm_options.ops = &njs_console_ops; vm_options.external = &njs_console; + vm_options.argv = argv; + vm_options.argc = argc; if (opts.interactive) { ret = njs_interactive_shell(&opts, &vm_options); diff -r 2cb51aab7e78 -r e18ee27ce760 njs/njs_vm.h --- a/njs/njs_vm.h Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/njs_vm.h Tue Jun 18 17:57:38 2019 +0300 @@ -1154,6 +1154,8 @@ struct njs_vm_shared_s { nxt_lvlhsh_t arrow_instance_hash; nxt_lvlhsh_t arguments_object_instance_hash; + nxt_lvlhsh_t env_hash; + njs_object_t string_object; njs_object_t objects[NJS_OBJECT_MAX]; njs_function_t functions[NJS_FUNCTION_MAX]; diff -r 2cb51aab7e78 -r e18ee27ce760 njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Tue Jun 18 17:57:22 2019 +0300 +++ b/njs/test/njs_expect_test.exp Tue Jun 18 17:57:38 2019 +0300 @@ -658,6 +658,20 @@ njs_run {"-c" "console.log(\"a b c\")"} njs_run {"-c" "console.log("} "SyntaxError: Unexpected end of input in string:1" +# process + +njs_run {"-c" "console.log(typeof process.argv)"} "object" +njs_run {"-c" "console.log(process.argv[3])" "AAA"} "AAA" + +njs_run {"-c" "console.log(typeof process.env)"} "object" +njs_run {"-c" "console.log(process.env.HOME != undefined)"} "true" +njs_run {"-c" "console.log(process.env.___UNDECLARED != undefined)"} "false" + +njs_run {"-c" "console.log(process.pid)"} "\\d+" + +njs_run {"-c" "console.log(process.ppid)"} "\\d+" + + # disassemble njs_test { From xeioex at nginx.com Tue Jun 18 17:41:47 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jun 2019 17:41:47 +0000 Subject: [njs] Changed njs_object_prop_define() prototype. Message-ID: details: https://hg.nginx.org/njs/rev/4d21c3e3807f branches: changeset: 1009:4d21c3e3807f user: Dmitry Volyntsev date: Tue Jun 18 20:27:25 2019 +0300 description: Changed njs_object_prop_define() prototype. diffstat: njs/njs_object.c | 5 ++--- njs/njs_object.h | 2 +- njs/njs_object_property.c | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diffs (55 lines): diff -r e18ee27ce760 -r 4d21c3e3807f njs/njs_object.c --- a/njs/njs_object.c Tue Jun 18 17:57:38 2019 +0300 +++ b/njs/njs_object.c Tue Jun 18 20:27:25 2019 +0300 @@ -1138,7 +1138,7 @@ njs_object_define_property(njs_vm_t *vm, name = njs_arg(args, nargs, 2); - ret = njs_object_prop_define(vm, value, name, descriptor->data.u.object); + ret = njs_object_prop_define(vm, value, name, descriptor); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -1192,8 +1192,7 @@ 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.data.u.object); + ret = njs_object_prop_define(vm, value, &prop->name, &prop->value); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; diff -r e18ee27ce760 -r 4d21c3e3807f njs/njs_object.h --- a/njs/njs_object.h Tue Jun 18 17:57:38 2019 +0300 +++ b/njs/njs_object.h Tue Jun 18 20:27:25 2019 +0300 @@ -117,7 +117,7 @@ njs_object_prop_t *njs_object_prop_alloc njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj, nxt_lvlhsh_query_t *lhq); njs_ret_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *name, const njs_object_t *descriptor); + const njs_value_t *name, const njs_value_t *value); njs_ret_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, const njs_value_t *value, const njs_value_t *property); njs_ret_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); diff -r e18ee27ce760 -r 4d21c3e3807f njs/njs_object_property.c --- a/njs/njs_object_property.c Tue Jun 18 17:57:38 2019 +0300 +++ b/njs/njs_object_property.c Tue Jun 18 20:27:25 2019 +0300 @@ -749,7 +749,7 @@ njs_object_property(njs_vm_t *vm, const */ njs_ret_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *name, const njs_object_t *descriptor) + const njs_value_t *name, const njs_value_t *value) { nxt_int_t ret; njs_object_prop_t *desc, *current; @@ -767,7 +767,7 @@ njs_object_prop_define(njs_vm_t *vm, njs return ret; } - desc = njs_descriptor_prop(vm, name, descriptor); + desc = njs_descriptor_prop(vm, name, value->data.u.object); if (nxt_slow_path(desc == NULL)) { return NXT_ERROR; } From xeioex at nginx.com Tue Jun 18 17:41:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jun 2019 17:41:48 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/c427fe5a4882 branches: changeset: 1010:c427fe5a4882 user: Dmitry Volyntsev date: Tue Jun 18 20:27:39 2019 +0300 description: Style. diffstat: njs/njs_object.c | 20 ++++---- njs/njs_object_property.c | 106 +++++++++++++++++++++++----------------------- 2 files changed, 63 insertions(+), 63 deletions(-) diffs (340 lines): diff -r 4d21c3e3807f -r c427fe5a4882 njs/njs_object.c --- a/njs/njs_object.c Tue Jun 18 20:27:25 2019 +0300 +++ b/njs/njs_object.c Tue Jun 18 20:27:39 2019 +0300 @@ -1114,7 +1114,7 @@ njs_object_define_property(njs_vm_t *vm, { nxt_int_t ret; njs_value_t *value; - const njs_value_t *name, *descriptor; + const njs_value_t *name, *desc; if (!njs_is_object(njs_arg(args, nargs, 1))) { njs_type_error(vm, "cannot convert %s argument to object", @@ -1129,16 +1129,16 @@ njs_object_define_property(njs_vm_t *vm, return NXT_ERROR; } - descriptor = njs_arg(args, nargs, 3); - - if (!njs_is_object(descriptor)) { + desc = njs_arg(args, nargs, 3); + + if (!njs_is_object(desc)) { njs_type_error(vm, "descriptor is not an object"); return NXT_ERROR; } name = njs_arg(args, nargs, 2); - ret = njs_object_prop_define(vm, value, name, descriptor); + ret = njs_object_prop_define(vm, value, name, desc); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -1158,7 +1158,7 @@ njs_object_define_properties(njs_vm_t *v nxt_lvlhsh_t *hash; nxt_lvlhsh_each_t lhe; njs_object_prop_t *prop; - const njs_value_t *descriptor; + const njs_value_t *desc; if (!njs_is_object(njs_arg(args, nargs, 1))) { njs_type_error(vm, "cannot convert %s argument to object", @@ -1173,16 +1173,16 @@ njs_object_define_properties(njs_vm_t *v return NXT_ERROR; } - descriptor = njs_arg(args, nargs, 2); - - if (!njs_is_object(descriptor)) { + desc = njs_arg(args, nargs, 2); + + if (!njs_is_object(desc)) { njs_type_error(vm, "descriptor is not an object"); return NXT_ERROR; } nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &descriptor->data.u.object->hash; + hash = &desc->data.u.object->hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); diff -r 4d21c3e3807f -r c427fe5a4882 njs/njs_object_property.c --- a/njs/njs_object_property.c Tue Jun 18 20:27:25 2019 +0300 +++ b/njs/njs_object_property.c Tue Jun 18 20:27:39 2019 +0300 @@ -752,7 +752,7 @@ njs_object_prop_define(njs_vm_t *vm, njs const njs_value_t *name, const njs_value_t *value) { nxt_int_t ret; - njs_object_prop_t *desc, *current; + njs_object_prop_t *prop, *prev; njs_property_query_t pq; njs_string_get(name, &pq.lhq.key); @@ -767,39 +767,39 @@ njs_object_prop_define(njs_vm_t *vm, njs return ret; } - desc = njs_descriptor_prop(vm, name, value->data.u.object); - if (nxt_slow_path(desc == NULL)) { + prop = njs_descriptor_prop(vm, name, value->data.u.object); + if (nxt_slow_path(prop == NULL)) { return NXT_ERROR; } if (nxt_fast_path(ret == NXT_DECLINED)) { - if (!njs_is_valid(&desc->value)) { - desc->value = njs_value_undefined; + if (!njs_is_valid(&prop->value)) { + prop->value = njs_value_undefined; } - if (desc->writable == NJS_ATTRIBUTE_UNSET) { - desc->writable = 0; + if (prop->writable == NJS_ATTRIBUTE_UNSET) { + prop->writable = 0; } - if (desc->enumerable == NJS_ATTRIBUTE_UNSET) { - desc->enumerable = 0; + if (prop->enumerable == NJS_ATTRIBUTE_UNSET) { + prop->enumerable = 0; } - if (desc->configurable == NJS_ATTRIBUTE_UNSET) { - desc->configurable = 0; + if (prop->configurable == NJS_ATTRIBUTE_UNSET) { + prop->configurable = 0; } if (nxt_slow_path(pq.lhq.value != NULL)) { - current = pq.lhq.value; + prev = pq.lhq.value; - if (nxt_slow_path(current->type == NJS_WHITEOUT)) { + if (nxt_slow_path(prev->type == NJS_WHITEOUT)) { /* Previously deleted property. */ - *current = *desc; + *prev = *prop; } } else { - pq.lhq.value = desc; + pq.lhq.value = prop; pq.lhq.replace = 0; pq.lhq.pool = vm->mem_pool; @@ -823,25 +823,25 @@ njs_object_prop_define(njs_vm_t *vm, njs } } - current = pq.lhq.value; + prev = pq.lhq.value; - switch (current->type) { + switch (prev->type) { case NJS_PROPERTY: case NJS_METHOD: break; case NJS_PROPERTY_REF: - if (njs_is_valid(&desc->value)) { - *current->value.data.u.value = desc->value; + if (njs_is_valid(&prop->value)) { + *prev->value.data.u.value = prop->value; } else { - *current->value.data.u.value = njs_value_undefined; + *prev->value.data.u.value = njs_value_undefined; } return NXT_OK; case NJS_PROPERTY_HANDLER: - if (current->writable && njs_is_valid(&desc->value)) { - ret = current->value.data.u.prop_handler(vm, object, &desc->value, + if (prev->writable && njs_is_valid(&prop->value)) { + ret = prev->value.data.u.prop_handler(vm, object, &prop->value, &vm->retval); if (nxt_slow_path(ret != NXT_OK)) { @@ -854,51 +854,51 @@ njs_object_prop_define(njs_vm_t *vm, njs default: njs_internal_error(vm, "unexpected property type \"%s\" " "while defining property", - njs_prop_type_string(current->type)); + njs_prop_type_string(prev->type)); return NXT_ERROR; } - if (!current->configurable) { + if (!prev->configurable) { - if (njs_is_valid(&desc->value) - && current->writable == NJS_ATTRIBUTE_FALSE - && !njs_values_strict_equal(&desc->value, ¤t->value)) + if (njs_is_valid(&prop->value) + && prev->writable == NJS_ATTRIBUTE_FALSE + && !njs_values_strict_equal(&prop->value, &prev->value)) { goto exception; } - if (desc->writable == NJS_ATTRIBUTE_TRUE - && current->writable == NJS_ATTRIBUTE_FALSE) + if (prop->writable == NJS_ATTRIBUTE_TRUE + && prev->writable == NJS_ATTRIBUTE_FALSE) { goto exception; } - if (desc->enumerable != NJS_ATTRIBUTE_UNSET - && current->enumerable != desc->enumerable) + if (prop->enumerable != NJS_ATTRIBUTE_UNSET + && prev->enumerable != prop->enumerable) { goto exception; } - if (desc->configurable == NJS_ATTRIBUTE_TRUE) { + if (prop->configurable == NJS_ATTRIBUTE_TRUE) { goto exception; } } - if (njs_is_valid(&desc->value)) { - current->value = desc->value; + if (njs_is_valid(&prop->value)) { + prev->value = prop->value; } - if (desc->writable != NJS_ATTRIBUTE_UNSET) { - current->writable = desc->writable; + if (prop->writable != NJS_ATTRIBUTE_UNSET) { + prev->writable = prop->writable; } - if (desc->enumerable != NJS_ATTRIBUTE_UNSET) { - current->enumerable = desc->enumerable; + if (prop->enumerable != NJS_ATTRIBUTE_UNSET) { + prev->enumerable = prop->enumerable; } - if (desc->configurable != NJS_ATTRIBUTE_UNSET) { - current->configurable = desc->configurable; + if (prop->configurable != NJS_ATTRIBUTE_UNSET) { + prev->configurable = prop->configurable; } return NXT_OK; @@ -913,7 +913,7 @@ exception: static njs_object_prop_t * njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, - const njs_object_t *descriptor) + const njs_object_t *desc) { njs_object_prop_t *prop, *pr; nxt_lvlhsh_query_t pq; @@ -927,7 +927,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pq.key = nxt_string_value("value"); pq.key_hash = NJS_VALUE_HASH; - pr = njs_object_property(vm, descriptor, &pq); + pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { prop->value = pr->value; } @@ -935,7 +935,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pq.key = nxt_string_value("writable"); pq.key_hash = NJS_WRITABABLE_HASH; - pr = njs_object_property(vm, descriptor, &pq); + pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { prop->writable = pr->value.data.truth; } @@ -943,7 +943,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pq.key = nxt_string_value("enumerable"); pq.key_hash = NJS_ENUMERABLE_HASH; - pr = njs_object_property(vm, descriptor, &pq); + pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { prop->enumerable = pr->value.data.truth; } @@ -951,7 +951,7 @@ njs_descriptor_prop(njs_vm_t *vm, const pq.key = nxt_string_value("configurable"); pq.key_hash = NJS_CONFIGURABLE_HASH; - pr = njs_object_property(vm, descriptor, &pq); + pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { prop->configurable = pr->value.data.truth; } @@ -974,7 +974,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, const njs_value_t *value, const njs_value_t *property) { nxt_int_t ret; - njs_object_t *descriptor; + njs_object_t *desc; njs_object_prop_t *pr, *prop; const njs_value_t *setval; nxt_lvlhsh_query_t lhq; @@ -1034,8 +1034,8 @@ njs_object_prop_descriptor(njs_vm_t *vm, return NXT_ERROR; } - descriptor = njs_object_alloc(vm); - if (nxt_slow_path(descriptor == NULL)) { + desc = njs_object_alloc(vm); + if (nxt_slow_path(desc == NULL)) { return NXT_ERROR; } @@ -1053,7 +1053,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, lhq.value = pr; - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NXT_ERROR; @@ -1071,7 +1071,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, lhq.value = pr; - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NXT_ERROR; @@ -1089,7 +1089,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, lhq.value = pr; - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NXT_ERROR; @@ -1107,13 +1107,13 @@ njs_object_prop_descriptor(njs_vm_t *vm, lhq.value = pr; - ret = nxt_lvlhsh_insert(&descriptor->hash, &lhq); + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { njs_internal_error(vm, "lvlhsh insert failed"); return NXT_ERROR; } - dest->data.u.object = descriptor; + dest->data.u.object = desc; dest->type = NJS_OBJECT; dest->data.truth = 1; From xeioex at nginx.com Tue Jun 18 17:41:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jun 2019 17:41:48 +0000 Subject: [njs] Added property getter/setter support in Object.defineProperty(). Message-ID: details: https://hg.nginx.org/njs/rev/2fb43ddbce84 branches: changeset: 1011:2fb43ddbce84 user: hongzhidao date: Mon Jun 10 22:23:56 2019 -0400 description: Added property getter/setter support in Object.defineProperty(). In collaboration with Dmitry Volyntsev. diffstat: njs/njs_array.c | 66 +++++++- njs/njs_function.c | 4 +- njs/njs_object.c | 6 +- njs/njs_object.h | 24 ++- njs/njs_object_hash.h | 14 + njs/njs_object_property.c | 326 +++++++++++++++++++++++++++++++++++++-------- njs/njs_vm.c | 27 ++- njs/test/njs_unit_test.c | 186 ++++++++++++++++++++++++++ 8 files changed, 564 insertions(+), 89 deletions(-) diffs (truncated from 1029 to 1000 lines): diff -r c427fe5a4882 -r 2fb43ddbce84 njs/njs_array.c --- a/njs/njs_array.c Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_array.c Mon Jun 10 22:23:56 2019 -0400 @@ -29,6 +29,8 @@ typedef struct { } u; njs_value_t length; + nxt_int_t start; + nxt_int_t end; } njs_array_fill_t; @@ -100,6 +102,8 @@ static njs_ret_t njs_array_prototype_joi static njs_value_t *njs_array_copy(njs_value_t *dst, njs_value_t *src); static njs_ret_t njs_array_prototype_fill_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); +static njs_ret_t njs_array_prototype_fill_object_continuation(njs_vm_t *vm, + njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_ret_t njs_array_prototype_for_each_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_ret_t njs_array_prototype_some_continuation(njs_vm_t *vm, @@ -524,8 +528,13 @@ njs_array_prototype_slice(njs_vm_t *vm, slice = njs_vm_continuation(vm); slice->u.cont.function = njs_array_prototype_slice_continuation; - ret = njs_value_property(vm, &args[0], &njs_string_length, &slice->length); - if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_TRAP)) { + ret = njs_value_property(vm, &args[0], &njs_string_length, &slice->length, + 0); + + if (nxt_slow_path(ret == NXT_ERROR + || ret == NJS_TRAP + || ret == NJS_APPLIED)) + { return ret; } @@ -671,7 +680,7 @@ njs_array_prototype_slice_copy(njs_vm_t njs_uint32_to_string(&name, start++); value = &array->start[n++]; - ret = njs_value_property(vm, this, &name, value); + ret = njs_value_property(vm, this, &name, value, 0); if (ret != NXT_OK) { *value = njs_value_invalid; @@ -1426,8 +1435,13 @@ njs_array_prototype_fill(njs_vm_t *vm, n fill = njs_vm_continuation(vm); fill->u.cont.function = njs_array_prototype_fill_continuation; - ret = njs_value_property(vm, this, &njs_string_length, &fill->length); - if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_TRAP)) { + ret = njs_value_property(vm, this, &njs_string_length, &fill->length, + 0); + + if (nxt_slow_path(ret == NXT_ERROR + || ret == NJS_TRAP + || ret == NJS_APPLIED)) + { return ret; } } @@ -1440,10 +1454,8 @@ static njs_ret_t njs_array_prototype_fill_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - njs_ret_t ret; nxt_int_t i, start, end, length; njs_array_t *array; - njs_value_t name; njs_object_t *object; njs_array_fill_t *fill; const njs_value_t *this, *value; @@ -1465,12 +1477,13 @@ njs_array_prototype_fill_continuation(nj return NXT_OK; } + fill = njs_vm_continuation(vm); + if (njs_is_array(this)) { array = this->data.u.array; length = array->length; } else { - fill = njs_vm_continuation(vm); if (nxt_slow_path(!njs_is_primitive(&fill->length))) { njs_vm_trap_value(vm, &fill->length); @@ -1494,22 +1507,47 @@ njs_array_prototype_fill_continuation(nj value = njs_arg(args, nargs, 1); - vm->retval = *this; - if (array != NULL) { for (i = start; i < end; i++) { array->start[i] = *value; } + vm->retval = *this; + return NXT_OK; } - for (i = start; i < end; i++) { - njs_uint32_to_string(&name, i); + fill->u.cont.function = njs_array_prototype_fill_object_continuation; + fill->start = start; + fill->end = end; + + return njs_array_prototype_fill_object_continuation(vm, args, nargs, + unused); +} + + +static njs_ret_t +njs_array_prototype_fill_object_continuation(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + njs_ret_t ret; + nxt_int_t end; + njs_value_t name; + njs_array_fill_t *fill; + const njs_value_t *value; + + fill = njs_vm_continuation(vm); + end = fill->end; + + vm->retval = *njs_arg(args, nargs, 0); + value = njs_arg(args, nargs, 1); + + while (fill->start < end) { + njs_uint32_to_string(&name, fill->start++); ret = njs_value_property_set(vm, &vm->retval, &name, - (njs_value_t *) value); - if (nxt_slow_path(ret == NXT_ERROR)) { + (njs_value_t *) value, 0); + if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) { return ret; } } diff -r c427fe5a4882 -r 2fb43ddbce84 njs/njs_function.c --- a/njs/njs_function.c Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_function.c Mon Jun 10 22:23:56 2019 -0400 @@ -1042,7 +1042,7 @@ njs_function_prototype_apply(njs_vm_t *v return NXT_ERROR; } - ret = njs_value_property(vm, arr_like, &njs_string_length, &length); + ret = njs_value_property(vm, arr_like, &njs_string_length, &length, 0); if (nxt_slow_path(ret == NXT_ERROR)) { return ret; } @@ -1064,7 +1064,7 @@ njs_function_prototype_apply(njs_vm_t *v for (i = 0; i < nargs; i++) { njs_uint32_to_string(&name, i); - ret = njs_value_property(vm, arr_like, &name, &args[i]); + ret = njs_value_property(vm, arr_like, &name, &args[i], 0); if (nxt_slow_path(ret == NXT_ERROR)) { return ret; } diff -r c427fe5a4882 -r 2fb43ddbce84 njs/njs_object.c --- a/njs/njs_object.c Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_object.c Mon Jun 10 22:23:56 2019 -0400 @@ -1421,7 +1421,11 @@ njs_object_is_frozen(njs_vm_t *vm, njs_v break; } - if (prop->writable || prop->configurable) { + if (prop->configurable) { + goto done; + } + + if (njs_is_data_descriptor(prop) && prop->writable) { goto done; } } diff -r c427fe5a4882 -r 2fb43ddbce84 njs/njs_object.h --- a/njs/njs_object.h Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_object.h Mon Jun 10 22:23:56 2019 -0400 @@ -19,7 +19,10 @@ typedef enum { /* * Attributes are generally used as Boolean values. - * The UNSET value is used internally only by njs_define_property(). + * 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, @@ -32,7 +35,10 @@ 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 */ @@ -41,6 +47,18 @@ typedef struct { } njs_object_prop_t; +#define njs_is_data_descriptor(prop) \ + ((prop)->writable != NJS_ATTRIBUTE_UNSET || njs_is_valid(&(prop)->value)) + + +#define njs_is_accessor_descriptor(prop) \ + (njs_is_valid(&(prop)->getter) || njs_is_valid(&(prop)->setter)) + + +#define njs_is_generic_descriptor(prop) \ + (!njs_is_data_descriptor(prop) && !njs_is_accessor_descriptor(prop)) + + typedef struct { nxt_lvlhsh_query_t lhq; @@ -109,9 +127,9 @@ njs_ret_t njs_object_prototype_to_string njs_ret_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object, const njs_value_t *property); njs_ret_t njs_value_property(njs_vm_t *vm, const njs_value_t *value, - const njs_value_t *property, njs_value_t *retval); + const njs_value_t *property, njs_value_t *retval, size_t advance); njs_ret_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *property, njs_value_t *value); + const njs_value_t *property, njs_value_t *value, size_t advance); 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 c427fe5a4882 -r 2fb43ddbce84 njs/njs_object_hash.h --- a/njs/njs_object_hash.h Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_object_hash.h Mon Jun 10 22:23:56 2019 -0400 @@ -271,4 +271,18 @@ 'w'), 'r'), 'i'), 't'), 'a'), 'b'), 'l'), 'e') +#define NJS_GET_HASH \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add(NXT_DJB_HASH_INIT, \ + 'g'), 'e'), 't') + + +#define NJS_SET_HASH \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add(NXT_DJB_HASH_INIT, \ + 's'), 'e'), 't') + + #endif /* _NJS_OBJECT_HASH_H_INCLUDED_ */ diff -r c427fe5a4882 -r 2fb43ddbce84 njs/njs_object_property.c --- a/njs/njs_object_property.c Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_object_property.c Mon Jun 10 22:23:56 2019 -0400 @@ -474,14 +474,15 @@ njs_external_property_delete(njs_vm_t *v * NXT_OK property has been found in object, * retval will contain the property's value * - * NXT_DECLINED property was not found in object, - * NJS_TRAP the property trap must be called, + * NXT_DECLINED property was not found in object + * NJS_TRAP the property trap must be called + * NJS_APPLIED the property getter was applied * NXT_ERROR exception has been thrown. * retval will contain undefined */ njs_ret_t njs_value_property(njs_vm_t *vm, const njs_value_t *value, - const njs_value_t *property, njs_value_t *retval) + const njs_value_t *property, njs_value_t *retval, size_t advance) { njs_ret_t ret; njs_object_prop_t *prop; @@ -512,8 +513,19 @@ njs_value_property(njs_vm_t *vm, const n /* Fall through. */ case NJS_PROPERTY: - *retval = prop->value; - break; + if (njs_is_data_descriptor(prop)) { + *retval = prop->value; + break; + } + + if (njs_is_undefined(&prop->getter)) { + *retval = njs_value_undefined; + break; + } + + return njs_function_activate(vm, prop->getter.data.u.function, + value, NULL, 0, (njs_index_t) retval, + advance); case NJS_PROPERTY_HANDLER: pq.scratch = *prop; @@ -557,11 +569,12 @@ njs_value_property(njs_vm_t *vm, const n /* * NXT_OK property has been set successfully * NJS_TRAP the property trap must be called + * NJS_APPLIED the property setter was applied * NXT_ERROR exception has been thrown. */ njs_ret_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, - const njs_value_t *property, njs_value_t *value) + const njs_value_t *property, njs_value_t *value, size_t advance) { njs_ret_t ret; njs_object_prop_t *prop, *shared; @@ -584,9 +597,17 @@ njs_value_property_set(njs_vm_t *vm, njs case NXT_OK: prop = pq.lhq.value; - if (nxt_slow_path(!prop->writable)) { + if (njs_is_data_descriptor(prop)) { + if (!prop->writable) { + njs_type_error(vm, + "Cannot assign to read-only property \"%V\" of %s", + &pq.lhq.key, njs_type_string(object->type)); + return NXT_ERROR; + } + + } else if (!njs_is_function(&prop->setter)) { njs_type_error(vm, - "Cannot assign to read-only property \"%V\" of %s", + "Cannot set property \"%V\" of %s which has only a getter", &pq.lhq.key, njs_type_string(object->type)); return NXT_ERROR; } @@ -608,6 +629,14 @@ njs_value_property_set(njs_vm_t *vm, njs break; } + if (njs_is_function(&prop->setter)) { + return njs_function_activate(vm, + prop->setter.data.u.function, + object, value, 1, + (njs_index_t) &vm->retval, + advance); + } + goto found; case NJS_PROPERTY_REF: @@ -704,6 +733,9 @@ 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; + return prop; } @@ -774,12 +806,25 @@ njs_object_prop_define(njs_vm_t *vm, njs if (nxt_fast_path(ret == NXT_DECLINED)) { - if (!njs_is_valid(&prop->value)) { - prop->value = njs_value_undefined; - } + /* 6.2.5.6 CompletePropertypropriptor */ + + if (njs_is_accessor_descriptor(prop)) { + if (!njs_is_valid(&prop->getter)) { + prop->getter = njs_value_undefined; + } - if (prop->writable == NJS_ATTRIBUTE_UNSET) { - prop->writable = 0; + 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) { @@ -826,8 +871,9 @@ njs_object_prop_define(njs_vm_t *vm, njs prev = pq.lhq.value; switch (prev->type) { + case NJS_METHOD: case NJS_PROPERTY: - case NJS_METHOD: + case NJS_PROPERTY_HANDLER: break; case NJS_PROPERTY_REF: @@ -839,18 +885,6 @@ njs_object_prop_define(njs_vm_t *vm, njs return NXT_OK; - case NJS_PROPERTY_HANDLER: - if (prev->writable && njs_is_valid(&prop->value)) { - ret = prev->value.data.u.prop_handler(vm, object, &prop->value, - &vm->retval); - - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - } - - return NXT_OK; - default: njs_internal_error(vm, "unexpected property type \"%s\" " "while defining property", @@ -859,18 +893,11 @@ njs_object_prop_define(njs_vm_t *vm, njs return NXT_ERROR; } + /* 9.1.6.3 ValidateAndApplyPropertyDescriptor */ + if (!prev->configurable) { - if (njs_is_valid(&prop->value) - && prev->writable == NJS_ATTRIBUTE_FALSE - && !njs_values_strict_equal(&prop->value, &prev->value)) - { - goto exception; - } - - if (prop->writable == NJS_ATTRIBUTE_TRUE - && prev->writable == NJS_ATTRIBUTE_FALSE) - { + if (prop->configurable == NJS_ATTRIBUTE_TRUE) { goto exception; } @@ -879,14 +906,100 @@ njs_object_prop_define(njs_vm_t *vm, njs { goto exception; } + } - if (prop->configurable == NJS_ATTRIBUTE_TRUE) { + 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)) { - prev->value = 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 (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + } + + } else { + prev->value = prop->value; + } } if (prop->writable != NJS_ATTRIBUTE_UNSET) { @@ -915,20 +1028,60 @@ static njs_object_prop_t * njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name, const njs_object_t *desc) { + nxt_bool_t data, accessor; njs_object_prop_t *prop, *pr; + const njs_value_t *setter, *getter; nxt_lvlhsh_query_t pq; + data = 0; + accessor = 0; + prop = njs_object_prop_alloc(vm, name, &njs_value_invalid, NJS_ATTRIBUTE_UNSET); if (nxt_slow_path(prop == NULL)) { return NULL; } + getter = &njs_value_invalid; + pq.key = nxt_string_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 = nxt_string_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 = nxt_string_value("value"); pq.key_hash = NJS_VALUE_HASH; pr = njs_object_property(vm, desc, &pq); if (pr != NULL) { + data = 1; prop->value = pr->value; } @@ -937,6 +1090,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; } @@ -956,11 +1110,19 @@ njs_descriptor_prop(njs_vm_t *vm, const 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 = @@ -1043,38 +1205,78 @@ njs_object_prop_descriptor(njs_vm_t *vm, lhq.replace = 0; lhq.pool = vm->mem_pool; - lhq.key = nxt_string_value("value"); - lhq.key_hash = NJS_VALUE_HASH; + if (njs_is_data_descriptor(prop)) { + + lhq.key = nxt_string_value("value"); + lhq.key_hash = NJS_VALUE_HASH; - pr = njs_object_prop_alloc(vm, &njs_object_value_string, &prop->value, 1); - if (nxt_slow_path(pr == NULL)) { - return NXT_ERROR; - } + pr = njs_object_prop_alloc(vm, &njs_object_value_string, &prop->value, + 1); + if (nxt_slow_path(pr == NULL)) { + return NXT_ERROR; + } + + lhq.value = pr; - lhq.value = pr; + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + + lhq.key = nxt_string_value("writable"); + lhq.key_hash = NJS_WRITABABLE_HASH; - ret = nxt_lvlhsh_insert(&desc->hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; - } + setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false; + + pr = njs_object_prop_alloc(vm, &njs_object_writable_string, setval, 1); + if (nxt_slow_path(pr == NULL)) { + return NXT_ERROR; + } + + lhq.value = pr; - lhq.key = nxt_string_value("writable"); - lhq.key_hash = NJS_WRITABABLE_HASH; + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + + } else { - setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false; + lhq.key = nxt_string_value("get"); + lhq.key_hash = NJS_GET_HASH; + + pr = njs_object_prop_alloc(vm, &njs_object_get_string, &prop->getter, + 1); + if (nxt_slow_path(pr == NULL)) { + return NXT_ERROR; + } + + lhq.value = pr; - pr = njs_object_prop_alloc(vm, &njs_object_writable_string, setval, 1); - if (nxt_slow_path(pr == NULL)) { - return NXT_ERROR; - } + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + + lhq.key = nxt_string_value("set"); + lhq.key_hash = NJS_SET_HASH; - lhq.value = pr; + pr = njs_object_prop_alloc(vm, &njs_object_set_string, &prop->setter, + 1); + if (nxt_slow_path(pr == NULL)) { + return NXT_ERROR; + } - ret = nxt_lvlhsh_insert(&desc->hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NXT_ERROR; + lhq.value = pr; + + ret = nxt_lvlhsh_insert(&desc->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } } lhq.key = nxt_string_value("enumerable"); diff -r c427fe5a4882 -r 2fb43ddbce84 njs/njs_vm.c --- a/njs/njs_vm.c Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/njs_vm.c Mon Jun 10 22:23:56 2019 -0400 @@ -533,14 +533,21 @@ njs_ret_t njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object, njs_value_t *property) { - njs_ret_t ret; - - ret = njs_value_property(vm, object, property, &vm->retval); + njs_ret_t ret; + njs_value_t *retval; + njs_vmcode_prop_get_t *code; + + code = (njs_vmcode_prop_get_t *) vm->current; + retval = njs_vmcode_operand(vm, code->value); + + ret = njs_value_property(vm, object, property, retval, + sizeof(njs_vmcode_prop_get_t)); if (ret == NXT_OK || ret == NXT_DECLINED) { + vm->retval = *retval; return sizeof(njs_vmcode_prop_get_t); } - return ret; + return (ret == NJS_APPLIED) ? 0 : ret; } @@ -665,12 +672,13 @@ njs_vmcode_property_set(njs_vm_t *vm, nj code = (njs_vmcode_prop_set_t *) vm->current; value = njs_vmcode_operand(vm, code->value); - ret = njs_value_property_set(vm, object, property, value); + ret = njs_value_property_set(vm, object, property, value, + sizeof(njs_vmcode_prop_set_t)); if (ret == NXT_OK) { return sizeof(njs_vmcode_prop_set_t); } - return ret; + return (ret == NJS_APPLIED) ? 0 : ret; } @@ -936,7 +944,12 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs if (njs_is_object(object)) { value = njs_value_undefined; - ret = njs_value_property(vm, constructor, &prototype_string, &value); + ret = njs_value_property(vm, constructor, &prototype_string, &value, 0); + + if (nxt_slow_path(ret == NJS_APPLIED)) { + njs_internal_error(vm, "getter is not supported in instanceof"); + return NXT_ERROR; + } if (nxt_fast_path(ret == NXT_OK)) { diff -r c427fe5a4882 -r 2fb43ddbce84 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Jun 18 20:27:39 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon Jun 10 22:23:56 2019 -0400 @@ -4009,6 +4009,29 @@ static njs_unit_test_t njs_test[] = ").every((x) => typeof x == 'object')"), nxt_string("true") }, + { nxt_string("var o = {}; Object.defineProperty(o, 'length', {get:()=>2}); " + "Array.prototype.slice.call(Array.prototype.fill.call(o, 1))"), + nxt_string("1,1") }, + + { nxt_string("var o = {}; Object.defineProperty(o, 'length', {get:()=> {throw TypeError('Boom')}}); " + "Array.prototype.fill.call(o, 1)"), + nxt_string("TypeError: Boom") }, + + { nxt_string("var o = Object({length: 3});" + "Object.defineProperty(o, '0', {set: ()=>{throw TypeError('Boom')}});" + "Array.prototype.fill.call(o, 1)"), + nxt_string("TypeError: Boom") }, + + { nxt_string("var o = Object({length: 3});" + "Object.defineProperty(o, '0', {set: function(v){this.a = 2 * v}});" + "Array.prototype.fill.call(o, 2).a"), + nxt_string("4") }, + + { nxt_string("var o = Object({length: 3});" + "Object.defineProperty(o, '0', {set: function(v){this[0] = 2 * v}});" + "Array.prototype.fill.call(o, 2)"), + nxt_string("RangeError: Maximum call stack size exceeded") }, + { nxt_string("var a = [];" "a.filter(function(v, i, a) { return v > 1 })"), nxt_string("") }, @@ -8201,6 +8224,10 @@ static njs_unit_test_t njs_test[] = { nxt_string("/./ instanceof Object"), nxt_string("true") }, + { nxt_string("Object.defineProperty(Function.prototype, \"prototype\", {get: ()=>Array.prototype});" + "[] instanceof Function.prototype"), + nxt_string("InternalError: getter is not supported in instanceof") }, + /* global this. */ { nxt_string("this"), @@ -9159,6 +9186,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = {}; Object.defineProperty(o, 'a', {value:1}); o.a"), nxt_string("1") }, + { nxt_string("var o = {}; Object.defineProperty(o, 'a', Object.create({value:1})); o.a"), + nxt_string("1") }, + { nxt_string("var o = {a:1, c:2}; Object.defineProperty(o, 'b', {});" "Object.keys(o)"), nxt_string("a,c") }, @@ -9309,6 +9339,32 @@ static njs_unit_test_t njs_test[] = nxt_string("1") }, { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {configurable:true, get:()=>1});" + "Object.defineProperty(o, 'a', {value:1});" + "var d = Object.getOwnPropertyDescriptor(o, 'a'); " + "[d.value, d.writable, d.enumerable, d.configurable, d.get, d.set]"), + nxt_string("1,false,false,true,,") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {configurable:true, value:1});" + "Object.defineProperty(o, 'a', {set:()=>1});" + "var d = Object.getOwnPropertyDescriptor(o, 'a'); " + "[d.value, d.writable, d.enumerable, d.configurable, d.get, d.set]"), + nxt_string(",,false,true,,[object Function]") }, + + { nxt_string("var o = {}; Object.defineProperty(o, 'a', {get: ()=>1, configurable:true}); " + "Object.defineProperty(o, 'a', {value:123}); o.a =2"), + nxt_string("TypeError: Cannot assign to read-only property \"a\" of object") }, + + { nxt_string("var o = {}; Object.defineProperty(o, 'a', {get: ()=>1, configurable:true}); " + "Object.defineProperty(o, 'a', {writable:false}); o.a"), + nxt_string("undefined") }, + + { nxt_string("var o = {}; Object.defineProperty(o, 'a', {value: 1, configurable:true}); " + "Object.defineProperty(o, 'a', {get:()=>1}); o.a = 2"), + nxt_string("TypeError: Cannot set property \"a\" of object which has only a getter") }, + + { nxt_string("var o = {};" "Object.defineProperty(o, 'a', { configurable: true, value: 0 });" "Object.defineProperty(o, 'a', { value: 1 });" "Object.defineProperty(o, 'a', { configurable: false, value: 2 }).a"), @@ -9387,6 +9443,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = Object.defineProperties({a:1}, {}); o.a"), nxt_string("1") }, + { nxt_string("var arr = [0, 1]; Object.defineProperty(arr, 'length', {value:3}); arr.length"), + nxt_string("3") }, + { nxt_string("Object.defineProperties()"), nxt_string("TypeError: cannot convert undefined argument to object") }, @@ -9477,6 +9536,133 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.prototype.hasOwnProperty('hasOwnProperty')"), nxt_string("true") }, + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined, set:undefined}).a"), + nxt_string("undefined") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:1})"), + nxt_string("TypeError: Getter must be a function") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined}).a"), + nxt_string("undefined") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:function(){return 1}}).a"), + nxt_string("1") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {set:1})"), + nxt_string("TypeError: Setter must be a function") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {set:undefined}); o.a"), + nxt_string("undefined") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {set:undefined}); o.a = 4;"), + nxt_string("TypeError: Cannot set property \"a\" of object which has only a getter") }, + + { nxt_string("var o = {a: 0};" + "Object.defineProperty(o, 'b', {set:function(x){this.a = x / 2;}}); o.b = 4; o.a;"), + nxt_string("2") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {value:undefined});" + "Object.defineProperty(o, 'a', {get:undefined})"), + nxt_string("TypeError: Cannot redefine property: \"a\"") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {});" + "Object.defineProperty(o, 'a', {get:undefined})"), + nxt_string("TypeError: Cannot redefine property: \"a\"") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined});" + "Object.defineProperty(o, 'a', {get:undefined}).a"), + nxt_string("undefined") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined});" + "Object.defineProperty(o, 'a', {set:undefined}).a"), + nxt_string("undefined") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined});" + "Object.defineProperty(o, 'a', {}); o.a"), + nxt_string("undefined") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined});" + "Object.defineProperty(o, 'a', {set:function(){}})"), + nxt_string("TypeError: Cannot redefine property: \"a\"") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:undefined});" + "Object.defineProperty(o, 'a', {get:function(){}})"), + nxt_string("TypeError: Cannot redefine property: \"a\"") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:()=>1, configurable:true});" + "Object.defineProperty(o, 'a', {get:()=>2}); o.a"), + nxt_string("2") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {set:function(v){this.aa=v;}, configurable:true});" + "Object.defineProperty(o, 'a', {get:function(){return this.aa}}); o.a = 1; o.a"), + nxt_string("1") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:()=>1, configurable:true});" + "Object.defineProperty(o, 'a', {value:2}).a"), + nxt_string("2") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {get:()=>1, configurable:true});" + "Object.defineProperty(o, 'a', {value:2});" + "var d = Object.getOwnPropertyDescriptor(o, 'a');" + "d.get === undefined && d.set === undefined"), + nxt_string("true") }, + + { nxt_string("var o = {};" + "Object.defineProperty(o, 'a', {value:1, configurable:true});" + "Object.defineProperty(o, 'a', {get:()=>2});" + "var d = Object.getOwnPropertyDescriptor(o, 'a');" + "d.writable === undefined && d.value === undefined"), + nxt_string("true") }, + + { nxt_string("Object.defineProperty(Date.prototype, 'year', {get: function() { return this.getFullYear();}});" + "var d = new Date(0); d.year"), + nxt_string("1970") }, + + { nxt_string("var o = [];" From sharpobject at gmail.com Tue Jun 18 23:13:34 2019 From: sharpobject at gmail.com (Robert Burke) Date: Tue, 18 Jun 2019 16:13:34 -0700 Subject: [PATCH] Range filter: always support ascending multipart ranges. In-Reply-To: References: Message-ID: Hello again :) > If you think you want to add support nevertheless, you may want to > elaborate more on why you need it. In my practice there are very > few legitimate users of multipart ranges, and at least some of > these actually benefit from disabling ranges support completely. Sure. I might distribute software patches for a large software project like so: my patcher downloads an index file. That file says that there is one really big file at some URL containing various files used by the software at various byte-ranges. The patcher makes some multipart range requests for that URL, asking for only the ranges that correspond to the files it needs to update. If the patcher instead gets the whole thing, my user is sad because he or she has to wait to download many times more data than expected. This is a strange way to do things. Why would I want to do it? Well, I want to let my users patch from a large number of old versions of my software to the current version (e.g. from versions 7000-10999 to version 11000) without downloading multiple versions of the same file and without just downloading the whole thing. I also want to minimize the number of round trips and connections, since RTT or connection overhead could dominate if I am requesting a bunch of tiny files one by one or in parallel. I hope this example is useful. Ultimately we make changes like this because our customers want them. I attached a version of the patch that applies cleanly given the recent upstream changes to range filter. Thanks, Robert -------------- next part -------------- A non-text attachment was scrubbed... Name: ascending_multi_ranges.patch Type: application/octet-stream Size: 16288 bytes Desc: not available URL: From xeioex at nginx.com Thu Jun 20 22:36:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 20 Jun 2019 22:36:17 +0000 Subject: [njs] Fixed use-of-uninitialized-value in njs_string_replace_join(). Message-ID: details: https://hg.nginx.org/njs/rev/df8d48ea3875 branches: changeset: 1013:df8d48ea3875 user: Dmitry Volyntsev date: Thu Jun 20 15:20:34 2019 +0300 description: Fixed use-of-uninitialized-value in njs_string_replace_join(). diffstat: njs/njs_string.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diffs (22 lines): diff -r d6ffea147fd3 -r df8d48ea3875 njs/njs_string.c --- a/njs/njs_string.c Thu Jun 20 07:36:57 2019 -0400 +++ b/njs/njs_string.c Thu Jun 20 15:20:34 2019 +0300 @@ -3652,12 +3652,16 @@ njs_string_replace_join(njs_vm_t *vm, nj n = r->parts.items; for (i = 0; i < n; i++) { + if (part[i].size == 0) { + continue; + } + + size += part[i].size; + if (part[i].start == NULL) { part[i].start = part[i].value.short_string.start; } - size += part[i].size; - len = nxt_utf8_length(part[i].start, part[i].size); if (len >= 0) { From xeioex at nginx.com Thu Jun 20 22:36:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 20 Jun 2019 22:36:16 +0000 Subject: [njs] Getting rid of lexer property and property_token. Message-ID: details: https://hg.nginx.org/njs/rev/d6ffea147fd3 branches: changeset: 1012:d6ffea147fd3 user: hongzhidao date: Thu Jun 20 07:36:57 2019 -0400 description: Getting rid of lexer property and property_token. diffstat: njs/njs_lexer.c | 5 -- njs/njs_lexer.h | 4 +- njs/njs_lexer_keyword.c | 1 + njs/njs_parser.c | 31 ---------------- njs/njs_parser.h | 21 ++++++++++- njs/njs_parser_expression.c | 31 +++++++++------- njs/njs_parser_terminal.c | 83 ++++++++++++++++++++++++++++---------------- 7 files changed, 92 insertions(+), 84 deletions(-) diffs (316 lines): diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_lexer.c --- a/njs/njs_lexer.c Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_lexer.c Thu Jun 20 07:36:57 2019 -0400 @@ -420,11 +420,6 @@ njs_lexer_token_name_resolve(njs_lexer_t { if (lt->token == NJS_TOKEN_NAME) { njs_lexer_keyword(lexer, lt); - - if (lexer->property) { - lexer->property_token = lt->token; - lt->token = NJS_TOKEN_NAME; - } } return lt->token; diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_lexer.h --- a/njs/njs_lexer.h Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_lexer.h Thu Jun 20 07:36:57 2019 -0400 @@ -231,13 +231,11 @@ typedef struct { typedef struct { njs_lexer_token_t *lexer_token; nxt_queue_t preread; /* of njs_lexer_token_t */ + uint8_t keyword; u_char *prev_start; njs_token_t prev_token:16; - uint8_t property; /* 1 bit */ - njs_token_t property_token:16; - uint32_t line; nxt_str_t file; diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_lexer_keyword.c Thu Jun 20 07:36:57 2019 -0400 @@ -191,5 +191,6 @@ njs_lexer_keyword(njs_lexer_t *lexer, nj keyword = lhq.value; lt->token = keyword->token; lt->number = keyword->number; + lexer->keyword = 1; } } diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_parser.c --- a/njs/njs_parser.c Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_parser.c Thu Jun 20 07:36:57 2019 -0400 @@ -2064,37 +2064,6 @@ njs_parser_grouping_expression(njs_vm_t } -njs_token_t -njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser) -{ - nxt_int_t ret; - njs_token_t token; - njs_parser_node_t *node; - - parser->lexer->property = 1; - - token = njs_parser_token(vm, parser); - - parser->lexer->property = 0; - - if (token == NJS_TOKEN_NAME) { - node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - ret = njs_parser_string_create(vm, &node->u.value); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; - } - - parser->node = node; - } - - return token; -} - - nxt_int_t njs_parser_match_arrow_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_parser.h --- a/njs/njs_parser.h Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_parser.h Thu Jun 20 07:36:57 2019 -0400 @@ -94,7 +94,6 @@ njs_token_t njs_parser_template_literal( njs_parser_node_t *parent); njs_parser_node_t *njs_parser_argument(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *expr, njs_index_t index); -njs_token_t njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser); nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value); njs_token_t njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); @@ -187,6 +186,26 @@ njs_parser_node_new(njs_vm_t *vm, njs_pa } +nxt_inline njs_parser_node_t * +njs_parser_node_string(njs_vm_t *vm, njs_parser_t *parser) +{ + nxt_int_t ret; + njs_parser_node_t *node; + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); + if (nxt_slow_path(node == NULL)) { + return NULL; + } + + ret = njs_parser_string_create(vm, &node->u.value); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + return node; +} + + nxt_inline njs_token_t njs_parser_match(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, njs_token_t match) diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_parser_expression.c --- a/njs/njs_parser_expression.c Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_parser_expression.c Thu Jun 20 07:36:57 2019 -0400 @@ -884,7 +884,7 @@ static njs_token_t njs_parser_property_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - njs_parser_node_t *node; + njs_parser_node_t *node, *prop_node; for ( ;; ) { if (token != NJS_TOKEN_DOT @@ -902,18 +902,22 @@ njs_parser_property_expression(njs_vm_t node->left = parser->node; if (token == NJS_TOKEN_DOT) { + token = njs_parser_token(vm, parser); - token = njs_parser_property_token(vm, parser); + if (token != NJS_TOKEN_NAME && !parser->lexer->keyword) { + return NJS_TOKEN_ILLEGAL; + } + + prop_node = njs_parser_node_string(vm, parser); + if (nxt_slow_path(prop_node == NULL)) { + return NJS_TOKEN_ERROR; + } + + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } - if (token != NJS_TOKEN_NAME) { - return NJS_TOKEN_ILLEGAL; - } - - token = njs_parser_token(vm, parser); - } else { token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { @@ -921,13 +925,14 @@ njs_parser_property_expression(njs_vm_t } token = njs_parser_property_brackets(vm, parser, token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + prop_node = parser->node; } - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - node->right = parser->node; + node->right = prop_node; parser->node = node; } } diff -r 2fb43ddbce84 -r d6ffea147fd3 njs/njs_parser_terminal.c --- a/njs/njs_parser_terminal.c Mon Jun 10 22:23:56 2019 -0400 +++ b/njs/njs_parser_terminal.c Thu Jun 20 07:36:57 2019 -0400 @@ -488,7 +488,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars uint32_t hash, token_line; nxt_int_t ret; nxt_str_t name; - njs_token_t token; + njs_token_t token, prop_token; njs_lexer_t *lexer; njs_parser_node_t *object, *property, *expression; @@ -506,54 +506,69 @@ njs_parser_object(njs_vm_t *vm, njs_pars object->u.object = obj; for ( ;; ) { - token = njs_parser_property_token(vm, parser); - - if (token == NJS_TOKEN_CLOSE_BRACE) { - break; + prop_token = njs_parser_token(vm, parser); + if (nxt_slow_path(prop_token <= NJS_TOKEN_ILLEGAL)) { + return prop_token; } - name.start = NULL; + nxt_memzero(&name, sizeof(nxt_str_t)); + + switch (prop_token) { + + case NJS_TOKEN_CLOSE_BRACE: + goto done; - switch (token) { + case NJS_TOKEN_NUMBER: + case NJS_TOKEN_STRING: + case NJS_TOKEN_ESCAPE_STRING: + token = njs_parser_terminal(vm, parser, prop_token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } - case NJS_TOKEN_NAME: + property = parser->node; + break; + + default: + if (prop_token != NJS_TOKEN_NAME && !lexer->keyword) { + return NJS_TOKEN_ILLEGAL; + } + + property = njs_parser_node_string(vm, parser); + if (nxt_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; - - case NJS_TOKEN_NUMBER: - case NJS_TOKEN_STRING: - case NJS_TOKEN_ESCAPE_STRING: - token = njs_parser_terminal(vm, parser, token); - break; - - default: - return NJS_TOKEN_ILLEGAL; } - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } + switch (token) { - property = parser->node; + case NJS_TOKEN_COMMA: + case NJS_TOKEN_CLOSE_BRACE: - if (name.start != NULL - && (token == NJS_TOKEN_COMMA || token == NJS_TOKEN_CLOSE_BRACE) - && lexer->property_token != NJS_TOKEN_THIS - && lexer->property_token != NJS_TOKEN_GLOBAL_THIS) - { - expression = njs_parser_reference(vm, parser, lexer->property_token, - &name, hash, token_line); + 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 (nxt_slow_path(expression == NULL)) { return NJS_TOKEN_ERROR; } - } else { - token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); + break; + + case NJS_TOKEN_COLON: + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -564,6 +579,10 @@ njs_parser_object(njs_vm_t *vm, njs_pars } expression = parser->node; + break; + + default: + return NJS_TOKEN_ILLEGAL; } ret = njs_parser_object_property(vm, parser, obj, property, expression); @@ -580,6 +599,8 @@ njs_parser_object(njs_vm_t *vm, njs_pars } } +done: + parser->node = obj; return njs_parser_token(vm, parser); From bizbucaliyiz at hotmail.com Mon Jun 24 16:01:36 2019 From: bizbucaliyiz at hotmail.com (Osman Kuzucu) Date: Mon, 24 Jun 2019 16:01:36 +0000 Subject: Nginx Php7.2 update In-Reply-To: References: Message-ID: Hello everyone, As I was configuring a new web server today, I have realized that the latest nginx version (at least the one that is distributed by the Digital Ocean) does have outdated configuration line for the PHP 7.2 The configuration line specifies the fastcgi line as "fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;" which causes "502 Bad Gateway" errors, and if users are not careful about the issue, they might have hard time debugging it. I suggest we change the default installation configuration to " fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;" so that if a user installs Nginx and PHP7.2, they will automaticly be able to run PHP files without any problem. Please excuse me if this has been addressed before. I tried to find a way to push a change but I couldn't find a Github repo or something similar, so I am sending this e-mail. Osman Kuzucu -------------- next part -------------- An HTML attachment was scrubbed... URL: From teward at thomas-ward.net Mon Jun 24 16:16:51 2019 From: teward at thomas-ward.net (Thomas Ward) Date: Mon, 24 Jun 2019 12:16:51 -0400 Subject: Nginx Php7.2 update In-Reply-To: References: Message-ID: <60eef8c0-af93-677d-04ce-b2bd9e5ff839@thomas-ward.net> I don't think NGINX upstream provides this example you're referring to... Have you tested the upstream version?? (I could have SWORN there was a bug on this in Ubuntu [1], but it was NACK'd for stable-release-updating because it's not severe enough to warrant an SRU). Thomas [1]: https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1831748 On 6/24/19 12:01 PM, Osman Kuzucu wrote: > Hello everyone, > > As I was configuring a new web server today, I have realized that the > latest nginx version (at least the one that is distributed by the > Digital Ocean) does have outdated configuration line for the PHP 7.2 > > The configuration line specifies the fastcgi line as "fastcgi_pass > unix:/var/run/php/php7.0-fpm.sock;" which causes "502 Bad Gateway" > errors, and if users are not careful about the issue, they might have > hard time debugging it.? > > I suggest we change the default installation configuration to " > fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;" so that if a user > installs Nginx and PHP7.2, they will automaticly be able to run PHP > files without any problem. > > Please excuse me if this has been addressed before. I tried to find a > way to push a change but I couldn't find a Github repo or something > similar, so I am sending this e-mail.? > > Osman Kuzucu > > _______________________________________________ > 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 teward at thomas-ward.net Mon Jun 24 16:26:07 2019 From: teward at thomas-ward.net (Thomas Ward) Date: Mon, 24 Jun 2019 12:26:07 -0400 Subject: Nginx Php7.2 update In-Reply-To: <60eef8c0-af93-677d-04ce-b2bd9e5ff839@thomas-ward.net> References: <60eef8c0-af93-677d-04ce-b2bd9e5ff839@thomas-ward.net> Message-ID: Oops, I left original poster off my reply... heh. (Reattaching them here for a reply-all) Thomas On 6/24/19 12:16 PM, Thomas Ward wrote: > > I don't think NGINX upstream provides this example you're referring to... > > > Have you tested the upstream version and verified that this stanza is > present there?? (I could have SWORN there was a bug on this in Ubuntu > [1], but it was NACK'd for stable-release-updating because it's not > severe enough to warrant an SRU). > > > Thomas > > > [1]: https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1831748 > > > > > On 6/24/19 12:01 PM, Osman Kuzucu wrote: >> Hello everyone, >> >> As I was configuring a new web server today, I have realized that the >> latest nginx version (at least the one that is distributed by the >> Digital Ocean) does have outdated configuration line for the PHP 7.2 >> >> The configuration line specifies the fastcgi line as "fastcgi_pass >> unix:/var/run/php/php7.0-fpm.sock;" which causes "502 Bad Gateway" >> errors, and if users are not careful about the issue, they might have >> hard time debugging it.? >> >> I suggest we change the default installation configuration to " >> fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;" so that if a user >> installs Nginx and PHP7.2, they will automaticly be able to run PHP >> files without any problem. >> >> Please excuse me if this has been addressed before. I tried to find a >> way to push a change but I couldn't find a Github repo or something >> similar, so I am sending this e-mail.? >> >> Osman Kuzucu >> >> _______________________________________________ >> 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: From bizbucaliyiz at hotmail.com Mon Jun 24 20:08:46 2019 From: bizbucaliyiz at hotmail.com (Osman Kuzucu) Date: Mon, 24 Jun 2019 20:08:46 +0000 Subject: Ynt: Nginx Php7.2 update In-Reply-To: References: <60eef8c0-af93-677d-04ce-b2bd9e5ff839@thomas-ward.net>, Message-ID: Hello, As I said I am new to the Nginx dev world, and didn't even know there was such website which I could keep track of the issues & additions & removals. What you have shared there is the exact thing I was mentioning. I honestly didn't tested the upstream version. What I did was pretty simple, create a fresh Ubuntu 18.04 x64 droplet from the Digital Ocean. After initial SSH access, use the command "sudo apt update", then "sudo apt upgrade" and finally "sudo apt install nginx". That command order installed the nginx with the default php7.0 setting and not with the php7.2. ________________________________ G?nderen: Thomas Ward G?nderildi: 24 Haziran 2019 Pazartesi 19:26 Kime: nginx-devel at nginx.org; bizbucaliyiz at hotmail.com Konu: Re: Nginx Php7.2 update Oops, I left original poster off my reply... heh. (Reattaching them here for a reply-all) Thomas On 6/24/19 12:16 PM, Thomas Ward wrote: I don't think NGINX upstream provides this example you're referring to... Have you tested the upstream version and verified that this stanza is present there? (I could have SWORN there was a bug on this in Ubuntu [1], but it was NACK'd for stable-release-updating because it's not severe enough to warrant an SRU). Thomas [1]: https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1831748 On 6/24/19 12:01 PM, Osman Kuzucu wrote: Hello everyone, As I was configuring a new web server today, I have realized that the latest nginx version (at least the one that is distributed by the Digital Ocean) does have outdated configuration line for the PHP 7.2 The configuration line specifies the fastcgi line as "fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;" which causes "502 Bad Gateway" errors, and if users are not careful about the issue, they might have hard time debugging it. I suggest we change the default installation configuration to " fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;" so that if a user installs Nginx and PHP7.2, they will automaticly be able to run PHP files without any problem. Please excuse me if this has been addressed before. I tried to find a way to push a change but I couldn't find a Github repo or something similar, so I am sending this e-mail. Osman Kuzucu _______________________________________________ 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: From teward at thomas-ward.net Mon Jun 24 20:29:28 2019 From: teward at thomas-ward.net (Thomas Ward) Date: Mon, 24 Jun 2019 16:29:28 -0400 Subject: Ynt: Nginx Php7.2 update In-Reply-To: References: <60eef8c0-af93-677d-04ce-b2bd9e5ff839@thomas-ward.net> Message-ID: <659b8a93-9edb-6fd7-47a7-190c47d870ca@thomas-ward.net> Fun Fact: I'm the downstream NGINX package maintainer in Ubuntu ;) THIS SAID, 'changing' the documentation at this point would have to be bundled with a more important fix in Ubuntu to fix that.? "Example Documentation" changes alone aren't enough to get it updated in an already-released release. This said... the "default" example in that package isn't exactly designed to be a "it will just work" all in one solution for PHP, it's designed as **guidance** not as explicit "confirmed to instantly work when you uncomment it" stuff.? Part of that's just because the packages don't move all at the same speed, and part of that is because you really should be learning to handle your own configurations independently from the defaults which can change or get overwritten or any number of other things. This said, discussing downstream packaging differences vs. NGINX upstream here is not the discussion topic for nginx-devel.? You can refer to the bug I linked already if you wish to continue this argument there. Thomas On 6/24/19 4:08 PM, Osman Kuzucu wrote: > Hello, > > As I said I am new to the Nginx dev world, and didn't even know there > was such website which I could keep track of the issues & additions & > removals.? > > What you have shared there is the exact thing I was mentioning. I > honestly didn't tested the upstream version. > > What I did was pretty simple, create a fresh Ubuntu 18.04 x64 ?droplet > from the Digital Ocean. After initial SSH access, use the command > "sudo apt update", then "sudo apt upgrade" and finally "sudo apt > install nginx". That command order installed the nginx with the > default php7.0 setting and not with the php7.2. > > > > ------------------------------------------------------------------------ > *G?nderen:* Thomas Ward > *G?nderildi:* 24 Haziran 2019 Pazartesi 19:26 > *Kime:* nginx-devel at nginx.org; bizbucaliyiz at hotmail.com > *Konu:* Re: Nginx Php7.2 update > ? > > Oops, I left original poster off my reply... heh. > > > (Reattaching them here for a reply-all) > > > > Thomas > > > > On 6/24/19 12:16 PM, Thomas Ward wrote: >> >> I don't think NGINX upstream provides this example you're referring to... >> >> >> Have you tested the upstream version and verified that this stanza is >> present there?? (I could have SWORN there was a bug on this in Ubuntu >> [1], but it was NACK'd for stable-release-updating because it's not >> severe enough to warrant an SRU). >> >> >> Thomas >> >> >> [1]: https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1831748 >> >> >> >> >> On 6/24/19 12:01 PM, Osman Kuzucu wrote: >>> Hello everyone, >>> >>> As I was configuring a new web server today, I have realized that >>> the latest nginx version (at least the one that is distributed by >>> the Digital Ocean) does have outdated configuration line for the PHP 7.2 >>> >>> The configuration line specifies the fastcgi line as "fastcgi_pass >>> unix:/var/run/php/php7.0-fpm.sock;" which causes "502 Bad Gateway" >>> errors, and if users are not careful about the issue, they might >>> have hard time debugging it.? >>> >>> I suggest we change the default installation configuration to " >>> fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;" so that if a user >>> installs Nginx and PHP7.2, they will automaticly be able to run PHP >>> files without any problem. >>> >>> Please excuse me if this has been addressed before. I tried to find >>> a way to push a change but I couldn't find a Github repo or >>> something similar, so I am sending this e-mail.? >>> >>> Osman Kuzucu >>> >>> _______________________________________________ >>> 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon Jun 24 23:37:30 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 Jun 2019 23:37:30 +0000 Subject: [njs] Fixed parseInt('-0'). Message-ID: details: https://hg.nginx.org/njs/rev/56dee6c2ad95 branches: changeset: 1014:56dee6c2ad95 user: Artem S. Povalyukhin date: Sat Jun 22 23:35:52 2019 +0300 description: Fixed parseInt('-0'). diffstat: njs/njs_number.c | 3 ++- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletions(-) diffs (26 lines): diff -r df8d48ea3875 -r 56dee6c2ad95 njs/njs_number.c --- a/njs/njs_number.c Thu Jun 20 15:20:34 2019 +0300 +++ b/njs/njs_number.c Sat Jun 22 23:35:52 2019 +0300 @@ -802,7 +802,8 @@ njs_number_parse_int(njs_vm_t *vm, njs_v n = njs_number_radix_parse(&p, end, radix); if (n >= 0) { - num = minus ? -n : n; + num = n; + num = minus ? -num : num; } } diff -r df8d48ea3875 -r 56dee6c2ad95 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Jun 20 15:20:34 2019 +0300 +++ b/njs/test/njs_unit_test.c Sat Jun 22 23:35:52 2019 +0300 @@ -11744,6 +11744,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("parseInt('0', 37)"), nxt_string("NaN") }, + { nxt_string("1/parseInt('-0')"), + nxt_string("-Infinity") }, + { nxt_string("parseFloat.name"), nxt_string("parseFloat") }, From xeioex at nginx.com Mon Jun 24 23:37:30 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 Jun 2019 23:37:30 +0000 Subject: [njs] Added signed zero support in njs.dump(). Message-ID: details: https://hg.nginx.org/njs/rev/892680a2eae0 branches: changeset: 1015:892680a2eae0 user: Artem S. Povalyukhin date: Tue Jun 25 00:06:12 2019 +0300 description: Added signed zero support in njs.dump(). This closes #184 issue on Github. diffstat: njs/njs_json.c | 18 ++++++++++++++++++ njs/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diffs (54 lines): diff -r 56dee6c2ad95 -r 892680a2eae0 njs/njs_json.c --- a/njs/njs_json.c Sat Jun 22 23:35:52 2019 +0300 +++ b/njs/njs_json.c Tue Jun 25 00:06:12 2019 +0300 @@ -2166,6 +2166,14 @@ njs_dump_value(njs_json_stringify_t *str case NJS_OBJECT_NUMBER: value = &value->data.u.object_value->value; + if (nxt_slow_path(value->data.u.number == 0.0 + && signbit(value->data.u.number))) + { + + njs_dump("[Number: -0]"); + break; + } + ret = njs_number_to_string(stringify->vm, &str_val, value); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; @@ -2273,6 +2281,16 @@ njs_dump_value(njs_json_stringify_t *str return njs_json_buf_append(stringify, "]}", 2); case NJS_NUMBER: + if (nxt_slow_path(value->data.u.number == 0.0 + && signbit(value->data.u.number))) + { + + njs_dump("-0"); + break; + } + + /* Fall through. */ + case NJS_REGEXP: case NJS_DATE: case NJS_OBJECT_ERROR: diff -r 56dee6c2ad95 -r 892680a2eae0 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat Jun 22 23:35:52 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue Jun 25 00:06:12 2019 +0300 @@ -12470,6 +12470,15 @@ static njs_unit_test_t njs_test[] = { nxt_string("njs.dump(njs) == `{version:'${njs.version}'}`"), nxt_string("true") }, + { nxt_string("njs.dump(-0)"), + nxt_string("-0") }, + + { nxt_string("njs.dump(Object(-0))"), + nxt_string("[Number: -0]") }, + + { nxt_string("njs.dump([0, -0])"), + nxt_string("[0,-0]") }, + /* Built-in methods name. */ { nxt_string( From mdounin at mdounin.ru Tue Jun 25 02:19:38 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 Jun 2019 02:19:38 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: https://hg.nginx.org/nginx/rev/e314532b7dbe branches: changeset: 7517:e314532b7dbe 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 xeioex at nginx.com Tue Jun 25 11:45:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 25 Jun 2019 11:45:16 +0000 Subject: [njs] Version 0.3.3. Message-ID: details: https://hg.nginx.org/njs/rev/c65a4be9867d branches: changeset: 1016:c65a4be9867d user: Dmitry Volyntsev date: Tue Jun 25 14:43:56 2019 +0300 description: Version 0.3.3. diffstat: CHANGES | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) diffs (67 lines): diff -r 892680a2eae0 -r c65a4be9867d CHANGES --- a/CHANGES Tue Jun 25 00:06:12 2019 +0300 +++ b/CHANGES Tue Jun 25 14:43:56 2019 +0300 @@ -1,3 +1,63 @@ + +Changes with njs 0.3.3 25 Jun 2019 + + nginx modules: + + *) Improvement: getting of special response headers in headersOut. + + *) Improvement: working with unknown methods in subrequest(). + + *) Improvement: added support for null as a second argument + of r.subrequest(). + + *) Bugfix: fixed processing empty output chain in stream body filter. + + Core: + *) Feature: added runtime support for property getter/setter. + Thanks to ??? (Hong Zhi Dao) and Artem S. Povalyukhin. + + *) Feature: added "process" global object. + + *) Feature: writable most of built-in properties and methods. + + *) Feature: added generic implementation of Array.prototype.fill(). + + *) Bugfix: fixed integer-overflow in String.prototype.concat(). + + *) Bugfix: fixed setting of object properties. + + *) Bugfix: fixed Array.prototype.toString(). + + *) Bugfix: fixed Date.prototype.toJSON(). + + *) Bugfix: fixed overwriting "constructor" property of built-in + prototypes. + + *) Bugfix: fixed processing of invalid surrogate pairs in strings. + + *) Bugfix: fixed processing of invalid surrogate pairs in JSON + strings. + + *) Bugfix: fixed heap-buffer-overflow in toUpperCase() and + toLowerCase(). + + *) Bugfix: fixed escaping lone closing square brackets in RegExp() + constructor. + + *) Bugfix: fixed String.prototype.toBytes() for ASCII strings. + + *) Bugfix: fixed handling zero byte characters inside RegExp + pattern strings. + + *) Bugfix: fixed String.prototype.toBytes() for ASCII strings. + + *) Bugfix: fixed truth value of JSON numbers in JSON.parse(). + + *) Bugfix: fixed use-of-uninitialized-value in + njs_string_replace_join(). + + *) Bugfix: fixed parseInt('-0'). + Thanks to Artem S. Povalyukhin. Changes with njs 0.3.2 21 May 2019 From xeioex at nginx.com Tue Jun 25 11:45:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 25 Jun 2019 11:45:17 +0000 Subject: [njs] Added tag 0.3.3 for changeset c65a4be9867d Message-ID: details: https://hg.nginx.org/njs/rev/63cd8e6679ba branches: changeset: 1017:63cd8e6679ba user: Dmitry Volyntsev date: Tue Jun 25 14:44:55 2019 +0300 description: Added tag 0.3.3 for changeset c65a4be9867d diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r c65a4be9867d -r 63cd8e6679ba .hgtags --- a/.hgtags Tue Jun 25 14:43:56 2019 +0300 +++ b/.hgtags Tue Jun 25 14:44:55 2019 +0300 @@ -26,3 +26,4 @@ ee190d3ace005f8eb063d4763b578f44d3028c68 1935ab4643fdaec5b4a8c36070f4d2cb8e3799d7 0.3.0 ebfbdb8d8fe2f640d880359575657cb53e38328f 0.3.1 82101d50fff6e4c7a92c0542a3d6026ff7e462fb 0.3.2 +c65a4be9867d434ca449a18d868305d5dcd5b91b 0.3.3 From mdounin at mdounin.ru Tue Jun 25 12:24:24 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 Jun 2019 12:24:24 +0000 Subject: [nginx] nginx-1.17.1-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/7816bd7dabf6 branches: changeset: 7518:7816bd7dabf6 user: Maxim Dounin date: Tue Jun 25 15:19:45 2019 +0300 description: nginx-1.17.1-RELEASE diffstat: docs/xml/nginx/changes.xml | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diffs (66 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,62 @@ + + + + +????????? limit_req_dry_run. + + +the "limit_req_dry_run" directive. + + + + + +??? ????????????? ????????? hash ? ????? upstream +?????? ???? ??????????? ?????? ???????? ? ???????????? +?? round-robin ????????????.
+??????? Niklas Keller. +
+ +when using the "hash" directive inside the "upstream" block +an empty hash key now triggers round-robin balancing.
+Thanks to Niklas Keller. +
+
+ + + +? ??????? ???????? ??? ????????? segmentation fault, +???? ?????????????? ??????????? ? ????????? image_filter, +? ?????? ? ????? 415 ???????????????? ? ?????? ????????? error_page; +?????? ????????? ? 1.11.10. + + +a segmentation fault might occur in a worker process +if caching was used along with the "image_filter" directive, +and errors with code 415 were redirected with the "error_page" directive; +the bug had appeared in 1.11.10. + + + + + +? ??????? ???????? ??? ????????? segmentation fault, +???? ????????????? ?????????? ????; +?????? ????????? ? 1.7.3. + + +a segmentation fault might occur in a worker process +if embedded perl was used; +the bug had appeared in 1.7.3. + + + +
+ + From mdounin at mdounin.ru Tue Jun 25 12:24:26 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 Jun 2019 12:24:26 +0000 Subject: [nginx] release-1.17.1 tag Message-ID: details: https://hg.nginx.org/nginx/rev/35ea9229c71a branches: changeset: 7519:35ea9229c71a user: Maxim Dounin date: Tue Jun 25 15:19:45 2019 +0300 description: release-1.17.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 054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0 +7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1 From michael.wuertinger at egym.com Wed Jun 26 17:41:27 2019 From: michael.wuertinger at egym.com (=?UTF-8?Q?Michael_W=C3=BCrtinger?=) Date: Wed, 26 Jun 2019 19:41:27 +0200 Subject: HTTP/2: allow unlimited number of requests in connection Message-ID: Hello, we're running a gRPC service behind an NGINX load balancer and we often see that the connection gets shut down with a GOAWAY message. Since our request deadlines are quite small and it takes some time to re-establish a connection this often leads to many failed requests. After analyzing the situation we realized that it is caused by the "http2_max_requests" option which defaults to 1000. After setting this to a ridiculously high value our problems disappeared. While there probably are use cases where limiting the life time of a connection makes sense we were wondering why it is not possible to disable this functionality and let a connection just live as long as possible? The following patch allows to do just that by setting http2_max_requests to 0. Please let me know what you think. Thanks, Michael # HG changeset patch # User Michael W?rtinger # Date 1561569724 -7200 # Wed Jun 26 19:22:04 2019 +0200 # Node ID d703d79897320bfc743b2ea6421e301985b2c7e4 # Parent 35ea9229c71a9207a24e51f327e1749e3accb26c HTTP/2: allow unlimited number of requests in connection Allows to disable the "http2_max_requests" limit by setting it to 0. This enables very long living HTTP/2 connections which is desirable for some use cases like gRPC connections. diff -r 35ea9229c71a -r d703d7989732 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Tue Jun 25 15:19:45 2019 +0300 +++ b/src/http/v2/ngx_http_v2.c Wed Jun 26 19:22:04 2019 +0200 @@ -1173,7 +1173,9 @@ ngx_http_v2_set_dependency(h2c, node, depend, excl); } - if (h2c->connection->requests >= h2scf->max_requests) { + if (h2scf->max_requests > 0 + && h2c->connection->requests >= h2scf->max_requests) + { h2c->goaway = 1; if (ngx_http_v2_send_goaway(h2c, NGX_HTTP_V2_NO_ERROR) == NGX_ERROR) { @@ -4514,7 +4516,7 @@ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, ngx_http_v2_module); - if (h2c->idle++ > 10 * h2scf->max_requests) { + if (h2c->idle++ > 10 * h2scf->max_requests && h2scf->max_requests > 0) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "http2 flood detected"); ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); -- From careygister at outlook.com Thu Jun 27 02:01:27 2019 From: careygister at outlook.com (Carey Gister) Date: Thu, 27 Jun 2019 02:01:27 +0000 Subject: Bug in ngx_http_slice_filter_module ngx_http_slice_parse_content_range function Message-ID: The ngx_http_slice_parse_content_range function assumes that the parsed buffer is null terminated. Since the buffer is an ngx_str_t, that assumption is false. If, by chance, the buffer is null terminated it is simply a matter of luck, and not design. In particular, if the headers_out.content_range ngx_str_t was allocated in the ngx_http_range_filter_module then the buffer was allocated as a non-zero terminated buffer by ngx_pnalloc. The fact that the buffer is not null terminated may lead to ngx_http_slice_parse_content_range returning an NGX_ERROR code after the buffer was successfully parsed, or, if the caller is unfortunate, leading to a random memory access failure. I've written a replacement function that uses the length of the ngx_str_t as a guard condition. This code works and passes all of the unit tests. How should I submit the replacement? Carey Gister 415-310-5304 -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Thu Jun 27 15:56:21 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 27 Jun 2019 15:56:21 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/0119e834a202 branches: changeset: 1018:0119e834a202 user: Valentin Bartenev date: Thu Jun 27 18:54:21 2019 +0300 description: Version bump. diffstat: njs/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 63cd8e6679ba -r 0119e834a202 njs/njs.h --- a/njs/njs.h Tue Jun 25 14:44:55 2019 +0300 +++ b/njs/njs.h Thu Jun 27 18:54:21 2019 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.3" +#define NJS_VERSION "0.3.4" #include From vbart at nginx.com Thu Jun 27 15:56:22 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 27 Jun 2019 15:56:22 +0000 Subject: [njs] Removed unused nalloc parameter from lvlhsh allocation functions. Message-ID: details: https://hg.nginx.org/njs/rev/9db5e400480c branches: changeset: 1019:9db5e400480c user: Valentin Bartenev date: Thu Jun 27 18:55:34 2019 +0300 description: Removed unused nalloc parameter from lvlhsh allocation functions. diffstat: njs/njs_event.c | 1 - njs/njs_extern.c | 2 -- njs/njs_lexer_keyword.c | 1 - njs/njs_module.c | 1 - njs/njs_object.c | 1 - njs/njs_shell.c | 5 ++--- njs/njs_string.c | 1 - njs/njs_variable.c | 2 -- njs/njs_vm.c | 2 +- njs/njs_vm.h | 2 +- njs/test/njs_unit_test.c | 3 +-- nxt/nxt_lvlhsh.c | 5 ++--- nxt/nxt_lvlhsh.h | 6 +----- nxt/test/lvlhsh_unit_test.c | 3 +-- 14 files changed, 9 insertions(+), 26 deletions(-) diffs (252 lines): diff -r 0119e834a202 -r 9db5e400480c njs/njs_event.c --- a/njs/njs_event.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_event.c Thu Jun 27 18:55:34 2019 +0300 @@ -15,7 +15,6 @@ const nxt_lvlhsh_proto_t njs_event_hash nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_event_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_extern.c --- a/njs/njs_extern.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_extern.c Thu Jun 27 18:55:34 2019 +0300 @@ -50,7 +50,6 @@ const nxt_lvlhsh_proto_t njs_extern_has nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - NXT_LVLHSH_BATCH_ALLOC, njs_extern_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, @@ -61,7 +60,6 @@ const nxt_lvlhsh_proto_t njs_extern_val nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - NXT_LVLHSH_BATCH_ALLOC, njs_extern_value_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_lexer_keyword.c Thu Jun 27 18:55:34 2019 +0300 @@ -138,7 +138,6 @@ const nxt_lvlhsh_proto_t njs_keyword_ha nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_keyword_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_module.c --- a/njs/njs_module.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_module.c Thu Jun 27 18:55:34 2019 +0300 @@ -415,7 +415,6 @@ const nxt_lvlhsh_proto_t njs_modules_ha nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_module_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_object.c --- a/njs/njs_object.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_object.c Thu Jun 27 18:55:34 2019 +0300 @@ -149,7 +149,6 @@ const nxt_lvlhsh_proto_t njs_object_has nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_object_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_shell.c --- a/njs/njs_shell.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_shell.c Thu Jun 27 18:55:34 2019 +0300 @@ -107,7 +107,7 @@ static void njs_console_clear_timer(njs_ njs_host_event_t event); static nxt_int_t lvlhsh_key_test(nxt_lvlhsh_query_t *lhq, void *data); -static void *lvlhsh_pool_alloc(void *pool, size_t size, nxt_uint_t nalloc); +static void *lvlhsh_pool_alloc(void *pool, size_t size); static void lvlhsh_pool_free(void *pool, void *p, size_t size); @@ -192,7 +192,6 @@ static njs_external_t njs_externals[] = static const nxt_lvlhsh_proto_t lvlhsh_proto nxt_aligned(64) = { NXT_LVLHSH_LARGE_SLAB, - 0, lvlhsh_key_test, lvlhsh_pool_alloc, lvlhsh_pool_free, @@ -1227,7 +1226,7 @@ lvlhsh_key_test(nxt_lvlhsh_query_t *lhq, static void * -lvlhsh_pool_alloc(void *pool, size_t size, nxt_uint_t nalloc) +lvlhsh_pool_alloc(void *pool, size_t size) { return nxt_mp_align(pool, size, size); } diff -r 0119e834a202 -r 9db5e400480c njs/njs_string.c --- a/njs/njs_string.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_string.c Thu Jun 27 18:55:34 2019 +0300 @@ -4591,7 +4591,6 @@ static const nxt_lvlhsh_proto_t njs_val nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_values_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_variable.c --- a/njs/njs_variable.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_variable.c Thu Jun 27 18:55:34 2019 +0300 @@ -37,7 +37,6 @@ const nxt_lvlhsh_proto_t njs_variables_ nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_variables_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, @@ -232,7 +231,6 @@ const nxt_lvlhsh_proto_t njs_references nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, - 0, njs_reference_hash_test, njs_lvlhsh_alloc, njs_lvlhsh_free, diff -r 0119e834a202 -r 9db5e400480c njs/njs_vm.c --- a/njs/njs_vm.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_vm.c Thu Jun 27 18:55:34 2019 +0300 @@ -3672,7 +3672,7 @@ njs_debug(njs_index_t index, njs_value_t void * -njs_lvlhsh_alloc(void *data, size_t size, nxt_uint_t nalloc) +njs_lvlhsh_alloc(void *data, size_t size) { return nxt_mp_align(data, size, size); } diff -r 0119e834a202 -r 9db5e400480c njs/njs_vm.h --- a/njs/njs_vm.h Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/njs_vm.h Thu Jun 27 18:55:34 2019 +0300 @@ -1339,7 +1339,7 @@ nxt_int_t njs_builtin_match_native_funct nxt_array_t *njs_vm_backtrace(njs_vm_t *vm); -void *njs_lvlhsh_alloc(void *data, size_t size, nxt_uint_t nalloc); +void *njs_lvlhsh_alloc(void *data, size_t size); void njs_lvlhsh_free(void *data, void *p, size_t size); njs_array_t * njs_value_enumerate(njs_vm_t *vm, const njs_value_t *value, diff -r 0119e834a202 -r 9db5e400480c njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Jun 27 18:54:21 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Jun 27 18:55:34 2019 +0300 @@ -13116,7 +13116,7 @@ lvlhsh_unit_test_key_test(nxt_lvlhsh_que static void * -lvlhsh_unit_test_pool_alloc(void *pool, size_t size, nxt_uint_t nalloc) +lvlhsh_unit_test_pool_alloc(void *pool, size_t size) { return nxt_mp_align(pool, size, size); } @@ -13131,7 +13131,6 @@ lvlhsh_unit_test_pool_free(void *pool, v static const nxt_lvlhsh_proto_t lvlhsh_proto nxt_aligned(64) = { NXT_LVLHSH_LARGE_SLAB, - 0, lvlhsh_unit_test_key_test, lvlhsh_unit_test_pool_alloc, lvlhsh_unit_test_pool_free, diff -r 0119e834a202 -r 9db5e400480c nxt/nxt_lvlhsh.c --- a/nxt/nxt_lvlhsh.c Thu Jun 27 18:54:21 2019 +0300 +++ b/nxt/nxt_lvlhsh.c Thu Jun 27 18:55:34 2019 +0300 @@ -285,8 +285,7 @@ nxt_lvlhsh_new_bucket(nxt_lvlhsh_query_t { uint32_t *bucket; - bucket = lhq->proto->alloc(lhq->pool, nxt_lvlhsh_bucket_size(lhq->proto), - lhq->proto->nalloc); + bucket = lhq->proto->alloc(lhq->pool, nxt_lvlhsh_bucket_size(lhq->proto)); if (nxt_fast_path(bucket != NULL)) { @@ -459,7 +458,7 @@ nxt_lvlhsh_convert_bucket_to_level(nxt_l proto = lhq->proto; size = nxt_lvlhsh_level_size(proto, nlvl); - lvl = proto->alloc(lhq->pool, size * (sizeof(void *)), proto->nalloc); + lvl = proto->alloc(lhq->pool, size * (sizeof(void *))); if (nxt_slow_path(lvl == NULL)) { return NXT_ERROR; diff -r 0119e834a202 -r 9db5e400480c nxt/nxt_lvlhsh.h --- a/nxt/nxt_lvlhsh.h Thu Jun 27 18:54:21 2019 +0300 +++ b/nxt/nxt_lvlhsh.h Thu Jun 27 18:55:34 2019 +0300 @@ -11,7 +11,7 @@ typedef struct nxt_lvlhsh_query_s nxt_lvlhsh_query_t; typedef nxt_int_t (*nxt_lvlhsh_test_t)(nxt_lvlhsh_query_t *lhq, void *data); -typedef void *(*nxt_lvlhsh_alloc_t)(void *ctx, size_t size, nxt_uint_t nalloc); +typedef void *(*nxt_lvlhsh_alloc_t)(void *ctx, size_t size); typedef void (*nxt_lvlhsh_free_t)(void *ctx, void *p, size_t size); @@ -19,7 +19,6 @@ typedef void (*nxt_lvlhsh_free_t)(void * #define NXT_LVLHSH_DEFAULT_BUCKET_SIZE 128 #define NXT_LVLHSH_ENTRY_SIZE 3 -#define NXT_LVLHSH_BATCH_ALLOC 16 /* 3 is shift of 64-bit pointer. */ #define NXT_LVLHSH_MEMALIGN_SHIFT (NXT_MAX_MEMALIGN_SHIFT - 3) @@ -28,7 +27,6 @@ typedef void (*nxt_lvlhsh_free_t)(void * #define NXT_LVLHSH_DEFAULT_BUCKET_SIZE 64 #define NXT_LVLHSH_ENTRY_SIZE 2 -#define NXT_LVLHSH_BATCH_ALLOC 8 /* 2 is shift of 32-bit pointer. */ #define NXT_LVLHSH_MEMALIGN_SHIFT (NXT_MAX_MEMALIGN_SHIFT - 2) @@ -73,7 +71,6 @@ typedef struct { uint32_t bucket_size; uint32_t bucket_mask; uint8_t shift[8]; - uint32_t nalloc; nxt_lvlhsh_test_t test; nxt_lvlhsh_alloc_t alloc; @@ -88,7 +85,6 @@ typedef struct { /* The maximum allowed aligned shift. */ uint32_t max_shift; - uint32_t nalloc; } nxt_lvlhsh_ctx_t; diff -r 0119e834a202 -r 9db5e400480c nxt/test/lvlhsh_unit_test.c --- a/nxt/test/lvlhsh_unit_test.c Thu Jun 27 18:54:21 2019 +0300 +++ b/nxt/test/lvlhsh_unit_test.c Thu Jun 27 18:55:34 2019 +0300 @@ -29,7 +29,7 @@ lvlhsh_unit_test_key_test(nxt_lvlhsh_que static void * -lvlhsh_unit_test_pool_alloc(void *pool, size_t size, nxt_uint_t nalloc) +lvlhsh_unit_test_pool_alloc(void *pool, size_t size) { return nxt_mp_align(pool, size, size); } @@ -44,7 +44,6 @@ lvlhsh_unit_test_pool_free(void *pool, v static const nxt_lvlhsh_proto_t lvlhsh_proto nxt_aligned(64) = { NXT_LVLHSH_LARGE_SLAB, - 0, lvlhsh_unit_test_key_test, lvlhsh_unit_test_pool_alloc, lvlhsh_unit_test_pool_free, From vbart at nginx.com Thu Jun 27 15:56:22 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 27 Jun 2019 15:56:22 +0000 Subject: [njs] Removed unused nxt_lvlhsh_ctx_t structure. Message-ID: details: https://hg.nginx.org/njs/rev/40f26bb516a6 branches: changeset: 1020:40f26bb516a6 user: Valentin Bartenev date: Thu Jun 27 18:55:34 2019 +0300 description: Removed unused nxt_lvlhsh_ctx_t structure. diffstat: nxt/nxt_lvlhsh.h | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diffs (20 lines): diff -r 9db5e400480c -r 40f26bb516a6 nxt/nxt_lvlhsh.h --- a/nxt/nxt_lvlhsh.h Thu Jun 27 18:55:34 2019 +0300 +++ b/nxt/nxt_lvlhsh.h Thu Jun 27 18:55:34 2019 +0300 @@ -79,16 +79,6 @@ typedef struct { typedef struct { - nxt_lvlhsh_test_t test; - nxt_lvlhsh_alloc_t alloc; - nxt_lvlhsh_free_t free; - - /* The maximum allowed aligned shift. */ - uint32_t max_shift; -} nxt_lvlhsh_ctx_t; - - -typedef struct { void *slot; } nxt_lvlhsh_t; From peter.bittner at gmx.net Thu Jun 27 17:12:51 2019 From: peter.bittner at gmx.net (Peter Bittner) Date: Thu, 27 Jun 2019 19:12:51 +0200 Subject: Default log file locations Message-ID: Hi there! In my day job I'm helping to get applications from traditional environments running in cloud environments. Cloud native applications are just "normal" applications, but there are a few properties that they should satisfy (apart from resiliency and scalability). For logging this boils down to what is prescribed by the 12-factor app: The log output should be a continuous stream, i.e. simply log to the terminal. Now, as of today, at least on Debian based container images, the behavior of Nginx is to write to /var/log/nginx/access.log and /var/log/nginx/error.log by default. We try to compensate this by making those files symbolic links to /dev/stdout and /dev/stderr. We're doing this also, because there seem to be cases when a log entry is written _before_ it is configured via the Nginx configuration file. >From my perspective it would be advantageous to have Nginx write to the terminal by default (i.e. no hardcoded log file locations) and allow to override this behavior via the Nginx configuration file. Is there any reason why the default behavior is not that way yet? Peter From vbart at nginx.com Thu Jun 27 17:35:00 2019 From: vbart at nginx.com (Valentin V. Bartenev) Date: Thu, 27 Jun 2019 20:35 +0300 Subject: Default log file locations In-Reply-To: References: Message-ID: <3190464.RldmLnIc5k@vbart-workstation> On Thursday 27 June 2019 19:12:51 Peter Bittner wrote: > Hi there! > > In my day job I'm helping to get applications from traditional > environments running in cloud environments. Cloud native applications > are just "normal" applications, but there are a few properties that > they should satisfy (apart from resiliency and scalability). > > For logging this boils down to what is prescribed by the 12-factor > app: The log output should be a continuous stream, i.e. simply log to > the terminal. > > Now, as of today, at least on Debian based container images, the > behavior of Nginx is to write to /var/log/nginx/access.log and > /var/log/nginx/error.log by default. We try to compensate this by > making those files symbolic links to /dev/stdout and /dev/stderr. > We're doing this also, because there seem to be cases when a log entry > is written _before_ it is configured via the Nginx configuration file. > > From my perspective it would be advantageous to have Nginx write to > the terminal by default (i.e. no hardcoded log file locations) and > allow to override this behavior via the Nginx configuration file. > > Is there any reason why the default behavior is not that way yet? [..] Afaik, there's no way in Linux systems to write to terminal in non-blocking manner. As the result, writing log can block the whole nginx worker process and cause DoS. IMHO, it's not a good idea to make your web-application depend on logging capabilities. wbr, Valentin V. Bartenev From peter.bittner at gmx.net Thu Jun 27 17:44:22 2019 From: peter.bittner at gmx.net (Peter Bittner) Date: Thu, 27 Jun 2019 19:44:22 +0200 Subject: Default log file locations In-Reply-To: <3190464.RldmLnIc5k@vbart-workstation> References: <3190464.RldmLnIc5k@vbart-workstation> Message-ID: I may be a bit ignorant about system-level operations, I apologize. Can you explain why this works better with writing to a file (i.e. the hardcoded location /var/log/nginx/*.log)? Peter On Thu 27 June 2019 19:35 Valentin V. Bartenev wrote: > > On Thursday 27 June 2019 19:12:51 Peter Bittner wrote: > > Hi there! > > > > In my day job I'm helping to get applications from traditional > > environments running in cloud environments. Cloud native applications > > are just "normal" applications, but there are a few properties that > > they should satisfy (apart from resiliency and scalability). > > > > For logging this boils down to what is prescribed by the 12-factor > > app: The log output should be a continuous stream, i.e. simply log to > > the terminal. > > > > Now, as of today, at least on Debian based container images, the > > behavior of Nginx is to write to /var/log/nginx/access.log and > > /var/log/nginx/error.log by default. We try to compensate this by > > making those files symbolic links to /dev/stdout and /dev/stderr. > > We're doing this also, because there seem to be cases when a log entry > > is written _before_ it is configured via the Nginx configuration file. > > > > From my perspective it would be advantageous to have Nginx write to > > the terminal by default (i.e. no hardcoded log file locations) and > > allow to override this behavior via the Nginx configuration file. > > > > Is there any reason why the default behavior is not that way yet? > [..] > > Afaik, there's no way in Linux systems to write to terminal in > non-blocking manner. As the result, writing log can block the > whole nginx worker process and cause DoS. > > IMHO, it's not a good idea to make your web-application depend > on logging capabilities. > > wbr, Valentin V. Bartenev From vbart at nginx.com Thu Jun 27 18:19:45 2019 From: vbart at nginx.com (Valentin V. Bartenev) Date: Thu, 27 Jun 2019 21:19:45 +0300 Subject: Default log file locations In-Reply-To: References: <3190464.RldmLnIc5k@vbart-workstation> Message-ID: <8179638.4KRVgS24HU@vbart-workstation> On Thursday 27 June 2019 19:44:22 Peter Bittner wrote: > I may be a bit ignorant about system-level operations, I apologize. > > Can you explain why this works better with writing to a file (i.e. the > hardcoded location /var/log/nginx/*.log)? > [..] In most cases writing to a file never blocks. Writing to stdout/stderr blocks as soon as buffers in kernel are getting full. This may happen when consumer is slower than producer, or if the consumer is just got stuck and don't read. You can see users experience this issue: https://github.com/docker/compose/issues/6018 So, nginx (like any other async application) must either log to a regular file or an UDP socket. Anything else is a bad idea from performance and reliability points of view. wbr, Valentin V. Bartenev From serg.brester at sebres.de Thu Jun 27 18:46:24 2019 From: serg.brester at sebres.de (Sergey Brester) Date: Thu, 27 Jun 2019 20:46:24 +0200 Subject: Default log file locations In-Reply-To: <3190464.RldmLnIc5k@vbart-workstation> References: <3190464.RldmLnIc5k@vbart-workstation> Message-ID: Hmm... >From _The Linux Programming Interface: A Linux and UNIX System Programming Handbook_ [2]: Nonblocking mode can be used with devices (e.g., terminals and pseudoterminals), pipes, FIFOs, and sockets. (Because file descriptors for pipes and sockets are not obtained using open(), we must enable this flag using the fcntl() F_SETFL operation described in Section 5.3.) So basically if a "sharing" of standard handles is properly implemented between master/workers and a line buffering is good enough for the logging, you can "write to terminal in non-blocking manner." Additionally note the stdout can be mapped to systemd journals (which are files and channel will be to pipe), if nginx would running as systemd service unit. Regards, Serg. 27.06.2019 19:35, Valentin V. Bartenev wrote: > Afaik, there's no way in Linux systems to write to terminal in > non-blocking manner. As the result, writing log can block the > whole nginx worker process and cause DoS. > > IMHO, it's not a good idea to make your web-application depend > on logging capabilities. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.orghttp://mailman.nginx.org/mailman/listinfo/nginx-devel [1] Links: ------ [1] http://mailman.nginx.org/mailman/listinfo/nginx-devel [2] https://books.google.de/books?id=Ps2SH727eCIC&lpg=PA103&ots=kMHcB5EQya&dq=From%20The%20Linux%20Programming%20Interface%3A%20A%20Linux%20and%20UNIX%20System%20Programming%20Handbook%3A%20Nonblocking%20mode%20can%20be%20used%20with%20devices%20(e.g.%2C%20terminals%20and%20pseudoterminals)%2C%20pipes%2C%20FIFOs%2C%20and%20sockets.%20(Because%20file%20descriptors%20for%20pipes%20and%20sockets%20are%20not%20obtained%20using%20open()%2C%20we%20must%20enable%20The%20Linux%20Programming%20Interface%3A%20A%20Linux%20and%20UNIX%20System%20Programming%20Handbook&hl=de&pg=PA103#v=onepage&q&f=false -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Sat Jun 29 10:05:16 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 29 Jun 2019 13:05:16 +0300 Subject: HTTP/2: allow unlimited number of requests in connection In-Reply-To: References: Message-ID: <20190629100516.GY1877@mdounin.ru> Hello! On Wed, Jun 26, 2019 at 07:41:27PM +0200, Michael W?rtinger wrote: > Hello, > > we're running a gRPC service behind an NGINX load balancer and we > often see that the connection gets shut down with a GOAWAY message. > Since our request deadlines are quite small and it takes some time to > re-establish a connection this often leads to many failed requests. > > After analyzing the situation we realized that it is caused by the > "http2_max_requests" option which defaults to 1000. After setting this > to a ridiculously high value our problems disappeared. > > While there probably are use cases where limiting the life time of a > connection makes sense we were wondering why it is not possible to > disable this functionality and let a connection just live as long as > possible? > > The following patch allows to do just that by setting http2_max_requests to 0. No, thank you. Closing connections periodically is required to free associated memory, and shouldn't be disabled. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sat Jun 29 10:32:51 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 29 Jun 2019 13:32:51 +0300 Subject: Bug in ngx_http_slice_filter_module ngx_http_slice_parse_content_range function In-Reply-To: References: Message-ID: <20190629103251.GZ1877@mdounin.ru> Hello! On Thu, Jun 27, 2019 at 02:01:27AM +0000, Carey Gister wrote: > The ngx_http_slice_parse_content_range function assumes that the > parsed buffer is null terminated. Since the buffer is an > ngx_str_t, that assumption is false. If, by chance, the buffer > is null terminated it is simply a matter of luck, and not > design. In many cases ngx_str_t is used for null-terminated strings. Most simple example is directive arguments during configuration parsing - while arguments are using ngx_str_t type, they are guaranteed to be null-terminated. Other examples are input headers, and upstream input headers. The latter implies that response Content-Range header will be null-terminated as seen by the slice module - unless you are producing it with some custom module. > In particular, if the headers_out.content_range ngx_str_t was > allocated in the ngx_http_range_filter_module then the buffer > was allocated as a non-zero terminated buffer by ngx_pnalloc. The range filter works after the slice module, hence whatever is set in the headers_out.content_range field by the range filter cannot affect slice module. Further, if slice module ever uses Content-Range header set by the range filter, this would indicate a severe bug, as it is expected to use Content-Range header from a backend response, not Content-Range header from the resulting response to the client. -- Maxim Dounin http://mdounin.ru/ From pgnet.dev at gmail.com Sat Jun 29 16:48:01 2019 From: pgnet.dev at gmail.com (PGNet Dev) Date: Sat, 29 Jun 2019 09:48:01 -0700 Subject: effect of bcrypt hash $cost on HTTP Basic authentication's login performance? Message-ID: When generating hashed data for "HTTP Basic" login auth protection, using bcrypt as the hash algorithm, one can vary the resultant hash strength by varying specify bcrypt's $cost, e.g. php -r "echo password_hash('$my_pass', PASSWORD_BCRYPT, ['cost' => $cost]) . PHP_EOL;" Of course, increased $cost requires increased encryption time. E.g., on my desktop, the hash encryption times vary with cost as, cost time 5 0m0.043s 6 0m0.055s 7 0m0.059s 8 0m0.075s 9 0m0.081s 10 0m0.110s 11 0m0.169s 12 0m0.285s 13 0m0.518s 14 0m0.785s 15 0m1.945s 16 0m3.782s 17 0m7.512s 18 0m14.973s 19 0m29.903s 20 0m59.735s 21 1m59.418s 22 3m58.792s ... For site login usage, does *client* login time vary at all with the hash $cost? Other than the initial, one-time hash generation, is there any login-performance reason NOT to use the highest hash $cost? From gmm at csdoc.com Sun Jun 30 07:44:14 2019 From: gmm at csdoc.com (Gena Makhomed) Date: Sun, 30 Jun 2019 10:44:14 +0300 Subject: [PATCH] Contrib: vim syntax, update core and 3rd party module directives. Message-ID: # HG changeset patch # User Gena Makhomed # Date 1561880341 -10800 # Sun Jun 30 10:39:01 2019 +0300 # Node ID f298b850ea1a8499b3ea51bde571d010dc7dfc69 # Parent 35ea9229c71a9207a24e51f327e1749e3accb26c Contrib: vim syntax, update core and 3rd party module directives. diff -r 35ea9229c71a -r f298b850ea1a contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Tue Jun 25 15:19:45 2019 +0300 +++ b/contrib/vim/syntax/nginx.vim Sun Jun 30 10:39:01 2019 +0300 @@ -333,6 +333,7 @@ syn keyword ngxDirective contained js_content syn keyword ngxDirective contained js_filter syn keyword ngxDirective contained js_include +syn keyword ngxDirective contained js_path syn keyword ngxDirective contained js_preread syn keyword ngxDirective contained js_set syn keyword ngxDirective contained keepalive @@ -353,6 +354,7 @@ syn keyword ngxDirective contained limit_rate syn keyword ngxDirective contained limit_rate_after syn keyword ngxDirective contained limit_req +syn keyword ngxDirective contained limit_req_dry_run syn keyword ngxDirective contained limit_req_log_level syn keyword ngxDirective contained limit_req_status syn keyword ngxDirective contained limit_req_zone @@ -472,6 +474,7 @@ syn keyword ngxDirective contained proxy_responses syn keyword ngxDirective contained proxy_send_lowat syn keyword ngxDirective contained proxy_send_timeout +syn keyword ngxDirective contained proxy_session_drop syn keyword ngxDirective contained proxy_set_body syn keyword ngxDirective contained proxy_set_header syn keyword ngxDirective contained proxy_socket_keepalive @@ -1325,6 +1328,7 @@ syn keyword ngxDirectiveThirdParty contained lua_code_cache syn keyword ngxDirectiveThirdParty contained lua_fake_shm syn keyword ngxDirectiveThirdParty contained lua_http10_buffering +syn keyword ngxDirectiveThirdParty contained lua_load_resty_core syn keyword ngxDirectiveThirdParty contained lua_malloc_trim syn keyword ngxDirectiveThirdParty contained lua_max_pending_timers syn keyword ngxDirectiveThirdParty contained lua_max_running_timers @@ -1779,6 +1783,7 @@ syn keyword ngxDirectiveThirdParty contained vod_fallback_upstream_location syn keyword ngxDirectiveThirdParty contained vod_force_continuous_timestamps syn keyword ngxDirectiveThirdParty contained vod_force_playlist_type_vod +syn keyword ngxDirectiveThirdParty contained vod_force_sequence_index syn keyword ngxDirectiveThirdParty contained vod_gop_look_ahead syn keyword ngxDirectiveThirdParty contained vod_gop_look_behind syn keyword ngxDirectiveThirdParty contained vod_ignore_edit_list