From mat999 at gmail.com Thu May 2 10:51:41 2019 From: mat999 at gmail.com (Mathew Heard) Date: Thu, 2 May 2019 20:51:41 +1000 Subject: SO_REUSEPORT In-Reply-To: References: <20190201141331.GT1877@mdounin.ru> <20190201154822.GV1877@mdounin.ru> Message-ID: Got a little bit further and confirmed this is definitely to do with the binary upgrade. www-data 988 99.9 0.7 365124 122784 ? R Jan30 131740:46 nginx: worker process root 2800 0.0 1.0 361828 165044 ? Ss Jan05 27:54 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; 2800 is nginx.old, also (nginx/1.15.8) as we did 2 builds with slightly different compile options. The processes do not respond to nice kill signals, only a -9 was able to kill it. On Wed, Apr 24, 2019 at 10:38 AM Mathew Heard wrote: > Yesterday one of my techs reported that a production server had a nginx > worker sitting at 99.9% CPU usage in top and not accepting new connections > (but getting it's share distributed due to SO_REUSEPORT). I thought this > might be related. > > The workers age was significantly older than it's peers so it appears to > have been a worker left from a previous configuration reload. It was child > to the single running master process and there was nothing of interest in > the error logs. > > Just sharing this here as it sounds related. > > On Tue, Feb 5, 2019 at 11:25 PM Tomas Kvasnicka wrote: > >> Hi! >> >> I just wanted to add my 2 cents here?. >> >> - We are facing a very similar issue. During reloads of reuseport enabled >> configuration it sometimes happens that no workers accept new connections, >> bandwidth basically drops to 0 and it all reverts back to normal within few >> seconds. Hurts but not deadly. >> - Our nginx uses the Intel QAT card which allows only a limited number of >> user-space processes using the card at any given moment. Therefore, our HUP >> handler has been patched quite a bit to shutdown workers one-by-one and >> then use the ngx_reap_child to start a new worker with updated >> configuration. >> - We only use the reuseport option in combination with the QAT-based >> servers (servers with the patched HUP behaviour). Therefore, I am not yet >> sure if changes in the reload mechanism are the cause of the issue - still >> investigating. >> - Thanks a lot for the ?ss -nltp? tip. >> - Currently testing the ?iptables-drop-empty-ACKs? workaround. >> - No two nginx masters are running simultaneously. >> - Reducing the number of workers is also not happening, due to the >> changes described above - the new value of worker_processes will simply be >> ignored. >> >> Thanks, >> Tomas >> _______________________________________________ >> 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 vbart at nginx.com Thu May 2 20:50:33 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 02 May 2019 20:50:33 +0000 Subject: [njs] Corrected error message when parsing "var" inside "for". Message-ID: details: https://hg.nginx.org/njs/rev/ae95d2637819 branches: changeset: 940:ae95d2637819 user: Valentin Bartenev date: Thu May 02 11:08:44 2019 +0300 description: Corrected error message when parsing "var" inside "for". The "var_in" flag indicates parsing inside the "for" statement with expectation of the "in" token, but it doesn't define the loop as a for-in one. In fact, that's unknown at the moment when this particular error message is emitted. As a result, the following code: for (var eval = 10; eval; eval--); produces the error message about for-in loop: SyntaxError: Identifier "eval" is forbidden in for-in var declaration Actually, according to the specification "eval" isn't a keyword and shouldn't cause any errors here. But this bug is beyond the scope of the current fix. diffstat: njs/njs_parser.c | 5 ++--- njs/test/njs_unit_test.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diffs (27 lines): diff -r 601a52c421d1 -r ae95d2637819 njs/njs_parser.c --- a/njs/njs_parser.c Mon Apr 29 15:57:36 2019 +0300 +++ b/njs/njs_parser.c Thu May 02 11:08:44 2019 +0300 @@ -1057,9 +1057,8 @@ njs_parser_var_statement(njs_vm_t *vm, n if (token != NJS_TOKEN_NAME) { if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " - "is forbidden in %s declaration", - njs_parser_text(parser), - var_in ? "for-in var" : "var"); + "is forbidden in var declaration", + njs_parser_text(parser)); } return NJS_TOKEN_ILLEGAL; diff -r 601a52c421d1 -r ae95d2637819 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon Apr 29 15:57:36 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 02 11:08:44 2019 +0300 @@ -6737,7 +6737,7 @@ static njs_unit_test_t njs_test[] = nxt_string("SyntaxError: Identifier \"arguments\" is forbidden in var declaration in 1") }, { nxt_string("for (var arguments in []) {}"), - nxt_string("SyntaxError: Identifier \"arguments\" is forbidden in for-in var declaration in 1") }, + nxt_string("SyntaxError: Identifier \"arguments\" is forbidden in var declaration in 1") }, { nxt_string("function arguments(){}"), nxt_string("SyntaxError: Identifier \"arguments\" is forbidden in function declaration in 1") }, From vbart at nginx.com Thu May 2 20:50:35 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 02 May 2019 20:50:35 +0000 Subject: [njs] Rejection of multiple "var" declarations in the for-in statement. Message-ID: details: https://hg.nginx.org/njs/rev/a9a4ffdea79c branches: changeset: 941:a9a4ffdea79c user: Valentin Bartenev date: Thu May 02 21:21:16 2019 +0300 description: Rejection of multiple "var" declarations in the for-in statement. diffstat: njs/njs_parser.c | 8 ++++++-- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diffs (31 lines): diff -r ae95d2637819 -r a9a4ffdea79c njs/njs_parser.c --- a/njs/njs_parser.c Thu May 02 11:08:44 2019 +0300 +++ b/njs/njs_parser.c Thu May 02 21:21:16 2019 +0300 @@ -1078,8 +1078,12 @@ njs_parser_var_statement(njs_vm_t *vm, n return token; } - if (var_in && token == NJS_TOKEN_IN) { - return njs_parser_var_in_statement(vm, parser, name); + if (var_in) { + if (token == NJS_TOKEN_IN) { + return njs_parser_var_in_statement(vm, parser, name); + } + + var_in = 0; } expr = NULL; diff -r ae95d2637819 -r a9a4ffdea79c njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 02 11:08:44 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 02 21:21:16 2019 +0300 @@ -2265,6 +2265,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("for (null in undefined);"), nxt_string("ReferenceError: Invalid left-hand side \"null\" in for-in statement in 1") }, + { nxt_string("for (var a, b in []);"), + nxt_string("SyntaxError: Unexpected token \"in\" in 1") }, + { nxt_string("var s = ''; for (var p in [1,2]) {s += p}; s"), nxt_string("01") }, From datong.sun at konghq.com Thu May 2 23:46:41 2019 From: datong.sun at konghq.com (Datong Sun) Date: Thu, 2 May 2019 16:46:41 -0700 Subject: lxr.nginx.org no longer working properly Message-ID: Hello, lxr.nginx.org stopped working properly. The static pages still shows fine but searching requests such as http://lxr.nginx.org/ident?_i=ngx_http_add_addresses returns 502 Bad Gateway. Thanks, Datong From vbart at nginx.com Fri May 3 21:56:05 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 03 May 2019 21:56:05 +0000 Subject: [njs] Added missed njs_internal_error() call in njs_regexp_exec_result(). Message-ID: details: https://hg.nginx.org/njs/rev/fe74f3c7863a branches: changeset: 942:fe74f3c7863a user: Valentin Bartenev date: Sat May 04 00:56:39 2019 +0300 description: Added missed njs_internal_error() call in njs_regexp_exec_result(). diffstat: njs/njs_regexp.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r a9a4ffdea79c -r fe74f3c7863a njs/njs_regexp.c --- a/njs/njs_regexp.c Thu May 02 21:21:16 2019 +0300 +++ b/njs/njs_regexp.c Sat May 04 00:56:39 2019 +0300 @@ -856,6 +856,8 @@ njs_regexp_exec_result(njs_vm_t *vm, njs goto done; } + njs_internal_error(vm, "lvlhsh insert failed"); + fail: ret = NXT_ERROR; From mdounin at mdounin.ru Fri May 3 22:52:01 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 4 May 2019 01:52:01 +0300 Subject: SO_REUSEPORT In-Reply-To: References: <20190201141331.GT1877@mdounin.ru> <20190201154822.GV1877@mdounin.ru> Message-ID: <20190503225201.GC1877@mdounin.ru> Hello! On Thu, May 02, 2019 at 08:51:41PM +1000, Mathew Heard wrote: > Got a little bit further and confirmed this is definitely to do with the > binary upgrade. > > www-data 988 99.9 0.7 365124 122784 ? R Jan30 131740:46 nginx: > worker process > root 2800 0.0 1.0 361828 165044 ? Ss Jan05 27:54 nginx: > master process /usr/sbin/nginx -g daemon on; master_process on; > > 2800 is nginx.old, also (nginx/1.15.8) as we did 2 builds with slightly > different compile options. > > The processes do not respond to nice kill signals, only a -9 was able to > kill it. So, as previously suggested, there is another problem elsewhere. And, if I'm reading "131740:46" correctly, the worker was eating CPU for about 90 days now. Looking into debugger where it spins might be helpful. Also make sure to take a look at the exact compile options (as shown by "nginx.old -V"), as well as any patches and/or modules loaded, and the configuration used. -- Maxim Dounin http://mdounin.ru/ From mat999 at gmail.com Fri May 3 23:02:20 2019 From: mat999 at gmail.com (Mathew Heard) Date: Sat, 4 May 2019 09:02:20 +1000 Subject: SO_REUSEPORT In-Reply-To: <20190503225201.GC1877@mdounin.ru> References: <20190201141331.GT1877@mdounin.ru> <20190201154822.GV1877@mdounin.ru> <20190503225201.GC1877@mdounin.ru> Message-ID: Not spinning since then, but that's when that worker (from the old binary) was spawned. It's an old worker spinning. Unfortunately there isnt any debug symbols. GDB: (gdb) bt #0 0x00007ff842edd016 in ?? () #1 0x0000000040d9ab70 in ?? () #2 0x4096580000000000 in ?? () #3 0x4064000000000000 in ?? () #4 0x00000009413dcda0 in ?? () #5 0x41f975d000000006 in ?? () #6 0x000000004190c148 in ?? () #7 0x00000000413e4580 in ?? () #8 0x40bb6b7840f961c8 in ?? () #9 0x0000000000464000 in ?? () #10 0x00007ffea78d5370 in ?? () #11 0x0000000000000000 in ?? () strace: --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} --- rt_sigreturn() = 1094569376 It is a reduced version (less additional modules) of Openresty so third party module interference is possible. Would there be any thing in particular re; modules I should check for? My first step has been trying to work out how to replicate it on demand. Just triggering binary reloads is not enough, something has to happen between them and I'm not yet sure what. On Sat, May 4, 2019 at 8:52 AM Maxim Dounin wrote: > Hello! > > On Thu, May 02, 2019 at 08:51:41PM +1000, Mathew Heard wrote: > > > Got a little bit further and confirmed this is definitely to do with the > > binary upgrade. > > > > www-data 988 99.9 0.7 365124 122784 ? R Jan30 131740:46 > nginx: > > worker process > > root 2800 0.0 1.0 361828 165044 ? Ss Jan05 27:54 nginx: > > master process /usr/sbin/nginx -g daemon on; master_process on; > > > > 2800 is nginx.old, also (nginx/1.15.8) as we did 2 builds with slightly > > different compile options. > > > > The processes do not respond to nice kill signals, only a -9 was able to > > kill it. > > So, as previously suggested, there is another problem elsewhere. > > And, if I'm reading "131740:46" correctly, the worker was eating > CPU for about 90 days now. Looking into debugger where it spins > might be helpful. > > Also make sure to take a look at the exact compile options (as > shown by "nginx.old -V"), as well as any patches and/or modules > loaded, and the configuration used. > > -- > 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 nginx-devel at hardfalcon.net Sat May 4 00:07:44 2019 From: nginx-devel at hardfalcon.net (Pascal Ernster) Date: Sat, 04 May 2019 02:07:44 +0200 Subject: [PATCH] Enable SSL_OP_PRIORITIZE_CHACHA for server-side SSL contexts Message-ID: <9560af6ada8f395a3b01.1556928464@hardfalcon0> # HG changeset patch # User Pascal Ernster # Date 1556927912 -7200 # Sat May 04 01:58:32 2019 +0200 # Node ID 9560af6ada8f395a3b01c66e6846fa7ebd41729d # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 Enable SSL_OP_PRIORITIZE_CHACHA for server-side SSL contexts. Available since OpenSSL 1.1.1, this prioritizes ChaCha ciphers when the client has a ChaCha20 cipher at the top of its preference list, indicating that the client does not have hardware acceleration for AES. The result is much better performance on devices like low-end Android smartphones or embedded hardware running OpenWRT. diff -r 16a1adadf437 -r 9560af6ada8f src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Apr 24 16:38:56 2019 +0300 +++ b/src/event/ngx_event_openssl.c Sat May 04 01:58:32 2019 +0200 @@ -380,6 +380,10 @@ SSL_CTX_set_mode(ssl->ctx, SSL_MODE_NO_AUTO_CHAIN); #endif +#ifdef SSL_OP_PRIORITIZE_CHACHA + SSL_CTX_set_options(ssl->ctx, SSL_OP_PRIORITIZE_CHACHA); +#endif + SSL_CTX_set_read_ahead(ssl->ctx, 1); SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); From mdounin at mdounin.ru Sat May 4 00:15:40 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 4 May 2019 03:15:40 +0300 Subject: SO_REUSEPORT In-Reply-To: References: <20190201141331.GT1877@mdounin.ru> <20190201154822.GV1877@mdounin.ru> <20190503225201.GC1877@mdounin.ru> Message-ID: <20190504001539.GE1877@mdounin.ru> Hello! On Sat, May 04, 2019 at 09:02:20AM +1000, Mathew Heard wrote: [...] > It is a reduced version (less additional modules) of Openresty so third > party module interference is possible. Would there be any thing in > particular re; modules I should check for? When I last checked, Openresty included not only various 3rd party modules, but also a bunch of various patches, including highly questionable ones. As such, the only recommendation I can give here is to switch to vanilla nginx instead. -- Maxim Dounin http://mdounin.ru/ From mat999 at gmail.com Sat May 4 00:17:25 2019 From: mat999 at gmail.com (Mathew Heard) Date: Sat, 4 May 2019 10:17:25 +1000 Subject: SO_REUSEPORT In-Reply-To: <20190504001539.GE1877@mdounin.ru> References: <20190201141331.GT1877@mdounin.ru> <20190201154822.GV1877@mdounin.ru> <20190503225201.GC1877@mdounin.ru> <20190504001539.GE1877@mdounin.ru> Message-ID: Maxim, Which patches / modules would you consider highly questionable? On Sat, May 4, 2019 at 10:15 AM Maxim Dounin wrote: > Hello! > > On Sat, May 04, 2019 at 09:02:20AM +1000, Mathew Heard wrote: > > [...] > > > It is a reduced version (less additional modules) of Openresty so third > > party module interference is possible. Would there be any thing in > > particular re; modules I should check for? > > When I last checked, Openresty included not only various 3rd party > modules, but also a bunch of various patches, including highly > questionable ones. As such, the only recommendation I can give > here is to switch to vanilla nginx instead. > > -- > 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 mdounin at mdounin.ru Sat May 4 00:37:51 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 4 May 2019 03:37:51 +0300 Subject: [PATCH] Enable SSL_OP_PRIORITIZE_CHACHA for server-side SSL contexts In-Reply-To: <9560af6ada8f395a3b01.1556928464@hardfalcon0> References: <9560af6ada8f395a3b01.1556928464@hardfalcon0> Message-ID: <20190504003751.GF1877@mdounin.ru> Hello! On Sat, May 04, 2019 at 02:07:44AM +0200, Pascal Ernster wrote: > # HG changeset patch > # User Pascal Ernster > # Date 1556927912 -7200 > # Sat May 04 01:58:32 2019 +0200 > # Node ID 9560af6ada8f395a3b01c66e6846fa7ebd41729d > # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 > Enable SSL_OP_PRIORITIZE_CHACHA for server-side SSL contexts. > > Available since OpenSSL 1.1.1, this prioritizes ChaCha ciphers when the client has a ChaCha20 cipher at the top of its preference list, indicating that the client does not have hardware acceleration for AES. The result is much better performance on devices like low-end Android smartphones or embedded hardware running OpenWRT. > > diff -r 16a1adadf437 -r 9560af6ada8f src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c Wed Apr 24 16:38:56 2019 +0300 > +++ b/src/event/ngx_event_openssl.c Sat May 04 01:58:32 2019 +0200 > @@ -380,6 +380,10 @@ > SSL_CTX_set_mode(ssl->ctx, SSL_MODE_NO_AUTO_CHAIN); > #endif > > +#ifdef SSL_OP_PRIORITIZE_CHACHA > + SSL_CTX_set_options(ssl->ctx, SSL_OP_PRIORITIZE_CHACHA); > +#endif > + > SSL_CTX_set_read_ahead(ssl->ctx, 1); > > SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); Thank you for the patch. See comments here: https://trac.nginx.org/nginx/ticket/1445 -- Maxim Dounin http://mdounin.ru/ From nginx-devel at hardfalcon.net Sat May 4 01:18:12 2019 From: nginx-devel at hardfalcon.net (Pascal Ernster) Date: Sat, 4 May 2019 03:18:12 +0200 Subject: [PATCH] Enable SSL_OP_PRIORITIZE_CHACHA for server-side SSL contexts In-Reply-To: <20190504003751.GF1877@mdounin.ru> References: <9560af6ada8f395a3b01.1556928464@hardfalcon0> <20190504003751.GF1877@mdounin.ru> Message-ID: Hi Maxim, [2019-05-04 02:37] Maxim Dounin: > Thank you for the patch. > See comments here: > > https://trac.nginx.org/nginx/ticket/1445 > In the first comment on that ticket, you write > At most, we can consider a generic interface to set various OpenSSL options. Would there be a realistic chance of you accepting a patch that simply exposes OpenSSL's SSL_CONF_cmd() through the nginx config file(s)? It would of course do the obvious basic checks using SSL_CONF_cmd_value_type() like "Does the requested option exist in OpenSSL?", "If a file/directory was specified, does it exist and is it readable?", "If a relative file/directory was specified, prepend the nginx configuration directory path to the string.", and would of course check the return value of SSL_CONF_cmd() itself, but it would *not* try to do anything further like "Prevent the user from overriding settings made through other nginx configuration directives". Since I'm not too experienced in writing C code, it would be quite a bit of work for me, so I'd like to know beforehand if it would be worth the effort at all, or if you'd reject the patch anyhow. Regards Pascal From vbart at nginx.com Sat May 4 13:58:06 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Sat, 04 May 2019 13:58:06 +0000 Subject: [njs] Simplified condition in njs_function_alloc(). Message-ID: details: https://hg.nginx.org/njs/rev/551d173ab9ec branches: changeset: 943:551d173ab9ec user: Valentin Bartenev date: Sat May 04 05:52:15 2019 +0300 description: Simplified condition in njs_function_alloc(). There's no reason to check both flags when one depends on another. See just a few lines above: function->ctor = !lambda->arrow. Now the condition is made similar to the one in njs_method_private_copy(). diffstat: njs/njs_function.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (18 lines): diff -r fe74f3c7863a -r 551d173ab9ec njs/njs_function.c --- a/njs/njs_function.c Sat May 04 00:56:39 2019 +0300 +++ b/njs/njs_function.c Sat May 04 05:52:15 2019 +0300 @@ -42,11 +42,11 @@ njs_function_alloc(njs_vm_t *vm, njs_fun function->args_offset = 1; function->u.lambda = lambda; - if (lambda->arrow || !function->ctor) { - function->object.shared_hash = vm->shared->arrow_instance_hash; + if (function->ctor) { + function->object.shared_hash = vm->shared->function_instance_hash; } else { - function->object.shared_hash = vm->shared->function_instance_hash; + function->object.shared_hash = vm->shared->arrow_instance_hash; } function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object; From vbart at nginx.com Sat May 4 14:11:25 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Sat, 04 May 2019 14:11:25 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/b7cdfafdc20b branches: changeset: 944:b7cdfafdc20b user: Valentin Bartenev date: Sat May 04 16:59:24 2019 +0300 description: Style. diffstat: njs/njs_disassembler.c | 2 -- njs/njs_function.c | 1 - njs/njs_json.c | 8 ++++---- njs/njs_object.c | 10 +++++----- njs/njs_parser.c | 7 +++---- njs/njs_string.c | 1 - njs/test/njs_unit_test.c | 10 +++++----- 7 files changed, 17 insertions(+), 22 deletions(-) diffs (123 lines): diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_disassembler.c --- a/njs/njs_disassembler.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/njs_disassembler.c Sat May 04 16:59:24 2019 +0300 @@ -295,7 +295,6 @@ njs_disassemble(u_char *start, u_char *e (size_t) method->method, method->nargs, method->code.ctor ? " CTOR" : ""); - p += sizeof(njs_vmcode_method_frame_t); continue; } @@ -308,7 +307,6 @@ njs_disassemble(u_char *start, u_char *e (size_t) prop_foreach->object, (size_t) prop_foreach->offset); - p += sizeof(njs_vmcode_prop_foreach_t); continue; } diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_function.c --- a/njs/njs_function.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/njs_function.c Sat May 04 16:59:24 2019 +0300 @@ -31,7 +31,6 @@ njs_function_alloc(njs_vm_t *vm, njs_fun goto fail; } - /* * nxt_mp_zalloc() does also: * nxt_lvlhsh_init(&function->object.hash); diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_json.c --- a/njs/njs_json.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/njs_json.c Sat May 04 16:59:24 2019 +0300 @@ -1916,10 +1916,10 @@ njs_json_append_number(njs_json_stringif static njs_value_t * njs_json_wrap_value(njs_vm_t *vm, const njs_value_t *value) { - nxt_int_t ret; - njs_value_t *wrapper; - njs_object_prop_t *prop; - nxt_lvlhsh_query_t lhq; + nxt_int_t ret; + njs_value_t *wrapper; + njs_object_prop_t *prop; + nxt_lvlhsh_query_t lhq; wrapper = nxt_mp_alloc(vm->mem_pool, sizeof(njs_value_t)); if (nxt_slow_path(wrapper == NULL)) { diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_object.c --- a/njs/njs_object.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/njs_object.c Sat May 04 16:59:24 2019 +0300 @@ -2619,11 +2619,11 @@ njs_value_t * njs_property_prototype_create(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_object_t *prototype) { - nxt_int_t ret; - njs_object_prop_t *prop; - nxt_lvlhsh_query_t lhq; - - static const njs_value_t proto_string = njs_string("prototype"); + nxt_int_t ret; + njs_object_prop_t *prop; + nxt_lvlhsh_query_t lhq; + + static const njs_value_t proto_string = njs_string("prototype"); prop = njs_object_prop_alloc(vm, &proto_string, &njs_value_undefined, 0); if (nxt_slow_path(prop == NULL)) { diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_parser.c --- a/njs/njs_parser.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/njs_parser.c Sat May 04 16:59:24 2019 +0300 @@ -1064,7 +1064,6 @@ njs_parser_var_statement(njs_vm_t *vm, n return NJS_TOKEN_ILLEGAL; } - name = njs_parser_variable_node(vm, parser, njs_parser_text(parser), njs_parser_key_hash(parser), @@ -2179,9 +2178,9 @@ njs_token_t njs_parser_arrow_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - njs_ret_t ret; - njs_index_t index; - njs_parser_node_t *node, *body, *parent; + njs_ret_t ret; + njs_index_t index; + njs_parser_node_t *node, *body, *parent; njs_function_lambda_t *lambda; node = njs_parser_node_new(vm, parser, NJS_TOKEN_FUNCTION_EXPRESSION); diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_string.c --- a/njs/njs_string.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/njs_string.c Sat May 04 16:59:24 2019 +0300 @@ -598,7 +598,6 @@ static const njs_object_prop_t njs_stri NJS_SKIP_ARG, NJS_STRING_ARG), }, - /* String.fromCharCode(). */ { .type = NJS_METHOD, diff -r 551d173ab9ec -r b7cdfafdc20b njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat May 04 05:52:15 2019 +0300 +++ b/njs/test/njs_unit_test.c Sat May 04 16:59:24 2019 +0300 @@ -13104,11 +13104,11 @@ done: static nxt_int_t njs_timezone_optional_test(nxt_bool_t disassemble, nxt_bool_t verbose) { - size_t size; - u_char buf[16]; - time_t clock; - struct tm tm; - nxt_int_t ret; + size_t size; + u_char buf[16]; + time_t clock; + struct tm tm; + nxt_int_t ret; /* * Chatham Islands NZ-CHAT time zone. From vbart at nginx.com Sat May 4 14:16:16 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Sat, 04 May 2019 14:16:16 +0000 Subject: [njs] Added the "name" property to the Function prototype object. Message-ID: details: https://hg.nginx.org/njs/rev/0c42e997371c branches: changeset: 945:0c42e997371c user: Valentin Bartenev date: Sat May 04 17:12:35 2019 +0300 description: Added the "name" property to the Function prototype object. Its value according to the ES6+ specification must be the empty String. diffstat: njs/njs_function.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diffs (16 lines): diff -r b7cdfafdc20b -r 0c42e997371c njs/njs_function.c --- a/njs/njs_function.c Sat May 04 16:59:24 2019 +0300 +++ b/njs/njs_function.c Sat May 04 17:12:35 2019 +0300 @@ -1175,6 +1175,12 @@ static const njs_object_prop_t njs_func { { .type = NJS_PROPERTY, + .name = njs_string("name"), + .value = njs_string(""), + }, + + { + .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 0, 0.0), }, From benishay at mellanox.com Mon May 6 06:02:10 2019 From: benishay at mellanox.com (Ben Ben Ishay) Date: Mon, 6 May 2019 06:02:10 +0000 Subject: FW: [PATCH] when we need to transfer data between file and socket we prefer to use sendfile instead of write because we save the copy to a buffer In-Reply-To: <6e9c9a7e-0297-e3ea-dc3c-a1e48697343a@mellanox.com> References: <20190418130733.GZ1877@mdounin.ru> <6e9c9a7e-0297-e3ea-dc3c-a1e48697343a@mellanox.com> Message-ID: -----Original Message----- From: Ben Ben Ishay Sent: Monday, April 29, 2019 12:08 PM To: Maxim Dounin ; Boris Pismenny Subject: Re: [PATCH] when we need to transfer data between file and socket we prefer to use sendfile instead of write because we save the copy to a buffer Hello! thank you for the review. we fixed the code style issues. before i send another patch i want to be sure that you agree with our attitude. On 4/18/2019 4:07 PM, Maxim Dounin wrote: > Hello! > > On Thu, Apr 18, 2019 at 10:32:56AM +0300, ben ben ishay wrote: > >> # HG changeset patch >> # User ben ben ishay >> # Date 1555572726 -10800 >> # Thu Apr 18 10:32:06 2019 +0300 >> # Node ID bb4c564a9f1c5c721c192e6188967c19aabbc0b9 >> # Parent a6e23e343081b79eb924da985a414909310aa7a3 >> when we need to transfer data between file and socket we prefer to use sendfile instead of write because we save the copy to a buffer. >> the use of sendfile is possible in openssl only if it support ktls(the master of openssl support ktls) otherwise there is a copy of the data to userspace for encryption in any case (this paper explain this https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fnetdevconf.org%2F1.2%2Fpapers%2Fktls.pdf&data=02%7C01%7Cbenishay%40mellanox.com%7C2203ce7481ec4c3e562308d6c3fed9f8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C1%7C636911896691245657&sdata=4%2F7ofqINYiEr9m%2B53E%2BA2hxrzb0P9xGeJsFrE4N6a6U%3D&reserved=0 ). >> the patch change the flow when the request is to send data over ssl and also the nginx use openssl that support ktls, the new flow using the sendfile function that tcp use for send data (ngx_linux_sendfile_chain). >> the performence with this patch applied was check with apib benchmark(this is the source https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fapigee%2Fapib)%2Cone&data=02%7C01%7Cbenishay%40mellanox.com%7C2203ce7481ec4c3e562308d6c3fed9f8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C1%7C636911896691255667&sdata=ZzsqevUA%2FOgpiZrIkos1MKoxbGkAEh0m1APYZbyEhrU%3D&reserved=0 machine run nginx and the other machine that connect back to back to the first one run apib with this comand: ./apib -c -d 30 https:///. >> the file size was 100K. >> >> the result display in this table , each value represnt average throughput in GBps of 10 runs. >> >> num of connection | regular nginx | new nginx >> 1 5 5.2 >> 2 7.5 8.5 >> 3 7.7 9 >> >> this result prove that this patch increase nginx performance and thus is useful. > > In no particular order: > > - Please read https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fnginx.org%2Fen%2Fdocs%2Fcontributing_changes.html&data=02%7C01%7Cbenishay%40mellanox.com%7C2203ce7481ec4c3e562308d6c3fed9f8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C1%7C636911896691255667&sdata=E%2BJmG06kBUWZfzWna%2FmH4C46u1ZHD%2F03R%2B50evoEOEk%3D&reserved=0 for > basic tips on how to submit patches. In particular, please make > sure to follow nginx coding style. > > - Note well that at least one bug in your code is directly related > to incorrect indentation and failure to properly use curly > brackets as explicitly required by the coding style. The style > is there to prevent such accidental bugs. > > - When you update your patches based on the feedback given, > consider replying to the thread in question instead of > posting a new thread. If for some reason you think a new thread > will be better, describe these reasons and post a reference to > the old thread. Also, make sure to describe changes you've > made based on the feedback. > > - The SSL_sendfile() call you are using in this version does not > seem to exists in any published version of OpenSSL, including > github repo. This is not going to work. > we attach a documentation link about this function(https://github.com/Mellanox/openssl/blob/tls_sendfile/doc/man3/SSL_write.pod), we have a pull request at advanced stage for adding this function. > - The approach you are using - that is, introducing changes into > ngx_linux_sendfile_chain.c - is not portable, and is not going > to work on other platforms if/when appropriate kernel level and > OpenSSL level support will be available. As suggested in the > previous thread, this should be something handled at the > ngx_event_openssl.c level. > we think that this is the best solution because there is a unique function for every OS and there is a difference between them for example ngx_linux_sendfile_chain use TCP_CORK option while ngx_freebsd_sendfile_chain dosent(in addition in solaris function ngx_solaris_sendfilev_chain there is a call to sendfilev that dosent exists in linux) , we can create a function that is constructed from the diffrenet flow for OS's but we think this option include copying code and thus the best option is to change the sendfile call in every ngx_sendfile function when the OS and OPENSSL will support SSL_Sendfile. > [...] > From maxim at nginx.com Mon May 6 07:01:30 2019 From: maxim at nginx.com (Maxim Konovalov) Date: Mon, 6 May 2019 10:01:30 +0300 Subject: lxr.nginx.org no longer working properly In-Reply-To: References: Message-ID: Hi Datong, On 03/05/2019 02:46, Datong Sun wrote: > Hello, > > lxr.nginx.org stopped working properly. The static pages still shows > fine but searching requests such as > http://lxr.nginx.org/ident?_i=ngx_http_add_addresses returns 502 Bad > Gateway. > Thanks for the report. It should be fixed now. -- Maxim Konovalov From vbart at nginx.com Mon May 6 08:32:13 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 08:32:13 +0000 Subject: [njs] Uncommented a successful test of getOwnPropertyNames(). Message-ID: details: https://hg.nginx.org/njs/rev/274d33eeb57d branches: changeset: 946:274d33eeb57d user: Valentin Bartenev date: Mon May 06 00:27:22 2019 +0300 description: Uncommented a successful test of getOwnPropertyNames(). It's actully passing after 1213e0a2b485 and d7a0eb59a7e7 changes. diffstat: njs/njs_object.c | 2 -- njs/test/njs_unit_test.c | 2 -- 2 files changed, 0 insertions(+), 4 deletions(-) diffs (26 lines): diff -r 0c42e997371c -r 274d33eeb57d njs/njs_object.c --- a/njs/njs_object.c Sat May 04 17:12:35 2019 +0300 +++ b/njs/njs_object.c Mon May 06 00:27:22 2019 +0300 @@ -442,8 +442,6 @@ njs_object_property_query(njs_vm_t *vm, do { pq->prototype = proto; - /* TODO: length should be Own property */ - if (nxt_fast_path(!pq->own || proto == object)) { ret = nxt_lvlhsh_find(&proto->hash, &pq->lhq); diff -r 0c42e997371c -r 274d33eeb57d njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat May 04 17:12:35 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 06 00:27:22 2019 +0300 @@ -9310,10 +9310,8 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.getOwnPropertyNames(Array)"), nxt_string("name,length,prototype,isArray,of") }, -#if 0 { nxt_string("Object.getOwnPropertyNames(Array.isArray)"), nxt_string("length") }, -#endif { nxt_string("Object.defineProperty(Object.freeze({}), 'b', {})"), nxt_string("TypeError: object is not extensible") }, From vbart at nginx.com Mon May 6 08:32:13 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 08:32:13 +0000 Subject: [njs] Added missing "static" to njs_object_property_query() declaration. Message-ID: details: https://hg.nginx.org/njs/rev/f3b145f3ca34 branches: changeset: 947:f3b145f3ca34 user: Valentin Bartenev date: Mon May 06 05:07:51 2019 +0300 description: Added missing "static" to njs_object_property_query() declaration. diffstat: njs/njs_object.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 274d33eeb57d -r f3b145f3ca34 njs/njs_object.c --- a/njs/njs_object.c Mon May 06 00:27:22 2019 +0300 +++ b/njs/njs_object.c Mon May 06 05:07:51 2019 +0300 @@ -417,7 +417,7 @@ njs_property_query(njs_vm_t *vm, njs_pro } -njs_ret_t +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) { From mdounin at mdounin.ru Mon May 6 13:22:53 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 6 May 2019 16:22:53 +0300 Subject: [PATCH] Enable SSL_OP_PRIORITIZE_CHACHA for server-side SSL contexts In-Reply-To: References: <9560af6ada8f395a3b01.1556928464@hardfalcon0> <20190504003751.GF1877@mdounin.ru> Message-ID: <20190506132253.GG1877@mdounin.ru> Hello! On Sat, May 04, 2019 at 03:18:12AM +0200, Pascal Ernster wrote: > [2019-05-04 02:37] Maxim Dounin: > > Thank you for the patch. > > See comments here: > > > > https://trac.nginx.org/nginx/ticket/1445 > > > > In the first comment on that ticket, you write > > > At most, we can consider a generic interface to set various OpenSSL options. > > Would there be a realistic chance of you accepting a patch that simply > exposes OpenSSL's SSL_CONF_cmd() through the nginx config file(s)? > > It would of course do the obvious basic checks using > SSL_CONF_cmd_value_type() like > "Does the requested option exist in OpenSSL?", > "If a file/directory was specified, does it exist and is it readable?", > "If a relative file/directory was specified, prepend the nginx > configuration directory path to the string.", > and would of course check the return value of SSL_CONF_cmd() itself, but > it would *not* try to do anything further like "Prevent the user from > overriding settings made through other nginx configuration directives". > > Since I'm not too experienced in writing C code, it would be quite a bit > of work for me, so I'd like to know beforehand if it would be worth the > effort at all, or if you'd reject the patch anyhow. As of now, such an option is considered. But whether a patch will be accepted or not heavily depends on the patch quality and overral simplicity of the interface involved. Note well that what your original patch does - that is, preferring ChaCha without any user-configurable options - can be easily achieved by using appropriate system-wide OpenSSL config. If unsure, you may consider this approach instead. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon May 6 14:30:11 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 6 May 2019 17:30:11 +0300 Subject: FW: [PATCH] when we need to transfer data between file and socket we prefer to use sendfile instead of write because we save the copy to a buffer In-Reply-To: References: <20190418130733.GZ1877@mdounin.ru> <6e9c9a7e-0297-e3ea-dc3c-a1e48697343a@mellanox.com> Message-ID: <20190506143011.GH1877@mdounin.ru> Hello! On Mon, May 06, 2019 at 06:02:10AM +0000, Ben Ben Ishay wrote: [...] > > - The SSL_sendfile() call you are using in this version does not > > seem to exists in any published version of OpenSSL, including > > github repo. This is not going to work. > > > we attach a documentation link about this > function(https://github.com/Mellanox/openssl/blob/tls_sendfile/doc/man3/SSL_write.pod), > we have a pull request at advanced stage for adding this function. > > > - The approach you are using - that is, introducing changes into > > ngx_linux_sendfile_chain.c - is not portable, and is not going > > to work on other platforms if/when appropriate kernel level and > > OpenSSL level support will be available. As suggested in the > > previous thread, this should be something handled at the > > ngx_event_openssl.c level. > > > we think that this is the best solution because there is a unique > function for every OS and there is a difference between them for > example ngx_linux_sendfile_chain use TCP_CORK option while > ngx_freebsd_sendfile_chain dosent(in addition in solaris function > ngx_solaris_sendfilev_chain there is a call to sendfilev that dosent > exists in linux) , we can create a function that is constructed from the > diffrenet flow for OS's but we think this option include copying code > and thus the best option is to change the sendfile call in every > ngx_sendfile function when the OS and OPENSSL will support SSL_Sendfile. While handling of the sendfile() syscall is certainly OS-specific, the SSL_sendfile() interface as provided by OpenSSL is certainly not going to follow these OS-specific code paths. For example, I cannot reasonably assume SSL_sendfile() will support headers and trailers on FreeBSD, or will be similar to sendfilev() interface on Solaris. That is, SSL_sendfile() is going to be a separate interface, different from all the OS-specific interfaces, with its own features and limitations. And most likely it will need different error handling, including handling of SSL-specific errors. As such, trying to change OS-specific sendfile chains in nginx looks wrong to me. Not to mention it will require additional application-level work upon introduction of in-kernel SSL/TLS in other OSes. Rather, it should be an SSL-level changes, introducing an SSL-level send chain, similar to one we already provide for SSL_write(). (Note well that using BIO_get_ktls_send() to find out if SSL_sendfile() can be used or not also looks strange and non-portable. If the route taken is to provide SSL_sendfile(), an OS-independent interface to use sendfile() when supported by the OpenSSL library, there should be a simplier / more portable way to test if SSL_sendfile() can be used on a particular SSL connection.) -- Maxim Dounin http://mdounin.ru/ From vbart at nginx.com Mon May 6 14:47:37 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 14:47:37 +0000 Subject: [njs] Fixed alignment of njs_object_prop_t in njs_method_private_copy(). Message-ID: details: https://hg.nginx.org/njs/rev/6ee0e7a44e79 branches: changeset: 948:6ee0e7a44e79 user: Valentin Bartenev date: Mon May 06 17:47:26 2019 +0300 description: Fixed alignment of njs_object_prop_t in njs_method_private_copy(). It must be aligned to njs_value_t. diffstat: njs/njs_object.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r f3b145f3ca34 -r 6ee0e7a44e79 njs/njs_object.c --- a/njs/njs_object.c Mon May 06 05:07:51 2019 +0300 +++ b/njs/njs_object.c Mon May 06 17:47:26 2019 +0300 @@ -773,7 +773,8 @@ njs_method_private_copy(njs_vm_t *vm, nj njs_function_t *function; njs_object_prop_t *prop, *shared; - prop = nxt_mp_alloc(vm->mem_pool, sizeof(njs_object_prop_t)); + 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; From vbart at nginx.com Mon May 6 15:37:28 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 15:37:28 +0000 Subject: [njs] Fixed own properties quering. Message-ID: details: https://hg.nginx.org/njs/rev/d94c836632c7 branches: changeset: 949:d94c836632c7 user: Valentin Bartenev date: Mon May 06 11:33:23 2019 +0300 description: Fixed own properties quering. njs_property_query() and njs_object_property_query() were simplified. diffstat: njs/njs_object.c | 124 +++++++++++++++++----------------------------- njs/test/njs_unit_test.c | 17 ++++++ 2 files changed, 63 insertions(+), 78 deletions(-) diffs (186 lines): diff -r 6ee0e7a44e79 -r d94c836632c7 njs/njs_object.c --- a/njs/njs_object.c Mon May 06 17:47:26 2019 +0300 +++ b/njs/njs_object.c Mon May 06 11:33:23 2019 +0300 @@ -322,39 +322,11 @@ njs_property_query(njs_vm_t *vm, njs_pro obj = &vm->string_object; break; - case NJS_OBJECT_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)) { - ret = njs_string_property_query(vm, pq, - &object->data.u.object_value->value, - index); - - if (nxt_fast_path(ret != NXT_DECLINED)) { - return ret; - } - } - } - - obj = object->data.u.object; - break; - + case NJS_OBJECT: case NJS_ARRAY: - if (nxt_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { - index = njs_value_to_index(property); - - if (nxt_fast_path(index < NJS_ARRAY_MAX_INDEX)) { - return njs_array_property_query(vm, pq, object->data.u.array, - index); - } - } - - /* Fall through. */ - - case NJS_OBJECT: case NJS_OBJECT_BOOLEAN: case NJS_OBJECT_NUMBER: + case NJS_OBJECT_STRING: case NJS_REGEXP: case NJS_DATE: case NJS_OBJECT_ERROR: @@ -442,62 +414,58 @@ njs_object_property_query(njs_vm_t *vm, do { pq->prototype = proto; - if (nxt_fast_path(!pq->own || proto == object)) { - ret = nxt_lvlhsh_find(&proto->hash, &pq->lhq); + 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) { + pq->shared = 0; + + return ret; + } + + } else { + ret = nxt_lvlhsh_find(&proto->shared_hash, &pq->lhq); if (ret == NXT_OK) { - prop = pq->lhq.value; - - if (prop->type != NJS_WHITEOUT) { - pq->shared = 0; - - return ret; - } - - goto next; - } - - if (proto != object - && !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; - return njs_string_property_query(vm, pq, &ov->value, - index); - } - - default: - break; - } + pq->shared = 1; + + return ret; } } - ret = nxt_lvlhsh_find(&proto->shared_hash, &pq->lhq); - - if (ret == NXT_OK) { - pq->shared = 1; - - return ret; - } - - if (pq->query > NJS_PROPERTY_QUERY_GET) { + if (pq->own || pq->query > NJS_PROPERTY_QUERY_GET) { return NXT_DECLINED; } -next: - proto = proto->__proto__; } while (proto != NULL); diff -r 6ee0e7a44e79 -r d94c836632c7 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon May 06 17:47:26 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 06 11:33:23 2019 +0300 @@ -9102,6 +9102,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("'s'.hasOwnProperty('1')"), nxt_string("false") }, + { nxt_string("Object.hasOwnProperty('hasOwnProperty')"), + nxt_string("false") }, + + { nxt_string("Object.prototype.hasOwnProperty('hasOwnProperty')"), + nxt_string("true") }, + { nxt_string("var p = { a:5 }; var o = Object.create(p);" "Object.getPrototypeOf(o) === p"), nxt_string("true") }, @@ -9160,6 +9166,17 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.create(function(a,b,c){}).length"), nxt_string("3") }, + { nxt_string("Object.create(Math).hasOwnProperty('abs')"), + nxt_string("false") }, + + { nxt_string("var m = Object.create(Math); m.abs = 3;" + "[m.hasOwnProperty('abs'), m.abs]"), + nxt_string("true,3") }, + + { nxt_string("var m = Object.create(Math); m.abs = Math.floor;" + "[m.hasOwnProperty('abs'), delete m.abs, m.abs(-1)]"), + nxt_string("true,true,1") }, + { nxt_string("Object.getOwnPropertyDescriptor({a:1}, 'a').value"), nxt_string("1") }, From vbart at nginx.com Mon May 6 16:59:18 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 16:59:18 +0000 Subject: [njs] Added support for RegExp "groups" object (ES9). Message-ID: details: https://hg.nginx.org/njs/rev/e9de8a5d423c branches: changeset: 950:e9de8a5d423c user: Valentin Bartenev date: Mon May 06 19:42:06 2019 +0300 description: Added support for RegExp "groups" object (ES9). diffstat: njs/njs_object_hash.h | 10 +++ njs/njs_regexp.c | 121 ++++++++++++++++++++++++++++++++++++++++++---- njs/njs_regexp_pattern.h | 18 +++--- njs/test/njs_unit_test.c | 12 ++++ nxt/nxt_pcre.c | 58 ++++++++++++++++++++++ nxt/nxt_pcre.h | 3 + nxt/nxt_regex.h | 2 + 7 files changed, 203 insertions(+), 21 deletions(-) diffs (368 lines): diff -r d94c836632c7 -r e9de8a5d423c njs/njs_object_hash.h --- a/njs/njs_object_hash.h Mon May 06 11:33:23 2019 +0300 +++ b/njs/njs_object_hash.h Mon May 06 19:42:06 2019 +0300 @@ -100,6 +100,16 @@ 'i'), 'n'), 'p'), 'u'), 't') +#define NJS_GROUPS_HASH \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add( \ + nxt_djb_hash_add(NXT_DJB_HASH_INIT, \ + 'g'), 'r'), 'o'), 'u'), 'p'), 's') + + #define NJS_JOIN_HASH \ nxt_djb_hash_add( \ nxt_djb_hash_add( \ diff -r d94c836632c7 -r e9de8a5d423c njs/njs_regexp.c --- a/njs/njs_regexp.c Mon May 06 11:33:23 2019 +0300 +++ b/njs/njs_regexp.c Mon May 06 19:42:06 2019 +0300 @@ -11,6 +11,13 @@ #include +struct njs_regexp_group_s { + nxt_str_t name; + uint32_t hash; + uint32_t capture; +}; + + static void *njs_regexp_malloc(size_t size, void *memory_data); static void njs_regexp_free(void *p, void *memory_data); static njs_regexp_flags_t njs_regexp_flags(u_char **start, u_char *end, @@ -327,6 +334,9 @@ njs_regexp_pattern_create(njs_vm_t *vm, int options, ret; u_char *p, *end; size_t size; + nxt_uint_t n; + nxt_regex_t *regex; + njs_regexp_group_t *group; njs_regexp_pattern_t *pattern; size = 1; /* A trailing "/". */ @@ -405,14 +415,42 @@ njs_regexp_pattern_create(njs_vm_t *vm, goto fail; } - if (!nxt_regex_is_valid(&pattern->regex[0]) - && !nxt_regex_is_valid(&pattern->regex[1])) - { + if (nxt_regex_is_valid(&pattern->regex[0])) { + regex = &pattern->regex[0]; + + } else if (nxt_regex_is_valid(&pattern->regex[1])) { + regex = &pattern->regex[1]; + + } else { goto fail; } *end = '/'; + pattern->ngroups = nxt_regex_named_captures(regex, NULL, 0); + + if (pattern->ngroups != 0) { + size = sizeof(njs_regexp_group_t) * pattern->ngroups; + + pattern->groups = nxt_mp_alloc(vm->mem_pool, size); + if (nxt_slow_path(pattern->groups == NULL)) { + njs_memory_error(vm); + return NULL; + } + + n = 0; + + do { + group = &pattern->groups[n]; + + group->capture = nxt_regex_named_captures(regex, &group->name, n); + group->hash = nxt_djb_hash(group->name.start, group->name.length); + + n++; + + } while (n != pattern->ngroups); + } + return pattern; fail: @@ -777,11 +815,15 @@ njs_regexp_exec_result(njs_vm_t *vm, njs njs_ret_t ret; nxt_uint_t i, n; njs_array_t *array; + njs_value_t name; + njs_object_t *groups; njs_object_prop_t *prop; + njs_regexp_group_t *group; nxt_lvlhsh_query_t lhq; static const njs_value_t string_index = njs_string("index"); static const njs_value_t string_input = njs_string("input"); + static const njs_value_t string_groups = njs_string("groups"); array = njs_array_alloc(vm, regexp->pattern->ncaptures, 0); if (nxt_slow_path(array == NULL)) { @@ -832,8 +874,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); if (nxt_slow_path(ret != NXT_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - goto fail; + goto insert_fail; } prop = njs_object_prop_alloc(vm, &string_input, ®exp->string, 1); @@ -846,16 +887,74 @@ njs_regexp_exec_result(njs_vm_t *vm, njs lhq.value = prop; ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + goto insert_fail; + } - if (nxt_fast_path(ret == NXT_OK)) { - vm->retval.data.u.array = array; - vm->retval.type = NJS_ARRAY; - vm->retval.data.truth = 1; + prop = njs_object_prop_alloc(vm, &string_groups, &njs_value_undefined, 1); + if (nxt_slow_path(prop == NULL)) { + goto fail; + } + + lhq.key_hash = NJS_GROUPS_HASH; + lhq.key = nxt_string_value("groups"); + lhq.value = prop; + + ret = nxt_lvlhsh_insert(&array->object.hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + goto insert_fail; + } + + if (regexp->pattern->ngroups != 0) { + groups = njs_object_alloc(vm); + if (nxt_slow_path(groups == NULL)) { + goto fail; + } + + prop->value.data.u.object = groups; + prop->value.type = NJS_OBJECT; + prop->value.data.truth = 1; + + i = 0; + + do { + group = ®exp->pattern->groups[i]; - ret = NXT_OK; - goto done; + ret = njs_string_set(vm, &name, group->name.start, + group->name.length); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + prop = njs_object_prop_alloc(vm, &name, + &array->start[group->capture], 1); + if (nxt_slow_path(prop == NULL)) { + goto fail; + } + + lhq.key_hash = group->hash; + lhq.key = group->name; + lhq.value = prop; + + ret = nxt_lvlhsh_insert(&groups->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + goto insert_fail; + } + + i++; + + } while (i < regexp->pattern->ngroups); } + vm->retval.data.u.array = array; + vm->retval.type = NJS_ARRAY; + vm->retval.data.truth = 1; + + ret = NXT_OK; + goto done; + +insert_fail: + njs_internal_error(vm, "lvlhsh insert failed"); fail: diff -r d94c836632c7 -r e9de8a5d423c njs/njs_regexp_pattern.h --- a/njs/njs_regexp_pattern.h Mon May 06 11:33:23 2019 +0300 +++ b/njs/njs_regexp_pattern.h Mon May 06 19:42:06 2019 +0300 @@ -17,6 +17,9 @@ typedef enum { } njs_regexp_utf8_t; +typedef struct njs_regexp_group_s njs_regexp_group_t; + + struct njs_regexp_pattern_s { nxt_regex_t regex[2]; @@ -30,20 +33,15 @@ struct njs_regexp_pattern_s { */ u_char *source; -#if (NXT_64BIT) - uint32_t ncaptures; + uint16_t ncaptures; + uint16_t ngroups; + uint8_t flags; /* 2 bits */ - uint8_t global; /* 1 bit */ uint8_t ignore_case; /* 1 bit */ uint8_t multiline; /* 1 bit */ -#else - uint16_t ncaptures; - uint8_t flags; /* 2 bits */ - uint8_t global:1; - uint8_t ignore_case:1; - uint8_t multiline:1; -#endif + + njs_regexp_group_t *groups; }; diff -r d94c836632c7 -r e9de8a5d423c njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon May 06 11:33:23 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 06 19:42:06 2019 +0300 @@ -7118,6 +7118,18 @@ static njs_unit_test_t njs_test[] = nxt_string("Quick Brown Fox Jumps Brown Jumps undefined " "4 25 The Quick Brown Fox Jumps Over The Lazy Dog") }, + { nxt_string("var r = /a/.exec('a'); ['groups' in r, typeof r.groups]"), + nxt_string("true,undefined") }, + + { nxt_string("var r = /(?[0-9]{2})\\/(?[0-9]{2})\\/(?[0-9]{4})/;" + "var g = r.exec('12/31/1986').groups;" + "g.d + '.' + g.m + '.' + g.y"), + nxt_string("31.12.1986") }, + + { nxt_string("var g = /(?(?no)?(?yes)?)/.exec('yes').groups;" + "[Object.keys(g).length,'no' in g, typeof g.no, g.yes, g.r]"), + nxt_string("3,true,undefined,yes,yes") }, + { nxt_string("var s; var r = /./g; while (s = r.exec('abc')); s"), nxt_string("null") }, diff -r d94c836632c7 -r e9de8a5d423c nxt/nxt_pcre.c --- a/nxt/nxt_pcre.c Mon May 06 11:33:23 2019 +0300 +++ b/nxt/nxt_pcre.c Mon May 06 19:42:06 2019 +0300 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +121,41 @@ nxt_regex_compile(nxt_regex_t *regex, u_ /* Reserve additional elements for the first "$0" capture. */ regex->ncaptures++; + if (regex->ncaptures > 1) { + err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_NAMECOUNT, + ®ex->nentries); + + if (nxt_slow_path(err < 0)) { + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, + "pcre_fullinfo(\"%s\", PCRE_INFO_NAMECOUNT) failed: %d", + pattern, err); + + goto done; + } + + if (regex->nentries != 0) { + err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_NAMEENTRYSIZE, + ®ex->entry_size); + + if (nxt_slow_path(err < 0)) { + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, "pcre_fullinfo(\"%s\", " + "PCRE_INFO_NAMEENTRYSIZE) failed: %d", pattern, err); + + goto done; + } + + err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_NAMETABLE, + ®ex->entries); + + if (nxt_slow_path(err < 0)) { + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, "pcre_fullinfo(\"%s\", " + "PCRE_INFO_NAMETABLE) failed: %d", pattern, err); + + goto done; + } + } + } + ret = NXT_OK; done: @@ -146,6 +182,28 @@ nxt_regex_ncaptures(nxt_regex_t *regex) } +nxt_int_t +nxt_regex_named_captures(nxt_regex_t *regex, nxt_str_t *name, int n) +{ + char *entry; + + if (name == NULL) { + return regex->nentries; + } + + if (n >= regex->nentries) { + return NXT_ERROR; + } + + entry = regex->entries + regex->entry_size * n; + + name->start = (u_char *) entry + 2; + name->length = nxt_strlen(name->start); + + return (entry[0] << 8) + entry[1]; +} + + nxt_regex_match_data_t * nxt_regex_match_data(nxt_regex_t *regex, nxt_regex_context_t *ctx) { diff -r d94c836632c7 -r e9de8a5d423c nxt/nxt_pcre.h --- a/nxt/nxt_pcre.h Mon May 06 11:33:23 2019 +0300 +++ b/nxt/nxt_pcre.h Mon May 06 19:42:06 2019 +0300 @@ -18,6 +18,9 @@ struct nxt_regex_s { pcre *code; pcre_extra *extra; int ncaptures; + int nentries; + int entry_size; + char *entries; }; diff -r d94c836632c7 -r e9de8a5d423c nxt/nxt_regex.h --- a/nxt/nxt_regex.h Mon May 06 11:33:23 2019 +0300 +++ b/nxt/nxt_regex.h Mon May 06 19:42:06 2019 +0300 @@ -31,6 +31,8 @@ NXT_EXPORT nxt_int_t nxt_regex_compile(n size_t len, nxt_uint_t options, nxt_regex_context_t *ctx); NXT_EXPORT nxt_bool_t nxt_regex_is_valid(nxt_regex_t *regex); NXT_EXPORT nxt_uint_t nxt_regex_ncaptures(nxt_regex_t *regex); +NXT_EXPORT nxt_int_t nxt_regex_named_captures(nxt_regex_t *regex, + nxt_str_t *name, int n); NXT_EXPORT nxt_regex_match_data_t *nxt_regex_match_data(nxt_regex_t *regex, nxt_regex_context_t *ctx); NXT_EXPORT void nxt_regex_match_data_free(nxt_regex_match_data_t *match_data, From vbart at nginx.com Mon May 6 17:48:46 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 17:48:46 +0000 Subject: [njs] Added own constructors to prototypes of built-in objects. Message-ID: details: https://hg.nginx.org/njs/rev/f876e5d1be41 branches: changeset: 951:f876e5d1be41 user: Valentin Bartenev date: Mon May 06 20:26:58 2019 +0300 description: Added own constructors to prototypes of built-in objects. diffstat: njs/njs_array.c | 6 ++++++ njs/njs_boolean.c | 6 ++++++ njs/njs_date.c | 6 ++++++ njs/njs_error.c | 42 ++++++++++++++++++++++++++++++++++++++++++ njs/njs_function.c | 6 ++++++ njs/njs_number.c | 6 ++++++ njs/njs_object.c | 2 +- njs/njs_object.h | 2 ++ njs/njs_regexp.c | 6 ++++++ njs/njs_string.c | 6 ++++++ njs/test/njs_unit_test.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 132 insertions(+), 1 deletions(-) diffs (348 lines): diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_array.c --- a/njs/njs_array.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_array.c Mon May 06 20:26:58 2019 +0300 @@ -2245,6 +2245,12 @@ static const njs_object_prop_t njs_arra }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_METHOD, .name = njs_string("slice"), .value = njs_native_function(njs_array_prototype_slice, diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_boolean.c --- a/njs/njs_boolean.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_boolean.c Mon May 06 20:26:58 2019 +0300 @@ -132,6 +132,12 @@ static const njs_object_prop_t njs_bool }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_boolean_prototype_value_of, 0, 0), diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_date.c --- a/njs/njs_date.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_date.c Mon May 06 20:26:58 2019 +0300 @@ -1942,6 +1942,12 @@ static const njs_object_prop_t njs_date }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_date_prototype_value_of, 0, diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_error.c --- a/njs/njs_error.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_error.c Mon May 06 20:26:58 2019 +0300 @@ -680,6 +680,12 @@ static const njs_object_prop_t njs_erro }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_PROPERTY, .name = njs_string("message"), .value = njs_string(""), @@ -713,6 +719,12 @@ static const njs_object_prop_t njs_eval .name = njs_string("name"), .value = njs_string("EvalError"), }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, }; @@ -774,6 +786,12 @@ static const njs_object_prop_t njs_rang .name = njs_string("name"), .value = njs_string("RangeError"), }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, }; @@ -791,6 +809,12 @@ static const njs_object_prop_t njs_refe .name = njs_string("name"), .value = njs_string("ReferenceError"), }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, }; @@ -808,6 +832,12 @@ static const njs_object_prop_t njs_synt .name = njs_string("name"), .value = njs_string("SyntaxError"), }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, }; @@ -825,6 +855,12 @@ static const njs_object_prop_t njs_type .name = njs_string("name"), .value = njs_string("TypeError"), }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, }; @@ -838,6 +874,12 @@ const njs_object_init_t njs_type_error_ static const njs_object_prop_t njs_uri_error_prototype_properties[] = { { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("URIError"), diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_function.c --- a/njs/njs_function.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_function.c Mon May 06 20:26:58 2019 +0300 @@ -1186,6 +1186,12 @@ static const njs_object_prop_t njs_func }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_METHOD, .name = njs_string("call"), .value = njs_native_function(njs_function_prototype_call, 0, 0), diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_number.c --- a/njs/njs_number.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_number.c Mon May 06 20:26:58 2019 +0300 @@ -645,6 +645,12 @@ static const njs_object_prop_t njs_numb }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_number_prototype_value_of, 0, 0), diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_object.c --- a/njs/njs_object.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_object.c Mon May 06 20:26:58 2019 +0300 @@ -2869,7 +2869,7 @@ njs_object_prototype_proto(njs_vm_t *vm, * "constructor" getter. The properties are set to appropriate function. */ -static njs_ret_t +njs_ret_t njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_object.h --- a/njs/njs_object.h Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_object.h Mon May 06 20:26:58 2019 +0300 @@ -103,6 +103,8 @@ njs_value_t *njs_property_prototype_crea njs_object_t *prototype); njs_ret_t njs_object_prototype_proto(njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +njs_ret_t njs_object_prototype_create_constructor(njs_vm_t *vm, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); njs_value_t *njs_property_constructor_create(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_value_t *constructor); njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_regexp.c --- a/njs/njs_regexp.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_regexp.c Mon May 06 20:26:58 2019 +0300 @@ -1015,6 +1015,12 @@ static const njs_object_prop_t njs_rege { { .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { + .type = NJS_PROPERTY_HANDLER, .name = njs_string("lastIndex"), .value = njs_prop_handler(njs_regexp_prototype_last_index), }, diff -r e9de8a5d423c -r f876e5d1be41 njs/njs_string.c --- a/njs/njs_string.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/njs_string.c Mon May 06 20:26:58 2019 +0300 @@ -3787,6 +3787,12 @@ static const njs_object_prop_t njs_stri }, { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("constructor"), + .value = njs_prop_handler(njs_object_prototype_create_constructor), + }, + + { .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_string_prototype_value_of, 0, 0), diff -r e9de8a5d423c -r f876e5d1be41 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon May 06 19:42:06 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 06 20:26:58 2019 +0300 @@ -7258,6 +7258,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Error.prototype.constructor == Error"), nxt_string("true") }, + { nxt_string("Error.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Error().__proto__ == Error.prototype"), nxt_string("true") }, @@ -7401,6 +7404,24 @@ static njs_unit_test_t njs_test[] = { nxt_string("URIError.prototype.constructor == URIError"), nxt_string("true") }, + { nxt_string("EvalError.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + + { nxt_string("RangeError.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + + { nxt_string("ReferenceError.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + + { nxt_string("SyntaxError.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + + { nxt_string("TypeError.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + + { nxt_string("URIError.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("EvalError().__proto__ == EvalError.prototype"), nxt_string("true") }, @@ -8006,6 +8027,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.prototype.constructor === Object"), nxt_string("true") }, + { nxt_string("Object.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Object.prototype.__proto__ === null"), nxt_string("true") }, @@ -8174,6 +8198,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Array.prototype.constructor === Array"), nxt_string("true") }, + { nxt_string("Array.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Array.prototype.__proto__ === Object.prototype"), nxt_string("true") }, @@ -8252,6 +8279,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Boolean.prototype.constructor === Boolean"), nxt_string("true") }, + { nxt_string("Boolean.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Boolean.prototype.__proto__ === Object.prototype"), nxt_string("true") }, @@ -8362,6 +8392,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Number.prototype.constructor === Number"), nxt_string("true") }, + { nxt_string("Number.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Number.prototype.__proto__ === Object.prototype"), nxt_string("true") }, @@ -8576,6 +8609,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("String.prototype.constructor === String"), nxt_string("true") }, + { nxt_string("String.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("String.prototype.__proto__ === Object.prototype"), nxt_string("true") }, @@ -8612,6 +8648,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Function.prototype.constructor === Function"), nxt_string("true") }, + { nxt_string("Function.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Function.prototype.__proto__ === Object.prototype"), nxt_string("true") }, @@ -8654,6 +8693,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("RegExp.prototype.constructor === RegExp"), nxt_string("true") }, + { nxt_string("RegExp.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("RegExp.prototype.__proto__ === Object.prototype"), nxt_string("true") }, @@ -10049,6 +10091,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Date.prototype.constructor === Date"), nxt_string("true") }, + { nxt_string("Date.prototype.hasOwnProperty('constructor')"), + nxt_string("true") }, + { nxt_string("Date.prototype.__proto__ === Object.prototype"), nxt_string("true") }, From vbart at nginx.com Mon May 6 18:25:17 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 06 May 2019 18:25:17 +0000 Subject: [njs] Fixed return value on deleting non-existent property. Message-ID: details: https://hg.nginx.org/njs/rev/96c78f35a809 branches: changeset: 952:96c78f35a809 user: Valentin Bartenev date: Mon May 06 21:24:31 2019 +0300 description: Fixed return value on deleting non-existent property. diffstat: njs/njs_vm.c | 9 +-------- njs/test/njs_unit_test.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 9 deletions(-) diffs (78 lines): diff -r f876e5d1be41 -r 96c78f35a809 njs/njs_vm.c --- a/njs/njs_vm.c Mon May 06 20:26:58 2019 +0300 +++ b/njs/njs_vm.c Mon May 06 21:24:31 2019 +0300 @@ -712,12 +712,9 @@ njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *property) { njs_ret_t ret; - const njs_value_t *retval; njs_object_prop_t *prop; njs_property_query_t pq; - retval = &njs_value_false; - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_DELETE, 1); ret = njs_property_query(vm, &pq, object, property); @@ -734,7 +731,6 @@ njs_vmcode_property_delete(njs_vm_t *vm, case NJS_PROPERTY_REF: njs_set_invalid(prop->value.data.u.value); - retval = &njs_value_true; goto done; case NJS_PROPERTY_HANDLER: @@ -744,7 +740,6 @@ njs_vmcode_property_delete(njs_vm_t *vm, return ret; } - retval = &njs_value_true; goto done; } @@ -768,8 +763,6 @@ njs_vmcode_property_delete(njs_vm_t *vm, prop->type = NJS_WHITEOUT; njs_set_invalid(&prop->value); - retval = &njs_value_true; - break; case NXT_DECLINED: @@ -784,7 +777,7 @@ njs_vmcode_property_delete(njs_vm_t *vm, done: - vm->retval = *retval; + vm->retval = njs_value_true; return sizeof(njs_vmcode_3addr_t); } diff -r f876e5d1be41 -r 96c78f35a809 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon May 06 20:26:58 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 06 21:24:31 2019 +0300 @@ -3128,6 +3128,15 @@ static njs_unit_test_t njs_test[] = { nxt_string("delete 1"), nxt_string("true") }, + { nxt_string("var a = []; delete a[1]"), + nxt_string("true") }, + + { nxt_string("var o = {}; [delete o.m, delete o.m]"), + nxt_string("true,true") }, + + { nxt_string("[delete Array.nonexistent, delete Array.Array]"), + nxt_string("true,true") }, + { nxt_string("var a; delete (a = 1); a"), nxt_string("1") }, @@ -3261,7 +3270,7 @@ static njs_unit_test_t njs_test[] = nxt_string("1,2,34") }, { nxt_string("delete[]['4e9']"), - nxt_string("false") }, + nxt_string("true") }, { nxt_string("var n = 1, a = [ n += 1 ]; a"), nxt_string("2") }, From fanjinke at hygon.cn Tue May 7 07:25:59 2019 From: fanjinke at hygon.cn (Jinke Fan) Date: Tue, 7 May 2019 07:25:59 +0000 Subject: [PATCH] Add support cache line size for Hygon Dhyana CPU Message-ID: <3b71cea366414c7b8bb6f21acf73480c@hygon.cn> # HG changeset patch # User Fanjinke # Date 1557209225 -28800 # Tue May 07 14:07:05 2019 +0800 # Node ID 9bc6da16b217ce2c5fc63048a705c2b3195d3bb7 # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 Add support cache line size for Hygon Dhyana CPU Background: Chengdu Haiguang IC Design Co., Ltd (Hygon) is a Joint Venture between AMD and Haiguang Information Technology Co.,Ltd., aims at providing high performance x86 processor for China server market. Its first generation processor codename is Dhyana, which originates from AMD technology and shares most of the architecture with AMD's family 17h, but with different CPU Vendor ID("HygonGenuine")/Family series number(Family 18h). diff -r 16a1adadf437 -r 9bc6da16b217 src/core/ngx_cpuinfo.c --- a/src/core/ngx_cpuinfo.c Wed Apr 24 16:38:56 2019 +0300 +++ b/src/core/ngx_cpuinfo.c Tue May 07 14:07:05 2019 +0800 @@ -124,6 +124,8 @@ } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { ngx_cacheline_size = 64; + } else if (ngx_strcmp(vendor, "HygonGenuine") == 0) { + ngx_cacheline_size = 64; } } From vbart at nginx.com Tue May 7 13:52:52 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 07 May 2019 13:52:52 +0000 Subject: [njs] Made configurable "length", "name", and most of built-in methods. Message-ID: details: https://hg.nginx.org/njs/rev/a84f514e864d branches: changeset: 953:a84f514e864d user: Valentin Bartenev date: Mon May 06 05:40:03 2019 +0300 description: Made configurable "length", "name", and most of built-in methods. diffstat: njs/njs_array.c | 28 ++++++++++++++++++++++++++ njs/njs_boolean.c | 6 +++++ njs/njs_builtin.c | 1 + njs/njs_crypto.c | 11 ++++++++++ njs/njs_date.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ njs/njs_error.c | 31 +++++++++++++++++++++++++++++ njs/njs_fs.c | 7 ++++++ njs/njs_function.c | 12 +++++++++++ njs/njs_json.c | 2 + njs/njs_math.c | 36 +++++++++++++++++++++++++++++++++ njs/njs_number.c | 20 ++++++++++++++++++ njs/njs_object.c | 27 +++++++++++++++++++++++- njs/njs_object.h | 1 + njs/njs_regexp.c | 9 ++++++++ njs/njs_string.c | 45 ++++++++++++++++++++++++++++++++++++++++++ njs/njs_vm.c | 51 +++++++++++++++++++++++++++++++++-------------- njs/test/njs_unit_test.c | 50 +++++++++++++++++++++++++++++++++++++++++++--- 17 files changed, 365 insertions(+), 21 deletions(-) diffs (truncated from 2439 to 1000 lines): diff -r 96c78f35a809 -r a84f514e864d njs/njs_array.c --- a/njs/njs_array.c Mon May 06 21:24:31 2019 +0300 +++ b/njs/njs_array.c Mon May 06 05:40:03 2019 +0300 @@ -370,6 +370,7 @@ static const njs_object_prop_t njs_arra .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Array"), + .configurable = 1, }, /* Array.length == 1. */ @@ -377,6 +378,7 @@ static const njs_object_prop_t njs_arra .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* Array.prototype. */ @@ -391,6 +393,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("isArray"), .value = njs_native_function(njs_array_is_array, 0, 0), + .configurable = 1, }, /* ES6. */ @@ -399,6 +402,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("of"), .value = njs_native_function(njs_array_of, 0, 0), + .configurable = 1, }, }; @@ -2256,30 +2260,35 @@ static const njs_object_prop_t njs_arra .value = njs_native_function(njs_array_prototype_slice, njs_continuation_size(njs_array_slice_t), NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("push"), .value = njs_native_function(njs_array_prototype_push, 0, 0), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("pop"), .value = njs_native_function(njs_array_prototype_pop, 0, 0), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("unshift"), .value = njs_native_function(njs_array_prototype_unshift, 0, 0), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("shift"), .value = njs_native_function(njs_array_prototype_shift, 0, 0), + .configurable = 1, }, { @@ -2287,6 +2296,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("splice"), .value = njs_native_function(njs_array_prototype_splice, 0, NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .configurable = 1, }, { @@ -2294,6 +2304,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("reverse"), .value = njs_native_function(njs_array_prototype_reverse, 0, NJS_OBJECT_ARG), + .configurable = 1, }, { @@ -2301,6 +2312,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("toString"), .value = njs_native_function(njs_array_prototype_to_string, NJS_CONTINUATION_SIZE, 0), + .configurable = 1, }, { @@ -2309,12 +2321,14 @@ static const njs_object_prop_t njs_arra .value = njs_native_function(njs_array_prototype_join, njs_continuation_size(njs_array_join_t), NJS_OBJECT_ARG, NJS_STRING_ARG), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("concat"), .value = njs_native_function(njs_array_prototype_concat, 0, 0), + .configurable = 1, }, { @@ -2322,6 +2336,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("indexOf"), .value = njs_native_function(njs_array_prototype_index_of, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .configurable = 1, }, { @@ -2329,6 +2344,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("lastIndexOf"), .value = njs_native_function(njs_array_prototype_last_index_of, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .configurable = 1, }, /* ES7. */ @@ -2337,6 +2353,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("includes"), .value = njs_native_function(njs_array_prototype_includes, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .configurable = 1, }, { @@ -2344,6 +2361,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("forEach"), .value = njs_native_function(njs_array_prototype_for_each, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, { @@ -2351,6 +2369,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("some"), .value = njs_native_function(njs_array_prototype_some, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, { @@ -2358,6 +2377,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("every"), .value = njs_native_function(njs_array_prototype_every, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, /* ES6. */ @@ -2367,6 +2387,7 @@ static const njs_object_prop_t njs_arra .value = njs_native_function(njs_array_prototype_fill, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2374,6 +2395,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("filter"), .value = njs_native_function(njs_array_prototype_filter, njs_continuation_size(njs_array_filter_t), 0), + .configurable = 1, }, /* ES6. */ @@ -2382,6 +2404,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("find"), .value = njs_native_function(njs_array_prototype_find, njs_continuation_size(njs_array_find_t), 0), + .configurable = 1, }, /* ES6. */ @@ -2390,6 +2413,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("findIndex"), .value = njs_native_function(njs_array_prototype_find_index, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, { @@ -2397,6 +2421,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("map"), .value = njs_native_function(njs_array_prototype_map, njs_continuation_size(njs_array_map_t), 0), + .configurable = 1, }, { @@ -2404,6 +2429,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("reduce"), .value = njs_native_function(njs_array_prototype_reduce, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, { @@ -2411,6 +2437,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("reduceRight"), .value = njs_native_function(njs_array_prototype_reduce_right, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, { @@ -2418,6 +2445,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("sort"), .value = njs_native_function(njs_array_prototype_sort, njs_continuation_size(njs_array_iter_t), 0), + .configurable = 1, }, }; diff -r 96c78f35a809 -r a84f514e864d njs/njs_boolean.c --- a/njs/njs_boolean.c Mon May 06 21:24:31 2019 +0300 +++ b/njs/njs_boolean.c Mon May 06 05:40:03 2019 +0300 @@ -46,6 +46,7 @@ static const njs_object_prop_t njs_bool .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Boolean"), + .configurable = 1, }, /* Boolean.length == 1. */ @@ -53,6 +54,7 @@ static const njs_object_prop_t njs_bool .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* Boolean.prototype. */ @@ -129,24 +131,28 @@ static const njs_object_prop_t njs_bool .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), .value = njs_prop_handler(njs_primitive_prototype_get_proto), + .configurable = 1, }, { .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_boolean_prototype_value_of, 0, 0), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_boolean_prototype_to_string, 0, 0), + .configurable = 1, }, }; diff -r 96c78f35a809 -r a84f514e864d njs/njs_builtin.c --- a/njs/njs_builtin.c Mon May 06 21:24:31 2019 +0300 +++ b/njs/njs_builtin.c Mon May 06 05:40:03 2019 +0300 @@ -1087,6 +1087,7 @@ static const njs_object_prop_t njs_njs_ .name = njs_string("dump"), .value = njs_native_function(njs_dump_value, 0, NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, }; diff -r 96c78f35a809 -r a84f514e864d njs/njs_crypto.c --- a/njs/njs_crypto.c Mon May 06 21:24:31 2019 +0300 +++ b/njs/njs_crypto.c Mon May 06 05:40:03 2019 +0300 @@ -331,12 +331,14 @@ static const njs_object_prop_t njs_hash .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Hash"), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_hash_prototype_to_string, 0, 0), + .configurable = 1, }, { @@ -344,6 +346,7 @@ static const njs_object_prop_t njs_hash .name = njs_string("update"), .value = njs_native_function(njs_hash_prototype_update, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .configurable = 1, }, { @@ -351,6 +354,7 @@ static const njs_object_prop_t njs_hash .name = njs_string("digest"), .value = njs_native_function(njs_hash_prototype_digest, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .configurable = 1, }, }; @@ -595,12 +599,14 @@ static const njs_object_prop_t njs_hmac .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Hmac"), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_hmac_prototype_to_string, 0, 0), + .configurable = 1, }, { @@ -608,6 +614,7 @@ static const njs_object_prop_t njs_hmac .name = njs_string("update"), .value = njs_native_function(njs_hmac_prototype_update, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .configurable = 1, }, { @@ -615,6 +622,7 @@ static const njs_object_prop_t njs_hmac .name = njs_string("digest"), .value = njs_native_function(njs_hmac_prototype_digest, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .configurable = 1, }, }; @@ -647,6 +655,7 @@ static const njs_object_prop_t njs_cryp .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("crypto"), + .configurable = 1, }, { @@ -660,6 +669,7 @@ static const njs_object_prop_t njs_cryp .name = njs_string("createHash"), .value = njs_native_function(njs_crypto_create_hash, 0, NJS_SKIP_ARG), + .configurable = 1, }, { @@ -667,6 +677,7 @@ static const njs_object_prop_t njs_cryp .name = njs_string("createHmac"), .value = njs_native_function(njs_crypto_create_hmac, 0, NJS_SKIP_ARG), + .configurable = 1, }, }; diff -r 96c78f35a809 -r a84f514e864d njs/njs_date.c --- a/njs/njs_date.c Mon May 06 21:24:31 2019 +0300 +++ b/njs/njs_date.c Mon May 06 05:40:03 2019 +0300 @@ -896,6 +896,7 @@ static const njs_object_prop_t njs_date .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Date"), + .configurable = 1, }, /* Date.length == 7. */ @@ -903,6 +904,7 @@ static const njs_object_prop_t njs_date .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 7.0), + .configurable = 1, }, /* Date.prototype. */ @@ -916,12 +918,14 @@ static const njs_object_prop_t njs_date .type = NJS_METHOD, .name = njs_string("UTC"), .value = njs_native_function(njs_date_utc, 0, 0), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("now"), .value = njs_native_function(njs_date_now, 0, 0), + .configurable = 1, }, { @@ -929,6 +933,7 @@ static const njs_object_prop_t njs_date .name = njs_string("parse"), .value = njs_native_function(njs_date_parse, 0, NJS_SKIP_ARG, NJS_STRING_ARG), + .configurable = 1, }, }; @@ -1939,6 +1944,7 @@ static const njs_object_prop_t njs_date .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), .value = njs_prop_handler(njs_primitive_prototype_get_proto), + .configurable = 1, }, { @@ -1952,6 +1958,7 @@ static const njs_object_prop_t njs_date .name = njs_string("valueOf"), .value = njs_native_function(njs_date_prototype_value_of, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -1959,6 +1966,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toString"), .value = njs_native_function(njs_date_prototype_to_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -1966,6 +1974,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toDateString"), .value = njs_native_function(njs_date_prototype_to_date_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -1973,6 +1982,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toTimeString"), .value = njs_native_function(njs_date_prototype_to_time_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -1980,6 +1990,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toLocaleString"), .value = njs_native_function(njs_date_prototype_to_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -1987,6 +1998,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("toLocaleDateString"), .value = njs_native_function(njs_date_prototype_to_date_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -1994,6 +2006,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("toLocaleTimeString"), .value = njs_native_function(njs_date_prototype_to_time_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2001,6 +2014,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toUTCString"), .value = njs_native_function(njs_date_prototype_to_utc_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2008,6 +2022,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toISOString"), .value = njs_native_function(njs_date_prototype_to_iso_string, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2015,6 +2030,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getTime"), .value = njs_native_function(njs_date_prototype_value_of, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2022,6 +2038,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getFullYear"), .value = njs_native_function(njs_date_prototype_get_full_year, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2029,6 +2046,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCFullYear"), .value = njs_native_function(njs_date_prototype_get_utc_full_year, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2036,6 +2054,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getMonth"), .value = njs_native_function(njs_date_prototype_get_month, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2043,6 +2062,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCMonth"), .value = njs_native_function(njs_date_prototype_get_utc_month, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2050,6 +2070,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getDate"), .value = njs_native_function(njs_date_prototype_get_date, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2057,6 +2078,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCDate"), .value = njs_native_function(njs_date_prototype_get_utc_date, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2064,6 +2086,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getDay"), .value = njs_native_function(njs_date_prototype_get_day, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2071,6 +2094,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCDay"), .value = njs_native_function(njs_date_prototype_get_utc_day, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2078,6 +2102,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getHours"), .value = njs_native_function(njs_date_prototype_get_hours, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2085,6 +2110,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCHours"), .value = njs_native_function(njs_date_prototype_get_utc_hours, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2092,6 +2118,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getMinutes"), .value = njs_native_function(njs_date_prototype_get_minutes, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2099,6 +2126,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCMinutes"), .value = njs_native_function(njs_date_prototype_get_utc_minutes, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2106,6 +2134,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getSeconds"), .value = njs_native_function(njs_date_prototype_get_seconds, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2113,6 +2142,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCSeconds"), .value = njs_native_function(njs_date_prototype_get_seconds, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2120,6 +2150,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("getMilliseconds"), .value = njs_native_function(njs_date_prototype_get_milliseconds, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2127,6 +2158,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("getUTCMilliseconds"), .value = njs_native_function(njs_date_prototype_get_milliseconds, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2134,6 +2166,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("getTimezoneOffset"), .value = njs_native_function(njs_date_prototype_get_timezone_offset, 0, NJS_DATE_ARG), + .configurable = 1, }, { @@ -2141,6 +2174,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setTime"), .value = njs_native_function(njs_date_prototype_set_time, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2148,6 +2182,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("setMilliseconds"), .value = njs_native_function(njs_date_prototype_set_milliseconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2155,6 +2190,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("setUTCMilliseconds"), .value = njs_native_function(njs_date_prototype_set_milliseconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2162,6 +2198,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setSeconds"), .value = njs_native_function(njs_date_prototype_set_seconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2169,6 +2206,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setUTCSeconds"), .value = njs_native_function(njs_date_prototype_set_seconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2177,6 +2215,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_minutes, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2185,6 +2224,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_utc_minutes, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2193,6 +2233,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_hours, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2201,6 +2242,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_utc_hours, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2208,6 +2250,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setDate"), .value = njs_native_function(njs_date_prototype_set_date, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2215,6 +2258,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setUTCDate"), .value = njs_native_function(njs_date_prototype_set_utc_date, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2222,6 +2266,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setMonth"), .value = njs_native_function(njs_date_prototype_set_month, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2229,6 +2274,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setUTCMonth"), .value = njs_native_function(njs_date_prototype_set_utc_month, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2237,6 +2283,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_full_year, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2245,6 +2292,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_utc_full_year, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .configurable = 1, }, { @@ -2252,6 +2300,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toJSON"), .value = njs_native_function(njs_date_prototype_to_json, NJS_CONTINUATION_SIZE, 0), + .configurable = 1, }, }; diff -r 96c78f35a809 -r a84f514e864d njs/njs_error.c --- a/njs/njs_error.c Mon May 06 21:24:31 2019 +0300 +++ b/njs/njs_error.c Mon May 06 05:40:03 2019 +0300 @@ -171,6 +171,7 @@ static const njs_object_prop_t njs_erro .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Error"), + .configurable = 1, }, /* Error.length == 1. */ @@ -178,6 +179,7 @@ static const njs_object_prop_t njs_erro .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* Error.prototype. */ @@ -211,6 +213,7 @@ static const njs_object_prop_t njs_eval .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("EvalError"), + .configurable = 1, }, /* EvalError.length == 1. */ @@ -218,6 +221,7 @@ static const njs_object_prop_t njs_eval .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* EvalError.prototype. */ @@ -251,6 +255,7 @@ static const njs_object_prop_t njs_inte .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("InternalError"), + .configurable = 1, }, /* InternalError.length == 1. */ @@ -258,6 +263,7 @@ static const njs_object_prop_t njs_inte .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* InternalError.prototype. */ @@ -291,6 +297,7 @@ static const njs_object_prop_t njs_rang .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("RangeError"), + .configurable = 1, }, /* RangeError.length == 1. */ @@ -298,6 +305,7 @@ static const njs_object_prop_t njs_rang .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* RangeError.prototype. */ @@ -331,6 +339,7 @@ static const njs_object_prop_t njs_refe .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("ReferenceError"), + .configurable = 1, }, /* ReferenceError.length == 1. */ @@ -338,6 +347,7 @@ static const njs_object_prop_t njs_refe .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* ReferenceError.prototype. */ @@ -371,6 +381,7 @@ static const njs_object_prop_t njs_synt .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("SyntaxError"), + .configurable = 1, }, /* SyntaxError.length == 1. */ @@ -378,6 +389,7 @@ static const njs_object_prop_t njs_synt .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* SyntaxError.prototype. */ @@ -411,6 +423,7 @@ static const njs_object_prop_t njs_type .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("TypeError"), + .configurable = 1, }, /* TypeError.length == 1. */ @@ -418,6 +431,7 @@ static const njs_object_prop_t njs_type .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* TypeError.prototype. */ @@ -451,6 +465,7 @@ static const njs_object_prop_t njs_uri_ .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("URIError"), + .configurable = 1, }, /* URIError.length == 1. */ @@ -458,6 +473,7 @@ static const njs_object_prop_t njs_uri_ .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* URIError.prototype. */ @@ -553,6 +569,7 @@ static const njs_object_prop_t njs_memo .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("MemoryError"), + .configurable = 1, }, /* MemoryError.length == 1. */ @@ -560,6 +577,7 @@ static const njs_object_prop_t njs_memo .type = NJS_PROPERTY, .name = njs_string("length"), .value = njs_value(NJS_NUMBER, 1, 1.0), + .configurable = 1, }, /* MemoryError.prototype. */ @@ -677,30 +695,35 @@ static const njs_object_prop_t njs_erro .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Error"), + .configurable = 1, }, { .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, { .type = NJS_PROPERTY, .name = njs_string("message"), .value = njs_string(""), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_error_prototype_value_of, 0, 0), + .configurable = 1, }, { .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_error_prototype_to_string, 0, 0), + .configurable = 1, }, }; @@ -718,6 +741,7 @@ static const njs_object_prop_t njs_eval .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("EvalError"), + .configurable = 1, }, { @@ -761,6 +785,7 @@ static const njs_object_prop_t njs_inte .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("InternalError"), + .configurable = 1, }, { @@ -768,6 +793,7 @@ static const njs_object_prop_t njs_inte .name = njs_string("toString"), .value = njs_native_function(njs_internal_error_prototype_to_string, 0, 0), + .configurable = 1, }, }; @@ -785,6 +811,7 @@ static const njs_object_prop_t njs_rang .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("RangeError"), + .configurable = 1, }, { @@ -808,6 +835,7 @@ static const njs_object_prop_t njs_refe .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("ReferenceError"), + .configurable = 1, }, { @@ -831,6 +859,7 @@ static const njs_object_prop_t njs_synt .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("SyntaxError"), + .configurable = 1, }, { @@ -854,6 +883,7 @@ static const njs_object_prop_t njs_type .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("TypeError"), + .configurable = 1, From xeioex at nginx.com Tue May 7 16:50:59 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 07 May 2019 16:50:59 +0000 Subject: [njs] Improved expect tests. Message-ID: details: https://hg.nginx.org/njs/rev/a7a632e7d686 branches: changeset: 954:a7a632e7d686 user: Dmitry Volyntsev date: Tue May 07 19:50:35 2019 +0300 description: Improved expect tests. diffstat: auto/expect | 3 ++- njs/test/inputrc | 5 +++++ njs/test/njs_expect_test.exp | 44 ++++++++++++++++++++++++++++++-------------- 3 files changed, 37 insertions(+), 15 deletions(-) diffs (154 lines): diff -r a84f514e864d -r a7a632e7d686 auto/expect --- a/auto/expect Mon May 06 05:40:03 2019 +0300 +++ b/auto/expect Tue May 07 19:50:35 2019 +0300 @@ -21,7 +21,8 @@ if [ $nxt_found = yes -a $NXT_HAVE_READL cat << END >> $NXT_MAKEFILE njs_expect_test: njs njs/test/njs_expect_test.exp - PATH=$NXT_BUILD_DIR:\$(PATH) expect -f njs/test/njs_expect_test.exp + INPUTRC=njs/test/inputrc PATH=$NXT_BUILD_DIR:\$(PATH) \ + expect -f njs/test/njs_expect_test.exp END else diff -r a84f514e864d -r a7a632e7d686 njs/test/inputrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/inputrc Tue May 07 19:50:35 2019 +0300 @@ -0,0 +1,5 @@ +set bell-style audible +set print-completions-horizontally on +set completion-display-width 0 +set completion-ignore-case on +set page-completions off diff -r a84f514e864d -r a7a632e7d686 njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Mon May 06 05:40:03 2019 +0300 +++ b/njs/test/njs_expect_test.exp Tue May 07 19:50:35 2019 +0300 @@ -12,6 +12,18 @@ proc njs_test {body {opts ""}} { eval spawn -nottycopy njs $opts } + # TODO: + # SIGINT handling race condition + # deb9-amd64-generic-njs-try + # ub1404-armv7-generic-njs-try + # ub1804-arm64-generic-njs-try + # UTF8 terminal support issue + # sol11-amd64-sunpro-njs-try + # ub1604-arm64-generic-njs-try + + # set timeout 30 + # expect_before timeout { exit 1 } + expect -re "interactive njs \\d+\.\\d+\.\\d+\r\n\r" expect "v. -> the properties and prototype methods of v.\r type console.help() for more information\r @@ -33,7 +45,6 @@ type console.help() for more information proc njs_run {opts output} { eval spawn -nottycopy njs $opts expect -re $output - expect eof } njs_test { @@ -41,7 +52,7 @@ njs_test { "njs.version\r\n\*\.\*\.\*"} } -# simple multi line interation +# simple multi line interaction njs_test { {"var a = 1\r\n" "var a = 1\r\nundefined\r\n>> "} @@ -62,30 +73,33 @@ njs_test { } # Global completions, single partial match + +# \a* is WORKAROUND for libedit-20170329.3.1-r3 +# which inserts '\rESC[6G' after '\a'. njs_test { {"O\t" - "O\abject"} + "O\a*bject"} } njs_test { {"Ma\t" - "Ma\ath"} + "Ma\a*th"} } njs_test { {"conso\t" - "conso\ale"} + "conso\a*le"} } # Global completions, multiple partial match njs_test { {"cons\t\t" - "console*console.help*console.time*const"} + "console*const"} } njs_test { {"O\t" - "O\abject"} + "O\a*bject"} {".\t\t" "Object.create*Object.isSealed"} } @@ -97,16 +111,16 @@ njs_test { njs_test { {"Object.g\t" - "Object.g\aet"} - {"\t" + "Object.g\a*et"} + {"\t\t" "Object.getOwnPropertyDescriptor*Object.getPrototypeOf"} } njs_test { {"Ma\t" - "Ma\ath"} + "Ma\a*th"} {".\t\t" - "Math.__proto__*Math.cbrt*Math.fround*Math.log2"} + "Math.abs*Math.atan2"} } # Global completions, no matches @@ -133,11 +147,13 @@ njs_test { "a*aa*arguments*await"} } +# z*z is WORKAROUND for libedit-20170329.3.1-r3 +# which inserts bogus '\a' between 'z' njs_test { {"var zz = 1\r\n" "var zz = 1\r\nundefined\r\n>> "} {"1 + z\t\r\n" - "1 + zz\r\n2"} + "1 + z*z*\r\n2"} } njs_test { @@ -375,7 +391,7 @@ njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} {"fs.read\t" - "fs.read\aFile"} + "fs.read\a*File"} } # require('fs').readFile() @@ -641,7 +657,7 @@ njs_run "-v" "\\d+\.\\d+\.\\d+" njs_test { {"1+1\r\n" - "00000 ADD*\r\n00040 STOP*\r\n\r\n2"} + "00000 ADD*\r\n*2"} {"for (var n in [1]) {try {break} finally{}}\r\n" "00000 ARRAY*\r\n*TRY BREAK*STOP*\r\n\r\nundefined"} {"(function() {try {return} finally{}})()\r\n" From xeioex at nginx.com Tue May 7 16:50:59 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 07 May 2019 16:50:59 +0000 Subject: [njs] Shell: sorting arguments in alphabetic order. Message-ID: details: https://hg.nginx.org/njs/rev/6adf4063e1bb branches: changeset: 955:6adf4063e1bb user: Dmitry Volyntsev date: Tue May 07 19:50:38 2019 +0300 description: Shell: sorting arguments in alphabetic order. diffstat: njs/njs_shell.c | 50 +++++++++++++++++----------------- njs/test/njs_expect_test.exp | 63 +++++++++++++++++++++++-------------------- 2 files changed, 58 insertions(+), 55 deletions(-) diffs (171 lines): diff -r a7a632e7d686 -r 6adf4063e1bb njs/njs_shell.c --- a/njs/njs_shell.c Tue May 07 19:50:35 2019 +0300 +++ b/njs/njs_shell.c Tue May 07 19:50:38 2019 +0300 @@ -30,15 +30,16 @@ typedef struct { + uint8_t disassemble; + uint8_t interactive; + uint8_t module; + uint8_t quiet; + uint8_t sandbox; + uint8_t version; + char *file; size_t n_paths; char **paths; - nxt_int_t version; - nxt_int_t disassemble; - nxt_int_t interactive; - nxt_int_t sandbox; - nxt_int_t quiet; - nxt_int_t module; } njs_opts_t; @@ -284,10 +285,10 @@ njs_get_options(njs_opts_t *opts, int ar "\n" "Options:\n" " -d print disassembled code.\n" + " -p set path prefix for modules.\n" " -q disable interactive introduction prompt.\n" " -s sandbox mode.\n" " -t script|module source code type (script is default).\n" - " -p set path prefix for modules.\n" " -v print njs version and exit.\n" " | - run code from a file or stdin.\n"; @@ -315,6 +316,23 @@ njs_get_options(njs_opts_t *opts, int ar opts->disassemble = 1; break; + case 'p': + if (++i < argc) { + opts->n_paths++; + paths = realloc(opts->paths, opts->n_paths * sizeof(char *)); + if (paths == NULL) { + nxt_error("failed to add path\n"); + return NXT_ERROR; + } + + opts->paths = paths; + opts->paths[opts->n_paths - 1] = argv[i]; + break; + } + + nxt_error("option \"-p\" requires directory name\n"); + return NXT_ERROR; + case 'q': opts->quiet = 1; break; @@ -339,24 +357,6 @@ njs_get_options(njs_opts_t *opts, int ar nxt_error("option \"-t\" requires source type\n"); return NXT_ERROR; - - case 'p': - if (++i < argc) { - opts->n_paths++; - paths = realloc(opts->paths, opts->n_paths * sizeof(char *)); - if (paths == NULL) { - nxt_error("failed to add path\n"); - return NXT_ERROR; - } - - opts->paths = paths; - opts->paths[opts->n_paths - 1] = argv[i]; - break; - } - - nxt_error("option \"-p\" requires directory name\n"); - return NXT_ERROR; - case 'v': case 'V': opts->version = 1; diff -r a7a632e7d686 -r 6adf4063e1bb njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Tue May 07 19:50:35 2019 +0300 +++ b/njs/test/njs_expect_test.exp Tue May 07 19:50:38 2019 +0300 @@ -649,10 +649,6 @@ njs_run "-p njs/test/module ./njs/test/m njs_run "-h" "Interactive njs shell.\r\n\r\nOptions:" -# version - -njs_run "-v" "\\d+\.\\d+\.\\d+" - # disassemble njs_test { @@ -664,32 +660,6 @@ njs_test { "00000 TRY START*\r\n*TRY RETURN*STOP*\r\n\r\nundefined"} } "-d" -# sandboxing - -njs_test { - {"var fs = require('fs')\r\n" - "Error: Cannot find module \"fs\"\r\n"} -} "-s" - -njs_test { - {"var crypto = require('crypto')\r\n" - "undefined\r\n"} -} "-s" - -# source type - -njs_test { - {"this\r\n" - "this\r\nundefined"} - {"(() => this)()\r\n" - "(() => this)()\r\nundefined"} -} "-t module" - -njs_test { - {"this.NaN\r\n" - "this.NaN\r\nNaN"} -} "-t script" - # modules njs_test { @@ -740,3 +710,36 @@ njs_run "-q ./njs/test/module/normal.js" njs_run "-p njs/test/module/libs/ -d ./njs/test/module/normal.js" \ "passed!" + +# sandboxing + +njs_test { + {"var fs = require('fs')\r\n" + "Error: Cannot find module \"fs\"\r\n"} +} "-s" + +njs_test { + {"var crypto = require('crypto')\r\n" + "undefined\r\n"} +} "-s" + + +# source type + +njs_test { + {"this\r\n" + "this\r\nundefined"} + {"(() => this)()\r\n" + "(() => this)()\r\nundefined"} +} "-t module" + +njs_test { + {"this.NaN\r\n" + "this.NaN\r\nNaN"} +} "-t script" + + +# version + +njs_run "-v" "\\d+\.\\d+\.\\d+" + From xeioex at nginx.com Tue May 7 16:51:00 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 07 May 2019 16:51:00 +0000 Subject: [njs] Shell: executing command from command line arguments. Message-ID: details: https://hg.nginx.org/njs/rev/1b95bc101b4c branches: changeset: 956:1b95bc101b4c user: Dmitry Volyntsev date: Tue May 07 19:50:39 2019 +0300 description: Shell: executing command from command line arguments. diffstat: njs/njs_shell.c | 31 ++++++++++++++++++++++++++++++- njs/test/njs_expect_test.exp | 6 ++++++ 2 files changed, 36 insertions(+), 1 deletions(-) diffs (94 lines): diff -r 6adf4063e1bb -r 1b95bc101b4c njs/njs_shell.c --- a/njs/njs_shell.c Tue May 07 19:50:38 2019 +0300 +++ b/njs/njs_shell.c Tue May 07 19:50:39 2019 +0300 @@ -38,6 +38,7 @@ typedef struct { uint8_t version; char *file; + char *command; size_t n_paths; char **paths; } njs_opts_t; @@ -211,8 +212,10 @@ int main(int argc, char **argv) { char path[MAXPATHLEN], *p; + njs_vm_t *vm; nxt_int_t ret; njs_opts_t opts; + nxt_str_t command; njs_vm_opt_t vm_options; nxt_memzero(&opts, sizeof(njs_opts_t)); @@ -240,7 +243,13 @@ main(int argc, char **argv) goto done; } - memcpy(path + nxt_strlen(path), "/shell", sizeof("/shell")); + if (opts.command == NULL) { + memcpy(path + nxt_strlen(path), "/shell", sizeof("/shell")); + + } else { + memcpy(path + nxt_strlen(path), "/string", sizeof("/string")); + } + opts.file = path; } @@ -260,6 +269,14 @@ main(int argc, char **argv) if (opts.interactive) { ret = njs_interactive_shell(&opts, &vm_options); + } else if (opts.command) { + vm = njs_create_vm(&opts, &vm_options); + if (vm != NULL) { + command.start = (u_char *) opts.command; + command.length = nxt_strlen(opts.command); + ret = njs_process_script(vm_options.external, &opts, &command); + } + } else { ret = njs_process_file(&opts, &vm_options); } @@ -284,6 +301,7 @@ njs_get_options(njs_opts_t *opts, int ar "Interactive njs shell.\n" "\n" "Options:\n" + " -c specify the command to execute.\n" " -d print disassembled code.\n" " -p set path prefix for modules.\n" " -q disable interactive introduction prompt.\n" @@ -312,6 +330,17 @@ njs_get_options(njs_opts_t *opts, int ar (void) write(STDIN_FILENO, help, nxt_length(help)); return ret; + case 'c': + opts->interactive = 0; + + if (++i < argc) { + opts->command = argv[i]; + break; + } + + nxt_error("option \"-c\" requires argument\n"); + return NXT_ERROR; + case 'd': opts->disassemble = 1; break; diff -r 6adf4063e1bb -r 1b95bc101b4c njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Tue May 07 19:50:38 2019 +0300 +++ b/njs/test/njs_expect_test.exp Tue May 07 19:50:39 2019 +0300 @@ -649,6 +649,12 @@ njs_run "-p njs/test/module ./njs/test/m njs_run "-h" "Interactive njs shell.\r\n\r\nOptions:" +# command + +njs_run "-c 'console.log(\"a b c\")'" "a b c" + +njs_run "-c 'console.log('" "SyntaxError: Unexpected token \"\" in string:1" + # disassemble njs_test { From vbart at nginx.com Tue May 7 17:41:48 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 07 May 2019 17:41:48 +0000 Subject: [njs] Made all constructor properties configurable. Message-ID: details: https://hg.nginx.org/njs/rev/ff76f83fc49a branches: changeset: 957:ff76f83fc49a user: Valentin Bartenev date: Tue May 07 20:41:07 2019 +0300 description: Made all constructor properties configurable. Note that actual "constructor" property is created on demand in the prototypes' private hash with "configurable" option set. This change corrects its state before any access. diffstat: njs/njs_array.c | 1 + njs/njs_date.c | 1 + njs/njs_error.c | 6 ++++++ njs/njs_regexp.c | 1 + 4 files changed, 9 insertions(+), 0 deletions(-) diffs (84 lines): diff -r 1b95bc101b4c -r ff76f83fc49a njs/njs_array.c --- a/njs/njs_array.c Tue May 07 19:50:39 2019 +0300 +++ b/njs/njs_array.c Tue May 07 20:41:07 2019 +0300 @@ -2252,6 +2252,7 @@ static const njs_object_prop_t njs_arra .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, { diff -r 1b95bc101b4c -r ff76f83fc49a njs/njs_date.c --- a/njs/njs_date.c Tue May 07 19:50:39 2019 +0300 +++ b/njs/njs_date.c Tue May 07 20:41:07 2019 +0300 @@ -1951,6 +1951,7 @@ static const njs_object_prop_t njs_date .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, { diff -r 1b95bc101b4c -r ff76f83fc49a njs/njs_error.c --- a/njs/njs_error.c Tue May 07 19:50:39 2019 +0300 +++ b/njs/njs_error.c Tue May 07 20:41:07 2019 +0300 @@ -748,6 +748,7 @@ static const njs_object_prop_t njs_eval .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, }; @@ -818,6 +819,7 @@ static const njs_object_prop_t njs_rang .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, }; @@ -842,6 +844,7 @@ static const njs_object_prop_t njs_refe .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, }; @@ -866,6 +869,7 @@ static const njs_object_prop_t njs_synt .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, }; @@ -890,6 +894,7 @@ static const njs_object_prop_t njs_type .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, }; @@ -907,6 +912,7 @@ static const njs_object_prop_t njs_uri_ .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, { diff -r 1b95bc101b4c -r ff76f83fc49a njs/njs_regexp.c --- a/njs/njs_regexp.c Tue May 07 19:50:39 2019 +0300 +++ b/njs/njs_regexp.c Tue May 07 20:41:07 2019 +0300 @@ -1019,6 +1019,7 @@ static const njs_object_prop_t njs_rege .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .configurable = 1, }, { From dark264sh at gmail.com Wed May 8 05:30:28 2019 From: dark264sh at gmail.com (Sangdeuk Kwon) Date: Wed, 8 May 2019 14:30:28 +0900 Subject: [PATCH] reset r->cache->valid_sec for following the redirect Message-ID: # HG changeset patch # User Sangdeuk Kwon # Date 1557288704 -32400 # Wed May 08 13:11:44 2019 +0900 # Node ID c4e1be885640a8302dcbf97162b3cbdc21710a84 # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 reset r->cache->valid_sec for following the redirect this config: http { proxy_intercept_errors on; proxy_cache_path /cache0 levels=1:2 keys_zone=STATIC:10m max_size=10g inactive=60m use_temp_path=off; proxy_cache_key "$host$uri"; proxy_cache STATIC; upstream up_servers { server 127.0.0.2:8080; } server { listen 127.0.0.1:8000; location / { proxy_pass http://up_servers; proxy_set_header Host $host; proxy_http_version 1.1; add_header X-Cached $upstream_cache_status; proxy_intercept_errors on; error_page 301 302 303 307 308 = @handle_redirects; } location @handle_redirects { set $orig_loc $upstream_http_location; proxy_pass $orig_loc; } } } When origin server does not send cache time header (max-age or expires), nginx can follow the redirect with location header. But, if origin server sends cache time header, nginx can't follow the redirect and nginx send 302 response without location header to a client. So the client also can't follow the redirect because of absenting location header. diff -r 16a1adadf437 -r c4e1be885640 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Apr 24 16:38:56 2019 +0300 +++ b/src/http/ngx_http_upstream.c Wed May 08 13:11:44 2019 +0900 @@ -2645,6 +2645,15 @@ if (valid) { r->cache->error = status; } + + if (status == NGX_HTTP_MOVED_PERMANENTLY + || status == NGX_HTTP_MOVED_TEMPORARILY + || status == NGX_HTTP_SEE_OTHER + || status == NGX_HTTP_TEMPORARY_REDIRECT + || status == NGX_HTTP_PERMANENT_REDIRECT) + { + r->cache->valid_sec = 0; + } } ngx_http_file_cache_free(r->cache, u->pipe->temp_file); -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Wed May 8 16:09:56 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 8 May 2019 19:09:56 +0300 Subject: [PATCH] Add support cache line size for Hygon Dhyana CPU In-Reply-To: <3b71cea366414c7b8bb6f21acf73480c@hygon.cn> References: <3b71cea366414c7b8bb6f21acf73480c@hygon.cn> Message-ID: <20190508160955.GN1877@mdounin.ru> Hello! On Tue, May 07, 2019 at 07:25:59AM +0000, Jinke Fan wrote: > # HG changeset patch > # User Fanjinke > # Date 1557209225 -28800 > # Tue May 07 14:07:05 2019 +0800 > # Node ID 9bc6da16b217ce2c5fc63048a705c2b3195d3bb7 > # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 > Add support cache line size for Hygon Dhyana CPU > > Background: > Chengdu Haiguang IC Design Co., Ltd (Hygon) is a Joint Venture between > AMD and Haiguang Information Technology Co.,Ltd., aims at providing high > performance x86 processor for China server market. Its first generation > processor codename is Dhyana, which originates from AMD technology and > shares most of the architecture with AMD's family 17h, but with different > CPU Vendor ID("HygonGenuine")/Family series number(Family 18h). > > diff -r 16a1adadf437 -r 9bc6da16b217 src/core/ngx_cpuinfo.c > --- a/src/core/ngx_cpuinfo.c Wed Apr 24 16:38:56 2019 +0300 > +++ b/src/core/ngx_cpuinfo.c Tue May 07 14:07:05 2019 +0800 > @@ -124,6 +124,8 @@ > > } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { > ngx_cacheline_size = 64; > + } else if (ngx_strcmp(vendor, "HygonGenuine") == 0) { > + ngx_cacheline_size = 64; > } > } > Thank you for the patch. Starting with nginx 1.13.8 this should already work out of the box on systems with sysconf(_SC_LEVEL1_DCACHE_LINESIZE) - that is, at least on all Linux systems - as long as the processor is supported by OS. Also, the default is 64 anyway on 64-bit platforms. -- Maxim Dounin http://mdounin.ru/ From vbart at nginx.com Wed May 8 22:21:07 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 08 May 2019 22:21:07 +0000 Subject: [njs] Better name for append elements count in njs_array_expand(). Message-ID: details: https://hg.nginx.org/njs/rev/4ed09499a560 branches: changeset: 958:4ed09499a560 user: Valentin Bartenev date: Wed May 08 19:09:10 2019 +0300 description: Better name for append elements count in njs_array_expand(). No functional changes. diffstat: njs/njs_array.c | 4 ++-- njs/njs_array.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diffs (30 lines): diff -r ff76f83fc49a -r 4ed09499a560 njs/njs_array.c --- a/njs/njs_array.c Tue May 07 20:41:07 2019 +0300 +++ b/njs/njs_array.c Wed May 08 19:09:10 2019 +0300 @@ -212,12 +212,12 @@ njs_array_string_add(njs_vm_t *vm, njs_a njs_ret_t njs_array_expand(njs_vm_t *vm, njs_array_t *array, uint32_t prepend, - uint32_t new_size) + uint32_t append) { uint64_t size; njs_value_t *start, *old; - size = (uint64_t) new_size + array->length; + size = (uint64_t) append + array->length; if (nxt_fast_path(size <= array->size && prepend == 0)) { return NXT_OK; diff -r ff76f83fc49a -r 4ed09499a560 njs/njs_array.h --- a/njs/njs_array.h Tue May 07 20:41:07 2019 +0300 +++ b/njs/njs_array.h Wed May 08 19:09:10 2019 +0300 @@ -20,7 +20,7 @@ njs_ret_t njs_array_add(njs_vm_t *vm, nj njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, const u_char *start, size_t size, size_t length); njs_ret_t njs_array_expand(njs_vm_t *vm, njs_array_t *array, uint32_t prepend, - uint32_t size); + uint32_t append); njs_ret_t njs_array_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); From vbart at nginx.com Wed May 8 22:21:07 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 08 May 2019 22:21:07 +0000 Subject: [njs] Simplified check for array length limit in njs_array_expand(). Message-ID: details: https://hg.nginx.org/njs/rev/cb9cbb358a8b branches: changeset: 959:cb9cbb358a8b user: Valentin Bartenev date: Wed May 08 19:09:10 2019 +0300 description: Simplified check for array length limit in njs_array_expand(). No functional changes. diffstat: njs/njs_array.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 4ed09499a560 -r cb9cbb358a8b njs/njs_array.c --- a/njs/njs_array.c Wed May 08 19:09:10 2019 +0300 +++ b/njs/njs_array.c Wed May 08 19:09:10 2019 +0300 @@ -230,7 +230,7 @@ njs_array_expand(njs_vm_t *vm, njs_array size += size / 2; } - if (nxt_slow_path(((prepend + size) * sizeof(njs_value_t)) >= UINT32_MAX)) { + if (nxt_slow_path((prepend + size) > NJS_ARRAY_MAX_LENGTH)) { goto memory_error; } From vbart at nginx.com Wed May 8 22:21:07 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 08 May 2019 22:21:07 +0000 Subject: [njs] Fixed arrays expansion. Message-ID: details: https://hg.nginx.org/njs/rev/8fe38b9f8a94 branches: changeset: 960:8fe38b9f8a94 user: Valentin Bartenev date: Wed May 08 19:09:10 2019 +0300 description: Fixed arrays expansion. There were two problems with njs_array_expand(): 1. It checked that the requred size with the appended elements wasn't bigger then the array size and then did nothing. If there were elements removed from the beggining (by shift() operation), then "size <= array->size" can be true even if there wasn't enought free space after the array. 2. After allocating more space to prepend elements, it set array->size without counting those elements. Probably, the original idea was to decrement array->size while removing elements from the beginning, but it wasn't done right. Even if so, the new version of the function looks cleaner. This closes #152 and closes #153 issues on Github. diffstat: njs/njs_array.c | 22 ++++++++++++---------- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 15 insertions(+), 10 deletions(-) diffs (69 lines): diff -r cb9cbb358a8b -r 8fe38b9f8a94 njs/njs_array.c --- a/njs/njs_array.c Wed May 08 19:09:10 2019 +0300 +++ b/njs/njs_array.c Wed May 08 19:09:10 2019 +0300 @@ -214,15 +214,19 @@ njs_ret_t njs_array_expand(njs_vm_t *vm, njs_array_t *array, uint32_t prepend, uint32_t append) { + uint32_t free_before, free_after; uint64_t size; njs_value_t *start, *old; - size = (uint64_t) append + array->length; - - if (nxt_fast_path(size <= array->size && prepend == 0)) { + free_before = array->start - array->data; + free_after = array->size - array->length - free_before; + + if (nxt_fast_path(free_before >= prepend && free_after >= append)) { return NXT_OK; } + size = (uint64_t) prepend + array->length + append; + if (size < 16) { size *= 2; @@ -230,12 +234,12 @@ njs_array_expand(njs_vm_t *vm, njs_array size += size / 2; } - if (nxt_slow_path((prepend + size) > NJS_ARRAY_MAX_LENGTH)) { + if (nxt_slow_path(size > NJS_ARRAY_MAX_LENGTH)) { goto memory_error; } start = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t), - (prepend + size) * sizeof(njs_value_t)); + size * sizeof(njs_value_t)); if (nxt_slow_path(start == NULL)) { goto memory_error; } @@ -728,11 +732,9 @@ njs_array_prototype_unshift(njs_vm_t *vm n = nargs - 1; if (n != 0) { - if ((intptr_t) n > (array->start - array->data)) { - ret = njs_array_expand(vm, array, n, 0); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = njs_array_expand(vm, array, n, 0); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } array->length += n; diff -r cb9cbb358a8b -r 8fe38b9f8a94 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed May 08 19:09:10 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed May 08 19:09:10 2019 +0300 @@ -3730,6 +3730,9 @@ static njs_unit_test_t njs_test[] = "len +' '+ a +' '+ a.shift()"), nxt_string("5 3,4,5,1,2 3") }, + { nxt_string("var a=[0], n = 64; while(--n) {a.push(n); a.shift()}; a"), + nxt_string("1") }, + { nxt_string("var a = []; a.splice()"), nxt_string("") }, From careygister at outlook.com Thu May 9 02:29:47 2019 From: careygister at outlook.com (Carey Gister) Date: Thu, 9 May 2019 02:29:47 +0000 Subject: Slice Module behavior over SSL Message-ID: Hi, I noticed that if I configure a server to use the slice module it will happily read slices of the appropriate size as fast as the upstream server can deliver them. However, if I configure the same server to run over SSL it requests the slices at a rate consonant with the speed with which the my client application is consuming the data -- in my case about 4MB per second. This behavior can be easily confirmed from my server access logs and I can provide a sample configuration file. Can anyone explain this behavior? Carey Gister -------------- next part -------------- An HTML attachment was scrubbed... URL: From fanjinke at hygon.cn Thu May 9 03:36:15 2019 From: fanjinke at hygon.cn (Jinke Fan) Date: Thu, 9 May 2019 03:36:15 +0000 Subject: [PATCH] Add support cache line size for Hygon Dhyana CPU References: <3b71cea366414c7b8bb6f21acf73480c@hygon.cn> <20190508160955.GN1877@mdounin.ru> Message-ID: Hello Maxim, On 2019/5/9 0:10, Maxim Dounin wrote: > Hello! > > On Tue, May 07, 2019 at 07:25:59AM +0000, Jinke Fan wrote: > >> # HG changeset patch >> # User Fanjinke >> # Date 1557209225 -28800 >> # Tue May 07 14:07:05 2019 +0800 >> # Node ID 9bc6da16b217ce2c5fc63048a705c2b3195d3bb7 >> # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 >> Add support cache line size for Hygon Dhyana CPU >> >> Background: >> Chengdu Haiguang IC Design Co., Ltd (Hygon) is a Joint Venture between >> AMD and Haiguang Information Technology Co.,Ltd., aims at providing high >> performance x86 processor for China server market. Its first generation >> processor codename is Dhyana, which originates from AMD technology and >> shares most of the architecture with AMD's family 17h, but with different >> CPU Vendor ID("HygonGenuine")/Family series number(Family 18h). >> >> diff -r 16a1adadf437 -r 9bc6da16b217 src/core/ngx_cpuinfo.c >> --- a/src/core/ngx_cpuinfo.c Wed Apr 24 16:38:56 2019 +0300 >> +++ b/src/core/ngx_cpuinfo.c Tue May 07 14:07:05 2019 +0800 >> @@ -124,6 +124,8 @@ >> >> } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { >> ngx_cacheline_size = 64; >> + } else if (ngx_strcmp(vendor, "HygonGenuine") == 0) { >> + ngx_cacheline_size = 64; >> } >> } >> > > Thank you for the patch. > > Starting with nginx 1.13.8 this should already work out of the box > on systems with sysconf(_SC_LEVEL1_DCACHE_LINESIZE) - that is, at > least on all Linux systems - as long as the processor is supported > by OS. Also, the default is 64 anyway on 64-bit platforms. > Thank you so much for viewing the patch. sysconf(_SC_LEVEL1_DCACHE_LINESIZE) support Hygon CPU since glibc-2.29, so,before glibc-2.29 sysconf(_SC_LEVEL1_DCACHE_LINESIZE) will return zero. ngx_cacheline_size = NGX_CPU_CACHE_LINE; Yes, actually, the NGX_CPU_CACHE_LINE is 64 on Hygon platform . Best Regards! Jinke. From itsnagaraj at gmail.com Mon May 13 01:45:18 2019 From: itsnagaraj at gmail.com (Nagaraj Gopal) Date: Mon, 13 May 2019 11:45:18 +1000 Subject: gRPC + Nginx Message-ID: Hi There, We are using nginx to route requests to our gRPC services. But nginx expects all the services to be deployed so that it can start up successfully. *proxy_pass* directive allows this behaviour by using variable for specifying upstream server and this allows nginx to start up even when the upstream service is unavailable. Can this behaviour be achieved using *grpc_pass *directive? Regards, Nagaraj -------------- next part -------------- An HTML attachment was scrubbed... URL: From eohm at eohm.net.eu.org Mon May 13 06:16:13 2019 From: eohm at eohm.net.eu.org (eohm at eohm.net.eu.org) Date: Mon, 13 May 2019 08:16:13 +0200 Subject: [PATCH] fix/unify access to SSL_CTX certificate chains Message-ID: <6c1d44aa7054fb130ece.1557728173@hetzner.eohm.net.eu.org> src/event/ngx_event_openssl_stapling.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) # HG changeset patch # User Elias Ohm # Date 1557697215 -7200 # Sun May 12 23:40:15 2019 +0200 # Node ID 6c1d44aa7054fb130ece5432119d04971b586795 # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 fix/unify access to SSL_CTX certificate chains for newer OpenSSL versions (1.0.2+) the chain is stored in the dedicated chain field (SSL_CTX_set0_chain_certs) belonging to a certificate while in older versions the extra_chain had to be used (SSL_CTX_add_extra_chain_cert) which is always global to the context. reading the chain is still implemented with SSL_CTX_get_extra_chain_certs for newer versions (if not directly from staple->ssl_ctx->extra_certs in older versions). however, this works for OpenSSL where the SSL_CTX_get_extra_chain_certs falls back to read chain_certs when no extra_certs are available but breaks for some other implementations where SSL_CTX_get_extra_chain_certs is implemented as SSL_CTX_get_extra_chain_certs_only in OpenSSL is implemented. in addition this is inconsistent use of the functions and the functionality of trying etxra certs and falling back to certifiactes chain is not needed here. diff -r 16a1adadf437 -r 6c1d44aa7054 src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c Wed Apr 24 16:38:56 2019 +0300 +++ b/src/event/ngx_event_openssl_stapling.c Sun May 12 23:40:15 2019 +0200 @@ -298,7 +298,10 @@ SSL_CTX_select_current_cert(ssl->ctx, cert); #endif -#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS +#ifdef SSL_CTX_get0_chain_certs + /* OpenSSL 1.0.2+ */ + SSL_CTX_get0_chain_certs(ssl->ctx, &chain); +#elif SSL_CTRL_GET_EXTRA_CHAIN_CERTS /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else @@ -655,7 +658,10 @@ SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert); #endif -#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS +#ifdef SSL_CTX_get0_chain_certs + /* OpenSSL 1.0.2+ */ + SSL_CTX_get0_chain_certs(staple->ssl_ctx, &chain); +#elif SSL_CTRL_GET_EXTRA_CHAIN_CERTS /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain); #else From mdounin at mdounin.ru Mon May 13 12:30:02 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 13 May 2019 15:30:02 +0300 Subject: [PATCH] fix/unify access to SSL_CTX certificate chains In-Reply-To: <6c1d44aa7054fb130ece.1557728173@hetzner.eohm.net.eu.org> References: <6c1d44aa7054fb130ece.1557728173@hetzner.eohm.net.eu.org> Message-ID: <20190513123002.GP1877@mdounin.ru> Hello! On Mon, May 13, 2019 at 08:16:13AM +0200, Elias Ohm via nginx-devel wrote: > src/event/ngx_event_openssl_stapling.c | 10 ++++++++-- > 1 files changed, 8 insertions(+), 2 deletions(-) > > > # HG changeset patch > # User Elias Ohm > # Date 1557697215 -7200 > # Sun May 12 23:40:15 2019 +0200 > # Node ID 6c1d44aa7054fb130ece5432119d04971b586795 > # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 > fix/unify access to SSL_CTX certificate chains > > for newer OpenSSL versions (1.0.2+) the chain is stored in the dedicated chain field (SSL_CTX_set0_chain_certs) belonging to a certificate while in older versions the extra_chain had to be used (SSL_CTX_add_extra_chain_cert) which is always global to the context. > > reading the chain is still implemented with SSL_CTX_get_extra_chain_certs for newer versions (if not directly from staple->ssl_ctx->extra_certs in older versions). > however, this works for OpenSSL where the SSL_CTX_get_extra_chain_certs falls back to read chain_certs when no extra_certs are available but breaks for some other implementations where SSL_CTX_get_extra_chain_certs is implemented as SSL_CTX_get_extra_chain_certs_only in OpenSSL is implemented. in addition this is inconsistent use of the functions and the functionality of trying etxra certs and falling back to certifiactes chain is not needed here. You may want to be more specific here: LibreSSL 2.9.1 introduced partial support for per-certificate chains, yet failed to introduce appropriate changes in SSL_CTX_get_extra_chain_certs(). Quoting documentation for SSL_CTX_get_extra_chain_certs(), as recently added to OpenSSL[1]: : SSL_CTX_get_extra_chain_certs() retrieves the extra chain : certificates associated with ctx, or the chain associated with the : current certificate of ctx if the extra chain is empty. This behaviour was in OpenSSL since original introduction of per-certificate chains in OpenSSL 1.0.2[2], so a code can safely use SSL_CTX_get_extra_chain_certs() to get the best of the available chains regardless of how certificate chains were set. And this is what the code in question in nginx does - it uses SSL_CTX_get_extra_chain_certs() to get the best of the available chains. While I generally like LibreSSL, this looks like a LibreSSL bug to me. And instead of trying to fix working code in nginx, you may want to focus on fixing SSL_CTX_get_extra_chain_certs() in LibreSSL. [1] https://github.com/openssl/openssl/commit/dc703d6b469f1b186483a55b59013fbaca2228fd [2] https://github.com/openssl/openssl/commit/a51f767645c117667d337f77fe1dd9c0a66d8410 -- Maxim Dounin http://mdounin.ru/ From arut at nginx.com Mon May 13 12:34:28 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 13 May 2019 12:34:28 +0000 Subject: [nginx] Unconditional compilation of the postpone filter. Message-ID: details: https://hg.nginx.org/nginx/rev/ee36940cfb0f branches: changeset: 7506:ee36940cfb0f user: Roman Arutyunyan date: Wed May 08 19:22:13 2019 +0300 description: Unconditional compilation of the postpone filter. Postpone filter is an essential part of subrequest functionality. In absence of it a subrequest response body is sent to the client out of order with respect to the main request header and body, as well as other subrequests. For in-memory subrequests the response is also sent to the client instead of being stored in memory. Currently the postpone filter is automatically enabled if one of the following standard modules which are known to create subrequests is enabled: ssi, slice, addition. However a third-party module that creates subrequests can still be built without the postpone filter or be dynamically loaded in nginx built without it. diffstat: auto/modules | 19 ++----------------- auto/options | 1 - 2 files changed, 2 insertions(+), 18 deletions(-) diffs (52 lines): diff -r 16a1adadf437 -r ee36940cfb0f auto/modules --- a/auto/modules Wed Apr 24 16:38:56 2019 +0300 +++ b/auto/modules Wed May 08 19:22:13 2019 +0300 @@ -102,21 +102,6 @@ if [ $HTTP = YES ]; then fi - if [ $HTTP_SSI = YES ]; then - HTTP_POSTPONE=YES - fi - - - if [ $HTTP_SLICE = YES ]; then - HTTP_POSTPONE=YES - fi - - - if [ $HTTP_ADDITION = YES ]; then - HTTP_POSTPONE=YES - fi - - # the module order is important # ngx_http_static_module # ngx_http_gzip_static_module @@ -252,13 +237,13 @@ if [ $HTTP = YES ]; then . auto/module fi - if [ $HTTP_POSTPONE = YES ]; then + if :; then ngx_module_name=ngx_http_postpone_filter_module ngx_module_incs= ngx_module_deps= ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c ngx_module_libs= - ngx_module_link=$HTTP_POSTPONE + ngx_module_link=YES . auto/module fi diff -r 16a1adadf437 -r ee36940cfb0f auto/options --- a/auto/options Wed Apr 24 16:38:56 2019 +0300 +++ b/auto/options Wed May 08 19:22:13 2019 +0300 @@ -60,7 +60,6 @@ HTTP_GZIP=YES HTTP_SSL=NO HTTP_V2=NO HTTP_SSI=YES -HTTP_POSTPONE=NO HTTP_REALIP=NO HTTP_XSLT=NO HTTP_IMAGE_FILTER=NO From mdounin at mdounin.ru Mon May 13 13:03:10 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 13 May 2019 16:03:10 +0300 Subject: FW: [PATCH] when we need to transfer data between file and socket we prefer to use sendfile instead of write because we save the copy to a buffer In-Reply-To: <9398a1fa-89dd-d636-d7ca-1fa5041d2931@mellanox.com> References: <20190418130733.GZ1877@mdounin.ru> <6e9c9a7e-0297-e3ea-dc3c-a1e48697343a@mellanox.com> <20190506143011.GH1877@mdounin.ru> <9398a1fa-89dd-d636-d7ca-1fa5041d2931@mellanox.com> Message-ID: <20190513130310.GQ1877@mdounin.ru> Hello! (Please keep this on the nginx-devel@ mailinig list.) On Mon, May 13, 2019 at 06:53:15AM +0000, Ben Ben Ishay wrote: > On 5/6/2019 5:30 PM, Maxim Dounin wrote: > > Hello! > > > > On Mon, May 06, 2019 at 06:02:10AM +0000, Ben Ben Ishay wrote: > > > > [...] > > > >>> - The SSL_sendfile() call you are using in this version does not > >>> seem to exists in any published version of OpenSSL, including > >>> github repo. This is not going to work. > >>> > >> we attach a documentation link about this > >> function(https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FMellanox%2Fopenssl%2Fblob%2Ftls_sendfile%2Fdoc%2Fman3%2FSSL_write.pod&data=02%7C01%7Cbenishay%40mellanox.com%7Cbb2fb3506bbd4953d2fd08d6d22f5f0d%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636927498228272408&sdata=Na%2B%2Be2nibz%2BkFBt%2FSGLYer9oe5D4OpVUp21LNWQsHzU%3D&reserved=0), > >> we have a pull request at advanced stage for adding this function. > >> > >>> - The approach you are using - that is, introducing changes into > >>> ngx_linux_sendfile_chain.c - is not portable, and is not going > >>> to work on other platforms if/when appropriate kernel level and > >>> OpenSSL level support will be available. As suggested in the > >>> previous thread, this should be something handled at the > >>> ngx_event_openssl.c level. > >>> > >> we think that this is the best solution because there is a unique > >> function for every OS and there is a difference between them for > >> example ngx_linux_sendfile_chain use TCP_CORK option while > >> ngx_freebsd_sendfile_chain dosent(in addition in solaris function > >> ngx_solaris_sendfilev_chain there is a call to sendfilev that dosent > >> exists in linux) , we can create a function that is constructed from the > >> diffrenet flow for OS's but we think this option include copying code > >> and thus the best option is to change the sendfile call in every > >> ngx_sendfile function when the OS and OPENSSL will support SSL_Sendfile. > > > > While handling of the sendfile() syscall is certainly OS-specific, > > the SSL_sendfile() interface as provided by OpenSSL is certainly > > not going to follow these OS-specific code paths. For example, I > > cannot reasonably assume SSL_sendfile() will support headers and > > trailers on FreeBSD, or will be similar to sendfilev() interface > > on Solaris. > > > The SSL_sendfile() is actually OS-specific, we attach the > documentation.(https://www.openssl.org/docs/manmaster/man3/SSL_sendfile.html) > The flag field has a use at least for FreeBSD. As per the documentation committed, it is actually not OS-specific (though may be available only on some OSes, with some per-OS nuances). And that's actually the point of the SSL_sendfile() interface. > > That is, SSL_sendfile() is going to be a separate interface, > > different from all the OS-specific interfaces, with its own > > features and limitations. And most likely it will need different > > error handling, including handling of SSL-specific errors. > > > we agree with your claim about error handling, and we will be glad to > hear your solution. I've already pointed you to the preliminiry work from Netflix, as well as to the SSL_write() usage in nginx. > > As such, trying to change OS-specific sendfile chains in nginx > > looks wrong to me. Not to mention it will require additional > > application-level work upon introduction of in-kernel SSL/TLS in > > other OSes. Rather, it should be an SSL-level changes, > > introducing an SSL-level send chain, similar to one we already > > provide for SSL_write(). > > > > (Note well that using BIO_get_ktls_send() to find out if > > SSL_sendfile() can be used or not also looks strange and > > non-portable. If the route taken is to provide SSL_sendfile(), an > > OS-independent interface to use sendfile() when supported by the > > OpenSSL library, there should be a simplier / more portable way to > > test if SSL_sendfile() can be used on a particular SSL > > connection.) > > > The documentation explain this. While it certainly does, things can be done in a more portable way. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Mon May 13 17:30:18 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 13 May 2019 17:30:18 +0000 Subject: [njs] Fixed heap-buffer-overflow in String.prototype.replace(). Message-ID: details: https://hg.nginx.org/njs/rev/6babef232e87 branches: changeset: 961:6babef232e87 user: Dmitry Volyntsev date: Mon May 13 20:28:40 2019 +0300 description: Fixed heap-buffer-overflow in String.prototype.replace(). This closes #154 issue on GitHub. diffstat: njs/njs_string.c | 5 ++--- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diffs (35 lines): diff -r 8fe38b9f8a94 -r 6babef232e87 njs/njs_string.c --- a/njs/njs_string.c Wed May 08 19:09:10 2019 +0300 +++ b/njs/njs_string.c Mon May 13 20:28:40 2019 +0300 @@ -3239,7 +3239,7 @@ njs_string_replace_search(njs_vm_t *vm, p = r->part[0].start; end = (p + r->part[0].size) - (search.length - 1); - do { + while (p < end) { if (memcmp(p, search.start, search.length) == 0) { if (r->substitutions != NULL) { @@ -3272,8 +3272,7 @@ njs_string_replace_search(njs_vm_t *vm, } else { p = (u_char *) nxt_utf8_next(p, end); } - - } while (p < end); + } njs_string_copy(&vm->retval, &args[0]); diff -r 8fe38b9f8a94 -r 6babef232e87 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed May 08 19:09:10 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 13 20:28:40 2019 +0300 @@ -5336,6 +5336,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("'abcdefgh'.replace('d', undefined)"), nxt_string("abcundefinedefgh") }, + { nxt_string("'a'.repeat(16).replace('a'.repeat(17)) === 'a'.repeat(16)"), + nxt_string("true") }, + { nxt_string("'abcdefgh'.replace('d', null)"), nxt_string("abcnullefgh") }, From mdounin at mdounin.ru Mon May 13 17:52:33 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 13 May 2019 20:52:33 +0300 Subject: [PATCH] reset r->cache->valid_sec for following the redirect In-Reply-To: References: Message-ID: <20190513175233.GU1877@mdounin.ru> Hello! On Wed, May 08, 2019 at 02:30:28PM +0900, Sangdeuk Kwon wrote: > # HG changeset patch > # User Sangdeuk Kwon > # Date 1557288704 -32400 > # Wed May 08 13:11:44 2019 +0900 > # Node ID c4e1be885640a8302dcbf97162b3cbdc21710a84 > # Parent 16a1adadf43751f59257ba419f6bacd530dd19d3 > reset r->cache->valid_sec for following the redirect > > this config: > > http { > proxy_intercept_errors on; > > proxy_cache_path /cache0 levels=1:2 keys_zone=STATIC:10m max_size=10g > inactive=60m use_temp_path=off; > proxy_cache_key "$host$uri"; > proxy_cache STATIC; > > upstream up_servers { > server 127.0.0.2:8080; > } > > server { > listen 127.0.0.1:8000; > > location / { > proxy_pass http://up_servers; > proxy_set_header Host $host; > proxy_http_version 1.1; > add_header X-Cached $upstream_cache_status; > > proxy_intercept_errors on; > error_page 301 302 303 307 308 = @handle_redirects; > } > > location @handle_redirects { > set $orig_loc $upstream_http_location; > proxy_pass $orig_loc; > } > } > } > > When origin server does not send cache time header (max-age or expires), > nginx can follow the redirect with location header. > But, if origin server sends cache time header, > nginx can't follow the redirect and nginx send 302 response without > location header to a client. > So the client also can't follow the redirect because of absenting location > header. > > diff -r 16a1adadf437 -r c4e1be885640 src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Wed Apr 24 16:38:56 2019 +0300 > +++ b/src/http/ngx_http_upstream.c Wed May 08 13:11:44 2019 +0900 > @@ -2645,6 +2645,15 @@ > if (valid) { > r->cache->error = status; > } > + > + if (status == NGX_HTTP_MOVED_PERMANENTLY > + || status == NGX_HTTP_MOVED_TEMPORARILY > + || status == NGX_HTTP_SEE_OTHER > + || status == NGX_HTTP_TEMPORARY_REDIRECT > + || status == NGX_HTTP_PERMANENT_REDIRECT) > + { > + r->cache->valid_sec = 0; > + } > } > > ngx_http_file_cache_free(r->cache, u->pipe->temp_file); Thanks for the patch. This seems to be a negative effect of dbd77a638eb7 (nginx 1.13.6, http://hg.nginx.org/nginx/rev/dbd77a638eb7), which manifests itself in the configuration in question. As long as the response is cached, the particular configuration cannot work, since $upstream_http_location is not available. An obvious workaround is to ensure that such configuration do not allow caching of responses, for example, by using "proxy_cache off;" in such locations. Using "r->cache->valid_sec = 0;" based on the status code, however, looks wrong to me. First of all, it doesn't actually disable caching, but rather preserves the existing response validity as is - and this may result in more or less arbitrary behaviour. Second, it doesn't clear to me if this is something to be done unconditionally - there can be configuration when caching is desired, despite the fact that $upstream_http_location will not be available. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon May 13 21:20:37 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 13 May 2019 21:20:37 +0000 Subject: [nginx] Range filter: fixed loss of incoming chain links. Message-ID: details: https://hg.nginx.org/nginx/rev/ea05113adbdb branches: changeset: 7507:ea05113adbdb user: Maxim Dounin date: Mon May 13 22:44:02 2019 +0300 description: Range filter: fixed loss of incoming chain links. Filters are not allowed to change incoming chain links, and should allocate their own links if any modifications are needed. Nevertheless ngx_http_range_singlepart_body() modified incoming chain links in some cases, notably at the end of the requested range. No problems caused by this are currently known, mostly because of limited number of possible modifications and the position of the range body filter in the filter chain. Though this behaviour is clearly incorrect and tests demonstrate that it can at least cause some proxy buffers being lost when using proxy_force_ranges, leading to less effective handling of responses. Fix is to always allocate new chain links in ngx_http_range_singlepart_body(). Links are explicitly freed to ensure constant memory usage with long-lived requests. diffstat: src/http/modules/ngx_http_range_filter_module.c | 54 ++++++++++++++++++++---- 1 files changed, 45 insertions(+), 9 deletions(-) diffs (88 lines): diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -700,8 +700,9 @@ ngx_http_range_singlepart_body(ngx_http_ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in) { off_t start, last; + ngx_int_t rc; ngx_buf_t *buf; - ngx_chain_t *out, *cl, **ll; + ngx_chain_t *out, *cl, *tl, **ll; ngx_http_range_t *range; out = NULL; @@ -721,8 +722,18 @@ ngx_http_range_singlepart_body(ngx_http_ "http range body buf: %O-%O", start, last); if (ngx_buf_special(buf)) { - *ll = cl; - ll = &cl->next; + + tl = ngx_alloc_chain_link(r->pool); + if (tl == NULL) { + return NGX_ERROR; + } + + tl->buf = buf; + tl->next = NULL; + + *ll = tl; + ll = &tl->next; + continue; } @@ -764,21 +775,46 @@ ngx_http_range_singlepart_body(ngx_http_ buf->last_buf = (r == r->main) ? 1 : 0; buf->last_in_chain = 1; - *ll = cl; - cl->next = NULL; + + tl = ngx_alloc_chain_link(r->pool); + if (tl == NULL) { + return NGX_ERROR; + } - break; + tl->buf = buf; + tl->next = NULL; + + *ll = tl; + ll = &tl->next; + + continue; } - *ll = cl; - ll = &cl->next; + tl = ngx_alloc_chain_link(r->pool); + if (tl == NULL) { + return NGX_ERROR; + } + + tl->buf = buf; + tl->next = NULL; + + *ll = tl; + ll = &tl->next; } if (out == NULL) { return NGX_OK; } - return ngx_http_next_body_filter(r, out); + rc = ngx_http_next_body_filter(r, out); + + while (out) { + cl = out; + out = out->next; + ngx_free_chain(r->pool, cl); + } + + return rc; } From mdounin at mdounin.ru Mon May 13 21:20:38 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 13 May 2019 21:20:38 +0000 Subject: [nginx] Range filter: fixed duplicate last buffers. Message-ID: details: https://hg.nginx.org/nginx/rev/c30a20e06c21 branches: changeset: 7508:c30a20e06c21 user: Maxim Dounin date: Mon May 13 22:44:49 2019 +0300 description: Range filter: fixed duplicate last buffers. In ngx_http_range_singlepart_body() special buffers where passed unmodified, including ones after the end of the range. As such, if the last buffer of a response was sent separately as a special buffer, two buffers with b->last_buf set were present in the response. In particular, this might result in a duplicate final chunk when using chunked transfer encoding (normally range filter and chunked transfer encoding are not used together, but this may happen if there are trailers in the response). This also likely to cause problems in HTTP/2. Fix is to skip all special buffers after we've sent the last part of the range requested. These special buffers are not meaningful anyway, since we set b->last_buf in the buffer with the last part of the range, and everything is expected to be flushed due to it. Additionally, ngx_http_next_body_filter() is now called even if no buffers are to be passed to it. This ensures that various write events are properly propagated through the filter chain. In particular, this fixes test failures observed with the above change and aio enabled. diffstat: src/http/modules/ngx_http_range_filter_module.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (25 lines): diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -723,6 +723,10 @@ ngx_http_range_singlepart_body(ngx_http_ if (ngx_buf_special(buf)) { + if (range->end <= start) { + continue; + } + tl = ngx_alloc_chain_link(r->pool); if (tl == NULL) { return NGX_ERROR; @@ -802,10 +806,6 @@ ngx_http_range_singlepart_body(ngx_http_ ll = &tl->next; } - if (out == NULL) { - return NGX_OK; - } - rc = ngx_http_next_body_filter(r, out); while (out) { From xeioex at nginx.com Tue May 14 16:34:19 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 14 May 2019 16:34:19 +0000 Subject: [njs] Fixed heap-buffer-overflow in String.prototype.lastIndexOf(). Message-ID: details: https://hg.nginx.org/njs/rev/895f4887702d branches: changeset: 963:895f4887702d user: Dmitry Volyntsev date: Tue May 14 19:13:53 2019 +0300 description: Fixed heap-buffer-overflow in String.prototype.lastIndexOf(). This closes #151 issue on Github. diffstat: njs/njs_string.c | 9 +++++++-- njs/test/njs_unit_test.c | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diffs (39 lines): diff -r 1cce73676665 -r 895f4887702d njs/njs_string.c --- a/njs/njs_string.c Tue May 14 19:00:03 2019 +0300 +++ b/njs/njs_string.c Tue May 14 19:13:53 2019 +0300 @@ -1831,8 +1831,13 @@ njs_string_prototype_last_index_of(njs_v } } - if (index > length) { - index = length; + if (search_length == 0) { + index = nxt_min(index, length); + goto done; + } + + if (index >= length) { + index = length - 1; } if (string.size == (size_t) length) { diff -r 1cce73676665 -r 895f4887702d njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 14 19:00:03 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 14 19:13:53 2019 +0300 @@ -5172,6 +5172,16 @@ static njs_unit_test_t njs_test[] = { nxt_string("''.lastIndexOf(undefined)"), nxt_string("-1") }, + { nxt_string("'?'.repeat(32).lastIndexOf('?')"), + nxt_string("31") }, + + { nxt_string("'?'.repeat(32).lastIndexOf``"), + nxt_string("32") }, + + { nxt_string("JSON.stringify(Array(24).fill(true).map((v,i) => 'abc abc ab abc ????????ab'.lastIndexOf('abc', i)))" + "== JSON.stringify([].concat(Array(4).fill(0), Array(7).fill(4), Array(13).fill(11)))"), + nxt_string("true") }, + { nxt_string("''.includes('')"), nxt_string("true") }, From xeioex at nginx.com Tue May 14 16:34:19 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 14 May 2019 16:34:19 +0000 Subject: [njs] Improved working with arguments in String.prototype.lastIndexOf(). Message-ID: details: https://hg.nginx.org/njs/rev/1cce73676665 branches: changeset: 962:1cce73676665 user: Dmitry Volyntsev date: Tue May 14 19:00:03 2019 +0300 description: Improved working with arguments in String.prototype.lastIndexOf(). diffstat: njs/njs_string.c | 128 +++++++++++++++++++++++++--------------------- njs/test/njs_unit_test.c | 18 ++++++ 2 files changed, 87 insertions(+), 59 deletions(-) diffs (196 lines): diff -r 6babef232e87 -r 1cce73676665 njs/njs_string.c --- a/njs/njs_string.c Mon May 13 20:28:40 2019 +0300 +++ b/njs/njs_string.c Tue May 14 19:00:03 2019 +0300 @@ -1796,80 +1796,90 @@ static njs_ret_t njs_string_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { + double pos; ssize_t index, start, length, search_length; const u_char *p, *end; + const njs_value_t *search_string; njs_string_prop_t string, search; index = -1; - if (nargs > 1) { - length = njs_string_prop(&string, &args[0]); - search_length = njs_string_prop(&search, &args[1]); - - if (length < search_length) { - goto done; - } - + length = njs_string_prop(&string, njs_arg(args, nargs, 0)); + + search_string = njs_arg(args, nargs, 1); + + if (njs_is_undefined(search_string)) { + search_string = &njs_string_undefined; + } + + search_length = njs_string_prop(&search, search_string); + + if (length < search_length) { + goto done; + } + + pos = njs_arg(args, nargs, 2)->data.u.number; + + if (isnan(pos)) { index = NJS_STRING_MAX_LENGTH; - if (nargs > 2) { - index = args[2].data.u.number; - - if (index < 0) { - index = 0; - } + } else { + index = njs_number_to_integer(pos); + + if (index < 0) { + index = 0; } - - if (index > length) { - index = length; + } + + if (index > length) { + index = length; + } + + if (string.size == (size_t) length) { + /* Byte or ASCII string. */ + + start = length - search.size; + + if (index > start) { + index = start; } - if (string.size == (size_t) length) { - /* Byte or ASCII string. */ - - start = length - search.size; - - if (index > start) { - index = start; + p = string.start + index; + + do { + if (memcmp(p, search.start, search.size) == 0) { + goto done; } - p = string.start + index; - - do { - if (memcmp(p, search.start, search.size) == 0) { - goto done; - } - - index--; - p--; - - } while (p >= string.start); - - } else { - /* UTF-8 string. */ - - end = string.start + string.size; - p = njs_string_offset(string.start, end, index); - end -= search.size; - - while (p > end) { - index--; - p = nxt_utf8_prev(p); + index--; + p--; + + } while (p >= string.start); + + } else { + /* UTF-8 string. */ + + end = string.start + string.size; + p = njs_string_offset(string.start, end, index); + end -= search.size; + + while (p > end) { + index--; + p = nxt_utf8_prev(p); + } + + for ( ;; ) { + if (memcmp(p, search.start, search.size) == 0) { + goto done; } - for ( ;; ) { - if (memcmp(p, search.start, search.size) == 0) { - goto done; - } - - index--; - - if (p <= string.start) { - break; - } - - p = nxt_utf8_prev(p); + index--; + + if (p <= string.start) { + break; } + + p = nxt_utf8_prev(p); } } @@ -3912,7 +3922,7 @@ static const njs_object_prop_t njs_stri .type = NJS_METHOD, .name = njs_string("lastIndexOf"), .value = njs_native_function(njs_string_prototype_last_index_of, 0, - NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG), + NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_NUMBER_ARG), .configurable = 1, }, diff -r 6babef232e87 -r 1cce73676665 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon May 13 20:28:40 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 14 19:00:03 2019 +0300 @@ -5127,6 +5127,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("'abc abc ????? abc'.lastIndexOf('?????')"), nxt_string("8") }, + { nxt_string("'abc abc ????? abc'.lastIndexOf('?????', undefined)"), + nxt_string("8") }, + + { nxt_string("'abc abc ????? abc'.lastIndexOf('?????', NaN)"), + nxt_string("8") }, + + { nxt_string("'abc abc ????? abc'.lastIndexOf('?????', {})"), + nxt_string("8") }, + + { nxt_string("String.prototype.lastIndexOf.call({toString:()=>'abc abc ????? abc'}, '?????')"), + nxt_string("8") }, + { nxt_string("'abc abc ????????'.lastIndexOf('?????')"), nxt_string("8") }, @@ -5154,6 +5166,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("''.lastIndexOf('')"), nxt_string("0") }, + { nxt_string("''.lastIndexOf()"), + nxt_string("-1") }, + + { nxt_string("''.lastIndexOf(undefined)"), + nxt_string("-1") }, + { nxt_string("''.includes('')"), nxt_string("true") }, From alexander.borisov at nginx.com Wed May 15 09:52:55 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Wed, 15 May 2019 09:52:55 +0000 Subject: [njs] Fixed regexp literals parsing. Message-ID: details: https://hg.nginx.org/njs/rev/56c75545da25 branches: changeset: 964:56c75545da25 user: Alexander Borisov date: Wed May 15 12:51:31 2019 +0300 description: Fixed regexp literals parsing. Problems were observed: 1. Escaping symbols: /\\\\/ 2. Solidus symbol ('/') in square bracket: /[/]/ This closes #149 issue on GitHub. diffstat: njs/njs_regexp.c | 36 +++++++++++++++++++++++++++++++----- njs/test/njs_unit_test.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 5 deletions(-) diffs (104 lines): diff -r 895f4887702d -r 56c75545da25 njs/njs_regexp.c --- a/njs/njs_regexp.c Tue May 14 19:13:53 2019 +0300 +++ b/njs/njs_regexp.c Wed May 15 12:51:31 2019 +0300 @@ -209,7 +209,7 @@ njs_regexp_create(njs_vm_t *vm, njs_valu njs_token_t njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value) { - u_char *p, c; + u_char *p; nxt_str_t text; njs_lexer_t *lexer; njs_regexp_flags_t flags; @@ -219,13 +219,37 @@ njs_regexp_literal(njs_vm_t *vm, njs_par for (p = lexer->start; p < lexer->end; p++) { - c = *p; + switch (*p) { + case '\n': + case '\r': + goto failed; - if (c == '\n' || c == '\r') { + case '[': + while (++p < lexer->end && *p != ']') { + switch (*p) { + case '\n': + case '\r': + goto failed; + + case '\\': + if (++p < lexer->end && (*p == '\n' || *p == '\r')) { + goto failed; + } + + break; + } + } + break; - } - if (c == '/' && !(p > lexer->start && p[-1] == '\\')) { + case '\\': + if (++p < lexer->end && (*p == '\n' || *p == '\r')) { + goto failed; + } + + break; + + case '/': text.start = lexer->start; text.length = p - text.start; p++; @@ -255,6 +279,8 @@ njs_regexp_literal(njs_vm_t *vm, njs_par } } +failed: + njs_parser_syntax_error(vm, parser, "Unterminated RegExp \"%*s\"", p - (lexer->start - 1), lexer->start - 1); diff -r 895f4887702d -r 56c75545da25 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 14 19:13:53 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed May 15 12:51:31 2019 +0300 @@ -7073,6 +7073,37 @@ static njs_unit_test_t njs_test[] = { nxt_string("/a\\q/"), nxt_string("/a\\q/") }, + { nxt_string("/\\\\/"), + nxt_string("/\\\\/") }, + + { nxt_string("/\\\\\\/"), + nxt_string("SyntaxError: Unterminated RegExp \"/\\\\\\/\" in 1") }, + + { nxt_string("/\\\\\\\\/"), + nxt_string("/\\\\\\\\/") }, + + { nxt_string("/\\\\\\//"), + nxt_string("/\\\\\\//") }, + + { nxt_string("/[A-Z/]/"), + nxt_string("/[A-Z/]/") }, + + { nxt_string("/[A-Z\n]/"), + nxt_string("SyntaxError: Unterminated RegExp \"/[A-Z\" in 1") }, + + { nxt_string("/[A-Z\\\n]/"), + nxt_string("SyntaxError: Unterminated RegExp \"/[A-Z\\\" in 1") }, + + { nxt_string("/\\\n/"), + nxt_string("SyntaxError: Unterminated RegExp \"/\\\" in 1") }, + + { nxt_string("/^[A-Za-z0-9+/]{4}$/.test('////')"), + nxt_string("true") }, + + { nxt_string("'[]!\"#$%&\\'()*+,.\\/:;<=>?@\\^_`{|}-'.split('')" + ".every(ch=>/[\\]\\[!\"#$%&'()*+,.\\/:;<=>?@\\^_`{|}-]/.test(ch))"), + nxt_string("true") }, + { nxt_string("/a\\q/.test('a\\q')"), nxt_string("true") }, From dnj0496 at gmail.com Thu May 16 00:35:54 2019 From: dnj0496 at gmail.com (Dk Jack) Date: Wed, 15 May 2019 17:35:54 -0700 Subject: redirect after body capture Message-ID: Hi, In my module, I am trying to forward the request to my server based on the content of the request body. To acheive this, I've added a body capture filter to capture the body. Here are the relevant parts of my code... static ngx_int_t nginx_inspect_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ... // extract body if (if_content_of_interest_in_body(body, body_length)) { ngx_str_t uri = ngx_string("/my_location"); ngx_http_internal_redirect(r, &url, NULL); ngx_http_finalize_request(r, NGX_DONE); // return NGX_DONE; // causes connection abort. } ... return ngx_http_next_body_filter(r, in); } I have the following conf for '/my_location': server { ... location / { ... } location /my_location { proxy_pass http://myserver; } } However, I am running into an issue with my code. If return NGX_DONE after internal redirect, I get a connection abort. If I call, next_body_filter, the connection seems to hang. Doing a redirect, using similar code in PREACCESS_PHASE works without any issues. The issue seems to happen only when I wait to read the entire body and perform the redirect based on the content of the body. With no body capture, it works fine. Do I need to do anything additional to redirect in the body filter? Thanks for your help. Regards, Dk. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dark264sh at gmail.com Thu May 16 04:28:29 2019 From: dark264sh at gmail.com (Sangdeuk Kwon) Date: Thu, 16 May 2019 13:28:29 +0900 Subject: [PATCH] reset r->cache->valid_sec for following the redirect Message-ID: Thank you for your review > An obvious workaround is to ensure that such configuration do not > allow caching of responses, for example, by using "proxy_cache > off;" in such locations. If using "proxy_cache off;", all response is not cached. The expected behavior is 1. when 200 response, it is cached 2. when 3xx response, nginx follow the redirect and followed response is cached nginx cannot configure whether cache or not cache by response status code. > Using "r->cache->valid_sec = 0;" based on the status code, > however, looks wrong to me. First of all, it doesn't actually > disable caching, but rather preserves the existing response > validity as is - and this may result in more or less arbitrary > behaviour. client ---> nginx ---> origin |---------->|---------->| req |<----------|<----------| 302 res |---------->|---------->| followed req |<----------|<----------| followed res client ---> nginx ---> origin |---------->|---------->| req | |<----------| 302 res | |---------->| followed req |<----------|<----------| followed res If nginx follow the redirect, it can reduce round-trip time of HTTP request/response sequence between client and nginx > Second, it doesn't clear to me if this is something to > be done unconditionally - there can be configuration when caching > is desired, despite the fact that $upstream_http_location will not > be available. I understood your concern. How about adding new directive? Syntax: proxy_follow_redirect on | off; Default: proxy_follow_redirect off; Context: http, server, location if (proxy_follow_redirect && (status == NGX_HTTP_MOVED_PERMANENTLY || status == NGX_HTTP_MOVED_TEMPORARILY || status == NGX_HTTP_SEE_OTHER || status == NGX_HTTP_TEMPORARY_REDIRECT || status == NGX_HTTP_PERMANENT_REDIRECT)) { r->cache->valid_sec = 0; } Thanks, Sangdeuk -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Thu May 16 12:21:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 16 May 2019 12:21:48 +0000 Subject: [njs] Fixed uninitialized-memory-access in Object.defineProperties(). Message-ID: details: https://hg.nginx.org/njs/rev/e0fdef4eb478 branches: changeset: 965:e0fdef4eb478 user: Dmitry Volyntsev date: Thu May 16 15:20:31 2019 +0300 description: Fixed uninitialized-memory-access in Object.defineProperties(). This closes #158 issue on Github. diffstat: njs/njs_object.c | 11 +++++------ njs/test/njs_unit_test.c | 3 +++ 2 files changed, 8 insertions(+), 6 deletions(-) diffs (45 lines): diff -r 56c75545da25 -r e0fdef4eb478 njs/njs_object.c --- a/njs/njs_object.c Wed May 15 12:51:31 2019 +0300 +++ b/njs/njs_object.c Thu May 16 15:20:31 2019 +0300 @@ -1705,7 +1705,7 @@ njs_object_define_property(njs_vm_t *vm, return NXT_ERROR; } - value = &args[1]; + value = njs_argument(args, 1); if (!value->data.u.object->extensible) { njs_type_error(vm, "object is not extensible"); @@ -1743,15 +1743,14 @@ njs_object_define_properties(njs_vm_t *v njs_object_prop_t *prop; const njs_value_t *descriptor; - value = &args[1]; - - if (!njs_is_object(value)) { + if (!njs_is_object(njs_arg(args, nargs, 1))) { njs_type_error(vm, "cannot convert %s argument to object", - njs_type_string(value->type)); - + njs_type_string(njs_arg(args, nargs, 1)->type)); return NXT_ERROR; } + value = njs_argument(args, 1); + if (!value->data.u.object->extensible) { njs_type_error(vm, "object is not extensible"); return NXT_ERROR; diff -r 56c75545da25 -r e0fdef4eb478 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed May 15 12:51:31 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 16 15:20:31 2019 +0300 @@ -9162,6 +9162,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = Object.defineProperties({a:1}, {}); o.a"), nxt_string("1") }, + { nxt_string("Object.defineProperties()"), + nxt_string("TypeError: cannot convert undefined argument to object") }, + { nxt_string("Object.defineProperties(1, {})"), nxt_string("TypeError: cannot convert number argument to object") }, From mdounin at mdounin.ru Thu May 16 14:12:41 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 16 May 2019 17:12:41 +0300 Subject: redirect after body capture In-Reply-To: References: Message-ID: <20190516141241.GA1877@mdounin.ru> Hello! On Wed, May 15, 2019 at 05:35:54PM -0700, Dk Jack wrote: > Hi, > In my module, I am trying to forward the request to my server based on the > content of the request body. To acheive this, I've added a body capture > filter to capture the body. Here are the relevant parts of my code... > > static ngx_int_t > nginx_inspect_body_filter(ngx_http_request_t *r, ngx_chain_t *in) > { > > ... // extract body > if (if_content_of_interest_in_body(body, body_length)) { > ngx_str_t uri = ngx_string("/my_location"); > ngx_http_internal_redirect(r, &url, NULL); > ngx_http_finalize_request(r, NGX_DONE); > // return NGX_DONE; // causes connection abort. > } > ... > return ngx_http_next_body_filter(r, in); > } > > I have the following conf for '/my_location': > > server { > ... > location / { > ... > } > location /my_location { > proxy_pass http://myserver; > } > } > > However, I am running into an issue with my code. If return NGX_DONE after > internal redirect, I get a connection abort. If I call, next_body_filter, > the connection seems to hang. > > Doing a redirect, using similar code in PREACCESS_PHASE works without any > issues. The issue seems to happen only when I wait to read the entire body > and perform the redirect based on the content of the body. With no body > capture, it works fine. > > Do I need to do anything additional to redirect in the body filter? Thanks > for your help. You are not allowed to do any redirects in a request body filter. Request body filters are to parse / analyze / change the request body. If there is a problem detected, you can abort the request, but that's more or less all you can do. Moreover, when a request body filter is called it may be already too late to do any redirects - for example, with request buffering switched off ("proxy_pass_request_buffering off;") reading the request body happens after the request is already passed to a backend. If you really want to do a redirect based on what a request body filter detected, consider reading the body in your own module, and once reading the request body complete - redirect based on the request body filtering results. -- Maxim Dounin http://mdounin.ru/ From alexander.borisov at nginx.com Thu May 16 15:59:39 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 16 May 2019 15:59:39 +0000 Subject: [njs] Fixed processing * quantifier for String.prototype.replace(). Message-ID: details: https://hg.nginx.org/njs/rev/9005991a53d6 branches: changeset: 966:9005991a53d6 user: Alexander Borisov date: Wed May 08 17:05:05 2019 +0300 description: Fixed processing * quantifier for String.prototype.replace(). This closes #73 issue on GitHub. diffstat: njs/njs_string.c | 134 +++++++++++++++++++++++++++++++++++++++++----- njs/test/njs_unit_test.c | 33 +++++++++++ 2 files changed, 151 insertions(+), 16 deletions(-) diffs (243 lines): diff -r e0fdef4eb478 -r 9005991a53d6 njs/njs_string.c --- a/njs/njs_string.c Thu May 16 15:20:31 2019 +0300 +++ b/njs/njs_string.c Wed May 08 17:05:05 2019 +0300 @@ -3061,11 +3061,16 @@ njs_string_replace_regexp(njs_vm_t *vm, njs_string_replace_t *r) { int *captures; + u_char *p, *start; njs_ret_t ret; + const u_char *end; njs_regexp_pattern_t *pattern; - njs_string_replace_part_t *part; + njs_string_replace_part_t replace; pattern = args[1].data.u.regexp->pattern; + end = r->part[0].start + r->part[0].size; + + replace = r->part[1]; do { ret = njs_regexp_match(vm, &pattern->regex[r->type], @@ -3102,25 +3107,50 @@ njs_string_replace_regexp(njs_vm_t *vm, r->part -= 2; } - r->part[2].start = r->part[0].start + captures[1]; - r->part[2].size = r->part[0].size - captures[1]; - njs_set_invalid(&r->part[2].value); - - if (r->function != NULL) { - return njs_string_replace_regexp_function(vm, args, r, - captures, ret); + if (captures[1] == 0) { + + /* Empty match. */ + + start = r->part[0].start; + + if (start < end) { + p = (u_char *) nxt_utf8_next(start, end); + + r->part[1].start = start; + r->part[1].size = p - start; + + r->part[2].start = p; + r->part[2].size = end - p; + + } else { + r->part[1].size = 0; + r->part[2].size = 0; + + /* To exit the loop. */ + r->part[2].start = start + 1; + } + + r->part[0] = replace; + + } else { + r->part[2].start = r->part[0].start + captures[1]; + r->part[2].size = r->part[0].size - captures[1]; + njs_set_invalid(&r->part[2].value); + + if (r->function != NULL) { + return njs_string_replace_regexp_function(vm, args, r, + captures, ret); + } + + r->part[0].size = captures[0]; + + r->part[1] = replace; } - r->part[0].size = captures[0]; - if (!pattern->global) { return njs_string_replace_regexp_join(vm, r); } - /* A literal replacement is stored in the second part. */ - part = r->parts.start; - r->part[1] = part[1]; - r->part += 2; } @@ -3131,7 +3161,7 @@ njs_string_replace_regexp(njs_vm_t *vm, return NXT_ERROR; } - } while (r->part[0].size > 0); + } while (r->part[0].start <= end); if (r->part != r->parts.start) { return njs_string_replace_regexp_join(vm, r); @@ -3447,11 +3477,15 @@ static njs_ret_t njs_string_replace_substitute(njs_vm_t *vm, njs_string_replace_t *r, int *captures) { - uint32_t i, n, last; + uint32_t i, n, last, index; + const u_char *end; njs_string_subst_t *s; njs_string_replace_part_t *part, *subject; + index = 0; + last = r->substitutions->items; + end = r->part[0].start + r->part[0].size; part = nxt_array_add_multiple(&r->parts, &njs_array_mem_proto, vm->mem_pool, last + 1); @@ -3462,6 +3496,22 @@ njs_string_replace_substitute(njs_vm_t * r->part = &part[-1]; part[last].start = r->part[0].start + captures[1]; + + if (captures[1] == 0) { + + /* Empty match. */ + + if (r->part[0].start < end) { + captures[1] = nxt_utf8_next(r->part[0].start, end) + - r->part[0].start; + part[last].start = r->part[0].start + captures[1]; + + } else { + /* To exit the loop. */ + part[last].start = r->part[0].start + 1; + } + } + part[last].size = r->part[0].size - captures[1]; njs_set_invalid(&part[last].value); @@ -3498,6 +3548,44 @@ njs_string_replace_substitute(njs_vm_t * * "$&" is the same as "$0", the "$0" however is not supported. */ default: + if (captures[n] == captures[n + 1]) { + + /* Empty match. */ + + if (captures[n - 1] == captures[n]) { + + /* + * Consecutive empty matches as in + * 'ab'.replace(/(z*)(h*)/g, 'x') + */ + + part->size = 0; + break; + } + + index = n; + continue; + } + + if (index != 0) { + + /* + * Inserting a single character after a series of + * (possibly several) empty matches. + */ + + if (part->start < end) { + part->start = r->part[0].start + captures[index]; + part->size = nxt_utf8_next(part->start, end) - part->start; + + } else { + part->size = 0; + } + + index = 0; + break; + } + part->start = r->part[0].start + captures[n]; part->size = captures[n + 1] - captures[n]; break; @@ -3507,6 +3595,20 @@ njs_string_replace_substitute(njs_vm_t * part++; } + if (index != 0) { + part->start = r->part[0].start + captures[index]; + + if (part->start < end) { + part->size = nxt_utf8_next(part->start, end) - part->start; + + } else { + part->size = 0; + } + + njs_set_invalid(&part->value); + part++; + } + r->part = part; return NXT_OK; diff -r e0fdef4eb478 -r 9005991a53d6 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 16 15:20:31 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed May 08 17:05:05 2019 +0300 @@ -5451,6 +5451,39 @@ static njs_unit_test_t njs_test[] = { nxt_string("('?' + '?'.repeat(33)+'?').replace(/(?+)(?+)/, function(m, p1) { return p1[32]; })"), nxt_string("??") }, + { nxt_string("'abc'.replace(/(h*)(z*)(g*)/g, '$1nn$2zz$3')"), + nxt_string("nnzzannzzbnnzzcnnzz") }, + + { nxt_string("'abc'.replace(/(h*)(z*)/g, '$1nn$2zz$3yy')"), + nxt_string("nnzz$3yyannzz$3yybnnzz$3yycnnzz$3yy") }, + + { nxt_string("'?'.replace(/(h*)/g, '$1??')"), + nxt_string("?????") }, + + { nxt_string("'?g'.replace(/(h*)/g, '$1??')"), + nxt_string("?????g??") }, + + { nxt_string("'?g'.replace(/(?*)/g, '$1??')"), + nxt_string("?????g??") }, + + { nxt_string("'?g'.replace(/(h*)/g, 'fg$1??')"), + nxt_string("fg???fg??gfg??") }, + + { nxt_string("'?g?f?'.replace(/(g?)/g, 'n$1i')"), + nxt_string("?ng?if?") }, + + { nxt_string("'aabbccaa'.replace(/a*/g, '')"), + nxt_string("bbcc") }, + + { nxt_string("'aabbccaab'.replace(/z*/g, '')"), + nxt_string("aabbccaab") }, + + { nxt_string("'???'.replace(/z*/g, '|')"), + nxt_string("|?|?|?|") }, + + { nxt_string("''.replace(/a*/g, '')"), + nxt_string("") }, + { nxt_string("'abc'.match(/a*/g)"), nxt_string("a,,,") }, From pluknet at nginx.com Thu May 16 16:29:23 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 16 May 2019 16:29:23 +0000 Subject: [nginx] SSL: removed OpenSSL 0.9.7 compatibility. Message-ID: details: https://hg.nginx.org/nginx/rev/b99cbafd51da branches: changeset: 7509:b99cbafd51da user: Sergey Kandaurov date: Mon Apr 11 15:46:36 2016 +0300 description: SSL: removed OpenSSL 0.9.7 compatibility. diffstat: src/event/ngx_event_openssl.c | 47 +-------------------------- src/event/ngx_event_openssl_stapling.c | 5 +-- src/http/ngx_http_upstream_round_robin.c | 5 +-- src/stream/ngx_stream_upstream_round_robin.c | 5 +-- 4 files changed, 6 insertions(+), 56 deletions(-) diffs (179 lines): diff -r c30a20e06c21 -r b99cbafd51da src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Mon May 13 22:44:49 2019 +0300 +++ b/src/event/ngx_event_openssl.c Mon Apr 11 15:46:36 2016 +0300 @@ -164,7 +164,6 @@ ngx_ssl_init(ngx_log_t *log) #endif -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef SSL_OP_NO_COMPRESSION { /* @@ -182,7 +181,6 @@ ngx_ssl_init(ngx_log_t *log) } } #endif -#endif ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); @@ -904,13 +902,6 @@ ngx_ssl_client_certificate(ngx_conf_t *c return NGX_ERROR; } - /* - * before 0.9.7h and 0.9.8 SSL_load_client_CA_file() - * always leaved an error in the error queue - */ - - ERR_clear_error(); - SSL_CTX_set_client_CA_list(ssl->ctx, list); return NGX_OK; @@ -1076,8 +1067,8 @@ ngx_ssl_info_callback(const ngx_ssl_conn * added to wbio, and set buffer size. */ - rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn); - wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn); + rbio = SSL_get_rbio(ssl_conn); + wbio = SSL_get_wbio(ssl_conn); if (rbio != wbio) { (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE); @@ -1360,7 +1351,6 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_ ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) { -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH /* @@ -1435,7 +1425,6 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s EC_KEY_free(ecdh); #endif #endif -#endif return NGX_OK; } @@ -3364,17 +3353,8 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_ } } -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL - session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length); -#else - - session_id = sess->session_id; - session_id_length = sess->session_id_length; - -#endif - #if (NGX_PTR_SIZE == 8) id = sess_id->sess_id; @@ -3450,13 +3430,10 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ #endif u_char *id, int len, int *copy) { -#if OPENSSL_VERSION_NUMBER >= 0x0090707fL - const -#endif - u_char *p; size_t slen; uint32_t hash; ngx_int_t rc; + const u_char *p; ngx_shm_zone_t *shm_zone; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node, *sentinel; @@ -3578,17 +3555,8 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx cache = shm_zone->data; -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL - id = (u_char *) SSL_SESSION_get_id(sess, &len); -#else - - id = sess->session_id; - len = sess->session_id_length; - -#endif - hash = ngx_crc32_short(id, len); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, @@ -4387,17 +4355,8 @@ ngx_ssl_get_session_id(ngx_connection_t return NGX_OK; } -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL - buf = (u_char *) SSL_SESSION_get_id(sess, &len); -#else - - buf = sess->session_id; - len = sess->session_id_length; - -#endif - s->len = 2 * len; s->data = ngx_pnalloc(pool, 2 * len); if (s->data == NULL) { diff -r c30a20e06c21 -r b99cbafd51da src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c Mon May 13 22:44:49 2019 +0300 +++ b/src/event/ngx_event_openssl_stapling.c Mon Apr 11 15:46:36 2016 +0300 @@ -589,15 +589,12 @@ ngx_ssl_stapling_update(ngx_ssl_stapling static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) { -#if OPENSSL_VERSION_NUMBER >= 0x0090707fL - const -#endif - u_char *p; int n; size_t len; time_t now, valid; ngx_str_t response; X509_STORE *store; + const u_char *p; STACK_OF(X509) *chain; OCSP_CERTID *id; OCSP_RESPONSE *ocsp; diff -r c30a20e06c21 -r b99cbafd51da src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c Mon May 13 22:44:49 2019 +0300 +++ b/src/http/ngx_http_upstream_round_robin.c Mon Apr 11 15:46:36 2016 +0300 @@ -669,10 +669,7 @@ ngx_http_upstream_set_round_robin_peer_s ngx_http_upstream_rr_peer_t *peer; #if (NGX_HTTP_UPSTREAM_ZONE) int len; -#if OPENSSL_VERSION_NUMBER >= 0x0090707fL - const -#endif - u_char *p; + const u_char *p; ngx_http_upstream_rr_peers_t *peers; u_char buf[NGX_SSL_MAX_SESSION_SIZE]; #endif diff -r c30a20e06c21 -r b99cbafd51da src/stream/ngx_stream_upstream_round_robin.c --- a/src/stream/ngx_stream_upstream_round_robin.c Mon May 13 22:44:49 2019 +0300 +++ b/src/stream/ngx_stream_upstream_round_robin.c Mon Apr 11 15:46:36 2016 +0300 @@ -701,10 +701,7 @@ ngx_stream_upstream_set_round_robin_peer ngx_stream_upstream_rr_peer_t *peer; #if (NGX_STREAM_UPSTREAM_ZONE) int len; -#if OPENSSL_VERSION_NUMBER >= 0x0090707fL - const -#endif - u_char *p; + const u_char *p; ngx_stream_upstream_rr_peers_t *peers; u_char buf[NGX_SSL_MAX_SESSION_SIZE]; #endif From alexander.borisov at nginx.com Thu May 16 17:19:42 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 16 May 2019 17:19:42 +0000 Subject: [njs] Improved String.prototype.replace(). Message-ID: details: https://hg.nginx.org/njs/rev/58de3054b28a branches: changeset: 967:58de3054b28a user: Alexander Borisov date: Tue May 14 13:00:44 2019 +0300 description: Improved String.prototype.replace(). If replace value is a function and the function return non string value, then convert returned value to string. This closes #61 issue on GitHub. diffstat: njs/njs_string.c | 20 ++++++++++++++------ njs/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diffs (57 lines): diff -r 9005991a53d6 -r 58de3054b28a njs/njs_string.c --- a/njs/njs_string.c Wed May 08 17:05:05 2019 +0300 +++ b/njs/njs_string.c Tue May 14 13:00:44 2019 +0300 @@ -3355,20 +3355,28 @@ static njs_ret_t njs_string_replace_search_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { + njs_ret_t ret; + njs_value_t string; njs_string_replace_t *r; r = njs_vm_continuation(vm); - if (njs_is_string(&r->retval)) { - njs_string_replacement_copy(&r->part[1], &r->retval); - - return njs_string_replace_join(vm, r); + if (!njs_is_primitive(&r->retval)) { + njs_vm_trap_value(vm, &r->retval); + return njs_trap(vm, NJS_TRAP_STRING_ARG); } - njs_internal_error(vm, "unexpected continuation retval type:%s", + ret = njs_primitive_value_to_string(vm, &string, &r->retval); + if (nxt_slow_path(ret != NJS_OK)) { + njs_type_error(vm, "cannot convert primitive value to string: %s", njs_type_string(r->retval.type)); - return NXT_ERROR; + return NXT_ERROR; + } + + njs_string_replacement_copy(&r->part[1], &string); + + return njs_string_replace_join(vm, r); } diff -r 9005991a53d6 -r 58de3054b28a njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed May 08 17:05:05 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 14 13:00:44 2019 +0300 @@ -5484,6 +5484,15 @@ static njs_unit_test_t njs_test[] = { nxt_string("''.replace(/a*/g, '')"), nxt_string("") }, + { nxt_string("'12345'.replace(3, () => 0)"), + nxt_string("12045") }, + + { nxt_string("'123'.replace(3, function() { return {toString: ()=>({})}; })"), + nxt_string("TypeError: Cannot convert object to primitive value") }, + + { nxt_string("'12345'.replace(3, () => ({toString: () => 'aaaa'}))"), + nxt_string("12aaaa45") }, + { nxt_string("'abc'.match(/a*/g)"), nxt_string("a,,,") }, From ranier.vf at gmail.com Fri May 17 13:05:27 2019 From: ranier.vf at gmail.com (Ranier Vf) Date: Fri, 17 May 2019 10:05:27 -0300 Subject: redirect after body capture In-Reply-To: References: Message-ID: Hi, Can you try: return ngx_http_internal_redirect(r, &url, NULL); Best regards, Ranier Vilela Em qua, 15 de mai de 2019 ?s 21:36, Dk Jack escreveu: > Hi, > In my module, I am trying to forward the request to my server based on the > content of the request body. To acheive this, I've added a body capture > filter to capture the body. Here are the relevant parts of my code... > > static ngx_int_t > nginx_inspect_body_filter(ngx_http_request_t *r, ngx_chain_t *in) > { > > ... // extract body > if (if_content_of_interest_in_body(body, body_length)) { > ngx_str_t uri = ngx_string("/my_location"); > ngx_http_internal_redirect(r, &url, NULL); > ngx_http_finalize_request(r, NGX_DONE); > // return NGX_DONE; // causes connection abort. > } > ... > return ngx_http_next_body_filter(r, in); > } > > I have the following conf for '/my_location': > > server { > ... > location / { > ... > } > location /my_location { > proxy_pass http://myserver; > } > } > > However, I am running into an issue with my code. If return NGX_DONE after > internal redirect, I get a connection abort. If I call, next_body_filter, > the connection seems to hang. > > Doing a redirect, using similar code in PREACCESS_PHASE works without any > issues. The issue seems to happen only when I wait to read the entire body > and perform the redirect based on the content of the body. With no body > capture, it works fine. > > Do I need to do anything additional to redirect in the body filter? Thanks > for your help. > > Regards, > Dk. > _______________________________________________ > 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 May 17 14:53:54 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 17 May 2019 14:53:54 +0000 Subject: [njs] Fixed Array.prototype.slice() for UTF8-invalid byte strings. Message-ID: details: https://hg.nginx.org/njs/rev/9af8e1b5f3c1 branches: changeset: 968:9af8e1b5f3c1 user: Dmitry Volyntsev date: Fri May 17 17:52:30 2019 +0300 description: Fixed Array.prototype.slice() for UTF8-invalid byte strings. This closes #160 issue on Github. diffstat: njs/njs_array.c | 31 ++++++++++++++++++------------- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 21 insertions(+), 13 deletions(-) diffs (66 lines): diff -r 58de3054b28a -r 9af8e1b5f3c1 njs/njs_array.c --- a/njs/njs_array.c Tue May 14 13:00:44 2019 +0300 +++ b/njs/njs_array.c Fri May 17 17:52:30 2019 +0300 @@ -577,7 +577,7 @@ njs_array_prototype_slice_copy(njs_vm_t { size_t size; u_char *dst; - uint32_t n, len; + uint32_t n; njs_ret_t ret; njs_array_t *array; njs_value_t *value, name; @@ -623,23 +623,28 @@ njs_array_prototype_slice_copy(njs_vm_t if (string.length == 0) { /* Byte string. */ - len = 0; + do { + value = &array->start[n++]; + dst = njs_string_short_start(value); + *dst = *src++; + njs_string_short_set(value, 1, 0); + + length--; + } while (length != 0); } else { /* UTF-8 or ASCII string. */ - len = 1; + do { + value = &array->start[n++]; + dst = njs_string_short_start(value); + dst = nxt_utf8_copy(dst, &src, end); + size = dst - njs_string_short_start(value); + njs_string_short_set(value, size, 1); + + length--; + } while (length != 0); } - do { - value = &array->start[n++]; - dst = njs_string_short_start(value); - dst = nxt_utf8_copy(dst, &src, end); - size = dst - njs_string_short_start(value); - njs_string_short_set(value, size, len); - - length--; - } while (length != 0); - } else if (njs_is_object(this)) { do { diff -r 58de3054b28a -r 9af8e1b5f3c1 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 14 13:00:44 2019 +0300 +++ b/njs/test/njs_unit_test.c Fri May 17 17:52:30 2019 +0300 @@ -3657,6 +3657,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("Array.prototype.slice.call('??Z?')"), nxt_string("?,?,Z,?") }, + { nxt_string("Array.prototype.slice.call(String.bytesFrom(Array(16).fill(0x9d)))[0].charCodeAt(0)"), + nxt_string("157") }, + { nxt_string("Array.prototype.slice.call('??Z?', 1)"), nxt_string("?,Z,?") }, From xeioex at nginx.com Fri May 17 18:17:57 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 17 May 2019 18:17:57 +0000 Subject: [njs] Fixed String.prototype.split() for UTF8-invalid byte strings. Message-ID: details: https://hg.nginx.org/njs/rev/e22397fd709a branches: changeset: 969:e22397fd709a user: Dmitry Volyntsev date: Fri May 17 21:16:31 2019 +0300 description: Fixed String.prototype.split() for UTF8-invalid byte strings. This closes #161 issue on Github. diffstat: njs/njs_string.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diffs (32 lines): diff -r 9af8e1b5f3c1 -r e22397fd709a njs/njs_string.c --- a/njs/njs_string.c Fri May 17 17:52:30 2019 +0300 +++ b/njs/njs_string.c Fri May 17 21:16:31 2019 +0300 @@ -2757,7 +2757,7 @@ njs_string_match_multiple(njs_vm_t *vm, /* - * String.split([string|regexp[, limit]]) + * String.prototype.split([string|regexp[, limit]]) */ static njs_ret_t @@ -2838,7 +2838,8 @@ found: /* Empty split string. */ if (p == next) { - p = nxt_utf8_next(p, end); + p = (utf8 != NJS_STRING_BYTE) ? nxt_utf8_next(p, end) + : p + 1; next = p; } @@ -2885,7 +2886,8 @@ found: /* Empty split regexp. */ if (p == next) { - p = nxt_utf8_next(p, end); + p = (utf8 != NJS_STRING_BYTE) ? nxt_utf8_next(p, end) + : p + 1; next = p; } From alexander.borisov at nginx.com Fri May 17 18:57:12 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Fri, 17 May 2019 18:57:12 +0000 Subject: [njs] Added escaping to lone closing square brackets in a regexp. Message-ID: details: https://hg.nginx.org/njs/rev/88263426432d branches: changeset: 970:88263426432d user: Alexander Borisov date: Fri May 17 17:01:10 2019 +0300 description: Added escaping to lone closing square brackets in a regexp. 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. As a workaround, the solution is to escape those lone brackets. This closes #157 issue on GitHub. diffstat: njs/njs_regexp.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 30 ++++++++++++++++++ 2 files changed, 110 insertions(+), 0 deletions(-) diffs (155 lines): diff -r e22397fd709a -r 88263426432d njs/njs_regexp.c --- a/njs/njs_regexp.c Fri May 17 21:16:31 2019 +0300 +++ b/njs/njs_regexp.c Fri May 17 17:01:10 2019 +0300 @@ -206,15 +206,71 @@ 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; + + 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; + } + + start = text->start; + end = text->start + text->length; + + for (p = start; p < end; p++) { + + switch (*p) { + case '[': + while (++p < end && *p != ']') { + if (*p == '\\') { + p++; + } + } + + break; + + case ']': + diff = p - start; + dst = nxt_cpymem(dst, start, diff); + dst = nxt_cpymem(dst, "\\]", 2); + + start = p + 1; + break; + + case '\\': + p++; + break; + } + } + + diff = p - start; + memcpy(dst, start, diff); + + text->start = dst - (length - diff); + text->length = length; + + return NJS_OK; +} + + 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++) { @@ -242,6 +298,10 @@ 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; @@ -267,8 +327,28 @@ 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; } diff -r e22397fd709a -r 88263426432d njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Fri May 17 21:16:31 2019 +0300 +++ b/njs/test/njs_unit_test.c Fri May 17 17:01:10 2019 +0300 @@ -5496,6 +5496,36 @@ static njs_unit_test_t njs_test[] = { nxt_string("'12345'.replace(3, () => ({toString: () => 'aaaa'}))"), nxt_string("12aaaa45") }, + { nxt_string("/]/"), + nxt_string("/\\]/") }, + + { nxt_string("/\\]/"), + nxt_string("/\\]/") }, + + { nxt_string("/ab]cd/"), + nxt_string("/ab\\]cd/") }, + + { nxt_string("/ab]/"), + nxt_string("/ab\\]/") }, + + { nxt_string("/]cd/"), + nxt_string("/\\]cd/") }, + + { nxt_string("']'.match(/]/)"), + nxt_string("]") }, + + { nxt_string("'ab]cd'.match(/]/)"), + nxt_string("]") }, + + { nxt_string("'ab]'.match(/]/)"), + nxt_string("]") }, + + { nxt_string("']cd'.match(/]/)"), + nxt_string("]") }, + + { nxt_string("'ab]cd'.match(/\\]/)"), + nxt_string("]") }, + { nxt_string("'abc'.match(/a*/g)"), nxt_string("a,,,") }, From xeioex at nginx.com Mon May 20 16:07:00 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 20 May 2019 16:07:00 +0000 Subject: [njs] Fixed handling of empty block statements. Message-ID: details: https://hg.nginx.org/njs/rev/14ec3b2096af branches: changeset: 971:14ec3b2096af user: hongzhidao date: Mon May 20 23:14:29 2019 +0800 description: Fixed handling of empty block statements. This closes #165 issue on Github. diffstat: njs/njs_generator.c | 2 +- njs/njs_parser.c | 18 +++++++----------- njs/test/njs_unit_test.c | 3 +++ 3 files changed, 11 insertions(+), 12 deletions(-) diffs (55 lines): diff -r 88263426432d -r 14ec3b2096af njs/njs_generator.c --- a/njs/njs_generator.c Fri May 17 17:01:10 2019 +0300 +++ b/njs/njs_generator.c Mon May 20 23:14:29 2019 +0800 @@ -1558,7 +1558,7 @@ njs_generate_block_statement(njs_vm_t *v return ret; } - ret = njs_generate_statement(vm, generator, node->left); + ret = njs_generate_statement(vm, generator, node); if (nxt_slow_path(ret != NXT_OK)) { return ret; } diff -r 88263426432d -r 14ec3b2096af njs/njs_parser.c --- a/njs/njs_parser.c Fri May 17 17:01:10 2019 +0300 +++ b/njs/njs_parser.c Mon May 20 23:14:29 2019 +0800 @@ -468,19 +468,15 @@ njs_parser_block_statement(njs_vm_t *vm, } } - if (parser->node != NULL) { - /* The statement is not empty block or just semicolon. */ - - node = njs_parser_node_new(vm, parser, NJS_TOKEN_BLOCK); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - node->left = parser->node; - node->right = NULL; - parser->node = node; + node = njs_parser_node_new(vm, parser, NJS_TOKEN_BLOCK); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; } + node->left = parser->node; + node->right = NULL; + parser->node = node; + njs_parser_scope_end(vm, parser); return njs_parser_token(vm, parser); diff -r 88263426432d -r 14ec3b2096af njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Fri May 17 17:01:10 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon May 20 23:14:29 2019 +0800 @@ -6016,6 +6016,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("function f() { return 1; } { function f() { return 2; } { function f() { return 3; } }} f()"), nxt_string("1") }, + { nxt_string("{function f() {} {} f() }"), + nxt_string("undefined") }, + { nxt_string("{ var f; function f() {} }"), nxt_string("SyntaxError: \"f\" has already been declared in 1") }, From xeioex at nginx.com Mon May 20 16:37:30 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 20 May 2019 16:37:30 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/283813f5840f branches: changeset: 972:283813f5840f user: hongzhidao date: Mon May 20 16:05:58 2019 +0800 description: Style. diffstat: njs/njs_builtin.c | 17 +++++++++-------- njs/njs_builtin.h | 1 + njs/njs_parser_terminal.c | 2 +- njs/njs_vm.h | 1 + 4 files changed, 12 insertions(+), 9 deletions(-) diffs (89 lines): diff -r 14ec3b2096af -r 283813f5840f njs/njs_builtin.c --- a/njs/njs_builtin.c Mon May 20 23:14:29 2019 +0800 +++ b/njs/njs_builtin.c Mon May 20 16:05:58 2019 +0800 @@ -30,11 +30,11 @@ static nxt_array_t *njs_vm_expression_co static nxt_array_t *njs_object_completions(njs_vm_t *vm, njs_object_t *object); -const njs_object_init_t njs_njs_object_init; -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_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 */ @@ -43,9 +43,9 @@ const njs_object_init_t *njs_object_i }; -const njs_object_init_t *njs_module_init[] = { - &njs_fs_object_init, /* fs */ - &njs_crypto_object_init, /* crypto */ +const njs_object_init_t *njs_module_init[] = { + &njs_fs_object_init, /* fs */ + &njs_crypto_object_init, /* crypto */ NULL }; @@ -73,7 +73,7 @@ const njs_object_init_t *njs_prototype_ }; -const njs_object_init_t *njs_constructor_init[] = { +const njs_object_init_t *njs_constructor_init[] = { &njs_object_constructor_init, &njs_array_constructor_init, &njs_boolean_constructor_init, @@ -97,7 +97,7 @@ const njs_object_init_t *njs_construc }; -const njs_object_init_t *njs_function_init[] = { +const njs_object_init_t *njs_function_init[] = { &njs_eval_function_init, &njs_to_string_function_init, &njs_is_nan_function_init, @@ -165,6 +165,7 @@ const njs_function_init_t njs_native_co { njs_memory_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } }, }; + const njs_object_prototype_t njs_prototype_values[] = { /* * GCC 4 complains about uninitialized .shared field, diff -r 14ec3b2096af -r 283813f5840f njs/njs_builtin.h --- a/njs/njs_builtin.h Mon May 20 23:14:29 2019 +0800 +++ b/njs/njs_builtin.h Mon May 20 16:05:58 2019 +0800 @@ -13,4 +13,5 @@ extern const njs_object_init_t *njs_mod extern const njs_object_init_t *njs_prototype_init[]; extern const njs_object_init_t *njs_constructor_init[]; + #endif /* _NJS_BUILTIN_H_INCLUDED_ */ diff -r 14ec3b2096af -r 283813f5840f njs/njs_parser_terminal.c --- a/njs/njs_parser_terminal.c Mon May 20 23:14:29 2019 +0800 +++ b/njs/njs_parser_terminal.c Mon May 20 16:05:58 2019 +0800 @@ -805,7 +805,7 @@ njs_parser_template_expression(njs_vm_t if (token != NJS_TOKEN_CLOSE_BRACE) { njs_parser_syntax_error(vm, parser, - "Missing \"}\" in template expression"); + "Missing \"}\" in template expression"); return NXT_ERROR; } diff -r 14ec3b2096af -r 283813f5840f njs/njs_vm.h --- a/njs/njs_vm.h Mon May 20 23:14:29 2019 +0800 +++ b/njs/njs_vm.h Mon May 20 16:05:58 2019 +0800 @@ -894,6 +894,7 @@ typedef enum { #define njs_is_callee_argument_index(index) \ (((index) & NJS_SCOPE_CALLEE_ARGUMENTS) == NJS_SCOPE_CALLEE_ARGUMENTS) + enum njs_prototypes_e { NJS_PROTOTYPE_OBJECT = 0, NJS_PROTOTYPE_ARRAY, From st4ck0v3rfl0w at gmail.com Tue May 21 12:52:25 2019 From: st4ck0v3rfl0w at gmail.com (st4ck0v3rfl0w) Date: Tue, 21 May 2019 14:52:25 +0200 Subject: Module: choose upstream server based on request body Message-ID: Hi, I want to create a module, that fastcgi_passes a request to different servers based on the content of the post request. Initially I had two ideas: 1. Create a load balancer module: I was not successful with this, because I did not know how to access the request. 2. Create a variable that classifies the request based on the content, then map it on server addresses and call fastcgi_pass on the map variable. This seems easy and elegant, but the r->request_body variable is NULL for me. What I did: - create module without directive - call ngx_http_add_variable in the preconfig function - set a getter for the variable - try to read r->request_body in the getter I just cannot find a lot of information about this online. I probably should call ngx_http_read_client_request_body at some point, but I am struggling how to use it correctly. How can I make the request_body available when reading the variable? Is there a different and easier / more elegant way to solve this? Thanks for your time :) -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue May 21 14:27:18 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 21 May 2019 14:27:18 +0000 Subject: [nginx] nginx-1.17.0-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/054c1c46395c branches: changeset: 7510:054c1c46395c user: Maxim Dounin date: Tue May 21 17:23:57 2019 +0300 description: nginx-1.17.0-RELEASE diffstat: docs/xml/nginx/changes.xml | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 62 insertions(+), 0 deletions(-) diffs (72 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,68 @@ + + + + +????????? limit_rate ? limit_rate_after ???????????? ??????????. + + +variables support in the "limit_rate" and "limit_rate_after" directives. + + + + + +????????? proxy_upload_rate ? proxy_download_rate ? ?????? stream +???????????? ??????????. + + +variables support +in the "proxy_upload_rate" and "proxy_download_rate" directives +in the stream module. + + + + + +??????????? ?????????????? ?????? OpenSSL—0.9.8. + + +minimum supported OpenSSL version is 0.9.8. + + + + + +?????? postpone-?????? ?????????? ??????. + + +now the postpone filter is always built. + + + + + +????????? include ?? ???????? ? ?????? if ? limit_except. + + +the "include" directive did not work inside the "if" and "limit_except" blocks. + + + + + +? ????????? byte ranges. + + +in byte ranges processing. + + + + + + From mdounin at mdounin.ru Tue May 21 14:27:19 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 21 May 2019 14:27:19 +0000 Subject: [nginx] release-1.17.0 tag Message-ID: details: https://hg.nginx.org/nginx/rev/234373adb2ce branches: changeset: 7511:234373adb2ce user: Maxim Dounin date: Tue May 21 17:23:57 2019 +0300 description: release-1.17.0 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -438,3 +438,4 @@ d2fd76709909767fc727a5b4affcf1dc9ca488a7 75f5c7f628411c79c7044102049f7ab4f7a246e7 release-1.15.10 5155d0296a5ef9841f035920527ffdb771076b44 release-1.15.11 0130ca3d58437b3c7c707cdddd813d530c68da9a release-1.15.12 +054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0 From xeioex at nginx.com Tue May 21 14:32:42 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 May 2019 14:32:42 +0000 Subject: [njs] Version 0.3.2. Message-ID: details: https://hg.nginx.org/njs/rev/82101d50fff6 branches: changeset: 973:82101d50fff6 user: Dmitry Volyntsev date: Tue May 21 17:31:13 2019 +0300 description: Version 0.3.2. diffstat: CHANGES | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 68 insertions(+), 0 deletions(-) diffs (75 lines): diff -r 283813f5840f -r 82101d50fff6 CHANGES --- a/CHANGES Mon May 20 16:05:58 2019 +0800 +++ b/CHANGES Tue May 21 17:31:13 2019 +0300 @@ -1,3 +1,71 @@ + +Changes with njs 0.3.2 21 May 2019 + + Core: + + *) Feature: added support for template literals. + Thanks to ??? (Hong Zhi Dao) and Artem S. Povalyukhin. + + *) Feature: executing command from command line arguments. + + *) Feature: added support for RegExp "groups" object (ES9). + + *) Feature: added block scoped function definitions support. + + *) Feature: added support for building with GNU Readline library. + + *) Feature: made configurable "length", "name", and most of built-in + methods. + + *) Feature: made all constructor properties configurable. + + *) Bugfix: fixed Regexp.prototype.exec() for Unicode-only regexps. + + *) Bugfix: fixed njs_vm_value_dump() for empty string values. + + *) Bugfix: fixed RegExp constructor for regexp value arguments. + + *) Bugfix: fixed walking over prototypes chain during iteration + over an object. + + *) Bugfix: fixed overflow in Array.prototype.concat(). + + *) Bugfix: fixed length calculation for UTF-8 string with escape + characters. + + *) Bugfix: fixed parsing surrogate pair presents as UTF-16 escape + sequences. + + *) Bugfix: fixed processing asterisk quantifier for + String.prototype.match(). + + *) Bugfix: fixed Date() constructor with one argument. + + *) Bugfix: fixed arrays expansion. + + *) Bugfix: fixed heap-buffer-overflow in String.prototype.replace(). + + *) Bugfix: fixed heap-buffer-overflow in + String.prototype.lastIndexOf(). + + *) Bugfix: fixed regexp literals parsing with escaped backslash and + backslash in square brackets. + + *) Bugfix: fixed regexp literals with lone closing brackets. + + *) Bugfix: fixed uninitialized-memory-access in + Object.defineProperties(). + + *) Bugfix: fixed processing "*" quantifier for + String.prototype.replace(). + + *) Bugfix: fixed Array.prototype.slice() for UTF8-invalid byte + strings. + + *) Bugfix: fixed String.prototype.split() for UTF8-invalid byte + strings. + + *) Bugfix: fixed handling of empty block statements. Changes with njs 0.3.1 16 Apr 2019 From xeioex at nginx.com Tue May 21 14:32:42 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 May 2019 14:32:42 +0000 Subject: [njs] Added tag 0.3.2 for changeset 82101d50fff6 Message-ID: details: https://hg.nginx.org/njs/rev/3a5325660c89 branches: changeset: 974:3a5325660c89 user: Dmitry Volyntsev date: Tue May 21 17:32:32 2019 +0300 description: Added tag 0.3.2 for changeset 82101d50fff6 diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 82101d50fff6 -r 3a5325660c89 .hgtags --- a/.hgtags Tue May 21 17:31:13 2019 +0300 +++ b/.hgtags Tue May 21 17:32:32 2019 +0300 @@ -25,3 +25,4 @@ 4624ba4f6497a3d10fe1c0a6f45fb453579502f5 ee190d3ace005f8eb063d4763b578f44d3028c68 0.2.8 1935ab4643fdaec5b4a8c36070f4d2cb8e3799d7 0.3.0 ebfbdb8d8fe2f640d880359575657cb53e38328f 0.3.1 +82101d50fff6e4c7a92c0542a3d6026ff7e462fb 0.3.2 From xeioex at nginx.com Tue May 21 16:39:41 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 May 2019 16:39:41 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/8d8fd9c98174 branches: changeset: 975:8d8fd9c98174 user: Dmitry Volyntsev date: Tue May 21 19:39:25 2019 +0300 description: Version bump. diffstat: njs/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 3a5325660c89 -r 8d8fd9c98174 njs/njs.h --- a/njs/njs.h Tue May 21 17:32:32 2019 +0300 +++ b/njs/njs.h Tue May 21 19:39:25 2019 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.2" +#define NJS_VERSION "0.3.3" #include From alexander.borisov at nginx.com Tue May 21 17:46:06 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 21 May 2019 17:46:06 +0000 Subject: [njs] Fixed integer-overflow in String.prototype.concat(). Message-ID: details: https://hg.nginx.org/njs/rev/96dc80e2ea1b branches: changeset: 976:96dc80e2ea1b user: Alexander Borisov date: Tue May 21 20:45:42 2019 +0300 description: Fixed integer-overflow in String.prototype.concat(). This closes #159 issue on GitHub. diffstat: njs/njs_string.c | 11 ++++++++--- njs/njs_string.h | 4 ++-- njs/test/njs_unit_test.c | 5 +++++ 3 files changed, 15 insertions(+), 5 deletions(-) diffs (61 lines): diff -r 8d8fd9c98174 -r 96dc80e2ea1b njs/njs_string.c --- a/njs/njs_string.c Tue May 21 19:39:25 2019 +0300 +++ b/njs/njs_string.c Tue May 21 20:45:42 2019 +0300 @@ -181,12 +181,17 @@ njs_string_new(njs_vm_t *vm, njs_value_t nxt_noinline u_char * -njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint32_t size, - uint32_t length) +njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint64_t size, + uint64_t length) { uint32_t total, map_offset, *map; njs_string_t *string; + if (nxt_slow_path(size > NJS_STRING_MAX_LENGTH)) { + njs_range_error(vm, "invalid string length"); + return NULL; + } + value->type = NJS_STRING; njs_string_truth(value, size); @@ -844,7 +849,7 @@ njs_string_prototype_concat(njs_vm_t *vm njs_index_t unused) { u_char *p, *start; - size_t size, length, mask; + uint64_t size, length, mask; nxt_uint_t i; njs_string_prop_t string; diff -r 8d8fd9c98174 -r 96dc80e2ea1b njs/njs_string.h --- a/njs/njs_string.h Tue May 21 19:39:25 2019 +0300 +++ b/njs/njs_string.h Tue May 21 20:45:42 2019 +0300 @@ -145,8 +145,8 @@ njs_string_length(njs_value_t *string) njs_ret_t njs_string_set(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size); -u_char *njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint32_t size, - uint32_t length); +u_char *njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint64_t size, + uint64_t length); njs_ret_t njs_string_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size, uint32_t length); njs_ret_t njs_string_hex(njs_vm_t *vm, njs_value_t *value, diff -r 8d8fd9c98174 -r 96dc80e2ea1b njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 21 19:39:25 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 21 20:45:42 2019 +0300 @@ -4620,6 +4620,11 @@ static njs_unit_test_t njs_test[] = { nxt_string("'A'.repeat(16).toBytes() === 'A'.repeat(16)"), nxt_string("true") }, + { nxt_string("var s = 'x'.repeat(2**10).repeat(2**14);" + "var a = Array(200).fill(s);" + "String.prototype.concat.apply(s, a.slice(1))"), + nxt_string("RangeError: invalid string length") }, + { nxt_string("var a = 'abcdefgh'; a.substr(3, 15)"), nxt_string("defgh") }, From vbart at nginx.com Tue May 21 18:25:28 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 21 May 2019 18:25:28 +0000 Subject: [njs] Uncommented a successful test of Object.create([1,2]).length. Message-ID: details: https://hg.nginx.org/njs/rev/260d9d4f29ee branches: changeset: 977:260d9d4f29ee user: Valentin Bartenev date: Tue May 21 21:15:21 2019 +0300 description: Uncommented a successful test of Object.create([1,2]).length. It's actually passing after f5bdddca3252. diffstat: njs/test/njs_unit_test.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 96dc80e2ea1b -r 260d9d4f29ee njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 21 20:45:42 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 21 21:15:21 2019 +0300 @@ -3399,10 +3399,8 @@ static njs_unit_test_t njs_test[] = { nxt_string("\n[\n1\n,\n2]\n[\n0]"), nxt_string("1") }, -#if 0 { nxt_string("Object.create([1,2]).length"), nxt_string("2") }, -#endif { nxt_string("Object.create(['?','?'])[1]"), nxt_string("?") }, From alexander.borisov at nginx.com Wed May 22 18:05:22 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Wed, 22 May 2019 18:05:22 +0000 Subject: [njs] Improved working with undefined symbols. Message-ID: details: https://hg.nginx.org/njs/rev/88c5787352b2 branches: changeset: 978:88c5787352b2 user: Alexander Borisov date: Wed May 22 21:01:39 2019 +0300 description: Improved working with undefined symbols. Throwing ReferenceError in runtime. This closes #150 issue on GitHub. diffstat: njs/njs_disassembler.c | 8 ++++++++ njs/njs_generator.c | 33 ++++++++++++++++++++++++++++++--- njs/njs_variable.c | 19 +++---------------- njs/njs_variable.h | 1 + njs/njs_vm.c | 15 +++++++++++++++ njs/njs_vm.h | 9 +++++++++ njs/test/njs_unit_test.c | 24 ++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 19 deletions(-) diffs (244 lines): diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_disassembler.c --- a/njs/njs_disassembler.c Tue May 21 21:15:21 2019 +0300 +++ b/njs/njs_disassembler.c Wed May 22 21:01:39 2019 +0300 @@ -411,6 +411,14 @@ njs_disassemble(u_char *start, u_char *e continue; } + if (operation == njs_vmcode_reference_error) { + nxt_printf("%05uz REFERENCE ERROR\n", p - start); + + p += sizeof(njs_vmcode_reference_error_t); + + continue; + } + code_name = code_names; n = nxt_nitems(code_names); diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_generator.c --- a/njs/njs_generator.c Tue May 21 21:15:21 2019 +0300 +++ b/njs/njs_generator.c Wed May 22 21:01:39 2019 +0300 @@ -174,6 +174,8 @@ static nxt_noinline nxt_int_t njs_genera njs_generator_t *generator, njs_parser_node_t *node); static nxt_noinline nxt_int_t njs_generate_index_release(njs_vm_t *vm, njs_generator_t *generator, njs_index_t index); +static nxt_int_t njs_generate_reference_error(njs_vm_t *vm, + njs_generator_t *generator, njs_parser_node_t *node); static nxt_int_t njs_generate_function_debug(njs_vm_t *vm, const nxt_str_t *name, njs_function_lambda_t *lambda, @@ -550,7 +552,7 @@ njs_generate_name(njs_vm_t *vm, njs_gene var = njs_variable_resolve(vm, node); if (nxt_slow_path(var == NULL)) { - return NXT_ERROR; + return njs_generate_reference_error(vm, generator, node); } if (var->type == NJS_VARIABLE_FUNCTION) { @@ -606,7 +608,7 @@ njs_generate_variable(njs_vm_t *vm, njs_ index = njs_variable_index(vm, node); if (nxt_slow_path(index == NJS_INDEX_NONE)) { - return NXT_ERROR; + return njs_generate_reference_error(vm, generator, node); } node->index = index; @@ -2304,7 +2306,7 @@ njs_generate_function_declaration(njs_vm var = njs_variable_resolve(vm, node); if (nxt_slow_path(var == NULL)) { - return NXT_ERROR; + return njs_generate_reference_error(vm, generator, node); } if (!njs_is_function(&var->value)) { @@ -2591,6 +2593,10 @@ njs_generate_function_call(njs_vm_t *vm, name = node; } + if (node->u.reference.not_defined) { + return NXT_OK; + } + njs_generate_code(generator, njs_vmcode_function_frame_t, func, njs_vmcode_function_frame, 2, 0); func_offset = njs_code_offset(generator, func); @@ -3273,6 +3279,27 @@ njs_generate_index_release(njs_vm_t *vm, static nxt_int_t +njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator, + njs_parser_node_t *node) +{ + njs_vmcode_reference_error_t *ref_err; + + if (nxt_slow_path(!node->u.reference.not_defined)) { + njs_internal_error(vm, "variable is not defined but not_defined " + "is not set"); + return NJS_ERROR; + } + + njs_generate_code(generator, njs_vmcode_reference_error_t, ref_err, + njs_vmcode_reference_error, 0, 0); + + ref_err->token_line = node->token_line; + + return njs_name_copy(vm, &ref_err->name, &node->u.reference.name); +} + + +static nxt_int_t njs_generate_function_debug(njs_vm_t *vm, const nxt_str_t *name, njs_function_lambda_t *lambda, njs_parser_node_t *node) { diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_variable.c --- a/njs/njs_variable.c Tue May 21 21:15:21 2019 +0300 +++ b/njs/njs_variable.c Wed May 22 21:01:39 2019 +0300 @@ -280,7 +280,6 @@ njs_variables_scope_resolve(njs_vm_t *vm { njs_ret_t ret; nxt_queue_t *nested; - njs_variable_t *var; nxt_queue_link_t *lnk; njs_parser_node_t *node; nxt_lvlhsh_each_t lhe; @@ -321,13 +320,7 @@ njs_variables_scope_resolve(njs_vm_t *vm } } - var = njs_variable_resolve(vm, node); - - if (nxt_slow_path(var == NULL)) { - if (vr->type != NJS_TYPEOF) { - return NXT_ERROR; - } - } + (void) njs_variable_resolve(vm, node); } } @@ -415,7 +408,8 @@ njs_variable_resolve(njs_vm_t *vm, njs_p ret = njs_variable_reference_resolve(vm, vr, node->scope); if (nxt_slow_path(ret != NXT_OK)) { - goto not_found; + node->u.reference.not_defined = 1; + return NULL; } scope_index = vr->scope_index; @@ -455,13 +449,6 @@ njs_variable_resolve(njs_vm_t *vm, njs_p node->index = index; return var; - -not_found: - - njs_parser_node_error(vm, node, NJS_OBJECT_REF_ERROR, - "\"%V\" is not defined", &vr->name); - - return NULL; } diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_variable.h --- a/njs/njs_variable.h Tue May 21 21:15:21 2019 +0300 +++ b/njs/njs_variable.h Wed May 22 21:01:39 2019 +0300 @@ -50,6 +50,7 @@ typedef struct { njs_variable_t *variable; njs_parser_scope_t *scope; nxt_uint_t scope_index; /* NJS_SCOPE_INDEX_... */ + nxt_bool_t not_defined; } njs_variable_reference_t; diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_vm.c --- a/njs/njs_vm.c Tue May 21 21:15:21 2019 +0300 +++ b/njs/njs_vm.c Wed May 22 21:01:39 2019 +0300 @@ -2523,6 +2523,21 @@ njs_vmcode_finally(njs_vm_t *vm, njs_val } +njs_ret_t +njs_vmcode_reference_error(njs_vm_t *vm, njs_value_t *invld1, + njs_value_t *invld2) +{ + njs_vmcode_reference_error_t *ref_err; + + ref_err = (njs_vmcode_reference_error_t *) vm->current; + + njs_reference_error(vm, "\"%V\" is not defined in %uD", &ref_err->name, + ref_err->token_line); + + return NJS_ERROR; +} + + static const njs_vmcode_1addr_t njs_trap_number[] = { { .code = { .operation = njs_vmcode_number_primitive, .operands = NJS_VMCODE_1OPERAND, diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_vm.h --- a/njs/njs_vm.h Tue May 21 21:15:21 2019 +0300 +++ b/njs/njs_vm.h Wed May 22 21:01:39 2019 +0300 @@ -849,6 +849,13 @@ typedef struct { } njs_vmcode_finally_t; +typedef struct { + njs_vmcode_t code; + nxt_str_t name; + uint32_t token_line; +} njs_vmcode_reference_error_t; + + typedef enum { NJS_SCOPE_ABSOLUTE = 0, NJS_SCOPE_GLOBAL = 1, @@ -1303,6 +1310,8 @@ njs_ret_t njs_vmcode_catch(njs_vm_t *vm, njs_value_t *exception); njs_ret_t njs_vmcode_finally(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval); +njs_ret_t njs_vmcode_reference_error(njs_vm_t *vm, njs_value_t *invld1, + njs_value_t *invld2); nxt_bool_t njs_values_strict_equal(const njs_value_t *val1, const njs_value_t *val2); diff -r 260d9d4f29ee -r 88c5787352b2 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 21 21:15:21 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed May 22 21:01:39 2019 +0300 @@ -6294,8 +6294,32 @@ static njs_unit_test_t njs_test[] = nxt_string("a") }, { nxt_string("function f() { var a = f2(); }"), + nxt_string("undefined") }, + + { nxt_string("function f() { var a = f2(); } f();"), nxt_string("ReferenceError: \"f2\" is not defined in 1") }, + { nxt_string("typeof Buffer !== 'undefined' ? Buffer : function Buffer(){}"), + nxt_string("[object Function]") }, + + { nxt_string("1 == 2 ? func() : '123'"), + nxt_string("123") }, + + { nxt_string("1 == 1 ? func() : '123'"), + nxt_string("ReferenceError: \"func\" is not defined in 1") }, + + { nxt_string("function f(){ if (1 == 1) { 1 == 2 ? some_var : '123' } }; f()"), + nxt_string("undefined") }, + + { nxt_string("function f(){ if (1 == 1) { 1 == 1 ? some_var : '123' } }; f()"), + nxt_string("ReferenceError: \"some_var\" is not defined in 1") }, + + { nxt_string("function f(){ if (1 == 1) { 1 == 2 ? some_func() : '123' } }; f()"), + nxt_string("undefined") }, + + { nxt_string("function f(){ if (1 == 1) { 1 == 1 ? some_func() : '123' } }; f()"), + nxt_string("ReferenceError: \"some_func\" is not defined in 1") }, + { nxt_string("(function(){ function f() {return f}; return f()})()"), nxt_string("[object Function]") }, From me at kelunik.com Wed May 22 19:59:46 2019 From: me at kelunik.com (Niklas Keller) Date: Wed, 22 May 2019 21:59:46 +0200 Subject: Using round robin for load balancing if hash key is empty Message-ID: Hey, I'd like to propose falling back to round robin if the hash key is empty. This allows using hashed cookie values for sticky sessions while using round robin for all requests that do not carry any session information and thus do not need the stickiness. While Nginx Plus allows to use the learning mode, this patch avoids the need for synchronization between multiple instances. Instead of falling back to round robin automatically, this could also be changed to offer a configuration option, but I think it's a sensible default. An additional configuration option could be added in the future to change the fallback from round robin to another node selection strategy. You can find the patch at the end of this email. Kind regards, Niklas # HG changeset patch # User Niklas Keller # Date 1558554036 -7200 # Wed May 22 21:40:36 2019 +0200 # Node ID 34015c26b7fe9bda83390d25d989acb109c8d1ea # Parent 234373adb2ce6023e69e527cbf2b60adf70b1130 Use round-robin if hash key is empty diff -r 234373adb2ce -r 34015c26b7fe src/http/modules/ngx_http_upstream_hash_module.c --- a/src/http/modules/ngx_http_upstream_hash_module.c Tue May 21 17:23:57 2019 +0300 +++ b/src/http/modules/ngx_http_upstream_hash_module.c Wed May 22 21:40:36 2019 +0200 @@ -178,7 +178,7 @@ ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } From vbart at nginx.com Thu May 23 12:54:47 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 23 May 2019 12:54:47 +0000 Subject: [njs] Fixed setting of object properties. Message-ID: details: https://hg.nginx.org/njs/rev/ff591ba3e780 branches: changeset: 979:ff591ba3e780 user: Valentin Bartenev date: Thu May 23 15:05:50 2019 +0300 description: Fixed setting of object properties. Now writability of prototype properties is properly taken into account. diffstat: njs/njs_disassembler.c | 2 + njs/njs_generator.c | 12 +- njs/njs_lexer.h | 1 + njs/njs_object.c | 48 ++------- njs/njs_object.h | 2 + njs/njs_parser_terminal.c | 2 +- njs/njs_vm.c | 240 +++++++++++++++++++++++++++++++++++---------- njs/njs_vm.h | 2 + njs/test/njs_unit_test.c | 70 +++++++++++-- 9 files changed, 269 insertions(+), 110 deletions(-) diffs (697 lines): diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_disassembler.c --- a/njs/njs_disassembler.c Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_disassembler.c Thu May 23 15:05:50 2019 +0300 @@ -36,6 +36,8 @@ static njs_code_name_t code_names[] = { { njs_vmcode_property_get, sizeof(njs_vmcode_prop_get_t), nxt_string("PROPERTY GET ") }, + { njs_vmcode_property_init, sizeof(njs_vmcode_prop_set_t), + nxt_string("PROPERTY INIT ") }, { njs_vmcode_property_set, sizeof(njs_vmcode_prop_set_t), nxt_string("PROPERTY SET ") }, { njs_vmcode_property_in, sizeof(njs_vmcode_3addr_t), diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_generator.c --- a/njs/njs_generator.c Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_generator.c Thu May 23 15:05:50 2019 +0300 @@ -1682,7 +1682,7 @@ njs_generate_assignment(njs_vm_t *vm, nj return NXT_OK; } - /* lvalue->token == NJS_TOKEN_PROPERTY */ + /* lvalue->token == NJS_TOKEN_PROPERTY(_INIT) */ /* Object. */ @@ -1735,8 +1735,14 @@ njs_generate_assignment(njs_vm_t *vm, nj return ret; } - njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, - njs_vmcode_property_set, 3, 0); + if (lvalue->token == NJS_TOKEN_PROPERTY_INIT) { + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, + njs_vmcode_property_init, 3, 0); + } else { + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, + njs_vmcode_property_set, 3, 0); + } + prop_set->value = expr->index; prop_set->object = object->index; prop_set->property = property->index; diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_lexer.h --- a/njs/njs_lexer.h Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_lexer.h Thu May 23 15:05:50 2019 +0300 @@ -123,6 +123,7 @@ typedef enum { NJS_TOKEN_OBJECT, NJS_TOKEN_OBJECT_VALUE, NJS_TOKEN_PROPERTY, + NJS_TOKEN_PROPERTY_INIT, NJS_TOKEN_PROPERTY_DELETE, NJS_TOKEN_ARRAY, diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_object.c --- a/njs/njs_object.c Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_object.c Thu May 23 15:05:50 2019 +0300 @@ -22,8 +22,6 @@ static njs_ret_t njs_external_property_s 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_object_query_prop_handler(njs_property_query_t *pq, - njs_object_t *object); 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); @@ -379,6 +377,7 @@ njs_property_query(njs_vm_t *vm, njs_pro 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); } @@ -395,6 +394,7 @@ njs_object_property_query(njs_vm_t *vm, { uint32_t index; njs_ret_t ret; + nxt_bool_t own; njs_array_t *array; njs_object_t *proto; njs_object_prop_t *prop; @@ -402,12 +402,8 @@ njs_object_property_query(njs_vm_t *vm, pq->lhq.proto = &njs_object_hash_proto; - if (pq->query == NJS_PROPERTY_QUERY_SET) { - ret = njs_object_query_prop_handler(pq, object); - if (ret == NXT_OK) { - return ret; - } - } + own = pq->own; + pq->own = 1; proto = object; @@ -450,6 +446,10 @@ njs_object_property_query(njs_vm_t *vm, return ret; } + if (pq->own) { + pq->own_whiteout = prop; + } + } else { ret = nxt_lvlhsh_find(&proto->shared_hash, &pq->lhq); @@ -460,10 +460,11 @@ njs_object_property_query(njs_vm_t *vm, } } - if (pq->own || pq->query > NJS_PROPERTY_QUERY_GET) { + if (own) { return NXT_DECLINED; } + pq->own = 0; proto = proto->__proto__; } while (proto != NULL); @@ -706,33 +707,6 @@ njs_external_property_delete(njs_vm_t *v } -static njs_ret_t -njs_object_query_prop_handler(njs_property_query_t *pq, njs_object_t *object) -{ - njs_ret_t ret; - njs_object_prop_t *prop; - - do { - pq->prototype = object; - - ret = nxt_lvlhsh_find(&object->shared_hash, &pq->lhq); - - if (ret == NXT_OK) { - prop = pq->lhq.value; - - if (prop->type == NJS_PROPERTY_HANDLER) { - return NXT_OK; - } - } - - object = object->__proto__; - - } while (object != NULL); - - return NXT_DECLINED; -} - - njs_ret_t njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq) { @@ -1862,7 +1836,7 @@ njs_define_property(njs_vm_t *vm, njs_va 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, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 1); ret = njs_property_query(vm, &pq, object, name); diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_object.h --- a/njs/njs_object.h Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_object.h Thu May 23 15:05:50 2019 +0300 @@ -53,6 +53,7 @@ typedef struct { njs_value_t value; njs_object_t *prototype; + njs_object_prop_t *own_whiteout; uint8_t query; uint8_t shared; uint8_t own; @@ -63,6 +64,7 @@ typedef struct { do { \ (pq)->lhq.key.length = 0; \ (pq)->lhq.value = NULL; \ + (pq)->own_whiteout = NULL; \ (pq)->query = _query; \ (pq)->shared = 0; \ (pq)->own = _own; \ diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_parser_terminal.c --- a/njs/njs_parser_terminal.c Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_parser_terminal.c Thu May 23 15:05:50 2019 +0300 @@ -599,7 +599,7 @@ njs_parser_object_property(njs_vm_t *vm, object->u.object = parent; - propref = njs_parser_node_new(vm, parser, NJS_TOKEN_PROPERTY); + propref = njs_parser_node_new(vm, parser, NJS_TOKEN_PROPERTY_INIT); if (nxt_slow_path(propref == NULL)) { return NXT_ERROR; } diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_vm.c --- a/njs/njs_vm.c Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_vm.c Thu May 23 15:05:50 2019 +0300 @@ -545,12 +545,122 @@ njs_vmcode_property_get(njs_vm_t *vm, nj njs_ret_t +njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *object, + njs_value_t *property) +{ + uint32_t index, size; + njs_ret_t ret; + njs_array_t *array; + njs_value_t *init, *value, name; + njs_object_t *obj; + njs_object_prop_t *prop; + nxt_lvlhsh_query_t lhq; + njs_vmcode_prop_set_t *code; + + code = (njs_vmcode_prop_set_t *) vm->current; + init = njs_vmcode_operand(vm, code->value); + + switch (object->type) { + case NJS_ARRAY: + index = njs_value_to_index(property); + if (nxt_slow_path(index == NJS_ARRAY_INVALID_INDEX)) { + njs_internal_error(vm, + "invalid index while property initialization"); + return NXT_ERROR; + } + + array = object->data.u.array; + + if (index >= array->length) { + 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; + } + + /* GC: retain. */ + array->start[index] = *init; + + break; + + case NJS_OBJECT: + ret = njs_primitive_value_to_string(vm, &name, property); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "failed conversion of type \"%s\" " + "to string while property initialization", + njs_type_string(property->type)); + return NXT_ERROR; + } + + njs_string_get(&name, &lhq.key); + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.proto = &njs_object_hash_proto; + lhq.pool = vm->mem_pool; + + obj = object->data.u.object; + + ret = nxt_lvlhsh_find(&obj->__proto__->shared_hash, &lhq); + if (ret == NXT_OK) { + prop = lhq.value; + + if (prop->type == NJS_PROPERTY_HANDLER) { + ret = prop->value.data.u.prop_handler(vm, object, init, + &vm->retval); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + break; + } + } + + prop = njs_object_prop_alloc(vm, &name, init, 1); + if (nxt_slow_path(prop == NULL)) { + return NXT_ERROR; + } + + lhq.value = prop; + lhq.replace = 1; + + ret = nxt_lvlhsh_insert(&obj->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert/replace failed"); + return NXT_ERROR; + } + + break; + + default: + njs_internal_error(vm, "unexpected object type \"%s\" " + "while property initialization", + njs_type_string(object->type)); + + return NXT_ERROR; + } + + return sizeof(njs_vmcode_prop_set_t); +} + + +njs_ret_t njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object, njs_value_t *property) { njs_ret_t ret; njs_value_t *value; - njs_object_prop_t *prop; + njs_object_prop_t *prop, *shared; njs_property_query_t pq; njs_vmcode_prop_set_t *code; @@ -563,6 +673,8 @@ njs_vmcode_property_set(njs_vm_t *vm, nj code = (njs_vmcode_prop_set_t *) vm->current; value = njs_vmcode_operand(vm, code->value); + shared = NULL; + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0); ret = njs_property_query(vm, &pq, object, property); @@ -572,70 +684,62 @@ njs_vmcode_property_set(njs_vm_t *vm, nj case NXT_OK: prop = pq.lhq.value; - switch (prop->type) { - case NJS_PROPERTY: - break; - - case NJS_PROPERTY_REF: - *prop->value.data.u.value = *value; + if (nxt_slow_path(!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; + } + + if (prop->type == NJS_PROPERTY_HANDLER) { + ret = prop->value.data.u.prop_handler(vm, object, value, + &vm->retval); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + return sizeof(njs_vmcode_prop_set_t); - - case NJS_PROPERTY_HANDLER: - if (prop->writable) { - ret = prop->value.data.u.prop_handler(vm, object, value, - &vm->retval); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; + } + + if (pq.own) { + switch (prop->type) { + case NJS_PROPERTY: + case NJS_METHOD: + if (nxt_slow_path(pq.shared)) { + shared = prop; + break; } + goto found; + + case NJS_PROPERTY_REF: + *prop->value.data.u.value = *value; return sizeof(njs_vmcode_prop_set_t); + + default: + njs_internal_error(vm, "unexpected property type \"%s\" " + "while setting", + njs_prop_type_string(prop->type)); + + return NXT_ERROR; } break; - - default: - njs_internal_error(vm, "unexpected property type \"%s\" " - "while setting", - njs_prop_type_string(prop->type)); - - return NXT_ERROR; } - break; + /* Fall through. */ case NXT_DECLINED: - if (nxt_slow_path(!object->data.u.object->extensible)) { - njs_type_error(vm, "Cannot add property \"%V\", " - "object is not extensible", &pq.lhq.key); - return NXT_ERROR; - } - - if (nxt_slow_path(pq.lhq.value != NULL)) { - prop = pq.lhq.value; - - if (nxt_slow_path(prop->type == NJS_WHITEOUT)) { - /* Previously deleted property. */ - prop->type = NJS_PROPERTY; - prop->enumerable = 1; - prop->configurable = 1; - prop->writable = 1; - break; - } - } - - prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_undefined, 1); - if (nxt_slow_path(prop == NULL)) { - return NXT_ERROR; - } - - pq.lhq.replace = 0; - pq.lhq.value = prop; - 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; + if (nxt_slow_path(pq.own_whiteout != NULL)) { + /* Previously deleted property. */ + prop = pq.own_whiteout; + + prop->type = NJS_PROPERTY; + prop->enumerable = 1; + prop->configurable = 1; + prop->writable = 1; + + goto found; } break; @@ -647,12 +751,34 @@ njs_vmcode_property_set(njs_vm_t *vm, nj return ret; } - if (nxt_slow_path(!prop->writable)) { - njs_type_error(vm, "Cannot assign to read-only property \"%V\" of %s", - &pq.lhq.key, njs_type_string(object->type)); + if (nxt_slow_path(!object->data.u.object->extensible)) { + njs_type_error(vm, "Cannot add property \"%V\", " + "object is not extensible", &pq.lhq.key); + return NXT_ERROR; + } + + prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_undefined, 1); + if (nxt_slow_path(prop == NULL)) { return NXT_ERROR; } + if (nxt_slow_path(shared != NULL)) { + prop->enumerable = shared->enumerable; + prop->configurable = shared->configurable; + } + + pq.lhq.replace = 0; + pq.lhq.value = prop; + pq.lhq.pool = vm->mem_pool; + + 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; + } + +found: + prop->value = *value; return sizeof(njs_vmcode_prop_set_t); diff -r 88c5787352b2 -r ff591ba3e780 njs/njs_vm.h --- a/njs/njs_vm.h Wed May 22 21:01:39 2019 +0300 +++ b/njs/njs_vm.h Thu May 23 15:05:50 2019 +0300 @@ -1194,6 +1194,8 @@ njs_ret_t njs_vmcode_object_copy(njs_vm_ njs_ret_t njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object, njs_value_t *property); +njs_ret_t njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *object, + njs_value_t *property); njs_ret_t njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object, njs_value_t *property); njs_ret_t njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *property, diff -r 88c5787352b2 -r ff591ba3e780 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed May 22 21:01:39 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 23 15:05:50 2019 +0300 @@ -3408,6 +3408,10 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.create(['?','?'])[false]"), nxt_string("undefined") }, + { nxt_string("var a = ['abc']; var o = Object.create(a); o[0] = 32;" + "[a,o[0]]"), + nxt_string("abc,32") }, + /* Array.length setter */ { nxt_string("[].length = {}"), @@ -3481,6 +3485,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("var a = []; a.concat([])"), nxt_string("") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("var s = { toString: function() { return 'S' } };" "var v = { toString: 8, valueOf: function() { return 'V' } };" "var o = [9]; o.join = function() { return 'O' };" @@ -3495,7 +3500,6 @@ static njs_unit_test_t njs_test[] = /* Array.toString(). */ -# if 0 { nxt_string("var a = [1,2,3]; a.join = 'NO';" "Object.prototype.toString = function () { return 'A' }; a"), nxt_string("[object Array]") }, @@ -6162,9 +6166,11 @@ static njs_unit_test_t njs_test[] = "(function(){(function(){(function(){})})})})})})})"), nxt_string("SyntaxError: The maximum function nesting level is \"5\" in 1") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("Function.prototype.toString = function () {return 'X'};" "eval"), nxt_string("X") }, +#endif { nxt_string("var o = {f:function(x){ return x**2}}; o.f\n(2)"), nxt_string("4") }, @@ -7128,6 +7134,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var f = (a,b) => 0; f.length"), nxt_string("2") }, + { nxt_string("var o = Object.create(f => 1); o.length = 3"), + nxt_string("TypeError: Cannot assign to read-only property \"length\" of object") }, + /* Scopes. */ { nxt_string("function f(x) { a = x } var a; f(5); a"), @@ -7420,6 +7429,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("Error('e')"), nxt_string("Error: e") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("var e = Error('e'); e.name = 'E'; e"), nxt_string("E: e") }, @@ -7431,6 +7441,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("var e = Error(); e.name = ''; e.message = 'e'; e"), nxt_string("e") }, +#endif { nxt_string("Error('e').name + ': ' + Error('e').message"), nxt_string("Error: e") }, @@ -7504,6 +7515,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("URIError('e').name + ': ' + URIError('e').message"), nxt_string("URIError: e") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("var e = EvalError('e'); e.name = 'E'; e"), nxt_string("E: e") }, @@ -7529,6 +7541,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("var e = MemoryError('e'); e.name = 'E'"), nxt_string("TypeError: Cannot add property \"name\", object is not extensible") }, +#endif { nxt_string("EvalError.prototype.name"), nxt_string("EvalError") }, @@ -8279,17 +8292,6 @@ static njs_unit_test_t njs_test[] = "var a = []; for(var p in x) a.push(p); a"), nxt_string("a,b,0,1,2") }, -#if 0 - /* TODO: No properties implementation for array type - * (enumerable, writable, configurable). - */ - - { nxt_string("var o = Object("abc"); var x = Object.create(o);" - "x['sd'] = 44; x[1] = 8; x[55] = 8;" - "Object.keys(x)"), - nxt_string("55,sd") }, -#endif - { nxt_string("Object.prototype.toString.call(Object.prototype)"), nxt_string("[object Object]") }, @@ -8405,11 +8407,21 @@ static njs_unit_test_t njs_test[] = { nxt_string("Array.prototype.length"), nxt_string("0") }, + { nxt_string("Array.prototype.length = 3, Array.prototype"), + nxt_string(",,") }, + + { nxt_string("var o = Object.create(Array.prototype);" + "Object.defineProperty(o, 'length', {value: 3});" + "[Array.prototype, Array.prototype.length, o.length]"), + nxt_string(",0,3") }, + { nxt_string("Array.constructor === Function"), nxt_string("true") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("var a = []; a.join = 'OK'; a"), nxt_string("[object Array]") }, +#endif { nxt_string("[].__proto__ === Array.prototype"), nxt_string("true") }, @@ -8751,6 +8763,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var s = new String('??'); s[1] = 'b'"), nxt_string("TypeError: Cannot assign to read-only property \"1\" of object string") }, + { nxt_string("var o = Object.create(new String('??')); o[1] = 'a'"), + nxt_string("TypeError: Cannot assign to read-only property \"1\" of object") }, + { nxt_string("var s = new String('??'); s[4] = 'ab'; s[4]"), nxt_string("ab") }, @@ -8828,6 +8843,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("'test'.constructor.prototype === String.prototype"), nxt_string("true") }, + { nxt_string("var o = Object.create(String.prototype); o.length = 1"), + nxt_string("TypeError: Cannot assign to read-only property \"length\" of object") }, + { nxt_string("Function.name"), nxt_string("Function") }, @@ -9127,6 +9145,30 @@ static njs_unit_test_t njs_test[] = "o.a = 1; o.a"), nxt_string("1") }, + { nxt_string("Object.defineProperty(Object.prototype, 'a', {writable:false});" + "var o = {a: 1}; [o.a++, o.a]"), + nxt_string("1,2") }, + + { nxt_string("var o = {};" + "Object.defineProperty(Object.prototype, 'a', {writable:false});" + "o.a = 1"), + nxt_string("TypeError: Cannot assign to read-only property \"a\" of object") }, + + { nxt_string("var o = {};" + "Object.defineProperty(Object.prototype, 'a', {writable:true});" + "o.a = 1; o.a"), + nxt_string("1") }, + + { nxt_string("var p = Object.create(Function);" + "Object.defineProperty(p, 'length', {writable: true});" + "p.length = 32; p.length"), + nxt_string("32") }, + + { nxt_string("var p = Object.create(Math.abs);" + "Object.defineProperty(p, 'length', {writable: true});" + "p.length = 23; p.length"), + nxt_string("23") }, + { nxt_string("var o = {};" "Object.defineProperty(o, 'a', {value:1}); delete o.a"), nxt_string("TypeError: Cannot delete property \"a\" of object") }, @@ -9418,6 +9460,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.create(Math).hasOwnProperty('abs')"), nxt_string("false") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("var m = Object.create(Math); m.abs = 3;" "[m.hasOwnProperty('abs'), m.abs]"), nxt_string("true,3") }, @@ -9425,6 +9468,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("var m = Object.create(Math); m.abs = Math.floor;" "[m.hasOwnProperty('abs'), delete m.abs, m.abs(-1)]"), nxt_string("true,true,1") }, +#endif { nxt_string("Object.getOwnPropertyDescriptor({a:1}, 'a').value"), nxt_string("1") }, @@ -11840,8 +11884,10 @@ static njs_unit_test_t njs_test[] = { nxt_string("JSON.stringify(URIError('e'))"), nxt_string("{}") }, +#if 0 /* Most built-in methods and properties must be writable. */ { nxt_string("var e = URIError('e'); e.name = 'E'; JSON.stringify(e)"), nxt_string("{\"name\":\"E\"}") }, +#endif { nxt_string("var e = URIError('e'); e.message = 'E'; JSON.stringify(e)"), nxt_string("{}") }, From vbart at nginx.com Thu May 23 12:54:47 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 23 May 2019 12:54:47 +0000 Subject: [njs] Made writable most of built-in properties and methods. Message-ID: details: https://hg.nginx.org/njs/rev/f7eedb8257eb branches: changeset: 980:f7eedb8257eb user: Valentin Bartenev date: Thu May 23 15:05:51 2019 +0300 description: Made writable most of built-in properties and methods. diffstat: njs/njs_array.c | 29 ++++++++++++++++++++++++++++- njs/njs_boolean.c | 4 ++++ njs/njs_crypto.c | 8 ++++++++ njs/njs_date.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ njs/njs_error.c | 19 +++++++++++++++++++ njs/njs_fs.c | 6 ++++++ njs/njs_function.c | 4 ++++ njs/njs_json.c | 2 ++ njs/njs_math.c | 36 ++++++++++++++++++++++++++++++++++++ njs/njs_number.c | 10 ++++++++++ njs/njs_object.c | 22 ++++++++++++++++++++++ njs/njs_regexp.c | 4 ++++ njs/njs_string.c | 32 ++++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 46 ++++++++++++++++++++++++++++++++-------------- 14 files changed, 255 insertions(+), 15 deletions(-) diffs (truncated from 1970 to 1000 lines): diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_array.c --- a/njs/njs_array.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_array.c Thu May 23 15:05:51 2019 +0300 @@ -397,6 +397,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("isArray"), .value = njs_native_function(njs_array_is_array, 0, 0), + .writable = 1, .configurable = 1, }, @@ -406,6 +407,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("of"), .value = njs_native_function(njs_array_of, 0, 0), + .writable = 1, .configurable = 1, }, }; @@ -2252,13 +2254,14 @@ static const njs_object_prop_t njs_arra .type = NJS_PROPERTY_HANDLER, .name = njs_string("length"), .value = njs_prop_handler(njs_array_length), - .writable = 1 + .writable = 1, }, { .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, @@ -2268,6 +2271,7 @@ static const njs_object_prop_t njs_arra .value = njs_native_function(njs_array_prototype_slice, njs_continuation_size(njs_array_slice_t), NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .writable = 1, .configurable = 1, }, @@ -2275,6 +2279,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("push"), .value = njs_native_function(njs_array_prototype_push, 0, 0), + .writable = 1, .configurable = 1, }, @@ -2282,6 +2287,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("pop"), .value = njs_native_function(njs_array_prototype_pop, 0, 0), + .writable = 1, .configurable = 1, }, @@ -2289,6 +2295,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("unshift"), .value = njs_native_function(njs_array_prototype_unshift, 0, 0), + .writable = 1, .configurable = 1, }, @@ -2296,6 +2303,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("shift"), .value = njs_native_function(njs_array_prototype_shift, 0, 0), + .writable = 1, .configurable = 1, }, @@ -2304,6 +2312,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("splice"), .value = njs_native_function(njs_array_prototype_splice, 0, NJS_OBJECT_ARG, NJS_INTEGER_ARG, NJS_INTEGER_ARG), + .writable = 1, .configurable = 1, }, @@ -2312,6 +2321,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("reverse"), .value = njs_native_function(njs_array_prototype_reverse, 0, NJS_OBJECT_ARG), + .writable = 1, .configurable = 1, }, @@ -2320,6 +2330,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("toString"), .value = njs_native_function(njs_array_prototype_to_string, NJS_CONTINUATION_SIZE, 0), + .writable = 1, .configurable = 1, }, @@ -2329,6 +2340,7 @@ static const njs_object_prop_t njs_arra .value = njs_native_function(njs_array_prototype_join, njs_continuation_size(njs_array_join_t), NJS_OBJECT_ARG, NJS_STRING_ARG), + .writable = 1, .configurable = 1, }, @@ -2336,6 +2348,7 @@ static const njs_object_prop_t njs_arra .type = NJS_METHOD, .name = njs_string("concat"), .value = njs_native_function(njs_array_prototype_concat, 0, 0), + .writable = 1, .configurable = 1, }, @@ -2344,6 +2357,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("indexOf"), .value = njs_native_function(njs_array_prototype_index_of, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .writable = 1, .configurable = 1, }, @@ -2352,6 +2366,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("lastIndexOf"), .value = njs_native_function(njs_array_prototype_last_index_of, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .writable = 1, .configurable = 1, }, @@ -2361,6 +2376,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("includes"), .value = njs_native_function(njs_array_prototype_includes, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_INTEGER_ARG), + .writable = 1, .configurable = 1, }, @@ -2369,6 +2385,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("forEach"), .value = njs_native_function(njs_array_prototype_for_each, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2377,6 +2394,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("some"), .value = njs_native_function(njs_array_prototype_some, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2385,6 +2403,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("every"), .value = njs_native_function(njs_array_prototype_every, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2395,6 +2414,7 @@ static const njs_object_prop_t njs_arra .value = njs_native_function(njs_array_prototype_fill, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2403,6 +2423,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("filter"), .value = njs_native_function(njs_array_prototype_filter, njs_continuation_size(njs_array_filter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2412,6 +2433,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("find"), .value = njs_native_function(njs_array_prototype_find, njs_continuation_size(njs_array_find_t), 0), + .writable = 1, .configurable = 1, }, @@ -2421,6 +2443,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("findIndex"), .value = njs_native_function(njs_array_prototype_find_index, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2429,6 +2452,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("map"), .value = njs_native_function(njs_array_prototype_map, njs_continuation_size(njs_array_map_t), 0), + .writable = 1, .configurable = 1, }, @@ -2437,6 +2461,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("reduce"), .value = njs_native_function(njs_array_prototype_reduce, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2445,6 +2470,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("reduceRight"), .value = njs_native_function(njs_array_prototype_reduce_right, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, @@ -2453,6 +2479,7 @@ static const njs_object_prop_t njs_arra .name = njs_string("sort"), .value = njs_native_function(njs_array_prototype_sort, njs_continuation_size(njs_array_iter_t), 0), + .writable = 1, .configurable = 1, }, }; diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_boolean.c --- a/njs/njs_boolean.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_boolean.c Thu May 23 15:05:51 2019 +0300 @@ -131,6 +131,7 @@ static const njs_object_prop_t njs_bool .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), .value = njs_prop_handler(njs_primitive_prototype_get_proto), + .writable = 1, .configurable = 1, }, @@ -138,6 +139,7 @@ static const njs_object_prop_t njs_bool .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, @@ -145,6 +147,7 @@ static const njs_object_prop_t njs_bool .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_boolean_prototype_value_of, 0, 0), + .writable = 1, .configurable = 1, }, @@ -152,6 +155,7 @@ static const njs_object_prop_t njs_bool .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_boolean_prototype_to_string, 0, 0), + .writable = 1, .configurable = 1, }, }; diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_crypto.c --- a/njs/njs_crypto.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_crypto.c Thu May 23 15:05:51 2019 +0300 @@ -338,6 +338,7 @@ static const njs_object_prop_t njs_hash .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_hash_prototype_to_string, 0, 0), + .writable = 1, .configurable = 1, }, @@ -346,6 +347,7 @@ static const njs_object_prop_t njs_hash .name = njs_string("update"), .value = njs_native_function(njs_hash_prototype_update, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, @@ -354,6 +356,7 @@ static const njs_object_prop_t njs_hash .name = njs_string("digest"), .value = njs_native_function(njs_hash_prototype_digest, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, }; @@ -606,6 +609,7 @@ static const njs_object_prop_t njs_hmac .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_hmac_prototype_to_string, 0, 0), + .writable = 1, .configurable = 1, }, @@ -614,6 +618,7 @@ static const njs_object_prop_t njs_hmac .name = njs_string("update"), .value = njs_native_function(njs_hmac_prototype_update, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, @@ -622,6 +627,7 @@ static const njs_object_prop_t njs_hmac .name = njs_string("digest"), .value = njs_native_function(njs_hmac_prototype_digest, 0, NJS_OBJECT_ARG, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, }; @@ -669,6 +675,7 @@ static const njs_object_prop_t njs_cryp .name = njs_string("createHash"), .value = njs_native_function(njs_crypto_create_hash, 0, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, @@ -677,6 +684,7 @@ static const njs_object_prop_t njs_cryp .name = njs_string("createHmac"), .value = njs_native_function(njs_crypto_create_hmac, 0, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_date.c --- a/njs/njs_date.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_date.c Thu May 23 15:05:51 2019 +0300 @@ -918,6 +918,7 @@ static const njs_object_prop_t njs_date .type = NJS_METHOD, .name = njs_string("UTC"), .value = njs_native_function(njs_date_utc, 0, 0), + .writable = 1, .configurable = 1, }, @@ -925,6 +926,7 @@ static const njs_object_prop_t njs_date .type = NJS_METHOD, .name = njs_string("now"), .value = njs_native_function(njs_date_now, 0, 0), + .writable = 1, .configurable = 1, }, @@ -933,6 +935,7 @@ static const njs_object_prop_t njs_date .name = njs_string("parse"), .value = njs_native_function(njs_date_parse, 0, NJS_SKIP_ARG, NJS_STRING_ARG), + .writable = 1, .configurable = 1, }, }; @@ -1944,6 +1947,7 @@ static const njs_object_prop_t njs_date .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), .value = njs_prop_handler(njs_primitive_prototype_get_proto), + .writable = 1, .configurable = 1, }, @@ -1951,6 +1955,7 @@ static const njs_object_prop_t njs_date .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, @@ -1959,6 +1964,7 @@ static const njs_object_prop_t njs_date .name = njs_string("valueOf"), .value = njs_native_function(njs_date_prototype_value_of, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -1967,6 +1973,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toString"), .value = njs_native_function(njs_date_prototype_to_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -1975,6 +1982,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toDateString"), .value = njs_native_function(njs_date_prototype_to_date_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -1983,6 +1991,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toTimeString"), .value = njs_native_function(njs_date_prototype_to_time_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -1991,6 +2000,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toLocaleString"), .value = njs_native_function(njs_date_prototype_to_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -1999,6 +2009,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("toLocaleDateString"), .value = njs_native_function(njs_date_prototype_to_date_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2007,6 +2018,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("toLocaleTimeString"), .value = njs_native_function(njs_date_prototype_to_time_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2015,6 +2027,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toUTCString"), .value = njs_native_function(njs_date_prototype_to_utc_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2023,6 +2036,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toISOString"), .value = njs_native_function(njs_date_prototype_to_iso_string, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2031,6 +2045,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getTime"), .value = njs_native_function(njs_date_prototype_value_of, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2039,6 +2054,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getFullYear"), .value = njs_native_function(njs_date_prototype_get_full_year, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2047,6 +2063,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCFullYear"), .value = njs_native_function(njs_date_prototype_get_utc_full_year, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2055,6 +2072,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getMonth"), .value = njs_native_function(njs_date_prototype_get_month, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2063,6 +2081,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCMonth"), .value = njs_native_function(njs_date_prototype_get_utc_month, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2071,6 +2090,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getDate"), .value = njs_native_function(njs_date_prototype_get_date, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2079,6 +2099,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCDate"), .value = njs_native_function(njs_date_prototype_get_utc_date, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2087,6 +2108,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getDay"), .value = njs_native_function(njs_date_prototype_get_day, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2095,6 +2117,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCDay"), .value = njs_native_function(njs_date_prototype_get_utc_day, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2103,6 +2126,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getHours"), .value = njs_native_function(njs_date_prototype_get_hours, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2111,6 +2135,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCHours"), .value = njs_native_function(njs_date_prototype_get_utc_hours, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2119,6 +2144,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getMinutes"), .value = njs_native_function(njs_date_prototype_get_minutes, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2127,6 +2153,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCMinutes"), .value = njs_native_function(njs_date_prototype_get_utc_minutes, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2135,6 +2162,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getSeconds"), .value = njs_native_function(njs_date_prototype_get_seconds, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2143,6 +2171,7 @@ static const njs_object_prop_t njs_date .name = njs_string("getUTCSeconds"), .value = njs_native_function(njs_date_prototype_get_seconds, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2151,6 +2180,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("getMilliseconds"), .value = njs_native_function(njs_date_prototype_get_milliseconds, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2159,6 +2189,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("getUTCMilliseconds"), .value = njs_native_function(njs_date_prototype_get_milliseconds, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2167,6 +2198,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("getTimezoneOffset"), .value = njs_native_function(njs_date_prototype_get_timezone_offset, 0, NJS_DATE_ARG), + .writable = 1, .configurable = 1, }, @@ -2175,6 +2207,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setTime"), .value = njs_native_function(njs_date_prototype_set_time, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2183,6 +2216,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("setMilliseconds"), .value = njs_native_function(njs_date_prototype_set_milliseconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2191,6 +2225,7 @@ static const njs_object_prop_t njs_date .name = njs_long_string("setUTCMilliseconds"), .value = njs_native_function(njs_date_prototype_set_milliseconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2199,6 +2234,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setSeconds"), .value = njs_native_function(njs_date_prototype_set_seconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2207,6 +2243,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setUTCSeconds"), .value = njs_native_function(njs_date_prototype_set_seconds, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2216,6 +2253,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_minutes, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2225,6 +2263,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_utc_minutes, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2234,6 +2273,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_hours, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2243,6 +2283,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_utc_hours, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2251,6 +2292,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setDate"), .value = njs_native_function(njs_date_prototype_set_date, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2259,6 +2301,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setUTCDate"), .value = njs_native_function(njs_date_prototype_set_utc_date, 0, NJS_DATE_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2267,6 +2310,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setMonth"), .value = njs_native_function(njs_date_prototype_set_month, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2275,6 +2319,7 @@ static const njs_object_prop_t njs_date .name = njs_string("setUTCMonth"), .value = njs_native_function(njs_date_prototype_set_utc_month, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2284,6 +2329,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_full_year, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2293,6 +2339,7 @@ static const njs_object_prop_t njs_date .value = njs_native_function(njs_date_prototype_set_utc_full_year, 0, NJS_DATE_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -2301,6 +2348,7 @@ static const njs_object_prop_t njs_date .name = njs_string("toJSON"), .value = njs_native_function(njs_date_prototype_to_json, NJS_CONTINUATION_SIZE, 0), + .writable = 1, .configurable = 1, }, }; diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_error.c --- a/njs/njs_error.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_error.c Thu May 23 15:05:51 2019 +0300 @@ -695,6 +695,7 @@ static const njs_object_prop_t njs_erro .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("Error"), + .writable = 1, .configurable = 1, }, @@ -702,6 +703,7 @@ static const njs_object_prop_t njs_erro .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, @@ -709,6 +711,7 @@ static const njs_object_prop_t njs_erro .type = NJS_PROPERTY, .name = njs_string("message"), .value = njs_string(""), + .writable = 1, .configurable = 1, }, @@ -716,6 +719,7 @@ static const njs_object_prop_t njs_erro .type = NJS_METHOD, .name = njs_string("valueOf"), .value = njs_native_function(njs_error_prototype_value_of, 0, 0), + .writable = 1, .configurable = 1, }, @@ -723,6 +727,7 @@ static const njs_object_prop_t njs_erro .type = NJS_METHOD, .name = njs_string("toString"), .value = njs_native_function(njs_error_prototype_to_string, 0, 0), + .writable = 1, .configurable = 1, }, }; @@ -741,6 +746,7 @@ static const njs_object_prop_t njs_eval .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("EvalError"), + .writable = 1, .configurable = 1, }, @@ -748,6 +754,7 @@ static const njs_object_prop_t njs_eval .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, }; @@ -786,6 +793,7 @@ static const njs_object_prop_t njs_inte .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("InternalError"), + .writable = 1, .configurable = 1, }, @@ -794,6 +802,7 @@ static const njs_object_prop_t njs_inte .name = njs_string("toString"), .value = njs_native_function(njs_internal_error_prototype_to_string, 0, 0), + .writable = 1, .configurable = 1, }, }; @@ -812,6 +821,7 @@ static const njs_object_prop_t njs_rang .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("RangeError"), + .writable = 1, .configurable = 1, }, @@ -819,6 +829,7 @@ static const njs_object_prop_t njs_rang .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, }; @@ -837,6 +848,7 @@ static const njs_object_prop_t njs_refe .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("ReferenceError"), + .writable = 1, .configurable = 1, }, @@ -844,6 +856,7 @@ static const njs_object_prop_t njs_refe .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, }; @@ -862,6 +875,7 @@ static const njs_object_prop_t njs_synt .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("SyntaxError"), + .writable = 1, .configurable = 1, }, @@ -869,6 +883,7 @@ static const njs_object_prop_t njs_synt .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, }; @@ -887,6 +902,7 @@ static const njs_object_prop_t njs_type .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("TypeError"), + .writable = 1, .configurable = 1, }, @@ -894,6 +910,7 @@ static const njs_object_prop_t njs_type .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, }; @@ -912,6 +929,7 @@ static const njs_object_prop_t njs_uri_ .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, @@ -919,6 +937,7 @@ static const njs_object_prop_t njs_uri_ .type = NJS_PROPERTY, .name = njs_string("name"), .value = njs_string("URIError"), + .writable = 1, .configurable = 1, }, }; diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_fs.c --- a/njs/njs_fs.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_fs.c Thu May 23 15:05:51 2019 +0300 @@ -1042,6 +1042,7 @@ static const njs_object_prop_t njs_fs_o .name = njs_string("readFile"), .value = njs_native_function(njs_fs_read_file, njs_continuation_size(njs_fs_cont_t), 0), + .writable = 1, .configurable = 1, }, @@ -1049,6 +1050,7 @@ static const njs_object_prop_t njs_fs_o .type = NJS_METHOD, .name = njs_string("readFileSync"), .value = njs_native_function(njs_fs_read_file_sync, 0, 0), + .writable = 1, .configurable = 1, }, @@ -1057,6 +1059,7 @@ static const njs_object_prop_t njs_fs_o .name = njs_string("appendFile"), .value = njs_native_function(njs_fs_append_file, njs_continuation_size(njs_fs_cont_t), 0), + .writable = 1, .configurable = 1, }, @@ -1065,6 +1068,7 @@ static const njs_object_prop_t njs_fs_o .name = njs_string("appendFileSync"), .value = njs_native_function(njs_fs_append_file_sync, njs_continuation_size(njs_fs_cont_t), 0), + .writable = 1, .configurable = 1, }, @@ -1073,6 +1077,7 @@ static const njs_object_prop_t njs_fs_o .name = njs_string("writeFile"), .value = njs_native_function(njs_fs_write_file, njs_continuation_size(njs_fs_cont_t), 0), + .writable = 1, .configurable = 1, }, @@ -1081,6 +1086,7 @@ static const njs_object_prop_t njs_fs_o .name = njs_string("writeFileSync"), .value = njs_native_function(njs_fs_write_file_sync, njs_continuation_size(njs_fs_cont_t), 0), + .writable = 1, .configurable = 1, }, diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_function.c --- a/njs/njs_function.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_function.c Thu May 23 15:05:51 2019 +0300 @@ -1193,6 +1193,7 @@ static const njs_object_prop_t njs_func .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), .value = njs_prop_handler(njs_object_prototype_create_constructor), + .writable = 1, .configurable = 1, }, @@ -1200,6 +1201,7 @@ static const njs_object_prop_t njs_func .type = NJS_METHOD, .name = njs_string("call"), .value = njs_native_function(njs_function_prototype_call, 0, 0), + .writable = 1, .configurable = 1, }, @@ -1207,6 +1209,7 @@ static const njs_object_prop_t njs_func .type = NJS_METHOD, .name = njs_string("apply"), .value = njs_native_function(njs_function_prototype_apply, 0, 0), + .writable = 1, .configurable = 1, }, @@ -1214,6 +1217,7 @@ static const njs_object_prop_t njs_func .type = NJS_METHOD, .name = njs_string("bind"), .value = njs_native_function(njs_function_prototype_bind, 0, 0), + .writable = 1, .configurable = 1, }, }; diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_json.c --- a/njs/njs_json.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_json.c Thu May 23 15:05:51 2019 +0300 @@ -2077,6 +2077,7 @@ static const njs_object_prop_t njs_json njs_continuation_size(njs_json_parse_t), NJS_SKIP_ARG, NJS_STRING_ARG, NJS_OBJECT_ARG), + .writable = 1, .configurable = 1, }, @@ -2088,6 +2089,7 @@ static const njs_object_prop_t njs_json njs_continuation_size(njs_json_stringify_t), NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_SKIP_ARG, NJS_SKIP_ARG), + .writable = 1, .configurable = 1, }, }; diff -r ff591ba3e780 -r f7eedb8257eb njs/njs_math.c --- a/njs/njs_math.c Thu May 23 15:05:50 2019 +0300 +++ b/njs/njs_math.c Thu May 23 15:05:51 2019 +0300 @@ -820,6 +820,7 @@ static const njs_object_prop_t njs_math .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), .value = njs_prop_handler(njs_object_prototype_proto), + .writable = 1, .configurable = 1, }, @@ -828,6 +829,7 @@ static const njs_object_prop_t njs_math .name = njs_string("abs"), .value = njs_native_function(njs_object_math_abs, 0, NJS_SKIP_ARG, NJS_NUMBER_ARG), + .writable = 1, .configurable = 1, }, @@ -836,6 +838,7 @@ static const njs_object_prop_t njs_math .name = njs_string("acos"), .value = njs_native_function(njs_object_math_acos, 0, NJS_SKIP_ARG, NJS_NUMBER_ARG), + .writable = 1, From vbart at nginx.com Thu May 23 12:54:48 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 23 May 2019 12:54:48 +0000 Subject: [njs] Fixed array length property handler. Message-ID: details: https://hg.nginx.org/njs/rev/fd0918b6dd56 branches: changeset: 981:fd0918b6dd56 user: Valentin Bartenev date: Thu May 23 15:05:51 2019 +0300 description: Fixed array length property handler. Previously it might change the length of prototype arrays. diffstat: njs/njs_array.c | 86 ++++++++++++++++++++++++++--------------------- njs/njs_vm.c | 12 +++++- njs/njs_vm.h | 5 ++ njs/test/njs_unit_test.c | 4 ++ 4 files changed, 65 insertions(+), 42 deletions(-) diffs (161 lines): diff -r f7eedb8257eb -r fd0918b6dd56 njs/njs_array.c --- a/njs/njs_array.c Thu May 23 15:05:51 2019 +0300 +++ b/njs/njs_array.c Thu May 23 15:05:51 2019 +0300 @@ -434,57 +434,65 @@ njs_array_length(njs_vm_t *vm, njs_value proto = value->data.u.object; - do { - if (nxt_fast_path(proto->type == NJS_ARRAY)) { - break; + if (setval == NULL) { + do { + if (nxt_fast_path(proto->type == NJS_ARRAY)) { + break; + } + + proto = proto->__proto__; + } while (proto != NULL); + + if (nxt_slow_path(proto == NULL)) { + njs_internal_error(vm, "no array in proto chain"); + return NJS_ERROR; } - proto = proto->__proto__; - } while (proto != NULL); - - if (nxt_slow_path(proto == NULL)) { - njs_internal_error(vm, "no array in proto chain"); + array = (njs_array_t *) proto; + + njs_value_number_set(retval, array->length); + return NJS_OK; + } + + if (proto->type != NJS_ARRAY) { + return NJS_DECLINED; + } + + if (!njs_is_number(setval)) { + njs_range_error(vm, "Invalid array length"); + return NJS_ERROR; + } + + num = setval->data.u.number; + length = (uint32_t) num; + + if ((double) length != num) { + njs_range_error(vm, "Invalid array length"); return NJS_ERROR; } array = (njs_array_t *) proto; - if (setval != NULL) { - if (!njs_is_number(setval)) { - njs_range_error(vm, "Invalid array length"); - return NJS_ERROR; - } - - num = setval->data.u.number; - length = (uint32_t) num; - - if ((double) length != num) { - njs_range_error(vm, "Invalid array length"); + size = (int64_t) length - array->length; + + if (size > 0) { + ret = njs_array_expand(vm, array, 0, size); + if (nxt_slow_path(ret != NXT_OK)) { return NJS_ERROR; } - size = (int64_t) length - array->length; - - if (size > 0) { - ret = njs_array_expand(vm, array, 0, size); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_ERROR; - } - - val = &array->start[array->length]; - - do { - njs_set_invalid(val); - val++; - size--; - } while (size != 0); - } - - array->length = length; + val = &array->start[array->length]; + + do { + njs_set_invalid(val); + val++; + size--; + } while (size != 0); } - njs_value_number_set(retval, array->length); - + array->length = length; + + njs_value_number_set(retval, length); return NJS_OK; } diff -r f7eedb8257eb -r fd0918b6dd56 njs/njs_vm.c --- a/njs/njs_vm.c Thu May 23 15:05:51 2019 +0300 +++ b/njs/njs_vm.c Thu May 23 15:05:51 2019 +0300 @@ -694,11 +694,17 @@ njs_vmcode_property_set(njs_vm_t *vm, nj if (prop->type == NJS_PROPERTY_HANDLER) { ret = prop->value.data.u.prop_handler(vm, object, value, &vm->retval); - if (nxt_slow_path(ret != NXT_OK)) { + + switch (ret) { + case NXT_OK: + return sizeof(njs_vmcode_prop_set_t); + + case NXT_DECLINED: + break; + + default: return ret; } - - return sizeof(njs_vmcode_prop_set_t); } if (pq.own) { diff -r f7eedb8257eb -r fd0918b6dd56 njs/njs_vm.h --- a/njs/njs_vm.h Thu May 23 15:05:51 2019 +0300 +++ b/njs/njs_vm.h Thu May 23 15:05:51 2019 +0300 @@ -147,6 +147,11 @@ typedef struct njs_generator_s nj * njs_prop_handler_t operates as a property getter and/or setter. * The handler receives NULL setval if it is invoked in GET context and * non-null otherwise. + * + * njs_prop_handler_t is expected to return: + * NXT_OK - handler executed successfully; + * NXT_ERROR - some error, vm->retval contains appropriate exception; + * NXT_DECLINED - handler was applied to inappropriate object. */ typedef njs_ret_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); diff -r f7eedb8257eb -r fd0918b6dd56 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 23 15:05:51 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 23 15:05:51 2019 +0300 @@ -8405,6 +8405,10 @@ static njs_unit_test_t njs_test[] = { nxt_string("Array.prototype.length = 3, Array.prototype"), nxt_string(",,") }, + { nxt_string("var o = Object.create(Array.prototype); o.length = 3;" + "[Array.prototype, Array.prototype.length, o.length]"), + nxt_string(",0,3") }, + { nxt_string("var o = Object.create(Array.prototype);" "Object.defineProperty(o, 'length', {value: 3});" "[Array.prototype, Array.prototype.length, o.length]"), From vbart at nginx.com Thu May 23 12:54:48 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 23 May 2019 12:54:48 +0000 Subject: [njs] Fixed overwriting "constructor" property of built-in prototypes. Message-ID: details: https://hg.nginx.org/njs/rev/4296c5b56e30 branches: changeset: 982:4296c5b56e30 user: Valentin Bartenev date: Thu May 23 15:05:52 2019 +0300 description: Fixed overwriting "constructor" property of built-in prototypes. diffstat: njs/njs_object.c | 11 +++++++---- njs/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diffs (54 lines): diff -r fd0918b6dd56 -r 4296c5b56e30 njs/njs_object.c --- a/njs/njs_object.c Thu May 23 15:05:51 2019 +0300 +++ b/njs/njs_object.c Thu May 23 15:05:52 2019 +0300 @@ -2909,8 +2909,11 @@ njs_object_prototype_create_constructor( found: - cons = njs_property_constructor_create(vm, &prototype->object.hash, - &vm->scopes[NJS_SCOPE_GLOBAL][index]); + if (setval == NULL) { + setval = &vm->scopes[NJS_SCOPE_GLOBAL][index]; + } + + cons = njs_property_constructor_create(vm, &prototype->object.hash, setval); if (nxt_fast_path(cons != NULL)) { *retval = *cons; return NXT_OK; @@ -2943,7 +2946,7 @@ njs_property_constructor_create(njs_vm_t lhq.value = prop; lhq.key_hash = NJS_CONSTRUCTOR_HASH; lhq.key = nxt_string_value("constructor"); - lhq.replace = 0; + lhq.replace = 1; lhq.pool = vm->mem_pool; lhq.proto = &njs_object_hash_proto; @@ -2953,7 +2956,7 @@ njs_property_constructor_create(njs_vm_t return &prop->value; } - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "lvlhsh insert/replace failed"); return NULL; } diff -r fd0918b6dd56 -r 4296c5b56e30 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 23 15:05:51 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 23 15:05:52 2019 +0300 @@ -8480,6 +8480,15 @@ static njs_unit_test_t njs_test[] = { nxt_string("Boolean.prototype.constructor === Boolean"), nxt_string("true") }, + { nxt_string("Boolean.prototype.constructor = 1;" + "Boolean.prototype.constructor"), + nxt_string("1") }, + + { nxt_string("var c = Boolean.prototype.constructor;" + "Boolean.prototype.constructor = 1;" + "[c(0), Boolean.prototype.constructor]"), + nxt_string("false,1") }, + { nxt_string("Boolean.prototype.hasOwnProperty('constructor')"), nxt_string("true") }, From vbart at nginx.com Thu May 23 13:39:14 2019 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 23 May 2019 13:39:14 +0000 Subject: [njs] Added "name" property for built-in methods. Message-ID: details: https://hg.nginx.org/njs/rev/5906cf108796 branches: changeset: 983:5906cf108796 user: Valentin Bartenev date: Thu May 23 16:21:55 2019 +0300 description: Added "name" property for built-in methods. diffstat: njs/njs_object.c | 28 ++++++++++++++++++++++++++-- njs/test/njs_unit_test.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diffs (95 lines): diff -r 4296c5b56e30 -r 5906cf108796 njs/njs_object.c --- a/njs/njs_object.c Thu May 23 15:05:52 2019 +0300 +++ b/njs/njs_object.c Thu May 23 16:21:55 2019 +0300 @@ -710,8 +710,12 @@ 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_function_t *function; - njs_object_prop_t *prop, *shared; + 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)); @@ -735,6 +739,26 @@ njs_method_private_copy(njs_vm_t *vm, nj 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; + } + pq->lhq.replace = 0; pq->lhq.value = prop; pq->lhq.pool = vm->mem_pool; diff -r 4296c5b56e30 -r 5906cf108796 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 23 15:05:52 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 23 16:21:55 2019 +0300 @@ -9625,7 +9625,7 @@ static njs_unit_test_t njs_test[] = nxt_string("name,length,prototype,isArray,of") }, { nxt_string("Object.getOwnPropertyNames(Array.isArray)"), - nxt_string("length") }, + nxt_string("name,length") }, { nxt_string("Object.defineProperty(Object.freeze({}), 'b', {})"), nxt_string("TypeError: object is not extensible") }, @@ -12173,6 +12173,37 @@ static njs_unit_test_t njs_test[] = { nxt_string("njs.dump($r.header)"), nxt_string("{type:\"object\",props:[\"getter\",\"foreach\",\"next\"]}") }, + /* Built-in methods name. */ + + { nxt_string( + "var fail;" + "function isMethodsHaveName(o) {" + " var except = [" + " 'prototype'," + " 'constructor'," + " ];" + " return Object.getOwnPropertyNames(o)" + " .filter(v => !except.includes(v)" + " && typeof o[v] == 'function')" + " .every(v => o[v].name == v" + " || !(fail = `${o.name}.${v}: ${o[v].name}`));" + "}" + "[" + " Boolean, Boolean.prototype," + " Number, Number.prototype," + " String, String.prototype," + " Object, Object.prototype," + " Array, Array.prototype," + " Function, Function.prototype," + " RegExp, RegExp.prototype," + " Date, Date.prototype," + " Error, Error.prototype," + " Math," + " JSON," + "].every(obj => isMethodsHaveName(obj)) || fail"), + + nxt_string("true") }, + /* require(). */ { nxt_string("require('unknown_module')"), From arut at nginx.com Thu May 23 13:49:32 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 23 May 2019 16:49:32 +0300 Subject: Using round robin for load balancing if hash key is empty In-Reply-To: References: Message-ID: <20190523134932.GC91566@Romans-MacBook-Air.local> Hello Niklas, On Wed, May 22, 2019 at 09:59:46PM +0200, Niklas Keller wrote: > Hey, > > I'd like to propose falling back to round robin if the hash key is > empty. This allows using hashed cookie values for sticky sessions > while using round robin for all requests that do not carry any session > information and thus do not need the stickiness. While Nginx Plus > allows to use the learning mode, this patch avoids the need for > synchronization between multiple instances. > > Instead of falling back to round robin automatically, this could also > be changed to offer a configuration option, but I think it's a > sensible default. > > An additional configuration option could be added in the future to > change the fallback from round robin to another node selection > strategy. > > You can find the patch at the end of this email. > > Kind regards, > Niklas > > # HG changeset patch > # User Niklas Keller > # Date 1558554036 -7200 > # Wed May 22 21:40:36 2019 +0200 > # Node ID 34015c26b7fe9bda83390d25d989acb109c8d1ea > # Parent 234373adb2ce6023e69e527cbf2b60adf70b1130 > Use round-robin if hash key is empty > > diff -r 234373adb2ce -r 34015c26b7fe > src/http/modules/ngx_http_upstream_hash_module.c > --- a/src/http/modules/ngx_http_upstream_hash_module.c Tue May 21 > 17:23:57 2019 +0300 > +++ b/src/http/modules/ngx_http_upstream_hash_module.c Wed May 22 > 21:40:36 2019 +0200 > @@ -178,7 +178,7 @@ > > ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); > > - if (hp->tries > 20 || hp->rrp.peers->single) { > + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { > ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); > return hp->get_rr_peer(pc, &hp->rrp); > } The proposition sounds reasonable. As for the patch, it makes sense to add the same condition to the consistent hash balancer and also make similar changes in the stream module. Attached is a modified patch with those changes. I also slightly changed the commit log. Please confirm the patch looks good for you. -- Roman Arutyunyan -------------- next part -------------- # HG changeset patch # User Niklas Keller # Date 1558614458 -10800 # Thu May 23 15:27:38 2019 +0300 # Node ID 34dff919b948dd9652b24459e6a40c303058df09 # Parent 234373adb2ce6023e69e527cbf2b60adf70b1130 Upstream hash: fall back to round-robin if hash key is empty. diff --git a/src/http/modules/ngx_http_upstream_hash_module.c b/src/http/modules/ngx_http_upstream_hash_module.c --- a/src/http/modules/ngx_http_upstream_hash_module.c +++ b/src/http/modules/ngx_http_upstream_hash_module.c @@ -178,7 +178,7 @@ ngx_http_upstream_get_hash_peer(ngx_peer ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } @@ -509,7 +509,7 @@ ngx_http_upstream_get_chash_peer(ngx_pee ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c --- a/src/stream/ngx_stream_upstream_hash_module.c +++ b/src/stream/ngx_stream_upstream_hash_module.c @@ -178,7 +178,7 @@ ngx_stream_upstream_get_hash_peer(ngx_pe ngx_stream_upstream_rr_peers_rlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } @@ -511,7 +511,7 @@ ngx_stream_upstream_get_chash_peer(ngx_p ngx_stream_upstream_rr_peers_wlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } From vl at nginx.com Thu May 23 15:21:27 2019 From: vl at nginx.com (Vladimir Homutov) Date: Thu, 23 May 2019 18:21:27 +0300 Subject: Using round robin for load balancing if hash key is empty In-Reply-To: References: Message-ID: <20190523152127.GA30003@vlpc> On Wed, May 22, 2019 at 09:59:46PM +0200, Niklas Keller wrote: > Hey, > > I'd like to propose falling back to round robin if the hash key is > empty. This allows using hashed cookie values for sticky sessions > while using round robin for all requests that do not carry any session > information and thus do not need the stickiness. While Nginx Plus > allows to use the learning mode, this patch avoids the need for > synchronization between multiple instances. > Can you please elaborate on balancing/sticky scheme you are using? Say, first request without cookie is balanced by round-robin, arrives at some backend, which responds with cookie. Next time, the request with cookie is balanced by hash algorithm, and the result can be easily another backend. How do you deal with this? From me at kelunik.com Thu May 23 17:54:46 2019 From: me at kelunik.com (Niklas Keller) Date: Thu, 23 May 2019 19:54:46 +0200 Subject: Using round robin for load balancing if hash key is empty In-Reply-To: <20190523152127.GA30003@vlpc> References: <20190523152127.GA30003@vlpc> Message-ID: > > I'd like to propose falling back to round robin if the hash key is > > empty. This allows using hashed cookie values for sticky sessions > > while using round robin for all requests that do not carry any session > > information and thus do not need the stickiness. While Nginx Plus > > allows to use the learning mode, this patch avoids the need for > > synchronization between multiple instances. > > > > Can you please elaborate on balancing/sticky scheme you are using? > > Say, first request without cookie is balanced by round-robin, arrives > at some backend, which responds with cookie. > Next time, the request with cookie is balanced by hash algorithm, > and the result can be easily another backend. How do you deal with this? Very few requests depend on the stickiness in our application. The main use case is showing success messages once after a form is submitted. In these cases, the usual flow is: - GET /form ? Server assigns cookie - POST /form ? Client sends cookie, a different server might be selected, but doesn't matter - GET /form?_key=abc ? Client sends cookie again, success message is shown and removed from the session, same server as in the previous request is selected For cookie-less clients, e.g. crawlers and webhooks, the stickiness doesn't matter at all, so these shouldn't be sticky to avoid peaks on single backend nodes. @Roman: Patch looks good to me, thanks! Regards, Niklas From xeioex at nginx.com Fri May 24 15:59:49 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 24 May 2019 15:59:49 +0000 Subject: [njs] Fixed Array.prototype.toString() and Date.prototype.toJSON(). Message-ID: details: https://hg.nginx.org/njs/rev/ff51b3e9ea05 branches: changeset: 984:ff51b3e9ea05 user: hongzhidao date: Wed May 22 07:54:58 2019 +0800 description: Fixed Array.prototype.toString() and Date.prototype.toJSON(). This closes #163, #164, #166 issues on Github. diffstat: njs/njs_array.c | 28 ++-------------------------- njs/njs_date.c | 27 ++------------------------- njs/njs_function.h | 30 ++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 6 ++++++ 4 files changed, 40 insertions(+), 51 deletions(-) diffs (187 lines): diff -r 5906cf108796 -r ff51b3e9ea05 njs/njs_array.c --- a/njs/njs_array.c Thu May 23 16:21:55 2019 +0300 +++ b/njs/njs_array.c Wed May 22 07:54:58 2019 +0800 @@ -85,8 +85,6 @@ static njs_ret_t njs_array_prototype_sli njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_ret_t njs_array_prototype_slice_copy(njs_vm_t *vm, njs_value_t *this, int64_t start, int64_t length); -static njs_ret_t njs_array_prototype_to_string_continuation(njs_vm_t *vm, - njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); static njs_ret_t njs_array_prototype_join_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static njs_value_t *njs_array_copy(njs_value_t *dst, njs_value_t *src); @@ -935,24 +933,13 @@ njs_array_prototype_reverse(njs_vm_t *vm } -/* - * ECMAScript 5.1: try first to use object method "join", then - * use the standard built-in method Object.prototype.toString(). - * Array.toString() must be a continuation otherwise it may - * endlessly call Array.join(). - */ - static njs_ret_t njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t retval) { njs_object_prop_t *prop; - njs_continuation_t *cont; nxt_lvlhsh_query_t lhq; - cont = njs_vm_continuation(vm); - cont->function = njs_array_prototype_to_string_continuation; - if (njs_is_object(&args[0])) { lhq.key_hash = NJS_JOIN_HASH; lhq.key = nxt_string_value("join"); @@ -960,8 +947,8 @@ njs_array_prototype_to_string(njs_vm_t * prop = njs_object_property(vm, args[0].data.u.object, &lhq); if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) { - return njs_function_apply(vm, prop->value.data.u.function, - args, nargs, retval); + return njs_function_replace(vm, prop->value.data.u.function, + args, nargs, retval); } } @@ -970,17 +957,6 @@ njs_array_prototype_to_string(njs_vm_t * static njs_ret_t -njs_array_prototype_to_string_continuation(njs_vm_t *vm, njs_value_t *args, - nxt_uint_t nargs, njs_index_t retval) -{ - /* Skip retval update. */ - vm->top_frame->skip = 1; - - return NXT_OK; -} - - -static njs_ret_t njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { diff -r 5906cf108796 -r ff51b3e9ea05 njs/njs_date.c --- a/njs/njs_date.c Thu May 23 16:21:55 2019 +0300 +++ b/njs/njs_date.c Wed May 22 07:54:58 2019 +0800 @@ -43,8 +43,6 @@ static nxt_noinline njs_ret_t njs_date_s double time); static nxt_noinline double njs_date_time(struct tm *tm, int64_t ms); static double njs_date_utc_time(struct tm *tm, double time); -static njs_ret_t njs_date_prototype_to_json_continuation(njs_vm_t *vm, - njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); static const njs_value_t njs_string_invalid_date = njs_string("Invalid Date"); @@ -1895,23 +1893,13 @@ njs_date_utc_time(struct tm *tm, double } -/* - * ECMAScript 5.1: call object method "toISOString". - * Date.toJSON() must be a continuation otherwise it may endlessly - * call Date.toISOString(). - */ - static njs_ret_t njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t retval) { njs_object_prop_t *prop; - njs_continuation_t *cont; nxt_lvlhsh_query_t lhq; - cont = njs_vm_continuation(vm); - cont->function = njs_date_prototype_to_json_continuation; - if (njs_is_object(&args[0])) { lhq.key_hash = NJS_TO_ISO_STRING_HASH; lhq.key = nxt_string_value("toISOString"); @@ -1919,8 +1907,8 @@ njs_date_prototype_to_json(njs_vm_t *vm, prop = njs_object_property(vm, args[0].data.u.object, &lhq); if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) { - return njs_function_apply(vm, prop->value.data.u.function, - args, nargs, retval); + return njs_function_replace(vm, prop->value.data.u.function, + args, nargs, retval); } } @@ -1930,17 +1918,6 @@ njs_date_prototype_to_json(njs_vm_t *vm, } -static njs_ret_t -njs_date_prototype_to_json_continuation(njs_vm_t *vm, njs_value_t *args, - nxt_uint_t nargs, njs_index_t retval) -{ - /* Skip retval update. */ - vm->top_frame->skip = 1; - - return NXT_OK; -} - - static const njs_object_prop_t njs_date_prototype_properties[] = { { diff -r 5906cf108796 -r ff51b3e9ea05 njs/njs_function.h --- a/njs/njs_function.h Thu May 23 16:21:55 2019 +0300 +++ b/njs/njs_function.h Wed May 22 07:54:58 2019 +0800 @@ -200,6 +200,36 @@ njs_function_apply(njs_vm_t *vm, njs_fun } +/* + * Replaces the current function with a new one. + * Can only be used for continuation functions + * (data.u.function.continuation_size > 0). + */ +nxt_inline njs_ret_t +njs_function_replace(njs_vm_t *vm, njs_function_t *function, + const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval) +{ + nxt_int_t ret; + + ret = njs_function_apply(vm, function, args, nargs, retval); + if (nxt_slow_path(ret == NXT_ERROR)) { + return ret; + } + + /* + * 1) njs_function_apply() allocs a new function frame, + * in order to preserve the retval of a new function and ignore + * retval of the current function during stack unwinding + * skip flag is needed. + * 2) it is also needed for correct callee arguments update in + * njs_function_native_call() see "Object((new Date(0)).toJSON())". + */ + vm->top_frame->previous->skip = 1; + + return NJS_APPLIED; +} + + nxt_inline njs_native_frame_t * njs_function_previous_frame(njs_native_frame_t *frame) { diff -r 5906cf108796 -r ff51b3e9ea05 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 23 16:21:55 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed May 22 07:54:58 2019 +0800 @@ -6085,6 +6085,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("function f(a,b) { }; var ff = f.bind(f, 1); ff.length"), nxt_string("1") }, + { nxt_string("Object((new Date(0)).toJSON())+0"), + nxt_string("1970-01-01T00:00:00.000Z0") }, + + { nxt_string("Object((new Array(0)).toString())+0"), + nxt_string("0") }, + { nxt_string("JSON.parse.length"), nxt_string("2") }, From arut at nginx.com Mon May 27 16:56:39 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 27 May 2019 16:56:39 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/99ef05560b96 branches: changeset: 7512:99ef05560b96 user: Roman Arutyunyan date: Mon May 27 19:47:50 2019 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 234373adb2ce -r 99ef05560b96 src/core/nginx.h --- a/src/core/nginx.h Tue May 21 17:23:57 2019 +0300 +++ b/src/core/nginx.h Mon May 27 19:47:50 2019 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1017000 -#define NGINX_VERSION "1.17.0" +#define nginx_version 1017001 +#define NGINX_VERSION "1.17.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From arut at nginx.com Mon May 27 16:56:41 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 27 May 2019 16:56:41 +0000 Subject: [nginx] Upstream hash: fall back to round-robin if hash key is empty. Message-ID: details: https://hg.nginx.org/nginx/rev/d964b0aee8e7 branches: changeset: 7513:d964b0aee8e7 user: Niklas Keller date: Thu May 23 16:49:22 2019 +0300 description: Upstream hash: fall back to round-robin if hash key is empty. diffstat: src/http/modules/ngx_http_upstream_hash_module.c | 4 ++-- src/stream/ngx_stream_upstream_hash_module.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diffs (42 lines): diff -r 99ef05560b96 -r d964b0aee8e7 src/http/modules/ngx_http_upstream_hash_module.c --- a/src/http/modules/ngx_http_upstream_hash_module.c Mon May 27 19:47:50 2019 +0300 +++ b/src/http/modules/ngx_http_upstream_hash_module.c Thu May 23 16:49:22 2019 +0300 @@ -178,7 +178,7 @@ ngx_http_upstream_get_hash_peer(ngx_peer ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } @@ -509,7 +509,7 @@ ngx_http_upstream_get_chash_peer(ngx_pee ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } diff -r 99ef05560b96 -r d964b0aee8e7 src/stream/ngx_stream_upstream_hash_module.c --- a/src/stream/ngx_stream_upstream_hash_module.c Mon May 27 19:47:50 2019 +0300 +++ b/src/stream/ngx_stream_upstream_hash_module.c Thu May 23 16:49:22 2019 +0300 @@ -178,7 +178,7 @@ ngx_stream_upstream_get_hash_peer(ngx_pe ngx_stream_upstream_rr_peers_rlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } @@ -511,7 +511,7 @@ ngx_stream_upstream_get_chash_peer(ngx_p ngx_stream_upstream_rr_peers_wlock(hp->rrp.peers); - if (hp->tries > 20 || hp->rrp.peers->single) { + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); return hp->get_rr_peer(pc, &hp->rrp); } From mdounin at mdounin.ru Mon May 27 16:56:54 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 27 May 2019 19:56:54 +0300 Subject: Using round robin for load balancing if hash key is empty In-Reply-To: <20190523134932.GC91566@Romans-MacBook-Air.local> References: <20190523134932.GC91566@Romans-MacBook-Air.local> Message-ID: <20190527165654.GH1877@mdounin.ru> Hello! On Thu, May 23, 2019 at 04:49:32PM +0300, Roman Arutyunyan wrote: [...] > # HG changeset patch > # User Niklas Keller > # Date 1558614458 -10800 > # Thu May 23 15:27:38 2019 +0300 > # Node ID 34dff919b948dd9652b24459e6a40c303058df09 > # Parent 234373adb2ce6023e69e527cbf2b60adf70b1130 > Upstream hash: fall back to round-robin if hash key is empty. > > diff --git a/src/http/modules/ngx_http_upstream_hash_module.c b/src/http/modules/ngx_http_upstream_hash_module.c > --- a/src/http/modules/ngx_http_upstream_hash_module.c > +++ b/src/http/modules/ngx_http_upstream_hash_module.c > @@ -178,7 +178,7 @@ ngx_http_upstream_get_hash_peer(ngx_peer > > ngx_http_upstream_rr_peers_rlock(hp->rrp.peers); > > - if (hp->tries > 20 || hp->rrp.peers->single) { > + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { > ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); > return hp->get_rr_peer(pc, &hp->rrp); > } > @@ -509,7 +509,7 @@ ngx_http_upstream_get_chash_peer(ngx_pee > > ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); > > - if (hp->tries > 20 || hp->rrp.peers->single) { > + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { > ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); > return hp->get_rr_peer(pc, &hp->rrp); > } > diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c > --- a/src/stream/ngx_stream_upstream_hash_module.c > +++ b/src/stream/ngx_stream_upstream_hash_module.c > @@ -178,7 +178,7 @@ ngx_stream_upstream_get_hash_peer(ngx_pe > > ngx_stream_upstream_rr_peers_rlock(hp->rrp.peers); > > - if (hp->tries > 20 || hp->rrp.peers->single) { > + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { > ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); > return hp->get_rr_peer(pc, &hp->rrp); > } > @@ -511,7 +511,7 @@ ngx_stream_upstream_get_chash_peer(ngx_p > > ngx_stream_upstream_rr_peers_wlock(hp->rrp.peers); > > - if (hp->tries > 20 || hp->rrp.peers->single) { > + if (hp->tries > 20 || hp->rrp.peers->single || hp->key.len == 0) { > ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); > return hp->get_rr_peer(pc, &hp->rrp); > } For the record: looks good to me, please commit. -- Maxim Dounin http://mdounin.ru/ From arut at nginx.com Mon May 27 16:59:43 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 27 May 2019 19:59:43 +0300 Subject: Using round robin for load balancing if hash key is empty In-Reply-To: References: <20190523152127.GA30003@vlpc> Message-ID: <20190527165943.GF91566@Romans-MacBook-Air.local> Hello Niklas, On Thu, May 23, 2019 at 07:54:46PM +0200, Niklas Keller wrote: > > > I'd like to propose falling back to round robin if the hash key is > > > empty. This allows using hashed cookie values for sticky sessions > > > while using round robin for all requests that do not carry any session > > > information and thus do not need the stickiness. While Nginx Plus > > > allows to use the learning mode, this patch avoids the need for > > > synchronization between multiple instances. > > > > > > > Can you please elaborate on balancing/sticky scheme you are using? > > > > Say, first request without cookie is balanced by round-robin, arrives > > at some backend, which responds with cookie. > > Next time, the request with cookie is balanced by hash algorithm, > > and the result can be easily another backend. How do you deal with this? > > Very few requests depend on the stickiness in our application. The > main use case is showing success messages once after a form is > submitted. > > In these cases, the usual flow is: > - GET /form ? Server assigns cookie > - POST /form ? Client sends cookie, a different server might be > selected, but doesn't matter > - GET /form?_key=abc ? Client sends cookie again, success message is > shown and removed from the session, same server as in the previous > request is selected > > For cookie-less clients, e.g. crawlers and webhooks, the stickiness > doesn't matter at all, so these shouldn't be sticky to avoid peaks on > single backend nodes. > > @Roman: Patch looks good to me, thanks! Committed, thanks. https://hg.nginx.org/nginx/rev/d964b0aee8e7 -- Roman Arutyunyan From alexander.borisov at nginx.com Mon May 27 17:32:43 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Mon, 27 May 2019 17:32:43 +0000 Subject: [njs] Fixed format of the reference exception. Message-ID: details: https://hg.nginx.org/njs/rev/7ae4f639fa43 branches: changeset: 985:7ae4f639fa43 user: Alexander Borisov date: Mon May 27 19:06:34 2019 +0300 description: Fixed format of the reference exception. Previously, it did not include filename. diffstat: njs/njs_generator.c | 6 ++++++ njs/njs_vm.c | 13 +++++++++++-- njs/njs_vm.h | 1 + njs/test/njs_expect_test.exp | 13 +++++++++++-- 4 files changed, 29 insertions(+), 4 deletions(-) diffs (91 lines): diff -r ff51b3e9ea05 -r 7ae4f639fa43 njs/njs_generator.c --- a/njs/njs_generator.c Wed May 22 07:54:58 2019 +0800 +++ b/njs/njs_generator.c Mon May 27 19:06:34 2019 +0300 @@ -3288,6 +3288,7 @@ static nxt_int_t njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { + njs_ret_t ret; njs_vmcode_reference_error_t *ref_err; if (nxt_slow_path(!node->u.reference.not_defined)) { @@ -3301,6 +3302,11 @@ njs_generate_reference_error(njs_vm_t *v ref_err->token_line = node->token_line; + ret = njs_name_copy(vm, &ref_err->file, &node->scope->file); + if (nxt_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + return njs_name_copy(vm, &ref_err->name, &node->u.reference.name); } diff -r ff51b3e9ea05 -r 7ae4f639fa43 njs/njs_vm.c --- a/njs/njs_vm.c Wed May 22 07:54:58 2019 +0800 +++ b/njs/njs_vm.c Mon May 27 19:06:34 2019 +0300 @@ -2659,12 +2659,21 @@ njs_ret_t njs_vmcode_reference_error(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2) { + nxt_str_t *file; njs_vmcode_reference_error_t *ref_err; ref_err = (njs_vmcode_reference_error_t *) vm->current; - njs_reference_error(vm, "\"%V\" is not defined in %uD", &ref_err->name, - ref_err->token_line); + file = &ref_err->file; + + if (file->length != 0 && !vm->options.quiet) { + njs_reference_error(vm, "\"%V\" is not defined in %V:%uD", + &ref_err->name, file, ref_err->token_line); + + } else { + njs_reference_error(vm, "\"%V\" is not defined in %uD", &ref_err->name, + ref_err->token_line); + } return NJS_ERROR; } diff -r ff51b3e9ea05 -r 7ae4f639fa43 njs/njs_vm.h --- a/njs/njs_vm.h Wed May 22 07:54:58 2019 +0800 +++ b/njs/njs_vm.h Mon May 27 19:06:34 2019 +0300 @@ -857,6 +857,7 @@ typedef struct { typedef struct { njs_vmcode_t code; nxt_str_t name; + nxt_str_t file; uint32_t token_line; } njs_vmcode_reference_error_t; diff -r ff51b3e9ea05 -r 7ae4f639fa43 njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Wed May 22 07:54:58 2019 +0800 +++ b/njs/test/njs_expect_test.exp Mon May 27 19:06:34 2019 +0300 @@ -668,6 +668,17 @@ njs_test { # modules +# FIXME: +# During import, the variable is declared regardless of the result of the import. +# Because of this, in the console mode, checking the variable after the import +# error may give an incorrect result. +# +# For example: +# {"import ref from 'ref_exception.js'\r\n" +# "ReferenceError: \"undeclared\" is not defined in ref_exception.js:1"} +# {"ref\r\n" +# "ReferenceError: \"ref\" is not defined in shell:1\r\n"} + njs_test { {"import lib1 from 'lib1.js'; import lib2 from 'lib1.js'\r\n" "undefined\r\n"} @@ -685,8 +696,6 @@ njs_test { "Non-default export is not supported in export_non_default.js:3\r\n"} {"import ref from 'ref_exception.js'\r\n" "ReferenceError: \"undeclared\" is not defined in ref_exception.js:1"} - {"ref\r\n" - "ReferenceError: \"ref\" is not defined in shell:1\r\n"} {"var ref\r\n" "undefined\r\n"} {"import ref from 'ref_exception.js'\r\n" From alexander.borisov at nginx.com Mon May 27 18:09:54 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Mon, 27 May 2019 18:09:54 +0000 Subject: [njs] Added njs_value_property_set() function. Message-ID: details: https://hg.nginx.org/njs/rev/4572a6e64bf1 branches: changeset: 986:4572a6e64bf1 user: Alexander Borisov date: Thu May 23 17:39:22 2019 +0300 description: Added njs_value_property_set() function. diffstat: njs/njs_object.h | 2 + njs/njs_vm.c | 254 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 135 insertions(+), 121 deletions(-) diffs (290 lines): diff -r 7ae4f639fa43 -r 4572a6e64bf1 njs/njs_object.h --- a/njs/njs_object.h Mon May 27 19:06:34 2019 +0300 +++ b/njs/njs_object.h Thu May 23 17:39:22 2019 +0300 @@ -88,6 +88,8 @@ njs_array_t *njs_object_own_enumerate(nj njs_object_enum_t kind, nxt_bool_t all); njs_ret_t njs_value_property(njs_vm_t *vm, const njs_value_t *value, const njs_value_t *property, njs_value_t *retval); +njs_ret_t njs_value_property_set(njs_vm_t *vm, njs_value_t *object, + const njs_value_t *property, njs_value_t *value); 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_property_query(njs_vm_t *vm, njs_property_query_t *pq, diff -r 7ae4f639fa43 -r 4572a6e64bf1 njs/njs_vm.c --- a/njs/njs_vm.c Mon May 27 19:06:34 2019 +0300 +++ b/njs/njs_vm.c Thu May 23 17:39:22 2019 +0300 @@ -660,134 +660,17 @@ njs_vmcode_property_set(njs_vm_t *vm, nj { njs_ret_t ret; njs_value_t *value; - njs_object_prop_t *prop, *shared; - njs_property_query_t pq; njs_vmcode_prop_set_t *code; - if (njs_is_primitive(object)) { - njs_type_error(vm, "property set on primitive %s type", - njs_type_string(object->type)); - return NXT_ERROR; - } - code = (njs_vmcode_prop_set_t *) vm->current; value = njs_vmcode_operand(vm, code->value); - shared = NULL; - - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0); - - ret = njs_property_query(vm, &pq, object, property); - - switch (ret) { - - case NXT_OK: - prop = pq.lhq.value; - - if (nxt_slow_path(!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; - } - - if (prop->type == NJS_PROPERTY_HANDLER) { - ret = prop->value.data.u.prop_handler(vm, object, value, - &vm->retval); - - switch (ret) { - case NXT_OK: - return sizeof(njs_vmcode_prop_set_t); - - case NXT_DECLINED: - break; - - default: - return ret; - } - } - - if (pq.own) { - switch (prop->type) { - case NJS_PROPERTY: - case NJS_METHOD: - if (nxt_slow_path(pq.shared)) { - shared = prop; - break; - } - - goto found; - - case NJS_PROPERTY_REF: - *prop->value.data.u.value = *value; - return sizeof(njs_vmcode_prop_set_t); - - default: - njs_internal_error(vm, "unexpected property type \"%s\" " - "while setting", - njs_prop_type_string(prop->type)); - - return NXT_ERROR; - } - - break; - } - - /* Fall through. */ - - case NXT_DECLINED: - if (nxt_slow_path(pq.own_whiteout != NULL)) { - /* Previously deleted property. */ - prop = pq.own_whiteout; - - prop->type = NJS_PROPERTY; - prop->enumerable = 1; - prop->configurable = 1; - prop->writable = 1; - - goto found; - } - - break; - - case NJS_TRAP: - case NXT_ERROR: - default: - - return ret; + ret = njs_value_property_set(vm, object, property, value); + if (ret == NXT_OK) { + return sizeof(njs_vmcode_prop_set_t); } - if (nxt_slow_path(!object->data.u.object->extensible)) { - njs_type_error(vm, "Cannot add property \"%V\", " - "object is not extensible", &pq.lhq.key); - return NXT_ERROR; - } - - prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_undefined, 1); - if (nxt_slow_path(prop == NULL)) { - return NXT_ERROR; - } - - if (nxt_slow_path(shared != NULL)) { - prop->enumerable = shared->enumerable; - prop->configurable = shared->configurable; - } - - pq.lhq.replace = 0; - pq.lhq.value = prop; - pq.lhq.pool = vm->mem_pool; - - 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; - } - -found: - - prop->value = *value; - - return sizeof(njs_vmcode_prop_set_t); + return ret; } @@ -3240,6 +3123,135 @@ njs_value_property(njs_vm_t *vm, const n } +/* + * NXT_OK property has been set successfully + * NJS_TRAP the property trap must be called + * 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) +{ + njs_ret_t ret; + njs_object_prop_t *prop, *shared; + njs_property_query_t pq; + + if (njs_is_primitive(object)) { + njs_type_error(vm, "property set on primitive %s type", + njs_type_string(object->type)); + return NXT_ERROR; + } + + shared = NULL; + + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 0); + + ret = njs_property_query(vm, &pq, object, property); + + switch (ret) { + + case NXT_OK: + prop = pq.lhq.value; + + if (nxt_slow_path(!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; + } + + if (prop->type == NJS_PROPERTY_HANDLER) { + ret = prop->value.data.u.prop_handler(vm, object, value, + &vm->retval); + if (ret != NXT_DECLINED) { + return ret; + } + } + + if (pq.own) { + switch (prop->type) { + case NJS_PROPERTY: + case NJS_METHOD: + if (nxt_slow_path(pq.shared)) { + shared = prop; + break; + } + + goto found; + + case NJS_PROPERTY_REF: + *prop->value.data.u.value = *value; + return NXT_OK; + + default: + njs_internal_error(vm, "unexpected property type \"%s\" " + "while setting", + njs_prop_type_string(prop->type)); + + return NXT_ERROR; + } + + break; + } + + /* Fall through. */ + + case NXT_DECLINED: + if (nxt_slow_path(pq.own_whiteout != NULL)) { + /* Previously deleted property. */ + prop = pq.own_whiteout; + + prop->type = NJS_PROPERTY; + prop->enumerable = 1; + prop->configurable = 1; + prop->writable = 1; + + goto found; + } + + break; + + case NJS_TRAP: + case NXT_ERROR: + default: + + return ret; + } + + if (nxt_slow_path(!object->data.u.object->extensible)) { + njs_type_error(vm, "Cannot add property \"%V\", " + "object is not extensible", &pq.lhq.key); + return NXT_ERROR; + } + + prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_undefined, 1); + if (nxt_slow_path(prop == NULL)) { + return NXT_ERROR; + } + + if (nxt_slow_path(shared != NULL)) { + prop->enumerable = shared->enumerable; + prop->configurable = shared->configurable; + } + + pq.lhq.replace = 0; + pq.lhq.value = prop; + pq.lhq.pool = vm->mem_pool; + + 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; + } + +found: + + prop->value = *value; + + return NXT_OK; +} + + njs_array_t * njs_value_enumerate(njs_vm_t *vm, const njs_value_t *value, njs_object_enum_t kind, nxt_bool_t all) From me at kelunik.com Mon May 27 21:00:32 2019 From: me at kelunik.com (Niklas Keller) Date: Mon, 27 May 2019 23:00:32 +0200 Subject: Using round robin for load balancing if hash key is empty In-Reply-To: <20190527165943.GF91566@Romans-MacBook-Air.local> References: <20190523152127.GA30003@vlpc> <20190527165943.GF91566@Romans-MacBook-Air.local> Message-ID: > Committed, thanks. > > https://hg.nginx.org/nginx/rev/d964b0aee8e7 I've just seen it, thanks! \o/ From xeioex at nginx.com Tue May 28 14:05:29 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 28 May 2019 14:05:29 +0000 Subject: [njs] HTTP: improved working with unknown methods in subrequest(). Message-ID: details: https://hg.nginx.org/njs/rev/6b7042a20523 branches: changeset: 988:6b7042a20523 user: Dmitry Volyntsev date: Tue May 28 17:04:33 2019 +0300 description: HTTP: improved working with unknown methods in subrequest(). diffstat: nginx/ngx_http_js_module.c | 25 ++++++++++++++----------- 1 files changed, 14 insertions(+), 11 deletions(-) diffs (63 lines): diff -r f6234460852a -r 6b7042a20523 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue May 28 15:57:35 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue May 28 17:04:33 2019 +0300 @@ -1728,7 +1728,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, { ngx_int_t rc; nxt_str_t uri_arg, args_arg, method_name, body_arg; - ngx_uint_t method, n, has_body; + ngx_uint_t method, methods_max, has_body; njs_value_t *value; njs_function_t *callback; ngx_http_js_ctx_t *ctx; @@ -1788,6 +1788,8 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, callback = NULL; method = 0; + methods_max = sizeof(methods) / sizeof(methods[0]); + args_arg.length = 0; args_arg.start = NULL; has_body = 0; @@ -1827,9 +1829,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, return NJS_ERROR; } - n = sizeof(methods) / sizeof(methods[0]); - - while (method < n) { + while (method < methods_max) { if (method_name.length == methods[method].name.len && ngx_memcmp(method_name.start, methods[method].name.data, method_name.length) @@ -1840,11 +1840,6 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, method++; } - - if (method == n) { - njs_vm_error(vm, "unknown method \"%V\"", &method_name); - return NJS_ERROR; - } } value = njs_vm_object_prop(vm, options, &body_key); @@ -1875,8 +1870,16 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, return NJS_ERROR; } - sr->method = methods[method].value; - sr->method_name = methods[method].name; + if (method != methods_max) { + sr->method = methods[method].value; + sr->method_name = methods[method].name; + + } else { + sr->method = NGX_HTTP_UNKNOWN; + sr->method_name.len = method_name.length; + sr->method_name.data = method_name.start; + } + sr->header_only = (sr->method == NGX_HTTP_HEAD) || (callback == NULL); if (has_body) { From xeioex at nginx.com Tue May 28 14:05:29 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 28 May 2019 14:05:29 +0000 Subject: [njs] HTTP: improved getting of special response headers. Message-ID: details: https://hg.nginx.org/njs/rev/f6234460852a branches: changeset: 987:f6234460852a user: Dmitry Volyntsev date: Tue May 28 15:57:35 2019 +0300 description: HTTP: improved getting of special response headers. diffstat: nginx/ngx_http_js_module.c | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diffs (48 lines): diff -r 4572a6e64bf1 -r f6234460852a nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu May 23 17:39:22 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue May 28 15:57:35 2019 +0300 @@ -922,13 +922,44 @@ static njs_ret_t ngx_http_js_ext_get_header_out(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { + u_char *p, *start; nxt_str_t *v; + ngx_str_t *hdr; ngx_table_elt_t *h; ngx_http_request_t *r; + u_char content_len[NGX_OFF_T_LEN]; r = (ngx_http_request_t *) obj; v = (nxt_str_t *) data; + if (v->length == nxt_length("Content-Type") + && ngx_strncasecmp(v->start, (u_char *) "Content-Type", + v->length) == 0) + { + hdr = &r->headers_out.content_type; + return njs_vm_value_string_set(vm, value, hdr->data, hdr->len); + } + + if (v->length == nxt_length("Content-Length") + && ngx_strncasecmp(v->start, (u_char *) "Content-Length", + v->length) == 0) + { + if (r->headers_out.content_length == NULL + && r->headers_out.content_length_n >= 0) + { + p = ngx_sprintf(content_len, "%O", r->headers_out.content_length_n); + + start = njs_vm_value_string_alloc(vm, value, p - content_len); + if (start == NULL) { + return NJS_ERROR; + } + + ngx_memcpy(start, content_len, p - content_len); + + return NJS_OK; + } + } + h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start, v->length); if (h == NULL) { From xeioex at nginx.com Tue May 28 14:05:29 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 28 May 2019 14:05:29 +0000 Subject: [njs] Stream: fixed processing empty output chain in body filter. Message-ID: details: https://hg.nginx.org/njs/rev/77e4b95109d4 branches: changeset: 989:77e4b95109d4 user: Dmitry Volyntsev date: Tue May 28 17:04:40 2019 +0300 description: Stream: fixed processing empty output chain in body filter. This closes #1735 on trac. diffstat: nginx/ngx_stream_js_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 6b7042a20523 -r 77e4b95109d4 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Tue May 28 17:04:33 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Tue May 28 17:04:40 2019 +0300 @@ -601,7 +601,7 @@ ngx_stream_js_body_filter(ngx_stream_ses *ctx->last_out = NULL; - if (out != NULL) { + if (out != NULL || c->buffered) { rc = ngx_stream_next_filter(s, out, from_upstream); ngx_chain_update_chains(c->pool, &ctx->free, &ctx->busy, &out, From alexander.borisov at nginx.com Tue May 28 17:45:26 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 28 May 2019 17:45:26 +0000 Subject: [njs] Added generic implementation of Array.prototype.fill(). Message-ID: details: https://hg.nginx.org/njs/rev/8e7e7ba29c71 branches: changeset: 990:8e7e7ba29c71 user: Alexander Borisov date: Thu May 23 18:03:46 2019 +0300 description: Added generic implementation of Array.prototype.fill(). According to ES6: 22.1.3.6. This closes #72 issue on GitHub. diffstat: njs/njs_array.c | 152 +++++++++++++++++++++++++++++++++------------- njs/test/njs_unit_test.c | 14 ++++ 2 files changed, 121 insertions(+), 45 deletions(-) diffs (219 lines): diff -r 77e4b95109d4 -r 8e7e7ba29c71 njs/njs_array.c --- a/njs/njs_array.c Tue May 28 17:04:40 2019 +0300 +++ b/njs/njs_array.c Thu May 23 18:03:46 2019 +0300 @@ -23,6 +23,16 @@ typedef struct { typedef struct { + union { + njs_continuation_t cont; + u_char padding[NJS_CONTINUATION_SIZE]; + } u; + + njs_value_t length; +} njs_array_fill_t; + + +typedef struct { njs_continuation_t cont; njs_value_t *values; uint32_t max; @@ -88,6 +98,8 @@ static njs_ret_t njs_array_prototype_sli static njs_ret_t njs_array_prototype_join_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); 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_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, @@ -1395,62 +1407,111 @@ static njs_ret_t njs_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { + njs_ret_t ret; + njs_value_t *this; + njs_array_fill_t *fill; + + static const njs_value_t njs_string_length = njs_string("length"); + + this = (njs_value_t *) njs_arg(args, nargs, 0); + + if (njs_is_primitive(this)) { + if (njs_is_null_or_undefined(this)) { + njs_type_error(vm, "\"this\" argument cannot be " + "undefined or null value"); + return NJS_ERROR; + } + + } else if (!njs_is_array(this)) { + 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)) { + return ret; + } + } + + return njs_array_prototype_fill_continuation(vm, args, nargs, unused); +} + + +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; - const njs_value_t *value; - - vm->retval = args[0]; - - if (!njs_is_array(&args[0])) { - return NXT_OK; - } - - array = args[0].data.u.array; - length = array->length; - - if (length == 0) { + njs_value_t name; + njs_object_t *object; + njs_array_fill_t *fill; + const njs_value_t *this, *value; + + array = NULL; + + this = njs_arg(args, nargs, 0); + + if (njs_is_primitive(this)) { + object = njs_object_value_alloc(vm, this, this->type); + if (nxt_slow_path(object == NULL)) { + return NXT_ERROR; + } + + vm->retval.data.u.object = object; + vm->retval.type = object->type; + vm->retval.data.truth = 1; + return NXT_OK; } - start = 0; - end = length; - - if (nargs > 2) { - start = args[2].data.u.number; - - if (start > length) { - start = length; - } - - if (start < 0) { - start += length; - - if (start < 0) { - start = 0; - } + 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); + return njs_trap(vm, NJS_TRAP_NUMBER_ARG); } - if (nargs > 3) { - end = args[3].data.u.number; - - if (end > length) { - end = length; - } - - if (end < 0) { - end += length; - - if (end < 0) { - end = 0; - } - } - } + length = njs_primitive_value_to_length(&fill->length); } + start = njs_primitive_value_to_integer(njs_arg(args, nargs, 2)); + start = (start < 0) ? nxt_max(length + start, 0) : nxt_min(start, length); + + if (njs_is_undefined(njs_arg(args, nargs, 3))) { + end = length; + + } else { + end = njs_primitive_value_to_integer(njs_arg(args, nargs, 3)); + } + + end = (end < 0) ? nxt_max(length + end, 0) : nxt_min(end, length); + value = njs_arg(args, nargs, 1); + vm->retval = *this; + + if (array != NULL) { + for (i = start; i < end; i++) { + array->start[i] = *value; + } + + return NXT_OK; + } + for (i = start; i < end; i++) { - array->start[i] = *value; + njs_uint32_to_string(&name, i); + + ret = njs_value_property_set(vm, &vm->retval, &name, + (njs_value_t *) value); + if (nxt_slow_path(ret == NXT_ERROR)) { + return ret; + } } return NXT_OK; @@ -2395,7 +2456,8 @@ static const njs_object_prop_t njs_arra { .type = NJS_METHOD, .name = njs_string("fill"), - .value = njs_native_function(njs_array_prototype_fill, 0, + .value = njs_native_function(njs_array_prototype_fill, + njs_continuation_size(njs_array_fill_t), NJS_OBJECT_ARG, NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), .writable = 1, diff -r 77e4b95109d4 -r 8e7e7ba29c71 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 28 17:04:40 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 23 18:03:46 2019 +0300 @@ -3995,6 +3995,20 @@ static njs_unit_test_t njs_test[] = "{ return a + (x === undefined); }, 0)"), nxt_string("3") }, + { nxt_string("var a = Array.prototype.fill.apply(" + "Object({length: 40}), [\"a\", 1, 20]); Object.values(a)"), + nxt_string("a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,40,a,a,a,a") }, + + { nxt_string("var a = Array.prototype.fill.apply({length: " + "{ valueOf: function() { return 40 }}}, [\"a\", 1, 20]);" + "Object.values(a)"), + nxt_string("a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,[object Object],a,a,a,a") }, + + { nxt_string("[NaN, false, ''].map(" + "(x) => Array.prototype.fill.call(x)" + ").every((x) => typeof x == 'object')"), + nxt_string("true") }, + { nxt_string("var a = [];" "a.filter(function(v, i, a) { return v > 1 })"), nxt_string("") }, From alexander.borisov at nginx.com Wed May 29 14:55:30 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Wed, 29 May 2019 14:55:30 +0000 Subject: [njs] Improved processing of invalid surrogate pairs in strings. Message-ID: details: https://hg.nginx.org/njs/rev/96dc9de9f92c branches: changeset: 991:96dc9de9f92c user: Alexander Borisov date: Tue May 28 20:49:58 2019 +0300 description: Improved processing of invalid surrogate pairs in strings. Previously, an exception was thrown on invalid surrogate pairs. Now, all such pairs are converted to replacement character. This closes #170 issue on GitHub. diffstat: njs/njs_parser_terminal.c | 51 +++++++++++++++++++++++++++++++--------------- njs/test/njs_unit_test.c | 20 +++++++++++++---- nxt/nxt_utf8.h | 2 + 3 files changed, 51 insertions(+), 22 deletions(-) diffs (129 lines): diff -r 8e7e7ba29c71 -r 96dc9de9f92c njs/njs_parser_terminal.c --- a/njs/njs_parser_terminal.c Thu May 23 18:03:46 2019 +0300 +++ b/njs/njs_parser_terminal.c Tue May 28 20:49:58 2019 +0300 @@ -1049,12 +1049,27 @@ njs_parser_escape_string_create(njs_vm_t } if (cp_pair != 0) { - cp = njs_string_surrogate_pair(cp_pair, cp); + if (nxt_fast_path(cp >= 0xdc00 && cp <= 0xdfff)) { + cp = njs_string_surrogate_pair(cp_pair, cp); + + } else if (nxt_slow_path(cp >= 0xd800 && cp <= 0xdbff)) { + cp = NXT_UTF8_REPLACEMENT; + + dst = nxt_utf8_encode(dst, (uint32_t) cp); + + } else { + dst = nxt_utf8_encode(dst, NXT_UTF8_REPLACEMENT); + } + cp_pair = 0; } else if (cp >= 0xd800 && cp <= 0xdfff) { - cp_pair = cp; - continue; + if (cp <= 0xdbff && src[0] == '\\' && src[1] == 'u') { + cp_pair = cp; + continue; + } + + cp = NXT_UTF8_REPLACEMENT; } dst = nxt_utf8_encode(dst, (uint32_t) cp); @@ -1183,20 +1198,29 @@ njs_parser_escape_string_calc_length(njs } if (cp_pair != 0) { - if (nxt_slow_path(cp < 0xdc00 || cp > 0xdfff)) { - goto invalid_pair; + if (nxt_fast_path(cp >= 0xdc00 && cp <= 0xdfff)) { + cp = njs_string_surrogate_pair(cp_pair, cp); + + } else if (nxt_slow_path(cp >= 0xd800 && cp <= 0xdbff)) { + cp = NXT_UTF8_REPLACEMENT; + + size += nxt_utf8_size(cp); + length++; + + } else { + size += nxt_utf8_size(NXT_UTF8_REPLACEMENT); + length++; } - cp = njs_string_surrogate_pair(cp_pair, cp); cp_pair = 0; } else if (cp >= 0xd800 && cp <= 0xdfff) { - if (nxt_slow_path(cp > 0xdbff || src[0] != '\\' || src[1] != 'u')) { - goto invalid_pair; + if (cp <= 0xdbff && src[0] == '\\' && src[1] == 'u') { + cp_pair = cp; + continue; } - cp_pair = cp; - continue; + cp = NXT_UTF8_REPLACEMENT; } size += nxt_utf8_size(cp); @@ -1214,11 +1238,4 @@ invalid: njs_parser_text(parser)); return NJS_ERROR; - -invalid_pair: - - njs_parser_syntax_error(vm, parser, "Invalid surrogate pair \"%V\"", - njs_parser_text(parser)); - - return NJS_ERROR; } diff -r 8e7e7ba29c71 -r 96dc9de9f92c njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 23 18:03:46 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 28 20:49:58 2019 +0300 @@ -4448,15 +4448,25 @@ static njs_unit_test_t njs_test[] = nxt_string("1") }, { nxt_string("'\\ud83d abc \\udc4d'"), - nxt_string("SyntaxError: Invalid surrogate pair " - "\"\\ud83d abc \\udc4d\" in 1") }, + nxt_string("? abc ?") }, { nxt_string("'\\ud83d'"), - nxt_string("SyntaxError: Invalid surrogate pair \"\\ud83d\" in 1") }, + nxt_string("?") }, { nxt_string("'\\ud83d\\uabcd'"), - nxt_string("SyntaxError: Invalid surrogate pair " - "\"\\ud83d\\uabcd\" in 1") }, + nxt_string("??") }, + + { nxt_string("'\\u{d800}\\u{dB00}'"), + nxt_string("??") }, + + { nxt_string("'\\u{d800}\\u{d7ff}'"), + nxt_string("??") }, + + { nxt_string("'\\u{d800}['"), + nxt_string("?[") }, + + { nxt_string("'\\u{D800}\\u{'"), + nxt_string("SyntaxError: Invalid Unicode code point \"\\u{D800}\\u{\" in 1") }, { nxt_string("''.hasOwnProperty('length')"), nxt_string("true") }, diff -r 8e7e7ba29c71 -r 96dc9de9f92c nxt/nxt_utf8.h --- a/nxt/nxt_utf8.h Thu May 23 18:03:46 2019 +0300 +++ b/nxt/nxt_utf8.h Tue May 28 20:49:58 2019 +0300 @@ -15,6 +15,8 @@ */ #define NXT_UTF8_SORT_INVALID 0x0EEE0EEE +#define NXT_UTF8_REPLACEMENT 0xFFFD + NXT_EXPORT u_char *nxt_utf8_encode(u_char *p, uint32_t u); NXT_EXPORT uint32_t nxt_utf8_decode(const u_char **start, const u_char *end); From alexander.borisov at nginx.com Wed May 29 18:11:35 2019 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Wed, 29 May 2019 18:11:35 +0000 Subject: [njs] Improved processing of invalid surrogate pairs in JSON strings. Message-ID: details: https://hg.nginx.org/njs/rev/82ca4be8b357 branches: changeset: 992:82ca4be8b357 user: Alexander Borisov date: Tue May 28 20:51:24 2019 +0300 description: Improved processing of invalid surrogate pairs in JSON strings. Previously, an exception was thrown on invalid surrogate pairs. Now, all such pairs are converted to replacement character. diffstat: njs/njs_json.c | 19 ++++++++++++------- njs/test/njs_unit_test.c | 13 +++++++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diffs (62 lines): diff -r 96dc9de9f92c -r 82ca4be8b357 njs/njs_json.c --- a/njs/njs_json.c Tue May 28 20:49:58 2019 +0300 +++ b/njs/njs_json.c Tue May 28 20:51:24 2019 +0300 @@ -806,8 +806,8 @@ njs_json_parse_string(njs_json_parse_ctx /* Surrogate pair. */ if (utf > 0xdbff || p[0] != '\\' || p[1] != 'u') { - njs_json_parse_exception(ctx, "Invalid Unicode char", p); - return NULL; + s = nxt_utf8_encode(s, NXT_UTF8_REPLACEMENT); + continue; } p += 2; @@ -815,12 +815,17 @@ njs_json_parse_string(njs_json_parse_ctx utf_low = njs_json_unicode(p); p += 4; - if (nxt_slow_path(utf_low < 0xdc00 || utf_low > 0xdfff)) { - njs_json_parse_exception(ctx, "Invalid surrogate pair", p); - return NULL; + if (nxt_fast_path(utf_low >= 0xdc00 && utf_low <= 0xdfff)) { + utf = njs_string_surrogate_pair(utf, utf_low); + + } else if (utf_low >= 0xd800 && utf_low <= 0xdbff) { + utf = NXT_UTF8_REPLACEMENT; + s = nxt_utf8_encode(s, NXT_UTF8_REPLACEMENT); + + } else { + utf = utf_low; + s = nxt_utf8_encode(s, NXT_UTF8_REPLACEMENT); } - - utf = njs_string_surrogate_pair(utf, utf_low); } s = nxt_utf8_encode(s, utf); diff -r 96dc9de9f92c -r 82ca4be8b357 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 28 20:49:58 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue May 28 20:51:24 2019 +0300 @@ -11799,10 +11799,19 @@ static njs_unit_test_t njs_test[] = nxt_string("SyntaxError: Unknown escape char at position 2") }, { nxt_string("JSON.parse('\"\\\\uDC01\"')"), - nxt_string("SyntaxError: Invalid Unicode char at position 7") }, + nxt_string("?") }, { nxt_string("JSON.parse('\"\\\\uD801\\\\uE000\"')"), - nxt_string("SyntaxError: Invalid surrogate pair at position 13") }, + nxt_string("??") }, + + { nxt_string("JSON.parse('\"\\\\uD83D\"')"), + nxt_string("?") }, + + { nxt_string("JSON.parse('\"\\\\uD800\\\\uDB00\"')"), + nxt_string("??") }, + + { nxt_string("JSON.parse('\"\\\\ud800[\"')"), + nxt_string("?[") }, { nxt_string("JSON.parse('{')"), nxt_string("SyntaxError: Unexpected end of input at position 1") }, From xeioex at nginx.com Thu May 30 11:18:08 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 30 May 2019 11:18:08 +0000 Subject: [njs] Removing possible ignored regexp compilation error. Message-ID: details: https://hg.nginx.org/njs/rev/ab5d059e4ef8 branches: changeset: 993:ab5d059e4ef8 user: Dmitry Volyntsev date: Thu May 30 14:17:59 2019 +0300 description: Removing possible ignored regexp compilation error. diffstat: njs/njs_regexp.c | 2 ++ njs/test/njs_unit_test.c | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) diffs (25 lines): diff -r 82ca4be8b357 -r ab5d059e4ef8 njs/njs_regexp.c --- a/njs/njs_regexp.c Tue May 28 20:51:24 2019 +0300 +++ b/njs/njs_regexp.c Thu May 30 14:17:59 2019 +0300 @@ -557,6 +557,8 @@ njs_regexp_pattern_create(njs_vm_t *vm, } while (n != pattern->ngroups); } + njs_value_undefined_set(&vm->retval); + return pattern; fail: diff -r 82ca4be8b357 -r ab5d059e4ef8 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue May 28 20:51:24 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 30 14:17:59 2019 +0300 @@ -7240,6 +7240,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("/^[A-Za-z0-9+/]{4}$/.test('////')"), nxt_string("true") }, + { nxt_string("/[\\uFDE0-\\uFFFD]/g; export default 1"), + nxt_string("SyntaxError: Illegal export statement in 1") }, + { nxt_string("'[]!\"#$%&\\'()*+,.\\/:;<=>?@\\^_`{|}-'.split('')" ".every(ch=>/[\\]\\[!\"#$%&'()*+,.\\/:;<=>?@\\^_`{|}-]/.test(ch))"), nxt_string("true") }, From xeioex at nginx.com Thu May 30 14:14:49 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 30 May 2019 14:14:49 +0000 Subject: [njs] Moving test added in ab5d059e4ef8 to a conditional list. Message-ID: details: https://hg.nginx.org/njs/rev/b6ecd0086ed3 branches: changeset: 994:b6ecd0086ed3 user: Dmitry Volyntsev date: Thu May 30 16:16:22 2019 +0300 description: Moving test added in ab5d059e4ef8 to a conditional list. As it can fail on older libpcre versions (pcre-7.8 for example). diffstat: njs/test/njs_unit_test.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (23 lines): diff -r ab5d059e4ef8 -r b6ecd0086ed3 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 30 14:17:59 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 30 16:16:22 2019 +0300 @@ -7240,9 +7240,6 @@ static njs_unit_test_t njs_test[] = { nxt_string("/^[A-Za-z0-9+/]{4}$/.test('////')"), nxt_string("true") }, - { nxt_string("/[\\uFDE0-\\uFFFD]/g; export default 1"), - nxt_string("SyntaxError: Illegal export statement in 1") }, - { nxt_string("'[]!\"#$%&\\'()*+,.\\/:;<=>?@\\^_`{|}-'.split('')" ".every(ch=>/[\\]\\[!\"#$%&'()*+,.\\/:;<=>?@\\^_`{|}-]/.test(ch))"), nxt_string("true") }, @@ -12785,6 +12782,9 @@ static njs_unit_test_t njs_regexp_test[ { nxt_string("RegExp('[\\\\u0430-\\\\u044f]+').exec('????')[0]"), nxt_string("????") }, + + { nxt_string("/[\\uFDE0-\\uFFFD]/g; export default 1"), + nxt_string("SyntaxError: Illegal export statement in 1") }, }; From xeioex at nginx.com Thu May 30 14:14:49 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 30 May 2019 14:14:49 +0000 Subject: [njs] Fixed heap-buffer-overflow in toUpperCase() and toLowerCase(). Message-ID: details: https://hg.nginx.org/njs/rev/cc9a99f09b51 branches: changeset: 995:cc9a99f09b51 user: Dmitry Volyntsev date: Thu May 30 16:46:26 2019 +0300 description: Fixed heap-buffer-overflow in toUpperCase() and toLowerCase(). In String.prototype. This closes #162 issue on Github. diffstat: njs/njs_string.c | 18 ++++++++++-------- njs/test/njs_unit_test.c | 8 ++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diffs (76 lines): diff -r b6ecd0086ed3 -r cc9a99f09b51 njs/njs_string.c --- a/njs/njs_string.c Thu May 30 16:16:22 2019 +0300 +++ b/njs/njs_string.c Thu May 30 16:46:26 2019 +0300 @@ -2171,7 +2171,7 @@ static njs_ret_t njs_string_prototype_to_lower_case(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - size_t size; + size_t size, length; u_char *p, *start; const u_char *s, *end; njs_string_prop_t string; @@ -2198,10 +2198,11 @@ njs_string_prototype_to_lower_case(njs_v } else { /* UTF-8 string. */ end = s + size; - - while (size != 0) { + length = string.length; + + while (length != 0) { p = nxt_utf8_encode(p, nxt_utf8_lower_case(&s, end)); - size--; + length--; } } @@ -2219,7 +2220,7 @@ static njs_ret_t njs_string_prototype_to_upper_case(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - size_t size; + size_t size, length; u_char *p, *start; const u_char *s, *end; njs_string_prop_t string; @@ -2246,10 +2247,11 @@ njs_string_prototype_to_upper_case(njs_v } else { /* UTF-8 string. */ end = s + size; - - while (size != 0) { + length = string.length; + + while (length != 0) { p = nxt_utf8_encode(p, nxt_utf8_upper_case(&s, end)); - size--; + length--; } } diff -r b6ecd0086ed3 -r cc9a99f09b51 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 30 16:16:22 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu May 30 16:46:26 2019 +0300 @@ -5277,8 +5277,8 @@ static njs_unit_test_t njs_test[] = { nxt_string("'??? ??? ????????'.endsWith('?????', 14)"), nxt_string("false") }, - { nxt_string("'ABC'.toLowerCase()"), - nxt_string("abc") }, + { nxt_string("'\x00?????????'.toLowerCase().length"), + nxt_string("10") }, { nxt_string("'???'.toLowerCase()"), nxt_string("???") }, @@ -5292,8 +5292,8 @@ static njs_unit_test_t njs_test[] = { nxt_string("'???'.toUpperCase()"), nxt_string("???") }, - { nxt_string("'???'.toUpperCase()"), - nxt_string("???") }, + { nxt_string("'\x00?????????'.toUpperCase().length"), + nxt_string("10") }, { nxt_string("var a = [], code;" "for (code = 0; code <= 1114111; code++) {" From xeioex at nginx.com Fri May 31 12:12:06 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 31 May 2019 12:12:06 +0000 Subject: [njs] Fixed String.prototype.toBytes() for ASCII strings. Message-ID: details: https://hg.nginx.org/njs/rev/1041e3241457 branches: changeset: 996:1041e3241457 user: Dmitry Volyntsev date: Fri May 31 15:11:39 2019 +0300 description: Fixed String.prototype.toBytes() for ASCII strings. This closes #155 issue on Github. diffstat: njs/njs_string.c | 2 +- njs/test/njs_unit_test.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diffs (34 lines): diff -r cc9a99f09b51 -r 1041e3241457 njs/njs_string.c --- a/njs/njs_string.c Thu May 30 16:46:26 2019 +0300 +++ b/njs/njs_string.c Fri May 31 15:11:39 2019 +0300 @@ -1048,7 +1048,7 @@ njs_string_prototype_to_bytes(njs_vm_t * if (nxt_fast_path(p != NULL)) { - if (string.length != 0) { + if (string.length != string.size) { /* UTF-8 string. */ end = string.start + string.size; diff -r cc9a99f09b51 -r 1041e3241457 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu May 30 16:46:26 2019 +0300 +++ b/njs/test/njs_unit_test.c Fri May 31 15:11:39 2019 +0300 @@ -4644,6 +4644,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("'A'.repeat(16).toBytes() === 'A'.repeat(16)"), nxt_string("true") }, + { nxt_string("'A'.repeat(38).toBytes(-5) === 'AAAAA'"), + nxt_string("true") }, + + { nxt_string("('?' + 'A'.repeat(32)).toBytes()"), + nxt_string("null") }, + + { nxt_string("('?' + 'A'.repeat(32)).toBytes(1) === 'A'.repeat(32)"), + nxt_string("true") }, + + { nxt_string("('?' + 'A'.repeat(40)).toBytes(-3,-1)"), + nxt_string("AA") }, + { nxt_string("var s = 'x'.repeat(2**10).repeat(2**14);" "var a = Array(200).fill(s);" "String.prototype.concat.apply(s, a.slice(1))"),