[njs] Removed surplus condition from Base64 decoded length counting.

2021-10-26 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/264fb92817cd
branches:  
changeset: 1730:264fb92817cd
user:  Valentin Bartenev 
date:  Tue Oct 26 16:14:07 2021 +0300
description:
Removed surplus condition from Base64 decoded length counting.

diffstat:

 src/njs_string.c |  4 
 1 files changed, 0 insertions(+), 4 deletions(-)

diffs (14 lines):

diff -r b9bbb230fe4f -r 264fb92817cd src/njs_string.c
--- a/src/njs_string.c  Wed Oct 20 13:01:55 2021 +
+++ b/src/njs_string.c  Tue Oct 26 16:14:07 2021 +0300
@@ -1885,10 +1885,6 @@ njs_decode_base64_length_core(const njs_
 size_t  len;
 
 for (len = 0; len < src->length; len++) {
-if (src->start[len] == '=') {
-break;
-}
-
 if (basis[src->start[len]] == 77) {
 break;
 }
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Unicode case tables updated to version 14.0.0 (May 2021).

2021-07-09 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/36dd0370b121
branches:  
changeset: 1673:36dd0370b121
user:  Valentin Bartenev 
date:  Fri Jul 09 12:03:11 2021 +0300
description:
Unicode case tables updated to version 14.0.0 (May 2021).

diffstat:

 src/njs_unicode_lower_case.h |  60 ++-
 src/njs_unicode_upper_case.h |  36 +-
 src/njs_utf8.c   |   2 +-
 3 files changed, 82 insertions(+), 16 deletions(-)

diffs (184 lines):

diff -r 45c470a2d710 -r 36dd0370b121 src/njs_unicode_lower_case.h
--- a/src/njs_unicode_lower_case.h  Tue Jun 29 17:08:23 2021 +0300
+++ b/src/njs_unicode_lower_case.h  Fri Jul 09 12:03:11 2021 +0300
@@ -1,7 +1,7 @@
 
 /*
- * 33 128-bytes blocks, 979 pointers.
- * 20330 bytes on 32-bit platforms, 24242 bytes on 64-bit platforms.
+ * 35 128-bytes blocks, 979 pointers.
+ * 21354 bytes on 32-bit platforms, 25266 bytes on 64-bit platforms.
  */
 
 #define NJS_UNICODE_MAX_LOWER_CASE  0x1e921
@@ -457,7 +457,7 @@ static const uint32_t  njs_unicode_lower
 0x02c40, 0x02c41, 0x02c42, 0x02c43, 0x02c44, 0x02c45, 0x02c46, 0x02c47,
 0x02c48, 0x02c49, 0x02c4a, 0x02c4b, 0x02c4c, 0x02c4d, 0x02c4e, 0x02c4f,
 0x02c50, 0x02c51, 0x02c52, 0x02c53, 0x02c54, 0x02c55, 0x02c56, 0x02c57,
-0x02c58, 0x02c59, 0x02c5a, 0x02c5b, 0x02c5c, 0x02c5d, 0x02c5e, 0x02c2f,
+0x02c58, 0x02c59, 0x02c5a, 0x02c5b, 0x02c5c, 0x02c5d, 0x02c5e, 0x02c5f,
 0x02c30, 0x02c31, 0x02c32, 0x02c33, 0x02c34, 0x02c35, 0x02c36, 0x02c37,
 0x02c38, 0x02c39, 0x02c3a, 0x02c3b, 0x02c3c, 0x02c3d, 0x02c3e, 0x02c3f,
 0x02c40, 0x02c41, 0x02c42, 0x02c43, 0x02c44, 0x02c45, 0x02c46, 0x02c47,
@@ -570,10 +570,10 @@ static const uint32_t  njs_unicode_lower
 0x0a7a9, 0x0a7a9, 0x00266, 0x0025c, 0x00261, 0x0026c, 0x0026a, 0x0a7af,
 0x0029e, 0x00287, 0x0029d, 0x0ab53, 0x0a7b5, 0x0a7b5, 0x0a7b7, 0x0a7b7,
 0x0a7b9, 0x0a7b9, 0x0a7bb, 0x0a7bb, 0x0a7bd, 0x0a7bd, 0x0a7bf, 0x0a7bf,
-0x0a7c0, 0x0a7c1, 0x0a7c3, 0x0a7c3, 0x0a794, 0x00282, 0x01d8e, 0x0a7c8,
+0x0a7c1, 0x0a7c1, 0x0a7c3, 0x0a7c3, 0x0a794, 0x00282, 0x01d8e, 0x0a7c8,
 0x0a7c8, 0x0a7ca, 0x0a7ca, 0x0a7cb, 0x0a7cc, 0x0a7cd, 0x0a7ce, 0x0a7cf,
-0x0a7d0, 0x0a7d1, 0x0a7d2, 0x0a7d3, 0x0a7d4, 0x0a7d5, 0x0a7d6, 0x0a7d7,
-0x0a7d8, 0x0a7d9, 0x0a7da, 0x0a7db, 0x0a7dc, 0x0a7dd, 0x0a7de, 0x0a7df,
+0x0a7d1, 0x0a7d1, 0x0a7d2, 0x0a7d3, 0x0a7d4, 0x0a7d5, 0x0a7d7, 0x0a7d7,
+0x0a7d9, 0x0a7d9, 0x0a7da, 0x0a7db, 0x0a7dc, 0x0a7dd, 0x0a7de, 0x0a7df,
 0x0a7e0, 0x0a7e1, 0x0a7e2, 0x0a7e3, 0x0a7e4, 0x0a7e5, 0x0a7e6, 0x0a7e7,
 0x0a7e8, 0x0a7e9, 0x0a7ea, 0x0a7eb, 0x0a7ec, 0x0a7ed, 0x0a7ee, 0x0a7ef,
 0x0a7f0, 0x0a7f1, 0x0a7f2, 0x0a7f3, 0x0a7f4, 0x0a7f6, 0x0a7f6, 0x0a7f7,
@@ -647,6 +647,50 @@ static const uint32_t  njs_unicode_lower
 };
 
 
+static const uint32_t  njs_unicode_lower_case_block_20a[128]
+njs_aligned(64) =
+{
+0x10500, 0x10501, 0x10502, 0x10503, 0x10504, 0x10505, 0x10506, 0x10507,
+0x10508, 0x10509, 0x1050a, 0x1050b, 0x1050c, 0x1050d, 0x1050e, 0x1050f,
+0x10510, 0x10511, 0x10512, 0x10513, 0x10514, 0x10515, 0x10516, 0x10517,
+0x10518, 0x10519, 0x1051a, 0x1051b, 0x1051c, 0x1051d, 0x1051e, 0x1051f,
+0x10520, 0x10521, 0x10522, 0x10523, 0x10524, 0x10525, 0x10526, 0x10527,
+0x10528, 0x10529, 0x1052a, 0x1052b, 0x1052c, 0x1052d, 0x1052e, 0x1052f,
+0x10530, 0x10531, 0x10532, 0x10533, 0x10534, 0x10535, 0x10536, 0x10537,
+0x10538, 0x10539, 0x1053a, 0x1053b, 0x1053c, 0x1053d, 0x1053e, 0x1053f,
+0x10540, 0x10541, 0x10542, 0x10543, 0x10544, 0x10545, 0x10546, 0x10547,
+0x10548, 0x10549, 0x1054a, 0x1054b, 0x1054c, 0x1054d, 0x1054e, 0x1054f,
+0x10550, 0x10551, 0x10552, 0x10553, 0x10554, 0x10555, 0x10556, 0x10557,
+0x10558, 0x10559, 0x1055a, 0x1055b, 0x1055c, 0x1055d, 0x1055e, 0x1055f,
+0x10560, 0x10561, 0x10562, 0x10563, 0x10564, 0x10565, 0x10566, 0x10567,
+0x10568, 0x10569, 0x1056a, 0x1056b, 0x1056c, 0x1056d, 0x1056e, 0x1056f,
+0x10597, 0x10598, 0x10599, 0x1059a, 0x1059b, 0x1059c, 0x1059d, 0x1059e,
+0x1059f, 0x105a0, 0x105a1, 0x1057b, 0x105a3, 0x105a4, 0x105a5, 0x105a6,
+};
+
+
+static const uint32_t  njs_unicode_lower_case_block_20b[128]
+njs_aligned(64) =
+{
+0x105a7, 0x105a8, 0x105a9, 0x105aa, 0x105ab, 0x105ac, 0x105ad, 0x105ae,
+0x105af, 0x105b0, 0x105b1, 0x1058b, 0x105b3, 0x105b4, 0x105b5, 0x105b6,
+0x105b7, 0x105b8, 0x105b9, 0x10593, 0x105bb, 0x105bc, 0x10596, 0x10597,
+0x10598, 0x10599, 0x1059a, 0x1059b, 0x1059c, 0x1059d, 0x1059e, 0x1059f,
+0x105a0, 0x105a1, 0x105a2, 0x105a3, 0x105a4, 0x105a5, 0x105a6, 0x105a7,
+0x105a8, 0x105a9, 0x105aa, 0x105ab, 0x105ac, 0x105ad, 0x105ae, 0x105af,
+0x105b0, 0x105b1, 0x105b2, 0x105b3, 0x105b4, 0x105b5, 0x105b6, 0x105b7,
+0x105b8, 0x105b9, 0x105ba, 0x105bb, 0x105bc, 0x105bd, 0x105be, 0x105bf,
+0x105c0, 0x105c1, 0x105c2, 0x105c3, 0x105c4, 0x105c5, 0x105c6, 0x105c7,
+0x105c8, 0x105c9, 0x105ca, 0x105cb, 0x105cc, 0x105cd, 0x105ce

[njs] Ignoring pcre_study() error.

2020-11-20 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/e51da8c71f26
branches:  
changeset: 1569:e51da8c71f26
user:  Valentin Bartenev 
date:  Fri Nov 20 12:29:30 2020 +0300
description:
Ignoring pcre_study() error.

It provides optional optimization that shouldn't be fatal for regex compilation.

diffstat:

 src/njs_pcre.c |  4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diffs (15 lines):

diff -r c947a300b96c -r e51da8c71f26 src/njs_pcre.c
--- a/src/njs_pcre.cWed Nov 18 18:09:11 2020 +
+++ b/src/njs_pcre.cFri Nov 20 12:29:30 2020 +0300
@@ -94,10 +94,8 @@ njs_regex_compile(njs_regex_t *regex, u_
 regex->extra = pcre_study(regex->code, 0, );
 
 if (njs_slow_path(errstr != NULL)) {
-njs_alert(ctx->trace, NJS_LEVEL_ERROR,
+njs_alert(ctx->trace, NJS_LEVEL_WARN,
   "pcre_study(\"%s\") failed: %s", pattern, errstr);
-
-goto done;
 }
 
 err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_CAPTURECOUNT,
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added support for numeric separators (ES12).

2020-08-17 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/4818a450f4e6
branches:  
changeset: 1495:4818a450f4e6
user:  Valentin Bartenev 
date:  Mon Aug 17 19:55:46 2020 +0300
description:
Added support for numeric separators (ES12).

diffstat:

 src/njs_json.c   |2 +-
 src/njs_lexer.c  |   10 +++-
 src/njs_number.c |   42 +-
 src/njs_number.h |6 +-
 src/njs_parser.c |4 +-
 src/njs_string.c |6 +-
 src/njs_strtod.c |   36 +++-
 src/njs_strtod.h |3 +-
 src/test/njs_unit_test.c |  101 ++
 9 files changed, 173 insertions(+), 37 deletions(-)

diffs (518 lines):

diff -r 10a2c35d53e7 -r 4818a450f4e6 src/njs_json.c
--- a/src/njs_json.cMon Aug 17 14:44:29 2020 +0300
+++ b/src/njs_json.cMon Aug 17 19:55:46 2020 +0300
@@ -796,7 +796,7 @@ njs_json_parse_number(njs_json_parse_ctx
 }
 
 start = p;
-num = njs_number_dec_parse(, ctx->end);
+num = njs_number_dec_parse(, ctx->end, 0);
 if (p != start) {
 njs_set_number(value, sign * num);
 return p;
diff -r 10a2c35d53e7 -r 4818a450f4e6 src/njs_lexer.c
--- a/src/njs_lexer.c   Mon Aug 17 14:44:29 2020 +0300
+++ b/src/njs_lexer.c   Mon Aug 17 19:55:46 2020 +0300
@@ -787,7 +787,7 @@ njs_lexer_number(njs_lexer_t *lexer, njs
 goto illegal_token;
 }
 
-token->number = njs_number_hex_parse(, lexer->end);
+token->number = njs_number_hex_parse(, lexer->end, 1);
 
 goto done;
 }
@@ -830,16 +830,20 @@ njs_lexer_number(njs_lexer_t *lexer, njs
 
 /* Legacy Octal literals are deprecated. */
 
-if (*p >= '0' && *p <= '9') {
+if ((*p >= '0' && *p <= '9') || *p == '_') {
 goto illegal_trailer;
 }
 }
 
 p--;
-token->number = njs_number_dec_parse(, lexer->end);
+token->number = njs_number_dec_parse(, lexer->end, 1);
 
 done:
 
+if (p[-1] == '_') {
+p--;
+}
+
 lexer->start = (u_char *) p;
 token->text.length = p - token->text.start;
 
diff -r 10a2c35d53e7 -r 4818a450f4e6 src/njs_number.c
--- a/src/njs_number.c  Mon Aug 17 14:44:29 2020 +0300
+++ b/src/njs_number.c  Mon Aug 17 19:55:46 2020 +0300
@@ -54,9 +54,10 @@ njs_key_to_index(const njs_value_t *valu
 
 
 double
-njs_number_dec_parse(const u_char **start, const u_char *end)
+njs_number_dec_parse(const u_char **start, const u_char *end,
+njs_bool_t literal)
 {
-return njs_strtod(start, end);
+return njs_strtod(start, end, literal);
 }
 
 
@@ -65,22 +66,27 @@ njs_number_oct_parse(const u_char **star
 {
 u_charc;
 uint64_t  num;
-const u_char  *p;
+const u_char  *p, *_;
 
 p = *start;
 
 num = 0;
+_ = p - 1;
 
-while (p < end) {
+for (; p < end; p++) {
 /* Values less than '0' become >= 208. */
 c = *p - '0';
 
 if (njs_slow_path(c > 7)) {
+if (*p == '_' && (p - _) > 1) {
+_ = p;
+continue;
+}
+
 break;
 }
 
 num = num * 8 + c;
-p++;
 }
 
 *start = p;
@@ -94,22 +100,27 @@ njs_number_bin_parse(const u_char **star
 {
 u_charc;
 uint64_t  num;
-const u_char  *p;
+const u_char  *p, *_;
 
 p = *start;
 
 num = 0;
+_ = p - 1;
 
-while (p < end) {
+for (; p < end; p++) {
 /* Values less than '0' become >= 208. */
 c = *p - '0';
 
 if (njs_slow_path(c > 1)) {
+if (*p == '_' && (p - _) > 1) {
+_ = p;
+continue;
+}
+
 break;
 }
 
 num = num * 2 + c;
-p++;
 }
 
 *start = p;
@@ -119,24 +130,31 @@ njs_number_bin_parse(const u_char **star
 
 
 uint64_t
-njs_number_hex_parse(const u_char **start, const u_char *end)
+njs_number_hex_parse(const u_char **start, const u_char *end,
+njs_bool_t literal)
 {
 uint64_t  num;
 njs_int_t n;
-const u_char  *p;
+const u_char  *p, *_;
 
 p = *start;
 
 num = 0;
+_ = p - 1;
 
-while (p < end) {
+for (; p < end; p++) {
 n = njs_char_to_hex(*p);
+
 if (njs_slow_path(n < 0)) {
+if (literal && *p == '_' && (p - _) > 1) {
+_ = p;
+continue;
+}
+
 break;
 }
 
 num = num * 16 + n;
-p++;
 }
 
 *start = p;
diff -r 10a2c35d53e7 -r 4818a450f4e6 src/njs_number.h
--- a/src/njs_number.h  Mon Aug 17 14:44:29 2020 +0300
+++ b/src/njs_number.h  Mon Aug 17 19:55:46 2020 +0300
@@ -12,10 +12,12 @@
 
 
 double njs_key_to_index(const njs_value_t *value);
-double njs_number_dec_parse(const u_char **start, const u_char *end);
+double njs_number_dec_pa

[njs] Unicode case tables updated to version 13.0.0 (March 2020).

2020-08-17 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/10a2c35d53e7
branches:  
changeset: 1494:10a2c35d53e7
user:  Valentin Bartenev 
date:  Mon Aug 17 14:44:29 2020 +0300
description:
Unicode case tables updated to version 13.0.0 (March 2020).

diffstat:

 src/njs_unicode_lower_case.h |  6 +++---
 src/njs_unicode_upper_case.h |  4 ++--
 src/njs_utf8.c   |  2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diffs (50 lines):

diff -r eebf9e525358 -r 10a2c35d53e7 src/njs_unicode_lower_case.h
--- a/src/njs_unicode_lower_case.h  Mon Aug 17 11:22:35 2020 +
+++ b/src/njs_unicode_lower_case.h  Mon Aug 17 14:44:29 2020 +0300
@@ -570,13 +570,13 @@ static const uint32_t  njs_unicode_lower
 0x0a7a9, 0x0a7a9, 0x00266, 0x0025c, 0x00261, 0x0026c, 0x0026a, 0x0a7af,
 0x0029e, 0x00287, 0x0029d, 0x0ab53, 0x0a7b5, 0x0a7b5, 0x0a7b7, 0x0a7b7,
 0x0a7b9, 0x0a7b9, 0x0a7bb, 0x0a7bb, 0x0a7bd, 0x0a7bd, 0x0a7bf, 0x0a7bf,
-0x0a7c0, 0x0a7c1, 0x0a7c3, 0x0a7c3, 0x0a794, 0x00282, 0x01d8e, 0x0a7c7,
-0x0a7c8, 0x0a7c9, 0x0a7ca, 0x0a7cb, 0x0a7cc, 0x0a7cd, 0x0a7ce, 0x0a7cf,
+0x0a7c0, 0x0a7c1, 0x0a7c3, 0x0a7c3, 0x0a794, 0x00282, 0x01d8e, 0x0a7c8,
+0x0a7c8, 0x0a7ca, 0x0a7ca, 0x0a7cb, 0x0a7cc, 0x0a7cd, 0x0a7ce, 0x0a7cf,
 0x0a7d0, 0x0a7d1, 0x0a7d2, 0x0a7d3, 0x0a7d4, 0x0a7d5, 0x0a7d6, 0x0a7d7,
 0x0a7d8, 0x0a7d9, 0x0a7da, 0x0a7db, 0x0a7dc, 0x0a7dd, 0x0a7de, 0x0a7df,
 0x0a7e0, 0x0a7e1, 0x0a7e2, 0x0a7e3, 0x0a7e4, 0x0a7e5, 0x0a7e6, 0x0a7e7,
 0x0a7e8, 0x0a7e9, 0x0a7ea, 0x0a7eb, 0x0a7ec, 0x0a7ed, 0x0a7ee, 0x0a7ef,
-0x0a7f0, 0x0a7f1, 0x0a7f2, 0x0a7f3, 0x0a7f4, 0x0a7f5, 0x0a7f6, 0x0a7f7,
+0x0a7f0, 0x0a7f1, 0x0a7f2, 0x0a7f3, 0x0a7f4, 0x0a7f6, 0x0a7f6, 0x0a7f7,
 0x0a7f8, 0x0a7f9, 0x0a7fa, 0x0a7fb, 0x0a7fc, 0x0a7fd, 0x0a7fe, 0x0a7ff,
 };
 
diff -r eebf9e525358 -r 10a2c35d53e7 src/njs_unicode_upper_case.h
--- a/src/njs_unicode_upper_case.h  Mon Aug 17 11:22:35 2020 +
+++ b/src/njs_unicode_upper_case.h  Mon Aug 17 14:44:29 2020 +0300
@@ -681,12 +681,12 @@ static const uint32_t  njs_unicode_upper
 0x0a7b0, 0x0a7b1, 0x0a7b2, 0x0a7b3, 0x0a7b4, 0x0a7b4, 0x0a7b6, 0x0a7b6,
 0x0a7b8, 0x0a7b8, 0x0a7ba, 0x0a7ba, 0x0a7bc, 0x0a7bc, 0x0a7be, 0x0a7be,
 0x0a7c0, 0x0a7c1, 0x0a7c2, 0x0a7c2, 0x0a7c4, 0x0a7c5, 0x0a7c6, 0x0a7c7,
-0x0a7c8, 0x0a7c9, 0x0a7ca, 0x0a7cb, 0x0a7cc, 0x0a7cd, 0x0a7ce, 0x0a7cf,
+0x0a7c7, 0x0a7c9, 0x0a7c9, 0x0a7cb, 0x0a7cc, 0x0a7cd, 0x0a7ce, 0x0a7cf,
 0x0a7d0, 0x0a7d1, 0x0a7d2, 0x0a7d3, 0x0a7d4, 0x0a7d5, 0x0a7d6, 0x0a7d7,
 0x0a7d8, 0x0a7d9, 0x0a7da, 0x0a7db, 0x0a7dc, 0x0a7dd, 0x0a7de, 0x0a7df,
 0x0a7e0, 0x0a7e1, 0x0a7e2, 0x0a7e3, 0x0a7e4, 0x0a7e5, 0x0a7e6, 0x0a7e7,
 0x0a7e8, 0x0a7e9, 0x0a7ea, 0x0a7eb, 0x0a7ec, 0x0a7ed, 0x0a7ee, 0x0a7ef,
-0x0a7f0, 0x0a7f1, 0x0a7f2, 0x0a7f3, 0x0a7f4, 0x0a7f5, 0x0a7f6, 0x0a7f7,
+0x0a7f0, 0x0a7f1, 0x0a7f2, 0x0a7f3, 0x0a7f4, 0x0a7f5, 0x0a7f5, 0x0a7f7,
 0x0a7f8, 0x0a7f9, 0x0a7fa, 0x0a7fb, 0x0a7fc, 0x0a7fd, 0x0a7fe, 0x0a7ff,
 };
 
diff -r eebf9e525358 -r 10a2c35d53e7 src/njs_utf8.c
--- a/src/njs_utf8.cMon Aug 17 11:22:35 2020 +
+++ b/src/njs_utf8.cMon Aug 17 14:44:29 2020 +0300
@@ -9,7 +9,7 @@
 
 /*
  * The njs_unicode_lower_case.h and njs_unicode_upper_case.h files are
- * files auto-generated from the UnicodeData.txt file version 12.1.0 (May 2019)
+ * auto-generated from the UnicodeData.txt file version 13.0.0 (March 2020)
  * provided by Unicode, Inc.:
  *
  *   ./njs_unicode_lower_case.pl UnicodeData.txt
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Introduced nullish coalescing operator.

2019-12-23 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/9c1ef5ab7a1f
branches:  
changeset: 1284:9c1ef5ab7a1f
user:  Valentin Bartenev 
date:  Thu Dec 12 18:50:27 2019 +0300
description:
Introduced nullish coalescing operator.

diffstat:

 src/njs_disassembler.c  |  12 ++
 src/njs_generator.c |   1 +
 src/njs_lexer.c |  11 ++
 src/njs_lexer.h |   2 +
 src/njs_parser_expression.c |  81 +++-
 src/njs_vmcode.c|   9 +++-
 src/njs_vmcode.h|  26 +++--
 src/test/njs_unit_test.c|  17 +
 8 files changed, 142 insertions(+), 17 deletions(-)

diffs (262 lines):

diff -r 5bf71dfc052f -r 9c1ef5ab7a1f src/njs_disassembler.c
--- a/src/njs_disassembler.cWed Dec 11 15:58:05 2019 +0300
+++ b/src/njs_disassembler.cThu Dec 12 18:50:27 2019 +0300
@@ -282,6 +282,18 @@ njs_disassemble(u_char *start, u_char *e
 continue;
 }
 
+if (operation == NJS_VMCODE_COALESCE) {
+test_jump = (njs_vmcode_test_jump_t *) p;
+
+njs_printf("%05uz COALESCE  %04Xz %04Xz +%uz\n",
+   p - start, (size_t) test_jump->retval,
+   (size_t) test_jump->value, (size_t) test_jump->offset);
+
+p += sizeof(njs_vmcode_test_jump_t);
+
+continue;
+}
+
 if (operation == NJS_VMCODE_FUNCTION_FRAME) {
 function = (njs_vmcode_function_frame_t *) p;
 
diff -r 5bf71dfc052f -r 9c1ef5ab7a1f src/njs_generator.c
--- a/src/njs_generator.c   Wed Dec 11 15:58:05 2019 +0300
+++ b/src/njs_generator.c   Thu Dec 12 18:50:27 2019 +0300
@@ -361,6 +361,7 @@ njs_generate(njs_vm_t *vm, njs_generator
 
 case NJS_TOKEN_LOGICAL_AND:
 case NJS_TOKEN_LOGICAL_OR:
+case NJS_TOKEN_COALESCE:
 return njs_generate_test_jump_expression(vm, generator, node);
 
 case NJS_TOKEN_DELETE:
diff -r 5bf71dfc052f -r 9c1ef5ab7a1f src/njs_lexer.c
--- a/src/njs_lexer.c   Wed Dec 11 15:58:05 2019 +0300
+++ b/src/njs_lexer.c   Thu Dec 12 18:50:27 2019 +0300
@@ -276,6 +276,11 @@ static const njs_lexer_multi_t  njs_grea
 };
 
 
+static const njs_lexer_multi_t  njs_conditional_token[] = {
+{ '?', NJS_TOKEN_COALESCE, 0, NULL },
+};
+
+
 static const njs_lexer_multi_t  njs_assignment_token[] = {
 { '=', NJS_TOKEN_EQUAL, 1, njs_strict_equal_token },
 { '>', NJS_TOKEN_ARROW, 0, NULL },
@@ -551,6 +556,12 @@ njs_lexer_next_token(njs_lexer_t *lexer,
 
 goto multi;
 
+case NJS_TOKEN_CONDITIONAL:
+n = njs_nitems(njs_conditional_token),
+multi = njs_conditional_token;
+
+goto multi;
+
 case NJS_TOKEN_LINE_END:
 lexer->line++;
 
diff -r 5bf71dfc052f -r 9c1ef5ab7a1f src/njs_lexer.h
--- a/src/njs_lexer.h   Wed Dec 11 15:58:05 2019 +0300
+++ b/src/njs_lexer.h   Thu Dec 12 18:50:27 2019 +0300
@@ -95,6 +95,8 @@ typedef enum {
 NJS_TOKEN_BITWISE_NOT,
 NJS_TOKEN_LOGICAL_NOT,
 
+NJS_TOKEN_COALESCE,
+
 NJS_TOKEN_IN,
 NJS_TOKEN_INSTANCEOF,
 NJS_TOKEN_TYPEOF,
diff -r 5bf71dfc052f -r 9c1ef5ab7a1f src/njs_parser_expression.c
--- a/src/njs_parser_expression.c   Wed Dec 11 15:58:05 2019 +0300
+++ b/src/njs_parser_expression.c   Thu Dec 12 18:50:27 2019 +0300
@@ -41,6 +41,8 @@ static njs_token_t njs_parser_any_expres
 njs_token_t token);
 static njs_token_t njs_parser_conditional_expression(njs_vm_t *vm,
 njs_parser_t *parser, njs_token_t token);
+static njs_token_t njs_parser_coalesce_expression(njs_vm_t *vm,
+njs_parser_t *parser, njs_token_t token);
 static njs_token_t njs_parser_binary_expression(njs_vm_t *vm,
 njs_parser_t *parser, const njs_parser_expression_t *expr,
 njs_token_t token);
@@ -359,9 +361,7 @@ njs_parser_conditional_expression(njs_vm
 {
 njs_parser_node_t  *node, *cond;
 
-token = njs_parser_binary_expression(vm, parser,
- _parser_logical_or_expression,
- token);
+token = njs_parser_coalesce_expression(vm, parser, token);
 if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
 return token;
 }
@@ -421,6 +421,81 @@ njs_parser_conditional_expression(njs_vm
 
 
 static njs_token_t
+njs_parser_coalesce_expression(njs_vm_t *vm, njs_parser_t *parser,
+njs_token_t token)
+{
+njs_token_tprev_token, next_token;
+njs_parser_node_t  *node;
+
+token = njs_parser_binary_expression(vm, parser,
+ _parser_logical_or_expression,
+ token);
+if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+return token;
+}
+
+for ( ;; ) {
+if (token != NJS_TOKEN_COALESCE) {
+return token;
+}
+
+prev_token = parser->lexer->prev_token;
+
+node = njs_parser_node_new(vm, parser, NJS_TOKEN_COALESCE);
+ 

[njs] Date.prototype.toUTCString() format was aligned to ES9.

2019-09-28 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/5c22e2f006fe
branches:  
changeset: 1166:5c22e2f006fe
user:  Valentin Bartenev 
date:  Fri Sep 27 22:21:55 2019 +0300
description:
Date.prototype.toUTCString() format was aligned to ES9.

This closes #224 issue on GitHub.

diffstat:

 src/njs_date.c   |  12 +++-
 src/test/njs_unit_test.c |   4 ++--
 2 files changed, 9 insertions(+), 7 deletions(-)

diffs (57 lines):

diff -r f516c8332495 -r 5c22e2f006fe src/njs_date.c
--- a/src/njs_date.cThu Sep 19 10:19:02 2019 +0300
+++ b/src/njs_date.cFri Sep 27 22:21:55 2019 +0300
@@ -14,7 +14,9 @@
  *   FreeBSD and MacOSX timegm() cannot handle years before 1900.
  */
 
-#define NJS_ISO_DATE_TIME_LEN  sizeof("+001970-09-28T12:00:00.000Z")
+#define NJS_ISO_DATE_TIME_LEN   sizeof("+001970-09-28T12:00:00.000Z")
+
+#define NJS_HTTP_DATE_TIME_LEN  sizeof("Mon, 28 Sep 1970 12:00:00 GMT")
 
 #define NJS_DATE_TIME_LEN \
 sizeof("Mon Sep 28 1970 12:00:00 GMT+0600 (X)")
@@ -1009,7 +1011,7 @@ njs_date_prototype_to_utc_string(njs_vm_
 {
 double time;
 time_t clock;
-u_char buf[NJS_DATE_TIME_LEN], *p;
+u_char buf[NJS_HTTP_DATE_TIME_LEN], *p;
 struct tm  tm;
 
 static const char  *week[] = { "Sun", "Mon", "Tue", "Wed",
@@ -1024,9 +1026,9 @@ njs_date_prototype_to_utc_string(njs_vm_
 clock = time / 1000;
 gmtime_r(, );
 
-p = njs_sprintf(buf, buf + NJS_DATE_TIME_LEN,
-"%s %s %02d %4d %02d:%02d:%02d GMT",
-week[tm.tm_wday], month[tm.tm_mon], tm.tm_mday,
+p = njs_sprintf(buf, buf + NJS_HTTP_DATE_TIME_LEN,
+"%s, %02d %s %4d %02d:%02d:%02d GMT",
+week[tm.tm_wday], tm.tm_mday, month[tm.tm_mon],
 tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
 
 return njs_string_new(vm, >retval, buf, p - buf, p - buf);
diff -r f516c8332495 -r 5c22e2f006fe src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c  Thu Sep 19 10:19:02 2019 +0300
+++ b/src/test/njs_unit_test.c  Fri Sep 27 22:21:55 2019 +0300
@@ -11323,7 +11323,7 @@ static njs_unit_test_t  njs_test[] =
   njs_str("18:45:00 GMT+") },
 
 { njs_str("var d = new Date(2011, 5, 24, 18, 45); d.toUTCString()"),
-  njs_str("Fri Jun 24 2011 18:45:00 GMT") },
+  njs_str("Fri, 24 Jun 2011 18:45:00 GMT") },
 
 { njs_str("var d = new Date(2011, 5, 24, 18, 45, 12, 625);"
  "d.toISOString()"),
@@ -14074,7 +14074,7 @@ static njs_unit_test_t  njs_tz_test[] =
njs_str("18:45:00 GMT+1245") },
 
  { njs_str("var d = new Date(2011, 5, 24, 18, 45); d.toUTCString()"),
-   njs_str("Fri Jun 24 2011 06:00:00 GMT") },
+   njs_str("Fri, 24 Jun 2011 06:00:00 GMT") },
 
  { njs_str("var d = new Date(2011, 5, 24, 18, 45, 12, 625);"
   "d.toISOString()"),
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed undefined behaviour in left shift of negative numbers.

2019-07-28 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/6be62551e6d4
branches:  
changeset: 1081:6be62551e6d4
user:  Valentin Bartenev 
date:  Sun Jul 28 17:19:51 2019 +0300
description:
Fixed undefined behaviour in left shift of negative numbers.

Now it's implementation defined.

diffstat:

 njs/njs_vmcode.c |  3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diffs (13 lines):

diff -r 07989e97b198 -r 6be62551e6d4 njs/njs_vmcode.c
--- a/njs/njs_vmcode.c  Sun Jul 28 15:00:40 2019 +0300
+++ b/njs/njs_vmcode.c  Sun Jul 28 17:19:51 2019 +0300
@@ -421,7 +421,8 @@ next:
 i32 = njs_number_to_int32(num);
 
 if (op == NJS_VMCODE_LEFT_SHIFT) {
-i32 <<= u32;
+/* Shifting of negative numbers is undefined. */
+i32 = (uint32_t) i32 << u32;
 } else {
 i32 >>= u32;
 }
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Slight improvements to njs_vmcode_interpreter().

2019-07-28 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/07989e97b198
branches:  
changeset: 1080:07989e97b198
user:  Valentin Bartenev 
date:  Sun Jul 28 15:00:40 2019 +0300
description:
Slight improvements to njs_vmcode_interpreter().

No functional changes.

diffstat:

 njs/njs_vmcode.c |  26 +-
 1 files changed, 9 insertions(+), 17 deletions(-)

diffs (74 lines):

diff -r 258b1e34ca0f -r 07989e97b198 njs/njs_vmcode.c
--- a/njs/njs_vmcode.c  Sun Jul 28 13:19:03 2019 +0300
+++ b/njs/njs_vmcode.c  Sun Jul 28 15:00:40 2019 +0300
@@ -379,13 +379,7 @@ next:
   || (!isnan(exponent)
   && !isinf(exponent)));
 
-if (valid) {
-num = pow(num, exponent);
-
-} else {
-num = NAN;
-}
-
+num = valid ? pow(num, exponent) : NAN;
 break;
 
 case NJS_VMCODE_DIVISION:
@@ -399,19 +393,19 @@ next:
 case NJS_VMCODE_BITWISE_AND:
 case NJS_VMCODE_BITWISE_OR:
 case NJS_VMCODE_BITWISE_XOR:
-i32 = njs_number_to_int32(num);
+i32 = njs_number_to_int32(njs_number(value2));
 
 switch (op) {
 case NJS_VMCODE_BITWISE_AND:
-i32 = i32 & njs_number_to_int32(njs_number(value2));
+i32 &= njs_number_to_int32(num);
 break;
 
 case NJS_VMCODE_BITWISE_OR:
-i32 = i32 | njs_number_to_int32(njs_number(value2));
+i32 |= njs_number_to_int32(num);
 break;
 
 case NJS_VMCODE_BITWISE_XOR:
-i32 = i32 ^ njs_number_to_int32(njs_number(value2));
+i32 ^= njs_number_to_int32(num);
 break;
 }
 
@@ -419,7 +413,7 @@ next:
 goto next;
 
 default:
-u32 = njs_number_to_uint32(njs_number(value2));
+u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f;
 
 switch (op) {
 case NJS_VMCODE_LEFT_SHIFT:
@@ -427,19 +421,17 @@ next:
 i32 = njs_number_to_int32(num);
 
 if (op == NJS_VMCODE_LEFT_SHIFT) {
-i32 <<= u32 & 0x1f;
+i32 <<= u32;
 } else {
-i32 >>= u32 & 0x1f;
+i32 >>= u32;
 }
 
 njs_set_int32(retval, i32);
-
 break;
 
 default: /* NJS_VMCODE_UNSIGNED_RIGHT_SHIFT */
 njs_set_uint32(retval,
-   njs_number_to_uint32(num)
-   >> (u32 & 0x1f));
+   njs_number_to_uint32(num) >> u32);
 }
 
 goto next;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added String.prototype.trimStrart() and String.prototype.trimEnd().

2019-07-28 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/258b1e34ca0f
branches:  
changeset: 1079:258b1e34ca0f
user:  Valentin Bartenev 
date:  Sun Jul 28 13:19:03 2019 +0300
description:
Added String.prototype.trimStrart() and String.prototype.trimEnd().

diffstat:

 njs/njs_string.c |  248 --
 njs/test/njs_unit_test.c |   12 +-
 nxt/nxt_string.h |   19 +++
 nxt/nxt_utf8.h   |   37 +++
 4 files changed, 189 insertions(+), 127 deletions(-)

diffs (424 lines):

diff -r ac39f4c902b5 -r 258b1e34ca0f njs/njs_string.c
--- a/njs/njs_string.c  Sun Jul 28 13:17:13 2019 +0300
+++ b/njs/njs_string.c  Sun Jul 28 13:19:03 2019 +0300
@@ -10,6 +10,10 @@
 #include 
 
 
+#define NJS_TRIM_START  1
+#define NJS_TRIM_END2
+
+
 typedef struct {
 u_char *start;
 size_t size;
@@ -68,6 +72,8 @@ static njs_ret_t njs_string_bytes_from_s
 const njs_value_t *args, nxt_uint_t nargs);
 static njs_ret_t njs_string_starts_or_ends_with(njs_vm_t *vm, njs_value_t 
*args,
 nxt_uint_t nargs, nxt_bool_t starts);
+static njs_ret_t njs_string_trim(njs_vm_t *vm, njs_value_t *value,
+nxt_uint_t mode);
 static njs_ret_t njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args,
 nxt_uint_t nargs, nxt_bool_t pad_start);
 static njs_ret_t njs_string_match_multiple(njs_vm_t *vm, njs_value_t *args,
@@ -2356,158 +2362,138 @@ static njs_ret_t
 njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
+return njs_string_trim(vm, [0], NJS_TRIM_START|NJS_TRIM_END);
+}
+
+
+static njs_ret_t
+njs_string_prototype_trim_start(njs_vm_t *vm, njs_value_t *args,
+nxt_uint_t nargs, njs_index_t unused)
+{
+return njs_string_trim(vm, [0], NJS_TRIM_START);
+}
+
+
+static njs_ret_t
+njs_string_prototype_trim_end(njs_vm_t *vm, njs_value_t *args,
+nxt_uint_t nargs, njs_index_t unused)
+{
+return njs_string_trim(vm, [0], NJS_TRIM_END);
+}
+
+
+static njs_ret_t
+njs_string_trim(njs_vm_t *vm, njs_value_t *value, nxt_uint_t mode)
+{
 uint32_t   u, trim, length;
 const u_char   *p, *prev, *start, *end;
 njs_string_prop_t  string;
 
 trim = 0;
 
-njs_string_prop(, [0]);
-
-p = string.start;
+njs_string_prop(, value);
+
+start = string.start;
 end = string.start + string.size;
 
 if (string.length == 0 || string.length == string.size) {
 /* Byte or ASCII string. */
 
-while (p < end) {
-
-switch (*p) {
-case 0x09:  /*   */
-case 0x0A:  /**/
-case 0x0B:  /**/
-case 0x0C:  /**/
-case 0x0D:  /**/
-case 0x20:  /**/
-case 0xA0:  /*  */
-trim++;
-p++;
-continue;
-
-default:
-start = p;
-p = end;
-
-for ( ;; ) {
-p--;
-
-switch (*p) {
-case 0x09:  /*   */
-case 0x0A:  /**/
-case 0x0B:  /**/
-case 0x0C:  /**/
-case 0x0D:  /**/
-case 0x20:  /**/
-case 0xA0:  /*  */
-trim++;
-continue;
-
-default:
-p++;
-goto done;
-}
+if (mode & NJS_TRIM_START) {
+for ( ;; ) {
+if (start == end) {
+goto empty;
+}
+
+if (nxt_is_whitespace(*start)) {
+start++;
+trim++;
+continue;
 }
+
+break;
+}
+}
+
+if (mode & NJS_TRIM_END) {
+for ( ;; ) {
+if (start == end) {
+goto empty;
+}
+
+end--;
+
+if (nxt_is_whitespace(*end)) {
+trim++;
+continue;
+}
+
+end++;
+break;
 }
 }
 
 } else {
 /* UTF-8 string. */
 
-while (p < end) {
-prev = p;
-u = nxt_utf8_decode(, end);
-
-switch (u) {
-case 0x0009:  /*   */
-case 0x000A:  /**/
-case 0x000B:  /**/
-case 0x000C:  /**/
-case 0x000D:  /**/
-case 0x0020:  /**/
-case 0x00A0:  /*  */
-case 0x1680:
-case 0x2000:
-case 0x2001:
-case 0x2002:
-case 0x2003:
-case 0x2004:
-case 0x2005:
-case 0x2006:
-case 0x2007:
-case 0x2008:
-case 0x2009:
- 

[njs] Updated the list of space separators in String.prototype.trim().

2019-07-28 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/ac39f4c902b5
branches:  
changeset: 1078:ac39f4c902b5
user:  Valentin Bartenev 
date:  Sun Jul 28 13:17:13 2019 +0300
description:
Updated the list of space separators in String.prototype.trim().

According to the specification it must include all Unicode code points listed
in the "Space_Separator" (Zs) category.

diffstat:

 njs/njs_string.c |  30 ++
 njs/test/njs_unit_test.c |  10 ++
 2 files changed, 40 insertions(+), 0 deletions(-)

diffs (71 lines):

diff -r 575c018f2206 -r ac39f4c902b5 njs/njs_string.c
--- a/njs/njs_string.c  Sat Jul 27 21:12:32 2019 +0300
+++ b/njs/njs_string.c  Sun Jul 28 13:17:13 2019 +0300
@@ -2425,8 +2425,23 @@ njs_string_prototype_trim(njs_vm_t *vm, 
 case 0x000D:  /**/
 case 0x0020:  /**/
 case 0x00A0:  /*  */
+case 0x1680:
+case 0x2000:
+case 0x2001:
+case 0x2002:
+case 0x2003:
+case 0x2004:
+case 0x2005:
+case 0x2006:
+case 0x2007:
+case 0x2008:
+case 0x2009:
+case 0x200A:
 case 0x2028:  /**/
 case 0x2029:  /**/
+case 0x202F:
+case 0x205F:
+case 0x3000:
 case 0xFEFF:  /*   */
 trim++;
 continue;
@@ -2448,8 +2463,23 @@ njs_string_prototype_trim(njs_vm_t *vm, 
 case 0x000D:  /**/
 case 0x0020:  /**/
 case 0x00A0:  /*  */
+case 0x1680:
+case 0x2000:
+case 0x2001:
+case 0x2002:
+case 0x2003:
+case 0x2004:
+case 0x2005:
+case 0x2006:
+case 0x2007:
+case 0x2008:
+case 0x2009:
+case 0x200A:
 case 0x2028:  /**/
 case 0x2029:  /**/
+case 0x202F:
+case 0x205F:
+case 0x3000:
 case 0xFEFF:  /*   */
 trim++;
 continue;
diff -r 575c018f2206 -r ac39f4c902b5 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sat Jul 27 21:12:32 2019 +0300
+++ b/njs/test/njs_unit_test.c  Sun Jul 28 13:17:13 2019 +0300
@@ -5653,6 +5653,16 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("'\\u2029abc\\uFEFF\\u2028'.trim()"),
   nxt_string("abc") },
 
+#if (!NXT_HAVE_MEMORY_SANITIZER) /* very long test under MSAN */
+{ nxt_string("var a = [], code;"
+ "for (code = 0; code <= 1114111; code++) {"
+ "var ws = String.fromCodePoint(code);"
+ "if ((ws + '-' + ws).trim() === '-')"
+ "a.push(code);"
+ "} a"),
+  
nxt_string("9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279")
 },
+#endif
+
 { nxt_string("'abcdefgh'.search()"),
   nxt_string("0") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed String.fromCodePoint(), broken after 0b82f1c9268c.

2019-07-27 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/575c018f2206
branches:  
changeset: 1077:575c018f2206
user:  Valentin Bartenev 
date:  Sat Jul 27 21:12:32 2019 +0300
description:
Fixed String.fromCodePoint(), broken after 0b82f1c9268c.

As it turned out, fromCodePoint() has shared the same handler with
fromCharCode(), but according to the specification these functions
have different semantics.  As a result, before 0b82f1c9268c both
functions had behaviour of fromCodePoint(), while after the change
they had behaviour of fromCharCode().

So, the fix is to revert back the code used before the change,
but only for fromCodePoint().

diffstat:

 njs/njs_string.c |  60 +++-
 njs/test/njs_unit_test.c |  44 ---
 2 files changed, 94 insertions(+), 10 deletions(-)

diffs (174 lines):

diff -r cba3bd29f263 -r 575c018f2206 njs/njs_string.c
--- a/njs/njs_string.c  Sat Jul 27 17:03:02 2019 +0300
+++ b/njs/njs_string.c  Sat Jul 27 21:12:32 2019 +0300
@@ -58,6 +58,8 @@ static void njs_string_slice_args(njs_sl
 nxt_uint_t nargs);
 static njs_ret_t njs_string_from_char_code(njs_vm_t *vm,
 njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
+static njs_ret_t njs_string_from_code_point(njs_vm_t *vm, njs_value_t *args,
+nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t njs_string_bytes_from(njs_vm_t *vm, njs_value_t *args,
 nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t njs_string_bytes_from_array(njs_vm_t *vm,
@@ -608,7 +610,7 @@ static const njs_object_prop_t  njs_stri
 {
 .type = NJS_METHOD,
 .name = njs_string("fromCodePoint"),
-.value = njs_native_function(njs_string_from_char_code, 0),
+.value = njs_native_function(njs_string_from_code_point, 0),
 .writable = 1,
 .configurable = 1,
 },
@@ -1730,6 +1732,62 @@ njs_string_from_char_code(njs_vm_t *vm, 
 
 
 static njs_ret_t
+njs_string_from_code_point(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+u_char  *p;
+double  num;
+size_t  size;
+int32_t code;
+njs_ret_t   ret;
+nxt_uint_t  i;
+
+for (i = 1; i < nargs; i++) {
+if (!njs_is_numeric([i])) {
+ret = njs_value_to_numeric(vm, [i], [i]);
+if (ret != NXT_OK) {
+return ret;
+}
+}
+}
+
+size = 0;
+
+for (i = 1; i < nargs; i++) {
+num = njs_number([i]);
+if (isnan(num)) {
+goto range_error;
+}
+
+code = num;
+
+if (code != num || code < 0 || code >= 0x11) {
+goto range_error;
+}
+
+size += nxt_utf8_size(code);
+}
+
+p = njs_string_alloc(vm, >retval, size, nargs - 1);
+if (nxt_slow_path(p == NULL)) {
+return NXT_ERROR;
+}
+
+for (i = 1; i < nargs; i++) {
+p = nxt_utf8_encode(p, njs_number([i]));
+}
+
+return NXT_OK;
+
+range_error:
+
+njs_range_error(vm, NULL);
+
+return NXT_ERROR;
+}
+
+
+static njs_ret_t
 njs_string_prototype_index_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t 
nargs,
 njs_index_t unused)
 {
diff -r cba3bd29f263 -r 575c018f2206 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sat Jul 27 17:03:02 2019 +0300
+++ b/njs/test/njs_unit_test.c  Sat Jul 27 21:12:32 2019 +0300
@@ -5348,20 +5348,32 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("String.fromCharCode('_').charCodeAt(0)"),
   nxt_string("0") },
 
+{ nxt_string("String.fromCodePoint('_')"),
+  nxt_string("RangeError") },
+
 { nxt_string("String.fromCharCode(65.14)"),
   nxt_string("A") },
 
+{ nxt_string("String.fromCodePoint(3.14)"),
+  nxt_string("RangeError") },
+
 { nxt_string("String.fromCharCode(65.14 + 65536)"),
   nxt_string("A") },
 
+{ nxt_string("String.fromCodePoint(65 + 65536)"),
+  nxt_string("A") },
+
 { nxt_string("String.fromCharCode(2**53 + 10)"),
   nxt_string("\n") },
 
-{ nxt_string("String.fromCharCode(65, 90)"),
-  nxt_string("AZ") },
-
-{ nxt_string("String.fromCharCode(945, 946, 947)"),
-  nxt_string("αβγ") },
+{ nxt_string("String.fromCodePoint(1114111 + 1)"),
+  nxt_string("RangeError") },
+
+{ nxt_string("String.fromCharCode(65, 90) + String.fromCodePoint(65, 90)"),
+  nxt_string("AZAZ") },
+
+{ nxt_string("String.fromCharCode(945, 946, 947) + 
String.fromCodePoint(945, 946, 947)"),
+  nxt_string("αβγαβγ") },
 
 { nxt_string("(function() {"
  "var n;"
@@ -5373,6 +5385,18 @@ static njs_unit_test_t  njs_test[] =
  "})()"

[njs] Fixed String.toLowerCase() and String.toUpperCase().

2019-07-27 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/cba3bd29f263
branches:  
changeset: 1076:cba3bd29f263
user:  Valentin Bartenev 
date:  Sat Jul 27 17:03:02 2019 +0300
description:
Fixed String.toLowerCase() and String.toUpperCase().

Previously these functions didn't took into account that the size of
a string may change during case transformation resulting in buffer
underflow or overflow.

diffstat:

 njs/njs_string.c |  88 +--
 njs/test/njs_unit_test.c |  11 -
 2 files changed, 71 insertions(+), 28 deletions(-)

diffs (176 lines):

diff -r 0b82f1c9268c -r cba3bd29f263 njs/njs_string.c
--- a/njs/njs_string.c  Sat Jul 27 16:12:26 2019 +0300
+++ b/njs/njs_string.c  Sat Jul 27 17:03:02 2019 +0300
@@ -2171,24 +2171,24 @@ njs_string_prototype_to_lower_case(njs_v
 nxt_uint_t nargs, njs_index_t unused)
 {
 size_t size, length;
-u_char *p, *start;
+u_char *p;
+uint32_t   code;
 const u_char   *s, *end;
 njs_string_prop_t  string;
 
 (void) njs_string_prop(, [0]);
 
-start = njs_string_alloc(vm, >retval, string.size, string.length);
-if (nxt_slow_path(start == NULL)) {
-return NXT_ERROR;
-}
-
-p = start;
-s = string.start;
-size = string.size;
-
-if (string.length == 0 || string.length == size) {
+if (string.length == 0 || string.length == string.size) {
 /* Byte or ASCII string. */
 
+p = njs_string_alloc(vm, >retval, string.size, string.length);
+if (nxt_slow_path(p == NULL)) {
+return NXT_ERROR;
+}
+
+s = string.start;
+size = string.size;
+
 while (size != 0) {
 *p++ = nxt_lower_case(*s++);
 size--;
@@ -2196,11 +2196,29 @@ njs_string_prototype_to_lower_case(njs_v
 
 } else {
 /* UTF-8 string. */
-end = s + size;
+s = string.start;
+end = s + string.size;
+length = string.length;
+
+size = 0;
+
+while (length != 0) {
+code = nxt_utf8_lower_case(, end);
+size += nxt_utf8_size(code);
+length--;
+}
+
+p = njs_string_alloc(vm, >retval, size, string.length);
+if (nxt_slow_path(p == NULL)) {
+return NXT_ERROR;
+}
+
+s = string.start;
 length = string.length;
 
 while (length != 0) {
-p = nxt_utf8_encode(p, nxt_utf8_lower_case(, end));
+code = nxt_utf8_lower_case(, end);
+p = nxt_utf8_encode(p, code);
 length--;
 }
 }
@@ -2220,24 +2238,24 @@ njs_string_prototype_to_upper_case(njs_v
 nxt_uint_t nargs, njs_index_t unused)
 {
 size_t size, length;
-u_char *p, *start;
+u_char *p;
+uint32_t   code;
 const u_char   *s, *end;
 njs_string_prop_t  string;
 
 (void) njs_string_prop(, [0]);
 
-start = njs_string_alloc(vm, >retval, string.size, string.length);
-if (nxt_slow_path(start == NULL)) {
-return NXT_ERROR;
-}
-
-p = start;
-s = string.start;
-size = string.size;
-
-if (string.length == 0 || string.length == size) {
+if (string.length == 0 || string.length == string.size) {
 /* Byte or ASCII string. */
 
+p = njs_string_alloc(vm, >retval, string.size, string.length);
+if (nxt_slow_path(p == NULL)) {
+return NXT_ERROR;
+}
+
+s = string.start;
+size = string.size;
+
 while (size != 0) {
 *p++ = nxt_upper_case(*s++);
 size--;
@@ -2245,11 +2263,29 @@ njs_string_prototype_to_upper_case(njs_v
 
 } else {
 /* UTF-8 string. */
-end = s + size;
+s = string.start;
+end = s + string.size;
+length = string.length;
+
+size = 0;
+
+while (length != 0) {
+code = nxt_utf8_upper_case(, end);
+size += nxt_utf8_size(code);
+length--;
+}
+
+p = njs_string_alloc(vm, >retval, size, string.length);
+if (nxt_slow_path(p == NULL)) {
+return NXT_ERROR;
+}
+
+s = string.start;
 length = string.length;
 
 while (length != 0) {
-p = nxt_utf8_encode(p, nxt_utf8_upper_case(, end));
+code = nxt_utf8_upper_case(, end);
+p = nxt_utf8_encode(p, code);
 length--;
 }
 }
diff -r 0b82f1c9268c -r cba3bd29f263 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sat Jul 27 16:12:26 2019 +0300
+++ b/njs/test/njs_unit_test.c  Sat Jul 27 17:03:02 2019 +0300
@@ -5561,16 +5561,24 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("'АБВ'.toLowerCase()"),
   nxt_string("абв") },
 
+{ nxt_string("'Ȿ'.repeat(256).toLowerCase() === 'ȿ'.repeat(256)"),
+  nxt_string("true") },
+
 

[njs] Fixed String.fromCharCode() for code points > 65535 and NaN.

2019-07-27 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/0b82f1c9268c
branches:  
changeset: 1075:0b82f1c9268c
user:  Valentin Bartenev 
date:  Sat Jul 27 16:12:26 2019 +0300
description:
Fixed String.fromCharCode() for code points > 65535 and NaN.

According to the specification the code units must be truncated to uint16.

diffstat:

 njs/njs_number.h|   7 +++
 njs/njs_string.c|  26 +-
 njs/test/njs_interactive_test.c |   4 ++--
 njs/test/njs_unit_test.c|  28 +++-
 nxt/nxt_utf8.h  |   4 
 5 files changed, 33 insertions(+), 36 deletions(-)

diffs (172 lines):

diff -r ab9fc6079788 -r 0b82f1c9268c njs/njs_number.h
--- a/njs/njs_number.h  Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/njs_number.h  Sat Jul 27 16:12:26 2019 +0300
@@ -86,6 +86,13 @@ njs_number_to_uint32(double num)
 }
 
 
+nxt_inline uint16_t
+njs_number_to_uint16(double num)
+{
+return (uint16_t) njs_number_to_int64(num);
+}
+
+
 nxt_inline uint32_t
 njs_number_to_length(double num)
 {
diff -r ab9fc6079788 -r 0b82f1c9268c njs/njs_string.c
--- a/njs/njs_string.c  Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/njs_string.c  Sat Jul 27 16:12:26 2019 +0300
@@ -1694,9 +1694,8 @@ njs_string_from_char_code(njs_vm_t *vm, 
 nxt_uint_t nargs, njs_index_t unused)
 {
 u_char  *p;
-double  num;
 size_t  size;
-int32_t code;
+uint16_tcode;
 njs_ret_t   ret;
 nxt_uint_t  i;
 
@@ -1712,18 +1711,8 @@ njs_string_from_char_code(njs_vm_t *vm, 
 size = 0;
 
 for (i = 1; i < nargs; i++) {
-num = njs_number([i]);
-if (isnan(num)) {
-goto range_error;
-}
-
-code = num;
-
-if (code != num || code < 0 || code >= 0x11) {
-goto range_error;
-}
-
-size += nxt_utf8_size(code);
+code = njs_number_to_uint16(njs_number([i]));
+size += nxt_utf8_size_uint16(code);
 }
 
 p = njs_string_alloc(vm, >retval, size, nargs - 1);
@@ -1732,16 +1721,11 @@ njs_string_from_char_code(njs_vm_t *vm, 
 }
 
 for (i = 1; i < nargs; i++) {
-p = nxt_utf8_encode(p, njs_number([i]));
+code = njs_number_to_uint16(njs_number([i]));
+p = nxt_utf8_encode(p, code);
 }
 
 return NXT_OK;
-
-range_error:
-
-njs_range_error(vm, NULL);
-
-return NXT_ERROR;
 }
 
 
diff -r ab9fc6079788 -r 0b82f1c9268c njs/test/njs_interactive_test.c
--- a/njs/test/njs_interactive_test.c   Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/test/njs_interactive_test.c   Sat Jul 27 16:12:26 2019 +0300
@@ -149,9 +149,9 @@ static njs_interactive_test_t  njs_test[
  "at f (:1)\n"
  "at main (native)\n") },
 
-{ nxt_string("String.fromCharCode(3.14)" ENTER),
+{ nxt_string("''.repeat(-1)" ENTER),
   nxt_string("RangeError\n"
- "at String.fromCharCode (native)\n"
+ "at String.prototype.repeat (native)\n"
  "at main (native)\n") },
 
 { nxt_string("Math.log({}.a.a)" ENTER),
diff -r ab9fc6079788 -r 0b82f1c9268c njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/test/njs_unit_test.c  Sat Jul 27 16:12:26 2019 +0300
@@ -5345,11 +5345,17 @@ static njs_unit_test_t  njs_test[] =
  " .length; a"),
   nxt_string("5") },
 
-{ nxt_string("String.fromCharCode('_')"),
-  nxt_string("RangeError") },
-
-{ nxt_string("String.fromCharCode(3.14)"),
-  nxt_string("RangeError") },
+{ nxt_string("String.fromCharCode('_').charCodeAt(0)"),
+  nxt_string("0") },
+
+{ nxt_string("String.fromCharCode(65.14)"),
+  nxt_string("A") },
+
+{ nxt_string("String.fromCharCode(65.14 + 65536)"),
+  nxt_string("A") },
+
+{ nxt_string("String.fromCharCode(2**53 + 10)"),
+  nxt_string("\n") },
 
 { nxt_string("String.fromCharCode(65, 90)"),
   nxt_string("AZ") },
@@ -5357,17 +5363,15 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("String.fromCharCode(945, 946, 947)"),
   nxt_string("αβγ") },
 
-#if (!NXT_HAVE_MEMORY_SANITIZER) /* very long test under MSAN */
 { nxt_string("(function() {"
  "var n;"
- "for (n = 0; n <= 1114111; n++) {"
+ "for (n = 0; n <= 65536; n++) {"
  "if (String.fromCharCode(n).charCodeAt(0) !== n)"
  "return n;"
  "}"
  "return -1"
  "})()"),
- 

[njs] Unicode case tables updated to version 12.1 (May 2019).

2019-07-26 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/dace17533126
branches:  
changeset: 1072:dace17533126
user:  Valentin Bartenev 
date:  Sat Jul 27 03:51:48 2019 +0300
description:
Unicode case tables updated to version 12.1 (May 2019).

diffstat:

 njs/test/njs_unit_test.c |2 +-
 nxt/nxt_unicode_lower_case.h |  676 +++-
 nxt/nxt_unicode_upper_case.h |  789 --
 nxt/nxt_utf8.c   |2 +-
 4 files changed, 1390 insertions(+), 79 deletions(-)

diffs (truncated from 1674 to 1000 lines):

diff -r 0af076f81e2b -r dace17533126 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sat Jul 27 03:51:48 2019 +0300
+++ b/njs/test/njs_unit_test.c  Sat Jul 27 03:51:48 2019 +0300
@@ -,7 +,7 @@ static njs_unit_test_t  njs_test[] =
  "if (s != n && s != n.toLowerCase())"
  "a.push(code);"
  "} a"),
-  
nxt_string("181,305,383,453,456,459,498,837,962,976,977,981,982,1008,1009,1013,7835,8126")
 },
+  
nxt_string("181,305,383,453,456,459,498,837,962,976,977,981,982,1008,1009,1013,7296,7297,7298,7299,7300,7301,7302,7303,7304,7835,8126")
 },
 
 { nxt_string("var a = [], code;"
  "for (code = 0; code <= 1114111; code++) {"
diff -r 0af076f81e2b -r dace17533126 nxt/nxt_unicode_lower_case.h
--- a/nxt/nxt_unicode_lower_case.h  Sat Jul 27 03:51:48 2019 +0300
+++ b/nxt/nxt_unicode_lower_case.h  Sat Jul 27 03:51:48 2019 +0300
@@ -1,10 +1,10 @@
 
 /*
- * 26 128-bytes blocks, 521 pointers.
- * 14920 bytes on 32-bit platforms, 17000 bytes on 64-bit platforms.
+ * 33 128-bytes blocks, 979 pointers.
+ * 20330 bytes on 32-bit platforms, 24242 bytes on 64-bit platforms.
  */
 
-#define NXT_UNICODE_MAX_LOWER_CASE  0x10427
+#define NXT_UNICODE_MAX_LOWER_CASE  0x1e921
 
 #define NXT_UNICODE_BLOCK_SIZE  128
 
@@ -137,7 +137,7 @@ static const uint32_t  nxt_unicode_lower
 0x00360, 0x00361, 0x00362, 0x00363, 0x00364, 0x00365, 0x00366, 0x00367,
 0x00368, 0x00369, 0x0036a, 0x0036b, 0x0036c, 0x0036d, 0x0036e, 0x0036f,
 0x00371, 0x00371, 0x00373, 0x00373, 0x00374, 0x00375, 0x00377, 0x00377,
-0x00378, 0x00379, 0x0037a, 0x0037b, 0x0037c, 0x0037d, 0x0037e, 0x0037f,
+0x00378, 0x00379, 0x0037a, 0x0037b, 0x0037c, 0x0037d, 0x0037e, 0x003f3,
 };
 
 
@@ -215,7 +215,7 @@ static const uint32_t  nxt_unicode_lower
 0x00511, 0x00511, 0x00513, 0x00513, 0x00515, 0x00515, 0x00517, 0x00517,
 0x00519, 0x00519, 0x0051b, 0x0051b, 0x0051d, 0x0051d, 0x0051f, 0x0051f,
 0x00521, 0x00521, 0x00523, 0x00523, 0x00525, 0x00525, 0x00527, 0x00527,
-0x00528, 0x00529, 0x0052a, 0x0052b, 0x0052c, 0x0052d, 0x0052e, 0x0052f,
+0x00529, 0x00529, 0x0052b, 0x0052b, 0x0052d, 0x0052d, 0x0052f, 0x0052f,
 0x00530, 0x00561, 0x00562, 0x00563, 0x00564, 0x00565, 0x00566, 0x00567,
 0x00568, 0x00569, 0x0056a, 0x0056b, 0x0056c, 0x0056d, 0x0056e, 0x0056f,
 0x00570, 0x00571, 0x00572, 0x00573, 0x00574, 0x00575, 0x00576, 0x00577,
@@ -251,6 +251,50 @@ static const uint32_t  nxt_unicode_lower
 };
 
 
+static const uint32_t  nxt_unicode_lower_case_block_027[128]
+nxt_aligned(64) =
+{
+0x01380, 0x01381, 0x01382, 0x01383, 0x01384, 0x01385, 0x01386, 0x01387,
+0x01388, 0x01389, 0x0138a, 0x0138b, 0x0138c, 0x0138d, 0x0138e, 0x0138f,
+0x01390, 0x01391, 0x01392, 0x01393, 0x01394, 0x01395, 0x01396, 0x01397,
+0x01398, 0x01399, 0x0139a, 0x0139b, 0x0139c, 0x0139d, 0x0139e, 0x0139f,
+0x0ab70, 0x0ab71, 0x0ab72, 0x0ab73, 0x0ab74, 0x0ab75, 0x0ab76, 0x0ab77,
+0x0ab78, 0x0ab79, 0x0ab7a, 0x0ab7b, 0x0ab7c, 0x0ab7d, 0x0ab7e, 0x0ab7f,
+0x0ab80, 0x0ab81, 0x0ab82, 0x0ab83, 0x0ab84, 0x0ab85, 0x0ab86, 0x0ab87,
+0x0ab88, 0x0ab89, 0x0ab8a, 0x0ab8b, 0x0ab8c, 0x0ab8d, 0x0ab8e, 0x0ab8f,
+0x0ab90, 0x0ab91, 0x0ab92, 0x0ab93, 0x0ab94, 0x0ab95, 0x0ab96, 0x0ab97,
+0x0ab98, 0x0ab99, 0x0ab9a, 0x0ab9b, 0x0ab9c, 0x0ab9d, 0x0ab9e, 0x0ab9f,
+0x0aba0, 0x0aba1, 0x0aba2, 0x0aba3, 0x0aba4, 0x0aba5, 0x0aba6, 0x0aba7,
+0x0aba8, 0x0aba9, 0x0abaa, 0x0abab, 0x0abac, 0x0abad, 0x0abae, 0x0abaf,
+0x0abb0, 0x0abb1, 0x0abb2, 0x0abb3, 0x0abb4, 0x0abb5, 0x0abb6, 0x0abb7,
+0x0abb8, 0x0abb9, 0x0abba, 0x0abbb, 0x0abbc, 0x0abbd, 0x0abbe, 0x0abbf,
+0x013f8, 0x013f9, 0x013fa, 0x013fb, 0x013fc, 0x013fd, 0x013f6, 0x013f7,
+0x013f8, 0x013f9, 0x013fa, 0x013fb, 0x013fc, 0x013fd, 0x013fe, 0x013ff,
+};
+
+
+static const uint32_t  nxt_unicode_lower_case_block_039[128]
+nxt_aligned(64) =
+{
+0x01c80, 0x01c81, 0x01c82, 0x01c83, 0x01c84, 0x01c85, 0x01c86, 0x01c87,
+0x01c88, 0x01c89, 0x01c8a, 0x01c8b, 0x01c8c, 0x01c8d, 0x01c8e, 0x01c8f,
+0x010d0, 0x010d1, 0x010d2, 0x010d3, 0x010d4, 0x010d5, 0x010d6, 0x010d7,
+0x010d8, 0x010d9, 0x010da, 0x010db, 0x010dc, 0x010dd, 0x010de, 0x010df,
+0x010e0, 0x010e1, 0x010e2, 0x010e3, 0x010e4, 0x010e5, 0x010e6, 0x010e7,
+0x0

[njs] Style in nxt_unicode_upper_case.pl and nxt_unicode_upper_case.h.

2019-07-26 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/0af076f81e2b
branches:  
changeset: 1071:0af076f81e2b
user:  Valentin Bartenev 
date:  Sat Jul 27 03:51:48 2019 +0300
description:
Style in nxt_unicode_upper_case.pl and nxt_unicode_upper_case.h.

diffstat:

 nxt/nxt_unicode_upper_case.h  |  4 ++--
 nxt/nxt_unicode_upper_case.pl |  4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diffs (29 lines):

diff -r 6aa2e67eaafc -r 0af076f81e2b nxt/nxt_unicode_upper_case.h
--- a/nxt/nxt_unicode_upper_case.h  Fri Jul 26 20:37:13 2019 +0300
+++ b/nxt/nxt_unicode_upper_case.h  Sat Jul 27 03:51:48 2019 +0300
@@ -4,9 +4,9 @@
  * 16496 bytes on 32-bit platforms, 18576 bytes on 64-bit platforms.
  */
 
-#define NXT_UNICODE_MAX_UPPER_CASE   0x1044f
+#define NXT_UNICODE_MAX_UPPER_CASE  0x1044f
 
-#define NXT_UNICODE_BLOCK_SIZE   128
+#define NXT_UNICODE_BLOCK_SIZE  128
 
 
 static const uint32_t  nxt_unicode_upper_case_block_000[128]
diff -r 6aa2e67eaafc -r 0af076f81e2b nxt/nxt_unicode_upper_case.pl
--- a/nxt/nxt_unicode_upper_case.pl Fri Jul 26 20:37:13 2019 +0300
+++ b/nxt/nxt_unicode_upper_case.pl Sat Jul 27 03:51:48 2019 +0300
@@ -48,8 +48,8 @@ printf("\n/*\n" .
($blocks - 1) * BLOCK_SIZE * 4 + $last_block_size + $max_block * 4,
($blocks - 1) * BLOCK_SIZE * 4 + $last_block_size + $max_block * 8);
 
-printf("#define NXT_UNICODE_MAX_UPPER_CASE   0x%05x\n\n", $max_upper_case);
-printf("#define NXT_UNICODE_BLOCK_SIZE   %d\n\n\n", BLOCK_SIZE);
+printf("#define NXT_UNICODE_MAX_UPPER_CASE  0x%05x\n\n", $max_upper_case);
+printf("#define NXT_UNICODE_BLOCK_SIZE  %d\n\n\n", BLOCK_SIZE);
 
 
 for my $block (sort { $a <=> $b } keys %blocks) {
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Optimized nxt_dec_count() using bisection.

2019-07-25 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/89082cb0bc84
branches:  
changeset: 1069:89082cb0bc84
user:  Valentin Bartenev 
date:  Thu Jul 25 22:07:57 2019 +0300
description:
Optimized nxt_dec_count() using bisection.

Previously, the number of comparisons required to count decimal numbers
was equal to decimal numbers count.

Now only 3 comparsions are needed for numbers with 1, 2, 3, 4, 5, or 6
decimal digits, and 4 comparsions are needed for numbers with 7, 8, 9,
and 10 decimal digits.

diffstat:

 nxt/nxt_dtoa.c |  30 --
 1 files changed, 20 insertions(+), 10 deletions(-)

diffs (41 lines):

diff -r 644af379d226 -r 89082cb0bc84 nxt/nxt_dtoa.c
--- a/nxt/nxt_dtoa.cThu Jul 25 20:17:42 2019 +0300
+++ b/nxt/nxt_dtoa.cThu Jul 25 22:07:57 2019 +0300
@@ -61,17 +61,27 @@ nxt_grisu2_round(char *start, size_t len
 nxt_inline int
 nxt_dec_count(uint32_t n)
 {
-if (n < 10) return 1;
-if (n < 100) return 2;
-if (n < 1000) return 3;
-if (n < 1) return 4;
-if (n < 10) return 5;
-if (n < 100) return 6;
-if (n < 1000) return 7;
-if (n < 1) return 8;
-if (n < 10) return 9;
+if (n < 1) {
+if (n < 100) {
+return (n < 10) ? 1 : 2;
+
+} else {
+return (n < 1000) ? 3 : 4;
+}
 
-return 10;
+} else {
+if (n < 100) {
+return (n < 10) ? 5 : 6;
+
+} else {
+if (n < 1) {
+return (n < 1000) ? 7 : 8;
+
+} else {
+return (n < 10) ? 9 : 10;
+}
+}
+}
 }
 
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed one byte overread in njs_string_to_c_string().

2019-07-25 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/644af379d226
branches:  
changeset: 1068:644af379d226
user:  Valentin Bartenev 
date:  Thu Jul 25 20:17:42 2019 +0300
description:
Fixed one byte overread in njs_string_to_c_string().

Short strings are packed quite tight in njs_value_t, so there's
no one more byte to test.

struct {
njs_value_type_t  type:8;

uint8_t   size:4;
uint8_t   length:4;

u_charstart[14];
} short_string;

With 14 bytes string this occupies 16 bytes, which is equal
to sizeof(njs_value_t).

diffstat:

 njs/njs_string.c |  5 +
 1 files changed, 1 insertions(+), 4 deletions(-)

diffs (15 lines):

diff -r 427edfbe6762 -r 644af379d226 njs/njs_string.c
--- a/njs/njs_string.c  Tue Jul 23 19:42:25 2019 +0300
+++ b/njs/njs_string.c  Thu Jul 25 20:17:42 2019 +0300
@@ -3906,10 +3906,7 @@ njs_string_to_c_string(njs_vm_t *vm, njs
 start = value->short_string.start;
 size = value->short_string.size;
 
-if (start[size] == '\0') {
-return start;
-
-} else if (size < NJS_STRING_SHORT) {
+if (size < NJS_STRING_SHORT) {
 start[size] = '\0';
 return start;
 }
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Optimized inlining of njs_values_strict_equal().

2019-07-11 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/ea18aa7693da
branches:  
changeset: 1041:ea18aa7693da
user:  Valentin Bartenev 
date:  Thu Jul 11 16:10:33 2019 +0300
description:
Optimized inlining of njs_values_strict_equal().

This function is often called inside loops and basically it does only a few cmp
instructions that can be inlined.

The more complex part related to comparing of two strings is functionally
identical to njs_string_eq(), but contains an optimization that avoids memcmp()
when strings have different lengths.  This optimization has been merged into
njs_string_eq().

No functional changes.

diffstat:

 njs/njs_string.c |  24 ++-
 njs/njs_string.h |   1 -
 njs/njs_value.c  |  71 
 njs/njs_value.h  |  29 +-
 4 files changed, 50 insertions(+), 75 deletions(-)

diffs (186 lines):

diff -r b5f72739c00e -r ea18aa7693da njs/njs_string.c
--- a/njs/njs_string.c  Thu Jul 11 15:42:33 2019 +0300
+++ b/njs/njs_string.c  Thu Jul 11 16:10:33 2019 +0300
@@ -689,7 +689,7 @@ njs_string_instance_length(njs_vm_t *vm,
 nxt_bool_t
 njs_string_eq(const njs_value_t *v1, const njs_value_t *v2)
 {
-size_tsize;
+size_tsize, length1, length2;
 const u_char  *start1, *start2;
 
 size = v1->short_string.size;
@@ -699,6 +699,17 @@ njs_string_eq(const njs_value_t *v1, con
 }
 
 if (size != NJS_STRING_LONG) {
+length1 = v1->short_string.length;
+length2 = v2->short_string.length;
+
+/*
+ * Using full memcmp() comparison if at least one string
+ * is a Byte string.
+ */
+if (length1 != 0 && length2 != 0 && length1 != length2) {
+return 0;
+}
+
 start1 = v1->short_string.start;
 start2 = v2->short_string.start;
 
@@ -709,6 +720,17 @@ njs_string_eq(const njs_value_t *v1, con
 return 0;
 }
 
+length1 = v1->long_string.data->length;
+length2 = v2->long_string.data->length;
+
+/*
+ * Using full memcmp() comparison if at least one string
+ * is a Byte string.
+ */
+if (length1 != 0 && length2 != 0 && length1 != length2) {
+return 0;
+}
+
 start1 = v1->long_string.data->start;
 start2 = v2->long_string.data->start;
 }
diff -r b5f72739c00e -r ea18aa7693da njs/njs_string.h
--- a/njs/njs_string.h  Thu Jul 11 15:42:33 2019 +0300
+++ b/njs/njs_string.h  Thu Jul 11 16:10:33 2019 +0300
@@ -168,7 +168,6 @@ njs_ret_t njs_string_validate(njs_vm_t *
 size_t njs_string_prop(njs_string_prop_t *string, const njs_value_t *value);
 njs_ret_t njs_string_constructor(njs_vm_t *vm, njs_value_t *args,
 nxt_uint_t nargs, njs_index_t unused);
-nxt_bool_t njs_string_eq(const njs_value_t *val1, const njs_value_t *val2);
 nxt_int_t njs_string_cmp(const njs_value_t *val1, const njs_value_t *val2);
 void njs_string_slice_string_prop(njs_string_prop_t *dst,
 const njs_string_prop_t *string, const njs_slice_prop_t *slice);
diff -r b5f72739c00e -r ea18aa7693da njs/njs_value.c
--- a/njs/njs_value.c   Thu Jul 11 15:42:33 2019 +0300
+++ b/njs/njs_value.c   Thu Jul 11 16:10:33 2019 +0300
@@ -91,77 +91,6 @@ njs_value_release(njs_vm_t *vm, njs_valu
 }
 
 
-nxt_bool_t
-njs_values_strict_equal(const njs_value_t *val1, const njs_value_t *val2)
-{
-size_tsize, length1, length2;
-const u_char  *start1, *start2;
-
-if (val1->type != val2->type) {
-return 0;
-}
-
-if (njs_is_numeric(val1)) {
-
-if (njs_is_undefined(val1)) {
-return 1;
-}
-
-/* Infinities are handled correctly by comparision. */
-return (njs_number(val1) == njs_number(val2));
-}
-
-if (njs_is_string(val1)) {
-size = val1->short_string.size;
-
-if (size != val2->short_string.size) {
-return 0;
-}
-
-if (size != NJS_STRING_LONG) {
-length1 = val1->short_string.length;
-length2 = val2->short_string.length;
-
-/*
- * Using full memcmp() comparison if at least one string
- * is a Byte string.
- */
-if (length1 != 0 && length2 != 0 && length1 != length2) {
-return 0;
-}
-
-start1 = val1->short_string.start;
-start2 = val2->short_string.start;
-
-} else {
-size = val1->long_string.size;
-
-if (size != val2->long_string.size) {
-return 0;
-}
-
-length1 = val1->long_string.data->length;
-length2 = val2->long_string.data->length;
-
-/*
- * Using full memcmp() comparison if at least one string
- * is a Byte string.
- */
-if (length1 != 0 

[njs] Reduced nesting level of branches in njs_string_replace_regexp().

2019-07-02 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/4a0f6ff54f88
branches:  
changeset: 1024:4a0f6ff54f88
user:  Valentin Bartenev 
date:  Mon Jul 01 22:44:14 2019 +0300
description:
Reduced nesting level of branches in njs_string_replace_regexp().

No functional changes.

diffstat:

 njs/njs_string.c |  163 +++---
 1 files changed, 82 insertions(+), 81 deletions(-)

diffs (181 lines):

diff -r 7a8584306099 -r 4a0f6ff54f88 njs/njs_string.c
--- a/njs/njs_string.c  Tue Jun 18 15:02:57 2019 +
+++ b/njs/njs_string.c  Mon Jul 01 22:44:14 2019 +0300
@@ -3092,95 +3092,96 @@ njs_string_replace_regexp(njs_vm_t *vm, 
r->part[0].start, r->part[0].size,
r->match_data);
 
-if (ret >= 0) {
-captures = nxt_regex_captures(r->match_data);
-
-if (r->substitutions != NULL) {
-ret = njs_string_replace_substitute(vm, r, captures);
-if (nxt_slow_path(ret != NXT_OK)) {
-return ret;
-}
-
-if (!pattern->global) {
-return njs_string_replace_regexp_join(vm, r);
-}
+if (ret < 0) {
+if (nxt_slow_path(ret != NXT_REGEX_NOMATCH)) {
+return NXT_ERROR;
+}
+
+break;
+}
+
+captures = nxt_regex_captures(r->match_data);
+
+if (r->substitutions != NULL) {
+ret = njs_string_replace_substitute(vm, r, captures);
+if (nxt_slow_path(ret != NXT_OK)) {
+return ret;
+}
+
+if (!pattern->global) {
+return njs_string_replace_regexp_join(vm, r);
+}
+
+continue;
+}
+
+if (r->part != r->parts.start) {
+r->part = nxt_array_add(>parts, _array_mem_proto,
+vm->mem_pool);
+if (nxt_slow_path(r->part == NULL)) {
+return NXT_ERROR;
+}
+
+r->part = nxt_array_add(>parts, _array_mem_proto,
+vm->mem_pool);
+if (nxt_slow_path(r->part == NULL)) {
+return NXT_ERROR;
+}
+
+r->part -= 2;
+}
+
+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 {
-if (r->part != r->parts.start) {
-r->part = nxt_array_add(>parts, _array_mem_proto,
-vm->mem_pool);
-if (nxt_slow_path(r->part == NULL)) {
-return NXT_ERROR;
-}
-
-r->part = nxt_array_add(>parts, _array_mem_proto,
-vm->mem_pool);
-if (nxt_slow_path(r->part == NULL)) {
-return NXT_ERROR;
-}
-
-r->part -= 2;
-}
-
-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;
-}
-
-if (r->function != NULL) {
-return njs_string_replace_regexp_function(vm, args, r,
- captures, 
ret);
-}
-
-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(>part[2].value);
-
-if (r->function != NULL) {
-return njs_string_replace_regexp_function(vm, args, r,
- captures, 
ret);
-}
-
- 

[njs] Version bump.

2019-06-27 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/0119e834a202
branches:  
changeset: 1018:0119e834a202
user:  Valentin Bartenev 
date:  Thu Jun 27 18:54:21 2019 +0300
description:
Version bump.

diffstat:

 njs/njs.h |  2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diffs (12 lines):

diff -r 63cd8e6679ba -r 0119e834a202 njs/njs.h
--- a/njs/njs.h Tue Jun 25 14:44:55 2019 +0300
+++ b/njs/njs.h Thu Jun 27 18:54:21 2019 +0300
@@ -11,7 +11,7 @@
 
 #include 
 
-#define NJS_VERSION "0.3.3"
+#define NJS_VERSION "0.3.4"
 
 
 #include 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Removed unused nxt_lvlhsh_ctx_t structure.

2019-06-27 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/40f26bb516a6
branches:  
changeset: 1020:40f26bb516a6
user:  Valentin Bartenev 
date:  Thu Jun 27 18:55:34 2019 +0300
description:
Removed unused nxt_lvlhsh_ctx_t structure.

diffstat:

 nxt/nxt_lvlhsh.h |  10 --
 1 files changed, 0 insertions(+), 10 deletions(-)

diffs (20 lines):

diff -r 9db5e400480c -r 40f26bb516a6 nxt/nxt_lvlhsh.h
--- a/nxt/nxt_lvlhsh.h  Thu Jun 27 18:55:34 2019 +0300
+++ b/nxt/nxt_lvlhsh.h  Thu Jun 27 18:55:34 2019 +0300
@@ -79,16 +79,6 @@ typedef struct {
 
 
 typedef struct {
-nxt_lvlhsh_test_t test;
-nxt_lvlhsh_alloc_talloc;
-nxt_lvlhsh_free_t free;
-
-/* The maximum allowed aligned shift. */
-uint32_t  max_shift;
-} nxt_lvlhsh_ctx_t;
-
-
-typedef struct {
 void  *slot;
 } nxt_lvlhsh_t;
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Removed unused nalloc parameter from lvlhsh allocation functions.

2019-06-27 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/9db5e400480c
branches:  
changeset: 1019:9db5e400480c
user:  Valentin Bartenev 
date:  Thu Jun 27 18:55:34 2019 +0300
description:
Removed unused nalloc parameter from lvlhsh allocation functions.

diffstat:

 njs/njs_event.c |  1 -
 njs/njs_extern.c|  2 --
 njs/njs_lexer_keyword.c |  1 -
 njs/njs_module.c|  1 -
 njs/njs_object.c|  1 -
 njs/njs_shell.c |  5 ++---
 njs/njs_string.c|  1 -
 njs/njs_variable.c  |  2 --
 njs/njs_vm.c|  2 +-
 njs/njs_vm.h|  2 +-
 njs/test/njs_unit_test.c|  3 +--
 nxt/nxt_lvlhsh.c|  5 ++---
 nxt/nxt_lvlhsh.h|  6 +-
 nxt/test/lvlhsh_unit_test.c |  3 +--
 14 files changed, 9 insertions(+), 26 deletions(-)

diffs (252 lines):

diff -r 0119e834a202 -r 9db5e400480c njs/njs_event.c
--- a/njs/njs_event.c   Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_event.c   Thu Jun 27 18:55:34 2019 +0300
@@ -15,7 +15,6 @@ const nxt_lvlhsh_proto_t  njs_event_hash
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_event_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_extern.c
--- a/njs/njs_extern.c  Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_extern.c  Thu Jun 27 18:55:34 2019 +0300
@@ -50,7 +50,6 @@ const nxt_lvlhsh_proto_t  njs_extern_has
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-NXT_LVLHSH_BATCH_ALLOC,
 njs_extern_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
@@ -61,7 +60,6 @@ const nxt_lvlhsh_proto_t  njs_extern_val
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-NXT_LVLHSH_BATCH_ALLOC,
 njs_extern_value_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c   Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_lexer_keyword.c   Thu Jun 27 18:55:34 2019 +0300
@@ -138,7 +138,6 @@ const nxt_lvlhsh_proto_t  njs_keyword_ha
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_keyword_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_module.c
--- a/njs/njs_module.c  Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_module.c  Thu Jun 27 18:55:34 2019 +0300
@@ -415,7 +415,6 @@ const nxt_lvlhsh_proto_t  njs_modules_ha
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_module_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_object.c
--- a/njs/njs_object.c  Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_object.c  Thu Jun 27 18:55:34 2019 +0300
@@ -149,7 +149,6 @@ const nxt_lvlhsh_proto_t  njs_object_has
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_object_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_shell.c
--- a/njs/njs_shell.c   Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_shell.c   Thu Jun 27 18:55:34 2019 +0300
@@ -107,7 +107,7 @@ static void njs_console_clear_timer(njs_
 njs_host_event_t event);
 
 static nxt_int_t lvlhsh_key_test(nxt_lvlhsh_query_t *lhq, void *data);
-static void *lvlhsh_pool_alloc(void *pool, size_t size, nxt_uint_t nalloc);
+static void *lvlhsh_pool_alloc(void *pool, size_t size);
 static void lvlhsh_pool_free(void *pool, void *p, size_t size);
 
 
@@ -192,7 +192,6 @@ static njs_external_t  njs_externals[] =
 
 static const nxt_lvlhsh_proto_t  lvlhsh_proto  nxt_aligned(64) = {
 NXT_LVLHSH_LARGE_SLAB,
-0,
 lvlhsh_key_test,
 lvlhsh_pool_alloc,
 lvlhsh_pool_free,
@@ -1227,7 +1226,7 @@ lvlhsh_key_test(nxt_lvlhsh_query_t *lhq,
 
 
 static void *
-lvlhsh_pool_alloc(void *pool, size_t size, nxt_uint_t nalloc)
+lvlhsh_pool_alloc(void *pool, size_t size)
 {
 return nxt_mp_align(pool, size, size);
 }
diff -r 0119e834a202 -r 9db5e400480c njs/njs_string.c
--- a/njs/njs_string.c  Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_string.c  Thu Jun 27 18:55:34 2019 +0300
@@ -4591,7 +4591,6 @@ static const nxt_lvlhsh_proto_t  njs_val
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_values_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_variable.c
--- a/njs/njs_variable.cThu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_variable.cThu Jun 27 18:55:34 2019 +0300
@@ -37,7 +37,6 @@ const nxt_lvlhsh_proto_t  njs_variables_
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_variables_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
@@ -232,7 +231,6 @@ const nxt_lvlhsh_proto_t  njs_references
 nxt_aligned(64) =
 {
 NXT_LVLHSH_DEFAULT,
-0,
 njs_reference_hash_test,
 njs_lvlhsh_alloc,
 njs_lvlhsh_free,
diff -r 0119e834a202 -r 9db5e400480c njs/njs_vm.c
--- a/njs/njs_vm.c  Thu Jun 27 18:54:21 2019 +0300
+++ b/njs/njs_vm.c  Thu Jun 27 18:55:34 2019 +0300
@@ -3672,7

[njs] Added "name" property for built-in methods.

2019-05-23 Thread Valentin Bartenev
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, _string, >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 = _object_hash_proto;
+lhq.pool = vm->mem_pool;
+
+ret = nxt_lvlhsh_insert(>object.hash, );
+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')"),
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed overwriting "constructor" property of built-in prototypes.

2019-05-23 Thread Valentin Bartenev
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, >object.hash,
-  
>scopes[NJS_SCOPE_GLOBAL][index]);
+if (setval == NULL) {
+setval = >scopes[NJS_SCOPE_GLOBAL][index];
+}
+
+cons = njs_property_constructor_create(vm, >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 = _object_hash_proto;
 
@@ -2953,7 +2956,7 @@ njs_property_constructor_create(njs_vm_t
 return >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") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Made writable most of built-in properties and methods.

2019-05-23 Thread Valentin Bartenev
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,

[njs] Fixed array length property handler.

2019-05-23 Thread Valentin Bartenev
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 = >start[array->length];
-
-do {
-njs_set_invalid(val);
-val++;
-size--;
-} while (size != 0);
-}
-
-array->length = length;
+val = >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,
   >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_snj
  * 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);
di

[njs] Fixed setting of object properties.

2019-05-23 Thread Valentin Bartenev
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.cWed May 22 21:01:39 2019 +0300
+++ b/njs/njs_disassembler.cThu 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_tindex;
 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 = _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(>shared_hash, >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__;

[njs] Uncommented a successful test of Object.create([1,2]).length.

2019-05-21 Thread Valentin Bartenev
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("β") },
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

[njs] Fixed arrays expansion.

2019-05-08 Thread Valentin Bartenev
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("") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Better name for append elements count in njs_array_expand().

2019-05-08 Thread Valentin Bartenev
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);
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Simplified check for array length limit in njs_array_expand().

2019-05-08 Thread Valentin Bartenev
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;
 }
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Made all constructor properties configurable.

2019-05-07 Thread Valentin Bartenev
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.cTue May 07 19:50:39 2019 +0300
+++ b/njs/njs_date.cTue 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,
 },
 
 {
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Made configurable "length", "name", and most of built-in methods.

2019-05-07 Thread Valentin Bartenev
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"),
   

[njs] Fixed return value on deleting non-existent property.

2019-05-06 Thread Valentin Bartenev
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 = _value_false;
-
 njs_property_query_init(, NJS_PROPERTY_QUERY_DELETE, 1);
 
 ret = njs_property_query(vm, , 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 = _value_true;
 goto done;
 
 case NJS_PROPERTY_HANDLER:
@@ -744,7 +740,6 @@ njs_vmcode_property_delete(njs_vm_t *vm,
 return ret;
 }
 
-retval = _value_true;
 goto done;
 }
 
@@ -768,8 +763,6 @@ njs_vmcode_property_delete(njs_vm_t *vm,
 prop->type = NJS_WHITEOUT;
 njs_set_invalid(>value);
 
-retval = _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") },
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added own constructors to prototypes of built-in objects.

2019-05-06 Thread Valentin Bartenev
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.cMon May 06 19:42:06 2019 +0300
+++ b/njs/njs_date.cMon 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 @@ 

[njs] Added support for RegExp "groups" object (ES9).

2019-05-06 Thread Valentin Bartenev
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_tsize;
+nxt_uint_tn;
+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(>regex[0])
-&& !nxt_regex_is_valid(>regex[1]))
-{
+if (nxt_regex_is_valid(>regex[0])) {
+regex = >regex[0];
+
+} else if (nxt_regex_is_valid(>regex[1])) {
+regex = >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 = >groups[n];
+
+group->capture = nxt_regex_named_captures(regex, >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(>object.hash, );
 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, _input, >string, 1);
@@ -846,16 +887,74 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
 lhq.value = prop;
 
 ret = nxt_lvlhsh_insert(>object.hash, );
+if (nxt_slow_path(ret != NXT_OK)) {
+goto insert_fail;
+}
 
-if (nxt_fast_path(ret

[njs] Fixed own properties quering.

2019-05-06 Thread Valentin Bartenev
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 = >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,
-
>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(>hash, >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, >value, index);
+
+if (nxt_fast_path(ret != NXT_DECLINED)) {
+return ret;
+}
+}
+
+default:
+break;
+}
+}
+
+ret = nxt_lvlhsh_find(>hash, >lhq);
+
+if (ret == NXT_OK) {
+prop = pq->lhq.value;
+
+if (prop->type != NJS_WHITEOUT) {
+pq->shared = 0;
+
+return ret;
+}
+
+} else {
+ret = nxt_lvlhsh_find(>shared_hash, >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, >value,
- index);
-}
-
-default:
-break;
-}
+pq->shared = 1;
+
+return ret;
 }
 }
 
-ret = nxt_lvlhsh_find(>shared_hash, >lhq);
-
-if (ret == NXT_OK) {
-   

[njs] Fixed alignment of njs_object_prop_t in njs_method_private_copy().

2019-05-06 Thread Valentin Bartenev
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;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Uncommented a successful test of getOwnPropertyNames().

2019-05-06 Thread Valentin Bartenev
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(>hash, >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") },
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added missing "static" to njs_object_property_query() declaration.

2019-05-06 Thread Valentin Bartenev
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)
 {
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added the "name" property to the Function prototype object.

2019-05-04 Thread Valentin Bartenev
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.cSat May 04 16:59:24 2019 +0300
+++ b/njs/njs_function.cSat 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),
 },
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Style.

2019-05-04 Thread Valentin Bartenev
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.cSat May 04 05:52:15 2019 +0300
+++ b/njs/njs_disassembler.cSat 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.cSat May 04 05:52:15 2019 +0300
+++ b/njs/njs_function.cSat 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(>object.hash);
diff -r 551d173ab9ec -r b7cdfafdc20b njs/njs_json.c
--- a/njs/njs_json.cSat May 04 05:52:15 2019 +0300
+++ b/njs/njs_json.cSat 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_tlhq;
+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_tlhq;
+
+static const njs_value_t  proto_string = njs_string("prototype");
 
 prop = njs_object_prop_alloc(vm, _string, _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_tindex;
+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;
+

[njs] Simplified condition in njs_function_alloc().

2019-05-04 Thread Valentin Bartenev
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.cSat May 04 00:56:39 2019 +0300
+++ b/njs/njs_function.cSat 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__ = 
>prototypes[NJS_PROTOTYPE_FUNCTION].object;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added missed njs_internal_error() call in njs_regexp_exec_result().

2019-05-03 Thread Valentin Bartenev
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;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Rejection of multiple "var" declarations in the for-in statement.

2019-05-02 Thread Valentin Bartenev
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") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Corrected error message when parsing "var" inside "for".

2019-05-02 Thread Valentin Bartenev
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") },
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Removed NXT_READLINE_CFLAGS.

2019-04-26 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/60e98e247a53
branches:  
changeset: 932:60e98e247a53
user:  Valentin Bartenev 
date:  Fri Apr 26 19:30:43 2019 +0300
description:
Removed NXT_READLINE_CFLAGS.

It's not needed after 61f2616e21c7.

diffstat:

 auto/make |  3 +--
 auto/readline |  4 
 2 files changed, 1 insertions(+), 6 deletions(-)

diffs (38 lines):

diff -r 760d38110fd9 -r 60e98e247a53 auto/make
--- a/auto/make Fri Apr 26 17:59:42 2019 +0300
+++ b/auto/make Fri Apr 26 19:30:43 2019 +0300
@@ -177,8 +177,7 @@ cat << END >> $NXT_MAKEFILE
$NXT_BUILD_DIR/libnjs.a \\
njs/njs_shell.c
\$(NXT_CC) -o $NXT_BUILD_DIR/njs \$(NXT_CFLAGS) \\
-   $NXT_LIB_AUX_CFLAGS \$(NXT_LIB_INCS) \\
-   $NXT_READLINE_CFLAGS -Injs \\
+   $NXT_LIB_AUX_CFLAGS \$(NXT_LIB_INCS) -Injs \\
njs/njs_shell.c \\
$NXT_BUILD_DIR/libnjs.a \\
-lm $NXT_LIBS $NXT_LIB_AUX_LIBS $NXT_READLINE_LIB
diff -r 760d38110fd9 -r 60e98e247a53 auto/readline
--- a/auto/readline Fri Apr 26 17:59:42 2019 +0300
+++ b/auto/readline Fri Apr 26 19:30:43 2019 +0300
@@ -2,7 +2,6 @@
 # Copyright (C) NGINX, Inc.
 
 
-NXT_READLINE_CFLAGS=
 NXT_READLINE_LIB=
 
 nxt_found=no
@@ -69,13 +68,10 @@ if [ $nxt_found = no ]; then
 . auto/feature
 fi
 
-
-
 NXT_DEFAULT_TARGET=libnjs
 
 if [ $nxt_found = yes ]; then
 NXT_HAVE_READLINE=YES
-NXT_READLINE_CFLAGS=$nxt_feature_incs
 NXT_READLINE_LIB=$nxt_feature_libs
 NXT_DEFAULT_TARGET="$NXT_DEFAULT_TARGET njs"
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Support for building with GNU Readline library.

2019-04-26 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/760d38110fd9
branches:  
changeset: 931:760d38110fd9
user:  Valentin Bartenev 
date:  Fri Apr 26 17:59:42 2019 +0300
description:
Support for building with GNU Readline library.

diffstat:

 auto/editline   |  68 -
 auto/expect |   2 +-
 auto/make   |   4 +-
 auto/readline   |  85 +
 configure   |   2 +-
 njs/njs_shell.c |   3 ++
 6 files changed, 92 insertions(+), 72 deletions(-)

diffs (214 lines):

diff -r 43dc900bc914 -r 760d38110fd9 auto/editline
--- a/auto/editline Thu Apr 25 19:50:20 2019 +0300
+++ /dev/null   Thu Jan 01 00:00:00 1970 +
@@ -1,68 +0,0 @@
-# Copyright (C) Dmitry Volyntsev
-# Copyright (C) NGINX, Inc.
-
-
-NXT_EDITLINE_CFLAGS=
-NXT_EDITLINE_LIB=
-
-nxt_found=no
-
-nxt_feature="editline library in editline/readline.h"
-nxt_feature_name=NXT_HAVE_EDITLINE
-nxt_feature_run=no
-nxt_feature_incs=
-nxt_feature_libs="-ledit"
-nxt_feature_test="#include 
-  #include 
-
-  int main(void) {
-  add_history(NULL);
-  return 0;
-  }"
-. auto/feature
-
-if [ $nxt_found = no ]; then
-
-# FreeBSD port
-
-nxt_feature_name=NXT_HAVE_EDIT_READLINE
-nxt_feature="editline in edit/readline/readline.h"
-nxt_feature_test="#include 
-  #include 
-
-  int main(void) {
-  add_history(NULL);
-  return 0;
-  }"
-
-. auto/feature
-fi
-
-if [ $nxt_found = no ]; then
-
-# NetBSD
-
-nxt_feature_name=NXT_HAVE_READLINE
-nxt_feature="editline in readline/readline.h"
-nxt_feature_test="#include 
-  #include 
-
-  int main(void) {
-  add_history(NULL);
-  return 0;
-  }"
-. auto/feature
-fi
-
-NXT_DEFAULT_TARGET=libnjs
-
-if [ $nxt_found = yes ]; then
-NXT_HAVE_LIBEDIT=YES
-NXT_EDITLINE_CFLAGS=$nxt_feature_incs
-NXT_EDITLINE_LIB=$nxt_feature_libs
-NXT_DEFAULT_TARGET="$NXT_DEFAULT_TARGET njs"
-
-else
-NXT_HAVE_LIBEDIT=NO
-$echo " - building interactive shell is not possible"
-fi
diff -r 43dc900bc914 -r 760d38110fd9 auto/expect
--- a/auto/expect   Thu Apr 25 19:50:20 2019 +0300
+++ b/auto/expect   Fri Apr 26 17:59:42 2019 +0300
@@ -17,7 +17,7 @@ else
 $echo " not found"
 fi
 
-if [ $nxt_found = yes -a $NXT_HAVE_LIBEDIT = YES ]; then
+if [ $nxt_found = yes -a $NXT_HAVE_READLINE = YES ]; then
 cat << END >> $NXT_MAKEFILE
 
 njs_expect_test:   njs njs/test/njs_expect_test.exp
diff -r 43dc900bc914 -r 760d38110fd9 auto/make
--- a/auto/make Thu Apr 25 19:50:20 2019 +0300
+++ b/auto/make Fri Apr 26 17:59:42 2019 +0300
@@ -178,10 +178,10 @@ cat << END >> $NXT_MAKEFILE
njs/njs_shell.c
\$(NXT_CC) -o $NXT_BUILD_DIR/njs \$(NXT_CFLAGS) \\
$NXT_LIB_AUX_CFLAGS \$(NXT_LIB_INCS) \\
-   $NXT_EDITLINE_CFLAGS -Injs \\
+   $NXT_READLINE_CFLAGS -Injs \\
njs/njs_shell.c \\
$NXT_BUILD_DIR/libnjs.a \\
-   -lm $NXT_LIBS $NXT_LIB_AUX_LIBS $NXT_EDITLINE_LIB
+   -lm $NXT_LIBS $NXT_LIB_AUX_LIBS $NXT_READLINE_LIB
 
 END
 
diff -r 43dc900bc914 -r 760d38110fd9 auto/readline
--- /dev/null   Thu Jan 01 00:00:00 1970 +
+++ b/auto/readline Fri Apr 26 17:59:42 2019 +0300
@@ -0,0 +1,85 @@
+# Copyright (C) Dmitry Volyntsev
+# Copyright (C) NGINX, Inc.
+
+
+NXT_READLINE_CFLAGS=
+NXT_READLINE_LIB=
+
+nxt_found=no
+
+nxt_feature="GNU readline library"
+nxt_feature_name=NXT_HAVE_GNU_READLINE
+nxt_feature_run=no
+nxt_feature_incs=
+nxt_feature_libs="-lreadline"
+nxt_feature_test="#include 
+  #include 
+  #include 
+
+  int main(void) {
+  add_history(NULL);
+  return 0;
+  }"
+. auto/feature
+
+if [ $nxt_found = no ]; then
+nxt_feature="editline library in editline/readline.h"
+nxt_feature_name=NXT_HAVE_EDITLINE
+nxt_feature_libs="-ledit"
+nxt_feature_test="#include 
+  #include 
+
+  int main(void) {
+  add_history(NULL);
+  return 0;
+  }"
+. auto/feature
+fi
+
+if [ $nxt_found = no ]; then
+
+# FreeBSD port
+
+nxt_feature_name=NXT_HAVE_EDIT_READLINE
+nxt_feature="editline in edit/readline/readline.h"
+nxt_feature_test="#include 
+  #include 
+
+  int main(void) {
+  add_history(NULL);
+

[njs] Object.entries() method.

2018-12-03 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/ce3a943df9c4
branches:  
changeset: 683:ce3a943df9c4
user:  Valentin Bartenev 
date:  Mon Dec 03 19:23:27 2018 +0300
description:
Object.entries() method.

diffstat:

 njs/njs_object.c |  151 ++-
 njs/njs_object.h |1 +
 njs/test/njs_unit_test.c |   37 +++
 3 files changed, 188 insertions(+), 1 deletions(-)

diffs (261 lines):

diff -r 1af8f40573f2 -r ce3a943df9c4 njs/njs_object.c
--- a/njs/njs_object.c  Mon Dec 03 19:20:58 2018 +0300
+++ b/njs/njs_object.c  Mon Dec 03 19:23:27 2018 +0300
@@ -914,6 +914,35 @@ njs_object_values(njs_vm_t *vm, njs_valu
 }
 
 
+static njs_ret_t
+njs_object_entries(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+ {
+njs_array_t*array;
+const njs_value_t  *value;
+
+value = njs_arg(args, nargs, 1);
+
+if (njs_is_null_or_void(value)) {
+njs_type_error(vm, "cannot convert %s argument to object",
+   njs_type_string(value->type));
+
+return NXT_ERROR;
+}
+
+array = njs_object_enumerate(vm, value, NJS_ENUM_BOTH);
+if (array == NULL) {
+return NXT_ERROR;
+}
+
+vm->retval.data.u.array = array;
+vm->retval.type = NJS_ARRAY;
+vm->retval.data.truth = 1;
+
+return NXT_OK;
+}
+
+
 njs_array_t *
 njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value,
 njs_object_enum_t kind)
@@ -921,7 +950,7 @@ njs_object_enumerate(njs_vm_t *vm, const
 u_char *dst;
 uint32_t   i, length, size, items_length, properties;
 njs_value_t*string, *item;
-njs_array_t*items, *array;
+njs_array_t*items, *array, *entry;
 nxt_lvlhsh_t   *hash;
 const u_char   *src, *end;
 njs_object_prop_t  *prop;
@@ -1013,6 +1042,29 @@ njs_object_enumerate(njs_vm_t *vm, const
 }
 
 break;
+
+case NJS_ENUM_BOTH:
+for (i = 0; i < length; i++) {
+if (njs_is_valid(>start[i])) {
+entry = njs_array_alloc(vm, 2, 0);
+if (nxt_slow_path(entry == NULL)) {
+return NULL;
+}
+
+njs_uint32_to_string(>start[0], i);
+
+/* GC: retain. */
+entry->start[1] = array->start[i];
+
+item->data.u.array = entry;
+item->type = NJS_ARRAY;
+item->data.truth = 1;
+
+item++;
+}
+}
+
+break;
 }
 
 } else if (length != 0) {
@@ -1057,6 +1109,66 @@ njs_object_enumerate(njs_vm_t *vm, const
 }
 
 break;
+
+case NJS_ENUM_BOTH:
+if (string_prop.size == (size_t) length) {
+/* Byte or ASCII string. */
+
+for (i = 0; i < length; i++) {
+entry = njs_array_alloc(vm, 2, 0);
+if (nxt_slow_path(entry == NULL)) {
+return NULL;
+}
+
+njs_uint32_to_string(>start[0], i);
+
+string = >start[1];
+
+dst = njs_string_short_start(string);
+dst[0] = string_prop.start[i];
+
+njs_string_short_set(string, 1, 1);
+
+item->data.u.array = entry;
+item->type = NJS_ARRAY;
+item->data.truth = 1;
+
+item++;
+}
+
+} else {
+/* UTF-8 string. */
+
+src = string_prop.start;
+end = src + string_prop.size;
+i = 0;
+
+do {
+entry = njs_array_alloc(vm, 2, 0);
+if (nxt_slow_path(entry == NULL)) {
+return NULL;
+}
+
+njs_uint32_to_string(>start[0], i++);
+
+string = >start[1];
+
+dst = njs_string_short_start(string);
+dst = nxt_utf8_copy(dst, , end);
+size = dst - njs_string_short_start(value);
+
+njs_string_short_set(string, size, 1);
+
+item->data.u.array = entry;
+item->type = NJS_ARRAY;
+item->data.truth = 1;
+
+item++;
+
+} while (src != end);
+}
+
+break;
 }
 }
 
@@ -1095,6 +1207,35 @@ njs_object_enumerate(njs_vm_t *vm, const
 }
 
 break;
+
+case NJS_ENUM_BOTH:
+for ( ;; ) {
+prop = nxt_lvlhsh_each(hash, );
+
+if (prop == NULL) {
+break;
+}
+
+if (prop->type != N

[njs] Object.values() method.

2018-12-03 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/1af8f40573f2
branches:  
changeset: 682:1af8f40573f2
user:  Valentin Bartenev 
date:  Mon Dec 03 19:20:58 2018 +0300
description:
Object.values() method.

diffstat:

 njs/njs_json.c   |4 +-
 njs/njs_object.c |  169 +++---
 njs/njs_object.h |9 ++-
 njs/test/njs_unit_test.c |   38 ++
 4 files changed, 191 insertions(+), 29 deletions(-)

diffs (347 lines):

diff -r 4a543ed58c95 -r 1af8f40573f2 njs/njs_json.c
--- a/njs/njs_json.cSat Dec 01 22:32:33 2018 +0300
+++ b/njs/njs_json.cMon Dec 03 19:20:58 2018 +0300
@@ -1095,7 +1095,7 @@ njs_json_push_parse_state(njs_vm_t *vm, 
 } else {
 state->type = NJS_JSON_OBJECT_START;
 state->prop_value = NULL;
-state->keys = njs_object_keys_array(vm, value);
+state->keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS);
 if (state->keys == NULL) {
 return NULL;
 }
@@ -1659,7 +1659,7 @@ njs_json_push_stringify_state(njs_vm_t *
 state->keys = njs_extern_keys_array(vm, value->external.proto);
 
 } else {
-state->keys = njs_object_keys_array(vm, value);
+state->keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS);
 }
 
 if (state->keys == NULL) {
diff -r 4a543ed58c95 -r 1af8f40573f2 njs/njs_object.c
--- a/njs/njs_object.c  Sat Dec 01 22:32:33 2018 +0300
+++ b/njs/njs_object.c  Mon Dec 03 19:20:58 2018 +0300
@@ -872,7 +872,7 @@ njs_object_keys(njs_vm_t *vm, njs_value_
 return NXT_ERROR;
 }
 
-keys = njs_object_keys_array(vm, value);
+keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS);
 if (keys == NULL) {
 return NXT_ERROR;
 }
@@ -885,20 +885,52 @@ njs_object_keys(njs_vm_t *vm, njs_value_
 }
 
 
+static njs_ret_t
+njs_object_values(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+ {
+njs_array_t*array;
+const njs_value_t  *value;
+
+value = njs_arg(args, nargs, 1);
+
+if (njs_is_null_or_void(value)) {
+njs_type_error(vm, "cannot convert %s argument to object",
+   njs_type_string(value->type));
+
+return NXT_ERROR;
+}
+
+array = njs_object_enumerate(vm, value, NJS_ENUM_VALUES);
+if (array == NULL) {
+return NXT_ERROR;
+}
+
+vm->retval.data.u.array = array;
+vm->retval.type = NJS_ARRAY;
+vm->retval.data.truth = 1;
+
+return NXT_OK;
+}
+
+
 njs_array_t *
-njs_object_keys_array(njs_vm_t *vm, const njs_value_t *value)
+njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value,
+njs_object_enum_t kind)
 {
-uint32_t   i, n, length, keys_length, properties;
-njs_value_t*string;
-njs_array_t*keys, *array;
+u_char *dst;
+uint32_t   i, length, size, items_length, properties;
+njs_value_t*string, *item;
+njs_array_t*items, *array;
 nxt_lvlhsh_t   *hash;
+const u_char   *src, *end;
 njs_object_prop_t  *prop;
 njs_string_prop_t  string_prop;
 nxt_lvlhsh_each_t  lhe;
 
 array = NULL;
 length = 0;
-keys_length = 0;
+items_length = 0;
 
 switch (value->type) {
 case NJS_ARRAY:
@@ -907,7 +939,7 @@ njs_object_keys_array(njs_vm_t *vm, cons
 
 for (i = 0; i < length; i++) {
 if (njs_is_valid(>start[i])) {
-keys_length++;
+items_length++;
 }
 }
 
@@ -923,7 +955,7 @@ njs_object_keys_array(njs_vm_t *vm, cons
 }
 
 length = njs_string_prop(_prop, string);
-keys_length += length;
+items_length += length;
 break;
 
 default:
@@ -950,46 +982,123 @@ njs_object_keys_array(njs_vm_t *vm, cons
 }
 }
 
-keys_length += properties;
+items_length += properties;
 }
 
-keys = njs_array_alloc(vm, keys_length, NJS_ARRAY_SPARE);
-if (nxt_slow_path(keys == NULL)) {
+items = njs_array_alloc(vm, items_length, NJS_ARRAY_SPARE);
+if (nxt_slow_path(items == NULL)) {
 return NULL;
 }
 
-n = 0;
+item = items->start;
 
 if (array != NULL) {
-for (i = 0; i < length; i++) {
-if (njs_is_valid(>start[i])) {
-njs_uint32_to_string(>start[n++], i);
+
+switch (kind) {
+case NJS_ENUM_KEYS:
+for (i = 0; i < length; i++) {
+if (njs_is_valid(>start[i])) {
+njs_uint32_to_string(item++, i);
+}
 }
+
+break;
+
+case NJS_ENUM_VALUES:
+for (i = 0; i < length; i++) {
+if (njs_is_valid(>start[i])) {
+/* GC: retain. */
+*item++ = array->st

[njs] Slightly optimized njs_object_keys_array().

2018-12-01 Thread Valentin Bartenev
details:   https://hg.nginx.org/njs/rev/4a543ed58c95
branches:  
changeset: 681:4a543ed58c95
user:  Valentin Bartenev 
date:  Sat Dec 01 22:32:33 2018 +0300
description:
Slightly optimized njs_object_keys_array().

There is no need to iterate over the object properties second time if after
the first attempt we know that it contains no enumerable properties.

Also removed surplus conditions.

diffstat:

 njs/njs_object.c |  19 ++-
 1 files changed, 10 insertions(+), 9 deletions(-)

diffs (61 lines):

diff -r e713f648ef71 -r 4a543ed58c95 njs/njs_object.c
--- a/njs/njs_object.c  Fri Nov 30 17:52:02 2018 +0300
+++ b/njs/njs_object.c  Sat Dec 01 22:32:33 2018 +0300
@@ -888,7 +888,7 @@ njs_object_keys(njs_vm_t *vm, njs_value_
 njs_array_t *
 njs_object_keys_array(njs_vm_t *vm, const njs_value_t *value)
 {
-uint32_t   i, n, length, keys_length;
+uint32_t   i, n, length, keys_length, properties;
 njs_value_t*string;
 njs_array_t*keys, *array;
 nxt_lvlhsh_t   *hash;
@@ -930,15 +930,14 @@ njs_object_keys_array(njs_vm_t *vm, cons
 break;
 }
 
+/* GCC 4 and Clang 3 complain about uninitialized hash. */
+hash = NULL;
+properties = 0;
+
 if (nxt_fast_path(njs_is_object(value))) {
 nxt_lvlhsh_each_init(, _object_hash_proto);
 hash = >data.u.object->hash;
 
-} else {
-hash = NULL;
-}
-
-if (nxt_fast_path(hash != NULL)) {
 for ( ;; ) {
 prop = nxt_lvlhsh_each(hash, );
 
@@ -947,9 +946,11 @@ njs_object_keys_array(njs_vm_t *vm, cons
 }
 
 if (prop->type != NJS_WHITEOUT && prop->enumerable) {
-keys_length++;
+properties++;
 }
 }
+
+keys_length += properties;
 }
 
 keys = njs_array_alloc(vm, keys_length, NJS_ARRAY_SPARE);
@@ -966,13 +967,13 @@ njs_object_keys_array(njs_vm_t *vm, cons
 }
 }
 
-} else if (length != 0) {
+} else {
 for (i = 0; i < length; i++) {
 njs_uint32_to_string(>start[n++], i);
 }
 }
 
-if (nxt_fast_path(hash != NULL)) {
+if (nxt_fast_path(properties != 0)) {
 nxt_lvlhsh_each_init(, _object_hash_proto);
 
 for ( ;; ) {
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] RegExp: fixed a case when lastIndex is greater than string size.

2018-11-12 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/f1da98bdd82f
branches:  
changeset: 647:f1da98bdd82f
user:  Valentin Bartenev 
date:  Mon Nov 12 17:22:14 2018 +0300
description:
RegExp: fixed a case when lastIndex is greater than string size.

Previously, it resulted in: "InternalError: pcre_exec() failed: -32" due to
negative string size caused by subtraction of last_index.

diffstat:

 njs/njs_regexp.c |  62 ---
 njs/test/njs_unit_test.c |   3 ++
 2 files changed, 35 insertions(+), 30 deletions(-)

diffs (91 lines):

diff -r 7d06ada396d7 -r f1da98bdd82f njs/njs_regexp.c
--- a/njs/njs_regexp.c  Fri Nov 09 18:22:01 2018 +0300
+++ b/njs/njs_regexp.c  Mon Nov 12 17:22:14 2018 +0300
@@ -644,42 +644,44 @@ njs_regexp_prototype_exec(njs_vm_t *vm, 
 
 (void) njs_string_prop(, value);
 
-utf8 = NJS_STRING_BYTE;
-type = NJS_REGEXP_BYTE;
-
-if (string.length != 0) {
-utf8 = NJS_STRING_ASCII;
-type = NJS_REGEXP_UTF8;
-
-if (string.length != string.size) {
-utf8 = NJS_STRING_UTF8;
-}
-}
+if (string.size >= regexp->last_index) {
+utf8 = NJS_STRING_BYTE;
+type = NJS_REGEXP_BYTE;
 
-pattern = regexp->pattern;
-
-if (nxt_regex_is_valid(>regex[type])) {
-string.start += regexp->last_index;
-string.size -= regexp->last_index;
+if (string.length != 0) {
+utf8 = NJS_STRING_ASCII;
+type = NJS_REGEXP_UTF8;
 
-match_data = nxt_regex_match_data(>regex[type],
-  vm->regex_context);
-if (nxt_slow_path(match_data == NULL)) {
-njs_memory_error(vm);
-return NXT_ERROR;
+if (string.length != string.size) {
+utf8 = NJS_STRING_UTF8;
+}
 }
 
-ret = njs_regexp_match(vm, >regex[type], string.start,
-   string.size, match_data);
-if (ret >= 0) {
-return njs_regexp_exec_result(vm, regexp, utf8, string.start,
-  match_data);
-}
+pattern = regexp->pattern;
+
+if (nxt_regex_is_valid(>regex[type])) {
+string.start += regexp->last_index;
+string.size -= regexp->last_index;
+
+match_data = nxt_regex_match_data(>regex[type],
+  vm->regex_context);
+if (nxt_slow_path(match_data == NULL)) {
+njs_memory_error(vm);
+return NXT_ERROR;
+}
 
-if (nxt_slow_path(ret != NXT_REGEX_NOMATCH)) {
-nxt_regex_match_data_free(match_data, vm->regex_context);
+ret = njs_regexp_match(vm, >regex[type], string.start,
+   string.size, match_data);
+if (ret >= 0) {
+return njs_regexp_exec_result(vm, regexp, utf8, string.start,
+  match_data);
+}
 
-return NXT_ERROR;
+if (nxt_slow_path(ret != NXT_REGEX_NOMATCH)) {
+nxt_regex_match_data_free(match_data, vm->regex_context);
+
+return NXT_ERROR;
+}
 }
 }
 
diff -r 7d06ada396d7 -r f1da98bdd82f njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Fri Nov 09 18:22:01 2018 +0300
+++ b/njs/test/njs_unit_test.c  Mon Nov 12 17:22:14 2018 +0300
@@ -5973,6 +5973,9 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("var a = /^$/.exec(''); a.length +' '+ a"),
   nxt_string("1 ") },
 
+{ nxt_string("var r = /3/g; r.exec('123') +' '+ r.exec('3')"),
+  nxt_string("3 null") },
+
 { nxt_string("var r = /бв/ig;"
  "var a = r.exec('АБВ');"
  "r.lastIndex +' '+ a +' '+ "
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

[njs] Fixed equality operator with object and string.

2018-11-09 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/7d06ada396d7
branches:  
changeset: 646:7d06ada396d7
user:  Valentin Bartenev 
date:  Fri Nov 09 18:22:01 2018 +0300
description:
Fixed equality operator with object and string.

diffstat:

 njs/njs_vm.c |  25 ++---
 njs/test/njs_unit_test.c |  19 +++
 2 files changed, 41 insertions(+), 3 deletions(-)

diffs (81 lines):

diff -r 025b22bf8c49 -r 7d06ada396d7 njs/njs_vm.c
--- a/njs/njs_vm.c  Thu Nov 08 20:32:45 2018 +0300
+++ b/njs/njs_vm.c  Fri Nov 09 18:22:01 2018 +0300
@@ -1519,7 +1519,8 @@ njs_vmcode_not_equal(njs_vm_t *vm, njs_v
 static nxt_noinline njs_ret_t
 njs_values_equal(njs_vm_t *vm, const njs_value_t *val1, const njs_value_t 
*val2)
 {
-nxt_bool_t  nv1, nv2;
+nxt_bool_t nv1, nv2;
+const njs_value_t  *hv, *lv;
 
 nv1 = njs_is_null_or_void(val1);
 nv2 = njs_is_null_or_void(val2);
@@ -1543,11 +1544,29 @@ njs_values_equal(njs_vm_t *vm, const njs
 return (val1->data.u.object == val2->data.u.object);
 }
 
-if (njs_is_object(val1) && njs_is_object(val2)) {
+/* Sort values as: numeric < string < objects. */
+
+if (val1->type > val2->type) {
+hv = val1;
+lv = val2;
+
+} else {
+hv = val2;
+lv = val1;
+}
+
+/* If "lv" is an object then "hv" can only be another object. */
+if (njs_is_object(lv)) {
 return 0;
 }
 
-return njs_trap(vm, NJS_TRAP_NUMBERS);
+/* If "hv" is a string then "lv" can only be a numeric. */
+if (njs_is_string(hv)) {
+return (lv->data.u.number == njs_string_to_number(hv, 0));
+}
+
+/* "hv" is an object and "lv" is either a string or a numeric. */
+return njs_trap(vm, NJS_TRAP_COMPARISON);
 }
 
 
diff -r 025b22bf8c49 -r 7d06ada396d7 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Thu Nov 08 20:32:45 2018 +0300
+++ b/njs/test/njs_unit_test.c  Fri Nov 09 18:22:01 2018 +0300
@@ -1142,6 +1142,15 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("var a = Object; a == Object"),
   nxt_string("true") },
 
+{ nxt_string("'1' == new Number(1)"),
+  nxt_string("true") },
+
+{ nxt_string("new String('abc') == 'abc'"),
+  nxt_string("true") },
+
+{ nxt_string("false == new String('0')"),
+  nxt_string("true") },
+
 { nxt_string("var a = { valueOf: function() { return 5 } };   a == 5"),
   nxt_string("true") },
 
@@ -1151,6 +1160,16 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("var a = { valueOf: function() { return '5' } }; a == '5'"),
   nxt_string("true") },
 
+{ nxt_string("var a = { valueOf: function() { return 5 } }; a == '5'"),
+  nxt_string("true") },
+
+{ nxt_string("var a = { toString: function() { return true } }; '1' == a"),
+  nxt_string("true") },
+
+{ nxt_string("var a = { valueOf: function() { return 'b' },"
+ "  toString: function() { return 'a' } }; a == 'a'"),
+  nxt_string("false") },
+
 /* Comparisions. */
 
 { nxt_string("1 < 2"),
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed equality operator when both operands are objects.

2018-11-09 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/025b22bf8c49
branches:  
changeset: 645:025b22bf8c49
user:  Valentin Bartenev 
date:  Thu Nov 08 20:32:45 2018 +0300
description:
Fixed equality operator when both operands are objects.

diffstat:

 njs/njs_vm.c |  4 
 njs/test/njs_unit_test.c |  6 ++
 2 files changed, 10 insertions(+), 0 deletions(-)

diffs (30 lines):

diff -r abec5f8d55a1 -r 025b22bf8c49 njs/njs_vm.c
--- a/njs/njs_vm.c  Fri Nov 09 18:05:39 2018 +0300
+++ b/njs/njs_vm.c  Thu Nov 08 20:32:45 2018 +0300
@@ -1543,6 +1543,10 @@ njs_values_equal(njs_vm_t *vm, const njs
 return (val1->data.u.object == val2->data.u.object);
 }
 
+if (njs_is_object(val1) && njs_is_object(val2)) {
+return 0;
+}
+
 return njs_trap(vm, NJS_TRAP_NUMBERS);
 }
 
diff -r abec5f8d55a1 -r 025b22bf8c49 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Fri Nov 09 18:05:39 2018 +0300
+++ b/njs/test/njs_unit_test.c  Thu Nov 08 20:32:45 2018 +0300
@@ -1136,6 +1136,12 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("({}) == false"),
   nxt_string("false") },
 
+{ nxt_string("new Number(1) == new String('1')"),
+  nxt_string("false") },
+
+{ nxt_string("var a = Object; a == Object"),
+  nxt_string("true") },
+
 { nxt_string("var a = { valueOf: function() { return 5 } };   a == 5"),
   nxt_string("true") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed equality operator with "null" value as right operand.

2018-11-09 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/abec5f8d55a1
branches:  
changeset: 644:abec5f8d55a1
user:  Valentin Bartenev 
date:  Fri Nov 09 18:05:39 2018 +0300
description:
Fixed equality operator with "null" value as right operand.

diffstat:

 njs/njs_vm.c |  9 +++--
 njs/test/njs_unit_test.c |  3 +++
 2 files changed, 10 insertions(+), 2 deletions(-)

diffs (33 lines):

diff -r c5a3ac902bc2 -r abec5f8d55a1 njs/njs_vm.c
--- a/njs/njs_vm.c  Thu Nov 08 16:45:54 2018 +0300
+++ b/njs/njs_vm.c  Fri Nov 09 18:05:39 2018 +0300
@@ -1519,9 +1519,14 @@ njs_vmcode_not_equal(njs_vm_t *vm, njs_v
 static nxt_noinline njs_ret_t
 njs_values_equal(njs_vm_t *vm, const njs_value_t *val1, const njs_value_t 
*val2)
 {
+nxt_bool_t  nv1, nv2;
+
+nv1 = njs_is_null_or_void(val1);
+nv2 = njs_is_null_or_void(val2);
+
 /* Void and null are equal and not comparable with anything else. */
-if (njs_is_null_or_void(val1)) {
-return (njs_is_null_or_void(val2));
+if (nv1 || nv2) {
+return (nv1 && nv2);
 }
 
 if (njs_is_numeric(val1) && njs_is_numeric(val2)) {
diff -r c5a3ac902bc2 -r abec5f8d55a1 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Thu Nov 08 16:45:54 2018 +0300
+++ b/njs/test/njs_unit_test.c  Fri Nov 09 18:05:39 2018 +0300
@@ -1025,6 +1025,9 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("null == false"),
   nxt_string("false") },
 
+{ nxt_string("0 == null"),
+  nxt_string("false") },
+
 { nxt_string("!null"),
   nxt_string("true") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed misplaced njs_internal_error().

2018-11-08 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/c5a3ac902bc2
branches:  
changeset: 643:c5a3ac902bc2
user:  Valentin Bartenev 
date:  Thu Nov 08 16:45:54 2018 +0300
description:
Fixed misplaced njs_internal_error().

diffstat:

 njs/njs_variable.c |  3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diffs (16 lines):

diff -r 6ebf35347eee -r c5a3ac902bc2 njs/njs_variable.c
--- a/njs/njs_variable.cWed Nov 07 18:41:29 2018 +0300
+++ b/njs/njs_variable.cThu Nov 08 16:45:54 2018 +0300
@@ -83,10 +83,11 @@ njs_builtin_add(njs_vm_t *vm, njs_parser
 ret = nxt_lvlhsh_insert(>variables, );
 
 if (nxt_fast_path(ret == NXT_OK)) {
-njs_internal_error(vm, "lvlhsh insert failed");
 return var;
 }
 
+njs_internal_error(vm, "lvlhsh insert failed");
+
 nxt_mem_cache_free(vm->mem_cache_pool, var->name.start);
 nxt_mem_cache_free(vm->mem_cache_pool, var);
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed configure process with non-default locale.

2018-07-24 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/7ccf9c0a412a
branches:  
changeset: 568:7ccf9c0a412a
user:  Valentin Bartenev 
date:  Tue Jul 24 19:25:39 2018 +0300
description:
Fixed configure process with non-default locale.

Overriding LANG might not work, since it has less precedence than LC_* settings.
LC_ALL has the highest precedence.

diffstat:

 configure  |  4 ++--
 nxt/auto/configure |  4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diffs (28 lines):

diff -r a4e5abdc345d -r 7ccf9c0a412a configure
--- a/configure Tue Jul 24 18:29:25 2018 +0300
+++ b/configure Tue Jul 24 19:25:39 2018 +0300
@@ -5,8 +5,8 @@
 
 
 # Disable localized program messages.
-LANG=C
-export LANG
+LC_ALL=C
+export LC_ALL
 
 # Stop on error exit status.
 set -e
diff -r a4e5abdc345d -r 7ccf9c0a412a nxt/auto/configure
--- a/nxt/auto/configureTue Jul 24 18:29:25 2018 +0300
+++ b/nxt/auto/configureTue Jul 24 19:25:39 2018 +0300
@@ -5,8 +5,8 @@
 
 
 # Disable localized program messages.
-LANG=C
-export LANG
+LC_ALL=C
+export LC_ALL
 
 # Stop on error exit status.
 set -e
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] String.padStart() and String.padEnd() methods.

2018-07-02 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/31e0580b3c02
branches:  
changeset: 547:31e0580b3c02
user:  Valentin Bartenev 
date:  Fri Jun 29 22:36:41 2018 +0300
description:
String.padStart() and String.padEnd() methods.

diffstat:

 njs/njs_string.c |  125 +++
 njs/test/njs_unit_test.c |   99 +
 2 files changed, 224 insertions(+), 0 deletions(-)

diffs (258 lines):

diff -r f2a2c9674082 -r 31e0580b3c02 njs/njs_string.c
--- a/njs/njs_string.c  Mon Jul 02 16:10:52 2018 +0300
+++ b/njs/njs_string.c  Fri Jun 29 22:36:41 2018 +0300
@@ -64,6 +64,8 @@ static njs_ret_t njs_string_from_char_co
 njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t njs_string_starts_or_ends_with(njs_vm_t *vm, njs_value_t 
*args,
 nxt_uint_t nargs, nxt_bool_t starts);
+static njs_ret_t njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args,
+nxt_uint_t nargs, nxt_bool_t pad_start);
 static njs_ret_t njs_string_match_multiple(njs_vm_t *vm, njs_value_t *args,
 njs_regexp_pattern_t *pattern);
 static njs_ret_t njs_string_split_part_add(njs_vm_t *vm, njs_array_t *array,
@@ -2073,6 +2075,113 @@ njs_string_prototype_repeat(njs_vm_t *vm
 }
 
 
+static njs_ret_t
+njs_string_prototype_pad_start(njs_vm_t *vm, njs_value_t *args,
+nxt_uint_t nargs, njs_index_t unused)
+{
+return njs_string_prototype_pad(vm, args, nargs, 1);
+}
+
+
+static njs_ret_t
+njs_string_prototype_pad_end(njs_vm_t *vm, njs_value_t *args,
+nxt_uint_t nargs, njs_index_t unused)
+{
+return njs_string_prototype_pad(vm, args, nargs, 0);
+}
+
+
+static njs_ret_t
+njs_string_prototype_pad(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+nxt_bool_t pad_start)
+{
+u_char *p, *start;
+size_t padding, trunc, new_size;
+int32_tlength, new_length;
+uint32_t   n, pad_length;
+const u_char   *end;
+njs_string_prop_t  string, pad_string;
+
+length = njs_string_prop(, [0]);
+new_length = nargs > 1 ? args[1].data.u.number : 0;
+
+if (new_length <= length) {
+vm->retval = args[0];
+return NJS_OK;
+}
+
+if (nxt_slow_path(new_length >= NJS_STRING_MAX_LENGTH)) {
+njs_range_error(vm, NULL);
+return NJS_ERROR;
+}
+
+padding = new_length - length;
+
+/* GCC and Clang complain about uninitialized n and trunc. */
+n = 0;
+trunc = 0;
+
+if (nargs > 2) {
+pad_length = njs_string_prop(_string, [2]);
+
+if (pad_string.size == 0) {
+vm->retval = args[0];
+return NJS_OK;
+}
+
+if (pad_string.size > 1) {
+n = padding / pad_length;
+trunc = padding % pad_length;
+
+if (pad_string.size != (size_t) pad_length) {
+/* UTF-8 string. */
+end = pad_string.start + pad_string.size;
+end = njs_string_offset(pad_string.start, end, trunc);
+
+trunc = end - pad_string.start;
+padding = pad_string.size * n + trunc;
+}
+}
+}
+
+new_size = string.size + padding;
+
+start = njs_string_alloc(vm, >retval, new_size, new_length);
+if (nxt_slow_path(start == NULL)) {
+return NJS_ERROR;
+}
+
+p = start;
+
+if (pad_start) {
+start += padding;
+
+} else {
+p += string.size;
+}
+
+memcpy(start, string.start, string.size);
+
+if (nargs == 2) {
+memset(p, ' ', padding);
+
+} else if (pad_string.size == 1) {
+memset(p, pad_string.start[0], padding);
+
+} else {
+while (n != 0) {
+memcpy(p, pad_string.start, pad_string.size);
+p += pad_string.size;
+n--;
+}
+
+memcpy(p, pad_string.start, trunc);
+}
+
+return NJS_OK;
+}
+
+
 /*
  * String.search([regexp])
  */
@@ -3490,6 +3599,22 @@ static const njs_object_prop_t  njs_stri
  NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG),
 },
 
+/* ES8. */
+{
+.type = NJS_METHOD,
+.name = njs_string("padStart"),
+.value = njs_native_function(njs_string_prototype_pad_start, 0,
+ NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_STRING_ARG),
+},
+
+/* ES8. */
+{
+.type = NJS_METHOD,
+.name = njs_string("padEnd"),
+.value = njs_native_function(njs_string_prototype_pad_end, 0,
+ NJS_STRING_OBJECT_ARG, NJS_INTEGER_ARG, NJS_STRING_ARG),
+},
+
 {
 .type = NJS_METHOD,
 .name = njs_string("search"),
diff -r f2a2c9674082 -r 31e0580b3c02 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Mon Jul 02 16:10:52 2018 +0300
+++ b/njs/test/njs_unit_test.c  Fri Jun 29 22:36:41 2018 +0300
@@ -4557,6 +4557,105 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("''.repeat

[njs] Allowed uppercased O in octal literal values.

2018-07-01 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/1cdf9c1a377d
branches:  
changeset: 544:1cdf9c1a377d
user:  Valentin Bartenev 
date:  Sun Jul 01 09:59:45 2018 +0300
description:
Allowed uppercased O in octal literal values.

diffstat:

 njs/njs_lexer.c  |  2 +-
 njs/test/njs_unit_test.c |  7 +--
 2 files changed, 6 insertions(+), 3 deletions(-)

diffs (39 lines):

diff -r a361553ce219 -r 1cdf9c1a377d njs/njs_lexer.c
--- a/njs/njs_lexer.c   Sat Jun 30 20:39:22 2018 +0300
+++ b/njs/njs_lexer.c   Sun Jul 01 09:59:45 2018 +0300
@@ -550,7 +550,7 @@ njs_lexer_number(njs_lexer_t *lexer)
 
 /* Octal literal values. */
 
-if (*p == 'o') {
+if (*p == 'o' || *p == 'O') {
 p++;
 
 if (p == lexer->end) {
diff -r a361553ce219 -r 1cdf9c1a377d njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sat Jun 30 20:39:22 2018 +0300
+++ b/njs/test/njs_unit_test.c  Sun Jul 01 09:59:45 2018 +0300
@@ -118,10 +118,13 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("0o0"),
   nxt_string("0") },
 
+{ nxt_string("0O10"),
+  nxt_string("8") },
+
 { nxt_string("0o011"),
   nxt_string("9") },
 
-{ nxt_string("-0o777"),
+{ nxt_string("-0O777"),
   nxt_string("-511") },
 
 /* Legacy Octal Numbers are deprecated. */
@@ -141,7 +144,7 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("0o"),
   nxt_string("SyntaxError: Unexpected token \"\" in 1") },
 
-{ nxt_string("0o778"),
+{ nxt_string("0O778"),
   nxt_string("SyntaxError: Unexpected token \"\" in 1") },
 
 /* Hex Numbers. */
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Added support of binary literals.

2018-07-01 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/e210675daceb
branches:  
changeset: 545:e210675daceb
user:  Valentin Bartenev 
date:  Sun Jul 01 10:01:53 2018 +0300
description:
Added support of binary literals.

diffstat:

 njs/njs_lexer.c  |  21 +
 njs/njs_number.c |  29 +
 njs/njs_number.h |   1 +
 njs/test/njs_unit_test.c |  20 
 4 files changed, 71 insertions(+), 0 deletions(-)

diffs (111 lines):

diff -r 1cdf9c1a377d -r e210675daceb njs/njs_lexer.c
--- a/njs/njs_lexer.c   Sun Jul 01 09:59:45 2018 +0300
+++ b/njs/njs_lexer.c   Sun Jul 01 10:01:53 2018 +0300
@@ -569,6 +569,27 @@ njs_lexer_number(njs_lexer_t *lexer)
 return NJS_TOKEN_NUMBER;
 }
 
+/* Binary literal values. */
+
+if (*p == 'b' || *p == 'B') {
+p++;
+
+if (p == lexer->end) {
+return NJS_TOKEN_ILLEGAL;
+}
+
+lexer->start = p;
+lexer->number = njs_number_bin_parse((const u_char **) 
>start,
+ lexer->end);
+p = lexer->start;
+
+if (p < lexer->end && (*p >= '2' && *p <= '9')) {
+return NJS_TOKEN_ILLEGAL;
+}
+
+return NJS_TOKEN_NUMBER;
+}
+
 /* Legacy Octal literals are deprecated. */
 
 if (*p >= '0' && *p <= '9') {
diff -r 1cdf9c1a377d -r e210675daceb njs/njs_number.c
--- a/njs/njs_number.c  Sun Jul 01 09:59:45 2018 +0300
+++ b/njs/njs_number.c  Sun Jul 01 10:01:53 2018 +0300
@@ -184,6 +184,35 @@ njs_number_oct_parse(const u_char **star
 
 
 uint64_t
+njs_number_bin_parse(const u_char **start, const u_char *end)
+{
+u_charc;
+uint64_t  num;
+const u_char  *p;
+
+p = *start;
+
+num = 0;
+
+while (p < end) {
+/* Values less than '0' become >= 208. */
+c = *p - '0';
+
+if (nxt_slow_path(c > 1)) {
+break;
+}
+
+num = num * 2 + c;
+p++;
+}
+
+*start = p;
+
+return num;
+}
+
+
+uint64_t
 njs_number_hex_parse(const u_char **start, const u_char *end)
 {
 u_charc;
diff -r 1cdf9c1a377d -r e210675daceb njs/njs_number.h
--- a/njs/njs_number.h  Sun Jul 01 09:59:45 2018 +0300
+++ b/njs/njs_number.h  Sun Jul 01 10:01:53 2018 +0300
@@ -14,6 +14,7 @@
 uint32_t njs_value_to_index(const njs_value_t *value);
 double njs_number_dec_parse(const u_char **start, const u_char *end);
 uint64_t njs_number_oct_parse(const u_char **start, const u_char *end);
+uint64_t njs_number_bin_parse(const u_char **start, const u_char *end);
 uint64_t njs_number_hex_parse(const u_char **start, const u_char *end);
 int64_t njs_number_radix_parse(const u_char **start, const u_char *end,
 uint8_t radix);
diff -r 1cdf9c1a377d -r e210675daceb njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sun Jul 01 09:59:45 2018 +0300
+++ b/njs/test/njs_unit_test.c  Sun Jul 01 10:01:53 2018 +0300
@@ -147,6 +147,26 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("0O778"),
   nxt_string("SyntaxError: Unexpected token \"\" in 1") },
 
+/* Binary Numbers. */
+
+{ nxt_string("0b0"),
+  nxt_string("0") },
+
+{ nxt_string("0B10"),
+  nxt_string("2") },
+
+{ nxt_string("0b0101"),
+  nxt_string("5") },
+
+{ nxt_string("-0B"),
+  nxt_string("-255") },
+
+{ nxt_string("0b"),
+  nxt_string("SyntaxError: Unexpected token \"\" in 1") },
+
+{ nxt_string("0B12"),
+  nxt_string("SyntaxError: Unexpected token \"\" in 1") },
+
 /* Hex Numbers. */
 
 { nxt_string("0x0"),
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed error handling of setting non-numeric Array.length.

2018-06-30 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/a361553ce219
branches:  
changeset: 543:a361553ce219
user:  Valentin Bartenev 
date:  Sat Jun 30 20:39:22 2018 +0300
description:
Fixed error handling of setting non-numeric Array.length.

diffstat:

 njs/njs_array.c |  5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diffs (15 lines):

diff -r 0307e2740df7 -r a361553ce219 njs/njs_array.c
--- a/njs/njs_array.c   Thu Jun 28 17:04:18 2018 +0300
+++ b/njs/njs_array.c   Sat Jun 30 20:39:22 2018 +0300
@@ -375,6 +375,11 @@ njs_array_prototype_length(njs_vm_t *vm,
 array = value->data.u.array;
 
 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;
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Introduced nxt_length() macro.

2018-06-26 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/255c79369f59
branches:  
changeset: 540:255c79369f59
user:  Valentin Bartenev 
date:  Tue Jun 26 18:25:22 2018 +0300
description:
Introduced nxt_length() macro.

diffstat:

 nginx/ngx_http_js_module.c  |   4 ++--
 njs/njs.c   |   2 +-
 njs/njs_extern.c|   2 +-
 njs/njs_json.c  |  10 +-
 njs/njs_parser.c|   2 +-
 njs/njs_string.c|   2 +-
 njs/njs_vm.h|   8 
 nxt/nxt_string.h|   3 ++-
 nxt/test/random_unit_test.c |   2 +-
 nxt/test/utf8_unit_test.c   |   4 ++--
 10 files changed, 20 insertions(+), 19 deletions(-)

diffs (157 lines):

diff -r 711079f55d46 -r 255c79369f59 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.cTue Jun 19 14:07:22 2018 +0300
+++ b/nginx/ngx_http_js_module.cTue Jun 26 18:25:22 2018 +0300
@@ -1157,9 +1157,9 @@ ngx_http_js_ext_set_header_out(njs_vm_t 
 h->value.data = p;
 h->value.len = value->length;
 
-if (h->key.len == sizeof("Content-Length") - 1
+if (h->key.len == nxt_length("Content-Length")
 && ngx_strncasecmp(h->key.data, (u_char *) "Content-Length",
-   sizeof("Content-Length") - 1) == 0)
+   nxt_length("Content-Length")) == 0)
 {
 n = ngx_atoi(value->start, value->length);
 if (n == NGX_ERROR) {
diff -r 711079f55d46 -r 255c79369f59 njs/njs.c
--- a/njs/njs.c Tue Jun 19 14:07:22 2018 +0300
+++ b/njs/njs.c Tue Jun 26 18:25:22 2018 +0300
@@ -131,7 +131,7 @@ njs_vm_create(njs_vm_opt_t *options)
 nxt_lvlhsh_init(>shared->values_hash);
 
 pattern = njs_regexp_pattern_create(vm, (u_char *) "(?:)",
-sizeof("(?:)") - 1, 0);
+nxt_length("(?:)"), 0);
 if (nxt_slow_path(pattern == NULL)) {
 return NULL;
 }
diff -r 711079f55d46 -r 255c79369f59 njs/njs_extern.c
--- a/njs/njs_extern.c  Tue Jun 19 14:07:22 2018 +0300
+++ b/njs/njs_extern.c  Tue Jun 26 18:25:22 2018 +0300
@@ -273,7 +273,7 @@ found:
 len = 0;
 
 for (pr = head; pr != NULL; pr = pr->next) {
-len += pr->str.length + sizeof(".") - 1;
+len += pr->str.length + nxt_length(".");
 }
 
 buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
diff -r 711079f55d46 -r 255c79369f59 njs/njs_json.c
--- a/njs/njs_json.cTue Jun 19 14:07:22 2018 +0300
+++ b/njs/njs_json.cTue Jun 26 18:25:22 2018 +0300
@@ -1400,19 +1400,19 @@ done:
  * The value to stringify is wrapped as '{"": value}'.
  * An empty object means empty result.
  */
-if (str.length <= sizeof("{\n\n}") - 1) {
+if (str.length <= nxt_length("{\n\n}")) {
 vm->retval = njs_value_void;
 return NXT_OK;
 }
 
 /* Stripping the wrapper's data. */
 
-str.start += sizeof("{\"\":") - 1;
-str.length -= sizeof("{\"\":}") - 1;
+str.start += nxt_length("{\"\":");
+str.length -= nxt_length("{\"\":}");
 
 if (stringify->space.length != 0) {
-str.start += sizeof("\n ") - 1;
-str.length -= sizeof("\n \n") - 1;
+str.start += nxt_length("\n ");
+str.length -= nxt_length("\n \n");
 }
 
 length = nxt_utf8_length(str.start, str.length);
diff -r 711079f55d46 -r 255c79369f59 njs/njs_parser.c
--- a/njs/njs_parser.c  Tue Jun 19 14:07:22 2018 +0300
+++ b/njs/njs_parser.c  Tue Jun 26 18:25:22 2018 +0300
@@ -2589,7 +2589,7 @@ njs_parser_trace_handler(nxt_trace_t *tr
 size_tsize;
 njs_vm_t  *vm;
 
-size = sizeof("InternalError: ") - 1;
+size = nxt_length("InternalError: ");
 memcpy(start, "InternalError: ", size);
 p = start + size;
 
diff -r 711079f55d46 -r 255c79369f59 njs/njs_string.c
--- a/njs/njs_string.c  Tue Jun 19 14:07:22 2018 +0300
+++ b/njs/njs_string.c  Tue Jun 26 18:25:22 2018 +0300
@@ -3165,7 +3165,7 @@ njs_string_to_number(const njs_value_t *
 nxt_bool_tminus;
 const u_char  *p, *start, *end;
 
-const size_t  infinity = sizeof("Infinity") - 1;
+const size_t  infinity = nxt_length("Infinity");
 
 size = value->short_string.size;
 
diff -r 711079f55d46 -r 255c79369f59 njs/njs_vm.h
--- a/njs/njs_vm.h  Tue Jun 19 14:07:22 2018 +0300
+++ b/njs/njs_vm.h  Tue Jun 26 18:25:22 2018 +0300
@@ -365,8 +365,8 @@ typedef struct {
 #define njs_string(s) {   \
 .short_string = { 

[nginx] MIME: added font/woff2 type (ticket #1243).

2018-06-15 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/118885f7a577
branches:  
changeset: 7303:118885f7a577
user:  Valentin Bartenev 
date:  Fri Jun 15 17:29:55 2018 +0300
description:
MIME: added font/woff2 type (ticket #1243).

diffstat:

 conf/mime.types |  1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diffs (11 lines):

diff -r bf1a7b363598 -r 118885f7a577 conf/mime.types
--- a/conf/mime.types   Fri Jun 15 17:29:55 2018 +0300
+++ b/conf/mime.types   Fri Jun 15 17:29:55 2018 +0300
@@ -25,6 +25,7 @@ types {
 image/x-ms-bmp   bmp;
 
 font/woffwoff;
+font/woff2   woff2;
 
 application/java-archive jar war ear;
 application/json json;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] MIME: changed type for woff to font/woff (ticket #1243).

2018-06-15 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/bf1a7b363598
branches:  
changeset: 7302:bf1a7b363598
user:  Valentin Bartenev 
date:  Fri Jun 15 17:29:55 2018 +0300
description:
MIME: changed type for woff to font/woff (ticket #1243).

According to RFC 8081 the previously used application/font-woff
type is deprecated.

diffstat:

 conf/mime.types |  3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diffs (13 lines):

diff -r f2396ecf608b -r bf1a7b363598 conf/mime.types
--- a/conf/mime.types   Fri Jun 15 11:46:14 2018 +0300
+++ b/conf/mime.types   Fri Jun 15 17:29:55 2018 +0300
@@ -24,7 +24,8 @@ types {
 image/x-jng  jng;
 image/x-ms-bmp   bmp;
 
-application/font-woffwoff;
+font/woffwoff;
+
 application/java-archive jar war ear;
 application/json json;
 application/mac-binhex40 hqx;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: enforce writing the sync request body buffer to file.

2017-10-04 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/b6dc472299da
branches:  
changeset: 7118:b6dc472299da
user:  Valentin Bartenev <vb...@nginx.com>
date:  Wed Oct 04 21:15:15 2017 +0300
description:
HTTP/2: enforce writing the sync request body buffer to file.

The sync flag of HTTP/2 request body buffer is used when the size of request
body is unknown or bigger than configured "client_body_buffer_size".  In this
case the buffer points to body data inside the global receive buffer that is
used for reading all HTTP/2 connections in the worker process.  Thus, when the
sync flag is set, the buffer must be flushed to a temporary file, otherwise
the request body data can be overwritten.

Previously, the sync buffer wasn't flushed to a temporary file if the whole
body was received in one DATA frame with the END_STREAM flag and wasn't
copied into the HTTP/2 body preread buffer.  As a result, the request body
might be corrupted (ticket #1384).

Now, setting r->request_body_in_file_only enforces writing the sync buffer
to a temporary file in all cases.

diffstat:

 src/http/v2/ngx_http_v2.c |  7 ++-
 1 files changed, 2 insertions(+), 5 deletions(-)

diffs (24 lines):

diff -r dbd77a638eb7 -r b6dc472299da src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Tue Oct 03 18:19:27 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Wed Oct 04 21:15:15 2017 +0300
@@ -3589,11 +3589,6 @@ ngx_http_v2_read_request_body(ngx_http_r
 rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
 
 } else {
-if (stream->preread) {
-/* enforce writing preread buffer to file */
-r->request_body_in_file_only = 1;
-}
-
 rb->buf = ngx_calloc_buf(r->pool);
 
 if (rb->buf != NULL) {
@@ -3694,6 +3689,8 @@ ngx_http_v2_process_request_body(ngx_htt
 buf->pos = buf->start = pos;
 buf->last = buf->end = pos + size;
 
+r->request_body_in_file_only = 1;
+
 } else {
 if (size > (size_t) (buf->end - buf->last)) {
 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] Parenthesized ASCII-related calculations.

2017-07-17 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/e3723f2a11b7
branches:  
changeset: 7067:e3723f2a11b7
user:  Valentin Bartenev <vb...@nginx.com>
date:  Mon Jul 17 17:23:51 2017 +0300
description:
Parenthesized ASCII-related calculations.

This also fixes potential undefined behaviour in the range and slice filter
modules, caused by local overflows of signed integers in expressions.

diffstat:

 src/core/ngx_parse_time.c   |  16 
 src/core/ngx_string.c   |   8 
 src/event/ngx_event_openssl_stapling.c  |   2 +-
 src/http/modules/ngx_http_range_filter_module.c |   4 ++--
 src/http/modules/ngx_http_slice_filter_module.c |   8 
 src/http/ngx_http_parse.c   |  14 +++---
 src/http/ngx_http_upstream.c|   6 +++---
 7 files changed, 29 insertions(+), 29 deletions(-)

diffs (282 lines):

diff -r a27e0c7e198c -r e3723f2a11b7 src/core/ngx_parse_time.c
--- a/src/core/ngx_parse_time.c Wed Jul 12 11:34:04 2017 +0300
+++ b/src/core/ngx_parse_time.c Mon Jul 17 17:23:51 2017 +0300
@@ -58,7 +58,7 @@ ngx_parse_http_time(u_char *value, size_
 return NGX_ERROR;
 }
 
-day = (*p - '0') * 10 + *(p + 1) - '0';
+day = (*p - '0') * 10 + (*(p + 1) - '0');
 p += 2;
 
 if (*p == ' ') {
@@ -132,7 +132,7 @@ ngx_parse_http_time(u_char *value, size_
 }
 
 year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
-   + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
+   + (*(p + 2) - '0') * 10 + (*(p + 3) - '0');
 p += 4;
 
 } else if (fmt == rfc850) {
@@ -140,7 +140,7 @@ ngx_parse_http_time(u_char *value, size_
 return NGX_ERROR;
 }
 
-year = (*p - '0') * 10 + *(p + 1) - '0';
+year = (*p - '0') * 10 + (*(p + 1) - '0');
 year += (year < 70) ? 2000 : 1900;
 p += 2;
 }
@@ -161,7 +161,7 @@ ngx_parse_http_time(u_char *value, size_
 return NGX_ERROR;
 }
 
-day = day * 10 + *p++ - '0';
+day = day * 10 + (*p++ - '0');
 }
 
 if (end - p < 14) {
@@ -177,7 +177,7 @@ ngx_parse_http_time(u_char *value, size_
 return NGX_ERROR;
 }
 
-hour = (*p - '0') * 10 + *(p + 1) - '0';
+hour = (*p - '0') * 10 + (*(p + 1) - '0');
 p += 2;
 
 if (*p++ != ':') {
@@ -188,7 +188,7 @@ ngx_parse_http_time(u_char *value, size_
 return NGX_ERROR;
 }
 
-min = (*p - '0') * 10 + *(p + 1) - '0';
+min = (*p - '0') * 10 + (*(p + 1) - '0');
 p += 2;
 
 if (*p++ != ':') {
@@ -199,7 +199,7 @@ ngx_parse_http_time(u_char *value, size_
 return NGX_ERROR;
 }
 
-sec = (*p - '0') * 10 + *(p + 1) - '0';
+sec = (*p - '0') * 10 + (*(p + 1) - '0');
 
 if (fmt == isoc) {
 p += 2;
@@ -216,7 +216,7 @@ ngx_parse_http_time(u_char *value, size_
 }
 
 year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
-   + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
+   + (*(p + 2) - '0') * 10 + (*(p + 3) - '0');
 }
 
 if (hour > 23 || min > 59 || sec > 59) {
diff -r a27e0c7e198c -r e3723f2a11b7 src/core/ngx_string.c
--- a/src/core/ngx_string.c Wed Jul 12 11:34:04 2017 +0300
+++ b/src/core/ngx_string.c Mon Jul 17 17:23:51 2017 +0300
@@ -178,7 +178,7 @@ ngx_vslprintf(u_char *buf, u_char *last,
 slen = (size_t) -1;
 
 while (*fmt >= '0' && *fmt <= '9') {
-width = width * 10 + *fmt++ - '0';
+width = width * 10 + (*fmt++ - '0');
 }
 
 
@@ -211,7 +211,7 @@ ngx_vslprintf(u_char *buf, u_char *last,
 fmt++;
 
 while (*fmt >= '0' && *fmt <= '9') {
-frac_width = frac_width * 10 + *fmt++ - '0';
+frac_width = frac_width * 10 + (*fmt++ - '0');
 }
 
 break;
@@ -1655,7 +1655,7 @@ ngx_unescape_uri(u_char **dst, u_char **
 state = sw_usual;
 
 if (ch >= '0' && ch <= '9') {
-ch = (u_char) ((decoded << 4) + ch - '0');
+ch = (u_char) ((decoded << 4) + (ch - '0'));
 
 if (type & NGX_UNESCAPE_REDIRECT) {
 if (ch > '%' && ch < 0x7f) {
@@ -1675,7 +1675,7 @@ ngx_unescape_uri(u_char **dst, u_char **
 
 c = (u_char) (ch | 0x20);
 if (c >= 'a' && c <= 'f') {
-ch = (u_char) ((decoded << 4) + c - 'a' + 10);
+ch = (u_char) ((decoded << 4) + (c - 'a') + 10);
 
 if (type & NGX_UNESCAPE_URI) {
 if (ch == '?') {
diff -r a27e0c7e198c -r e3723f2a11b7 src/event/ngx_event_openssl_stapling.c
--- a/src/event/ngx_event_openssl_stapling.cWed Jul 12 11:34:04 2017 +0300
+++ b/src/event/ng

[nginx] HTTP/2: reject HTTP/2 requests without ":scheme" pseudo-header.

2017-06-13 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/3c55863e6887
branches:  
changeset: 7029:3c55863e6887
user:  Piotr Sikora 
date:  Tue Jun 13 17:01:08 2017 +0300
description:
HTTP/2: reject HTTP/2 requests without ":scheme" pseudo-header.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diffs (11 lines):

diff -r e6f399a176e7 -r 3c55863e6887 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Wed Jun 07 18:46:36 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Tue Jun 13 17:01:08 2017 +0300
@@ -3332,6 +3332,7 @@ ngx_http_v2_construct_request_line(ngx_h
 static const u_char ending[] = " HTTP/2.0";
 
 if (r->method_name.len == 0
+|| r->schema_start == NULL
 || r->unparsed_uri.len == 0)
 {
 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: send SETTINGS ACK after applying all SETTINGS params.

2017-06-02 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/859d80f57aab
branches:  
changeset: 7023:859d80f57aab
user:  Piotr Sikora 
date:  Fri Jun 02 15:05:24 2017 +0300
description:
HTTP/2: send SETTINGS ACK after applying all SETTINGS params.

This avoids sending unnecessary SETTINGS ACK in case of PROTOCOL_ERROR.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diffs (21 lines):

diff -r 645ed7112a01 -r 859d80f57aab src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:20 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:24 2017 +0300
@@ -1959,8 +1959,6 @@ ngx_http_v2_state_settings(ngx_http_v2_c
 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
 }
 
-ngx_http_v2_send_settings(h2c, 1);
-
 return ngx_http_v2_state_settings_params(h2c, pos, end);
 }
 
@@ -2026,6 +2024,8 @@ ngx_http_v2_state_settings_params(ngx_ht
 pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
 }
 
+ngx_http_v2_send_settings(h2c, 1);
+
 if (window_delta) {
 if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
 return ngx_http_v2_connection_error(h2c,
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: don't send SETTINGS ACK before already queued DATA frames.

2017-06-02 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/7206c3630310
branches:  
changeset: 7025:7206c3630310
user:  Piotr Sikora 
date:  Fri Jun 02 15:05:32 2017 +0300
description:
HTTP/2: don't send SETTINGS ACK before already queued DATA frames.

Previously, SETTINGS ACK was sent immediately upon receipt of SETTINGS
frame, before already queued DATA frames created using old SETTINGS.

This incorrect behavior was source of interoperability issues, because
peers rely on the fact that new SETTINGS are in effect after receiving
SETTINGS ACK.

Reported by Feng Li.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  2 +-
 src/http/v2/ngx_http_v2.h |  9 +
 2 files changed, 10 insertions(+), 1 deletions(-)

diffs (31 lines):

diff -r 79de0d2aa432 -r 7206c3630310 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:28 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:32 2017 +0300
@@ -2032,7 +2032,7 @@ ngx_http_v2_state_settings_params(ngx_ht
 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
 }
 
-ngx_http_v2_queue_blocked_frame(h2c, frame);
+ngx_http_v2_queue_ordered_frame(h2c, frame);
 
 if (window_delta) {
 if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
diff -r 79de0d2aa432 -r 7206c3630310 src/http/v2/ngx_http_v2.h
--- a/src/http/v2/ngx_http_v2.h Fri Jun 02 15:05:28 2017 +0300
+++ b/src/http/v2/ngx_http_v2.h Fri Jun 02 15:05:32 2017 +0300
@@ -261,6 +261,15 @@ ngx_http_v2_queue_blocked_frame(ngx_http
 }
 
 
+static ngx_inline void
+ngx_http_v2_queue_ordered_frame(ngx_http_v2_connection_t *h2c,
+ngx_http_v2_out_frame_t *frame)
+{
+frame->next = h2c->last_out;
+h2c->last_out = frame;
+}
+
+
 void ngx_http_v2_init(ngx_event_t *rev);
 void ngx_http_v2_request_headers_init(void);
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: make SETTINGS ACK frame reusable.

2017-06-02 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/79de0d2aa432
branches:  
changeset: 7024:79de0d2aa432
user:  Piotr Sikora 
date:  Fri Jun 02 15:05:28 2017 +0300
description:
HTTP/2: make SETTINGS ACK frame reusable.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  62 +-
 1 files changed, 34 insertions(+), 28 deletions(-)

diffs (132 lines):

diff -r 859d80f57aab -r 79de0d2aa432 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:24 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:28 2017 +0300
@@ -28,6 +28,7 @@
 #define NGX_HTTP_V2_HTTP_1_1_REQUIRED0xd
 
 /* frame sizes */
+#define NGX_HTTP_V2_SETTINGS_ACK_SIZE0
 #define NGX_HTTP_V2_RST_STREAM_SIZE  4
 #define NGX_HTTP_V2_PRIORITY_SIZE5
 #define NGX_HTTP_V2_PING_SIZE8
@@ -128,8 +129,7 @@ static ngx_http_v2_node_t *ngx_http_v2_g
 #define ngx_http_v2_index_size(h2scf)  (h2scf->streams_index_mask + 1)
 #define ngx_http_v2_index(h2scf, sid)  ((sid >> 1) & h2scf->streams_index_mask)
 
-static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c,
-ngx_uint_t ack);
+static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c);
 static ngx_int_t ngx_http_v2_settings_frame_handler(
 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
 static ngx_int_t ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c,
@@ -269,7 +269,7 @@ ngx_http_v2_init(ngx_event_t *rev)
 return;
 }
 
-if (ngx_http_v2_send_settings(h2c, 0) == NGX_ERROR) {
+if (ngx_http_v2_send_settings(h2c) == NGX_ERROR) {
 ngx_http_close_connection(c);
 return;
 }
@@ -1967,8 +1967,9 @@ static u_char *
 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
 u_char *end)
 {
-ssize_t window_delta;
-ngx_uint_t  id, value;
+ssize_t   window_delta;
+ngx_uint_tid, value;
+ngx_http_v2_out_frame_t  *frame;
 
 window_delta = 0;
 
@@ -2024,7 +2025,14 @@ ngx_http_v2_state_settings_params(ngx_ht
 pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
 }
 
-ngx_http_v2_send_settings(h2c, 1);
+frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_SETTINGS_ACK_SIZE,
+  NGX_HTTP_V2_SETTINGS_FRAME,
+  NGX_HTTP_V2_ACK_FLAG, 0);
+if (frame == NULL) {
+return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
+}
+
+ngx_http_v2_queue_blocked_frame(h2c, frame);
 
 if (window_delta) {
 if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
@@ -2476,7 +2484,7 @@ ngx_http_v2_parse_int(ngx_http_v2_connec
 
 
 static ngx_int_t
-ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack)
+ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c)
 {
 size_tlen;
 ngx_buf_t*buf;
@@ -2484,8 +2492,8 @@ ngx_http_v2_send_settings(ngx_http_v2_co
 ngx_http_v2_srv_conf_t   *h2scf;
 ngx_http_v2_out_frame_t  *frame;
 
-ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
-   "http2 send SETTINGS frame ack:%ui", ack);
+ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
+   "http2 send SETTINGS frame");
 
 frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t));
 if (frame == NULL) {
@@ -2497,7 +2505,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co
 return NGX_ERROR;
 }
 
-len = ack ? 0 : (sizeof(uint16_t) + sizeof(uint32_t)) * 3;
+len = NGX_HTTP_V2_SETTINGS_PARAM_SIZE * 3;
 
 buf = ngx_create_temp_buf(h2c->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE + len);
 if (buf == NULL) {
@@ -2521,28 +2529,26 @@ ngx_http_v2_send_settings(ngx_http_v2_co
 buf->last = ngx_http_v2_write_len_and_type(buf->last, len,
NGX_HTTP_V2_SETTINGS_FRAME);
 
-*buf->last++ = ack ? NGX_HTTP_V2_ACK_FLAG : NGX_HTTP_V2_NO_FLAG;
+*buf->last++ = NGX_HTTP_V2_NO_FLAG;
 
 buf->last = ngx_http_v2_write_sid(buf->last, 0);
 
-if (!ack) {
-h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
- ngx_http_v2_module);
-
-buf->last = ngx_http_v2_write_uint16(buf->last,
- NGX_HTTP_V2_MAX_STREAMS_SETTING);
-buf->last = ngx_http_v2_write_uint32(buf->last,
- h2scf->concurrent_streams);
-
-buf->last = ngx_http_v2_write_uint16(buf->last,
+h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
+ ngx_http_v2_module);
+
+buf->last = ngx_http_v2_write_uint16(buf->last,
+ NGX_HTTP_V2_MAX_STREAMS_SETTING);
+  

[nginx] HTTP/2: emit new frames only after applying all SETTINGS params.

2017-06-02 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/645ed7112a01
branches:  
changeset: 7022:645ed7112a01
user:  Piotr Sikora 
date:  Fri Jun 02 15:05:20 2017 +0300
description:
HTTP/2: emit new frames only after applying all SETTINGS params.

Previously, new frames could be emitted in the middle of applying
new (and already acknowledged) SETTINGS params, which is illegal.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  17 +++--
 1 files changed, 11 insertions(+), 6 deletions(-)

diffs (43 lines):

diff -r 639e48c382a6 -r 645ed7112a01 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Fri Jun 02 12:55:31 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Fri Jun 02 15:05:20 2017 +0300
@@ -1969,8 +1969,11 @@ static u_char *
 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
 u_char *end)
 {
+ssize_t window_delta;
 ngx_uint_t  id, value;
 
+window_delta = 0;
+
 while (h2c->state.length) {
 if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) {
 return ngx_http_v2_state_save(h2c, pos, end,
@@ -1995,12 +1998,7 @@ ngx_http_v2_state_settings_params(ngx_ht
   NGX_HTTP_V2_FLOW_CTRL_ERROR);
 }
 
-if (ngx_http_v2_adjust_windows(h2c, value - h2c->init_window)
-!= NGX_OK)
-{
-return ngx_http_v2_connection_error(h2c,
-
NGX_HTTP_V2_INTERNAL_ERROR);
-}
+window_delta = value - h2c->init_window;
 
 h2c->init_window = value;
 break;
@@ -2028,6 +2026,13 @@ ngx_http_v2_state_settings_params(ngx_ht
 pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
 }
 
+if (window_delta) {
+if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
+return ngx_http_v2_connection_error(h2c,
+NGX_HTTP_V2_INTERNAL_ERROR);
+}
+}
+
 return ngx_http_v2_state_complete(h2c, pos, end);
 }
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] Version bump.

2017-05-30 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/dfed742c0183
branches:  
changeset: 7015:dfed742c0183
user:  Valentin Bartenev <vb...@nginx.com>
date:  Tue May 30 19:29:45 2017 +0300
description:
Version bump.

diffstat:

 src/core/nginx.h |  4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diffs (14 lines):

diff -r b4cb75066262 -r dfed742c0183 src/core/nginx.h
--- a/src/core/nginx.h  Tue May 30 17:55:23 2017 +0300
+++ b/src/core/nginx.h  Tue May 30 19:29:45 2017 +0300
@@ -9,8 +9,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version  1013001
-#define NGINX_VERSION  "1.13.1"
+#define nginx_version  1013002
+#define NGINX_VERSION  "1.13.2"
 #define NGINX_VER  "nginx/" NGINX_VERSION
 
 #ifdef NGX_BUILD
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: add debug logging of pseudo-headers and cookies.

2017-05-30 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/ab6ef3037840
branches:  
changeset: 7016:ab6ef3037840
user:  Piotr Sikora 
date:  Tue May 30 17:42:27 2017 +0300
description:
HTTP/2: add debug logging of pseudo-headers and cookies.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  62 ++
 1 files changed, 35 insertions(+), 27 deletions(-)

diffs (82 lines):

diff -r dfed742c0183 -r ab6ef3037840 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Tue May 30 19:29:45 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Tue May 30 17:42:27 2017 +0300
@@ -1568,6 +1568,10 @@ ngx_http_v2_state_process_header(ngx_htt
 rc = ngx_http_v2_pseudo_header(r, header);
 
 if (rc == NGX_OK) {
+ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+   "http2 pseudo-header: \":%V: %V\"",
+   >name, >value);
+
 return ngx_http_v2_state_header_complete(h2c, pos, end);
 }
 
@@ -1609,36 +1613,40 @@ ngx_http_v2_state_process_header(ngx_htt
 NGX_HTTP_V2_INTERNAL_ERROR);
 }
 
-return ngx_http_v2_state_header_complete(h2c, pos, end);
-}
-
-h = ngx_list_push(>headers_in.headers);
-if (h == NULL) {
-return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
-}
-
-h->key.len = header->name.len;
-h->key.data = header->name.data;
-
-/* TODO Optimization: precalculate hash and handler for indexed headers. */
-h->hash = ngx_hash_key(h->key.data, h->key.len);
-
-h->value.len = header->value.len;
-h->value.data = header->value.data;
-
-h->lowcase_key = h->key.data;
-
-cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
-hh = ngx_hash_find(>headers_in_hash, h->hash,
-   h->lowcase_key, h->key.len);
-
-if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
-goto error;
+} else {
+h = ngx_list_push(>headers_in.headers);
+if (h == NULL) {
+return ngx_http_v2_connection_error(h2c,
+NGX_HTTP_V2_INTERNAL_ERROR);
+}
+
+h->key.len = header->name.len;
+h->key.data = header->name.data;
+
+/*
+ * TODO Optimization: precalculate hash
+ * and handler for indexed headers.
+ */
+h->hash = ngx_hash_key(h->key.data, h->key.len);
+
+h->value.len = header->value.len;
+h->value.data = header->value.data;
+
+h->lowcase_key = h->key.data;
+
+cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+hh = ngx_hash_find(>headers_in_hash, h->hash,
+   h->lowcase_key, h->key.len);
+
+if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
+goto error;
+}
 }
 
 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-   "http2 http header: \"%V: %V\"", >key, >value);
+   "http2 http header: \"%V: %V\"",
+   >name, >value);
 
 return ngx_http_v2_state_header_complete(h2c, pos, end);
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: fixed segfault when memory allocation failed.

2017-05-23 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/b624fbf7bee2
branches:  
changeset: 7004:b624fbf7bee2
user:  Valentin Bartenev <vb...@nginx.com>
date:  Tue May 23 20:19:39 2017 +0300
description:
HTTP/2: fixed segfault when memory allocation failed.

If allocation of cleanup handler in the HTTP/2 header filter failed, then
a stream might be freed with a HEADERS frame left in the output queue.

Now the HEADERS frame is accounted in the queue before trying to allocate
the cleanup handler.

diffstat:

 src/http/v2/ngx_http_v2_filter_module.c |  4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diffs (21 lines):

diff -r 7943298d4ac0 -r b624fbf7bee2 src/http/v2/ngx_http_v2_filter_module.c
--- a/src/http/v2/ngx_http_v2_filter_module.c   Mon May 22 16:34:47 2017 +0300
+++ b/src/http/v2/ngx_http_v2_filter_module.c   Tue May 23 20:19:39 2017 +0300
@@ -619,6 +619,8 @@ ngx_http_v2_header_filter(ngx_http_reque
 
 ngx_http_v2_queue_blocked_frame(r->stream->connection, frame);
 
+r->stream->queued = 1;
+
 cln = ngx_http_cleanup_add(r, 0);
 if (cln == NULL) {
 return NGX_ERROR;
@@ -627,8 +629,6 @@ ngx_http_v2_header_filter(ngx_http_reque
 cln->handler = ngx_http_v2_filter_cleanup;
 cln->data = r->stream;
 
-r->stream->queued = 1;
-
 fc->send_chain = ngx_http_v2_send_chain;
 fc->need_last_buf = 1;
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: reduced difference to HTTP/1.x in reading request body.

2017-04-24 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/2c4dbcd6f2e4
branches:  
changeset: 6989:2c4dbcd6f2e4
user:  Valentin Bartenev <vb...@nginx.com>
date:  Mon Apr 24 14:17:13 2017 +0300
description:
HTTP/2: reduced difference to HTTP/1.x in reading request body.

Particularly, this eliminates difference in behavior for requests without body
and deduplicates code.

Prodded by Piotr Sikora.

diffstat:

 src/http/ngx_http_request_body.c |  20 
 src/http/v2/ngx_http_v2.c|  28 +---
 src/http/v2/ngx_http_v2.h|   3 +--
 3 files changed, 18 insertions(+), 33 deletions(-)

diffs (115 lines):

diff -r cc823122d50d -r 2c4dbcd6f2e4 src/http/ngx_http_request_body.c
--- a/src/http/ngx_http_request_body.c  Mon Apr 24 14:16:57 2017 +0300
+++ b/src/http/ngx_http_request_body.c  Mon Apr 24 14:17:13 2017 +0300
@@ -46,13 +46,6 @@ ngx_http_read_client_request_body(ngx_ht
 return NGX_OK;
 }
 
-#if (NGX_HTTP_V2)
-if (r->stream) {
-rc = ngx_http_v2_read_request_body(r, post_handler);
-goto done;
-}
-#endif
-
 if (ngx_http_test_expect(r) != NGX_OK) {
 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
 goto done;
@@ -85,6 +78,13 @@ ngx_http_read_client_request_body(ngx_ht
 return NGX_OK;
 }
 
+#if (NGX_HTTP_V2)
+if (r->stream) {
+rc = ngx_http_v2_read_request_body(r);
+goto done;
+}
+#endif
+
 preread = r->header_in->last - r->header_in->pos;
 
 if (preread) {
@@ -805,7 +805,11 @@ ngx_http_test_expect(ngx_http_request_t 
 
 if (r->expect_tested
 || r->headers_in.expect == NULL
-|| r->http_version < NGX_HTTP_VERSION_11)
+|| r->http_version < NGX_HTTP_VERSION_11
+#if (NGX_HTTP_V2)
+|| r->stream != NULL
+#endif
+   )
 {
 return NGX_OK;
 }
diff -r cc823122d50d -r 2c4dbcd6f2e4 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Mon Apr 24 14:16:57 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Mon Apr 24 14:17:13 2017 +0300
@@ -3522,8 +3522,7 @@ ngx_http_v2_run_request(ngx_http_request
 
 
 ngx_int_t
-ngx_http_v2_read_request_body(ngx_http_request_t *r,
-ngx_http_client_body_handler_pt post_handler)
+ngx_http_v2_read_request_body(ngx_http_request_t *r)
 {
 off_t  len;
 size_t size;
@@ -3536,33 +3535,14 @@ ngx_http_v2_read_request_body(ngx_http_r
 ngx_http_v2_connection_t  *h2c;
 
 stream = r->stream;
+rb = r->request_body;
 
 if (stream->skip_data) {
 r->request_body_no_buffering = 0;
-post_handler(r);
+rb->post_handler(r);
 return NGX_OK;
 }
 
-rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
-if (rb == NULL) {
-return NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-/*
- * set by ngx_pcalloc():
- *
- * rb->bufs = NULL;
- * rb->buf = NULL;
- * rb->received = 0;
- * rb->free = NULL;
- * rb->busy = NULL;
- */
-
-rb->rest = 1;
-rb->post_handler = post_handler;
-
-r->request_body = rb;
-
 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
@@ -3612,6 +3592,8 @@ ngx_http_v2_read_request_body(ngx_http_r
 return NGX_HTTP_INTERNAL_SERVER_ERROR;
 }
 
+rb->rest = 1;
+
 buf = stream->preread;
 
 if (stream->in_closed) {
diff -r cc823122d50d -r 2c4dbcd6f2e4 src/http/v2/ngx_http_v2.h
--- a/src/http/v2/ngx_http_v2.h Mon Apr 24 14:16:57 2017 +0300
+++ b/src/http/v2/ngx_http_v2.h Mon Apr 24 14:17:13 2017 +0300
@@ -264,8 +264,7 @@ ngx_http_v2_queue_blocked_frame(ngx_http
 void ngx_http_v2_init(ngx_event_t *rev);
 void ngx_http_v2_request_headers_init(void);
 
-ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r,
-ngx_http_client_body_handler_pt post_handler);
+ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r);
 ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r);
 
 void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc);
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] Core: improved JSON escaping.

2017-04-12 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/289403abc84e
branches:  
changeset: 6974:289403abc84e
user:  Valentin Bartenev <vb...@nginx.com>
date:  Wed Apr 12 22:47:57 2017 +0300
description:
Core: improved JSON escaping.

Two-character representations are now used for \b, \f, \n, \r, and \t.

diffstat:

 src/core/ngx_string.c |  51 ---
 1 files changed, 44 insertions(+), 7 deletions(-)

diffs (68 lines):

diff -r 99934aade555 -r 289403abc84e src/core/ngx_string.c
--- a/src/core/ngx_string.c Wed Apr 12 22:21:04 2017 +0300
+++ b/src/core/ngx_string.c Wed Apr 12 22:47:57 2017 +0300
@@ -1808,7 +1808,19 @@ ngx_escape_json(u_char *dst, u_char *src
 len++;
 
 } else if (ch <= 0x1f) {
-len += sizeof("\\u001F") - 2;
+
+switch (ch) {
+case '\n':
+case '\r':
+case '\t':
+case '\b':
+case '\f':
+len++;
+break;
+
+default:
+len += sizeof("\\u001F") - 2;
+}
 }
 
 size--;
@@ -1829,12 +1841,37 @@ ngx_escape_json(u_char *dst, u_char *src
 *dst++ = ch;
 
 } else {
-*dst++ = '\\'; *dst++ = 'u'; *dst++ = '0'; *dst++ = '0';
-*dst++ = '0' + (ch >> 4);
-
-ch &= 0xf;
-
-*dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10);
+*dst++ = '\\';
+
+switch (ch) {
+case '\n':
+*dst++ = 'n';
+break;
+
+case '\r':
+*dst++ = 'r';
+break;
+
+case '\t':
+*dst++ = 't';
+break;
+
+case '\b':
+*dst++ = 'b';
+break;
+
+case '\f':
+*dst++ = 'f';
+break;
+
+default:
+*dst++ = 'u'; *dst++ = '0'; *dst++ = '0';
+*dst++ = '0' + (ch >> 4);
+
+ch &= 0xf;
+
+*dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10);
+}
 }
 
 size--;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: style and typos.

2017-03-30 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/28dc369899ea
branches:  
changeset: 6958:28dc369899ea
user:  Piotr Sikora 
date:  Sun Mar 26 01:25:01 2017 -0700
description:
HTTP/2: style and typos.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  11 ++-
 src/http/v2/ngx_http_v2.h |   4 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diffs (69 lines):

diff -r 83bae3d354ab -r 28dc369899ea src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Wed Mar 29 20:21:01 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:01 2017 -0700
@@ -941,7 +941,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_
 
 if (size >= h2c->state.length) {
 size = h2c->state.length;
-stream->in_closed  = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
+stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
 }
 
 r = stream->request;
@@ -1905,7 +1905,7 @@ ngx_http_v2_state_rst_stream(ngx_http_v2
 
 if (node == NULL || node->stream == NULL) {
 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
-"unknown http2 stream");
+   "unknown http2 stream");
 
 return ngx_http_v2_state_complete(h2c, pos, end);
 }
@@ -2019,6 +2019,7 @@ ngx_http_v2_state_settings_params(ngx_ht
 break;
 
 case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING:
+
 if (value > NGX_HTTP_V2_MAX_FRAME_SIZE
 || value < NGX_HTTP_V2_DEFAULT_FRAME_SIZE)
 {
@@ -3076,7 +3077,7 @@ ngx_http_v2_pseudo_header(ngx_http_reque
 }
 
 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-  "client sent unknown pseudo header \"%V\"",
+  "client sent unknown pseudo-header \":%V\"",
   >name);
 
 return NGX_DECLINED;
@@ -3223,14 +3224,14 @@ ngx_http_v2_parse_scheme(ngx_http_reques
 {
 if (r->schema_start) {
 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-  "client sent duplicate :schema header");
+  "client sent duplicate :scheme header");
 
 return NGX_DECLINED;
 }
 
 if (header->value.len == 0) {
 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-  "client sent empty :schema header");
+  "client sent empty :scheme header");
 
 return NGX_DECLINED;
 }
diff -r 83bae3d354ab -r 28dc369899ea src/http/v2/ngx_http_v2.h
--- a/src/http/v2/ngx_http_v2.h Wed Mar 29 20:21:01 2017 +0300
+++ b/src/http/v2/ngx_http_v2.h Sun Mar 26 01:25:01 2017 -0700
@@ -249,8 +249,8 @@ ngx_http_v2_queue_blocked_frame(ngx_http
 {
 ngx_http_v2_out_frame_t  **out;
 
-for (out = >last_out; *out; out = &(*out)->next)
-{
+for (out = >last_out; *out; out = &(*out)->next) {
+
 if ((*out)->blocked || (*out)->stream == NULL) {
 break;
 }
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: fixed stream finalization.

2017-03-29 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/9b5f31fdb850
branches:  
changeset: 6956:9b5f31fdb850
user:  Valentin Bartenev <vb...@nginx.com>
date:  Wed Mar 29 20:16:23 2017 +0300
description:
HTTP/2: fixed stream finalization.

In order to finalize stream the error flag is set on fake connection and
either "write" or "read" event handler is called.  The read events of fake
connections are always ready, but it's not the case with the write events.

When the ready flag isn't set, the error flag can be not checked in some
cases and as a result stream isn't finalized.  Now the ready flag is
explicilty set on write events for proper finalization in all cases.

diffstat:

 src/http/v2/ngx_http_v2.c |  3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diffs (14 lines):

diff -r d38161da62cd -r 9b5f31fdb850 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:05 2017 -0700
+++ b/src/http/v2/ngx_http_v2.c Wed Mar 29 20:16:23 2017 +0300
@@ -4266,7 +4266,10 @@ ngx_http_v2_finalize_connection(ngx_http
 
 if (stream->queued) {
 stream->queued = 0;
+
 ev = fc->write;
+ev->active = 0;
+ev->ready = 1;
 
 } else {
 ev = fc->read;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: emit PROTOCOL_ERROR on padding errors.

2017-03-29 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/d38161da62cd
branches:  
changeset: 6955:d38161da62cd
user:  Piotr Sikora 
date:  Sun Mar 26 01:25:05 2017 -0700
description:
HTTP/2: emit PROTOCOL_ERROR on padding errors.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diffs (23 lines):

diff -r 052305810ca4 -r d38161da62cd src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:04 2017 -0700
+++ b/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:05 2017 -0700
@@ -812,7 +812,8 @@ ngx_http_v2_state_data(ngx_http_v2_conne
   "with incorrect length: %uz, padding: %uz",
   size, h2c->state.padding);
 
-return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
+return ngx_http_v2_connection_error(h2c,
+NGX_HTTP_V2_PROTOCOL_ERROR);
 }
 
 h2c->state.length -= 1 + h2c->state.padding;
@@ -1055,7 +1056,8 @@ ngx_http_v2_state_headers(ngx_http_v2_co
   "with incorrect length: %uz, padding: %uz",
   h2c->state.length, h2c->state.padding);
 
-return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
+return ngx_http_v2_connection_error(h2c,
+NGX_HTTP_V2_PROTOCOL_ERROR);
 }
 
 h2c->state.length -= h2c->state.padding;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: fix flow control with padded DATA frames.

2017-03-29 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/052305810ca4
branches:  
changeset: 6954:052305810ca4
user:  Piotr Sikora 
date:  Sun Mar 26 01:25:04 2017 -0700
description:
HTTP/2: fix flow control with padded DATA frames.

Previously, flow control didn't account for padding in DATA frames,
which meant that its view of the world could drift from peer's view
by up to 256 bytes per received padded DATA frame, which could lead
to a deadlock.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2.c |  24 +---
 1 files changed, 13 insertions(+), 11 deletions(-)

diffs (80 lines):

diff -r 663e6a48bfcb -r 052305810ca4 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:03 2017 -0700
+++ b/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:04 2017 -0700
@@ -783,9 +783,12 @@ ngx_http_v2_state_head(ngx_http_v2_conne
 static u_char *
 ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
 {
+size_t size;
 ngx_http_v2_node_t*node;
 ngx_http_v2_stream_t  *stream;
 
+size = h2c->state.length;
+
 if (h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG) {
 
 if (h2c->state.length == 0) {
@@ -802,33 +805,32 @@ ngx_http_v2_state_data(ngx_http_v2_conne
 }
 
 h2c->state.padding = *pos++;
-h2c->state.length--;
-
-if (h2c->state.padding > h2c->state.length) {
+
+if (h2c->state.padding >= size) {
 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
   "client sent padded DATA frame "
   "with incorrect length: %uz, padding: %uz",
-  h2c->state.length, h2c->state.padding);
+  size, h2c->state.padding);
 
 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
 }
 
-h2c->state.length -= h2c->state.padding;
+h2c->state.length -= 1 + h2c->state.padding;
 }
 
 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"http2 DATA frame");
 
-if (h2c->state.length > h2c->recv_window) {
+if (size > h2c->recv_window) {
 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
   "client violated connection flow control: "
   "received DATA frame length %uz, available window %uz",
-  h2c->state.length, h2c->recv_window);
+  size, h2c->recv_window);
 
 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_FLOW_CTRL_ERROR);
 }
 
-h2c->recv_window -= h2c->state.length;
+h2c->recv_window -= size;
 
 if (h2c->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) {
 
@@ -854,11 +856,11 @@ ngx_http_v2_state_data(ngx_http_v2_conne
 
 stream = node->stream;
 
-if (h2c->state.length > stream->recv_window) {
+if (size > stream->recv_window) {
 ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
   "client violated flow control for stream %ui: "
   "received DATA frame length %uz, available window %uz",
-  node->id, h2c->state.length, stream->recv_window);
+  node->id, size, stream->recv_window);
 
 if (ngx_http_v2_terminate_stream(h2c, stream,
  NGX_HTTP_V2_FLOW_CTRL_ERROR)
@@ -871,7 +873,7 @@ ngx_http_v2_state_data(ngx_http_v2_conne
 return ngx_http_v2_state_skip_padded(h2c, pos, end);
 }
 
-stream->recv_window -= h2c->state.length;
+stream->recv_window -= size;
 
 if (stream->no_flow_control
 && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4)
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: fix $body_bytes_sent variable.

2017-03-29 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/663e6a48bfcb
branches:  
changeset: 6953:663e6a48bfcb
user:  Piotr Sikora 
date:  Sun Mar 26 01:25:03 2017 -0700
description:
HTTP/2: fix $body_bytes_sent variable.

Previously, its value included payloads and frame headers of HEADERS
and CONTINUATION frames.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2_filter_module.c |  3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diffs (13 lines):

diff -r afc60bd9008f -r 663e6a48bfcb src/http/v2/ngx_http_v2_filter_module.c
--- a/src/http/v2/ngx_http_v2_filter_module.c   Sun Mar 26 01:25:02 2017 -0700
+++ b/src/http/v2/ngx_http_v2_filter_module.c   Sun Mar 26 01:25:03 2017 -0700
@@ -1211,6 +1211,9 @@ ngx_http_v2_headers_frame_handler(ngx_ht
"http2:%ui HEADERS frame %p was sent",
stream->node->id, frame);
 
+stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE
++ frame->length;
+
 ngx_http_v2_handle_frame(stream, frame);
 
 ngx_http_v2_handle_stream(h2c, stream);
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: fix $bytes_sent variable.

2017-03-29 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/afc60bd9008f
branches:  
changeset: 6952:afc60bd9008f
user:  Piotr Sikora 
date:  Sun Mar 26 01:25:02 2017 -0700
description:
HTTP/2: fix $bytes_sent variable.

Previously, its value accounted for payloads of HEADERS, CONTINUATION
and DATA frames, as well as frame headers of HEADERS and DATA frames,
but it didn't account for frame headers of CONTINUATION frames.

Signed-off-by: Piotr Sikora 

diffstat:

 src/http/v2/ngx_http_v2_filter_module.c |  2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diffs (12 lines):

diff -r ce37362a7a70 -r afc60bd9008f src/http/v2/ngx_http_v2_filter_module.c
--- a/src/http/v2/ngx_http_v2_filter_module.c   Tue Mar 28 18:15:42 2017 +0300
+++ b/src/http/v2/ngx_http_v2_filter_module.c   Sun Mar 26 01:25:02 2017 -0700
@@ -769,6 +769,8 @@ ngx_http_v2_create_headers_frame(ngx_htt
 rest -= frame_size;
 
 if (rest) {
+frame->length += NGX_HTTP_V2_FRAME_HEADER_SIZE;
+
 type = NGX_HTTP_V2_CONTINUATION_FRAME;
 flags = NGX_HTTP_V2_NO_FLAG;
 continue;
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Test for right-associativity of exponential operator.

2016-12-23 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/58342f302de3
branches:  
changeset: 289:58342f302de3
user:  Valentin Bartenev <vb...@nginx.com>
date:  Fri Dec 23 19:42:15 2016 +0300
description:
Test for right-associativity of exponential operator.

diffstat:

 njs/test/njs_unit_test.c |  3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diffs (13 lines):

diff -r f5225d9cc97b -r 58342f302de3 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Mon Dec 19 14:19:59 2016 +0300
+++ b/njs/test/njs_unit_test.c  Fri Dec 23 19:42:15 2016 +0300
@@ -226,6 +226,9 @@ static njs_unit_test_t  njs_test[] =
 
 /* Exponentiation. */
 
+{ nxt_string("2 ** 3 ** 2"),
+  nxt_string("512") },
+
 { nxt_string("2 ** (3 ** 2)"),
   nxt_string("512") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] The nxt_expect() macro.

2016-12-19 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/a76d7066a117
branches:  
changeset: 287:a76d7066a117
user:  Valentin Bartenev <vb...@nginx.com>
date:  Mon Dec 19 14:19:43 2016 +0300
description:
The nxt_expect() macro.

diffstat:

 nxt/nxt_clang.h |  6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diffs (18 lines):

diff -r 631a3be91d22 -r a76d7066a117 nxt/nxt_clang.h
--- a/nxt/nxt_clang.h   Fri Dec 16 17:52:15 2016 +0300
+++ b/nxt/nxt_clang.h   Mon Dec 19 14:19:43 2016 +0300
@@ -27,10 +27,12 @@
 
 
 #if (NXT_HAVE_BUILTIN_EXPECT)
-#define nxt_fast_path(x)   __builtin_expect((long) (x), 1)
-#define nxt_slow_path(x)   __builtin_expect((long) (x), 0)
+#define nxt_expect(c, x)   __builtin_expect((long) (x), (c))
+#define nxt_fast_path(x)   nxt_expect(1, x)
+#define nxt_slow_path(x)   nxt_expect(0, x)
 
 #else
+#define nxt_expect(c, x)   (x)
 #define nxt_fast_path(x)   (x)
 #define nxt_slow_path(x)   (x)
 #endif
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Exponentiation operators.

2016-12-19 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/f5225d9cc97b
branches:  
changeset: 288:f5225d9cc97b
user:  Valentin Bartenev <vb...@nginx.com>
date:  Mon Dec 19 14:19:59 2016 +0300
description:
Exponentiation operators.

diffstat:

 njs/njs_disassembler.c  |2 +
 njs/njs_generator.c |2 +
 njs/njs_lexer.c |6 +
 njs/njs_parser.h|3 +
 njs/njs_parser_expression.c |   76 +-
 njs/njs_vm.c|   34 +
 njs/njs_vm.h|2 +
 njs/test/njs_unit_test.c|  157 
 8 files changed, 281 insertions(+), 1 deletions(-)

diffs (406 lines):

diff -r a76d7066a117 -r f5225d9cc97b njs/njs_disassembler.c
--- a/njs/njs_disassembler.cMon Dec 19 14:19:43 2016 +0300
+++ b/njs/njs_disassembler.cMon Dec 19 14:19:59 2016 +0300
@@ -87,6 +87,8 @@ static njs_code_name_t  code_names[] = {
   nxt_string("SUBSTRACT   ") },
 { njs_vmcode_multiplication, sizeof(njs_vmcode_3addr_t),
   nxt_string("MULTIPLY") },
+{ njs_vmcode_exponentiation, sizeof(njs_vmcode_3addr_t),
+  nxt_string("POWER   ") },
 { njs_vmcode_division, sizeof(njs_vmcode_3addr_t),
   nxt_string("DIVIDE  ") },
 { njs_vmcode_remainder, sizeof(njs_vmcode_3addr_t),
diff -r a76d7066a117 -r f5225d9cc97b njs/njs_generator.c
--- a/njs/njs_generator.c   Mon Dec 19 14:19:43 2016 +0300
+++ b/njs/njs_generator.c   Mon Dec 19 14:19:59 2016 +0300
@@ -184,6 +184,7 @@ njs_generator(njs_vm_t *vm, njs_parser_t
 case NJS_TOKEN_ADDITION_ASSIGNMENT:
 case NJS_TOKEN_SUBSTRACTION_ASSIGNMENT:
 case NJS_TOKEN_MULTIPLICATION_ASSIGNMENT:
+case NJS_TOKEN_EXPONENTIATION_ASSIGNMENT:
 case NJS_TOKEN_DIVISION_ASSIGNMENT:
 case NJS_TOKEN_REMAINDER_ASSIGNMENT:
 return njs_generate_operation_assignment(vm, parser, node);
@@ -219,6 +220,7 @@ njs_generator(njs_vm_t *vm, njs_parser_t
 case NJS_TOKEN_ADDITION:
 case NJS_TOKEN_SUBSTRACTION:
 case NJS_TOKEN_MULTIPLICATION:
+case NJS_TOKEN_EXPONENTIATION:
 case NJS_TOKEN_DIVISION:
 case NJS_TOKEN_REMAINDER:
 case NJS_TOKEN_PROPERTY_DELETE:
diff -r a76d7066a117 -r f5225d9cc97b njs/njs_lexer.c
--- a/njs/njs_lexer.c   Mon Dec 19 14:19:43 2016 +0300
+++ b/njs/njs_lexer.c   Mon Dec 19 14:19:59 2016 +0300
@@ -203,8 +203,14 @@ static const njs_lexer_multi_t  njs_subs
 };
 
 
+static const njs_lexer_multi_t  njs_exponentiation_token[] = {
+{ '=', NJS_TOKEN_EXPONENTIATION_ASSIGNMENT, 0, NULL },
+};
+
+
 static const njs_lexer_multi_t  njs_multiplication_token[] = {
 { '=', NJS_TOKEN_MULTIPLICATION_ASSIGNMENT, 0, NULL },
+{ '*', NJS_TOKEN_EXPONENTIATION, 1, njs_exponentiation_token },
 };
 
 
diff -r a76d7066a117 -r f5225d9cc97b njs/njs_parser.h
--- a/njs/njs_parser.h  Mon Dec 19 14:19:43 2016 +0300
+++ b/njs/njs_parser.h  Mon Dec 19 14:19:59 2016 +0300
@@ -41,6 +41,7 @@ typedef enum {
 NJS_TOKEN_ADDITION_ASSIGNMENT,
 NJS_TOKEN_SUBSTRACTION_ASSIGNMENT,
 NJS_TOKEN_MULTIPLICATION_ASSIGNMENT,
+NJS_TOKEN_EXPONENTIATION_ASSIGNMENT,
 NJS_TOKEN_DIVISION_ASSIGNMENT,
 NJS_TOKEN_REMAINDER_ASSIGNMENT,
 NJS_TOKEN_LEFT_SHIFT_ASSIGNMENT,
@@ -69,6 +70,8 @@ typedef enum {
 
 NJS_TOKEN_MULTIPLICATION,
 
+NJS_TOKEN_EXPONENTIATION,
+
 NJS_TOKEN_DIVISION,
 
 NJS_TOKEN_REMAINDER,
diff -r a76d7066a117 -r f5225d9cc97b njs/njs_parser_expression.c
--- a/njs/njs_parser_expression.c   Mon Dec 19 14:19:43 2016 +0300
+++ b/njs/njs_parser_expression.c   Mon Dec 19 14:19:59 2016 +0300
@@ -63,6 +63,9 @@ static njs_token_t njs_parser_conditiona
 static njs_token_t njs_parser_binary_expression(njs_vm_t *vm,
 njs_parser_t *parser, const njs_parser_expression_t *expr,
 njs_token_t token);
+static njs_token_t njs_parser_exponential_expression(njs_vm_t *vm,
+njs_parser_t *parser, const njs_parser_expression_t *expr,
+njs_token_t token);
 static njs_token_t njs_parser_unary_expression(njs_vm_t *vm,
 njs_parser_t *parser, const njs_parser_expression_t *expr,
 njs_token_t token);
@@ -83,7 +86,7 @@ static njs_token_t njs_parser_property_b
 static const njs_parser_expression_t
 njs_parser_factor_expression =
 {
-njs_parser_unary_expression,
+njs_parser_exponential_expression,
 NULL,
 3, {
 { NJS_TOKEN_MULTIPLICATION, njs_vmcode_multiplication,
@@ -391,6 +394,11 @@ njs_parser_assignment_expression(njs_vm_
 operation = njs_vmcode_multiplication;
 break;
 
+case NJS_TOKEN_EXPONENTIATION_ASSIGNMENT:
+nxt_thread_log_debug("JS: **=");
+operation = njs_vmcode_exponentiation;
+break;
+
 case NJS_TOKEN_DIVISION_ASSIGNMENT:
 nxt_thread_log_debug("JS: /=");
 operation = njs_vmcode_division;
@@ -685,6 +693,64 @@ njs_parser_binary_expression(njs_vm_t *v
 

[nginx] Access log: support for json escaping.

2016-12-15 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/0cf4e82e7c48
branches:  
changeset: 6840:0cf4e82e7c48
user:  Valentin Bartenev <vb...@nginx.com>
date:  Thu Dec 15 16:25:42 2016 +0300
description:
Access log: support for json escaping.

diffstat:

 src/http/modules/ngx_http_log_module.c |  83 +++--
 src/stream/ngx_stream_log_module.c |  83 +++--
 2 files changed, 154 insertions(+), 12 deletions(-)

diffs (275 lines):

diff -r 32714e608629 -r 0cf4e82e7c48 src/http/modules/ngx_http_log_module.c
--- a/src/http/modules/ngx_http_log_module.cTue Dec 13 00:49:44 2016 +0100
+++ b/src/http/modules/ngx_http_log_module.cThu Dec 15 16:25:42 2016 +0300
@@ -126,12 +126,16 @@ static u_char *ngx_http_log_request_leng
 ngx_http_log_op_t *op);
 
 static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
-ngx_http_log_op_t *op, ngx_str_t *value);
+ngx_http_log_op_t *op, ngx_str_t *value, ngx_uint_t json);
 static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
 uintptr_t data);
 static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
 ngx_http_log_op_t *op);
 static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
+static size_t ngx_http_log_json_variable_getlen(ngx_http_request_t *r,
+uintptr_t data);
+static u_char *ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf,
+ngx_http_log_op_t *op);
 
 
 static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
@@ -909,7 +913,7 @@ ngx_http_log_request_length(ngx_http_req
 
 static ngx_int_t
 ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
-ngx_str_t *value)
+ngx_str_t *value, ngx_uint_t json)
 {
 ngx_int_t  index;
 
@@ -919,8 +923,16 @@ ngx_http_log_variable_compile(ngx_conf_t
 }
 
 op->len = 0;
-op->getlen = ngx_http_log_variable_getlen;
-op->run = ngx_http_log_variable;
+
+if (json) {
+op->getlen = ngx_http_log_json_variable_getlen;
+op->run = ngx_http_log_json_variable;
+
+} else {
+op->getlen = ngx_http_log_variable_getlen;
+op->run = ngx_http_log_variable;
+}
+
 op->data = index;
 
 return NGX_OK;
@@ -1028,6 +1040,47 @@ ngx_http_log_escape(u_char *dst, u_char 
 }
 
 
+static size_t
+ngx_http_log_json_variable_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+uintptr_t   len;
+ngx_http_variable_value_t  *value;
+
+value = ngx_http_get_indexed_variable(r, data);
+
+if (value == NULL || value->not_found) {
+return 0;
+}
+
+len = ngx_escape_json(NULL, value->data, value->len);
+
+value->escape = len ? 1 : 0;
+
+return value->len + len;
+}
+
+
+static u_char *
+ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf,
+ngx_http_log_op_t *op)
+{
+ngx_http_variable_value_t  *value;
+
+value = ngx_http_get_indexed_variable(r, op->data);
+
+if (value == NULL || value->not_found) {
+return buf;
+}
+
+if (value->escape == 0) {
+return ngx_cpymem(buf, value->data, value->len);
+
+} else {
+return (u_char *) ngx_escape_json(buf, value->data, value->len);
+}
+}
+
+
 static void *
 ngx_http_log_create_main_conf(ngx_conf_t *cf)
 {
@@ -1491,12 +1544,28 @@ ngx_http_log_compile_format(ngx_conf_t *
 size_t   i, len;
 ngx_str_t   *value, var;
 ngx_int_t   *flush;
-ngx_uint_t   bracket;
+ngx_uint_t   bracket, json;
 ngx_http_log_op_t   *op;
 ngx_http_log_var_t  *v;
 
+json = 0;
 value = args->elts;
 
+if (s < args->nelts && ngx_strncmp(value[s].data, "escape=", 7) == 0) {
+data = value[s].data + 7;
+
+if (ngx_strcmp(data, "json") == 0) {
+json = 1;
+
+} else if (ngx_strcmp(data, "default") != 0) {
+ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+   "unknown log format escaping \"%s\"", data);
+return NGX_CONF_ERROR;
+}
+
+s++;
+}
+
 for ( /* void */ ; s < args->nelts; s++) {
 
 i = 0;
@@ -1575,7 +1644,9 @@ ngx_http_log_compile_format(ngx_conf_t *
 }
 }
 
-if (ngx_http_log_variable_compile(cf, op, ) != NGX_OK) {
+if (ngx_http_log_variable_compile(cf, op, , json)
+!= NGX_OK)
+{
 return NGX_CONF_ERROR;
 }
 
diff -r 32714e608629 -r 0cf4e82e7c48 src/stream/ngx_stream_log_module.c
--- a/src/stream/ngx_stream_log_module.cTue Dec 13 00:49:44 2016 +0100
+++ b/src/stream/ngx_stream_log_module.cThu Dec 15 16:25:42 2016 +0300
@@ -106,12 +106,16 @@ static void ngx_stream_log_flush(ngx_ope
 static void ngx_stream_log_flush_handler(ngx_event_t *ev);
 

[njs] Math.pow() method fix.

2016-12-08 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/db0d8e2a4928
branches:  
changeset: 280:db0d8e2a4928
user:  Valentin Bartenev <vb...@nginx.com>
date:  Thu Dec 08 01:52:41 2016 +0300
description:
Math.pow() method fix.

diffstat:

 njs/njs_math.c   |  12 -
 njs/test/njs_unit_test.c |  60 
 2 files changed, 71 insertions(+), 1 deletions(-)

diffs (92 lines):

diff -r 6a60530c7b6b -r db0d8e2a4928 njs/njs_math.c
--- a/njs/njs_math.cThu Dec 08 19:50:03 2016 +0300
+++ b/njs/njs_math.cThu Dec 08 01:52:41 2016 +0300
@@ -578,7 +578,17 @@ njs_object_math_pow(njs_vm_t *vm, njs_va
 base = args[1].data.u.number;
 exponent = args[2].data.u.number;
 
-num = pow(base, exponent);
+/*
+ * Accordig to ECMA-262 the result of Math.pow(+/-1, +/-Infinity)
+ * should be NaN.
+ */
+
+if (fabs(base) != 1 || !isinf(exponent)) {
+num = pow(base, exponent);
+
+} else {
+num = NAN;
+}
 
 } else {
 num = NAN;
diff -r 6a60530c7b6b -r db0d8e2a4928 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Thu Dec 08 19:50:03 2016 +0300
+++ b/njs/test/njs_unit_test.c  Thu Dec 08 01:52:41 2016 +0300
@@ -6215,6 +6215,66 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("Math.pow()"),
   nxt_string("NaN") },
 
+{ nxt_string("Math.pow('a', -0)"),
+  nxt_string("1") },
+
+{ nxt_string("Math.pow(1.1, Infinity)"),
+  nxt_string("Infinity") },
+
+{ nxt_string("Math.pow(-1.1, -Infinity)"),
+  nxt_string("0") },
+
+{ nxt_string("Math.pow(-1, Infinity)"),
+  nxt_string("NaN") },
+
+{ nxt_string("Math.pow(1, -Infinity)"),
+  nxt_string("NaN") },
+
+{ nxt_string("Math.pow(-0.9, Infinity)"),
+  nxt_string("0") },
+
+{ nxt_string("Math.pow(0.9, -Infinity)"),
+  nxt_string("Infinity") },
+
+{ nxt_string("Math.pow('Infinity', 0.1)"),
+  nxt_string("Infinity") },
+
+{ nxt_string("Math.pow(Infinity, '-0.1')"),
+  nxt_string("0") },
+
+{ nxt_string("Math.pow(-Infinity, 3)"),
+  nxt_string("-Infinity") },
+
+{ nxt_string("Math.pow('-Infinity', '3.1')"),
+  nxt_string("Infinity") },
+
+{ nxt_string("Math.pow(-Infinity, '-3')"),
+  nxt_string("-0") },
+
+{ nxt_string("Math.pow('-Infinity', -2)"),
+  nxt_string("0") },
+
+{ nxt_string("Math.pow('0', 0.1)"),
+  nxt_string("0") },
+
+{ nxt_string("Math.pow(0, '-0.1')"),
+  nxt_string("Infinity") },
+
+{ nxt_string("Math.pow(-0, 3)"),
+  nxt_string("-0") },
+
+{ nxt_string("Math.pow('-0', '3.1')"),
+  nxt_string("0") },
+
+{ nxt_string("Math.pow(-0, '-3')"),
+  nxt_string("-Infinity") },
+
+{ nxt_string("Math.pow('-0', -2)"),
+  nxt_string("Infinity") },
+
+{ nxt_string("Math.pow(-3, 0.1)"),
+  nxt_string("NaN") },
+
 { nxt_string("var a = Math.random(); a >= 0 && a < 1"),
   nxt_string("true") },
 
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] NXT_DEBUG_MEMORY macro.

2016-12-08 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/af66e460d7a0
branches:  
changeset: 278:af66e460d7a0
user:  Valentin Bartenev <vb...@nginx.com>
date:  Thu Dec 08 19:29:40 2016 +0300
description:
NXT_DEBUG_MEMORY macro.

It allows to turn off accumulation of small pool allocations into a big
preallocated chunk of memory.  This is useful for debugging memory access
with sanitizer, since such accumulation can cover buffer overruns from
being detected.

diffstat:

 nxt/nxt_mem_cache_pool.c |  14 ++
 1 files changed, 14 insertions(+), 0 deletions(-)

diffs (69 lines):

diff -r 0315d62a78c2 -r af66e460d7a0 nxt/nxt_mem_cache_pool.c
--- a/nxt/nxt_mem_cache_pool.c  Thu Dec 08 17:15:54 2016 +0300
+++ b/nxt/nxt_mem_cache_pool.c  Thu Dec 08 19:29:40 2016 +0300
@@ -124,12 +124,14 @@ struct nxt_mem_cache_pool_s {
 
 
 static nxt_uint_t nxt_mem_cache_shift(nxt_uint_t n);
+#if !(NXT_DEBUG_MEMORY)
 static void *nxt_mem_cache_alloc_small(nxt_mem_cache_pool_t *pool, size_t 
size);
 static nxt_uint_t nxt_mem_cache_alloc_chunk(u_char *map, nxt_uint_t size);
 static nxt_mem_cache_page_t *
 nxt_mem_cache_alloc_page(nxt_mem_cache_pool_t *pool);
 static nxt_mem_cache_block_t *
 nxt_mem_cache_alloc_cluster(nxt_mem_cache_pool_t *pool);
+#endif
 static void *nxt_mem_cache_alloc_large(nxt_mem_cache_pool_t *pool,
 size_t alignment, size_t size);
 static intptr_t nxt_mem_cache_rbtree_compare(nxt_rbtree_node_t *node1,
@@ -302,10 +304,14 @@ nxt_mem_cache_alloc(nxt_mem_cache_pool_t
 pool->proto->trace(pool->trace, "mem cache alloc: %zd", size);
 }
 
+#if !(NXT_DEBUG_MEMORY)
+
 if (size <= pool->page_size) {
 return nxt_mem_cache_alloc_small(pool, size);
 }
 
+#endif
+
 return nxt_mem_cache_alloc_large(pool, NXT_MAX_ALIGNMENT, size);
 }
 
@@ -337,6 +343,8 @@ nxt_mem_cache_align(nxt_mem_cache_pool_t
 
 if (nxt_fast_path((alignment - 1) & alignment) == 0) {
 
+#if !(NXT_DEBUG_MEMORY)
+
 if (size <= pool->page_size && alignment <= pool->page_alignment) {
 size = nxt_max(size, alignment);
 
@@ -345,6 +353,8 @@ nxt_mem_cache_align(nxt_mem_cache_pool_t
 }
 }
 
+#endif
+
 return nxt_mem_cache_alloc_large(pool, alignment, size);
 }
 
@@ -367,6 +377,8 @@ nxt_mem_cache_zalign(nxt_mem_cache_pool_
 }
 
 
+#if !(NXT_DEBUG_MEMORY)
+
 static void *
 nxt_mem_cache_alloc_small(nxt_mem_cache_pool_t *pool, size_t size)
 {
@@ -549,6 +561,8 @@ nxt_mem_cache_alloc_cluster(nxt_mem_cach
 return cluster;
 }
 
+#endif
+
 
 static void *
 nxt_mem_cache_alloc_large(nxt_mem_cache_pool_t *pool, size_t alignment,
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed a unit test for Math.acosh().

2016-12-02 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/7275165c3832
branches:  
changeset: 271:7275165c3832
user:  Valentin Bartenev <vb...@nginx.com>
date:  Fri Dec 02 17:11:57 2016 +0300
description:
Fixed a unit test for Math.acosh().

diffstat:

 njs/test/njs_unit_test.c |  6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diffs (18 lines):

diff -r f8f20b27724e -r 7275165c3832 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Thu Dec 01 19:45:19 2016 +0300
+++ b/njs/test/njs_unit_test.c  Fri Dec 02 17:11:57 2016 +0300
@@ -5568,11 +5568,11 @@ static njs_unit_test_t  njs_test[] =
   nxt_string("Infinity") },
 
 /*
- * The difference is 2 * Number.EPSILON on FreeBSD
+ * The difference is Number.EPSILON on Linux/i686
  * and zero on other platforms.
  */
-{ nxt_string("Math.abs(Math.cosh(1) - (1/Math.E + Math.E)/2)"
- " <= 2 * Number.EPSILON"),
+{ nxt_string("Math.abs(Math.acosh((1/Math.E + Math.E)/2) - 1)"
+ " <= Number.EPSILON"),
   nxt_string("true") },
 
 { nxt_string("Math.asin()"),

___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[nginx] HTTP/2: fixed saving preread buffer to temp file (ticket #1143).

2016-11-28 Thread Valentin Bartenev
details:   http://hg.nginx.org/nginx/rev/52bd8cc17f34
branches:  
changeset: 6805:52bd8cc17f34
user:  Valentin Bartenev <vb...@nginx.com>
date:  Mon Nov 28 19:19:21 2016 +0300
description:
HTTP/2: fixed saving preread buffer to temp file (ticket #1143).

Previously, a request body bigger than "client_body_buffer_size" wasn't written
into a temporary file if it has been pre-read entirely.  The preread buffer
is freed after processing, thus subsequent use of it might result in sending
corrupted body or cause a segfault.

diffstat:

 src/http/v2/ngx_http_v2.c |  3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diffs (13 lines):

diff -r 2c7a2d75938a -r 52bd8cc17f34 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Mon Nov 21 16:49:19 2016 +0300
+++ b/src/http/v2/ngx_http_v2.c Mon Nov 28 19:19:21 2016 +0300
@@ -3575,6 +3575,9 @@ ngx_http_v2_read_request_body(ngx_http_r
 rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
 
 } else {
+/* enforce writing body to file */
+r->request_body_in_file_only = 1;
+
 rb->buf = ngx_calloc_buf(r->pool);
 
 if (rb->buf != NULL) {

___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Math.clz32 method.

2016-11-21 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/fd2a05f9eacf
branches:  
changeset: 266:fd2a05f9eacf
user:  Valentin Bartenev <vb...@nginx.com>
date:  Tue Nov 22 00:06:46 2016 +0300
description:
Math.clz32 method.

diffstat:

 njs/njs_math.c   |  29 +
 njs/test/njs_unit_test.c |  27 +++
 nxt/auto/clang   |  14 ++
 nxt/nxt_clang.h  |  32 
 4 files changed, 102 insertions(+), 0 deletions(-)

diffs (149 lines):

diff -r 9f0f13857c46 -r fd2a05f9eacf njs/njs_math.c
--- a/njs/njs_math.cSat Nov 19 22:20:06 2016 +0300
+++ b/njs/njs_math.cTue Nov 22 00:06:46 2016 +0300
@@ -233,6 +233,27 @@ njs_object_math_ceil(njs_vm_t *vm, njs_v
 
 
 static njs_ret_t
+njs_object_math_clz32(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+doublenum;
+uint32_t  ui32;
+
+if (nargs > 1) {
+ui32 = njs_number_to_integer(args[1].data.u.number);
+num = nxt_leading_zeros(ui32);
+
+} else {
+num = 32;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_cos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -869,6 +890,14 @@ static const njs_object_prop_t  njs_math
  NJS_SKIP_ARG, NJS_NUMBER_ARG),
 },
 
+/* ES6. */
+{
+.type = NJS_METHOD,
+.name = njs_string("clz32"),
+.value = njs_native_function(njs_object_math_clz32, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+},
+
 {
 .type = NJS_METHOD,
 .name = njs_string("cos"),
diff -r 9f0f13857c46 -r fd2a05f9eacf njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Sat Nov 19 22:20:06 2016 +0300
+++ b/njs/test/njs_unit_test.c  Tue Nov 22 00:06:46 2016 +0300
@@ -5799,6 +5799,33 @@ static njs_unit_test_t  njs_test[] =
 { nxt_string("Math.ceil(3.1)"),
   nxt_string("4") },
 
+{ nxt_string("Math.clz32()"),
+  nxt_string("32") },
+
+{ nxt_string("Math.clz32('abc')"),
+  nxt_string("32") },
+
+{ nxt_string("Math.clz32(NaN)"),
+  nxt_string("32") },
+
+{ nxt_string("Math.clz32(Infinity)"),
+  nxt_string("32") },
+
+{ nxt_string("Math.clz32('1')"),
+  nxt_string("31") },
+
+{ nxt_string("Math.clz32(0)"),
+  nxt_string("32") },
+
+{ nxt_string("Math.clz32('65535')"),
+  nxt_string("16") },
+
+{ nxt_string("Math.clz32(-1)"),
+  nxt_string("0") },
+
+{ nxt_string("Math.clz32(4294967298)"),
+  nxt_string("30") },
+
 { nxt_string("Math.cos()"),
   nxt_string("NaN") },
 
diff -r 9f0f13857c46 -r fd2a05f9eacf nxt/auto/clang
--- a/nxt/auto/clangSat Nov 19 22:20:06 2016 +0300
+++ b/nxt/auto/clangTue Nov 22 00:06:46 2016 +0300
@@ -203,6 +203,20 @@ nxt_feature_test="int main(void) {
 . ${NXT_AUTO}feature
 
 
+nxt_feature="GCC __builtin_clz()"
+nxt_feature_name=NXT_HAVE_BUILTIN_CLZ
+nxt_feature_run=no
+nxt_feature_incs=
+nxt_feature_libs=
+nxt_feature_test="int main(void) {
+  if (__builtin_clz(1) != 31) {
+  return 1;
+  }
+  return 0;
+  }"
+. ${NXT_AUTO}feature
+
+
 nxt_feature="GCC __attribute__ visibility"
 nxt_feature_name=NXT_HAVE_GCC_ATTRIBUTE_VISIBILITY
 nxt_feature_run=no
diff -r 9f0f13857c46 -r fd2a05f9eacf nxt/nxt_clang.h
--- a/nxt/nxt_clang.h   Sat Nov 19 22:20:06 2016 +0300
+++ b/nxt/nxt_clang.h   Tue Nov 22 00:06:46 2016 +0300
@@ -52,6 +52,38 @@
 #endif
 
 
+#if (NXT_HAVE_BUILTIN_CLZ)
+#define nxt_leading_zeros(x)  (((x) == 0) ? 32 : __builtin_clz(x))
+
+#else
+
+nxt_inline uint32_t
+nxt_leading_zeros(uint32_t x)
+{
+uint32_t  n;
+
+/*
+ * There is no sense to optimize this function, since almost
+ * all platforms nowadays support the built-in instruction.
+ */
+
+if (x == 0) {
+return 32;
+}
+
+n = 0;
+
+while ((x & 0x8000) == 0) {
+n++;
+x <<= 1;
+}
+
+return n;
+}
+
+#endif
+
+
 #if (NXT_HAVE_GCC_ATTRIBUTE_VISIBILITY)
 #define NXT_EXPORT __attribute__((visibility("default")))
 

___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Optimized conversion of negative numbers to integer.

2016-11-19 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/9f0f13857c46
branches:  
changeset: 265:9f0f13857c46
user:  Valentin Bartenev <vb...@nginx.com>
date:  Sat Nov 19 22:20:06 2016 +0300
description:
Optimized conversion of negative numbers to integer.

There is no reason to use fmod() for all negative numbers.
The numbers in range [-2^53, 2^53] can be converted directly
to int64_t.

diffstat:

 njs/njs_number.c |  15 ---
 1 files changed, 8 insertions(+), 7 deletions(-)

diffs (27 lines):

diff -r 91dc07616b19 -r 9f0f13857c46 njs/njs_number.c
--- a/njs/njs_number.c  Sat Nov 19 22:20:06 2016 +0300
+++ b/njs/njs_number.c  Sat Nov 19 22:20:06 2016 +0300
@@ -749,15 +749,16 @@ njs_number_to_integer(double num)
 int64_t  i64;
 
 /*
- * ECMAScript 5.1: integer must be modulo 2^32.
- * 2^53 is the largest integer number which can be stored in the IEEE-754
- * format and numbers less than 2^53 can be just converted to int64_t
- * eliding more expensive fmod() operation.  Then the int64 integer is
- * truncated to uint32_t.  The NaN can be converted to 0x8000
- * and becomes 0 after truncation.  fmod() of the infinity returns NaN.
+ * ES5.1: integer must be modulo 2^32.
+ * 2^53 is the largest integer number which can be stored safely
+ * in the IEEE-754 format and numbers less than 2^53 can be just
+ * converted to int64_t eliding more expensive fmod() operation.
+ * Then the int64 integer is truncated to uint32_t.  The NaN is
+ * converted to 0x8000 and becomes 0 after truncation.
+ * fmod() of the Infinity returns NaN.
  */
 
-if (num < 0 || num > 9007199254740992.0) {
+if (fabs(num) > 9007199254740992.0) {
 i64 = fmod(num, 4294967296.0);
 
 } else {

___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Math.imul() method.

2016-11-19 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/91dc07616b19
branches:  
changeset: 264:91dc07616b19
user:  Valentin Bartenev <vb...@nginx.com>
date:  Sat Nov 19 22:20:06 2016 +0300
description:
Math.imul() method.

diffstat:

 njs/njs_math.c   |  31 ++
 njs/njs_number.c |  25 +
 njs/njs_number.h |   1 +
 njs/njs_vm.c |  52 ++
 njs/test/njs_unit_test.c |  57 
 5 files changed, 127 insertions(+), 39 deletions(-)

diffs (276 lines):

diff -r f06c2b48ff78 -r 91dc07616b19 njs/njs_math.c
--- a/njs/njs_math.cFri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_math.cSat Nov 19 22:20:06 2016 +0300
@@ -378,6 +378,29 @@ njs_object_math_hypot(njs_vm_t *vm, njs_
 
 
 static njs_ret_t
+njs_object_math_imul(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+doublenum;
+uint32_t  a, b;
+
+if (nargs > 2) {
+a = njs_number_to_integer(args[1].data.u.number);
+b = njs_number_to_integer(args[2].data.u.number);
+
+num = (int32_t) (a * b);
+
+} else {
+num = 0;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -898,6 +921,14 @@ static const njs_object_prop_t  njs_math
 .value = njs_native_function(njs_object_math_hypot, 0, 0),
 },
 
+/* ES6. */
+{
+.type = NJS_METHOD,
+.name = njs_string("imul"),
+.value = njs_native_function(njs_object_math_imul, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+},
+
 {
 .type = NJS_METHOD,
 .name = njs_string("log"),
diff -r f06c2b48ff78 -r 91dc07616b19 njs/njs_number.c
--- a/njs/njs_number.c  Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_number.c  Sat Nov 19 22:20:06 2016 +0300
@@ -741,3 +741,28 @@ njs_number_parse_float(njs_vm_t *vm, njs
 
 return NXT_OK;
 }
+
+
+nxt_noinline uint32_t
+njs_number_to_integer(double num)
+{
+int64_t  i64;
+
+/*
+ * ECMAScript 5.1: integer must be modulo 2^32.
+ * 2^53 is the largest integer number which can be stored in the IEEE-754
+ * format and numbers less than 2^53 can be just converted to int64_t
+ * eliding more expensive fmod() operation.  Then the int64 integer is
+ * truncated to uint32_t.  The NaN can be converted to 0x8000
+ * and becomes 0 after truncation.  fmod() of the infinity returns NaN.
+ */
+
+if (num < 0 || num > 9007199254740992.0) {
+i64 = fmod(num, 4294967296.0);
+
+} else {
+i64 = num;
+}
+
+return (uint32_t) i64;
+}
diff -r f06c2b48ff78 -r 91dc07616b19 njs/njs_number.h
--- a/njs/njs_number.h  Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_number.h  Sat Nov 19 22:20:06 2016 +0300
@@ -27,6 +27,7 @@ njs_ret_t njs_number_parse_int(njs_vm_t 
 nxt_uint_t nargs, njs_index_t unused);
 njs_ret_t njs_number_parse_float(njs_vm_t *vm, njs_value_t *args,
 nxt_uint_t nargs, njs_index_t unused);
+nxt_noinline uint32_t njs_number_to_integer(double num);
 
 
 extern const njs_object_init_t  njs_number_constructor_init;
diff -r f06c2b48ff78 -r 91dc07616b19 njs/njs_vm.c
--- a/njs/njs_vm.c  Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_vm.c  Sat Nov 19 22:20:06 2016 +0300
@@ -78,7 +78,6 @@ static njs_ret_t njs_object_property_que
 njs_property_query_t *pq, njs_value_t *value, njs_object_t *object);
 static njs_ret_t njs_method_private_copy(njs_vm_t *vm,
 njs_property_query_t *pq);
-static nxt_noinline uint32_t njs_integer_value(double num);
 static nxt_noinline njs_ret_t njs_values_equal(const njs_value_t *val1,
 const njs_value_t *val2);
 static nxt_noinline njs_ret_t njs_values_compare(const njs_value_t *val1,
@@ -1639,8 +1638,8 @@ njs_vmcode_left_shift(njs_vm_t *vm, njs_
 
 if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
 
-num1 = njs_integer_value(val1->data.u.number);
-num2 = njs_integer_value(val2->data.u.number);
+num1 = njs_number_to_integer(val1->data.u.number);
+num2 = njs_number_to_integer(val2->data.u.number);
 njs_number_set(>retval, num1 << (num2 & 0x1f));
 
 return sizeof(njs_vmcode_3addr_t);
@@ -1658,8 +1657,8 @@ njs_vmcode_right_shift(njs_vm_t *vm, njs
 
 if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
 
-num1 = njs_integer_value(val1->data.u.number);
-num2 = njs_integer_value(val2->data.u.number);
+num1 = njs_number_to_integer(val1->data.u.number);
+num2 = njs_number_to_integer(val2->data.u.number);
 njs_number_set(>retval, num1 >> (num2 & 0x1f));
 
 return sizeof(njs_vmcode_3addr_t);
@@ -1678,8 +1677,8 @@ njs_v

[njs] More Math methods from ES6.

2016-11-18 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/4f4bda866d8e
branches:  
changeset: 262:4f4bda866d8e
user:  Valentin Bartenev <vb...@nginx.com>
date:  Fri Nov 18 17:25:25 2016 +0300
description:
More Math methods from ES6.

diffstat:

 njs/njs_math.c   |  333 +++
 njs/test/njs_unit_test.c |  292 +
 2 files changed, 625 insertions(+), 0 deletions(-)

diffs (820 lines):

diff -r f402a8c64d7a -r 4f4bda866d8e njs/njs_math.c
--- a/njs/njs_math.cWed Nov 16 15:21:07 2016 +0300
+++ b/njs/njs_math.cFri Nov 18 17:25:25 2016 +0300
@@ -69,6 +69,25 @@ njs_object_math_acos(njs_vm_t *vm, njs_v
 
 
 static njs_ret_t
+njs_object_math_acosh(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = acosh(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_asin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -97,6 +116,25 @@ njs_object_math_asin(njs_vm_t *vm, njs_v
 
 
 static njs_ret_t
+njs_object_math_asinh(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = asinh(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_atan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -138,6 +176,44 @@ njs_object_math_atan2(njs_vm_t *vm, njs_
 
 
 static njs_ret_t
+njs_object_math_atanh(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = atanh(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_cbrt(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = cbrt(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_ceil(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -176,6 +252,25 @@ njs_object_math_cos(njs_vm_t *vm, njs_va
 
 
 static njs_ret_t
+njs_object_math_cosh(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = cosh(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_exp(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -195,6 +290,25 @@ njs_object_math_exp(njs_vm_t *vm, njs_va
 
 
 static njs_ret_t
+njs_object_math_expm1(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = expm1(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_floor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -214,6 +328,25 @@ njs_object_math_floor(njs_vm_t *vm, njs_
 
 
 static njs_ret_t
+njs_object_math_fround(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = (float) args[1].data.u.number;
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
 njs_object_math_hypot(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
@@ -264,6 +397,72 @@ njs_object_math_log(njs_vm_t *vm, njs_va
 
 
 static njs_ret_t
+njs_object_math_log10(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = log10(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_log1p(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = log1p(args[1].data.u.number);
+
+} else {
+num = NAN;
+}
+
+njs_number_set(>retval, num);
+
+return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_log2(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+njs_index_t unused)
+{
+double  num;
+
+if (nargs > 1) {
+num = args[1].data.u.number;
+
+#if (NXT_SOLARIS)
+/* On Solaris 10 log(-1) returns -Infinity. */
+if (num &

[njs] Improved unit test for Math.exp(1).

2016-11-18 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/f06c2b48ff78
branches:  
changeset: 263:f06c2b48ff78
user:  Valentin Bartenev <vb...@nginx.com>
date:  Fri Nov 18 17:25:45 2016 +0300
description:
Improved unit test for Math.exp(1).

diffstat:

 njs/test/njs_unit_test.c |  2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diffs (12 lines):

diff -r 4f4bda866d8e -r f06c2b48ff78 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c  Fri Nov 18 17:25:25 2016 +0300
+++ b/njs/test/njs_unit_test.c  Fri Nov 18 17:25:45 2016 +0300
@@ -5868,7 +5868,7 @@ static njs_unit_test_t  njs_test[] =
  * The difference is 2 * Number.EPSILON on FreeBSD
  * and zero on other platforms.
  */
-{ nxt_string("Math.exp(1) - Math.E <= 2 * Number.EPSILON"),
+{ nxt_string("Math.abs(Math.exp(1) - Math.E) <= 2 * Number.EPSILON"),
   nxt_string("true") },
 
 { nxt_string("Math.expm1()"),

___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Removed checking for range errors in Math.hypot().

2016-11-16 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/8253ecba7ad6
branches:  
changeset: 259:8253ecba7ad6
user:  Valentin Bartenev <vb...@nginx.com>
date:  Wed Nov 16 12:49:53 2016 +0300
description:
Removed checking for range errors in Math.hypot().

It seems other interpreters do not return an exception in this case.

diffstat:

 njs/njs_math.c |  10 +-
 1 files changed, 1 insertions(+), 9 deletions(-)

diffs (27 lines):

diff -r 56bf74dccca1 -r 8253ecba7ad6 njs/njs_math.c
--- a/njs/njs_math.cWed Nov 16 12:49:53 2016 +0300
+++ b/njs/njs_math.cWed Nov 16 12:49:53 2016 +0300
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 
 static njs_ret_t
@@ -216,14 +215,7 @@ njs_object_math_hypot(njs_vm_t *vm, njs_
 for (i = 2; i < nargs; i++) {
 num = hypot(num, args[i].data.u.number);
 
-if (num == HUGE_VAL) {
-/* HUGE_VAL is equal to INFINITY on IEEE-754 systems. */
-
-if (nxt_slow_path(errno == ERANGE)) {
-vm->exception = _exception_range_error;
-return NXT_ERROR;
-}
-
+if (num == INFINITY) {
 break;
 }
 }

___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Refactored Math methods.

2016-11-16 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/56bf74dccca1
branches:  
changeset: 258:56bf74dccca1
user:  Valentin Bartenev <vb...@nginx.com>
date:  Wed Nov 16 12:49:53 2016 +0300
description:
Refactored Math methods.

diffstat:

 njs/njs_math.c |  94 -
 1 files changed, 46 insertions(+), 48 deletions(-)

diffs (287 lines):

diff -r 87b49eec0c34 -r 56bf74dccca1 njs/njs_math.c
--- a/njs/njs_math.cWed Nov 16 12:49:52 2016 +0300
+++ b/njs/njs_math.cWed Nov 16 12:49:53 2016 +0300
@@ -29,13 +29,13 @@ njs_object_math_abs(njs_vm_t *vm, njs_va
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = fabs(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, fabs(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -48,13 +48,13 @@ njs_object_math_acos(njs_vm_t *vm, njs_v
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = acos(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, acos(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -67,13 +67,13 @@ njs_object_math_asin(njs_vm_t *vm, njs_v
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = asin(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, asin(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -86,13 +86,13 @@ njs_object_math_atan(njs_vm_t *vm, njs_v
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = atan(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, atan(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -102,20 +102,19 @@ static njs_ret_t
 njs_object_math_atan2(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
-double  y, x;
+double  num, y, x;
 
-y = NAN;
-x = NAN;
+if (nargs > 2) {
+y = args[1].data.u.number;
+x = args[2].data.u.number;
 
-if (nargs > 1) {
-y = args[1].data.u.number;
+num = atan2(y, x);
+
+} else {
+num = NAN;
 }
 
-if (nargs > 2) {
-x = args[2].data.u.number;
-}
-
-njs_number_set(>retval, atan2(y, x));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -128,13 +127,13 @@ njs_object_math_ceil(njs_vm_t *vm, njs_v
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = ceil(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, ceil(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -147,13 +146,13 @@ njs_object_math_cos(njs_vm_t *vm, njs_va
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = cos(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, cos(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -166,13 +165,13 @@ njs_object_math_exp(njs_vm_t *vm, njs_va
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = exp(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, exp(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -185,13 +184,13 @@ njs_object_math_floor(njs_vm_t *vm, njs_
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = floor(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, floor(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -242,13 +241,13 @@ njs_object_math_log(njs_vm_t *vm, njs_va
 double  num;
 
 if (nargs > 1) {
-num = args[1].data.u.number;
+num = log(args[1].data.u.number);
 
 } else {
 num = NAN;
 }
 
-njs_number_set(>retval, log(num));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -320,20 +319,19 @@ static njs_ret_t
 njs_object_math_pow(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 njs_index_t unused)
 {
-double  base, exponent;
+double  num, base, exponent;
 
-base = NAN;
-exponent = NAN;
+if (nargs > 2) {
+base = args[1].data.u.number;
+exponent = args[2].data.u.number;
 
-if (nargs > 1) {
-base = args[1].data.u.number;
+num = pow(base, exponent);
+
+} else {
+num = NAN;
 }
 
-if (nargs > 2) {
-exponent = args[2].data.u.number;
-}
-
-njs_number_set(>retval, pow(base, exponent));
+njs_number_set(>retval, num);
 
 return NXT_OK;
 }
@@ -360,13 +358,13 @@ njs_object_math_round(njs_vm_t 

[njs] Moved njs_string_offset_map_init() closer to its usage.

2016-11-10 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/0939df226d5c
branches:  
changeset: 251:0939df226d5c
user:  Valentin Bartenev <vb...@nginx.com>
date:  Thu Nov 10 19:09:13 2016 +0300
description:
Moved njs_string_offset_map_init() closer to its usage.

No functional changes.

diffstat:

 njs/njs_string.c |  58 
 njs/njs_string.h |   2 +-
 2 files changed, 30 insertions(+), 30 deletions(-)

diffs (94 lines):

diff -r adf61ca4267b -r 0939df226d5c njs/njs_string.c
--- a/njs/njs_string.c  Thu Nov 10 18:54:28 2016 +0300
+++ b/njs/njs_string.c  Thu Nov 10 19:09:13 2016 +0300
@@ -466,35 +466,6 @@ njs_string_prototype_length(njs_vm_t *vm
 }
 
 
-nxt_noinline void
-njs_string_offset_map_init(const u_char *start, size_t size)
-{
-size_toffset;
-uint32_t  *map;
-nxt_uint_tn;
-const u_char  *p, *end;
-
-end = start + size;
-map = njs_string_map_start(end);
-p = start;
-n = 0;
-offset = NJS_STRING_MAP_STRIDE;
-
-do {
-if (offset == 0) {
-map[n++] = p - start;
-offset = NJS_STRING_MAP_STRIDE;
-}
-
-/* The UTF-8 string should be valid since its length is known. */
-p = nxt_utf8_next(p, end);
-
-offset--;
-
-} while (p < end);
-}
-
-
 nxt_bool_t
 njs_string_eq(const njs_value_t *v1, const njs_value_t *v2)
 {
@@ -1588,6 +1559,35 @@ njs_string_index(njs_string_prop_t *stri
 }
 
 
+nxt_noinline void
+njs_string_offset_map_init(const u_char *start, size_t size)
+{
+size_toffset;
+uint32_t  *map;
+nxt_uint_tn;
+const u_char  *p, *end;
+
+end = start + size;
+map = njs_string_map_start(end);
+p = start;
+n = 0;
+offset = NJS_STRING_MAP_STRIDE;
+
+do {
+if (offset == 0) {
+map[n++] = p - start;
+offset = NJS_STRING_MAP_STRIDE;
+}
+
+/* The UTF-8 string should be valid since its length is known. */
+p = nxt_utf8_next(p, end);
+
+offset--;
+
+} while (p < end);
+}
+
+
 /*
  * String.toLowerCase().
  * The method supports only simple folding.  For example, Turkish "İ"
diff -r adf61ca4267b -r 0939df226d5c njs/njs_string.h
--- a/njs/njs_string.h  Thu Nov 10 18:54:28 2016 +0300
+++ b/njs/njs_string.h  Thu Nov 10 19:09:13 2016 +0300
@@ -128,7 +128,6 @@ nxt_noinline size_t njs_string_prop(njs_
 njs_value_t *value);
 njs_ret_t njs_string_constructor(njs_vm_t *vm, njs_value_t *args,
 nxt_uint_t nargs, njs_index_t unused);
-void njs_string_offset_map_init(const u_char *start, size_t size);
 nxt_bool_t njs_string_eq(const njs_value_t *val1, const njs_value_t *val2);
 nxt_int_t njs_string_cmp(const njs_value_t *val1, const njs_value_t *val2);
 njs_ret_t njs_string_slice(njs_vm_t *vm, njs_value_t *dst,
@@ -137,6 +136,7 @@ const u_char *njs_string_offset(const u_
 size_t index);
 nxt_noinline uint32_t njs_string_index(njs_string_prop_t *string,
 uint32_t offset);
+void njs_string_offset_map_init(const u_char *start, size_t size);
 njs_ret_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
 const njs_value_t *src);
 double njs_string_to_number(njs_value_t *value, nxt_bool_t exact);
___
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

[njs] On-demand initialization of UTF-8 strings offset map.

2016-11-10 Thread Valentin Bartenev
details:   http://hg.nginx.org/njs/rev/adf61ca4267b
branches:  
changeset: 250:adf61ca4267b
user:  Valentin Bartenev <vb...@nginx.com>
date:  Thu Nov 10 18:54:28 2016 +0300
description:
On-demand initialization of UTF-8 strings offset map.

diffstat:

 njs/njs_string.c |  70 ++-
 njs/njs_string.h |   6 ++--
 njs/njs_vm.c |   4 ---
 3 files changed, 31 insertions(+), 49 deletions(-)

diffs (229 lines):

diff -r 187882f1895a -r adf61ca4267b njs/njs_string.c
--- a/njs/njs_string.c  Thu Nov 10 18:45:10 2016 +0300
+++ b/njs/njs_string.c  Thu Nov 10 18:54:28 2016 +0300
@@ -178,11 +178,6 @@ njs_string_new(njs_vm_t *vm, njs_value_t
 
 if (nxt_fast_path(p != NULL)) {
 memcpy(p, start, size);
-
-if (size != length && length >= NJS_STRING_MAP_STRIDE) {
-njs_string_offset_map_init(p, size);
-}
-
 return NXT_OK;
 }
 
@@ -194,7 +189,7 @@ nxt_noinline u_char *
 njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint32_t size,
 uint32_t length)
 {
-uint32_t  total;
+uint32_t  total, map_offset, *map;
 njs_string_t  *string;
 
 value->type = NJS_STRING;
@@ -217,9 +212,11 @@ njs_string_alloc(njs_vm_t *vm, njs_value
 value->data.string_size = size;
 
 if (size != length && length > NJS_STRING_MAP_STRIDE) {
-total = njs_string_map_offset(size) + njs_string_map_size(length);
+map_offset = njs_string_map_offset(size);
+total = map_offset + njs_string_map_size(length);
 
 } else {
+map_offset = 0;
 total = size;
 }
 
@@ -233,6 +230,11 @@ njs_string_alloc(njs_vm_t *vm, njs_value
 string->length = length;
 string->retain = 1;
 
+if (map_offset != 0) {
+map = (uint32_t *) (string->start + map_offset);
+map[0] = 0;
+}
+
 return string->start;
 }
 
@@ -251,15 +253,16 @@ njs_string_copy(njs_value_t *dst, njs_va
 
 /*
  * njs_string_validate() validates an UTF-8 string, evaluates its length,
- * sets njs_string_prop_t struct, and initializes offset map if it is required.
+ * sets njs_string_prop_t struct.
  */
 
 nxt_noinline njs_ret_t
 njs_string_validate(njs_vm_t *vm, njs_string_prop_t *string, njs_value_t 
*value)
 {
-u_char   *start;
-size_t   new_size;
-ssize_t  size, length;
+u_char*start;
+size_tnew_size, map_offset;
+ssize_t   size, length;
+uint32_t  *map;
 
 size = value->short_string.size;
 
@@ -297,8 +300,8 @@ njs_string_validate(njs_vm_t *vm, njs_st
  * Reallocate the long string with offset map
  * after the string.
  */
-new_size = njs_string_map_offset(size)
-   + njs_string_map_size(length);
+map_offset = njs_string_map_offset(size);
+new_size = map_offset + njs_string_map_size(length);
 
 start = nxt_mem_cache_alloc(vm->mem_cache_pool, new_size);
 if (nxt_slow_path(start == NULL)) {
@@ -309,7 +312,8 @@ njs_string_validate(njs_vm_t *vm, njs_st
 string->start = start;
 value->data.u.string->start = start;
 
-njs_string_offset_map_init(start, size);
+map = (uint32_t *) (start + map_offset);
+map[0] = 0;
 }
 }
 
@@ -649,10 +653,6 @@ njs_string_prototype_concat(njs_vm_t *vm
 p += string.size;
 }
 
-if (length >= NJS_STRING_MAP_STRIDE && size != length) {
-njs_string_offset_map_init(start, size);
-}
-
 return NXT_OK;
 }
 
@@ -766,10 +766,6 @@ njs_string_prototype_from_bytes(njs_vm_t
 for (p = string.start; p < end; p++) {
 s = nxt_utf8_encode(s, *p);
 }
-
-if (slice.length >= NJS_STRING_MAP_STRIDE || size != slice.length) 
{
-njs_string_offset_map_init(start, size);
-}
 }
 
 return NXT_OK;
@@ -1518,8 +1514,7 @@ done:
 
 
 /*
- * njs_string_offset() assumes that index is correct
- * and the optional offset map has been initialized.
+ * njs_string_offset() assumes that index is correct.
  */
 
 nxt_noinline const u_char *
@@ -1531,6 +1526,10 @@ njs_string_offset(const u_char *start, c
 if (index >= NJS_STRING_MAP_STRIDE) {
 map = njs_string_map_start(end);
 
+if (map[0] == 0) {
+njs_string_offset_map_init(start, end - start);
+}
+
 start += map[index / NJS_STRING_MAP_STRIDE - 1];
 }
 
@@ -1543,8 +1542,7 @@ njs_string_offset(const u_char *start, c
 
 
 /*
- * njs_string_index() assumes that offset is correct
- * and the optional offset map has been initialized.
+ * njs_string_index() assumes that offset is correct.
  */
 
 nxt_noinline uint32_t
@@ -1565,6 

  1   2   3   4   >