njs-0.8.5
Hello, I'm glad to announce a new release of NGINX JavaScript module (njs). Learn more about njs: - Overview and introduction: https://nginx.org/en/docs/njs/ - NGINX JavaScript in Your Web Server Configuration: https://youtu.be/Jc_L6UffFOs - Extending NGINX with Custom Code: https://youtu.be/0CVhq4AUU7M - Using node modules with njs: https://nginx.org/en/docs/njs/node_modules.html - Writing njs code using TypeScript definition files: https://nginx.org/en/docs/njs/typescript.html Feel free to try it and give us feedback on: - Github: https://github.com/nginx/njs/issues Additional examples and howtos can be found here: - Github: https://github.com/nginx/njs-examples Changes with njs 0.8.5 25 Jun 2024 nginx modules: *) Change: r.variables.var, r.requestText, r.responseText, s.variables.var, and the "data" argument of the s.on() callback with "upload" or "download" event types will now convert bytes invalid in UTF-8 encoding into the replacement character. When working with binary data, use r.rawVariables.var, r.requestBuffer, r.responseBuffer, s.rawVariables.var, and the "upstream" or "downstream" event type for s.on() instead. *) Feature: added timeout argument for shared dictionary methods add(), set() and incr(). *) Bugfix: fixed checking for duplicate js_set variables. *) Bugfix: fixed request Host header when the port is non-standard. *) Bugfix: fixed handling of a zero-length request body in ngx.fetch() and r.subrequest(). *) Bugfix: fixed heap-buffer-overflow in Headers.get(). *) Bugfix: fixed r.subrequest() error handling. Core: *) Feature: added zlib module for QuickJS engine. *) Bugfix: fixed zlib.inflate(). *) Bugfix: fixed String.prototype.replaceAll() with zero-length argument. *) Bugfix: fixed retval handling after an exception in Array.prototype.toSpliced(), Array.prototype.toReversed(), Array.prototype.toSorted(). *) Bugfix: fixed RegExp.prototype[@@replace]() with replacements containing "$'", "$\`" and strings with Unicode characters. *) Bugfix: fixed a one-byte overread in decodeURI() and decodeURIComponent(). *) Bugfix: fixed tracking of argument scope. *) Bugfix: fixed integer overflow in Date.parse(). ___ nginx mailing list nginx@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx
[nginx-announce] njs-0.8.5
Hello, I'm glad to announce a new release of NGINX JavaScript module (njs). Learn more about njs: - Overview and introduction: https://nginx.org/en/docs/njs/ - NGINX JavaScript in Your Web Server Configuration: https://youtu.be/Jc_L6UffFOs - Extending NGINX with Custom Code: https://youtu.be/0CVhq4AUU7M - Using node modules with njs: https://nginx.org/en/docs/njs/node_modules.html - Writing njs code using TypeScript definition files: https://nginx.org/en/docs/njs/typescript.html Feel free to try it and give us feedback on: - Github: https://github.com/nginx/njs/issues Additional examples and howtos can be found here: - Github: https://github.com/nginx/njs-examples Changes with njs 0.8.5 25 Jun 2024 nginx modules: *) Change: r.variables.var, r.requestText, r.responseText, s.variables.var, and the "data" argument of the s.on() callback with "upload" or "download" event types will now convert bytes invalid in UTF-8 encoding into the replacement character. When working with binary data, use r.rawVariables.var, r.requestBuffer, r.responseBuffer, s.rawVariables.var, and the "upstream" or "downstream" event type for s.on() instead. *) Feature: added timeout argument for shared dictionary methods add(), set() and incr(). *) Bugfix: fixed checking for duplicate js_set variables. *) Bugfix: fixed request Host header when the port is non-standard. *) Bugfix: fixed handling of a zero-length request body in ngx.fetch() and r.subrequest(). *) Bugfix: fixed heap-buffer-overflow in Headers.get(). *) Bugfix: fixed r.subrequest() error handling. Core: *) Feature: added zlib module for QuickJS engine. *) Bugfix: fixed zlib.inflate(). *) Bugfix: fixed String.prototype.replaceAll() with zero-length argument. *) Bugfix: fixed retval handling after an exception in Array.prototype.toSpliced(), Array.prototype.toReversed(), Array.prototype.toSorted(). *) Bugfix: fixed RegExp.prototype[@@replace]() with replacements containing "$'", "$\`" and strings with Unicode characters. *) Bugfix: fixed a one-byte overread in decodeURI() and decodeURIComponent(). *) Bugfix: fixed tracking of argument scope. *) Bugfix: fixed integer overflow in Date.parse(). ___ nginx-announce mailing list nginx-announce@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-announce
NGINX JavaScript (njs) has migrated to Github
Hello, This week we took the next step in our commitment to the Open Source community by moving the official njs code repository to GitHub (https://github.com/nginx/njs). As part of the move, we have revamped our testing infrastructure and added clearer guidelines around installation, building, and contributing source code. We believe these changes will serve two purposes: 1. Modernize njs by creating a single place for the community to contribute, ask questions, and provide feedback. 2. Underscore our commitment to openness, consistency, transparency, and fairness in our acceptance of contributions. Importantly, these changes do not impact core njs source code, functionality, or license in any way. They simply do a better job at codifying existing guidelines, while providing a modern approach for managing the project and community. Please refer to the following files for more details: README.md https://github.com/nginx/njs/blob/master/README.md Provides basic information on what NJS is, how it is used (including links to sample code & projects), installing, debugging, building from source, etc... CONTRIBUTING.md https://github.com/nginx/njs/blob/master/CONTRIBUTING.md Provides clear guidelines for asking questions, suggesting improvements, and contributing code. You will also find our code and git style guides here. CODE_OF_CONDUCT.md https://github.com/nginx/njs/blob/master/CODE_OF_CONDUCT.md Our pledge, policies, and guidelines for community etiquette, along with enforcement procedures. SECURITY.md https://github.com/nginx/njs/blob/master/SECURITY.md Our security policy, including what constitutes a security concern and procedures for reporting vulnerabilities. SUPPORT.md https://github.com/nginx/njs/blob/master/SUPPORT.md A list of all support resources available to the community. For additional information on F5 NGINX’s commitment to our Open Source projects and communities, please see: https://www.f5.com/company/blog/nginx/meetup-recap-nginxs-commitments-to-the-open-source-community We look forward to your feedback, questions, and contributions as we work together to make njs even faster, more powerful, and feature-rich! ___ nginx mailing list nginx@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx
[njs] Fetch: fixed heap-buffer-overflow in Headers.get().
details: https://hg.nginx.org/njs/rev/f75f670905f0 branches: changeset: 2339:f75f670905f0 user: Dmitry Volyntsev date: Thu May 23 22:50:34 2024 -0700 description: Fetch: fixed heap-buffer-overflow in Headers.get(). Previously, when more than one header with the same name added to a Headers object and Headers.get() was used to get the the duplicate header heap-buffer-overflow occured. The overflow occurred due to an incorrect calculation of the combined header value's length. The issue was introduced in c43261bad627 (0.7.10). diffstat: nginx/ngx_js_fetch.c | 31 ++- 1 files changed, 10 insertions(+), 21 deletions(-) diffs (60 lines): diff -r 437fc09db765 -r f75f670905f0 nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Thu May 23 22:50:19 2024 -0700 +++ b/nginx/ngx_js_fetch.c Thu May 23 22:50:34 2024 -0700 @@ -3181,9 +3181,8 @@ static njs_int_t ngx_headers_js_get(njs_vm_t *vm, njs_value_t *value, njs_str_t *name, njs_value_t *retval, njs_bool_t as_array) { -u_char*data, *p; -size_t len; njs_int_t rc; +njs_chb_t chain; ngx_uint_t i; ngx_js_tb_elt_t *h, *ph; ngx_list_part_t *part; @@ -3254,36 +3253,26 @@ ngx_headers_js_get(njs_vm_t *vm, njs_val return NJS_DECLINED; } -len = 0; +NJS_CHB_MP_INIT(, vm); + h = ph; -while (ph != NULL) { -len = ph->value.len + njs_length(", "); -ph = ph->next; -} - -len -= njs_length(", "); - -data = njs_mp_alloc(njs_vm_memory_pool(vm), len); -if (data == NULL) { -njs_vm_memory_error(vm); -return NJS_ERROR; -} - -p = data; - for ( ;; ) { -p = ngx_cpymem(p, h->value.data, h->value.len); +njs_chb_append(, h->value.data, h->value.len); if (h->next == NULL) { break; } -*p++ = ','; *p++ = ' '; +njs_chb_append_literal(, ", "); h = h->next; } -return njs_vm_value_string_create(vm, retval, data, p - data); +rc = njs_vm_value_string_create_chb(vm, retval, ); + +njs_chb_destroy(); + +return rc; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Added fast path in njs_chb_utf8_length() for ASCII input.
details: https://hg.nginx.org/njs/rev/437fc09db765 branches: changeset: 2338:437fc09db765 user: Dmitry Volyntsev date: Thu May 23 22:50:19 2024 -0700 description: Added fast path in njs_chb_utf8_length() for ASCII input. diffstat: src/njs_chb.h| 19 +++ src/test/njs_benchmark.c | 33 + 2 files changed, 52 insertions(+), 0 deletions(-) diffs (93 lines): diff -r 585756e8cafe -r 437fc09db765 src/njs_chb.h --- a/src/njs_chb.h Wed May 22 23:08:15 2024 -0700 +++ b/src/njs_chb.h Thu May 23 22:50:19 2024 -0700 @@ -96,6 +96,8 @@ njs_chb_size(njs_chb_t *chain) njs_inline int64_t njs_chb_utf8_length(njs_chb_t *chain) { +u_char *p, *p_end; +size_t size; int64_t len, length; njs_chb_node_t *n; @@ -108,6 +110,23 @@ njs_chb_utf8_length(njs_chb_t *chain) length = 0; while (n != NULL) { +p = n->start; +size = njs_chb_node_size(n); +p_end = p + size; + +while (p < p_end && *p < 0x80) { + p++; +} + +if (p != p_end) { +break; +} + +length += size; +n = n->next; +} + +while (n != NULL) { len = njs_utf8_length(n->start, njs_chb_node_size(n)); if (njs_slow_path(len < 0)) { return -1; diff -r 585756e8cafe -r 437fc09db765 src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Wed May 22 23:08:15 2024 -0700 +++ b/src/test/njs_benchmark.c Thu May 23 22:50:19 2024 -0700 @@ -305,6 +305,21 @@ static njs_benchmark_test_t njs_test[] njs_str("undefined"), 1 }, +{ "string create chb 'x'.repeat(256)", + njs_str("benchmark.string('chb', 'x'.repeat(256), 1)"), + njs_str("undefined"), + 1 }, + +{ "string create chb 'Д'.repeat(128)", + njs_str("benchmark.string('chb', 'Д'.repeat(128), 1)"), + njs_str("undefined"), + 1 }, + +{ "string create chb 'x'.repeat(128) + 'Д'.repeat(64)", + njs_str("benchmark.string('chb', 'x'.repeat(128) + 'Д'.repeat(64), 1)"), + njs_str("undefined"), + 1 }, + { "JSON.parse", njs_str("JSON.parse('{\"a\":123, \"XXX\":[3,4,null]}').a"), njs_str("123"), @@ -696,6 +711,7 @@ njs_benchmark_string(njs_vm_t *vm, njs_v njs_index_t unused, njs_value_t *retval) { int64_t i, n; +njs_chb_tchain; njs_str_ts, mode; njs_value_t value; @@ -718,6 +734,23 @@ njs_benchmark_string(njs_vm_t *vm, njs_v njs_string_create(vm, , s.start, s.length); } +} else if (memcmp(mode.start, "chb", 3) == 0) { + +NJS_CHB_MP_INIT(, vm); + +njs_chb_append_literal(, "abc"); +njs_chb_append(, s.start, s.length); +njs_chb_append_literal(, "abc"); +njs_chb_append(, s.start, s.length); +njs_chb_append_literal(, "abc"); +njs_chb_append(, s.start, s.length); + +for (i = 0; i < n; i++) { +njs_string_create_chb(vm, , ); +} + +njs_chb_destroy(); + } else { njs_type_error(vm, "unknown mode \"%V\"", ); return NJS_ERROR; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed retval handling after an exception.
details: https://hg.nginx.org/njs/rev/585756e8cafe branches: changeset: 2337:585756e8cafe user: Dmitry Volyntsev date: Wed May 22 23:08:15 2024 -0700 description: Fixed retval handling after an exception. Previously, some functions set a retval too early. If this happened before an exception a partially created object in inconsistent state may be visible outside the affected functions. The following functions were fixed: Object.prototype.valueOf() Array.prototype.toSpliced() Array.prototype.toReversed() Array.prototype.toSorted() This fixes #713 issue on Github. diffstat: src/njs_array.c | 39 ++- src/njs_object.c | 14 ++ src/test/njs_unit_test.c | 12 3 files changed, 44 insertions(+), 21 deletions(-) diffs (203 lines): diff -r 077a5b2f30d8 -r 585756e8cafe src/njs_array.c --- a/src/njs_array.c Wed May 22 17:26:16 2024 -0700 +++ b/src/njs_array.c Wed May 22 23:08:15 2024 -0700 @@ -591,14 +591,14 @@ njs_array_of(njs_vm_t *vm, njs_value_t * return NJS_ERROR; } -njs_set_array(retval, array); - if (array->object.fast_array) { for (i = 0; i < length; i++) { array->start[i] = args[i + 1]; } } +njs_set_array(retval, array); + return NJS_OK; } @@ -1388,7 +1388,7 @@ njs_array_prototype_to_spliced(njs_vm_t { int64_t i, n, r, start, length, to_insert, to_skip, new_length; njs_int_tret; -njs_value_t *this, value; +njs_value_t *this, a, value; njs_array_t *array; this = njs_argument(args, 0); @@ -1439,7 +1439,7 @@ njs_array_prototype_to_spliced(njs_vm_t return NJS_ERROR; } -njs_set_array(retval, array); +njs_set_array(, array); for (i = 0; i < start; i++) { ret = njs_value_property_i64(vm, this, i, ); @@ -1447,14 +1447,14 @@ njs_array_prototype_to_spliced(njs_vm_t return NJS_ERROR; } -ret = njs_value_create_data_prop_i64(vm, retval, i, , 0); +ret = njs_value_create_data_prop_i64(vm, , i, , 0); if (njs_slow_path(ret != NJS_OK)) { return ret; } } for (n = 3; to_insert-- > 0; i++, n++) { -ret = njs_value_create_data_prop_i64(vm, retval, i, [n], 0); +ret = njs_value_create_data_prop_i64(vm, , i, [n], 0); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1468,7 +1468,7 @@ njs_array_prototype_to_spliced(njs_vm_t return NJS_ERROR; } -ret = njs_value_create_data_prop_i64(vm, retval, i, , 0); +ret = njs_value_create_data_prop_i64(vm, , i, , 0); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1477,6 +1477,8 @@ njs_array_prototype_to_spliced(njs_vm_t i++; } +njs_set_array(retval, array); + return NJS_OK; } @@ -1562,7 +1564,7 @@ njs_array_prototype_to_reversed(njs_vm_t int64_t length, i; njs_int_tret; njs_array_t *array; -njs_value_t *this, value; +njs_value_t *this, a, value; this = njs_argument(args, 0); @@ -1581,7 +1583,7 @@ njs_array_prototype_to_reversed(njs_vm_t return NJS_ERROR; } -njs_set_array(retval, array); +njs_set_array(, array); for (i = 0; i < length; i++) { ret = njs_value_property_i64(vm, this, length - i - 1, ); @@ -1589,12 +1591,14 @@ njs_array_prototype_to_reversed(njs_vm_t return NJS_ERROR; } -ret = njs_value_create_data_prop_i64(vm, retval, i, , 0); +ret = njs_value_create_data_prop_i64(vm, , i, , 0); if (njs_slow_path(ret != NJS_OK)) { return ret; } } +njs_set_array(retval, array); + return NJS_OK; } @@ -3018,7 +3022,7 @@ njs_array_prototype_to_sorted(njs_vm_t * int64_ti, nslots, nunds, length; njs_int_t ret; njs_array_t*array; -njs_value_t*this, *comparefn; +njs_value_t*this, *comparefn, a; njs_function_t *compare; njs_array_sort_slot_t *slots; @@ -3070,24 +3074,25 @@ njs_array_prototype_to_sorted(njs_vm_t * njs_assert(length == (nslots + nunds)); -njs_set_array(retval, array); +njs_set_array(, array); for (i = 0; i < nslots; i++) { -ret = njs_value_property_i64_set(vm, retval, i, [i].value); -if (njs_slow_path(ret == NJS_ERROR)) { +ret = njs_value_create_data_prop_i64(vm, , i, [i].value, 0); +if (njs_slow_path(ret != NJS_OK)) { goto exception; } } for (; i < length; i++) { -ret = njs_value_property_i64_set(vm, retval, i, - njs_value_arg(_value_undefined)); -if (njs_slow_path(ret == NJS_ERROR)) { +ret = njs_value_crea
[njs] Improved String.prototype.replaceAll() for readability.
details: https://hg.nginx.org/njs/rev/077a5b2f30d8 branches: changeset: 2336:077a5b2f30d8 user: Dmitry Volyntsev date: Wed May 22 17:26:16 2024 -0700 description: Improved String.prototype.replaceAll() for readability. diffstat: src/njs_string.c | 44 ++-- 1 files changed, 26 insertions(+), 18 deletions(-) diffs (100 lines): diff -r e496851c0fe7 -r 077a5b2f30d8 src/njs_string.c --- a/src/njs_string.c Wed May 22 17:26:08 2024 -0700 +++ b/src/njs_string.c Wed May 22 17:26:16 2024 -0700 @@ -3228,7 +3228,7 @@ njs_string_prototype_replace(njs_vm_t *v njs_index_t replaceAll, njs_value_t *retval) { u_char *r; -size_t length, size, increment, end_of_last_match; +size_t length, size, end_of_last_match; int64_tpos; njs_int_t ret; njs_str_t str; @@ -3236,7 +3236,7 @@ njs_string_prototype_replace(njs_vm_t *v njs_value_t*this, *search, *replace; njs_value_tsearch_lvalue, replace_lvalue, replacer, value, arguments[3]; -const u_char *p, *p_start; +const u_char *start, *end; njs_function_t *func_replace; njs_string_prop_t string, s, ret_string; @@ -3331,7 +3331,6 @@ njs_string_prototype_replace(njs_vm_t *v } if (!replaceAll) { - if (func_replace == NULL) { ret = njs_string_get_substitution(vm, search, this, pos, NULL, 0, NULL, replace, ); @@ -3356,7 +3355,7 @@ njs_string_prototype_replace(njs_vm_t *v } } -p = njs_string_offset(, pos); +end = njs_string_offset(, pos); (void) njs_string_prop(_string, ); @@ -3368,17 +3367,16 @@ njs_string_prototype_replace(njs_vm_t *v return NJS_ERROR; } -r = njs_cpymem(r, string.start, p - string.start); +r = njs_cpymem(r, string.start, end - string.start); r = njs_cpymem(r, ret_string.start, ret_string.size); -memcpy(r, p + s.size, string.size - s.size - (p - string.start)); +memcpy(r, end + s.size, string.size - s.size - (end - string.start)); return NJS_OK; } NJS_CHB_MP_INIT(, vm); -p_start = string.start; -increment = s.length != 0 ? s.length : 1; +start = string.start; do { if (func_replace == NULL) { @@ -3405,20 +3403,30 @@ njs_string_prototype_replace(njs_vm_t *v } } -p = njs_string_offset(, pos); +end = njs_string_offset(, pos); (void) njs_string_prop(_string, ); -njs_chb_append(, p_start, p - p_start); +njs_chb_append(, start, end - start); njs_chb_append(, ret_string.start, ret_string.size); -p_start = p + s.size; -end_of_last_match = pos + increment; - -pos = njs_string_index_of(, , end_of_last_match); - -} while (pos >= 0 && end_of_last_match <= string.length); - -njs_chb_append(, p_start, string.start + string.size - p_start); +start = end + s.size; +end_of_last_match = pos + s.length; + +if (njs_slow_path(s.length == 0)) { +if (end_of_last_match >= string.length) { +pos = -1; + +} else { +pos = end_of_last_match + 1; +} + +} else { +pos = njs_string_index_of(, , end_of_last_match); +} + +} while (pos >= 0); + +njs_chb_append(, start, string.start + string.size - start); ret = njs_string_create_chb(vm, retval, ); if (njs_slow_path(ret != NJS_OK)) { ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed String.prototype.replaceAll() with zero length argument.
details: https://hg.nginx.org/njs/rev/e496851c0fe7 branches: changeset: 2335:e496851c0fe7 user: Dmitry Volyntsev date: Wed May 22 17:26:08 2024 -0700 description: Fixed String.prototype.replaceAll() with zero length argument. This fixes #712 issue on Github. diffstat: src/njs_string.c | 15 --- src/njs_string.h | 4 src/test/njs_unit_test.c | 6 ++ 3 files changed, 14 insertions(+), 11 deletions(-) diffs (76 lines): diff -r bc09b884022d -r e496851c0fe7 src/njs_string.c --- a/src/njs_string.c Tue May 21 23:41:10 2024 -0700 +++ b/src/njs_string.c Wed May 22 17:26:08 2024 -0700 @@ -1736,7 +1736,9 @@ njs_string_index_of(njs_string_prop_t *s } else { /* UTF-8 string. */ -p = njs_string_utf8_offset(string->start, end, index); +p = (index < string->length) +? njs_string_utf8_offset(string->start, end, index) +: end; end -= search->size - 1; while (p < end) { @@ -3231,7 +3233,6 @@ njs_string_prototype_replace(njs_vm_t *v njs_int_t ret; njs_str_t str; njs_chb_t chain; -njs_bool_t is_ascii_string; njs_value_t*this, *search, *replace; njs_value_tsearch_lvalue, replace_lvalue, replacer, value, arguments[3]; @@ -3378,7 +3379,6 @@ njs_string_prototype_replace(njs_vm_t *v p_start = string.start; increment = s.length != 0 ? s.length : 1; -is_ascii_string = njs_is_ascii_string(); do { if (func_replace == NULL) { @@ -3405,14 +3405,7 @@ njs_string_prototype_replace(njs_vm_t *v } } -if (is_ascii_string) { -p = string.start + pos; - -} else { -p = njs_string_utf8_offset(string.start, string.start + string.size, - pos); -} - +p = njs_string_offset(, pos); (void) njs_string_prop(_string, ); njs_chb_append(, p_start, p - p_start); diff -r bc09b884022d -r e496851c0fe7 src/njs_string.h --- a/src/njs_string.h Tue May 21 23:41:10 2024 -0700 +++ b/src/njs_string.h Wed May 22 17:26:08 2024 -0700 @@ -245,6 +245,10 @@ njs_string_offset(njs_string_prop_t *str /* UTF-8 string. */ +if (index == (int64_t) string->length) { +return string->start + string->size; +} + return njs_string_utf8_offset(string->start, string->start + string->size, index); } diff -r bc09b884022d -r e496851c0fe7 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue May 21 23:41:10 2024 -0700 +++ b/src/test/njs_unit_test.c Wed May 22 17:26:08 2024 -0700 @@ -,6 +,12 @@ static njs_unit_test_t njs_test[] = { njs_str("var r = 'αβγ'.replaceAll('', 'X'); [r, r.length]"), njs_str("XαXβXγX,7") }, +{ njs_str("var r = ''.replaceAll('', 'z'); [r, r.length]"), + njs_str("z,1") }, + +{ njs_str("var r = 'α'.padStart(32).replaceAll('', 'z'); [r, r.length]"), + njs_str("z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z zαz,65") }, + { njs_str("'abc'.replace('b', (m, o, s) => `|${s}|${o}|${m}|`)"), njs_str("a|abc|1|b|c") }, ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Aligned StringIndexOf() implementation with the spec.
details: https://hg.nginx.org/njs/rev/bc09b884022d branches: changeset: 2334:bc09b884022d user: Dmitry Volyntsev date: Tue May 21 23:41:10 2024 -0700 description: Aligned StringIndexOf() implementation with the spec. When searchValue is empty the function should return early when fromIndex <= len is also true. diffstat: src/njs_string.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 2d098d2a1c85 -r bc09b884022d src/njs_string.c --- a/src/njs_string.c Tue May 21 23:41:10 2024 -0700 +++ b/src/njs_string.c Tue May 21 23:41:10 2024 -0700 @@ -1710,8 +1710,8 @@ njs_string_index_of(njs_string_prop_t *s length = string->length; -if (njs_slow_path(search->length == 0)) { -return (from < length) ? from : length; +if (search->length == 0 && from <= length) { +return from; } index = from; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Removed code for byte strings in built-in functions.
details: https://hg.nginx.org/njs/rev/2d098d2a1c85 branches: changeset: 2333:2d098d2a1c85 user: Dmitry Volyntsev date: Tue May 21 23:41:10 2024 -0700 description: Removed code for byte strings in built-in functions. diffstat: src/njs_array.c | 52 -- src/njs_iterator.c | 2 +- src/njs_json.c | 9 +- src/njs_object.c | 4 +- src/njs_regexp.c | 16 +++ src/njs_string.c | 65 +-- src/njs_string.h | 20 ++--- src/njs_vmcode.c | 9 -- src/test/njs_unit_test.c | 30 +- 9 files changed, 49 insertions(+), 158 deletions(-) diffs (596 lines): diff -r 27da19960b72 -r 2d098d2a1c85 src/njs_array.c --- a/src/njs_array.c Tue May 21 23:38:19 2024 -0700 +++ b/src/njs_array.c Tue May 21 23:41:10 2024 -0700 @@ -826,29 +826,15 @@ njs_array_prototype_slice_copy(njs_vm_t src = string.start; end = src + string.size; -if (string.length == 0) { -/* Byte string. */ -do { -value = >start[n++]; -dst = njs_string_short_start(value); -*dst = *src++; -njs_string_short_set(value, 1, 0); - -length--; -} while (length != 0); - -} else { -/* UTF-8 or ASCII string. */ -do { -value = >start[n++]; -dst = njs_string_short_start(value); -dst = njs_utf8_copy(dst, , end); -size = dst - njs_string_short_start(value); -njs_string_short_set(value, size, 1); - -length--; -} while (length != 0); -} +do { +value = >start[n++]; +dst = njs_string_short_start(value); +dst = njs_utf8_copy(dst, , end); +size = dst - njs_string_short_start(value); +njs_string_short_set(value, size, 1); + +length--; +} while (length != 0); } else if (njs_is_object(this)) { @@ -1647,11 +1633,10 @@ static njs_int_t njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { -u_char *p, *last; +u_char *p; int64_ti, size, len, length; njs_int_t ret; njs_chb_t chain; -njs_utf8_t utf8; njs_value_t*value, *this, entry; njs_string_prop_t separator, string; @@ -1684,7 +1669,6 @@ njs_array_prototype_join(njs_vm_t *vm, n } length = 0; -utf8 = njs_is_byte_string() ? NJS_STRING_BYTE : NJS_STRING_UTF8; ret = njs_object_length(vm, this, ); if (njs_slow_path(ret == NJS_ERROR)) { @@ -1708,29 +1692,15 @@ njs_array_prototype_join(njs_vm_t *vm, n if (!njs_is_null_or_undefined(value)) { if (!njs_is_string(value)) { -last = njs_chb_current(); - ret = njs_value_to_chain(vm, , value); if (njs_slow_path(ret < NJS_OK)) { return ret; } -if (last != njs_chb_current() && ret == 0) { -/* - * Appended values was a byte string. - */ -utf8 = NJS_STRING_BYTE; -} - length += ret; } else { (void) njs_string_prop(, value); - -if (njs_is_byte_string()) { -utf8 = NJS_STRING_BYTE; -} - length += string.length; njs_chb_append(, string.start, string.size); } @@ -1755,7 +1725,7 @@ njs_array_prototype_join(njs_vm_t *vm, n length -= separator.length; -p = njs_string_alloc(vm, retval, size, utf8 ? length : 0); +p = njs_string_alloc(vm, retval, size, length); if (njs_slow_path(p == NULL)) { return NJS_ERROR; } diff -r 27da19960b72 -r 2d098d2a1c85 src/njs_iterator.c --- a/src/njs_iterator.cTue May 21 23:38:19 2024 -0700 +++ b/src/njs_iterator.cTue May 21 23:41:10 2024 -0700 @@ -355,7 +355,7 @@ njs_object_iterate(njs_vm_t *vm, njs_ite end = p + string_prop.size; if ((size_t) length == string_prop.size) { -/* Byte or ASCII string. */ +/* ASCII string. */ for (i = from; i < to; i++) { /* This cannot fail. */ diff -r 27da19960b72 -r 2d098d2a1c85 src/njs_json.c --- a/src/njs_json.cTue May 21 23:38:19 2024 -0700 +++ b/src/njs_json.cTue May 21 23:41:10 2024 -0700 @@ -226,13 +226,6 @@ njs_json_stringify(njs_vm_t *vm, njs_val switch (space->type) { case N
[njs] Avoid creating byte strings explicitly.
details: https://hg.nginx.org/njs/rev/27da19960b72 branches: changeset: 2332:27da19960b72 user: Dmitry Volyntsev date: Tue May 21 23:38:19 2024 -0700 description: Avoid creating byte strings explicitly. Previously, calls like njs_string_new(,,,0) produced byte strings by explicitly providing zero length argument. diffstat: src/njs_builtin.c | 4 ++-- src/njs_json.c| 8 +--- src/njs_vm.c | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diffs (58 lines): diff -r 286dbef3c0b2 -r 27da19960b72 src/njs_builtin.c --- a/src/njs_builtin.c Mon May 20 16:44:10 2024 -0700 +++ b/src/njs_builtin.c Tue May 21 23:38:19 2024 -0700 @@ -388,7 +388,7 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t return NJS_ERROR; } -ret = njs_string_new(vm, >name, buf, p - buf, 0); +ret = njs_string_create(vm, >name, buf, p - buf); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -590,7 +590,7 @@ njs_ext_dump(njs_vm_t *vm, njs_value_t * return NJS_ERROR; } -return njs_string_new(vm, retval, str.start, str.length, 0); +return njs_string_create(vm, retval, str.start, str.length); } diff -r 286dbef3c0b2 -r 27da19960b72 src/njs_json.c --- a/src/njs_json.cMon May 20 16:44:10 2024 -0700 +++ b/src/njs_json.cTue May 21 23:38:19 2024 -0700 @@ -548,7 +548,6 @@ njs_json_parse_string(njs_json_parse_ctx { u_charch, *s, *dst; size_tsize, surplus; -ssize_t length; uint32_t utf, utf_low; njs_int_t ret; const u_char *start, *last; @@ -742,12 +741,7 @@ njs_json_parse_string(njs_json_parse_ctx start = dst; } -length = njs_utf8_length(start, size); -if (njs_slow_path(length < 0)) { -length = 0; -} - -ret = njs_string_new(ctx->vm, value, (u_char *) start, size, length); +ret = njs_string_create(ctx->vm, value, (u_char *) start, size); if (njs_slow_path(ret != NJS_OK)) { return NULL; } diff -r 286dbef3c0b2 -r 27da19960b72 src/njs_vm.c --- a/src/njs_vm.c Mon May 20 16:44:10 2024 -0700 +++ b/src/njs_vm.c Tue May 21 23:38:19 2024 -0700 @@ -874,7 +874,7 @@ njs_vm_bind2(njs_vm_t *vm, const njs_str njs_lvlhsh_t*hash; njs_lvlhsh_query_t lhq; -ret = njs_string_new(vm, >name, var_name->start, var_name->length, 0); +ret = njs_string_create(vm, >name, var_name->start, var_name->length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] HTTP: fixed handling of 0 length request body.
details: https://hg.nginx.org/njs/rev/286dbef3c0b2 branches: changeset: 2331:286dbef3c0b2 user: Dmitry Volyntsev date: Mon May 20 16:44:10 2024 -0700 description: HTTP: fixed handling of 0 length request body. Previously, when r.requestBuffer was passed as a body argument to ngx.fetch() or r.subrequest() then exception was thrown "Error: invalid Request body" when the request body had 0 length. diffstat: src/njs_vm.c | 6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diffs (16 lines): diff -r 8851a78723dc -r 286dbef3c0b2 src/njs_vm.c --- a/src/njs_vm.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_vm.c Mon May 20 16:44:10 2024 -0700 @@ -1602,6 +1602,12 @@ njs_vm_value_to_bytes(njs_vm_t *vm, njs_ } if (njs_slow_path(njs_is_detached_buffer(buffer))) { +if (length == 0) { +dst->length = 0; +dst->start = NULL; +return NJS_OK; +} + njs_type_error(vm, "detached buffer"); return NJS_ERROR; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Removing njs_string_set() from builtin functions.
details: https://hg.nginx.org/njs/rev/8851a78723dc branches: changeset: 2330:8851a78723dc user: Dmitry Volyntsev date: Fri May 17 21:54:50 2024 -0700 description: Removing njs_string_set() from builtin functions. This is the last function that produced byte strings. diffstat: src/njs_builtin.c| 9 - src/njs_error.c | 2 +- src/njs_extern.c | 5 +++-- src/njs_parser.c | 2 +- src/njs_regexp.c | 4 ++-- src/njs_string.c | 4 ++-- src/njs_string.h | 3 ++- src/njs_vm.c | 4 ++-- src/test/njs_benchmark.c | 2 +- 9 files changed, 18 insertions(+), 17 deletions(-) diffs (159 lines): diff -r 4e0553f7ea68 -r 8851a78723dc src/njs_builtin.c --- a/src/njs_builtin.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_builtin.c Fri May 17 21:54:50 2024 -0700 @@ -1201,8 +1201,8 @@ njs_process_object_argv(njs_vm_t *vm, nj i = 0; for (arg = vm->options.argv; i < vm->options.argc; arg++) { -njs_string_set(vm, >start[i++], (u_char *) *arg, - njs_strlen(*arg)); +njs_string_create(vm, >start[i++], (u_char *) *arg, + njs_strlen(*arg)); } prop = njs_object_prop_alloc(vm, _string, _value_undefined, 1); @@ -1265,7 +1265,7 @@ njs_env_hash_init(njs_vm_t *vm, njs_lvlh continue; } -ret = njs_string_create(vm, >name, (char *) entry, val - entry); +ret = njs_string_create(vm, >name, entry, val - entry); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1285,8 +1285,7 @@ njs_env_hash_init(njs_vm_t *vm, njs_lvlh val++; -ret = njs_string_create(vm, njs_prop_value(prop), (char *) val, -njs_strlen(val)); +ret = njs_string_create(vm, njs_prop_value(prop), val, njs_strlen(val)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } diff -r 4e0553f7ea68 -r 8851a78723dc src/njs_error.c --- a/src/njs_error.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_error.c Fri May 17 21:54:50 2024 -0700 @@ -147,7 +147,7 @@ njs_error_stack_new(njs_vm_t *vm, njs_ob return ret; } -return njs_string_set(vm, retval, string.start, string.length); +return njs_string_create(vm, retval, string.start, string.length); } diff -r 4e0553f7ea68 -r 8851a78723dc src/njs_extern.c --- a/src/njs_extern.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_extern.c Fri May 17 21:54:50 2024 -0700 @@ -74,8 +74,9 @@ njs_external_add(njs_vm_t *vm, njs_arr_t lhq.key_hash = external->name.symbol; } else { -ret = njs_string_set(vm, >name, external->name.string.start, - external->name.string.length); +ret = njs_string_create(vm, >name, +external->name.string.start, +external->name.string.length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } diff -r 4e0553f7ea68 -r 8851a78723dc src/njs_parser.c --- a/src/njs_parser.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_parser.c Fri May 17 21:54:50 2024 -0700 @@ -9242,7 +9242,7 @@ njs_parser_error(njs_vm_t *vm, njs_objec njs_value_property_set(vm, , njs_value_arg(_number), ); if (file->length != 0) { -ret = njs_string_set(vm, , file->start, file->length); +ret = njs_string_create(vm, , file->start, file->length); if (ret == NJS_OK) { njs_value_property_set(vm, , njs_value_arg(_name), ); diff -r 4e0553f7ea68 -r 8851a78723dc src/njs_regexp.c --- a/src/njs_regexp.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_regexp.c Fri May 17 21:54:50 2024 -0700 @@ -1144,8 +1144,8 @@ njs_regexp_exec_result(njs_vm_t *vm, njs do { group = >groups[i]; -ret = njs_string_set(vm, , group->name.start, - group->name.length); +ret = njs_string_create(vm, , group->name.start, +group->name.length); if (njs_slow_path(ret != NJS_OK)) { goto fail; } diff -r 4e0553f7ea68 -r 8851a78723dc src/njs_string.c --- a/src/njs_string.c Fri May 17 21:54:50 2024 -0700 +++ b/src/njs_string.c Fri May 17 21:54:50 2024 -0700 @@ -127,7 +127,7 @@ njs_string_set(njs_vm_t *vm, njs_value_t njs_int_t -njs_string_create(njs_vm_t *vm, njs_value_t *value, const char *src, +njs_string_create(njs_vm_t *vm, njs_value_t *value, const u_char *src, size_t size) { u_char *p, *p_end; @@ -3152,7 +3152,7 @@ njs_string_get_substitution(njs_vm_t *vm p += 2; -ret = njs_string_create(vm, , (const char *) p, r - p); +ret = njs_str
[njs] Change: removed byte strings API.
details: https://hg.nginx.org/njs/rev/4e0553f7ea68 branches: changeset: 2329:4e0553f7ea68 user: Dmitry Volyntsev date: Fri May 17 21:54:50 2024 -0700 description: Change: removed byte strings API. These functions are unsafe because they produce byte strings. Byte strings may not work as expected with the existing JS methods. The following functions were removed: - njs_vm_value_string_set() use njs_vm_value_string_create() as a drop-in replacement. - njs_vm_value_string_alloc() use njs_chb_t and njs_vm_value_string_create_chb() instead. This fixes #710 on Github. diffstat: external/njs_query_string_module.c |2 +- external/njs_shell.c |4 +- external/njs_webcrypto_module.c| 54 ++-- external/njs_xml_module.c | 20 ++-- nginx/ngx_http_js_module.c | 150 ++-- nginx/ngx_js.c | 34 nginx/ngx_js.h |2 +- nginx/ngx_js_fetch.c | 32 +++--- nginx/ngx_js_shared_dict.c | 25 +++-- nginx/ngx_stream_js_module.c |4 +- src/njs.h |8 - src/njs_string.c |2 +- src/njs_vm.c | 19 + src/test/njs_benchmark.c | 12 +- src/test/njs_externals_test.c | 38 src/test/njs_unit_test.c | 32 +++--- 16 files changed, 193 insertions(+), 245 deletions(-) diffs (truncated from 1114 to 1000 lines): diff -r dec46ad52e9a -r 4e0553f7ea68 external/njs_query_string_module.c --- a/external/njs_query_string_module.cFri May 17 21:54:49 2024 -0700 +++ b/external/njs_query_string_module.cFri May 17 21:54:50 2024 -0700 @@ -694,7 +694,7 @@ njs_query_string_stringify(njs_vm_t *vm, object = njs_arg(args, nargs, 1); if (njs_slow_path(!njs_value_is_object(object))) { -njs_vm_value_string_set(vm, retval, (u_char *) "", 0); +njs_vm_value_string_create(vm, retval, (u_char *) "", 0); return NJS_OK; } diff -r dec46ad52e9a -r 4e0553f7ea68 external/njs_shell.c --- a/external/njs_shell.c Fri May 17 21:54:49 2024 -0700 +++ b/external/njs_shell.c Fri May 17 21:54:50 2024 -0700 @@ -1579,8 +1579,8 @@ njs_engine_njs_complete(njs_engine_t *en while (p < end && *p != '.') { p++; } -ret = njs_vm_value_string_set(vm, njs_value_arg(), start, - p - start); +ret = njs_vm_value_string_create(vm, njs_value_arg(), start, + p - start); if (njs_slow_path(ret != NJS_OK)) { return NULL; } diff -r dec46ad52e9a -r 4e0553f7ea68 external/njs_webcrypto_module.c --- a/external/njs_webcrypto_module.c Fri May 17 21:54:49 2024 -0700 +++ b/external/njs_webcrypto_module.c Fri May 17 21:54:50 2024 -0700 @@ -1855,7 +1855,7 @@ njs_export_jwk_rsa(njs_vm_t *vm, njs_web return NJS_ERROR; } -njs_vm_value_string_set(vm, njs_value_arg(_s), (u_char *) "RSA", 3); +njs_vm_value_string_create(vm, njs_value_arg(_s), (u_char *) "RSA", 3); ret = njs_vm_object_prop_set(vm, retval, _kty, _s); if (ret != NJS_OK) { @@ -1909,8 +1909,8 @@ njs_export_jwk_rsa(njs_vm_t *vm, njs_web nm = _webcrypto_alg_name[key->alg->type][key->hash]; -(void) njs_vm_value_string_set(vm, njs_value_arg(), nm->start, - nm->length); +(void) njs_vm_value_string_create(vm, njs_value_arg(), nm->start, + nm->length); return njs_vm_object_prop_set(vm, retval, _alg, ); } @@ -1975,8 +1975,8 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webc nid = EC_GROUP_get_curve_name(group); cname = njs_algorithm_curve_name(nid); -(void) njs_vm_value_string_set(vm, njs_value_arg(), - cname->start, cname->length); +(void) njs_vm_value_string_create(vm, njs_value_arg(), + cname->start, cname->length); if (cname->length == 0) { njs_vm_type_error(vm, "Unsupported JWK EC curve: %s", OBJ_nid2sn(nid)); @@ -1988,7 +1988,7 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webc goto fail; } -njs_vm_value_string_set(vm, njs_value_arg(_s), (u_char *) "EC", 2); +njs_vm_value_string_create(vm, njs_value_arg(_s), (u_char *) "EC", 2); ret = njs_vm_object_prop_set(vm, retval, _kty, _s); if (ret != NJS_OK) { @@ -2154,8 +2154,8 @@ njs_export_jwk_oct(njs_vm_t *vm, njs_web if (key->alg->type == NJS_ALGORITHM_HMAC) { nm = _webcrypto_alg_name[type][key->hash]; -(void) njs_vm_value_string_set(vm, njs_value_arg(), nm->start, - nm->length); +(void) njs_vm_value_string_create(vm, njs_
[njs] Optimized string creation with ASCII input.
details: https://hg.nginx.org/njs/rev/dec46ad52e9a branches: changeset: 2328:dec46ad52e9a user: Dmitry Volyntsev date: Fri May 17 21:54:49 2024 -0700 description: Optimized string creation with ASCII input. diffstat: src/njs_string.c | 12 1 files changed, 12 insertions(+), 0 deletions(-) diffs (24 lines): diff -r f474755a4dce -r dec46ad52e9a src/njs_string.c --- a/src/njs_string.c Fri May 17 18:36:12 2024 -0700 +++ b/src/njs_string.c Fri May 17 21:54:49 2024 -0700 @@ -130,8 +130,20 @@ njs_int_t njs_string_create(njs_vm_t *vm, njs_value_t *value, const char *src, size_t size) { +u_char *p, *p_end; njs_str_t str; +p = (u_char *) src; +p_end = p + size; + +while (p < p_end && *p < 0x80) { + p++; +} + +if (p == p_end) { +return njs_string_new(vm, value, (u_char *) src, size, size); +} + str.start = (u_char *) src; str.length = size; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Added string creation benchmark.
details: https://hg.nginx.org/njs/rev/f474755a4dce branches: changeset: 2327:f474755a4dce user: Dmitry Volyntsev date: Fri May 17 18:36:12 2024 -0700 description: Added string creation benchmark. diffstat: src/test/njs_benchmark.c | 159 ++- 1 files changed, 158 insertions(+), 1 deletions(-) diffs (185 lines): diff -r 02369792b032 -r f474755a4dce src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Thu May 09 12:58:57 2024 -0700 +++ b/src/test/njs_benchmark.c Fri May 17 18:36:12 2024 -0700 @@ -29,12 +29,52 @@ typedef struct { } njs_opts_t; +static njs_int_t njs_benchmark_preinit(njs_vm_t *vm); +static njs_int_t njs_benchmark_init(njs_vm_t *vm); +static njs_int_t njs_benchmark_string(njs_vm_t *vm, njs_value_t *args, +njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); + + +static njs_external_t njs_benchmark_external[] = { + +{ +.flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL, +.name.symbol = NJS_SYMBOL_TO_STRING_TAG, +.u.property = { +.value = "Benchmark", +} +}, + +{ +.flags = NJS_EXTERN_METHOD, +.name.string = njs_str("string"), +.writable = 1, +.configurable = 1, +.enumerable = 1, +.u.method = { +.native = njs_benchmark_string, +} +}, +}; + + +njs_module_t njs_benchmark_module = { +.name = njs_str("benchmark"), +.preinit = njs_benchmark_preinit, +.init = njs_benchmark_init, +}; + + njs_module_t *njs_benchmark_addon_external_modules[] = { _unit_test_external_module, -NULL, +_benchmark_module, +NULL }; +static njs_int_tnjs_benchmark_proto_id; + + static uint64_t njs_time(void) { @@ -225,6 +265,46 @@ static njs_benchmark_test_t njs_test[] njs_str("4"), 10 }, +{ "string set 'abcdefABCDEF'", + njs_str("benchmark.string('set', 'abcdef', 100)"), + njs_str("undefined"), + 1 }, + +{ "string set 'АБВГДЕ'", + njs_str("benchmark.string('set', 'АБВГДЕ', 100)"), + njs_str("undefined"), + 1 }, + +{ "string set 'x'.repeat(24)", + njs_str("benchmark.string('set', 'x'.repeat(32), 100)"), + njs_str("undefined"), + 1 }, + +{ "string set 'Д'.repeat(12)", + njs_str("benchmark.string('set', 'А'.repeat(16), 100)"), + njs_str("undefined"), + 1 }, + +{ "string create 'abcdefABCDEF'", + njs_str("benchmark.string('create', 'abcdef', 100)"), + njs_str("undefined"), + 1 }, + +{ "string create 'АБВГДЕ'", + njs_str("benchmark.string('create', 'АБВГДЕ', 100)"), + njs_str("undefined"), + 1 }, + +{ "string create 'x'.repeat(24)", + njs_str("benchmark.string('create', 'x'.repeat(32), 100)"), + njs_str("undefined"), + 1 }, + +{ "string create 'Д'.repeat(12)", + njs_str("benchmark.string('create', 'А'.repeat(16), 100)"), + njs_str("undefined"), + 1 }, + { "JSON.parse", njs_str("JSON.parse('{\"a\":123, \"XXX\":[3,4,null]}').a"), njs_str("123"), @@ -570,3 +650,80 @@ invalid_options: return EXIT_FAILURE; } + + +static njs_int_t +njs_benchmark_preinit(njs_vm_t *vm) +{ +njs_benchmark_proto_id = njs_vm_external_prototype(vm, + njs_benchmark_external, + njs_nitems(njs_benchmark_external)); +if (njs_slow_path(njs_benchmark_proto_id < 0)) { +njs_printf("njs_vm_external_prototype() failed\n"); +return NJS_ERROR; +} + +return NJS_OK; +} + + +static njs_int_t +njs_benchmark_init(njs_vm_t *vm) +{ +njs_int_t ret; +njs_opaque_value_t value; + +static const njs_str_t benchmark = njs_str("benchmark"); + +ret = njs_vm_external_create(vm, njs_value_arg(), + njs_benchmark_proto_id, NULL, 1); +if (njs_slow_path(ret != NJS_OK)) { +return NJS_ERROR; +} + +ret = njs_vm_bind(vm, , njs_value_arg(), 1); +if (njs_slow_path(ret != NJS_OK)) { +njs_printf("njs_vm_bind() failed\n"); +return NJS_ERROR; +} + +return NJS_OK; +} + + +static njs_int_t +njs_benchmark_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, +njs_index_t unused, njs_value_t *retval) +{ +int64_t i, n; +njs_str_ts, mode; +njs_value_t value; + +njs_value_string_get(njs_arg(args, nargs, 1), ); + +njs_value_string_get(njs_arg(args, nargs, 2), ); + +if (njs_value_to_integer(vm, njs_arg(args, nar
[njs] Configure: fixed QuickJS detection with --with-quickjs flag.
details: https://hg.nginx.org/njs/rev/02369792b032 branches: changeset: 2326:02369792b032 user: Dmitry Volyntsev date: Thu May 09 12:58:57 2024 -0700 description: Configure: fixed QuickJS detection with --with-quickjs flag. diffstat: auto/quickjs | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r f146b5dc21cc -r 02369792b032 auto/quickjs --- a/auto/quickjs Wed May 01 17:31:01 2024 -0700 +++ b/auto/quickjs Thu May 09 12:58:57 2024 -0700 @@ -81,7 +81,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $njs_feature_libs" fi -if [ $NJS_QUICKJS = YES -a $njs_found = no ]; then +if [ $NJS_QUICKJS = YES -a $NJS_HAVE_QUICKJS = NO ]; then echo echo $0: error: no QuickJS library found. echo ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] QuickJS: added zlib module.
details: https://hg.nginx.org/njs/rev/f146b5dc21cc branches: changeset: 2325:f146b5dc21cc user: Dmitry Volyntsev date: Wed May 01 17:31:01 2024 -0700 description: QuickJS: added zlib module. diffstat: auto/init | 1 + auto/make |42 +- auto/qjs_module| 6 + auto/qjs_modules |20 + auto/quickjs |21 + auto/sources | 4 + configure | 3 +- external/njs_shell.c |15 +- external/qjs_zlib_module.c | 512 +++ src/qjs.c | 109 src/qjs.h |79 ++ src/qjs_buffer.c | 1174 src/test/njs_unit_test.c | 301 --- test/buffer.t.js | 236 test/harness/runTsuite.js |10 +- test/setup | 2 +- test/zlib.t.mjs| 109 17 files changed, 2322 insertions(+), 322 deletions(-) diffs (truncated from 2828 to 1000 lines): diff -r 18fc657411ca -r f146b5dc21cc auto/init --- a/auto/init Fri Apr 26 16:48:19 2024 -0700 +++ b/auto/init Wed May 01 17:31:01 2024 -0700 @@ -16,6 +16,7 @@ NJS_CFLAGS=${NJS_CFLAGS=} NJS_BUILD_DIR=${NJS_BUILD_DIR:-build} NJS_LIB_MODULES= +QJS_LIB_MODULES= NJS_LIBRT= diff -r 18fc657411ca -r f146b5dc21cc auto/make --- a/auto/make Fri Apr 26 16:48:19 2024 -0700 +++ b/auto/make Wed May 01 17:31:01 2024 -0700 @@ -15,11 +15,6 @@ njs_modules_c=$NJS_BUILD_DIR/njs_modules NJS_LIB_SRCS="$NJS_LIB_SRCS $njs_modules_c" -njs_incs=`echo $NJS_LIB_INCS \ -| sed -e "s# *\([^ ]*\)#$njs_regex_cont-I\1#g"` -njs_objs=`echo $NJS_LIB_SRCS \ -| sed -e "s# *\([^ ]*\.\)c#$NJS_BUILD_DIR/\1o$njs_regex_cont#g"` - cat << END> $njs_modules_c #include @@ -45,6 +40,43 @@ cat << END END +if [ $NJS_HAVE_QUICKJS = YES ]; then + +qjs_modules_c=$NJS_BUILD_DIR/qjs_modules.c + +NJS_LIB_SRCS="$NJS_LIB_SRCS $qjs_modules_c" + +cat << END> $qjs_modules_c + +#include + +END + +for mod in $QJS_LIB_MODULES +do +echo "extern qjs_module_t $mod;" >> $qjs_modules_c +done + +echo >> $qjs_modules_c +echo 'qjs_module_t *qjs_modules[] = {'>> $qjs_modules_c + +for mod in $QJS_LIB_MODULES +do +echo "&$mod," >> $qjs_modules_c +done + +cat << END>> $qjs_modules_c +NULL +}; + +END +fi + +njs_incs=`echo $NJS_LIB_INCS \ +| sed -e "s# *\([^ ]*\)#$njs_regex_cont-I\1#g"` +njs_objs=`echo $NJS_LIB_SRCS \ +| sed -e "s# *\([^ ]*\.\)c#$NJS_BUILD_DIR/\1o$njs_regex_cont#g"` + cat << END > $NJS_MAKEFILE # This file is auto-generated by configure diff -r 18fc657411ca -r f146b5dc21cc auto/qjs_module --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/auto/qjs_module Wed May 01 17:31:01 2024 -0700 @@ -0,0 +1,6 @@ +# Copyright (C) Dmitry Volyntsev +# Copyright (C) F5, Inc + +QJS_LIB_MODULES="$QJS_LIB_MODULES $njs_module_name" +NJS_LIB_SRCS="$NJS_LIB_SRCS $njs_module_srcs" +NJS_LIB_INCS="$NJS_LIB_INCS $njs_module_incs" diff -r 18fc657411ca -r f146b5dc21cc auto/qjs_modules --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/auto/qjs_modules Wed May 01 17:31:01 2024 -0700 @@ -0,0 +1,20 @@ +# Copyright (C) Dmitry Volyntsev +# Copyright (C) F5, Inc + +if [ $NJS_HAVE_QUICKJS = YES ]; then + +njs_module_name=qjs_buffer_module +njs_module_incs= +njs_module_srcs=src/qjs_buffer.c + +. auto/qjs_module + +if [ $NJS_ZLIB = YES -a $NJS_HAVE_ZLIB = YES ]; then +njs_module_name=qjs_zlib_module +njs_module_incs= +njs_module_srcs=external/qjs_zlib_module.c + +. auto/qjs_module +fi + +fi diff -r 18fc657411ca -r f146b5dc21cc auto/quickjs --- a/auto/quickjs Fri Apr 26 16:48:19 2024 -0700 +++ b/auto/quickjs Wed May 01 17:31:01 2024 -0700 @@ -25,6 +25,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then JSRuntime *rt; rt = JS_NewRuntime(); + (void) JS_GetClassID; JS_FreeRuntime(rt); return 0; }" @@ -54,6 +55,26 @@ if [ $NJS_TRY_QUICKJS = YES ]; then fi if [ $njs_found = yes ]; then + +njs_feature="QuickJS JS_NewTypedArray()" +njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored \"-Wcast-function-type\" + #endif + + #include +
[njs] Tests: fixed typo in stream_js_dup_set.t introduced in be271e8d0b3b.
details: https://hg.nginx.org/njs/rev/18fc657411ca branches: changeset: 2324:18fc657411ca user: Dmitry Volyntsev date: Fri Apr 26 16:48:19 2024 -0700 description: Tests: fixed typo in stream_js_dup_set.t introduced in be271e8d0b3b. Previously, with typo the test was always skipped. diffstat: nginx/t/stream_js_dup_set.t | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 7456fe29ac0a -r 18fc657411ca nginx/t/stream_js_dup_set.t --- a/nginx/t/stream_js_dup_set.t Fri Apr 26 16:48:17 2024 -0700 +++ b/nginx/t/stream_js_dup_set.t Fri Apr 26 16:48:19 2024 -0700 @@ -46,7 +46,7 @@ stream { server { listen 127.0.0.1:8082; -js_set $test test.foo1; +js_set $test test.foo; return 8082:$test; } } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fetch: fixed request Host header when the port is non-standard.
details: https://hg.nginx.org/njs/rev/7456fe29ac0a branches: changeset: 2323:7456fe29ac0a user: Dmitry Volyntsev date: Fri Apr 26 16:48:17 2024 -0700 description: Fetch: fixed request Host header when the port is non-standard. This fixes #707 issue on Github. diffstat: nginx/ngx_js_fetch.c| 5 +++ nginx/t/js_fetch_resolver.t | 69 2 files changed, 67 insertions(+), 7 deletions(-) diffs (122 lines): diff -r 622387b5b612 -r 7456fe29ac0a nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Fri Apr 26 16:27:52 2024 -0700 +++ b/nginx/ngx_js_fetch.c Fri Apr 26 16:48:17 2024 -0700 @@ -786,6 +786,11 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value if (!has_host) { njs_chb_append_literal(>chain, "Host: "); njs_chb_append(>chain, u.host.data, u.host.len); + +if (!u.no_port) { +njs_chb_sprintf(>chain, 32, ":%d", u.port); +} + njs_chb_append_literal(>chain, CRLF); } diff -r 622387b5b612 -r 7456fe29ac0a nginx/t/js_fetch_resolver.t --- a/nginx/t/js_fetch_resolver.t Fri Apr 26 16:27:52 2024 -0700 +++ b/nginx/t/js_fetch_resolver.t Fri Apr 26 16:48:17 2024 -0700 @@ -65,6 +65,23 @@ http { location /loc { js_content test.loc; } + +location /host { +return 200 8080:$http_host; +} +} + +server { +listen 127.0.0.1:8081; +server_name aaa; + +location /loc { +js_content test.loc; +} + +location /host { +return 200 8081:$http_host; +} } server { @@ -80,19 +97,29 @@ http { EOF my $p0 = port(8080); +my $p1 = port(8081); $t->write_file('test.js', <http://\${r.args.domain}:$p0/loc`; +const p0 = $p0; +const p1 = $p1; + +async function dns(r) { +var port = r.args.port == undefined || r.args.port == 'p0' ? p0 : p1; +var loc = r.args.loc == undefined ? 'loc' : r.args.loc; +var url = `http://\${r.args.domain}:\${port}/\${loc}`; -ngx.fetch(url) -.then(reply => reply.text()) -.then(body => r.return(200, body)) -.catch(e => r.return(501, e.message)) +try { +let reply = await ngx.fetch(url); +let body = await reply.text(); +r.return(200, body); + +} catch (e) { +r.return(501, e.message); +} } function str(v) { return v ? v : ''}; @@ -109,7 +136,7 @@ my $p0 = port(8080); export default {njs: test_njs, dns, loc}; EOF -$t->try_run('no njs.fetch')->plan(3); +$t->try_run('no njs.fetch')->plan(5); $t->run_daemon(\_daemon, port(8981), $t); $t->waitforfile($t->testdir . '/' . port(8981)); @@ -121,6 +148,34 @@ like(http_get('/dns?domain=many'), qr/ma like(http_get('/dns?domain=unknown'), qr/"unknown" could not be resolved/s, 'fetch dns unknown'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.5'); + +like(http_get('/dns?domain=aaa=p0=host'), qr/8080:aaa:$p0$/s, + 'fetch aaa:8080'); +like(http_get('/dns?domain=aaa=p1=host'), qr/8081:aaa:$p1$/s, + 'fetch aaa:8081'); +} + +### + +sub has_version { + my $need = shift; + + http_get('/njs') =~ /^([.0-9]+)$/m; + + my @v = split(/\./, $1); + my ($n, $v); + + for $n (split(/\./, $need)) { + $v = shift @v || 0; + return 0 if $n > $v; + return 1 if $v > $n; + } + + return 1; +} + ### sub reply_handler { ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Allowing to use custom allocator in njs_chb_t.
details: https://hg.nginx.org/njs/rev/622387b5b612 branches: changeset: 2322:622387b5b612 user: Dmitry Volyntsev date: Fri Apr 26 16:27:52 2024 -0700 description: Allowing to use custom allocator in njs_chb_t. diffstat: external/njs_query_string_module.c | 6 +++--- external/njs_xml_module.c | 2 +- external/njs_zlib_module.c | 4 ++-- nginx/ngx_js_fetch.c | 6 +++--- src/njs_array.c| 2 +- src/njs_chb.c | 21 + src/njs_chb.h | 27 --- src/njs_error.c| 2 +- src/njs_function.c | 2 +- src/njs_json.c | 4 ++-- src/njs_regexp.c | 2 +- src/njs_string.c | 8 src/njs_typed_array.c | 2 +- src/njs_vm.c | 2 +- src/test/njs_unit_test.c | 2 +- 15 files changed, 55 insertions(+), 37 deletions(-) diffs (347 lines): diff -r a97a9f3b3cea -r 622387b5b612 external/njs_query_string_module.c --- a/external/njs_query_string_module.cMon Apr 22 18:59:03 2024 -0700 +++ b/external/njs_query_string_module.cFri Apr 26 16:27:52 2024 -0700 @@ -152,7 +152,7 @@ njs_query_string_decode(njs_vm_t *vm, nj -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; -njs_chb_init(, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(, vm); njs_utf8_decode_init(); cp = 0; @@ -749,7 +749,7 @@ njs_query_string_stringify(njs_vm_t *vm, encode = njs_value_function(val); } -njs_chb_init(, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(, vm); keys = njs_vm_object_keys(vm, object, njs_value_arg()); if (njs_slow_path(keys == NULL)) { @@ -841,7 +841,7 @@ njs_query_string_escape(njs_vm_t *vm, nj njs_value_string_get(string, ); -njs_chb_init(, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(, vm); ret = njs_query_string_encode(, ); if (njs_slow_path(ret != NJS_OK)) { diff -r a97a9f3b3cea -r 622387b5b612 external/njs_xml_module.c --- a/external/njs_xml_module.c Mon Apr 22 18:59:03 2024 -0700 +++ b/external/njs_xml_module.c Fri Apr 26 16:27:52 2024 -0700 @@ -1788,7 +1788,7 @@ njs_xml_ext_canonicalization(njs_vm_t *v } } -njs_chb_init(, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(, vm); buf = xmlOutputBufferCreateIO(njs_xml_buf_write_cb, NULL, , NULL); if (njs_slow_path(buf == NULL)) { diff -r a97a9f3b3cea -r 622387b5b612 external/njs_zlib_module.c --- a/external/njs_zlib_module.cMon Apr 22 18:59:03 2024 -0700 +++ b/external/njs_zlib_module.cFri Apr 26 16:27:52 2024 -0700 @@ -320,7 +320,7 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v } } -njs_chb_init(, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(, vm); do { stream.next_out = njs_chb_reserve(, chunk_size); @@ -461,7 +461,7 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v } } -njs_chb_init(, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(, vm); while (rc != Z_STREAM_END) { stream.next_out = njs_chb_reserve(, chunk_size); diff -r a97a9f3b3cea -r 622387b5b612 nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Mon Apr 22 18:59:03 2024 -0700 +++ b/nginx/ngx_js_fetch.c Fri Apr 26 16:27:52 2024 -0700 @@ -740,7 +740,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value http->header_only = njs_strstr_eq(, _str_value("HEAD")); -njs_chb_init(>chain, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(>chain, vm); njs_chb_append(>chain, request.method.start, request.method.length); njs_chb_append_literal(>chain, " "); @@ -1051,7 +1051,7 @@ ngx_js_ext_response_constructor(njs_vm_t } } -njs_chb_init(>chain, njs_vm_memory_pool(vm)); +NJS_CHB_MP_INIT(>chain, vm); body = njs_arg(args, nargs, 1); @@ -2468,7 +2468,7 @@ ngx_js_http_process_headers(ngx_js_http_ njs_chb_destroy(>chain); -njs_chb_init(>response.chain, njs_vm_memory_pool(http->vm)); +NJS_CHB_MP_INIT(>response.chain, http->vm); http->process = ngx_js_http_process_body; diff -r a97a9f3b3cea -r 622387b5b612 src/njs_array.c --- a/src/njs_array.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_array.c Fri Apr 26 16:27:52 2024 -0700 @@ -1698,7 +1698,7 @@ njs_array_prototype_join(njs_vm_t *vm, n value = -njs_chb_init(, vm->mem_pool); +NJS_CHB_MP_INIT(, vm); for (i = 0; i < len; i++) { ret = njs_value_property_i64(vm, this, i, value); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_chb.c --- a/src/njs_chb.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_chb.c Fri Apr 26 16:27:52 2024 -0700 @@ -12,6 +12,19 @@ void +njs_chb_init(njs_chb_t *chain, void *pool, njs_chb_alloc_t alloc, +njs_chb_free_t free) +{ +chain->error = 0; +ch
[njs] Configure: fixed default path QuickJS discovery typo.
details: https://hg.nginx.org/njs/rev/a97a9f3b3cea branches: changeset: 2321:a97a9f3b3cea user: Dmitry Volyntsev date: Mon Apr 22 18:59:03 2024 -0700 description: Configure: fixed default path QuickJS discovery typo. The issue was introduced in 1c8b6b9bc06c (0.8.4). This closes #706 issue on Github. diffstat: auto/quickjs | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r 0cb259f67ade -r a97a9f3b3cea auto/quickjs --- a/auto/quickjs Mon Apr 22 17:52:14 2024 -0700 +++ b/auto/quickjs Mon Apr 22 18:59:03 2024 -0700 @@ -40,7 +40,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs.lto" njs_feature_incs="/usr/include/quickjs/" -njs_feature_libs="-L/usr/lib/quickjs/ -lquijs.lto -lm -ldl -lpthread" +njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs.lto -lm -ldl -lpthread" . auto/feature fi @@ -48,7 +48,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs" njs_feature_incs="/usr/include/quickjs/" -njs_feature_libs="-L/usr/lib/quickjs/ -lquijs -lm -ldl -lpthread" +njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs -lm -ldl -lpthread" . auto/feature fi ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Zlib: improved tests with zlib-ng.
details: https://hg.nginx.org/njs/rev/0cb259f67ade branches: changeset: 2320:0cb259f67ade user: Dmitry Volyntsev date: Mon Apr 22 17:52:14 2024 -0700 description: Zlib: improved tests with zlib-ng. This fixes #704 issue on Github. diffstat: src/test/njs_unit_test.c | 13 +++-- 1 files changed, 7 insertions(+), 6 deletions(-) diffs (25 lines): diff -r d640adf691a7 -r 0cb259f67ade src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Apr 22 17:52:06 2024 -0700 +++ b/src/test/njs_unit_test.c Mon Apr 22 17:52:14 2024 -0700 @@ -22319,14 +22319,15 @@ static njs_unit_test_t njs_zlib_test[] njs_str("WAKA,αβγ") }, { njs_str("const zlib = require('zlib');" - "['WAKA', 'αβγ']" - ".map(v => zlib.deflateRawSync(v).toString('base64'))"), - njs_str("C3f0dgQA,O7fx3KZzmwE=") }, + "const enc = ['WAKA', 'αβγ'].map(v => zlib.deflateRawSync(v).toString('base64'));" + "enc.map(v => zlib.inflateRawSync(Buffer.from(v, 'base64')).toString())"), + njs_str("WAKA,αβγ") }, { njs_str("const zlib = require('zlib');" - "['WAKA', 'αβγ']" - ".map(v => zlib.deflateRawSync(v, {dictionary: Buffer.from('WAKA')}).toString('base64'))"), - njs_str("CwdiAA==,O7fx3KZzmwE=") }, + "const enc = ['WAKA', 'αβγ']" + ".map(v => zlib.deflateRawSync(v, {dictionary: Buffer.from('WAKA')}).toString('base64'));" + "enc.map(v => zlib.inflateRawSync(Buffer.from(v, 'base64'), {dictionary: Buffer.from('WAKA')}))"), + njs_str("WAKA,αβγ") }, { njs_str("const zlib = require('zlib');" "['WAKA', 'αβγ']" ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Zlib: fixed inflate().
details: https://hg.nginx.org/njs/rev/d640adf691a7 branches: changeset: 2319:d640adf691a7 user: Dmitry Volyntsev date: Mon Apr 22 17:52:06 2024 -0700 description: Zlib: fixed inflate(). Previously, the function might fail to return the last part of the compressed content. This problem is more visible when output size > 1024 or when chunkSize < the content size. diffstat: external/njs_zlib_module.c | 2 +- src/test/njs_unit_test.c | 7 +++ 2 files changed, 8 insertions(+), 1 deletions(-) diffs (29 lines): diff -r be271e8d0b3b -r d640adf691a7 external/njs_zlib_module.c --- a/external/njs_zlib_module.cMon Apr 22 17:51:45 2024 -0700 +++ b/external/njs_zlib_module.cMon Apr 22 17:52:06 2024 -0700 @@ -463,7 +463,7 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v njs_chb_init(, njs_vm_memory_pool(vm)); -while (stream.avail_in > 0) { +while (rc != Z_STREAM_END) { stream.next_out = njs_chb_reserve(, chunk_size); if (njs_slow_path(stream.next_out == NULL)) { njs_vm_memory_error(vm); diff -r be271e8d0b3b -r d640adf691a7 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Apr 22 17:51:45 2024 -0700 +++ b/src/test/njs_unit_test.c Mon Apr 22 17:52:06 2024 -0700 @@ -22352,6 +22352,13 @@ static njs_unit_test_t njs_zlib_test[] njs_str("eJwLd/R2BAAC+gEl,eJw7t/HcpnObAQ/sBIE=") }, { njs_str("const zlib = require('zlib');" + "const buf = 'αβγ'.repeat(56);" + "const enc = zlib.deflateRawSync(buf, {chunkSize:64}).toString('base64');" + "const dec = zlib.inflateRawSync(Buffer.from(enc, 'base64')).toString();" + "buf == dec"), + njs_str("true") }, + +{ njs_str("const zlib = require('zlib');" "['WAKA'.repeat(1024), 'αβγ'.repeat(1024)]" ".map(v => [v, zlib.deflateRawSync(v).toString('base64')])" ".every(pair => pair[0] == zlib.inflateRawSync(Buffer.from(pair[1], 'base64')).toString())"), ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Modules: improved checking for duplicate js_set variables.
details: https://hg.nginx.org/njs/rev/be271e8d0b3b branches: changeset: 2318:be271e8d0b3b user: Dmitry Volyntsev date: Mon Apr 22 17:51:45 2024 -0700 description: Modules: improved checking for duplicate js_set variables. Since 6fb1aca4eeaf (0.8.4) the identical js_set variables introduced as a part of an include file that is shared amongst multiple vhosts are rejected during configuration parsing. The patch ignores duplicate js_set variables when they refer to the same JS function. This fixes #705 issue on Github. diffstat: nginx/ngx_http_js_module.c | 15 ++-- nginx/ngx_stream_js_module.c | 15 ++-- nginx/t/js_dup_set.t | 74 nginx/t/stream_js_dup_set.t | 72 ++ 4 files changed, 168 insertions(+), 8 deletions(-) diffs (218 lines): diff -r b73f99c7bc54 -r be271e8d0b3b nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cMon Apr 22 17:51:24 2024 -0700 +++ b/nginx/ngx_http_js_module.cMon Apr 22 17:51:45 2024 -0700 @@ -4732,7 +4732,7 @@ invalid: static char * ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { -ngx_str_t*value, *fname; +ngx_str_t*value, *fname, *prev; ngx_http_variable_t *v; value = cf->args->elts; @@ -4759,9 +4759,16 @@ ngx_http_js_set(ngx_conf_t *cf, ngx_comm *fname = value[2]; if (v->get_handler == ngx_http_js_variable_set) { -ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "variable \"%V\" is already declared", [1]); -return NGX_CONF_ERROR; +prev = (ngx_str_t *) v->data; + +if (fname->len != prev->len +|| ngx_strncmp(fname->data, prev->data, fname->len) != 0) +{ +ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is redeclared with " + "different function name", [1]); +return NGX_CONF_ERROR; +} } v->get_handler = ngx_http_js_variable_set; diff -r b73f99c7bc54 -r be271e8d0b3b nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Apr 22 17:51:24 2024 -0700 +++ b/nginx/ngx_stream_js_module.c Mon Apr 22 17:51:45 2024 -0700 @@ -2191,7 +2191,7 @@ invalid: static char * ngx_stream_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { -ngx_str_t *value, *fname; +ngx_str_t *value, *fname, *prev; ngx_stream_variable_t *v; value = cf->args->elts; @@ -2218,9 +2218,16 @@ ngx_stream_js_set(ngx_conf_t *cf, ngx_co *fname = value[2]; if (v->get_handler == ngx_stream_js_variable_set) { -ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "variable \"%V\" is already declared", [1]); -return NGX_CONF_ERROR; +prev = (ngx_str_t *) v->data; + +if (fname->len != prev->len +|| ngx_strncmp(fname->data, prev->data, fname->len) != 0) +{ +ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is redeclared with " + "different function name", [1]); +return NGX_CONF_ERROR; +} } v->get_handler = ngx_stream_js_variable_set; diff -r b73f99c7bc54 -r be271e8d0b3b nginx/t/js_dup_set.t --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/nginx/t/js_dup_set.t Mon Apr 22 17:51:45 2024 -0700 @@ -0,0 +1,74 @@ +#!/usr/bin/perl + +# (C) Dmitry Volyntsev +# (C) Nginx, Inc. + +# Tests for http njs module, duplicate identical js_set directives. + +### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; + +### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/http/) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { +%%TEST_GLOBALS_HTTP%% + +js_import test.js; + +server { +listen 127.0.0.1:8080; +server_name localhost; + +location /set1 { +js_set $test test.foo; +return 200 set1:$test; +} + +location /set2 { +js_set $test test.foo; +return 200 set2:$test; +} +} +} + +EOF + +$t->write_file('test.js', <try_run('no njs')->plan(2); + +### + +like(http_get('/set1'), qr/set1:42/, '/set1 location'); +like(http_get('/set2'), qr/set2:42/, '/set2 location'); + +#
[njs] Version bump.
details: https://hg.nginx.org/njs/rev/b73f99c7bc54 branches: changeset: 2317:b73f99c7bc54 user: Dmitry Volyntsev date: Mon Apr 22 17:51:24 2024 -0700 description: Version bump. diffstat: src/njs.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 7133f0400019 -r b73f99c7bc54 src/njs.h --- a/src/njs.h Mon Apr 15 16:44:33 2024 -0700 +++ b/src/njs.h Mon Apr 22 17:51:24 2024 -0700 @@ -11,8 +11,8 @@ #include -#define NJS_VERSION "0.8.4" -#define NJS_VERSION_NUMBER 0x000804 +#define NJS_VERSION "0.8.5" +#define NJS_VERSION_NUMBER 0x000805 #include ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
njs-0.8.4
Hello, I'm glad to announce a new release of NGINX JavaScript module (njs). This release introduced the initial QuickJS engine support in CLI as well as regular bugfixes. Notable new features: - QuickJS in njs CLI: : $ ./configure --cc-opt="-I/path/to/quickjs -L/path/to/quickjs" && make njs : $ ./build/njs -n QuickJS : : >> new Map() : [object Map] Learn more about njs: - Overview and introduction: https://nginx.org/en/docs/njs/ - NGINX JavaScript in Your Web Server Configuration: https://youtu.be/Jc_L6UffFOs - Extending NGINX with Custom Code: https://youtu.be/0CVhq4AUU7M - Using node modules with njs: https://nginx.org/en/docs/njs/node_modules.html - Writing njs code using TypeScript definition files: https://nginx.org/en/docs/njs/typescript.html Feel free to try it and give us feedback on: - Github: https://github.com/nginx/njs/issues - Mailing list: https://mailman.nginx.org/mailman/listinfo/nginx-devel Additional examples and howtos can be found here: - Github: https://github.com/nginx/njs-examples Changes with njs 0.8.4 16 Apr 2024 nginx modules: *) Feature: allowing to set Server header for outgoing headers. *) Improvement: validating URI and args arguments in r.subrequest(). *) Improvement: checking for duplicate js_set variables. *) Bugfix: fixed clear() method of a shared dictionary without timeout introduced in 0.8.3. *) Bugfix: fixed r.send() with Buffer argument. Core: *) Feature: added QuickJS engine support in CLI. *) Bugfix: fixed atob() with non-padded base64 strings. ___ nginx mailing list nginx@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx
[nginx-announce] njs-0.8.4
Hello, I'm glad to announce a new release of NGINX JavaScript module (njs). This release introduced the initial QuickJS engine support in CLI as well as regular bugfixes. Notable new features: - QuickJS in njs CLI: : $ ./configure --cc-opt="-I/path/to/quickjs -L/path/to/quickjs" && make njs : $ ./build/njs -n QuickJS : : >> new Map() : [object Map] Learn more about njs: - Overview and introduction: https://nginx.org/en/docs/njs/ - NGINX JavaScript in Your Web Server Configuration: https://youtu.be/Jc_L6UffFOs - Extending NGINX with Custom Code: https://youtu.be/0CVhq4AUU7M - Using node modules with njs: https://nginx.org/en/docs/njs/node_modules.html - Writing njs code using TypeScript definition files: https://nginx.org/en/docs/njs/typescript.html Feel free to try it and give us feedback on: - Github: https://github.com/nginx/njs/issues - Mailing list: https://mailman.nginx.org/mailman/listinfo/nginx-devel Additional examples and howtos can be found here: - Github: https://github.com/nginx/njs-examples Changes with njs 0.8.4 16 Apr 2024 nginx modules: *) Feature: allowing to set Server header for outgoing headers. *) Improvement: validating URI and args arguments in r.subrequest(). *) Improvement: checking for duplicate js_set variables. *) Bugfix: fixed clear() method of a shared dictionary without timeout introduced in 0.8.3. *) Bugfix: fixed r.send() with Buffer argument. Core: *) Feature: added QuickJS engine support in CLI. *) Bugfix: fixed atob() with non-padded base64 strings. ___ nginx-announce mailing list nginx-announce@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-announce
[njs] Added tag 0.8.4 for changeset 11d956c1577c
details: https://hg.nginx.org/njs/rev/7133f0400019 branches: changeset: 2316:7133f0400019 user: Dmitry Volyntsev date: Mon Apr 15 16:44:33 2024 -0700 description: Added tag 0.8.4 for changeset 11d956c1577c diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 11d956c1577c -r 7133f0400019 .hgtags --- a/.hgtags Mon Apr 15 16:40:21 2024 -0700 +++ b/.hgtags Mon Apr 15 16:44:33 2024 -0700 @@ -66,3 +66,4 @@ 0ed1952588ab1e0e1c18425fe7923b2b76f38a65 a52b49f9afcf410597dc6657ad39ae3dbbfeec56 0.8.1 45f81882c780a12e56be519cd3106c4fe5567a64 0.8.2 3aba7ee620807ad10bc34bff3677350fa8a3c3b2 0.8.3 +11d956c1577c91037a2c122d4a9d818a9733562d 0.8.4 ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Version 0.8.4.
details: https://hg.nginx.org/njs/rev/11d956c1577c branches: changeset: 2315:11d956c1577c user: Dmitry Volyntsev date: Mon Apr 15 16:40:21 2024 -0700 description: Version 0.8.4. diffstat: CHANGES | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) diffs (28 lines): diff -r adaeb3c3f59a -r 11d956c1577c CHANGES --- a/CHANGES Mon Apr 08 22:47:28 2024 -0700 +++ b/CHANGES Mon Apr 15 16:40:21 2024 -0700 @@ -1,3 +1,24 @@ +Changes with njs 0.8.4 16 Apr 2024 + +nginx modules: + +*) Feature: allowing to set Server header for outgoing headers. + +*) Improvement: validating URI and args arguments in r.subrequest(). + +*) Improvement: checking for duplicate js_set variables. + +*) Bugfix: fixed clear() method of a shared dictionary without + timeout introduced in 0.8.3. + +*) Bugfix: fixed r.send() with Buffer argument. + +Core: + +*) Feature: added QuickJS engine support in CLI. + +*) Bugfix: fixed atob() with non-padded base64 strings. + Changes with njs 0.8.3 07 Feb 2024 nginx modules: ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] HTTP: fixed r.send() with Buffer argument.
details: https://hg.nginx.org/njs/rev/adaeb3c3f59a branches: changeset: 2314:adaeb3c3f59a user: Dmitry Volyntsev date: Mon Apr 08 22:47:28 2024 -0700 description: HTTP: fixed r.send() with Buffer argument. Previously, only string value type was accepted. This closes #701 issue on Github. diffstat: nginx/ngx_http_js_module.c | 69 ++ nginx/t/js.t | 22 +- src/njs.h | 2 - src/njs_vm.c | 41 --- 4 files changed, 47 insertions(+), 87 deletions(-) diffs (208 lines): diff -r 6fb1aca4eeaf -r adaeb3c3f59a nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cMon Apr 08 22:47:24 2024 -0700 +++ b/nginx/ngx_http_js_module.cMon Apr 08 22:47:28 2024 -0700 @@ -2199,10 +2199,8 @@ static njs_int_t ngx_http_js_ext_send(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { -njs_int_tret; njs_str_ts; ngx_buf_t *b; -uintptr_tnext; ngx_uint_t n; ngx_chain_t *out, *cl, **ll; ngx_http_js_ctx_t *ctx; @@ -2226,47 +2224,34 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v ll = for (n = 1; n < nargs; n++) { -next = 0; - -for ( ;; ) { -ret = njs_vm_value_string_copy(vm, , njs_argument(args, n), - ); - -if (ret == NJS_DECLINED) { -break; -} - -if (ret == NJS_ERROR) { -return NJS_ERROR; -} - -if (s.length == 0) { -continue; -} - -/* TODO: njs_value_release(vm, value) in buf completion */ - -b = ngx_calloc_buf(r->pool); -if (b == NULL) { -return NJS_ERROR; -} - -b->start = s.start; -b->pos = b->start; -b->end = s.start + s.length; -b->last = b->end; -b->memory = 1; - -cl = ngx_alloc_chain_link(r->pool); -if (cl == NULL) { -return NJS_ERROR; -} - -cl->buf = b; - -*ll = cl; -ll = >next; +if (ngx_js_string(vm, njs_argument(args, n), ) != NGX_OK) { +return NJS_ERROR; +} + +if (s.length == 0) { +continue; +} + +b = ngx_calloc_buf(r->pool); +if (b == NULL) { +return NJS_ERROR; } + +b->start = s.start; +b->pos = b->start; +b->end = s.start + s.length; +b->last = b->end; +b->memory = 1; + +cl = ngx_alloc_chain_link(r->pool); +if (cl == NULL) { +return NJS_ERROR; +} + +cl->buf = b; + +*ll = cl; +ll = >next; } *ll = NULL; diff -r 6fb1aca4eeaf -r adaeb3c3f59a nginx/t/js.t --- a/nginx/t/js.t Mon Apr 08 22:47:24 2024 -0700 +++ b/nginx/t/js.t Mon Apr 08 22:47:28 2024 -0700 @@ -112,6 +112,10 @@ http { js_content test.send; } +location /send_buffer { +js_content test.send_buffer; +} + location /return_method { js_content test.return_method; } @@ -219,6 +223,13 @@ EOF r.finish(); } +function send_buffer(r) { +r.status = 200; +r.sendHeader(); +r.send(Buffer.from("send_buffer")); +r.finish(); +} + function return_method(r) { r.return(Number(r.args.c), r.args.t); } @@ -265,11 +276,11 @@ EOF variable, global_obj, status, request_body, internal, request_body_cache, send, return_method, sub_internal, type, log, buffer_variable, except, content_except, -content_empty}; +content_empty, send_buffer}; EOF -$t->try_run('no njs available')->plan(28); +$t->try_run('no njs available')->plan(29); ### @@ -289,6 +300,13 @@ like(http_post_big('/body'), qr/200.*^(1 like(http_get('/send?foo=12345=11=bar==z'), qr/n=foo, v=12 n=foo-2, v=ba n=foo-3, v=z/, 'r.send'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.4'); + +like(http_get('/send_buffer'), qr/send_buffer/, 'r.send accepts buffer'); + +} + like(http_get('/return_method?c=200'), qr/200 OK.*\x0d\x0a?\x0d\x0a?$/s, 'return code'); like(http_get('/return_method?c=200=SEE-THIS'), qr/200 OK.*^SEE-THIS$/ms, diff -r 6fb1aca4eeaf -r adaeb3c3f59a src/njs.h --- a/src/njs.h Mon Apr 08 22:47:24 2024 -0700 +++ b/src/njs.h Mon Apr 08 22:47:28 2024 -0700 @@ -412,8 +412,6 @@ NJS_EXPORT njs_int_t njs_vm_value_string njs_value_t *value
[njs] Modules: checking for duplicate js_set variables.
details: https://hg.nginx.org/njs/rev/6fb1aca4eeaf branches: changeset: 2313:6fb1aca4eeaf user: Dmitry Volyntsev date: Mon Apr 08 22:47:24 2024 -0700 description: Modules: checking for duplicate js_set variables. This closes #700 issue on Github. diffstat: nginx/ngx_http_js_module.c | 6 ++ nginx/ngx_stream_js_module.c | 6 ++ 2 files changed, 12 insertions(+), 0 deletions(-) diffs (32 lines): diff -r 1c8b6b9bc06c -r 6fb1aca4eeaf nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cThu Apr 04 16:07:53 2024 -0700 +++ b/nginx/ngx_http_js_module.cMon Apr 08 22:47:24 2024 -0700 @@ -4773,6 +4773,12 @@ ngx_http_js_set(ngx_conf_t *cf, ngx_comm *fname = value[2]; +if (v->get_handler == ngx_http_js_variable_set) { +ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is already declared", [1]); +return NGX_CONF_ERROR; +} + v->get_handler = ngx_http_js_variable_set; v->data = (uintptr_t) fname; diff -r 1c8b6b9bc06c -r 6fb1aca4eeaf nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Thu Apr 04 16:07:53 2024 -0700 +++ b/nginx/ngx_stream_js_module.c Mon Apr 08 22:47:24 2024 -0700 @@ -2217,6 +2217,12 @@ ngx_stream_js_set(ngx_conf_t *cf, ngx_co *fname = value[2]; +if (v->get_handler == ngx_stream_js_variable_set) { +ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is already declared", [1]); +return NGX_CONF_ERROR; +} + v->get_handler = ngx_stream_js_variable_set; v->data = (uintptr_t) fname; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Configure: added --with-quickjs option.
details: https://hg.nginx.org/njs/rev/1c8b6b9bc06c branches: changeset: 2312:1c8b6b9bc06c user: Dmitry Volyntsev date: Thu Apr 04 16:07:53 2024 -0700 description: Configure: added --with-quickjs option. diffstat: auto/help| 1 + auto/options | 6 -- auto/quickjs | 13 ++--- 3 files changed, 15 insertions(+), 5 deletions(-) diffs (81 lines): diff -r 834096122cef -r 1c8b6b9bc06c auto/help --- a/auto/help Thu Apr 04 16:07:46 2024 -0700 +++ b/auto/help Thu Apr 04 16:07:53 2024 -0700 @@ -48,4 +48,5 @@ default: "$NJS_LD_OPT" --no-zlib disables zlib discovery. When this option is enabled zlib dependant code is not built as a part of libnjs.a. + --with-quickjsrequires QuickJS engine. END diff -r 834096122cef -r 1c8b6b9bc06c auto/options --- a/auto/options Thu Apr 04 16:07:46 2024 -0700 +++ b/auto/options Thu Apr 04 16:07:53 2024 -0700 @@ -14,7 +14,8 @@ NJS_DEBUG_GENERATOR=NO NJS_ADDRESS_SANITIZER=NO NJS_ADDR2LINE=NO -NJS_QUICKJS=YES +NJS_QUICKJS=NO +NJS_TRY_QUICKJS=YES NJS_OPENSSL=YES NJS_LIBXML2=YES NJS_ZLIB=YES @@ -48,7 +49,7 @@ do --debug-opcode=*)NJS_DEBUG_OPCODE="$value" ;; --debug-generator=*) NJS_DEBUG_GENERATOR="$value";; ---no-quickjs)NJS_QUICKJS=NO ;; +--no-quickjs)NJS_TRY_QUICKJS=NO ;; --no-openssl)NJS_OPENSSL=NO ;; --no-libxml2)NJS_LIBXML2=NO ;; --no-zlib) NJS_ZLIB=NO ;; @@ -57,6 +58,7 @@ do --no-pcre2) NJS_TRY_PCRE2=NO;; --no-goto) NJS_TRY_GOTO=NO ;; +--with-quickjs) NJS_TRY_QUICKJS=YES; NJS_QUICKJS=YES ;; --help) . auto/help diff -r 834096122cef -r 1c8b6b9bc06c auto/quickjs --- a/auto/quickjs Thu Apr 04 16:07:46 2024 -0700 +++ b/auto/quickjs Thu Apr 04 16:07:53 2024 -0700 @@ -6,7 +6,7 @@ NJS_QUICKJS_LIB= NJS_HAVE_QUICKJS=NO -if [ $NJS_QUICKJS = YES ]; then +if [ $NJS_TRY_QUICKJS = YES ]; then njs_found=no njs_feature="QuickJS library -lquickjs.lto" @@ -40,7 +40,7 @@ if [ $NJS_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs.lto" njs_feature_incs="/usr/include/quickjs/" -njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs.lto -lm -ldl -lpthread" +njs_feature_libs="-L/usr/lib/quickjs/ -lquijs.lto -lm -ldl -lpthread" . auto/feature fi @@ -48,7 +48,7 @@ if [ $NJS_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs" njs_feature_incs="/usr/include/quickjs/" -njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs -lm -ldl -lpthread" +njs_feature_libs="-L/usr/lib/quickjs/ -lquijs -lm -ldl -lpthread" . auto/feature fi @@ -60,4 +60,11 @@ if [ $NJS_QUICKJS = YES ]; then NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $njs_feature_libs" fi +if [ $NJS_QUICKJS = YES -a $njs_found = no ]; then +echo +echo $0: error: no QuickJS library found. +echo +exit 1; +fi + fi ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Configure: improved QuickJS discovery.
details: https://hg.nginx.org/njs/rev/834096122cef branches: changeset: 2311:834096122cef user: Dmitry Volyntsev date: Thu Apr 04 16:07:46 2024 -0700 description: Configure: improved QuickJS discovery. At the first try do not assume the exact library and includes location. diffstat: auto/quickjs | 16 1 files changed, 12 insertions(+), 4 deletions(-) diffs (43 lines): diff -r b83e2ae81937 -r 834096122cef auto/quickjs --- a/auto/quickjs Thu Apr 04 16:07:39 2024 -0700 +++ b/auto/quickjs Thu Apr 04 16:07:46 2024 -0700 @@ -9,11 +9,11 @@ NJS_HAVE_QUICKJS=NO if [ $NJS_QUICKJS = YES ]; then njs_found=no -njs_feature="QuickJS library" +njs_feature="QuickJS library -lquickjs.lto" njs_feature_name=NJS_HAVE_QUICKJS njs_feature_run=yes njs_feature_incs= -njs_feature_libs="" +njs_feature_libs="-lquickjs.lto -lm -ldl -lpthread" njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) #pragma GCC diagnostic push #pragma GCC diagnostic ignored \"-Wcast-function-type\" @@ -31,7 +31,14 @@ if [ $NJS_QUICKJS = YES ]; then . auto/feature if [ $njs_found = no ]; then -njs_feature="QuickJS library -lquickjs.lto" +njs_feature="QuickJS library -lquickjs" +njs_feature_libs="-lquickjs -lm -ldl -lpthread" + +. auto/feature +fi + +if [ $njs_found = no ]; then +njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs.lto" njs_feature_incs="/usr/include/quickjs/" njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs.lto -lm -ldl -lpthread" @@ -39,7 +46,8 @@ if [ $NJS_QUICKJS = YES ]; then fi if [ $njs_found = no ]; then -njs_feature="QuickJS library -lquickjs" +njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs" +njs_feature_incs="/usr/include/quickjs/" njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs -lm -ldl -lpthread" . auto/feature ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Configure: added --no-quickjs description in configure --help.
details: https://hg.nginx.org/njs/rev/b83e2ae81937 branches: changeset: 2310:b83e2ae81937 user: Dmitry Volyntsev date: Thu Apr 04 16:07:39 2024 -0700 description: Configure: added --no-quickjs description in configure --help. Forgotten in cb3e068a511c. diffstat: auto/help | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r 3a5b8b59cce9 -r b83e2ae81937 auto/help --- a/auto/help Thu Apr 04 16:07:37 2024 -0700 +++ b/auto/help Thu Apr 04 16:07:39 2024 -0700 @@ -44,6 +44,7 @@ default: "$NJS_LD_OPT" --no-pcre2disables PCRE2 discovery for RegExp backend. When this option is enabled only PCRE library is discovered. + --no-quickjs disables QuickJS engine discovery. --no-zlib disables zlib discovery. When this option is enabled zlib dependant code is not built as a part of libnjs.a. ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Configure: sorted options alphabetically in configure --help.
details: https://hg.nginx.org/njs/rev/3a5b8b59cce9 branches: changeset: 2309:3a5b8b59cce9 user: Dmitry Volyntsev date: Thu Apr 04 16:07:37 2024 -0700 description: Configure: sorted options alphabetically in configure --help. diffstat: auto/help | 68 +++--- 1 files changed, 30 insertions(+), 38 deletions(-) diffs (85 lines): diff -r 2d6d9d1e8b8f -r 3a5b8b59cce9 auto/help --- a/auto/help Tue Apr 02 08:52:56 2024 -0700 +++ b/auto/help Thu Apr 04 16:07:37 2024 -0700 @@ -7,46 +7,15 @@ cat << END ./configure options: - --cc=FILE set C compiler filename, default: "$CC" - --cc-opt=OPTIONS set additional C compiler options, \ -default: "$NJS_CC_OPT" - --ld-opt=OPTIONS set additional linker options, \ -default: "$NJS_LD_OPT" - --ar=FILE set static linking program, default: "$AR" - - --build-dir=DIR set build directory, default: "$NJS_BUILD_DIR" - - --no-pcre disables PCRE/PCRE2 discovery for RegExp -backend. This flag allows to build PCRE/PCRE2 -outside of libnjs.a. When this option is enabled -functions described in njs_regex.h are not built. -Instead this functions are expected to be provided -while linking. - - --no-pcre2disables PCRE2 discovery for RegExp backend. -When this option is enabled only PCRE library -is discovered. - - --no-goto disables computed goto discovery. -When this option is enabled 'switch' statement -will be always used in instead of computed goto. - - --no-openssl disables OpenSSL discovery. When this option is -enabled OpenSSL dependant code is not built as a -part of libnjs.a. - - --no-libxml2 disabled libxml2 discovery. When this option is -enabled libxml2 dependant code is not built as a -part of libnjs.a. - - --no-zlib disabled zlib discovery. When this option is -enabled zlib dependant code is not built as a -part of libnjs.a. - + --addr2line=YES enables native function symbolization, \ +default: "$NJS_ADDR2LINE" --address-sanitizer=YES enables build with address sanitizer, \ default: "$NJS_ADDRESS_SANITIZER" - --addr2line=YES enables native function symbolization, \ -default: "$NJS_ADDR2LINE" + --ar=FILE sets static linking program, default: "$AR" + --build-dir=DIR sets build directory, default: "$NJS_BUILD_DIR" + --cc=FILE sets C compiler filename, default: "$CC" + --cc-opt=OPTIONS sets additional C compiler options, \ +default: "$NJS_CC_OPT" --debug=YES enables additional runtime checks, \ default: "$NJS_DEBUG" --debug-memory=YESenables memory alloc debug, \ @@ -55,4 +24,27 @@ default: "$NJS_DEBUG_MEMORY" default: "$NJS_DEBUG_OPCODE" --debug-generator=YES enables generator debug, \ default: "$NJS_DEBUG_GENERATOR" + --ld-opt=OPTIONS sets additional linker options, \ +default: "$NJS_LD_OPT" + --no-goto disables computed goto discovery. +When this option is enabled 'switch' statement +will be always used in instead of computed goto. + --no-libxml2 disables libxml2 discovery. When this option is +enabled libxml2 dependant code is not built as a +part of libnjs.a. + --no-openssl disables OpenSSL discovery. When this option is +enabled OpenSSL dependant code is not built as a +part of libnjs.a. + --no-pcre disables PCRE/PCRE2 discovery for RegExp +backend. This flag allows to build PCRE/PCRE2 +outside of libnjs.a. When this option is enabled +functions described in njs_regex.h are not built. +Instead this functions are expected to be provided +while linking. + --no-pcre2disables PCRE2 discovery for RegExp backend. +When this option is enabled only PCRE library +is discovered. + --no-zlib disables zlib discovery. When this option is +enabled zlib dep
[njs] HTTP: validating URI and args arguments in r.subrequest().
details: https://hg.nginx.org/njs/rev/2d6d9d1e8b8f branches: changeset: 2308:2d6d9d1e8b8f user: Dmitry Volyntsev date: Tue Apr 02 08:52:56 2024 -0700 description: HTTP: validating URI and args arguments in r.subrequest(). diffstat: nginx/ngx_http_js_module.c | 37 + nginx/t/js_subrequests.t | 40 ++-- 2 files changed, 75 insertions(+), 2 deletions(-) diffs (138 lines): diff -r 17af51d42ad9 -r 2d6d9d1e8b8f nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cMon Apr 01 23:13:25 2024 -0700 +++ b/nginx/ngx_http_js_module.cTue Apr 02 08:52:56 2024 -0700 @@ -305,6 +305,9 @@ static char *ngx_http_js_merge_loc_conf( static ngx_ssl_t *ngx_http_js_ssl(njs_vm_t *vm, ngx_http_request_t *r); static ngx_flag_t ngx_http_js_ssl_verify(njs_vm_t *vm, ngx_http_request_t *r); +static ngx_int_t ngx_http_js_parse_unsafe_uri(ngx_http_request_t *r, +njs_str_t *uri, njs_str_t *args); + #if (NGX_HTTP_SSL) static ngx_conf_bitmask_t ngx_http_js_ssl_protocols[] = { @@ -3272,6 +3275,11 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } } +if (ngx_http_js_parse_unsafe_uri(r, _arg, _arg) != NGX_OK) { +njs_vm_error(vm, "unsafe uri"); +return NJS_ERROR; +} + arg = njs_arg(args, nargs, 3); if (callback == NULL && !njs_value_is_undefined(arg)) { @@ -4979,3 +4987,32 @@ ngx_http_js_ssl_verify(njs_vm_t *vm, ngx return 0; #endif } + + +static ngx_int_t +ngx_http_js_parse_unsafe_uri(ngx_http_request_t *r, njs_str_t *uri, +njs_str_t *args) +{ +ngx_str_t uri_arg, args_arg; +ngx_uint_t flags; + +flags = NGX_HTTP_LOG_UNSAFE; + +uri_arg.data = uri->start; +uri_arg.len = uri->length; + +args_arg.data = args->start; +args_arg.len = args->length; + +if (ngx_http_parse_unsafe_uri(r, _arg, _arg, ) != NGX_OK) { +return NGX_ERROR; +} + +uri->start = uri_arg.data; +uri->length = uri_arg.len; + +args->start = args_arg.data; +args->length = args_arg.len; + +return NGX_OK; +} diff -r 17af51d42ad9 -r 2d6d9d1e8b8f nginx/t/js_subrequests.t --- a/nginx/t/js_subrequests.t Mon Apr 01 23:13:25 2024 -0700 +++ b/nginx/t/js_subrequests.t Tue Apr 02 08:52:56 2024 -0700 @@ -148,6 +148,10 @@ http { js_content test.sr_unavail_pr; } +location /sr_unsafe { +js_content test.sr_unsafe; +} + location /sr_broken { js_content test.sr_broken; } @@ -385,6 +389,11 @@ EOF subrequest_fn_pr(req, ['/unavail'], ['uri', 'status']); } +function sr_unsafe(r) { +r.subrequest('../dir'); +r.return(200); +} + function sr_broken(r) { r.subrequest('/daemon/unfinished', reply => { r.return(200, JSON.stringify({code:reply.status})); @@ -498,13 +507,14 @@ EOF sr_unavail_pr, sr_broken, sr_too_large, sr_in_sr, sr_js_in_subrequest, sr_js_in_subrequest_pr, js_sub, sr_in_sr_callback, sr_out_of_order, sr_except_not_a_func, -sr_uri_except, sr_except_failed_to_convert_options_arg}; +sr_uri_except, sr_except_failed_to_convert_options_arg, +sr_unsafe}; EOF $t->write_file('t', '["SEE-THIS"]'); -$t->try_run('no njs available')->plan(32); +$t->try_run('no njs available')->plan(33); $t->run_daemon(\_daemon); ### @@ -558,6 +568,13 @@ is(get_json('/sr_in_sr_callback'), '{"e":"subrequest can only be created for the primary request"}', 'subrequest for non-primary request'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.4'); + +like(http_get('/sr_unsafe'), qr/500/s, 'unsafe subrequest uri'); + +} + $t->stop(); ok(index($t->read_file('error.log'), 'callback is not a function') > 0, @@ -634,3 +651,22 @@ sub http_daemon { } ### + +sub has_version { + my $need = shift; + + http_get('/njs') =~ /^([.0-9]+)$/m; + + my @v = split(/\./, $1); + my ($n, $v); + + for $n (split(/\./, $need)) { + $v = shift @v || 0; + return 0 if $n > $v; + return 1 if $v > $n; + } + + return 1; +} + +### ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Tests: adapt stream_js.t to nginx changes.
details: https://hg.nginx.org/njs/rev/17af51d42ad9 branches: changeset: 2307:17af51d42ad9 user: Dmitry Volyntsev date: Mon Apr 01 23:13:25 2024 -0700 description: Tests: adapt stream_js.t to nginx changes. Make the test more robust against changes in nginx, specifically cf890df37bb6 (Stream: socket peek in preread phase). The filter callbacks may be called multiple times by nginx and the exact number is not specified. The new test avoids relying on the exact number of calls from nginx. diffstat: nginx/t/stream_js.t | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diffs (57 lines): diff -r 454d9c032c60 -r 17af51d42ad9 nginx/t/stream_js.t --- a/nginx/t/stream_js.t Mon Apr 01 23:13:24 2024 -0700 +++ b/nginx/t/stream_js.t Mon Apr 01 23:13:25 2024 -0700 @@ -227,9 +227,10 @@ EOF } var res = ''; +var step = (v) => { if (!res || res[res.length - 1] != v) res += v }; function access_step(s) { -res += '1'; +step(1); setTimeout(function() { if (s.remoteAddress.match('127.0.0.1')) { @@ -240,8 +241,8 @@ EOF function preread_step(s) { s.on('upload', function (data) { -res += '2'; -if (res.length >= 3) { +step(2); +if (data.length > 0) { s.done(); } }); @@ -249,18 +250,18 @@ EOF function filter_step(s) { s.on('upload', function(data, flags) { +step(3); s.send(data); -res += '3'; }); s.on('download', function(data, flags) { if (!flags.last) { -res += '4'; +step(4); s.send(data); } else { -res += '5'; +step(5); s.send(res, {last:1}); s.off('download'); } @@ -409,7 +410,7 @@ is(stream('127.0.0.1:' . port(8082))->re is(stream('127.0.0.1:' . port(8083))->read(), '', 'stream js unknown function'); is(stream('127.0.0.1:' . port(8084))->read(), 'sess_unk=undefined', 's.unk'); -is(stream('127.0.0.1:' . port(8086))->io('0'), '0122345', +is(stream('127.0.0.1:' . port(8086))->io('0'), '012345', 'async handlers order'); is(stream('127.0.0.1:' . port(8087))->io('#'), 'OK', 'access_undecided'); is(stream('127.0.0.1:' . port(8088))->io('#'), 'OK', 'access_allow'); ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Tests: adapt stream_js_preload_object.t to nginx changes.
details: https://hg.nginx.org/njs/rev/454d9c032c60 branches: changeset: 2306:454d9c032c60 user: Dmitry Volyntsev date: Mon Apr 01 23:13:24 2024 -0700 description: Tests: adapt stream_js_preload_object.t to nginx changes. Make the test more robust against changes in nginx, specifically cf890df37bb6 (Stream: socket peek in preread phase). The filter callbacks may be called multiple times by nginx and the exact number is not specified. The new test avoids relying on the exact number of calls from nginx. diffstat: nginx/t/stream_js_preload_object.t | 21 ++--- 1 files changed, 10 insertions(+), 11 deletions(-) diffs (56 lines): diff -r 498b2387ef04 -r 454d9c032c60 nginx/t/stream_js_preload_object.t --- a/nginx/t/stream_js_preload_object.tMon Apr 01 23:13:23 2024 -0700 +++ b/nginx/t/stream_js_preload_object.tMon Apr 01 23:13:24 2024 -0700 @@ -66,16 +66,17 @@ EOF $t->write_file('lib.js', <= 3) { +pup = g1.b[1]; +if (data.length > 0) { s.done(); } }); @@ -83,18 +84,16 @@ EOF function filter(s) { s.on('upload', function(data, flags) { +fup = g1.c.prop[0].a; s.send(data); -res += g1.c.prop[0].a; }); s.on('download', function(data, flags) { -if (!flags.last) { -res += g1.b[3]; -s.send(data); +fdown = g1.b[3]; +s.send(data); -} else { -res += g1.b[4]; -s.send(res, {last:1}); +if (flags.last) { +s.send(`\${acc}\${pup}\${fup}\${fdown}`, flags); s.off('download'); } }); @@ -117,6 +116,6 @@ EOF ### is(stream('127.0.0.1:' . port(8081))->read(), 'element', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); +is(stream('127.0.0.1:' . port(8082))->io('0'), 'x1234', 'filter chain'); ### ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Tests: simplified stream_js_import2.t.
details: https://hg.nginx.org/njs/rev/498b2387ef04 branches: changeset: 2305:498b2387ef04 user: Dmitry Volyntsev date: Mon Apr 01 23:13:23 2024 -0700 description: Tests: simplified stream_js_import2.t. The test should only verify js_import directive in server context according to its description. diffstat: nginx/t/stream_js_import2.t | 59 + 1 files changed, 1 insertions(+), 58 deletions(-) diffs (81 lines): diff -r e16e93f43303 -r 498b2387ef04 nginx/t/stream_js_import2.t --- a/nginx/t/stream_js_import2.t Mon Apr 01 23:13:21 2024 -0700 +++ b/nginx/t/stream_js_import2.t Mon Apr 01 23:13:23 2024 -0700 @@ -42,76 +42,19 @@ stream { js_set $test foo.bar.p; return $test; } - -server { -listen 127.0.0.1:8082; - -js_import lib.js; - -js_access lib.access; -js_preread lib.preread; -js_filter lib.filter; -proxy_pass 127.0.0.1:8083; -} - -server { -listen 127.0.0.1:8083; -return "x"; -} } EOF -$t->write_file('lib.js', <= 3) { -s.done(); -} -}); -} - -function filter(s) { -s.on('upload', function(data, flags) { -s.send(data); -res += '3'; -}); - -s.on('download', function(data, flags) { -if (!flags.last) { -res += '4'; -s.send(data); - -} else { -res += '5'; -s.send(res, {last:1}); -s.off('download'); -} -}); -} - -export default {access, preread, filter}; - -EOF - $t->write_file('main.js', <try_run('no njs available')->plan(2); +$t->try_run('no njs available')->plan(1); ### is(stream('127.0.0.1:' . port(8081))->read(), 'P-TEST', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); ### ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Tests: removed stream_js_import.t.
details: https://hg.nginx.org/njs/rev/e16e93f43303 branches: changeset: 2304:e16e93f43303 user: Dmitry Volyntsev date: Mon Apr 01 23:13:21 2024 -0700 description: Tests: removed stream_js_import.t. js_import is the only directive to load JS code since 0.7.1, so the test is redundant. diffstat: nginx/t/stream_js_import.t | 117 - 1 files changed, 0 insertions(+), 117 deletions(-) diffs (121 lines): diff -r f632fe16ba05 -r e16e93f43303 nginx/t/stream_js_import.t --- a/nginx/t/stream_js_import.tTue Mar 19 21:05:51 2024 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,117 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, js_import directive. - -### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { -%%TEST_GLOBALS_STREAM%% - -js_set $test foo.bar.p; - -js_import lib.js; -js_import foo from ./main.js; - -server { -listen 127.0.0.1:8081; -return $test; -} - -server { -listen 127.0.0.1:8082; -js_access lib.access; -js_preread lib.preread; -js_filter lib.filter; -proxy_pass 127.0.0.1:8083; -} - -server { -listen 127.0.0.1:8083; -return "x"; -} -} - -EOF - -$t->write_file('lib.js', <= 3) { -s.done(); -} -}); -} - -function filter(s) { -s.on('upload', function(data, flags) { -s.send(data); -res += '3'; -}); - -s.on('download', function(data, flags) { -if (!flags.last) { -res += '4'; -s.send(data); - -} else { -res += '5'; -s.send(res, {last:1}); -s.off('download'); -} -}); -} - -export default {access, preread, filter}; - -EOF - -$t->write_file('main.js', <try_run('no njs available')->plan(2); - -### - -is(stream('127.0.0.1:' . port(8081))->read(), 'P-TEST', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); - -### ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Modules: fixed clear() method of a shared dictionary without timeout.
details: https://hg.nginx.org/njs/rev/f632fe16ba05 branches: changeset: 2303:f632fe16ba05 user: Dmitry Volyntsev date: Tue Mar 19 21:05:51 2024 -0700 description: Modules: fixed clear() method of a shared dictionary without timeout. Previously, the code did not unlock the rwlock when a dict was empty. The issue was introduced in 4a15613f4e8b (0.8.3). This closes issue #699 on Github. diffstat: nginx/ngx_js_shared_dict.c | 4 +++- nginx/t/js_shared_dict.t | 1 + 2 files changed, 4 insertions(+), 1 deletions(-) diffs (32 lines): diff -r 85313a068147 -r f632fe16ba05 nginx/ngx_js_shared_dict.c --- a/nginx/ngx_js_shared_dict.cMon Mar 18 22:24:57 2024 -0700 +++ b/nginx/ngx_js_shared_dict.cTue Mar 19 21:05:51 2024 -0700 @@ -479,7 +479,7 @@ njs_js_ext_shared_dict_clear(njs_vm_t *v rbtree = >sh->rbtree; if (rbtree->root == rbtree->sentinel) { -return NJS_OK; +goto done; } for (rn = ngx_rbtree_min(rbtree->root, rbtree->sentinel); @@ -494,6 +494,8 @@ njs_js_ext_shared_dict_clear(njs_vm_t *v } } +done: + ngx_rwlock_unlock(>sh->rwlock); njs_value_undefined_set(retval); diff -r 85313a068147 -r f632fe16ba05 nginx/t/js_shared_dict.t --- a/nginx/t/js_shared_dict.t Mon Mar 18 22:24:57 2024 -0700 +++ b/nginx/t/js_shared_dict.t Tue Mar 19 21:05:51 2024 -0700 @@ -266,6 +266,7 @@ EOF function set_clear(r) { var dict = ngx.shared.no_timeout; +dict.clear(); dict.set("test", "test value"); dict.set("test1", "test1 value"); dict.clear(); ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Shell: added completions for QuickJS engine.
details: https://hg.nginx.org/njs/rev/85313a068147 branches: changeset: 2302:85313a068147 user: Dmitry Volyntsev date: Mon Mar 18 22:24:57 2024 -0700 description: Shell: added completions for QuickJS engine. diffstat: external/njs_shell.c| 202 +++- test/shell_test.exp | 147 ++ test/shell_test_njs.exp | 148 --- 3 files changed, 345 insertions(+), 152 deletions(-) diffs (541 lines): diff -r fe94552843d7 -r 85313a068147 external/njs_shell.c --- a/external/njs_shell.c Mon Mar 18 22:15:48 2024 -0700 +++ b/external/njs_shell.c Mon Mar 18 22:24:57 2024 -0700 @@ -3106,6 +3106,203 @@ njs_engine_qjs_output(njs_engine_t *engi return NJS_OK; } + +static njs_arr_t * +njs_qjs_object_completions(njs_engine_t *engine, JSContext *ctx, +JSValueConst object, njs_str_t *expression) +{ +u_char *prefix; +size_t len, prefix_len; +JSValue prototype; +uint32_tk, n, length; +njs_int_t ret; +njs_arr_t *array; +njs_str_t *completion, key; +JSPropertyEnum *ptab; + +prefix = expression->start + expression->length; + +while (prefix > expression->start && *prefix != '.') { +prefix--; +} + +if (prefix != expression->start) { +prefix++; +} + +ptab = NULL; +key.start = NULL; +prefix_len = prefix - expression->start; +len = expression->length - prefix_len; + +array = njs_arr_create(engine->pool, 8, sizeof(njs_str_t)); +if (njs_slow_path(array == NULL)) { +goto fail; +} + +while (!JS_IsNull(object)) { +ret = JS_GetOwnPropertyNames(ctx, , , object, + JS_GPN_STRING_MASK); +if (ret < 0) { +goto fail; +} + +for (n = 0; n < length; n++) { +key.start = (u_char *) JS_AtomToCString(ctx, ptab[n].atom); +JS_FreeAtom(ctx, ptab[n].atom); +if (njs_slow_path(key.start == NULL)) { +goto fail; +} + +key.length = njs_strlen(key.start); + +if (len > key.length || njs_strncmp(key.start, prefix, len) != 0) { +goto next; +} + +for (k = 0; k < array->items; k++) { +completion = njs_arr_item(array, k); + +if ((completion->length - prefix_len - 1) == key.length +&& njs_strncmp(>start[prefix_len], + key.start, key.length) + == 0) +{ +goto next; +} +} + +completion = njs_arr_add(array); +if (njs_slow_path(completion == NULL)) { +goto fail; +} + +completion->length = prefix_len + key.length + 1; +completion->start = njs_mp_alloc(engine->pool, completion->length); +if (njs_slow_path(completion->start == NULL)) { +goto fail; +} + +njs_sprintf(completion->start, +completion->start + completion->length, +"%*s%V%Z", prefix_len, expression->start, ); + +next: + +JS_FreeCString(ctx, (const char *) key.start); +} + +js_free_rt(JS_GetRuntime(ctx), ptab); + +prototype = JS_GetPrototype(ctx, object); +if (JS_IsException(prototype)) { +goto fail; +} + +JS_FreeValue(ctx, object); +object = prototype; +} + +return array; + +fail: + +if (array != NULL) { +njs_arr_destroy(array); +} + +if (key.start != NULL) { +JS_FreeCString(ctx, (const char *) key.start); +} + +if (ptab != NULL) { +js_free_rt(JS_GetRuntime(ctx), ptab); +} + +JS_FreeValue(ctx, object); + +return NULL; +} + + +static njs_arr_t * +njs_engine_qjs_complete(njs_engine_t *engine, njs_str_t *expression) +{ +u_char *p, *start, *end; +JSAtom key; +JSValue value, retval; +njs_arr_t *arr; +JSContext *ctx; +njs_bool_t global; + +ctx = engine->u.qjs.ctx; + +p = expression->start; +end = p + expression->length; + +global = 1; +value = JS_GetGlobalObject(ctx); + +while (p < end && *p != '.') { p++; } + +if (p == end) { +goto done; +} + +p = expression->start; + +for ( ;; ) { + +start = (*p == '.' && p < end) ? ++p: p; + +if (p == end) { +break; +} + +while (p < end && *p != '.') { p++; } + +key = JS_NewAtomLen(ctx, (char *) start, p - start); +if (key == JS_ATOM_NULL) { +goto fail; +} + +retval = JS_GetPropert
[njs] Shell: completions are refactored and moved out of the core.
details: https://hg.nginx.org/njs/rev/fe94552843d7 branches: changeset: 2301:fe94552843d7 user: Dmitry Volyntsev date: Mon Mar 18 22:15:48 2024 -0700 description: Shell: completions are refactored and moved out of the core. diffstat: external/njs_shell.c| 275 +++- src/njs.h |2 - src/njs_builtin.c | 294 +--- test/shell_test_njs.exp | 26 +-- 4 files changed, 201 insertions(+), 396 deletions(-) diffs (737 lines): diff -r 1aa2bb15c966 -r fe94552843d7 external/njs_shell.c --- a/external/njs_shell.c Fri Mar 15 23:14:39 2024 -0700 +++ b/external/njs_shell.c Mon Mar 18 22:15:48 2024 -0700 @@ -83,15 +83,7 @@ typedef enum { typedef struct { size_t index; -size_t length; -njs_arr_t *completions; njs_arr_t *suffix_completions; -njs_rbtree_node_t *node; - -enum { - NJS_COMPLETION_SUFFIX = 0, - NJS_COMPLETION_GLOBAL -} phase; } njs_completion_t; @@ -157,7 +149,6 @@ struct njs_engine_s { njs_vm_t*vm; njs_opaque_value_t value; -njs_completion_tcompletion; } njs; #if (NJS_HAVE_QUICKJS) struct { @@ -174,9 +165,11 @@ struct njs_engine_s { njs_int_t (*process_events)(njs_engine_t *engine); njs_int_t (*destroy)(njs_engine_t *engine); njs_int_t (*output)(njs_engine_t *engine, njs_int_t ret); +njs_arr_t*(*complete)(njs_engine_t *engine, njs_str_t *ex); unsignedtype; njs_mp_t*pool; +njs_completion_tcompletion; }; typedef struct { @@ -1361,11 +1354,6 @@ njs_engine_njs_init(njs_engine_t *engine return NJS_ERROR; } -engine->u.njs.completion.completions = njs_vm_completions(vm, NULL); -if (engine->u.njs.completion.completions == NULL) { -return NJS_ERROR; -} - if (opts->unhandled_rejection) { njs_vm_set_rejection_tracker(vm, njs_rejection_tracker, njs_vm_external_ptr(vm)); @@ -1455,6 +1443,179 @@ njs_engine_njs_output(njs_engine_t *engi } +static njs_arr_t * +njs_object_completions(njs_vm_t *vm, njs_value_t *object, njs_str_t *expression) +{ +u_char *prefix; +size_t len, prefix_len; +int64_t k, n, length; +njs_int_t ret; +njs_arr_t *array; +njs_str_t *completion, key; +njs_value_t *keys; +njs_opaque_value_t *start, retval, prototype; + +prefix = expression->start + expression->length; + +while (prefix > expression->start && *prefix != '.') { +prefix--; +} + +if (prefix != expression->start) { +prefix++; +} + +prefix_len = prefix - expression->start; +len = expression->length - prefix_len; + +array = njs_arr_create(njs_vm_memory_pool(vm), 8, sizeof(njs_str_t)); +if (njs_slow_path(array == NULL)) { +goto fail; +} + +while (!njs_value_is_null(object)) { +keys = njs_vm_value_enumerate(vm, object, NJS_ENUM_KEYS + | NJS_ENUM_STRING, + njs_value_arg()); +if (njs_slow_path(keys == NULL)) { +goto fail; +} + +(void) njs_vm_array_length(vm, keys, ); + +start = (njs_opaque_value_t *) njs_vm_array_start(vm, keys); +if (start == NULL) { +goto fail; +} + + +for (n = 0; n < length; n++) { +ret = njs_vm_value_to_string(vm, , njs_value_arg(start)); +if (njs_slow_path(ret != NJS_OK)) { +goto fail; +} + +start++; + +if (len > key.length || njs_strncmp(key.start, prefix, len) != 0) { +continue; +} + +for (k = 0; k < array->items; k++) { +completion = njs_arr_item(array, k); + +if ((completion->length - prefix_len - 1) == key.length +&& njs_strncmp(>start[prefix_len], + key.start, key.length) + == 0) +{ +break; +} +} + +if (k != array->items) { +continue; +} + +completion = njs_arr_add(array); +if (njs_slow_path(completion == NULL)) { +goto fail; +} + +completion->length = prefix_len + key.length + 1; +completion->start = njs_mp_alloc(njs_vm_memory_pool(vm), + comp
[njs] Introduced njs_vm_value_enumerate() and njs_vm_value_own_enumerate().
details: https://hg.nginx.org/njs/rev/1aa2bb15c966 branches: changeset: 2300:1aa2bb15c966 user: Dmitry Volyntsev date: Fri Mar 15 23:14:39 2024 -0700 description: Introduced njs_vm_value_enumerate() and njs_vm_value_own_enumerate(). diffstat: src/njs.h | 16 ++ src/njs_value.h | 12 --- src/njs_vm.c| 88 + 3 files changed, 104 insertions(+), 12 deletions(-) diffs (153 lines): diff -r b0e42db5ca84 -r 1aa2bb15c966 src/njs.h --- a/src/njs.h Fri Mar 15 22:47:50 2024 -0700 +++ b/src/njs.h Fri Mar 15 23:14:39 2024 -0700 @@ -129,6 +129,18 @@ typedef enum { typedef enum { +#define njs_object_enum_kind(flags) (flags & 7) +NJS_ENUM_KEYS = 1, +NJS_ENUM_VALUES = 2, +NJS_ENUM_BOTH = 4, +#define njs_object_enum(flags) (flags & (NJS_ENUM_STRING | NJS_ENUM_SYMBOL)) +NJS_ENUM_STRING = 8, +NJS_ENUM_SYMBOL = 16, +NJS_ENUM_ENUMERABLE_ONLY = 32, +} njs_object_enum_t; + + +typedef enum { /* * Extern property type. */ @@ -497,6 +509,10 @@ NJS_EXPORT njs_int_t njs_vm_object_alloc ...); NJS_EXPORT njs_value_t *njs_vm_object_keys(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval); +NJS_EXPORT njs_value_t *njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value, +uint32_t flags, njs_value_t *retval); +NJS_EXPORT njs_value_t *njs_vm_value_own_enumerate(njs_vm_t *vm, +njs_value_t *value, uint32_t flags, njs_value_t *retval); NJS_EXPORT njs_value_t *njs_vm_object_prop(njs_vm_t *vm, njs_value_t *value, const njs_str_t *key, njs_opaque_value_t *retval); NJS_EXPORT njs_int_t njs_vm_object_prop_set(njs_vm_t *vm, njs_value_t *value, diff -r b0e42db5ca84 -r 1aa2bb15c966 src/njs_value.h --- a/src/njs_value.h Fri Mar 15 22:47:50 2024 -0700 +++ b/src/njs_value.h Fri Mar 15 23:14:39 2024 -0700 @@ -313,18 +313,6 @@ struct njs_object_type_init_s { typedef enum { -#define njs_object_enum_kind(flags) (flags & 7) -NJS_ENUM_KEYS = 1, -NJS_ENUM_VALUES = 2, -NJS_ENUM_BOTH = 4, -#define njs_object_enum(flags) (flags & (NJS_ENUM_STRING | NJS_ENUM_SYMBOL)) -NJS_ENUM_STRING = 8, -NJS_ENUM_SYMBOL = 16, -NJS_ENUM_ENUMERABLE_ONLY = 32, -} njs_object_enum_t; - - -typedef enum { NJS_PROPERTY = 0, NJS_ACCESSOR, NJS_PROPERTY_REF, diff -r b0e42db5ca84 -r 1aa2bb15c966 src/njs_vm.c --- a/src/njs_vm.c Fri Mar 15 22:47:50 2024 -0700 +++ b/src/njs_vm.c Fri Mar 15 23:14:39 2024 -0700 @@ -1114,6 +1114,94 @@ njs_vm_exception_string(njs_vm_t *vm, nj } +njs_value_t * +njs_vm_value_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags, +njs_value_t *retval) +{ +ssize_t length; +njs_int_tret; +njs_value_t *val; +njs_array_t *keys; +njs_rbtree_t *variables; +njs_rbtree_node_t*rb_node; +njs_variable_node_t *node; +const njs_lexer_entry_t *lex_entry; + +static const njs_str_t njs_this_str = njs_str("this"); + +keys = njs_value_enumerate(vm, value, flags); +if (njs_slow_path(keys == NULL)) { +return NULL; +} + +if (!njs_values_same(value, >global_value) +|| vm->global_scope == NULL) +{ +goto done; +} + +/* TODO: workaround for values in global object. */ + +variables = >global_scope->variables; +rb_node = njs_rbtree_min(variables); + +while (njs_rbtree_is_there_successor(variables, rb_node)) { +node = (njs_variable_node_t *) rb_node; + +lex_entry = njs_lexer_entry(node->variable->unique_id); +if (njs_slow_path(lex_entry == NULL)) { +return NULL; +} + +if (njs_strstr_eq(_entry->name, _this_str)) { +rb_node = njs_rbtree_node_successor(variables, rb_node); +continue; +} + +length = njs_utf8_length(lex_entry->name.start, lex_entry->name.length); +if (njs_slow_path(length < 0)) { +return NULL; +} + +val = njs_array_push(vm, keys); +if (njs_slow_path(value == NULL)) { +return NULL; +} + +ret = njs_string_new(vm, val, lex_entry->name.start, + lex_entry->name.length, length); +if (njs_slow_path(ret != NJS_OK)) { +return NULL; +} + +rb_node = njs_rbtree_node_successor(variables, rb_node); +} + +done: + + njs_set_array(retval, keys); + + return retval; +} + + +njs_value_t * +njs_vm_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, uint32_t flags, +njs_value_t *retval) +{ +njs_array_t *keys; + +keys = njs_value_own_enumerate(vm, value, flags); +if (njs_slow_path(keys == NULL)) { +return NULL; +} + +njs_set_array(retval, keys); + +return retval; +} + + njs_int_t njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, ...)
[njs] Refactoring njs_value_own_enumerate() and friends.
details: https://hg.nginx.org/njs/rev/b0e42db5ca84 branches: changeset: 2299:b0e42db5ca84 user: Dmitry Volyntsev date: Fri Mar 15 22:47:50 2024 -0700 description: Refactoring njs_value_own_enumerate() and friends. All three flag-like arguments are merged into a single flag argument. diffstat: src/njs_array.c |4 +- src/njs_builtin.c |2 +- src/njs_json.c|8 +- src/njs_object.c | 154 + src/njs_object.h |4 +- src/njs_value.c | 20 ++ src/njs_value.h | 21 +++--- src/njs_vm.c |4 +- src/njs_vmcode.c |6 +- 9 files changed, 106 insertions(+), 117 deletions(-) diffs (727 lines): diff -r 6808a27d254a -r b0e42db5ca84 src/njs_array.c --- a/src/njs_array.c Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_array.c Fri Mar 15 22:47:50 2024 -0700 @@ -1868,8 +1868,8 @@ njs_array_keys(njs_vm_t *vm, njs_value_t { njs_array_t *keys; -keys = njs_value_own_enumerate(vm, object, NJS_ENUM_KEYS, NJS_ENUM_STRING, - all); +keys = njs_value_own_enumerate(vm, object, NJS_ENUM_KEYS | NJS_ENUM_STRING + | (!all ? NJS_ENUM_ENUMERABLE_ONLY : 0)); if (njs_slow_path(keys == NULL)) { return NULL; } diff -r 6808a27d254a -r b0e42db5ca84 src/njs_builtin.c --- a/src/njs_builtin.c Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_builtin.c Fri Mar 15 22:47:50 2024 -0700 @@ -648,7 +648,7 @@ njs_object_completions(njs_vm_t *vm, njs object->type = NJS_OBJECT; } -keys = njs_value_enumerate(vm, object, NJS_ENUM_KEYS, NJS_ENUM_STRING, 1); +keys = njs_value_enumerate(vm, object, NJS_ENUM_KEYS | NJS_ENUM_STRING); if (njs_slow_path(keys == NULL)) { goto done; } diff -r 6808a27d254a -r b0e42db5ca84 src/njs_json.c --- a/src/njs_json.cThu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_json.cFri Mar 15 22:47:50 2024 -0700 @@ -44,7 +44,7 @@ typedef struct { njs_value_treplacer; njs_str_t space; u_char space_buf[16]; -njs_object_enum_type_t keys_type; +uint32_t keys_type; } njs_json_stringify_t; @@ -998,8 +998,10 @@ njs_json_push_stringify_state(njs_json_s } } else { -state->keys = njs_value_own_enumerate(stringify->vm, value, NJS_ENUM_KEYS, - stringify->keys_type, 0); +state->keys = njs_value_own_enumerate(stringify->vm, value, + NJS_ENUM_KEYS + | stringify->keys_type + | NJS_ENUM_ENUMERABLE_ONLY); if (njs_slow_path(state->keys == NULL)) { return NULL; diff -r 6808a27d254a -r b0e42db5ca84 src/njs_object.c --- a/src/njs_object.c Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_object.c Fri Mar 15 22:47:50 2024 -0700 @@ -18,17 +18,16 @@ static njs_int_t njs_object_hash_test(nj static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin, const njs_object_t *end, njs_lvlhsh_query_t *lhq); static njs_int_t njs_object_enumerate_array(njs_vm_t *vm, -const njs_array_t *array, njs_array_t *items, njs_object_enum_t kind); +const njs_array_t *array, njs_array_t *items, uint32_t flags); static njs_int_t njs_object_enumerate_typed_array(njs_vm_t *vm, -const njs_typed_array_t *array, njs_array_t *items, njs_object_enum_t kind); +const njs_typed_array_t *array, njs_array_t *items, uint32_t flags); static njs_int_t njs_object_enumerate_string(njs_vm_t *vm, -const njs_value_t *value, njs_array_t *items, njs_object_enum_t kind); +const njs_value_t *value, njs_array_t *items, uint32_t flags); static njs_int_t njs_object_enumerate_object(njs_vm_t *vm, -const njs_object_t *object, njs_array_t *items, njs_object_enum_t kind, -njs_object_enum_type_t type, njs_bool_t all); +const njs_object_t *object, njs_array_t *items, uint32_t flags); static njs_int_t njs_object_own_enumerate_object(njs_vm_t *vm, const njs_object_t *object, const njs_object_t *parent, njs_array_t *items, -njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); +uint32_t flags); static njs_int_t njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_object_set_prototype(njs_vm_t *vm, njs_object_t *object, @@ -324,8 +323,8 @@ njs_object_keys(njs_vm_t *vm, njs_value_ return NJS_ERROR; } -keys = njs_value_own_enumerate(vm, value, NJS_ENUM_KEYS, - NJS_ENUM_STRING, 0); +keys = njs_value_own_enumerate(vm, value, NJS_ENUM_KEYS | NJS_ENUM_STRING + | NJS_ENUM_ENUMERABLE_ONLY); if (keys == NULL) { return NJS
[njs] Introduced njs_vm_prototype() to get a value's prototype.
details: https://hg.nginx.org/njs/rev/6808a27d254a branches: changeset: 2298:6808a27d254a user: Dmitry Volyntsev date: Thu Mar 14 23:28:03 2024 -0700 description: Introduced njs_vm_prototype() to get a value's prototype. diffstat: src/njs.h| 2 ++ src/njs_object.c | 2 +- src/njs_object.h | 2 ++ src/njs_vm.c | 13 + 4 files changed, 18 insertions(+), 1 deletions(-) diffs (59 lines): diff -r 00b89201fb71 -r 6808a27d254a src/njs.h --- a/src/njs.h Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs.h Thu Mar 14 23:28:03 2024 -0700 @@ -373,6 +373,8 @@ NJS_EXPORT njs_int_t njs_vm_value(njs_vm njs_value_t *retval); NJS_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, const njs_str_t *name); NJS_EXPORT njs_bool_t njs_vm_constructor(njs_vm_t *vm); +NJS_EXPORT njs_int_t njs_vm_prototype(njs_vm_t *vm, njs_value_t *value, +njs_value_t *retval); NJS_EXPORT void njs_vm_throw(njs_vm_t *vm, const njs_value_t *value); NJS_EXPORT void njs_vm_error2(njs_vm_t *vm, unsigned error_type, diff -r 00b89201fb71 -r 6808a27d254a src/njs_object.c --- a/src/njs_object.c Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_object.c Thu Mar 14 23:28:03 2024 -0700 @@ -1598,7 +1598,7 @@ njs_object_get_own_property(njs_vm_t *vm } -static njs_int_t +njs_int_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { diff -r 00b89201fb71 -r 6808a27d254a src/njs_object.h --- a/src/njs_object.h Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_object.h Thu Mar 14 23:28:03 2024 -0700 @@ -106,6 +106,8 @@ njs_int_t njs_object_prop_define(njs_vm_ njs_value_t *name, njs_value_t *value, unsigned flags, uint32_t hash); njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_value_t *value, njs_value_t *setval); +njs_int_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, +njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); const char *njs_prop_type_string(njs_object_prop_type_t type); njs_int_t njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init, const njs_object_prop_t *base, njs_value_t *value, njs_value_t *retval); diff -r 00b89201fb71 -r 6808a27d254a src/njs_vm.c --- a/src/njs_vm.c Thu Mar 14 23:28:03 2024 -0700 +++ b/src/njs_vm.c Thu Mar 14 23:28:03 2024 -0700 @@ -1201,6 +1201,19 @@ njs_vm_object_keys(njs_vm_t *vm, njs_val njs_int_t +njs_vm_prototype(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) +{ +njs_value_t arguments[2]; + +njs_set_undefined([0]); +njs_value_assign([1], value); + +return njs_object_get_prototype_of(vm, njs_value_arg(), 2, 0, + retval); +} + + +njs_int_t njs_vm_array_alloc(njs_vm_t *vm, njs_value_t *retval, uint32_t spare) { njs_array_t *array; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Introduced njs_vm_global() to get global object.
details: https://hg.nginx.org/njs/rev/00b89201fb71 branches: changeset: 2297:00b89201fb71 user: Dmitry Volyntsev date: Thu Mar 14 23:28:03 2024 -0700 description: Introduced njs_vm_global() to get global object. diffstat: src/njs.h| 1 + src/njs_vm.c | 8 2 files changed, 9 insertions(+), 0 deletions(-) diffs (29 lines): diff -r 8309b884e265 -r 00b89201fb71 src/njs.h --- a/src/njs.h Tue Mar 05 11:43:49 2024 -0800 +++ b/src/njs.h Thu Mar 14 23:28:03 2024 -0700 @@ -368,6 +368,7 @@ NJS_EXPORT njs_int_t njs_vm_bind(njs_vm_ njs_int_t njs_vm_bind_handler(njs_vm_t *vm, const njs_str_t *var_name, njs_prop_handler_t handler, uint16_t magic16, uint32_t magic32, njs_bool_t shared); +NJS_EXPORT njs_int_t njs_vm_global(njs_vm_t *vm, njs_value_t *retval); NJS_EXPORT njs_int_t njs_vm_value(njs_vm_t *vm, const njs_str_t *path, njs_value_t *retval); NJS_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, const njs_str_t *name); diff -r 8309b884e265 -r 00b89201fb71 src/njs_vm.c --- a/src/njs_vm.c Tue Mar 05 11:43:49 2024 -0800 +++ b/src/njs_vm.c Thu Mar 14 23:28:03 2024 -0700 @@ -814,6 +814,14 @@ njs_vm_error3(njs_vm_t *vm, unsigned typ njs_int_t +njs_vm_global(njs_vm_t *vm, njs_value_t *retval) +{ +njs_value_assign(retval, >global_value); +return NJS_OK; +} + + +njs_int_t njs_vm_value(njs_vm_t *vm, const njs_str_t *path, njs_value_t *retval) { u_char *start, *p, *end; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
Re: lock in nginx/njs
On 12.03.2024 23:00, Eugene Prokopiev wrote: Здравствуйте! Скажите, нет ли чего-нибудь похожего на https://github.com/openresty/lua-resty-lock/ в nginx/njs? Или может есть другой способ разрешить выполнять запросы с одинаковым $uri строго по очереди (один выполняется, остальные ждут)? А чем вас https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_lock не устраивает? Или более подробно опишите свою задачу ___ nginx-ru mailing list nginx-ru@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: [PATCH] HTTP: remove needless code
On 3/5/24 10:15 AM, Sergey A. Osokin wrote: # HG changeset patch # User Sergey A. Osokin # Date 1709662441 -10800 # Tue Mar 05 21:14:01 2024 +0300 # Node ID 00de871f1e5e0936e2401aaec863bf7040de8608 # Parent eb01434865d7b698f036f199084308726c2827ea HTTP: remove needless code. diff -r eb01434865d7 -r 00de871f1e5e nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cThu Feb 29 20:56:56 2024 -0800 +++ b/nginx/ngx_http_js_module.cTue Mar 05 21:14:01 2024 +0300 @@ -4193,8 +4193,6 @@ } return NJS_OK; - -return NJS_OK; } Thank you for catching the issue. It is already fixed here https://hg.nginx.org/njs/rev/8309b884e265. ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed typo introduced in eb01434865d7.
details: https://hg.nginx.org/njs/rev/8309b884e265 branches: changeset: 2296:8309b884e265 user: Dmitry Volyntsev date: Tue Mar 05 11:43:49 2024 -0800 description: Fixed typo introduced in eb01434865d7. diffstat: nginx/ngx_http_js_module.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diffs (12 lines): diff -r eb01434865d7 -r 8309b884e265 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cThu Feb 29 20:56:56 2024 -0800 +++ b/nginx/ngx_http_js_module.cTue Mar 05 11:43:49 2024 -0800 @@ -4193,8 +4193,6 @@ ngx_http_js_server(njs_vm_t *vm, ngx_htt } return NJS_OK; - -return NJS_OK; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] HTTP: allowing to set Server header.
details: https://hg.nginx.org/njs/rev/eb01434865d7 branches: changeset: 2295:eb01434865d7 user: Dmitry Volyntsev date: Thu Feb 29 20:56:56 2024 -0800 description: HTTP: allowing to set Server header. diffstat: nginx/ngx_http_js_module.c | 38 ++ nginx/t/js_headers.t | 22 -- 2 files changed, 58 insertions(+), 2 deletions(-) diffs (140 lines): diff -r d7a0bbcba46e -r eb01434865d7 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cThu Feb 29 18:56:13 2024 -0800 +++ b/nginx/ngx_http_js_module.cThu Feb 29 20:56:56 2024 -0800 @@ -149,6 +149,9 @@ static njs_int_t ngx_http_js_last_modifi static njs_int_t ngx_http_js_location122(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_http_js_server122(njs_vm_t *vm, ngx_http_request_t *r, +ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, +njs_value_t *retval); #endif static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); @@ -255,6 +258,9 @@ static njs_int_t ngx_http_js_last_modifi static njs_int_t ngx_http_js_location(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_http_js_server(njs_vm_t *vm, ngx_http_request_t *r, +unsigned flags, njs_str_t *name, njs_value_t *setval, +njs_value_t *retval); static ngx_pool_t *ngx_http_js_pool(njs_vm_t *vm, ngx_http_request_t *r); static ngx_resolver_t *ngx_http_js_resolver(njs_vm_t *vm, @@ -1617,6 +1623,7 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, { njs_str("Expires"), ngx_http_js_header_single }, { njs_str("Last-Modified"), ngx_http_js_last_modified122 }, { njs_str("Location"), ngx_http_js_location122 }, +{ njs_str("Server"), ngx_http_js_server122 }, { njs_str("Set-Cookie"), ngx_http_js_header_array }, { njs_str("Retry-After"), ngx_http_js_header_single }, { njs_str(""), ngx_http_js_header_generic }, @@ -1630,6 +1637,7 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, { njs_str("Expires"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, { njs_str("Last-Modified"), 0, ngx_http_js_last_modified }, { njs_str("Location"), 0, ngx_http_js_location }, +{ njs_str("Server"), 0, ngx_http_js_server }, { njs_str("Set-Cookie"), NJS_HEADER_ARRAY, ngx_http_js_header_out }, { njs_str("Retry-After"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, { njs_str(""), 0, ngx_http_js_header_out }, @@ -2065,6 +2073,14 @@ ngx_http_js_location122(njs_vm_t *vm, ng { return ngx_http_js_location(vm, r, 0, v, setval, retval); } + + +static njs_int_t +ngx_http_js_server122(njs_vm_t *vm, ngx_http_request_t *r, +ngx_list_t *headers, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ +return ngx_http_js_server(vm, r, 0, v, setval, retval); +} #endif @@ -4160,6 +4176,28 @@ ngx_http_js_location(njs_vm_t *vm, ngx_h } +static njs_int_t +ngx_http_js_server(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, +njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ +njs_int_t rc; +ngx_table_elt_t *h; + +rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, ); +if (rc == NJS_ERROR) { +return NJS_ERROR; +} + +if (setval != NULL || retval == NULL) { +r->headers_out.server = h; +} + +return NJS_OK; + +return NJS_OK; +} + + static void ngx_http_js_periodic_handler(ngx_event_t *ev) { diff -r d7a0bbcba46e -r eb01434865d7 nginx/t/js_headers.t --- a/nginx/t/js_headers.t Thu Feb 29 18:56:13 2024 -0800 +++ b/nginx/t/js_headers.t Thu Feb 29 20:56:56 2024 -0800 @@ -160,6 +160,10 @@ http { js_content test.copy_subrequest_hdrs; } +location /server { +js_content test.server; +} + location = /subrequest { internal; @@ -435,6 +439,11 @@ EOF r.return(200, resp.responseText); } +function server(r) { +r.headersOut['Server'] = 'Foo'; +r.return(200); +} + function subrequest(r) { r.headersOut['A'] = 'a'; r.headersOut['Content-Encoding'] = 'ce'; @@ -456,12 +465,12 @@ EOF hdr_out, raw_hdr_out, hdr_out_array, hdr_out_single, hdr_out_set_cookie, ihdr_out, hdr_out_special_set, copy_subrequest_hdrs, subrequest, date, last_modified, -location, location_sr}; +location, location_sr, server}; EOF -$t->try_run('no njs')->plan(46); +$t->try_run('no njs')->plan(49);
[njs] Shell: revert -t option back to preserve backward compatibility.
details: https://hg.nginx.org/njs/rev/d7a0bbcba46e branches: changeset: 2294:d7a0bbcba46e user: Dmitry Volyntsev date: Thu Feb 29 18:56:13 2024 -0800 description: Shell: revert -t option back to preserve backward compatibility. The issue was introduced in cb3e068a511c. diffstat: external/njs_shell.c | 16 1 files changed, 16 insertions(+), 0 deletions(-) diffs (26 lines): diff -r 49417e2749e0 -r d7a0bbcba46e external/njs_shell.c --- a/external/njs_shell.c Tue Feb 27 23:25:11 2024 -0800 +++ b/external/njs_shell.c Thu Feb 29 18:56:13 2024 -0800 @@ -726,6 +726,22 @@ njs_options_parse(njs_opts_t *opts, int opts->sandbox = 1; break; +case 't': +if (++i < argc) { +if (strcmp(argv[i], "module") == 0) { +opts->module = 1; + +} else if (strcmp(argv[i], "script") != 0) { +njs_stderror("option \"-t\" unexpected source type: %s\n", + argv[i]); +return NJS_ERROR; +} + +break; +} + +njs_stderror("option \"-t\" requires source type\n"); +return NJS_ERROR; case 'v': case 'V': opts->version = 1; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Removed duplicate expect tests introduced in cb3e068a511c.
details: https://hg.nginx.org/njs/rev/49417e2749e0 branches: changeset: 2293:49417e2749e0 user: Dmitry Volyntsev date: Tue Feb 27 23:25:11 2024 -0800 description: Removed duplicate expect tests introduced in cb3e068a511c. diffstat: test/shell_test_njs.exp | 32 1 files changed, 0 insertions(+), 32 deletions(-) diffs (42 lines): diff -r 46699330f4f2 -r 49417e2749e0 test/shell_test_njs.exp --- a/test/shell_test_njs.exp Tue Feb 27 23:25:05 2024 -0800 +++ b/test/shell_test_njs.exp Tue Feb 27 23:25:11 2024 -0800 @@ -212,38 +212,6 @@ njs_test { "TypeError: cannot get property \"a\" of undefined"} } -# console.time* functions -njs_test { -{"console.time()\r\n" - "console.time()\r\nundefined\r\n>> "} -{"console.timeEnd()\r\n" - "console.timeEnd()\r\ndefault: *.*ms\r\nundefined\r\n>> "} -{"console.time(undefined)\r\n" - "console.time(undefined)\r\nundefined\r\n>> "} -{"console.timeEnd(undefined)\r\n" - "console.timeEnd(undefined)\r\ndefault: *.*ms\r\nundefined\r\n>> "} -{"console.time('abc')\r\n" - "console.time('abc')\r\nundefined\r\n>> "} -{"console.time('abc')\r\n" - "console.time('abc')\r\nTimer \"abc\" already exists.\r\nundefined\r\n>> "} -{"console.timeEnd('abc')\r\n" - "console.timeEnd('abc')\r\nabc: *.*ms\r\nundefined\r\n>> "} -{"console.time(true)\r\n" - "console.time(true)\r\nundefined\r\n>> "} -{"console.timeEnd(true)\r\n" - "console.timeEnd(true)\r\ntrue: *.*ms\r\nundefined\r\n>> "} -{"console.time(42)\r\n" - "console.time(42)\r\nundefined\r\n>> "} -{"console.timeEnd(42)\r\n" - "console.timeEnd(42)\r\n42: *.*ms\r\nundefined\r\n>> "} -{"console.timeEnd()\r\n" - "console.timeEnd()\r\nTimer \"default\" doesn’t exist."} -{"console.timeEnd('abc')\r\n" - "console.timeEnd('abc')\r\nTimer \"abc\" doesn’t exist."} -{"console.time('abc')\r\n" - "console.time('abc')\r\nundefined\r\n>> "} -} - njs_test { {"console.ll()\r\n" "console.ll()\r\nThrown:\r\nTypeError: (intermediate value)\\\[\"ll\"] is not a function"} ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Shell: fixed memory pool issues introduced in cb3e068a511c.
details: https://hg.nginx.org/njs/rev/46699330f4f2 branches: changeset: 2292:46699330f4f2 user: Dmitry Volyntsev date: Tue Feb 27 23:25:05 2024 -0800 description: Shell: fixed memory pool issues introduced in cb3e068a511c. diffstat: external/njs_shell.c | 15 +-- 1 files changed, 9 insertions(+), 6 deletions(-) diffs (52 lines): diff -r e73d4947372d -r 46699330f4f2 external/njs_shell.c --- a/external/njs_shell.c Tue Feb 27 23:24:55 2024 -0800 +++ b/external/njs_shell.c Tue Feb 27 23:25:05 2024 -0800 @@ -1270,7 +1270,7 @@ njs_module_loader(njs_vm_t *vm, njs_exte return NULL; } -ret = njs_module_read(njs_vm_memory_pool(vm), info.fd, ); +ret = njs_module_read(console->engine->pool, info.fd, ); (void) close(info.fd); @@ -1293,10 +1293,10 @@ njs_module_loader(njs_vm_t *vm, njs_exte module = njs_vm_compile_module(vm, , , [text.length]); -njs_mp_free(njs_vm_memory_pool(vm), console->cwd.start); +njs_mp_free(console->engine->pool, console->cwd.start); console->cwd = prev_cwd; -njs_mp_free(njs_vm_memory_pool(vm), text.start); +njs_mp_free(console->engine->pool, text.start); return module; } @@ -3716,7 +3716,7 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu njs_queue_remove(>link); njs_rbtree_delete(>events, (njs_rbtree_part_t *) rb); -njs_mp_free(console->engine->pool, ev); +njs_mp_free(njs_vm_memory_pool(vm), ev); njs_value_undefined_set(retval); @@ -3780,12 +3780,15 @@ njs_console_time(njs_console_t *console, link = njs_queue_next(link); } -label = njs_mp_alloc(console->engine->pool, sizeof(njs_timelabel_t)); +label = njs_mp_alloc(console->engine->pool, + sizeof(njs_timelabel_t) + name->length); if (njs_slow_path(label == NULL)) { return NJS_ERROR; } -label->name = *name; +label->name.start = (u_char *) label + sizeof(njs_timelabel_t); +memcpy(label->name.start, name->start, name->length); +label->name.length = name->length; label->time = njs_time(); njs_queue_insert_tail(>labels, >link); ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Simplified working with global value.
details: https://hg.nginx.org/njs/rev/e73d4947372d branches: changeset: 2291:e73d4947372d user: Dmitry Volyntsev date: Tue Feb 27 23:24:55 2024 -0800 description: Simplified working with global value. diffstat: src/njs_builtin.c | 6 ++ src/njs_function.c | 2 +- src/njs_vm.c | 4 +--- 3 files changed, 4 insertions(+), 8 deletions(-) diffs (63 lines): diff -r cb3e068a511c -r e73d4947372d src/njs_builtin.c --- a/src/njs_builtin.c Thu Feb 22 20:25:43 2024 -0800 +++ b/src/njs_builtin.c Tue Feb 27 23:24:55 2024 -0800 @@ -258,8 +258,6 @@ njs_builtin_objects_create(njs_vm_t *vm) vm->global_object = shared->objects[0]; vm->global_object.shared = 0; -njs_set_object(>global_value, >global_object); - string_object = >string_object; njs_lvlhsh_init(_object->hash); string_object->shared_hash = shared->string_instance_hash; @@ -442,7 +440,7 @@ njs_builtin_completions(njs_vm_t *vm) ctx.type = NJS_BUILTIN_TRAVERSE_KEYS; njs_lvlhsh_init(); -ret = njs_object_traverse(vm, >global_object, , +ret = njs_object_traverse(vm, njs_object(>global_value), , njs_builtin_traverse); if (njs_slow_path(ret != NJS_OK)) { return NULL; @@ -753,7 +751,7 @@ njs_builtin_match_native_function(njs_vm ctx.match = njs_str_value(""); -ret = njs_object_traverse(vm, >global_object, , +ret = njs_object_traverse(vm, njs_object(>global_value), , njs_builtin_traverse); if (ret == NJS_DONE) { diff -r cb3e068a511c -r e73d4947372d src/njs_function.c --- a/src/njs_function.cThu Feb 22 20:25:43 2024 -0800 +++ b/src/njs_function.cTue Feb 27 23:24:55 2024 -0800 @@ -435,7 +435,7 @@ njs_function_lambda_frame(njs_vm_t *vm, if (njs_slow_path(function->global_this && njs_is_null_or_undefined(this))) { -njs_set_object(native_frame->local[0], >global_object); +njs_value_assign(native_frame->local[0], >global_value); } /* Copy arguments. */ diff -r cb3e068a511c -r e73d4947372d src/njs_vm.c --- a/src/njs_vm.c Thu Feb 22 20:25:43 2024 -0800 +++ b/src/njs_vm.c Tue Feb 27 23:24:55 2024 -0800 @@ -425,8 +425,6 @@ njs_vm_clone(njs_vm_t *vm, njs_external_ nvm->levels[NJS_LEVEL_GLOBAL] = global; -njs_set_object(>global_value, >global_object); - /* globalThis and this */ njs_scope_value_set(nvm, njs_scope_global_this_index(), >global_value); @@ -826,7 +824,7 @@ njs_vm_value(njs_vm_t *vm, const njs_str start = path->start; end = start + path->length; -njs_set_object(, >global_object); +njs_value_assign(, >global_value); for ( ;; ) { p = njs_strlchr(start, end, '.'); ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Shell: added QuickJS engine support.
details: https://hg.nginx.org/njs/rev/cb3e068a511c branches: changeset: 2290:cb3e068a511c user: Dmitry Volyntsev date: Thu Feb 22 20:25:43 2024 -0800 description: Shell: added QuickJS engine support. diffstat: auto/expect |22 +- auto/make|23 +- auto/options | 2 + auto/quickjs |55 + auto/summary | 4 + configure| 1 + external/njs_shell.c | 2225 - src/njs_builtin.c| 3 + src/test/njs_unit_test.c | 4 +- test/setup | 5 + test/shell_test.exp | 361 +--- test/shell_test_njs.exp | 418 test/test262 | 5 + 13 files changed, 2531 insertions(+), 597 deletions(-) diffs (truncated from 3866 to 1000 lines): diff -r 272af619b821 -r cb3e068a511c auto/expect --- a/auto/expect Thu Feb 22 17:38:58 2024 -0800 +++ b/auto/expect Thu Feb 22 20:25:43 2024 -0800 @@ -20,11 +20,31 @@ fi if [ $njs_found = yes -a $NJS_HAVE_READLINE = YES ]; then cat << END >> $NJS_MAKEFILE -shell_test:njs test/shell_test.exp +shell_test_njs:njs test/shell_test.exp PATH=$NJS_BUILD_DIR:\$(PATH) LANG=C.UTF-8 TERM=screen \ expect -f test/shell_test.exp + PATH=$NJS_BUILD_DIR:\$(PATH) LANG=C.UTF-8 TERM=screen \ +expect -f test/shell_test_njs.exp END +if [ $NJS_HAVE_QUICKJS = YES ]; then +cat << END >> $NJS_MAKEFILE + +shell_test:shell_test_njs shell_test_quickjs + +shell_test_quickjs:njs test/shell_test.exp + PATH=$NJS_BUILD_DIR:\$(PATH) LANG=C.UTF-8 TERM=screen NJS_ENGINE=QuickJS \ +expect -f test/shell_test.exp +END + +else +cat << END >> $NJS_MAKEFILE + +shell_test:shell_test_njs +END + +fi + else echo " - expect tests are disabled" diff -r 272af619b821 -r cb3e068a511c auto/make --- a/auto/make Thu Feb 22 17:38:58 2024 -0800 +++ b/auto/make Thu Feb 22 20:25:43 2024 -0800 @@ -241,8 +241,7 @@ lib_test: $NJS_BUILD_DIR/njs_auto_config $NJS_BUILD_DIR/lvlhsh_unit_test $NJS_BUILD_DIR/unicode_unit_test -test262: njs - +test262_njs: njs test/test262 --binary=$NJS_BUILD_DIR/njs unit_test: $NJS_BUILD_DIR/njs_auto_config.h \\ @@ -265,6 +264,26 @@ dist: && echo njs-\$(NJS_VER).tar.gz done END +if [ $NJS_HAVE_QUICKJS = YES ]; then +cat << END >> $NJS_MAKEFILE + +test262: njs test262_njs test262_quickjs + +test262_quickjs: njs + NJS_SKIP_LIST="test/js/promise_rejection_tracker_recursive.t.js \\ +test/js/async_exception_in_await.t.js" \\ + test/test262 --binary='$NJS_BUILD_DIR/njs -n QuickJS -m' +END + +else +cat << END >> $NJS_MAKEFILE + +test262: njs test262_njs +END + +fi + + njs_ts_deps=`echo $NJS_TS_SRCS \ | sed -e "s# *\([^ ][^ ]*\)#\1$njs_regex_cont#g"` diff -r 272af619b821 -r cb3e068a511c auto/options --- a/auto/options Thu Feb 22 17:38:58 2024 -0800 +++ b/auto/options Thu Feb 22 20:25:43 2024 -0800 @@ -14,6 +14,7 @@ NJS_DEBUG_GENERATOR=NO NJS_ADDRESS_SANITIZER=NO NJS_ADDR2LINE=NO +NJS_QUICKJS=YES NJS_OPENSSL=YES NJS_LIBXML2=YES NJS_ZLIB=YES @@ -47,6 +48,7 @@ do --debug-opcode=*)NJS_DEBUG_OPCODE="$value" ;; --debug-generator=*) NJS_DEBUG_GENERATOR="$value";; +--no-quickjs)NJS_QUICKJS=NO ;; --no-openssl)NJS_OPENSSL=NO ;; --no-libxml2)NJS_LIBXML2=NO ;; --no-zlib) NJS_ZLIB=NO ;; diff -r 272af619b821 -r cb3e068a511c auto/quickjs --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/auto/quickjs Thu Feb 22 20:25:43 2024 -0800 @@ -0,0 +1,55 @@ + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + + +NJS_QUICKJS_LIB= +NJS_HAVE_QUICKJS=NO + +if [ $NJS_QUICKJS = YES ]; then +njs_found=no + +njs_feature="QuickJS library" +njs_feature_name=NJS_HAVE_QUICKJS +njs_feature_run=yes +njs_feature_incs= +njs_feature_libs="" +njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored \"-Wcast-function-type\" + #endif + + #include + + int main() { + JSRuntime *rt; + + rt = JS_NewRuntime(); + JS_FreeRuntime(rt); + return 0; + }" +. auto/feature + +if [ $njs_found = no ]; then +njs_feature="QuickJS library -lquickjs.lto" +njs_feature_incs="/usr/inclu
[njs] Fixed atob() with non-padded base64 strings.
details: https://hg.nginx.org/njs/rev/272af619b821 branches: changeset: 2289:272af619b821 user: Dmitry Volyntsev date: Thu Feb 22 17:38:58 2024 -0800 description: Fixed atob() with non-padded base64 strings. This fixes #695 issue on Github. diffstat: src/njs_string.c | 9 - src/test/njs_unit_test.c | 12 2 files changed, 20 insertions(+), 1 deletions(-) diffs (41 lines): diff -r 0479e5821ab2 -r 272af619b821 src/njs_string.c --- a/src/njs_string.c Wed Feb 14 21:34:02 2024 -0800 +++ b/src/njs_string.c Thu Feb 22 17:38:58 2024 -0800 @@ -4298,7 +4298,14 @@ njs_string_atob(njs_vm_t *vm, njs_value_ } } -len = njs_base64_decoded_length(str.length, pad); +len = str.length; + +if (len % 4 != 0) { +pad = 4 - (len % 4); +len += pad; +} + +len = njs_base64_decoded_length(len, pad); njs_chb_init(, vm->mem_pool); diff -r 0479e5821ab2 -r 272af619b821 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Feb 14 21:34:02 2024 -0800 +++ b/src/test/njs_unit_test.c Thu Feb 22 17:38:58 2024 -0800 @@ -10093,6 +10093,18 @@ static njs_unit_test_t njs_test[] = "].every(v => c(atob(v)).toString() == '8,52,86')"), njs_str("true")}, +{ njs_str("atob('aGVsbG8=')"), + njs_str("hello") }, + +{ njs_str("atob('aGVsbG8')"), + njs_str("hello") }, + +{ njs_str("atob('TQ==')"), + njs_str("M") }, + +{ njs_str("atob('TQ')"), + njs_str("M") }, + /* Functions. */ { njs_str("return"), ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Moving hash code out of the njs core.
details: https://hg.nginx.org/njs/rev/0479e5821ab2 branches: changeset: 2288:0479e5821ab2 user: Dmitry Volyntsev date: Wed Feb 14 21:34:02 2024 -0800 description: Moving hash code out of the njs core. diffstat: auto/modules |5 +- auto/sources |3 - external/njs_crypto_module.c |2 +- external/njs_hash.h | 32 external/njs_md5.c | 270 external/njs_sha1.c | 298 external/njs_sha2.c | 320 +++ src/njs_hash.h | 32 src/njs_main.h |2 - src/njs_md5.c| 266 --- src/njs_sha1.c | 294 --- src/njs_sha2.c | 316 -- 12 files changed, 925 insertions(+), 915 deletions(-) diffs (truncated from 1914 to 1000 lines): diff -r 6fa96ea99037 -r 0479e5821ab2 auto/modules --- a/auto/modules Wed Feb 14 21:33:56 2024 -0800 +++ b/auto/modules Wed Feb 14 21:34:02 2024 -0800 @@ -9,7 +9,10 @@ njs_module_srcs=src/njs_buffer.c njs_module_name=njs_crypto_module njs_module_incs= -njs_module_srcs=external/njs_crypto_module.c +njs_module_srcs="external/njs_crypto_module.c \ + external/njs_md5.c \ + external/njs_sha1.c \ + external/njs_sha2.c" . auto/module diff -r 6fa96ea99037 -r 0479e5821ab2 auto/sources --- a/auto/sources Wed Feb 14 21:33:56 2024 -0800 +++ b/auto/sources Wed Feb 14 21:34:02 2024 -0800 @@ -13,9 +13,6 @@ NJS_LIB_SRCS=" \ src/njs_flathsh.c \ src/njs_trace.c \ src/njs_random.c \ - src/njs_md5.c \ - src/njs_sha1.c \ - src/njs_sha2.c \ src/njs_malloc.c \ src/njs_mp.c \ src/njs_sprintf.c \ diff -r 6fa96ea99037 -r 0479e5821ab2 external/njs_crypto_module.c --- a/external/njs_crypto_module.c Wed Feb 14 21:33:56 2024 -0800 +++ b/external/njs_crypto_module.c Wed Feb 14 21:34:02 2024 -0800 @@ -6,9 +6,9 @@ #include -#include #include #include +#include "njs_hash.h" typedef void (*njs_hash_init)(njs_hash_t *ctx); diff -r 6fa96ea99037 -r 0479e5821ab2 external/njs_hash.h --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/external/njs_hash.h Wed Feb 14 21:34:02 2024 -0800 @@ -0,0 +1,32 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + + +#ifndef _NJS_HASH_H_INCLUDED_ +#define _NJS_HASH_H_INCLUDED_ + + +typedef struct { +uint64_t bytes; +uint32_t a, b, c, d, e, f, g, h; +u_charbuffer[64]; +} njs_hash_t; + + +NJS_EXPORT void njs_md5_init(njs_hash_t *ctx); +NJS_EXPORT void njs_md5_update(njs_hash_t *ctx, const void *data, size_t size); +NJS_EXPORT void njs_md5_final(u_char result[32], njs_hash_t *ctx); + +NJS_EXPORT void njs_sha1_init(njs_hash_t *ctx); +NJS_EXPORT void njs_sha1_update(njs_hash_t *ctx, const void *data, size_t size); +NJS_EXPORT void njs_sha1_final(u_char result[32], njs_hash_t *ctx); + +NJS_EXPORT void njs_sha2_init(njs_hash_t *ctx); +NJS_EXPORT void njs_sha2_update(njs_hash_t *ctx, const void *data, size_t size); +NJS_EXPORT void njs_sha2_final(u_char result[32], njs_hash_t *ctx); + + +#endif /* _NJS_HASH_H_INCLUDED_ */ diff -r 6fa96ea99037 -r 0479e5821ab2 external/njs_md5.c --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/external/njs_md5.cWed Feb 14 21:34:02 2024 -0800 @@ -0,0 +1,270 @@ + +/* + * An internal implementation, based on Alexander Peslyak's + * public domain implementation: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + */ + + +#include +#include +#include +#include +#include "njs_hash.h" + + +static const u_char *njs_md5_body(njs_hash_t *ctx, const u_char *data, +size_t size); + + +void +njs_md5_init(njs_hash_t *ctx) +{ +ctx->a = 0x67452301; +ctx->b = 0xefcdab89; +ctx->c = 0x98badcfe; +ctx->d = 0x10325476; + +ctx->bytes = 0; +} + + +void +njs_md5_update(njs_hash_t *ctx, const void *data, size_t size) +{ +size_t used, free; + +used = (size_t) (ctx->bytes & 0x3f); +ctx->bytes += size; + +if (used) { +free = 64 - used; + +if (size < free) { +memcpy(>buffer[used], data, size); +return; +} + +memcpy(>buffer[used], data, free); +data = (u_char *) data + free; +size -= free; +(void) njs_md5_body(ctx, ctx->buffer, 64); +} + +if (size >= 64) { +data = njs_md5_body(ctx, data, size & ~(size_t) 0x3f); +size &= 0x3f; +} + +memcpy(ctx->buffer, data, size); +} + + +void +njs_md5_final(u_char result[32], njs_hash_t *ctx) +{ +size_t used, free; + +used = (size_t) (ctx->bytes & 0x3f); + +ctx->buffer[used++]
[njs] Moved njs_time() out of the core as it is not a part of the spec.
details: https://hg.nginx.org/njs/rev/6fa96ea99037 branches: changeset: 2287:6fa96ea99037 user: Dmitry Volyntsev date: Wed Feb 14 21:33:56 2024 -0800 description: Moved njs_time() out of the core as it is not a part of the spec. diffstat: auto/sources | 1 - external/njs_shell.c | 21 - src/njs_date.c | 13 + src/njs_main.h | 1 - src/njs_time.c | 27 --- src/njs_time.h | 27 --- src/test/njs_benchmark.c | 19 +++ 7 files changed, 52 insertions(+), 57 deletions(-) diffs (178 lines): diff -r d3a9f2f153f8 -r 6fa96ea99037 auto/sources --- a/auto/sources Wed Feb 07 17:57:02 2024 -0800 +++ b/auto/sources Wed Feb 14 21:33:56 2024 -0800 @@ -16,7 +16,6 @@ NJS_LIB_SRCS=" \ src/njs_md5.c \ src/njs_sha1.c \ src/njs_sha2.c \ - src/njs_time.c \ src/njs_malloc.c \ src/njs_mp.c \ src/njs_sprintf.c \ diff -r d3a9f2f153f8 -r 6fa96ea99037 external/njs_shell.c --- a/external/njs_shell.c Wed Feb 07 17:57:02 2024 -0800 +++ b/external/njs_shell.c Wed Feb 14 21:33:56 2024 -0800 @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -169,6 +168,7 @@ static void njs_console_logger(njs_log_l static intptr_t njs_event_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2); +static uint64_t njs_time(void); njs_int_t njs_array_buffer_detach(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -2122,3 +2122,22 @@ njs_event_rbtree_compare(njs_rbtree_node return 0; } + + +static uint64_t +njs_time(void) +{ +#if (NJS_HAVE_CLOCK_MONOTONIC) +struct timespec ts; + +clock_gettime(CLOCK_MONOTONIC, ); + +return (uint64_t) ts.tv_sec * 10 + ts.tv_nsec; +#else +struct timeval tv; + +gettimeofday(, NULL); + +return (uint64_t) tv.tv_sec * 10 + tv.tv_usec * 1000; +#endif +} diff -r d3a9f2f153f8 -r 6fa96ea99037 src/njs_date.c --- a/src/njs_date.cWed Feb 07 17:57:02 2024 -0800 +++ b/src/njs_date.cWed Feb 14 21:33:56 2024 -0800 @@ -22,6 +22,19 @@ #define NJS_DATE_MSEC 7 +#if (NJS_HAVE_TM_GMTOFF) + +#define njs_timezone(tm) \ +((tm)->tm_gmtoff) + +#elif (NJS_HAVE_ALTZONE) + +#define njs_timezone(tm) \ +(-(((tm)->tm_isdst > 0) ? altzone : timezone)) + +#endif + + #define njs_date_magic(field, local) \ ((local << 6) + field) diff -r d3a9f2f153f8 -r 6fa96ea99037 src/njs_main.h --- a/src/njs_main.hWed Feb 07 17:57:02 2024 -0800 +++ b/src/njs_main.hWed Feb 14 21:33:56 2024 -0800 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff -r d3a9f2f153f8 -r 6fa96ea99037 src/njs_time.c --- a/src/njs_time.cWed Feb 07 17:57:02 2024 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,27 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - - -#include - - -uint64_t -njs_time(void) -{ -#if (NJS_HAVE_CLOCK_MONOTONIC) -struct timespec ts; - -clock_gettime(CLOCK_MONOTONIC, ); - -return (uint64_t) ts.tv_sec * 10 + ts.tv_nsec; -#else -struct timeval tv; - -gettimeofday(, NULL); - -return (uint64_t) tv.tv_sec * 10 + tv.tv_usec * 1000; -#endif -} diff -r d3a9f2f153f8 -r 6fa96ea99037 src/njs_time.h --- a/src/njs_time.hWed Feb 07 17:57:02 2024 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,27 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NJS_TIME_H_INCLUDED_ -#define _NJS_TIME_H_INCLUDED_ - - -#if (NJS_HAVE_TM_GMTOFF) - -#define njs_timezone(tm) \ -((tm)->tm_gmtoff) - -#elif (NJS_HAVE_ALTZONE) - -#define njs_timezone(tm) \ -(-(((tm)->tm_isdst > 0) ? altzone : timezone)) - -#endif - - -uint64_t njs_time(void); - - -#endif /* _NJS_TIME_H_INCLUDED_ */ diff -r d3a9f2f153f8 -r 6fa96ea99037 src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Wed Feb 07 17:57:02 2024 -0800 +++ b/src/test/njs_benchmark.c Wed Feb 14 21:33:56 2024 -0800 @@ -35,6 +35,25 @@ njs_module_t *njs_benchmark_addon_extern }; +static uint64_t +njs_time(void) +{ +#if (NJS_HAVE_CLOCK_MONOTONIC) +struct timespec ts; + +clock_gettime(CLOCK_MONOTONIC, ); + +return (uint64_t) ts.tv_sec * 10 + ts.tv_nsec; +#else +struct timeval tv; + +gettimeofday(, NULL); + +return (uint64_t) tv.tv_sec * 10 + tv.tv_usec * 1000; +#endif +} + + static njs_int_t njs_benchmark_test(njs_vm_t *parent, njs_opts_t *opts, njs_value_t *report, njs_benchmark_test_t *test)
[njs] Test262: fix import_global_ref_var.t.js.
details: https://hg.nginx.org/njs/rev/d3a9f2f153f8 branches: changeset: 2286:d3a9f2f153f8 user: Dmitry Volyntsev date: Wed Feb 07 17:57:02 2024 -0800 description: Test262: fix import_global_ref_var.t.js. diffstat: test/js/import_global_ref_var.t.js | 2 +- test/js/module/export_global_a.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diffs (22 lines): diff -r 82ae061db9d0 -r d3a9f2f153f8 test/js/import_global_ref_var.t.js --- a/test/js/import_global_ref_var.t.jsWed Feb 07 17:57:01 2024 -0800 +++ b/test/js/import_global_ref_var.t.jsWed Feb 07 17:57:02 2024 -0800 @@ -4,7 +4,7 @@ flags: [] paths: [test/js/module/] ---*/ -var a = 42; +globalThis.a = 42; import m from 'export_global_a.js'; assert.sameValue(m.f(), 42); diff -r 82ae061db9d0 -r d3a9f2f153f8 test/js/module/export_global_a.js --- a/test/js/module/export_global_a.js Wed Feb 07 17:57:01 2024 -0800 +++ b/test/js/module/export_global_a.js Wed Feb 07 17:57:02 2024 -0800 @@ -1,5 +1,5 @@ function f() { -return a; +return globalThis.a; } export default {f}; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Test262: simplified import_chain.t.js.
details: https://hg.nginx.org/njs/rev/82ae061db9d0 branches: changeset: 2285:82ae061db9d0 user: Dmitry Volyntsev date: Wed Feb 07 17:57:01 2024 -0800 description: Test262: simplified import_chain.t.js. Avoid using "crypto" module, which unnessesary complicates the test. diffstat: test/js/import_chain.t.js | 8 ++-- test/js/module/libs/hash.js | 5 + test/js/module/sub/sub1.js | 3 +-- 3 files changed, 4 insertions(+), 12 deletions(-) diffs (49 lines): diff -r 45f72ce8761b -r 82ae061db9d0 test/js/import_chain.t.js --- a/test/js/import_chain.t.js Wed Feb 07 17:57:01 2024 -0800 +++ b/test/js/import_chain.t.js Wed Feb 07 17:57:01 2024 -0800 @@ -4,10 +4,6 @@ flags: [] paths: [test/js/module/, test/js/module/libs/, test/js/module/sub] ---*/ -import lib2 from 'lib2.js'; +import lib2 from 'lib2.js'; -import crypto from 'crypto'; -var h = crypto.createHash('md5'); -var hash = h.update('AB').digest('hex'); - -assert.sameValue(lib2.hash(), hash); +assert.sameValue(lib2.hash(), "XXX"); diff -r 45f72ce8761b -r 82ae061db9d0 test/js/module/libs/hash.js --- a/test/js/module/libs/hash.js Wed Feb 07 17:57:01 2024 -0800 +++ b/test/js/module/libs/hash.js Wed Feb 07 17:57:01 2024 -0800 @@ -1,11 +1,8 @@ function hash() { -var h = crypto.createHash('md5'); -var v = h.update('AB').digest('hex'); -return v; +return "XXX"; } import sub from 'sub/sub3.js'; import name from 'name.js'; -import crypto from 'crypto'; export default {hash, name}; diff -r 45f72ce8761b -r 82ae061db9d0 test/js/module/sub/sub1.js --- a/test/js/module/sub/sub1.jsWed Feb 07 17:57:01 2024 -0800 +++ b/test/js/module/sub/sub1.jsWed Feb 07 17:57:01 2024 -0800 @@ -1,5 +1,5 @@ function hash() { -return sub2.hash(crypto); +return sub2.hash(); } function error() { @@ -7,6 +7,5 @@ function error() { } import sub2 from 'sub2.js'; -import crypto from 'crypto'; export default {hash, error}; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Removed njs_file.c not needed after 8aad26845b18 (0.8.3).
details: https://hg.nginx.org/njs/rev/45f72ce8761b branches: changeset: 2284:45f72ce8761b user: Dmitry Volyntsev date: Wed Feb 07 17:57:01 2024 -0800 description: Removed njs_file.c not needed after 8aad26845b18 (0.8.3). diffstat: auto/sources | 1 - src/njs_file.c | 69 - src/njs_file.h | 15 --- src/njs_main.h | 1 - src/test/njs_unit_test.c | 98 5 files changed, 0 insertions(+), 184 deletions(-) diffs (236 lines): diff -r 93562e512d26 -r 45f72ce8761b auto/sources --- a/auto/sources Wed Feb 07 17:56:59 2024 -0800 +++ b/auto/sources Wed Feb 07 17:57:01 2024 -0800 @@ -17,7 +17,6 @@ NJS_LIB_SRCS=" \ src/njs_sha1.c \ src/njs_sha2.c \ src/njs_time.c \ - src/njs_file.c \ src/njs_malloc.c \ src/njs_mp.c \ src/njs_sprintf.c \ diff -r 93562e512d26 -r 45f72ce8761b src/njs_file.c --- a/src/njs_file.cWed Feb 07 17:56:59 2024 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,69 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - - -#include - - -void -njs_file_basename(const njs_str_t *path, njs_str_t *name) -{ -const u_char *p, *end; - -end = path->start + path->length; -p = end - 1; - -/* Stripping dir prefix. */ - -while (p >= path->start && *p != '/') { p--; } - -p++; - -name->start = (u_char *) p; -name->length = end - p; -} - - -void -njs_file_dirname(const njs_str_t *path, njs_str_t *name) -{ -const u_char *p, *end; - -if (path->length == 0) { -goto current_dir; -} - -p = path->start + path->length - 1; - -/* Stripping basename. */ - -while (p >= path->start && *p != '/') { p--; } - -end = p + 1; - -if (end == path->start) { -goto current_dir; -} - -/* Stripping trailing slashes. */ - -while (p >= path->start && *p == '/') { p--; } - -p++; - -if (p == path->start) { -p = end; -} - -name->start = path->start; -name->length = p - path->start; - -return; - -current_dir: - -*name = njs_str_value("."); -} diff -r 93562e512d26 -r 45f72ce8761b src/njs_file.h --- a/src/njs_file.hWed Feb 07 17:56:59 2024 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,15 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NJS_FILE_H_INCLUDED_ -#define _NJS_FILE_H_INCLUDED_ - - -void njs_file_basename(const njs_str_t *path, njs_str_t *name); -void njs_file_dirname(const njs_str_t *path, njs_str_t *name); - - -#endif /* _NJS_FILE_H_INCLUDED_ */ diff -r 93562e512d26 -r 45f72ce8761b src/njs_main.h --- a/src/njs_main.hWed Feb 07 17:56:59 2024 -0800 +++ b/src/njs_main.hWed Feb 07 17:57:01 2024 -0800 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff -r 93562e512d26 -r 45f72ce8761b src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Feb 07 17:56:59 2024 -0800 +++ b/src/test/njs_unit_test.c Wed Feb 07 17:57:01 2024 -0800 @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -24449,99 +24448,6 @@ njs_vm_object_alloc_test(njs_vm_t *vm, n static njs_int_t -njs_file_basename_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat) -{ -njs_str_t name; -njs_bool_t success; -njs_uint_t i; - -static const struct { -njs_str_t path; -njs_str_t expected; -} tests[] = { -{ njs_str(""),njs_str("") }, -{ njs_str("/"), njs_str("") }, -{ njs_str("/a"), njs_str("a") }, -{ njs_str("///"), njs_str("") }, -{ njs_str("///a"),njs_str("a") }, -{ njs_str("///a/"), njs_str("") }, -{ njs_str("a"), njs_str("a") }, -{ njs_str("a/"), njs_str("") }, -{ njs_str("a//"), njs_str("") }, -{ njs_str("path/name"), njs_str("name") }, -{ njs_str("/path/name"), njs_str("name") }, -{ njs_str("/path/name/"), njs_str("") }, -}; - -for (i = 0; i < njs_nitems(tests); i++) { -njs_file_basename([i].path, ); - -success = njs_strstr_eq([i].expected, ); - -if (!success) { -njs_printf("njs_file_basename_test(\"%V\"):\n" - "expected: \"%V\"\n got: \"%V\"\n", - [i].path, [i].expected, ); - -stat->failed++; - -} else { -stat->passed++; -} -} -
[njs] Version bump.
details: https://hg.nginx.org/njs/rev/93562e512d26 branches: changeset: 2283:93562e512d26 user: Dmitry Volyntsev date: Wed Feb 07 17:56:59 2024 -0800 description: Version bump. diffstat: src/njs.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r f98dd6884786 -r 93562e512d26 src/njs.h --- a/src/njs.h Wed Feb 07 08:34:17 2024 -0800 +++ b/src/njs.h Wed Feb 07 17:56:59 2024 -0800 @@ -11,8 +11,8 @@ #include -#define NJS_VERSION "0.8.3" -#define NJS_VERSION_NUMBER 0x000803 +#define NJS_VERSION "0.8.4" +#define NJS_VERSION_NUMBER 0x000804 #include ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
njs-0.8.3
Hello, I'm glad to announce a new release of NGINX JavaScript module (njs). This release focuses on stabilization of recently released features and fixing bugs found by various fuzzers. Learn more about njs: - Overview and introduction: https://nginx.org/en/docs/njs/ - NGINX JavaScript in Your Web Server Configuration: https://youtu.be/Jc_L6UffFOs - Extending NGINX with Custom Code: https://youtu.be/0CVhq4AUU7M - Using node modules with njs: https://nginx.org/en/docs/njs/node_modules.html - Writing njs code using TypeScript definition files: https://nginx.org/en/docs/njs/typescript.html Feel free to try it and give us feedback on: - Github: https://github.com/nginx/njs/issues - Mailing list: https://mailman.nginx.org/mailman/listinfo/nginx-devel Additional examples and howtos can be found here: - Github: https://github.com/nginx/njs-examples Changes with njs 0.8.3 07 Feb 2024 nginx modules: *) Bugfix: fixed Headers.set(). *) Bugfix: fixed js_set with Buffer values. *) Bugfix: fixed clear() method of a shared dictionary when timeout is not specified. *) Bugfix: fixed stub_status statistic when js_periodic is enabled. Core: *) Bugfix: fixed building with libxml2 2.12 and later. *) Bugfix: fixed Date constructor for overflows and with NaN values. *) Bugfix: fixed underflow in querystring.parse(). *) Bugfix: fixed potential buffer overread in String.prototype.match(). *) Bugfix: fixed parsing of for-in loops. *) Bugfix: fixed parsing of hexadecimal, octal, and binary literals with no digits. ___ nginx mailing list nginx@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx
[nginx-announce] njs-0.8.3
Hello, I'm glad to announce a new release of NGINX JavaScript module (njs). This release focuses on stabilization of recently released features and fixing bugs found by various fuzzers. Learn more about njs: - Overview and introduction: https://nginx.org/en/docs/njs/ - NGINX JavaScript in Your Web Server Configuration: https://youtu.be/Jc_L6UffFOs - Extending NGINX with Custom Code: https://youtu.be/0CVhq4AUU7M - Using node modules with njs: https://nginx.org/en/docs/njs/node_modules.html - Writing njs code using TypeScript definition files: https://nginx.org/en/docs/njs/typescript.html Feel free to try it and give us feedback on: - Github: https://github.com/nginx/njs/issues - Mailing list: https://mailman.nginx.org/mailman/listinfo/nginx-devel Additional examples and howtos can be found here: - Github: https://github.com/nginx/njs-examples Changes with njs 0.8.3 07 Feb 2024 nginx modules: *) Bugfix: fixed Headers.set(). *) Bugfix: fixed js_set with Buffer values. *) Bugfix: fixed clear() method of a shared dictionary when timeout is not specified. *) Bugfix: fixed stub_status statistic when js_periodic is enabled. Core: *) Bugfix: fixed building with libxml2 2.12 and later. *) Bugfix: fixed Date constructor for overflows and with NaN values. *) Bugfix: fixed underflow in querystring.parse(). *) Bugfix: fixed potential buffer overread in String.prototype.match(). *) Bugfix: fixed parsing of for-in loops. *) Bugfix: fixed parsing of hexadecimal, octal, and binary literals with no digits. ___ nginx-announce mailing list nginx-announce@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-announce
[njs] Added tag 0.8.3 for changeset 3aba7ee62080
details: https://hg.nginx.org/njs/rev/f98dd6884786 branches: changeset: 2282:f98dd6884786 user: Dmitry Volyntsev date: Wed Feb 07 08:34:17 2024 -0800 description: Added tag 0.8.3 for changeset 3aba7ee62080 diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 3aba7ee62080 -r f98dd6884786 .hgtags --- a/.hgtags Wed Feb 07 08:34:00 2024 -0800 +++ b/.hgtags Wed Feb 07 08:34:17 2024 -0800 @@ -65,3 +65,4 @@ a1faa64d4972020413fd168e2b542bcc150819c0 0ed1952588ab1e0e1c18425fe7923b2b76f38a65 0.8.0 a52b49f9afcf410597dc6657ad39ae3dbbfeec56 0.8.1 45f81882c780a12e56be519cd3106c4fe5567a64 0.8.2 +3aba7ee620807ad10bc34bff3677350fa8a3c3b2 0.8.3 ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Version 0.8.3.
details: https://hg.nginx.org/njs/rev/3aba7ee62080 branches: changeset: 2281:3aba7ee62080 user: Dmitry Volyntsev date: Wed Feb 07 08:34:00 2024 -0800 description: Version 0.8.3. diffstat: CHANGES | 31 +++ 1 files changed, 31 insertions(+), 0 deletions(-) diffs (38 lines): diff -r 25e548de3d61 -r 3aba7ee62080 CHANGES --- a/CHANGES Tue Feb 06 19:32:08 2024 -0800 +++ b/CHANGES Wed Feb 07 08:34:00 2024 -0800 @@ -1,3 +1,34 @@ +Changes with njs 0.8.3 07 Feb 2024 + +nginx modules: + +*) Bugfix: fixed Headers.set(). + +*) Bugfix: fixed js_set with Buffer values. + +*) Bugfix: fixed clear() method of a shared dictionary when + a timeout is not specified. + +*) Bugfix: fixed stub_status statistics when js_periodic is + enabled. + +Core: + +*) Bugfix: fixed building with libxml2 2.12 and later. + +*) Bugfix: fixed Date constructor for overflows and with + NaN values. + +*) Bugfix: fixed underflow in querystring.parse(). + +*) Bugfix: fixed potential buffer overread in + String.prototype.match(). + +*) Bugfix: fixed parsing of for-in loops. + +*) Bugfix: fixed parsing of hexadecimal, octal, and binary + literals with no digits. + Changes with njs 0.8.2 24 Oct 2023 nginx modules: ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Reverted changes introduced in 7eaaa7d57636 (not released) back.
details: https://hg.nginx.org/njs/rev/25e548de3d61 branches: changeset: 2280:25e548de3d61 user: Dmitry Volyntsev date: Tue Feb 06 19:32:08 2024 -0800 description: Reverted changes introduced in 7eaaa7d57636 (not released) back. Relative importing is again supported. diffstat: external/njs_shell.c | 101 - nginx/ngx_js.c| 88 - nginx/ngx_js.h|1 + nginx/t/js_import_relative.t | 100 + test/js/import_relative_path.t.js |9 +++ test/js/module/libs/hash.js |1 + test/js/module/sub/sub3.js|1 + 7 files changed, 296 insertions(+), 5 deletions(-) diffs (468 lines): diff -r 673d78618fc9 -r 25e548de3d61 external/njs_shell.c --- a/external/njs_shell.c Wed Jan 31 17:06:58 2024 -0800 +++ b/external/njs_shell.c Tue Feb 06 19:32:08 2024 -0800 @@ -115,6 +115,8 @@ typedef struct { njs_queue_t labels; +njs_str_t cwd; + njs_arr_t *rejected_promises; njs_bool_t suppress_stdout; @@ -693,6 +695,8 @@ njs_console_init(njs_vm_t *vm, njs_conso njs_queue_init(>posted_events); njs_queue_init(>labels); +njs_memzero(>cwd, sizeof(njs_str_t)); + console->rejected_promises = NULL; console->completion.completions = njs_vm_completions(vm, NULL); @@ -869,7 +873,7 @@ njs_module_path(const njs_str_t *dir, nj if (dir != NULL) { length += dir->length; -if (length == 0) { +if (length == 0 || dir->length == 0) { return NJS_DECLINED; } @@ -915,7 +919,8 @@ njs_module_path(const njs_str_t *dir, nj static njs_int_t -njs_module_lookup(njs_opts_t *opts, njs_module_info_t *info) +njs_module_lookup(njs_opts_t *opts, const njs_str_t *cwd, +njs_module_info_t *info) { njs_int_t ret; njs_str_t *path; @@ -925,6 +930,12 @@ njs_module_lookup(njs_opts_t *opts, njs_ return njs_module_path(NULL, info); } +ret = njs_module_path(cwd, info); + +if (ret != NJS_DECLINED) { +return ret; +} + path = opts->paths; for (i = 0; i < opts->n_paths; i++) { @@ -980,23 +991,86 @@ fail: } +static void +njs_file_dirname(const njs_str_t *path, njs_str_t *name) +{ +const u_char *p, *end; + +if (path->length == 0) { +goto current_dir; +} + +p = path->start + path->length - 1; + +/* Stripping basename. */ + +while (p >= path->start && *p != '/') { p--; } + +end = p + 1; + +if (end == path->start) { +goto current_dir; +} + +/* Stripping trailing slashes. */ + +while (p >= path->start && *p == '/') { p--; } + +p++; + +if (p == path->start) { +p = end; +} + +name->start = path->start; +name->length = p - path->start; + +return; + +current_dir: + +*name = njs_str_value("."); +} + + +static njs_int_t +njs_console_set_cwd(njs_vm_t *vm, njs_console_t *console, njs_str_t *file) +{ +njs_str_t cwd; + +njs_file_dirname(file, ); + +console->cwd.start = njs_mp_alloc(njs_vm_memory_pool(vm), cwd.length); +if (njs_slow_path(console->cwd.start == NULL)) { +return NJS_ERROR; +} + +memcpy(console->cwd.start, cwd.start, cwd.length); +console->cwd.length = cwd.length; + +return NJS_OK; +} + + static njs_mod_t * njs_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name) { u_char *start; njs_int_t ret; -njs_str_t text; +njs_str_t text, prev_cwd; njs_mod_t *module; njs_opts_t *opts; +njs_console_t *console; njs_module_info_t info; opts = external; +console = njs_vm_external_ptr(vm); njs_memzero(, sizeof(njs_module_info_t)); info.name = *name; -ret = njs_module_lookup(opts, ); +ret = njs_module_lookup(opts, >cwd, ); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -1010,11 +1084,23 @@ njs_module_loader(njs_vm_t *vm, njs_exte return NULL; } +prev_cwd = console->cwd; + +ret = njs_console_set_cwd(vm, console, ); +if (njs_slow_path(ret != NJS_OK)) { +njs_vm_internal_error(vm, "while setting cwd for \"%V\" module", + ); +return NULL; +} + start = text.start; module = njs_vm_compile_module(vm, , , [text.length]); +njs_mp_free(njs_vm_memory_pool(vm), console->cwd.start); +console->cwd = prev_cwd; + njs_mp_free(njs_vm_memory_pool(vm), text.start); return module; @@ -1025,6 +,7 @@ static njs_vm_t * njs_create_vm(njs_opts_t *opts) { njs_vm_t *vm; +
[njs] HTTP: fixed stub_status statistic when js_periodic is enabled.
details: https://hg.nginx.org/njs/rev/673d78618fc9 branches: changeset: 2279:673d78618fc9 user: Dmitry Volyntsev date: Wed Jan 31 17:06:58 2024 -0800 description: HTTP: fixed stub_status statistic when js_periodic is enabled. Previously, when js_periodic is enabled the Reading statistic was growing each time the js_periodic handler was called. The issue was introduced in f1bd0b1db065 (0.8.1). This fixes #692 issue on Github. diffstat: nginx/ngx_http_js_module.c | 16 +--- 1 files changed, 5 insertions(+), 11 deletions(-) diffs (39 lines): diff -r fca50ba4db9d -r 673d78618fc9 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cMon Jan 29 17:16:08 2024 -0800 +++ b/nginx/ngx_http_js_module.cWed Jan 31 17:06:58 2024 -0800 @@ -4323,30 +4323,24 @@ ngx_http_js_periodic_finalize(ngx_http_r static void ngx_http_js_periodic_destroy(ngx_http_request_t *r, ngx_js_periodic_t *periodic) { -ngx_connection_t*c; -ngx_http_cleanup_t *cln; +ngx_connection_t *c; c = r->connection; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http js periodic destroy: \"%V\"", - >method); + "http js periodic destroy: \"%V\"", >method); periodic->connection = NULL; -for (cln = r->cleanup; cln; cln = cln->next) { -if (cln->handler) { -cln->handler(cln->data); -} -} +r->logged = 1; + +ngx_http_free_request(r, NGX_OK); ngx_free_connection(c); c->fd = (ngx_socket_t) -1; c->pool = NULL; c->destroyed = 1; - -ngx_destroy_pool(r->pool); } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Style.
details: https://hg.nginx.org/njs/rev/fca50ba4db9d branches: changeset: 2278:fca50ba4db9d user: Dmitry Volyntsev date: Mon Jan 29 17:16:08 2024 -0800 description: Style. diffstat: src/njs_builtin.c | 2 +- src/njs_clang.h | 26 +- 2 files changed, 14 insertions(+), 14 deletions(-) diffs (48 lines): diff -r 478795e3296b -r fca50ba4db9d src/njs_builtin.c --- a/src/njs_builtin.c Mon Jan 29 17:16:07 2024 -0800 +++ b/src/njs_builtin.c Mon Jan 29 17:16:08 2024 -0800 @@ -28,7 +28,7 @@ static njs_int_t njs_global_this_prop_ha static njs_arr_t *njs_vm_expression_completions(njs_vm_t *vm, njs_str_t *expression); static njs_arr_t *njs_vm_global_var_completions(njs_vm_t *vm, - njs_str_t *expression); +njs_str_t *expression); static njs_arr_t *njs_object_completions(njs_vm_t *vm, njs_value_t *object, njs_str_t *expression); static njs_int_t njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, diff -r 478795e3296b -r fca50ba4db9d src/njs_clang.h --- a/src/njs_clang.h Mon Jan 29 17:16:07 2024 -0800 +++ b/src/njs_clang.h Mon Jan 29 17:16:08 2024 -0800 @@ -193,19 +193,19 @@ njs_leading_zeros64(uint64_t x) njs_inline NJS_NOSANITIZE("float-cast-overflow") int64_t njs_unsafe_cast_double_to_int64(double num) { - /* -* Casting NaN to integer is undefined behavior, -* but it is fine in some cases where we do additional checks later. -* For example: -* int64_t i64 = njs_unsafe_cast_double_to_int64(num); -* if (i64 == num) { -*// num is integer -* } -* -* We do this as inline function to avoid UndefinedBehaviorSanitizer -* warnings. -*/ - return (int64_t) num; +/* + * Casting NaN to integer is undefined behavior, + * but it is fine in some cases where we do additional checks later. + * For example: + * int64_t i64 = njs_unsafe_cast_double_to_int64(num); + * if (i64 == num) { + *// num is integer + * } + * + * We do this as inline function to avoid UndefinedBehaviorSanitizer + * warnings. + */ +return (int64_t) num; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] 2024 year.
details: https://hg.nginx.org/njs/rev/478795e3296b branches: changeset: 2277:478795e3296b user: Dmitry Volyntsev date: Mon Jan 29 17:16:07 2024 -0800 description: 2024 year. diffstat: LICENSE | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (16 lines): diff -r 9e2a757cb33e -r 478795e3296b LICENSE --- a/LICENSE Mon Jan 29 17:16:01 2024 -0800 +++ b/LICENSE Mon Jan 29 17:16:07 2024 -0800 @@ -1,9 +1,9 @@ /* - * Copyright (C) 2015-2023 NGINX, Inc. + * Copyright (C) 2015-2024 NGINX, Inc. * Copyright (C) 2015-2021 Igor Sysoev - * Copyright (C) 2017-2023 Dmitry Volyntsev + * Copyright (C) 2017-2024 Dmitry Volyntsev * Copyright (C) 2019-2022 Alexander Borisov - * Copyright (C) 2022-2023 Vadim Zhestikov + * Copyright (C) 2022-2024 Vadim Zhestikov * All rights reserved. * * Redistribution and use in source and binary forms, with or without ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Test262: handling the mkdir issue with a host file system.
details: https://hg.nginx.org/njs/rev/9e2a757cb33e branches: changeset: 2276:9e2a757cb33e user: Dmitry Volyntsev date: Mon Jan 29 17:16:01 2024 -0800 description: Test262: handling the mkdir issue with a host file system. diffstat: test/fs/promises_05.t.js | 13 - 1 files changed, 12 insertions(+), 1 deletions(-) diffs (23 lines): diff -r a2959e490279 -r 9e2a757cb33e test/fs/promises_05.t.js --- a/test/fs/promises_05.t.js Mon Jan 29 08:57:49 2024 -0800 +++ b/test/fs/promises_05.t.js Mon Jan 29 17:16:01 2024 -0800 @@ -49,7 +49,18 @@ var testSync = () => new Promise((resolv try { fs.writeFileSync(fname(dname_utf8), fname(dname_utf8)); -throw new Error('fs.mkdirSync error 1'); +const mode = fs.statSync(fname(dname_utf8)).mode & 0o777; + +if (mode == 0o555) { +/* + * Some file systems ignore the mode parameter for mkdir. + * For example: a shared folder on a MacOS host mounted + * to a Linux guest via Parallels Desktop. + */ +throw new Error('fs.writeFileSync did not respect mode'); +} + +fs.unlinkSync(fname(dname_utf8)); } catch (e) { if (e.syscall != 'open' || e.code != 'EACCES') { ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed fuzzer build after 9b3dac56fd8a.
details: https://hg.nginx.org/njs/rev/6770c015efdc branches: changeset: 2273:6770c015efdc user: Dmitry Volyntsev date: Thu Jan 25 14:48:05 2024 -0800 description: Fixed fuzzer build after 9b3dac56fd8a. diffstat: external/njs_shell.c | 60 +++ 1 files changed, 27 insertions(+), 33 deletions(-) diffs (120 lines): diff -r 9b3dac56fd8a -r 6770c015efdc external/njs_shell.c --- a/external/njs_shell.c Tue Jan 23 16:34:10 2024 -0800 +++ b/external/njs_shell.c Thu Jan 25 14:48:05 2024 -0800 @@ -137,8 +137,7 @@ static njs_int_t njs_process_script(njs_ #ifndef NJS_FUZZER_TARGET static njs_int_t njs_options_parse(njs_opts_t *opts, int argc, char **argv); -static njs_int_t njs_options_add_path(njs_opts_t *opts, u_char *path, -size_t len); +static njs_int_t njs_options_add_path(njs_opts_t *opts, char *path, size_t len); static void njs_options_free(njs_opts_t *opts); #ifdef NJS_HAVE_READLINE @@ -400,7 +399,8 @@ done: static njs_int_t njs_options_parse(njs_opts_t *opts, int argc, char **argv) { -char*p; +char*p, *start; +size_t len; njs_int_t i, ret; njs_uint_t n; @@ -447,6 +447,27 @@ njs_options_parse(njs_opts_t *opts, int opts->exit_code = atoi(p); } +start = getenv("NJS_PATH"); +if (start != NULL) { +for ( ;; ) { +p = (char *) njs_strchr(start, ':'); + +len = (p != NULL) ? (size_t) (p - start) : njs_strlen(start); + +ret = njs_options_add_path(opts, start, len); +if (ret != NJS_OK) { +njs_stderror("failed to add path\n"); +return NJS_ERROR; +} + +if (p == NULL) { +break; +} + +start = p + 1; +} +} + for (i = 1; i < argc; i++) { p = argv[i]; @@ -526,8 +547,7 @@ njs_options_parse(njs_opts_t *opts, int case 'p': if (++i < argc) { -ret = njs_options_add_path(opts, (u_char *) argv[i], - njs_strlen(argv[i])); +ret = njs_options_add_path(opts, argv[i], njs_strlen(argv[i])); if (ret != NJS_OK) { njs_stderror("failed to add path\n"); return NJS_ERROR; @@ -604,7 +624,7 @@ done: static njs_int_t -njs_options_add_path(njs_opts_t *opts, u_char *path, size_t len) +njs_options_add_path(njs_opts_t *opts, char *path, size_t len) { njs_str_t *paths; @@ -617,7 +637,7 @@ njs_options_add_path(njs_opts_t *opts, u } opts->paths = paths; -opts->paths[opts->n_paths - 1].start = path; +opts->paths[opts->n_paths - 1].start = (u_char *) path; opts->paths[opts->n_paths - 1].length = len; return NJS_OK; @@ -1004,10 +1024,7 @@ njs_module_loader(njs_vm_t *vm, njs_exte static njs_vm_t * njs_create_vm(njs_opts_t *opts) { -size_tlen; -u_char*p, *start; njs_vm_t *vm; -njs_int_t ret; njs_vm_opt_t vm_options; njs_vm_opt_init(_options); @@ -1053,29 +1070,6 @@ njs_create_vm(njs_opts_t *opts) njs_vm_set_module_loader(vm, njs_module_loader, opts); -start = (u_char *) getenv("NJS_PATH"); -if (start == NULL) { -return vm; -} - -for ( ;; ) { -p = njs_strchr(start, ':'); - -len = (p != NULL) ? (size_t) (p - start) : njs_strlen(start); - -ret = njs_options_add_path(opts, start, len); -if (ret != NJS_OK) { -njs_stderror("failed to add path\n"); -return NULL; -} - -if (p == NULL) { -break; -} - -start = p + 1; -} - return vm; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Moving out HostLoadImportedModule from njs core.
details: https://hg.nginx.org/njs/rev/9b3dac56fd8a branches: changeset: 2272:9b3dac56fd8a user: Dmitry Volyntsev date: Tue Jan 23 16:34:10 2024 -0800 description: Moving out HostLoadImportedModule from njs core. HostLoadImportedModule should be implemented by host environment according to ECMAScript specs. The following method was removed: njs_vm_add_path(). diffstat: external/njs_shell.c | 230 +- nginx/ngx_js.c | 211 ++ src/njs.h|2 - src/njs_module.c | 230 --- src/njs_module.h |1 - src/njs_parser.c | 39 src/njs_vm.c | 23 - src/njs_vm.h |1 - 8 files changed, 438 insertions(+), 299 deletions(-) diffs (915 lines): diff -r 7eaaa7d57636 -r 9b3dac56fd8a external/njs_shell.c --- a/external/njs_shell.c Tue Jan 23 16:33:52 2024 -0800 +++ b/external/njs_shell.c Tue Jan 23 16:34:10 2024 -0800 @@ -47,7 +47,7 @@ typedef struct { char*file; njs_str_t command; size_t n_paths; -char**paths; +njs_str_t *paths; char**argv; njs_uint_t argc; } njs_opts_t; @@ -99,6 +99,14 @@ typedef struct { typedef struct { +int fd; +njs_str_t name; +njs_str_t file; +charpath[NJS_MAX_PATH + 1]; +} njs_module_info_t; + + +typedef struct { njs_vm_t*vm; uint32_tevent_id; @@ -129,6 +137,8 @@ static njs_int_t njs_process_script(njs_ #ifndef NJS_FUZZER_TARGET static njs_int_t njs_options_parse(njs_opts_t *opts, int argc, char **argv); +static njs_int_t njs_options_add_path(njs_opts_t *opts, u_char *path, +size_t len); static void njs_options_free(njs_opts_t *opts); #ifdef NJS_HAVE_READLINE @@ -390,7 +400,7 @@ done: static njs_int_t njs_options_parse(njs_opts_t *opts, int argc, char **argv) { -char*p, **paths; +char*p; njs_int_t i, ret; njs_uint_t n; @@ -516,15 +526,13 @@ njs_options_parse(njs_opts_t *opts, int case 'p': if (++i < argc) { -opts->n_paths++; -paths = realloc(opts->paths, opts->n_paths * sizeof(char *)); -if (paths == NULL) { +ret = njs_options_add_path(opts, (u_char *) argv[i], + njs_strlen(argv[i])); +if (ret != NJS_OK) { njs_stderror("failed to add path\n"); return NJS_ERROR; } -opts->paths = paths; -opts->paths[opts->n_paths - 1] = argv[i]; break; } @@ -595,6 +603,27 @@ done: } +static njs_int_t +njs_options_add_path(njs_opts_t *opts, u_char *path, size_t len) +{ +njs_str_t *paths; + +opts->n_paths++; + +paths = realloc(opts->paths, opts->n_paths * sizeof(njs_str_t)); +if (paths == NULL) { +njs_stderror("failed to add path\n"); +return NJS_ERROR; +} + +opts->paths = paths; +opts->paths[opts->n_paths - 1].start = path; +opts->paths[opts->n_paths - 1].length = len; + +return NJS_OK; +} + + static void njs_options_free(njs_opts_t *opts) { @@ -806,14 +835,179 @@ njs_rejection_tracker(njs_vm_t *vm, njs_ } +static njs_int_t +njs_module_path(const njs_str_t *dir, njs_module_info_t *info) +{ +char*p; +size_t length; +njs_bool_t trail; +charsrc[NJS_MAX_PATH + 1]; + +trail = 0; +length = info->name.length; + +if (dir != NULL) { +length += dir->length; + +if (length == 0) { +return NJS_DECLINED; +} + +trail = (dir->start[dir->length - 1] != '/'); + +if (trail) { +length++; +} +} + +if (njs_slow_path(length > NJS_MAX_PATH)) { +return NJS_ERROR; +} + +p = [0]; + +if (dir != NULL) { +p = (char *) njs_cpymem(p, dir->start, dir->length); + +if (trail) { +*p++ = '/'; +} +} + +p = (char *) njs_cpymem(p, info->name.start, info->name.length); +*p = '\0'; + +p = realpath([0], >path[0]); +if (p == NULL) { +return NJS_DECLINED; +} + +info->fd = open(>path[0], O_RDONLY); +if (info->fd < 0) { +return NJS_DECLINED; +} + +info->file.start = (u_char *) >path[0]; +info->file.length = njs_strlen(info->file.start); + +return NJS_OK; +} + + +static njs_int_t +njs_module_lookup(njs_opts_t *opts, njs_module_info_t *info) +{ +njs_int_t ret; +njs_str_t *path; +njs_uint_t i;
[njs] Change: imported modules are not resolved relative to current dir.
details: https://hg.nginx.org/njs/rev/7eaaa7d57636 branches: changeset: 2271:7eaaa7d57636 user: Dmitry Volyntsev date: Tue Jan 23 16:33:52 2024 -0800 description: Change: imported modules are not resolved relative to current dir. Previously, when a module was imported with a relative path it was looked for first in the directory of the importing context (global, or a module). For example when: main.js: import libs/lib1.js; libs/lib1.js: import lib2.js; lib2.js was looked for first in libs/. Now, it is only looked for in directories speficied with js_path and a directory of nginx configuration file. diffstat: src/njs_module.c | 24 ++-- test/js/import_chain.t.js | 2 +- test/js/import_relative_path.t.js | 10 -- test/shell_test.exp | 4 ++-- 4 files changed, 9 insertions(+), 31 deletions(-) diffs (120 lines): diff -r 6485ad23565e -r 7eaaa7d57636 src/njs_module.c --- a/src/njs_module.c Tue Jan 23 16:33:29 2024 -0800 +++ b/src/njs_module.c Tue Jan 23 16:33:52 2024 -0800 @@ -16,8 +16,7 @@ typedef struct { } njs_module_info_t; -static njs_int_t njs_module_lookup(njs_vm_t *vm, const njs_str_t *cwd, -njs_module_info_t *info); +static njs_int_t njs_module_lookup(njs_vm_t *vm, njs_module_info_t *info); static njs_int_t njs_module_path(njs_vm_t *vm, const njs_str_t *dir, njs_module_info_t *info); static njs_int_t njs_module_read(njs_vm_t *vm, int fd, njs_str_t *body); @@ -45,7 +44,7 @@ njs_parser_module(njs_parser_t *parser, goto done; } -external = parser; +external = NULL; loader = njs_default_module_loader; if (vm->module_loader != NULL) { @@ -70,7 +69,7 @@ done: static njs_int_t -njs_module_lookup(njs_vm_t *vm, const njs_str_t *cwd, njs_module_info_t *info) +njs_module_lookup(njs_vm_t *vm, njs_module_info_t *info) { njs_int_t ret; njs_str_t *path; @@ -80,12 +79,6 @@ njs_module_lookup(njs_vm_t *vm, const nj return njs_module_path(vm, NULL, info); } -ret = njs_module_path(vm, cwd, info); - -if (ret != NJS_DECLINED) { -return ret; -} - if (vm->paths == NULL) { return NJS_DECLINED; } @@ -158,7 +151,6 @@ njs_module_path(njs_vm_t *vm, const njs_ return NJS_DECLINED; } - info->file.start = (u_char *) >path[0]; info->file.length = njs_strlen(info->file.start); @@ -359,24 +351,20 @@ njs_module_require(njs_vm_t *vm, njs_val static njs_mod_t * -njs_default_module_loader(njs_vm_t *vm, njs_external_ptr_t external, +njs_default_module_loader(njs_vm_t *vm, njs_external_ptr_t unused, njs_str_t *name) { u_char *start; njs_int_t ret; -njs_str_t cwd, text; +njs_str_t text; njs_mod_t *module; -njs_parser_t *prev; njs_module_info_t info; -prev = external; - njs_memzero(, sizeof(njs_module_info_t)); info.name = *name; -njs_file_dirname(>lexer->file, ); -ret = njs_module_lookup(vm, , ); +ret = njs_module_lookup(vm, ); if (njs_slow_path(ret != NJS_OK)) { return NULL; } diff -r 6485ad23565e -r 7eaaa7d57636 test/js/import_chain.t.js --- a/test/js/import_chain.t.js Tue Jan 23 16:33:29 2024 -0800 +++ b/test/js/import_chain.t.js Tue Jan 23 16:33:52 2024 -0800 @@ -1,7 +1,7 @@ /*--- includes: [] flags: [] -paths: [test/js/module/, test/js/module/libs/] +paths: [test/js/module/, test/js/module/libs/, test/js/module/sub] ---*/ import lib2 from 'lib2.js'; diff -r 6485ad23565e -r 7eaaa7d57636 test/js/import_relative_path.t.js --- a/test/js/import_relative_path.t.js Tue Jan 23 16:33:29 2024 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,10 +0,0 @@ -/*--- -includes: [] -flags: [] -paths: [test/js/module/] */ - -import name from 'name.js'; -import hash from 'libs/hash.js'; - -assert.sameValue(hash.name, "libs.name"); diff -r 6485ad23565e -r 7eaaa7d57636 test/shell_test.exp --- a/test/shell_test.exp Tue Jan 23 16:33:29 2024 -0800 +++ b/test/shell_test.exp Tue Jan 23 16:33:52 2024 -0800 @@ -563,8 +563,8 @@ njs_test { # quiet mode -njs_run {"-q" "test/js/import_relative_path.t.js"} \ -"SyntaxError: Cannot find module \"name.js\" in 7" +njs_run {"-q" "test/js/import_chain.t.js"} \ +"SyntaxError: Cannot find module \"lib2.js\" in 7" # sandboxing ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Shell: fixed unhandled rejected promises handling.
details: https://hg.nginx.org/njs/rev/6485ad23565e branches: changeset: 2270:6485ad23565e user: Dmitry Volyntsev date: Tue Jan 23 16:33:29 2024 -0800 description: Shell: fixed unhandled rejected promises handling. The issue was introduced in dffdf7c50dfc (not released yet). diffstat: external/njs_shell.c | 10 +- test/js/promise_reject_post_catch.t.js | 9 - test/shell_test.exp| 9 + 3 files changed, 14 insertions(+), 14 deletions(-) diffs (59 lines): diff -r 8aad26845b18 -r 6485ad23565e external/njs_shell.c --- a/external/njs_shell.c Thu Jan 18 18:03:35 2024 -0800 +++ b/external/njs_shell.c Tue Jan 23 16:33:29 2024 -0800 @@ -1207,6 +1207,11 @@ njs_process_script(njs_vm_t *vm, void *r } } +ret = njs_process_events(runtime); +if (njs_slow_path(ret == NJS_ERROR)) { +break; +} + if (njs_unhandled_rejection(runtime)) { njs_process_output(vm, NULL, NJS_ERROR); @@ -1215,11 +1220,6 @@ njs_process_script(njs_vm_t *vm, void *r } } -ret = njs_process_events(runtime); -if (njs_slow_path(ret == NJS_ERROR)) { -break; -} - if (ret == NJS_OK) { break; } diff -r 8aad26845b18 -r 6485ad23565e test/js/promise_reject_post_catch.t.js --- a/test/js/promise_reject_post_catch.t.jsThu Jan 18 18:03:35 2024 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 + @@ -1,9 +0,0 @@ -/*--- -includes: [] -flags: [] -negative: - phase: runtime */ - -var p = Promise.reject(); -setImmediate(() => {p.catch(() => {})}); diff -r 8aad26845b18 -r 6485ad23565e test/shell_test.exp --- a/test/shell_test.exp Thu Jan 18 18:03:35 2024 -0800 +++ b/test/shell_test.exp Tue Jan 23 16:33:29 2024 -0800 @@ -476,6 +476,15 @@ ReferenceError: \"ref\" is not defined at anonymous \\\(string:1\\\) at main \\\(string:1\\\)\n$" +njs_test { +{"setImmediate(() => { console.log('x'); return Promise.reject('xx'); })\r\n" + "0\r\nx\r\nThrown:\r\nError: unhandled promise rejection: xx\r\n"} +{"setImmediate(() => { console.log('x'); return Promise.reject('xx'); })\r\n" + "1\r\nx\r\nThrown:\r\nError: unhandled promise rejection: xx\r\n"} +{"42\r\n" + "42\r\n"} +} + # CLI OPTIONS # help ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Moving out HostPromiseRejectionTracker from njs core.
details: https://hg.nginx.org/njs/rev/8aad26845b18 branches: changeset: 2269:8aad26845b18 user: Dmitry Volyntsev date: Thu Jan 18 18:03:35 2024 -0800 description: Moving out HostPromiseRejectionTracker from njs core. HostPromiseRejectionTracker should be implemented by host environment according to ECMAScript specs. The following method was removed: njs_vm_unhandled_rejection(). The following method was introduced: njs_vm_set_rejection_tracker(). diffstat: external/njs_shell.c | 103 +- nginx/ngx_http_js_module.c |1 - nginx/ngx_js.c | 101 +++-- nginx/ngx_js.h |2 + nginx/ngx_stream_js_module.c |1 - src/njs.h| 15 ++--- src/njs_promise.c| 74 -- src/njs_value.c |7 ++ src/njs_vm.c | 40 +++ src/njs_vm.h |4 +- 10 files changed, 230 insertions(+), 118 deletions(-) diffs (651 lines): diff -r da8b044e1c61 -r 8aad26845b18 external/njs_shell.c --- a/external/njs_shell.c Thu Jan 18 18:03:24 2024 -0800 +++ b/external/njs_shell.c Thu Jan 18 18:03:35 2024 -0800 @@ -93,6 +93,12 @@ typedef struct { typedef struct { +void*promise; +njs_opaque_value_t message; +} njs_rejected_promise_t; + + +typedef struct { njs_vm_t*vm; uint32_tevent_id; @@ -101,6 +107,8 @@ typedef struct { njs_queue_t labels; +njs_arr_t *rejected_promises; + njs_bool_t suppress_stdout; njs_completion_tcompletion; @@ -422,7 +430,7 @@ njs_options_parse(njs_opts_t *opts, int opts->denormals = 1; opts->exit_code = EXIT_FAILURE; -opts->unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW; +opts->unhandled_rejection = 1; p = getenv("NJS_EXIT_CODE"); if (p != NULL) { @@ -528,7 +536,7 @@ njs_options_parse(njs_opts_t *opts, int break; case 'r': -opts->unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE; +opts->unhandled_rejection = 0; break; case 's': @@ -636,6 +644,8 @@ njs_console_init(njs_vm_t *vm, njs_conso njs_queue_init(>posted_events); njs_queue_init(>labels); +console->rejected_promises = NULL; + console->completion.completions = njs_vm_completions(vm, NULL); if (console->completion.completions == NULL) { return NJS_ERROR; @@ -749,6 +759,53 @@ njs_externals_init(njs_vm_t *vm) } +static void +njs_rejection_tracker(njs_vm_t *vm, njs_external_ptr_t external, +njs_bool_t is_handled, njs_value_t *promise, njs_value_t *reason) +{ +void*promise_obj; +uint32_ti, length; +njs_console_t *console; +njs_rejected_promise_t *rejected_promise; + +console = external; + +if (is_handled && console->rejected_promises != NULL) { +rejected_promise = console->rejected_promises->start; +length = console->rejected_promises->items; + +promise_obj = njs_value_ptr(promise); + +for (i = 0; i < length; i++) { +if (rejected_promise[i].promise == promise_obj) { +njs_arr_remove(console->rejected_promises, + _promise[i]); + +break; +} +} + +return; +} + +if (console->rejected_promises == NULL) { +console->rejected_promises = njs_arr_create(njs_vm_memory_pool(vm), 4, + sizeof(njs_rejected_promise_t)); +if (njs_slow_path(console->rejected_promises == NULL)) { +return; +} +} + +rejected_promise = njs_arr_add(console->rejected_promises); +if (njs_slow_path(rejected_promise == NULL)) { +return; +} + +rejected_promise->promise = njs_value_ptr(promise); +njs_value_assign(_promise->message, reason); +} + + static njs_vm_t * njs_create_vm(njs_opts_t *opts) { @@ -784,7 +841,6 @@ njs_create_vm(njs_opts_t *opts) vm_options.argv = opts->argv; vm_options.argc = opts->argc; vm_options.ast = opts->ast; -vm_options.unhandled_rejection = opts->unhandled_rejection; if (opts->stack_size != 0) { vm_options.max_stack_size = opts->stack_size; @@ -796,6 +852,11 @@ njs_create_vm(njs_opts_t *opts) return NULL; } +if (opts->unhandled_rejection) { +njs_vm_set_rejection_tracker(vm, njs_rejection_tracker, + njs_vm_external_ptr(vm)); +} + for (i = 0; i < opts->n_paths; i++) { path.start = (u_char *) opts->paths[i]; path.length = njs_strlen(opt
[njs] Fixed tracking of unhandled rejected promises.
details: https://hg.nginx.org/njs/rev/da8b044e1c61 branches: changeset: 2268:da8b044e1c61 user: Dmitry Volyntsev date: Thu Jan 18 18:03:24 2024 -0800 description: Fixed tracking of unhandled rejected promises. Checking for unhandled promise rejections while looping for pending jobs produces false-positive reports when an rejected promised is handled by one of the pending jobs later. The fix is to check for unhandled promise rejections only at top level calls like ngx_js_name_invoke() and ngx_js_name_call() and only after all pending jobs are processed. The issue was introduced in bc80bcb3102c (not released yet). diffstat: external/njs_shell.c | 10 +- nginx/ngx_js.c| 11 +-- src/test/njs_externals_test.c | 2 +- src/test/njs_unit_test.c | 4 +--- 4 files changed, 20 insertions(+), 7 deletions(-) diffs (88 lines): diff -r 4fba78789fe4 -r da8b044e1c61 external/njs_shell.c --- a/external/njs_shell.c Thu Jan 11 15:13:47 2024 -0800 +++ b/external/njs_shell.c Thu Jan 18 18:03:24 2024 -0800 @@ -1100,7 +1100,7 @@ njs_process_script(njs_vm_t *vm, void *r for ( ;; ) { ret = njs_vm_execute_pending_job(vm); if (ret <= NJS_OK) { -if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) { +if (ret == NJS_ERROR) { njs_process_output(vm, NULL, ret); if (!njs_vm_options(vm)->interactive) { @@ -1112,6 +1112,14 @@ njs_process_script(njs_vm_t *vm, void *r } } +if (njs_vm_unhandled_rejection(vm)) { +njs_process_output(vm, NULL, NJS_ERROR); + +if (!njs_vm_options(vm)->interactive) { +return NJS_ERROR; +} +} + ret = njs_process_events(runtime); if (njs_slow_path(ret == NJS_ERROR)) { break; diff -r 4fba78789fe4 -r da8b044e1c61 nginx/ngx_js.c --- a/nginx/ngx_js.cThu Jan 11 15:13:47 2024 -0800 +++ b/nginx/ngx_js.cThu Jan 18 18:03:24 2024 -0800 @@ -357,7 +357,7 @@ ngx_js_call(njs_vm_t *vm, njs_function_t if (ret <= NJS_OK) { c = ngx_external_connection(vm, njs_vm_external_ptr(vm)); -if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) { +if (ret == NJS_ERROR) { ngx_js_exception(vm, ); ngx_log_error(NGX_LOG_ERR, c->log, 0, @@ -417,7 +417,7 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str for ( ;; ) { ret = njs_vm_execute_pending_job(vm); if (ret <= NJS_OK) { -if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) { +if (ret == NJS_ERROR) { ngx_js_exception(vm, ); ngx_log_error(NGX_LOG_ERR, log, 0, @@ -429,6 +429,13 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str } } +if (njs_vm_unhandled_rejection(vm)) { +ngx_js_exception(vm, ); + +ngx_log_error(NGX_LOG_ERR, log, 0, "js exception: %V", ); +return NGX_ERROR; +} + ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); return njs_rbtree_is_empty(>waiting_events) ? NGX_OK : NGX_AGAIN; diff -r 4fba78789fe4 -r da8b044e1c61 src/test/njs_externals_test.c --- a/src/test/njs_externals_test.c Thu Jan 11 15:13:47 2024 -0800 +++ b/src/test/njs_externals_test.c Thu Jan 18 18:03:24 2024 -0800 @@ -1485,7 +1485,7 @@ njs_external_call(njs_vm_t *vm, const nj for ( ;; ) { ret = njs_vm_execute_pending_job(vm); if (ret <= NJS_OK) { -if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) { +if (ret == NJS_ERROR) { return NJS_ERROR; } diff -r 4fba78789fe4 -r da8b044e1c61 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Jan 11 15:13:47 2024 -0800 +++ b/src/test/njs_unit_test.c Thu Jan 18 18:03:24 2024 -0800 @@ -23708,9 +23708,7 @@ njs_process_test(njs_external_state_t *s for ( ;; ) { ret = njs_vm_execute_pending_job(state->vm); if (ret <= NJS_OK) { -if (ret == NJS_ERROR -|| njs_vm_unhandled_rejection(state->vm)) -{ +if (ret == NJS_ERROR) { return NJS_ERROR; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] HTTP: avoiding arithmetic ops with NULL pointer in r.args getter.
details: https://hg.nginx.org/njs/rev/4fba78789fe4 branches: changeset: 2267:4fba78789fe4 user: Dmitry Volyntsev date: Thu Jan 11 15:13:47 2024 -0800 description: HTTP: avoiding arithmetic ops with NULL pointer in r.args getter. Found by UndefinedBehaviorSanitizer. diffstat: nginx/ngx_http_js_module.c | 7 --- 1 files changed, 4 insertions(+), 3 deletions(-) diffs (24 lines): diff -r 2b221f44efa6 -r 4fba78789fe4 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cThu Jan 11 15:13:43 2024 -0800 +++ b/nginx/ngx_http_js_module.cThu Jan 11 15:13:47 2024 -0800 @@ -2615,7 +2615,8 @@ static njs_int_t ngx_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { -njs_int_t ret; +u_char *data; +njs_int_tret; njs_value_t *args; ngx_http_js_ctx_t *ctx; ngx_http_request_t *r; @@ -2631,8 +2632,8 @@ ngx_http_js_ext_get_args(njs_vm_t *vm, n args = njs_value_arg(>args); if (njs_value_is_null(args)) { -ret = njs_vm_query_string_parse(vm, r->args.data, -r->args.data + r->args.len, args); +data = (r->args.len != 0) ? r->args.data : (u_char *) ""; +ret = njs_vm_query_string_parse(vm, data, data + r->args.len, args); if (ret == NJS_ERROR) { return NJS_ERROR; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] QueryString: avoiding arithmetic ops with NULL in parse().
details: https://hg.nginx.org/njs/rev/2b221f44efa6 branches: changeset: 2266:2b221f44efa6 user: Dmitry Volyntsev date: Thu Jan 11 15:13:43 2024 -0800 description: QueryString: avoiding arithmetic ops with NULL in parse(). Found by UndefinedBehaviorSanitizer. diffstat: external/njs_query_string_module.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diffs (22 lines): diff -r a5f279148c9f -r 2b221f44efa6 external/njs_query_string_module.c --- a/external/njs_query_string_module.cWed Jan 10 16:26:35 2024 -0800 +++ b/external/njs_query_string_module.cThu Jan 11 15:13:43 2024 -0800 @@ -491,7 +491,7 @@ njs_query_string_parser(njs_vm_t *vm, u_ key = query; -do { +while (key < end) { if (count++ == max_keys) { break; } @@ -519,8 +519,7 @@ njs_query_string_parser(njs_vm_t *vm, u_ next: key = part + sep->length; - -} while (key < end); +} return NJS_OK; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed potential buffer overread in String.prototype.match().
details: https://hg.nginx.org/njs/rev/476f7b3e617d branches: changeset: 2264:476f7b3e617d user: Dmitry Volyntsev date: Tue Jan 09 17:56:19 2024 -0800 description: Fixed potential buffer overread in String.prototype.match(). diffstat: src/njs_string.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 50c587f74a09 -r 476f7b3e617d src/njs_string.c --- a/src/njs_string.c Tue Jan 09 09:14:42 2024 -0800 +++ b/src/njs_string.c Tue Jan 09 17:56:19 2024 -0800 @@ -2797,7 +2797,7 @@ njs_string_prototype_match(njs_vm_t *vm, match: -return njs_regexp_prototype_exec(vm, arguments, nargs, unused, retval); +return njs_regexp_prototype_exec(vm, arguments, 2, unused, retval); } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
Re: [PATCH] Satisfy UBSan in njs
On 1/3/24 4:55 PM, Ben Kallus wrote: When I run my nginx+njs application with UBSan enabled, I encounter a few instances of undefined behavior in njs: 1. A memcpy from NULL 2. A couple of offsets applied to NULL 3. A u32 assigned to nan 4. A u32 assigned to inf This patch adds checks to prevent these undefined operations. With it, my application no longer has any UBSan alerts. Hi Ben, I did a bunch of patches related to UBSan in njs core, most notably https://hg.nginx.org/njs/rev/0490f1ae4cf5. Now unit tests and test262 pass without warnings. Thank you for prodding. # HG changeset patch # User Ben Kallus # Date 1704329280 18000 # Wed Jan 03 19:48:00 2024 -0500 # Node ID 85d5846984fc2731ad74f91f21c74be67d6974a9 # Parent 4a15613f4e8bb4a8349ee1cefbae07585da4cbc6 Prevent undefined operations on NULL, INF, and NAN diff -r 4a15613f4e8b -r 85d5846984fc nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cTue Dec 19 12:37:05 2023 -0800 +++ b/nginx/ngx_http_js_module.cWed Jan 03 19:48:00 2024 -0500 @@ -2717,7 +2717,9 @@ for ( /* void */ ; cl; cl = cl->next) { buf = cl->buf; -p = ngx_cpymem(p, buf->pos, buf->last - buf->pos); +if (buf->last - buf->pos > 0) { +p = ngx_cpymem(p, buf->pos, buf->last - buf->pos); +} } done: diff -r 4a15613f4e8b -r 85d5846984fc src/njs_extern.c --- a/src/njs_extern.c Tue Dec 19 12:37:05 2023 -0800 +++ b/src/njs_extern.c Wed Jan 03 19:48:00 2024 -0500 @@ -38,7 +38,10 @@ lhq.proto = _object_hash_proto; lhq.pool = vm->mem_pool; -end = external + n; +end = external; +if (n > 0) { +end += n; +} while (external < end) { diff -r 4a15613f4e8b -r 85d5846984fc src/njs_number.h --- a/src/njs_number.h Tue Dec 19 12:37:05 2023 -0800 +++ b/src/njs_number.h Wed Jan 03 19:48:00 2024 -0500 @@ -41,6 +41,10 @@ { uint32_t u32; +if (isnan(num) || isinf(num)) { +return 0; +} + u32 = num; return (u32 == num && u32 != 0x); diff -r 4a15613f4e8b -r 85d5846984fc src/njs_object.c --- a/src/njs_object.c Tue Dec 19 12:37:05 2023 -0800 +++ b/src/njs_object.c Wed Jan 03 19:48:00 2024 -0500 @@ -598,7 +598,10 @@ start = array->start; p = start; -end = p + array->length; +end = p; +if (array->length > 0) { +end += array->length; +} switch (kind) { case NJS_ENUM_KEYS: ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Avoiding arithmetic ops with NULL in %TypedArray%.prototype.sort().
details: https://hg.nginx.org/njs/rev/50c587f74a09 branches: changeset: 2263:50c587f74a09 user: Dmitry Volyntsev date: Tue Jan 09 09:14:42 2024 -0800 description: Avoiding arithmetic ops with NULL in %TypedArray%.prototype.sort(). Found by UndefinedBehaviorSanitizer. diffstat: src/njs_typed_array.c | 9 + 1 files changed, 5 insertions(+), 4 deletions(-) diffs (26 lines): diff -r f4cb0dc3e8ea -r 50c587f74a09 src/njs_typed_array.c --- a/src/njs_typed_array.c Mon Jan 08 22:21:14 2024 -0800 +++ b/src/njs_typed_array.c Tue Jan 09 09:14:42 2024 -0800 @@ -2035,6 +2035,11 @@ njs_typed_array_prototype_sort(njs_vm_t } njs_qsort(base, length, element_size, cmp, ); + +if (njs_slow_path(ctx.exception)) { +return NJS_ERROR; +} + if (ctx.function != NULL) { if (>u.u8[array->offset * element_size] == orig) { memcpy(orig, base, length * element_size); @@ -2043,10 +2048,6 @@ njs_typed_array_prototype_sort(njs_vm_t njs_mp_free(vm->mem_pool, base); } -if (njs_slow_path(ctx.exception)) { -return NJS_ERROR; -} - njs_set_typed_array(retval, array); return NJS_OK; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Avoiding casting Infinity to integer in String.fromCodePoint().
details: https://hg.nginx.org/njs/rev/f4cb0dc3e8ea branches: changeset: 2262:f4cb0dc3e8ea user: Dmitry Volyntsev date: Mon Jan 08 22:21:14 2024 -0800 description: Avoiding casting Infinity to integer in String.fromCodePoint(). Found by UndefinedBehaviorSanitizer. diffstat: src/njs_string.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5d2a3da0674f -r f4cb0dc3e8ea src/njs_string.c --- a/src/njs_string.c Mon Jan 08 22:20:19 2024 -0800 +++ b/src/njs_string.c Mon Jan 08 22:21:14 2024 -0800 @@ -1617,7 +1617,7 @@ njs_string_from_char_code(njs_vm_t *vm, if (is_point) { num = njs_number([i]); -if (isnan(num)) { +if (isnan(num) || isinf(num)) { goto range_error; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Avoiding arithmetic operations with NULL pointer in TextDecoder().
details: https://hg.nginx.org/njs/rev/5d2a3da0674f branches: changeset: 2261:5d2a3da0674f user: Dmitry Volyntsev date: Mon Jan 08 22:20:19 2024 -0800 description: Avoiding arithmetic operations with NULL pointer in TextDecoder(). Found by UndefinedBehaviorSanitizer. diffstat: src/njs_encoding.c | 2 +- src/njs_utf8.c | 30 -- 2 files changed, 17 insertions(+), 15 deletions(-) diffs (57 lines): diff -r c15a6129ade7 -r 5d2a3da0674f src/njs_encoding.c --- a/src/njs_encoding.cMon Jan 08 22:20:10 2024 -0800 +++ b/src/njs_encoding.cMon Jan 08 22:20:19 2024 -0800 @@ -543,7 +543,7 @@ njs_text_decoder_decode(njs_vm_t *vm, nj /* Looking for BOM. */ -if (!data->ignore_bom) { +if (start != NULL && !data->ignore_bom) { start += njs_utf8_bom(start, end); } diff -r c15a6129ade7 -r 5d2a3da0674f src/njs_utf8.c --- a/src/njs_utf8.cMon Jan 08 22:20:10 2024 -0800 +++ b/src/njs_utf8.cMon Jan 08 22:20:19 2024 -0800 @@ -361,25 +361,27 @@ njs_utf8_stream_length(njs_unicode_decod size = 0; length = 0; -end = p + len; +if (p != NULL) { +end = p + len; + +while (p < end) { +codepoint = njs_utf8_decode(ctx, , end); -while (p < end) { -codepoint = njs_utf8_decode(ctx, , end); +if (codepoint > NJS_UNICODE_MAX_CODEPOINT) { +if (codepoint == NJS_UNICODE_CONTINUE) { +break; +} -if (codepoint > NJS_UNICODE_MAX_CODEPOINT) { -if (codepoint == NJS_UNICODE_CONTINUE) { -break; +if (fatal) { +return -1; +} + +codepoint = NJS_UNICODE_REPLACEMENT; } -if (fatal) { -return -1; -} - -codepoint = NJS_UNICODE_REPLACEMENT; +size += njs_utf8_size(codepoint); +length++; } - -size += njs_utf8_size(codepoint); -length++; } if (last && ctx->need != 0x00) { ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Avoiding casting NaN value to int64_t in njs.dump().
details: https://hg.nginx.org/njs/rev/c15a6129ade7 branches: changeset: 2260:c15a6129ade7 user: Dmitry Volyntsev date: Mon Jan 08 22:20:10 2024 -0800 description: Avoiding casting NaN value to int64_t in njs.dump(). Found by UndefinedBehaviorSanitizer. diffstat: src/njs_json.c | 10 ++ 1 files changed, 6 insertions(+), 4 deletions(-) diffs (41 lines): diff -r e2c6451435a0 -r c15a6129ade7 src/njs_json.c --- a/src/njs_json.cMon Jan 08 22:19:59 2024 -0800 +++ b/src/njs_json.cMon Jan 08 22:20:10 2024 -0800 @@ -1894,7 +1894,7 @@ njs_dump_visited(njs_vm_t *vm, njs_json_ } -njs_inline njs_bool_t +njs_inline void njs_dump_empty(njs_json_stringify_t *stringify, njs_json_state_t *state, njs_chb_t *chain, njs_bool_t sep_position) { @@ -1902,7 +1902,7 @@ njs_dump_empty(njs_json_stringify_t *str int64_t diff; if (!state->array) { -return 0; +return; } if (sep_position) { @@ -1919,6 +1919,10 @@ njs_dump_empty(njs_json_stringify_t *str } } +if (isnan(prev)) { +return; +} + if (isnan(key)) { key = state->length; } @@ -1947,8 +1951,6 @@ njs_dump_empty(njs_json_stringify_t *str njs_json_stringify_indent(stringify, chain, 1); } } - -return 1; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Avoiding pointer wraparound for padded integer specifier.
details: https://hg.nginx.org/njs/rev/e2c6451435a0 branches: changeset: 2259:e2c6451435a0 user: Dmitry Volyntsev date: Mon Jan 08 22:19:59 2024 -0800 description: Avoiding pointer wraparound for padded integer specifier. Previously, when integer was larger than the padded width in a integer specifier, the "end" pointer was evaluated to a value before "buf" pointer. Found by UndefinedBehaviorSanitizer. diffstat: src/njs_sprintf.c | 9 - 1 files changed, 4 insertions(+), 5 deletions(-) diffs (28 lines): diff -r 0490f1ae4cf5 -r e2c6451435a0 src/njs_sprintf.c --- a/src/njs_sprintf.c Sun Jul 30 10:21:51 2023 +0100 +++ b/src/njs_sprintf.c Mon Jan 08 22:19:59 2024 -0800 @@ -522,12 +522,12 @@ njs_integer(njs_sprintf_t *spf, u_char * } while (ui64 != 0); } +length = (temp + NJS_INT64_T_LEN) - p; + /* Zero or space padding. */ -if (spf->width != 0) { - -length = (temp + NJS_INT64_T_LEN) - p; -end = buf + (spf->width - length); +if (length < spf->width) { +end = buf + spf->width - length; end = njs_min(end, spf->end); while (buf < end) { @@ -537,7 +537,6 @@ njs_integer(njs_sprintf_t *spf, u_char * /* Number copying. */ -length = (temp + NJS_INT64_T_LEN) - p; end = buf + length; end = njs_min(end, spf->end); ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Ignoring UndefinedBehaviorSanitizer warnings where appropriate.
details: https://hg.nginx.org/njs/rev/0490f1ae4cf5 branches: changeset: 2258:0490f1ae4cf5 user: Dmitry Volyntsev date: Sun Jul 30 10:21:51 2023 +0100 description: Ignoring UndefinedBehaviorSanitizer warnings where appropriate. Prodded by David Carlier and Ben Kallus. diffstat: auto/clang| 11 +++ src/njs_clang.h | 25 + src/njs_number.c | 4 +++- src/njs_number.h | 2 +- src/njs_typed_array.c | 2 +- 5 files changed, 41 insertions(+), 3 deletions(-) diffs (94 lines): diff -r 275d785ab5bf -r 0490f1ae4cf5 auto/clang --- a/auto/clangMon Jan 08 16:40:42 2024 -0800 +++ b/auto/clangSun Jul 30 10:21:51 2023 +0100 @@ -161,6 +161,17 @@ njs_feature_test="int main(int argc, cha . auto/feature +njs_feature="GCC __attribute__ no_sanitize" +njs_feature_name=NJS_HAVE_GCC_ATTRIBUTE_NO_SANITIZE +njs_feature_run=no +njs_feature_path= +njs_feature_libs= +njs_feature_test="__attribute__((no_sanitize(\"undefined\"))) int main(void) { +return 0; + }" +. auto/feature + + njs_feature="Address sanitizer" njs_feature_name=NJS_HAVE_ADDRESS_SANITIZER njs_feature_run=no diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_clang.h --- a/src/njs_clang.h Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_clang.h Sun Jul 30 10:21:51 2023 +0100 @@ -183,6 +183,31 @@ njs_leading_zeros64(uint64_t x) #define njs_msan_unpoison(ptr, size) #endif +#if (NJS_HAVE_GCC_ATTRIBUTE_NO_SANITIZE) +#define NJS_NOSANITIZE(options) __attribute__((no_sanitize(options))) +#else +#define NJS_NOSANITIZE(options) +#endif + + +njs_inline NJS_NOSANITIZE("float-cast-overflow") int64_t +njs_unsafe_cast_double_to_int64(double num) +{ + /* +* Casting NaN to integer is undefined behavior, +* but it is fine in some cases where we do additional checks later. +* For example: +* int64_t i64 = njs_unsafe_cast_double_to_int64(num); +* if (i64 == num) { +*// num is integer +* } +* +* We do this as inline function to avoid UndefinedBehaviorSanitizer +* warnings. +*/ + return (int64_t) num; +} + #if (NJS_HAVE_DENORMALS_CONTROL) #include diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_number.c --- a/src/njs_number.c Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_number.c Sun Jul 30 10:21:51 2023 +0100 @@ -382,7 +382,9 @@ njs_number_is_safe_integer(njs_vm_t *vm, if (nargs > 1 && njs_is_number([1])) { num = njs_number([1]); -if (num == (int64_t) num && fabs(num) <= NJS_MAX_SAFE_INTEGER) { +if (num == njs_unsafe_cast_double_to_int64(num) +&& fabs(num) <= NJS_MAX_SAFE_INTEGER) +{ integer = 1; } } diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_number.h --- a/src/njs_number.h Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_number.h Sun Jul 30 10:21:51 2023 +0100 @@ -36,7 +36,7 @@ njs_int_t njs_number_parse_float(njs_vm_ njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); -njs_inline njs_bool_t +njs_inline NJS_NOSANITIZE("float-cast-overflow") njs_bool_t njs_number_is_integer_index(double num) { uint32_t u32; diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_typed_array.c --- a/src/njs_typed_array.c Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_typed_array.c Sun Jul 30 10:21:51 2023 +0100 @@ -1388,7 +1388,7 @@ njs_typed_array_prototype_index_of(njs_v v = njs_number(njs_argument(args, 1)); -i64 = v; +i64 = njs_unsafe_cast_double_to_int64(v); integer = (v == i64); buffer = array->buffer; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed RegExp.prototype.exec() when second argument is absent.
details: https://hg.nginx.org/njs/rev/275d785ab5bf branches: changeset: 2257:275d785ab5bf user: Dmitry Volyntsev date: Mon Jan 08 16:40:42 2024 -0800 description: Fixed RegExp.prototype.exec() when second argument is absent. Previously, when the second argument is undefined, NaN is casted to unsigned which is undefined behavior. Found by UndefinedBehaviorSanitizer. diffstat: src/njs_regexp.c | 11 +-- 1 files changed, 9 insertions(+), 2 deletions(-) diffs (28 lines): diff -r 41d0de3ad198 -r 275d785ab5bf src/njs_regexp.c --- a/src/njs_regexp.c Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_regexp.c Mon Jan 08 16:40:42 2024 -0800 @@ -1235,6 +1235,7 @@ njs_int_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { +unsigned flags; njs_int_tret; njs_value_t *r, *s; njs_value_t string_lvalue; @@ -1253,8 +1254,14 @@ njs_regexp_prototype_exec(njs_vm_t *vm, return ret; } -return njs_regexp_builtin_exec(vm, r, s, - njs_number(njs_arg(args, nargs, 2)), retval); +if (nargs > 2) { +flags = njs_number(njs_arg(args, nargs, 2)); + +} else { +flags = 0; +} + +return njs_regexp_builtin_exec(vm, r, s, flags, retval); } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed initialization of external prototypes with object entry.
details: https://hg.nginx.org/njs/rev/ee4d396aa418 branches: changeset: 2255:ee4d396aa418 user: Dmitry Volyntsev date: Mon Jan 08 16:40:42 2024 -0800 description: Fixed initialization of external prototypes with object entry. When external was NULL (for example, when .u.object.properties is not declared), an arithmetic operation was performed with NULL pointer which is undefined behavior. Found by UndefinedBehaviorSanitizer. diffstat: src/njs_extern.c | 4 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff -r c43745da92cd -r ee4d396aa418 src/njs_extern.c --- a/src/njs_extern.c Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_extern.c Mon Jan 08 16:40:42 2024 -0800 @@ -34,6 +34,10 @@ njs_external_add(njs_vm_t *vm, njs_arr_t hash = >external_shared_hash; njs_lvlhsh_init(hash); +if (n == 0) { +return NJS_OK; +} + lhq.replace = 0; lhq.proto = _object_hash_proto; lhq.pool = vm->mem_pool; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Improved array enumeration with length 0.
details: https://hg.nginx.org/njs/rev/41d0de3ad198 branches: changeset: 2256:41d0de3ad198 user: Dmitry Volyntsev date: Mon Jan 08 16:40:42 2024 -0800 description: Improved array enumeration with length 0. The fix eliminates an arithmetic operation with NULL pointer. Found by UndefinedBehaviorSanitizer. diffstat: src/njs_object.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r ee4d396aa418 -r 41d0de3ad198 src/njs_object.c --- a/src/njs_object.c Mon Jan 08 16:40:42 2024 -0800 +++ b/src/njs_object.c Mon Jan 08 16:40:42 2024 -0800 @@ -591,7 +591,7 @@ njs_object_enumerate_array(njs_vm_t *vm, njs_value_t *p, *start, *end; njs_array_t *entry; -if (!array->object.fast_array) { +if (!array->object.fast_array || array->length == 0) { return NJS_OK; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] QueryString: fixed underflow in parse().
details: https://hg.nginx.org/njs/rev/c43745da92cd branches: changeset: 2254:c43745da92cd user: Dmitry Volyntsev date: Mon Jan 08 16:40:42 2024 -0800 description: QueryString: fixed underflow in parse(). Previously, njs_query_string_append() might be provided with invalid val_size value when value in a key-value pair was absent. Found by UndefinedBehaviorSanitizer. diffstat: external/njs_query_string_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 9fadb2e9c6ea -r c43745da92cd external/njs_query_string_module.c --- a/external/njs_query_string_module.cMon Jan 08 16:40:42 2024 -0800 +++ b/external/njs_query_string_module.cMon Jan 08 16:40:42 2024 -0800 @@ -506,7 +506,7 @@ njs_query_string_parser(njs_vm_t *vm, u_ size = val - key; -if (val != end) { +if (val != part) { val += eq->length; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Fixed external values initialization in unit tests.
details: https://hg.nginx.org/njs/rev/9fadb2e9c6ea branches: changeset: 2253:9fadb2e9c6ea user: Dmitry Volyntsev date: Mon Jan 08 16:40:42 2024 -0800 description: Fixed external values initialization in unit tests. Since 0.8.0 modules can create their own constructors and prototypes. A modules has two method: preinit() and init(). A module should add its constructors and prototypes in preinit() and create its own values in init(). Creating a value in preinit() results in an error. The patch fixes the issue by creating an external value in init() instead of preinit(). Found by UndefinedBehaviorSanitizer. diffstat: src/test/njs_externals_test.c | 136 ++--- 1 files changed, 72 insertions(+), 64 deletions(-) diffs (176 lines): diff -r 721475693b80 -r 9fadb2e9c6ea src/test/njs_externals_test.c --- a/src/test/njs_externals_test.c Mon Jan 08 16:40:42 2024 -0800 +++ b/src/test/njs_externals_test.c Mon Jan 08 16:40:42 2024 -0800 @@ -28,6 +28,7 @@ typedef struct { static njs_int_t njs_externals_262_init(njs_vm_t *vm); static njs_int_t njs_externals_shared_preinit(njs_vm_t *vm); +static njs_int_t njs_externals_shared_init(njs_vm_t *vm); njs_int_t njs_array_buffer_detach(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -47,7 +48,7 @@ njs_module_t njs_unit_test_262_module = njs_module_t njs_unit_test_external_module = { .name = njs_str("external"), .preinit = njs_externals_shared_preinit, -.init = NULL, +.init = njs_externals_shared_init, }; @@ -1253,77 +1254,15 @@ njs_externals_init_internal(njs_vm_t *vm { njs_int_t ret; njs_uint_ti, j; -njs_function_t*f; -njs_opaque_value_tvalue; njs_unit_test_req_t *requests; njs_unit_test_prop_t *prop; -static const njs_str_t external_ctor = njs_str("ExternalConstructor"); -static const njs_str_t external_null = njs_str("ExternalNull"); -static const njs_str_t external_error = njs_str("ExternalError"); - -if (shared) { -njs_external_r_proto_id = njs_vm_external_prototype(vm, - njs_unit_test_r_external, - njs_nitems(njs_unit_test_r_external)); -if (njs_slow_path(njs_external_r_proto_id < 0)) { -njs_printf("njs_vm_external_prototype() failed\n"); -return NJS_ERROR; -} - -f = njs_vm_function_alloc(vm, njs_unit_test_constructor, 1, 1); -if (f == NULL) { -njs_printf("njs_vm_function_alloc() failed\n"); -return NJS_ERROR; -} - -njs_value_function_set(njs_value_arg(), f); - -ret = njs_vm_bind(vm, _ctor, njs_value_arg(), 1); -if (njs_slow_path(ret != NJS_OK)) { -njs_printf("njs_vm_bind() failed\n"); -return NJS_ERROR; -} - -njs_external_null_proto_id = njs_vm_external_prototype(vm, - njs_unit_test_null_external, - njs_nitems(njs_unit_test_null_external)); -if (njs_slow_path(njs_external_null_proto_id < 0)) { -njs_printf("njs_vm_external_prototype() failed\n"); -return NJS_ERROR; -} - -ret = njs_vm_external_create(vm, njs_value_arg(), - njs_external_null_proto_id, NULL, 1); -if (njs_slow_path(ret != NJS_OK)) { -return NJS_ERROR; -} - -ret = njs_vm_bind(vm, _null, njs_value_arg(), 1); -if (njs_slow_path(ret != NJS_OK)) { -njs_printf("njs_vm_bind() failed\n"); -return NJS_ERROR; -} - -njs_external_error_ctor_id = -njs_vm_external_constructor(vm, _error, - njs_error_constructor, njs_unit_test_ctor_props, - njs_nitems(njs_unit_test_ctor_props), - njs_unit_test_proto_props, - njs_nitems(njs_unit_test_proto_props)); -if (njs_slow_path(njs_external_error_ctor_id < 0)) { -njs_printf("njs_vm_external_constructor() failed\n"); -return NJS_ERROR; -} -} - requests = njs_mp_zalloc(vm->mem_pool, n * sizeof(njs_unit_test_req_t)); if (njs_slow_path(requests == NULL)) { return NJS_ERROR; } for (i = 0; i < n; i++) { - requests[i] = init[i].request; ret = njs_vm_external_create(vm, njs_value_arg([i].value), @@ -1396,7 +1335,76 @@ njs_externals_262_init(njs_vm_t *vm) static njs_int_t njs_externals_shared_preinit(njs_vm_t *vm) { -return njs_externals_init_internal(vm, njs_test_requests, 1, 1); +static const
[njs] Unifying hash function prototypes.
details: https://hg.nginx.org/njs/rev/721475693b80 branches: changeset: 2252:721475693b80 user: Dmitry Volyntsev date: Mon Jan 08 16:40:42 2024 -0800 description: Unifying hash function prototypes. This fixes UndefinedBehaviorSanitizer warning "call to function through pointer to incorrect function type". Found by UndefinedBehaviorSanitizer. diffstat: external/njs_crypto_module.c | 71 +-- src/njs_hash.h | 32 +++ src/njs_main.h | 4 +- src/njs_md5.c| 10 +++--- src/njs_md5.h| 23 -- src/njs_sha1.c | 10 +++--- src/njs_sha1.h | 24 -- src/njs_sha2.c | 10 +++--- src/njs_sha2.h | 24 -- 9 files changed, 77 insertions(+), 131 deletions(-) diffs (424 lines): diff -r 57071ecadeb5 -r 721475693b80 external/njs_crypto_module.c --- a/external/njs_crypto_module.c Mon Jan 08 16:40:27 2024 -0800 +++ b/external/njs_crypto_module.c Mon Jan 08 16:40:42 2024 -0800 @@ -6,16 +6,14 @@ #include -#include -#include -#include +#include #include #include -typedef void (*njs_hash_init)(void *ctx); -typedef void (*njs_hash_update)(void *ctx, const void *data, size_t size); -typedef void (*njs_hash_final)(u_char *result, void *ctx); +typedef void (*njs_hash_init)(njs_hash_t *ctx); +typedef void (*njs_hash_update)(njs_hash_t *ctx, const void *data, size_t size); +typedef void (*njs_hash_final)(u_char result[32], njs_hash_t *ctx); typedef njs_int_t (*njs_digest_encode)(njs_vm_t *vm, njs_value_t *value, const njs_str_t *src); @@ -31,24 +29,13 @@ typedef struct { } njs_hash_alg_t; typedef struct { -union { -njs_md5_t md5; -njs_sha1_t sha1; -njs_sha2_t sha2; -} u; - +njs_hash_t ctx; njs_hash_alg_t *alg; } njs_digest_t; typedef struct { u_char opad[64]; - -union { -njs_md5_t md5; -njs_sha1_t sha1; -njs_sha2_t sha2; -} u; - +njs_hash_t ctx; njs_hash_alg_t *alg; } njs_hmac_t; @@ -85,25 +72,25 @@ static njs_hash_alg_t njs_hash_algorithm { njs_str("md5"), 16, - (njs_hash_init) njs_md5_init, - (njs_hash_update) njs_md5_update, - (njs_hash_final) njs_md5_final + njs_md5_init, + njs_md5_update, + njs_md5_final }, { njs_str("sha1"), 20, - (njs_hash_init) njs_sha1_init, - (njs_hash_update) njs_sha1_update, - (njs_hash_final) njs_sha1_final + njs_sha1_init, + njs_sha1_update, + njs_sha1_final }, { njs_str("sha256"), 32, - (njs_hash_init) njs_sha2_init, - (njs_hash_update) njs_sha2_update, - (njs_hash_final) njs_sha2_final + njs_sha2_init, + njs_sha2_update, + njs_sha2_final }, { @@ -312,7 +299,7 @@ njs_crypto_create_hash(njs_vm_t *vm, njs dgst->alg = alg; -alg->init(>u); +alg->init(>ctx); return njs_vm_external_create(vm, retval, njs_crypto_hash_proto_id, dgst, 0); @@ -390,10 +377,10 @@ njs_hash_prototype_update(njs_vm_t *vm, } if (!hmac) { -dgst->alg->update(>u, data.start, data.length); +dgst->alg->update(>ctx, data.start, data.length); } else { -ctx->alg->update(>u, data.start, data.length); +ctx->alg->update(>ctx, data.start, data.length); } njs_value_assign(retval, this); @@ -450,17 +437,17 @@ njs_hash_prototype_digest(njs_vm_t *vm, if (!hmac) { alg = dgst->alg; -alg->final(digest, >u); +alg->final(digest, >ctx); dgst->alg = NULL; } else { alg = ctx->alg; -alg->final(hash1, >u); +alg->final(hash1, >ctx); -alg->init(>u); -alg->update(>u, ctx->opad, 64); -alg->update(>u, hash1, alg->size); -alg->final(digest, >u); +alg->init(>ctx); +alg->update(>ctx, ctx->opad, 64); +alg->update(>ctx, hash1, alg->size); +alg->final(digest, >ctx); ctx->alg = NULL; } @@ -562,9 +549,9 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs ctx->alg = alg; if (key.length > sizeof(key_buf)) { -alg->init(>u); -alg->update(>u, key.start, key.length); -alg->final(digest, >u); +alg->init(>ctx); +alg->update(>ctx, key.start, key.length); +alg->final(digest, >ctx); memcpy(key_buf, digest, alg->size); njs_explicit_memzero(key_buf + alg->size, sizeof(key_buf) - alg->size); @@ -583,8 +570,8 @@ njs
[njs] Fixed Date constructor for overflows and with NaN values.
details: https://hg.nginx.org/njs/rev/57071ecadeb5 branches: changeset: 2251:57071ecadeb5 user: Dmitry Volyntsev date: Mon Jan 08 16:40:27 2024 -0800 description: Fixed Date constructor for overflows and with NaN values. Found by UndefinedBehaviorSanitizer. diffstat: src/njs_date.c | 8 1 files changed, 8 insertions(+), 0 deletions(-) diffs (23 lines): diff -r 4a15613f4e8b -r 57071ecadeb5 src/njs_date.c --- a/src/njs_date.cTue Dec 19 12:37:05 2023 -0800 +++ b/src/njs_date.cMon Jan 08 16:40:27 2024 -0800 @@ -243,11 +243,19 @@ njs_make_date(int64_t tm[], njs_bool_t l days = njs_make_day(tm[NJS_DATE_YR], tm[NJS_DATE_MON], tm[NJS_DATE_DAY]); +if (njs_slow_path(isnan(days))) { +return NAN; +} + time = ((tm[NJS_DATE_HR] * 60.0 + tm[NJS_DATE_MIN]) * 60.0 + tm[NJS_DATE_SEC]) * 1000.0 + tm[NJS_DATE_MSEC]; time += days * 8640.0; +if (time < -8.64e15 || time > 8.64e15) { +return NAN; +} + if (local) { time += njs_tz_offset(time) * 6; } ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Moving out logger from njs core.
details: https://hg.nginx.org/njs/rev/fc1001f6801b branches: changeset: 2249:fc1001f6801b user: Dmitry Volyntsev date: Thu Dec 14 22:32:02 2023 -0800 description: Moving out logger from njs core. Logger is not part of the JS runtime according to ECMAScript and should be implemented by host environment. diffstat: external/njs_fs_module.c | 1 - external/njs_shell.c | 70 --- nginx/ngx_http_js_module.c | 11 +- nginx/ngx_js.c | 40 ++-- nginx/ngx_js.h | 6 ++- nginx/ngx_stream_js_module.c | 6 --- src/njs.h| 26 src/njs_builtin.c| 9 +- src/njs_vm.c | 25 --- 9 files changed, 82 insertions(+), 112 deletions(-) diffs (493 lines): diff -r ad1a7ad3c715 -r fc1001f6801b external/njs_fs_module.c --- a/external/njs_fs_module.c Wed Dec 13 18:38:47 2023 -0800 +++ b/external/njs_fs_module.c Thu Dec 14 22:32:02 2023 -0800 @@ -3668,7 +3668,6 @@ njs_fs_filehandle_cleanup(void *data) njs_filehandle_t *fh = data; if (fh->vm != NULL && fh->fd != -1) { -njs_vm_warn(fh->vm, "closing file description %d on cleanup\n", fh->fd); (void) close(fh->fd); } } diff -r ad1a7ad3c715 -r fc1001f6801b external/njs_shell.c --- a/external/njs_shell.c Wed Dec 13 18:38:47 2023 -0800 +++ b/external/njs_shell.c Thu Dec 14 22:32:02 2023 -0800 @@ -53,6 +53,13 @@ typedef struct { } njs_opts_t; +typedef enum { +NJS_LOG_ERROR = 4, +NJS_LOG_WARN = 5, +NJS_LOG_INFO = 7, +} njs_log_level_t; + + typedef struct { size_t index; size_t length; @@ -137,8 +144,9 @@ static njs_int_t njs_ext_console_time(nj static njs_int_t njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); -static void njs_console_log(njs_vm_t *vm, njs_external_ptr_t external, -njs_log_level_t level, const u_char *start, size_t length); +static void njs_console_log(njs_log_level_t level, const char *fmt, ...); +static void njs_console_logger(njs_log_level_t level, const u_char *start, +size_t length); static intptr_t njs_event_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2); @@ -159,7 +167,7 @@ static njs_external_t njs_ext_console[] .native = njs_ext_console_log, #define NJS_LOG_DUMP 16 #define NJS_LOG_MASK 15 -.magic8 = NJS_LOG_LEVEL_INFO | NJS_LOG_DUMP, +.magic8 = NJS_LOG_INFO | NJS_LOG_DUMP, } }, @@ -171,7 +179,7 @@ static njs_external_t njs_ext_console[] .enumerable = 1, .u.method = { .native = njs_ext_console_log, -.magic8 = NJS_LOG_LEVEL_ERROR, +.magic8 = NJS_LOG_ERROR, } }, @@ -183,7 +191,7 @@ static njs_external_t njs_ext_console[] .enumerable = 1, .u.method = { .native = njs_ext_console_log, -.magic8 = NJS_LOG_LEVEL_INFO, +.magic8 = NJS_LOG_INFO, } }, @@ -195,7 +203,7 @@ static njs_external_t njs_ext_console[] .enumerable = 1, .u.method = { .native = njs_ext_console_log, -.magic8 = NJS_LOG_LEVEL_INFO, +.magic8 = NJS_LOG_INFO, } }, @@ -237,7 +245,7 @@ static njs_external_t njs_ext_console[] .enumerable = 1, .u.method = { .native = njs_ext_console_log, -.magic8 = NJS_LOG_LEVEL_WARN, +.magic8 = NJS_LOG_WARN, } }, @@ -268,11 +276,6 @@ static njs_external_t njs_ext_262[] = { }; -static njs_vm_ops_t njs_console_ops = { -njs_console_log, -}; - - njs_module_t njs_console_module = { .name = njs_str("console"), .preinit = NULL, @@ -776,7 +779,6 @@ njs_create_vm(njs_opts_t *opts) vm_options.opcode_debug = opts->opcode_debug; #endif -vm_options.ops = _console_ops; vm_options.addons = njs_console_addon_modules; vm_options.external = _console; vm_options.argv = opts->argv; @@ -1419,7 +1421,7 @@ njs_ext_console_log(njs_vm_t *vm, njs_va return NJS_ERROR; } -njs_vm_logger(vm, level, "%*s\n", msg.length, msg.start); +njs_console_logger(level, msg.start, msg.length); n++; } @@ -1475,7 +1477,8 @@ njs_ext_console_time(njs_vm_t *vm, njs_v label = njs_queue_link_data(link, njs_timelabel_t, link); if (njs_strstr_eq(, >name)) { -njs_vm_log(vm, "Timer \"%V\" already exists.\n", ); +njs_console_log(NJS_LOG_INFO, "Timer \"%V\" already exists.", +); njs_value_undefined_set(retval); return NJS_OK; } @@ -1546,7 +1549,8 @@ n
[njs] Introduced njs_vm_set_module_loader().
details: https://hg.nginx.org/njs/rev/ad1a7ad3c715 branches: changeset: 2248:ad1a7ad3c715 user: Dmitry Volyntsev date: Wed Dec 13 18:38:47 2023 -0800 description: Introduced njs_vm_set_module_loader(). diffstat: external/njs_shell.c | 1 - nginx/ngx_http_js_module.c | 1 - nginx/ngx_stream_js_module.c | 1 - src/njs.h| 3 ++- src/njs_module.c | 6 +++--- src/njs_vm.c | 9 + src/njs_vm.h | 3 +++ 7 files changed, 17 insertions(+), 7 deletions(-) diffs (101 lines): diff -r 34df3f0796cf -r ad1a7ad3c715 external/njs_shell.c --- a/external/njs_shell.c Mon Dec 11 19:10:38 2023 -0800 +++ b/external/njs_shell.c Wed Dec 13 18:38:47 2023 -0800 @@ -269,7 +269,6 @@ static njs_external_t njs_ext_262[] = { static njs_vm_ops_t njs_console_ops = { -NULL, njs_console_log, }; diff -r 34df3f0796cf -r ad1a7ad3c715 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.cMon Dec 11 19:10:38 2023 -0800 +++ b/nginx/ngx_http_js_module.cWed Dec 13 18:38:47 2023 -0800 @@ -840,7 +840,6 @@ static njs_external_t ngx_http_js_ext_p static njs_vm_ops_t ngx_http_js_ops = { -NULL, ngx_js_logger, }; diff -r 34df3f0796cf -r ad1a7ad3c715 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Dec 11 19:10:38 2023 -0800 +++ b/nginx/ngx_stream_js_module.c Wed Dec 13 18:38:47 2023 -0800 @@ -609,7 +609,6 @@ static njs_external_t ngx_stream_js_ext static njs_vm_ops_t ngx_stream_js_ops = { -NULL, ngx_js_logger, }; diff -r 34df3f0796cf -r ad1a7ad3c715 src/njs.h --- a/src/njs.h Mon Dec 11 19:10:38 2023 -0800 +++ b/src/njs.h Wed Dec 13 18:38:47 2023 -0800 @@ -214,7 +214,6 @@ typedef void (*njs_logger_t)(njs_vm_t *v typedef struct { -njs_module_loader_t module_loader; njs_logger_tlogger; } njs_vm_ops_t; @@ -310,6 +309,8 @@ NJS_EXPORT njs_vm_t *njs_vm_create(njs_v NJS_EXPORT void njs_vm_destroy(njs_vm_t *vm); NJS_EXPORT njs_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end); +NJS_EXPORT void njs_vm_set_module_loader(njs_vm_t *vm, +njs_module_loader_t module_loader, void *opaque); NJS_EXPORT njs_mod_t *njs_vm_add_module(njs_vm_t *vm, njs_str_t *name, njs_value_t *value); NJS_EXPORT njs_mod_t *njs_vm_compile_module(njs_vm_t *vm, njs_str_t *name, diff -r 34df3f0796cf -r ad1a7ad3c715 src/njs_module.c --- a/src/njs_module.c Mon Dec 11 19:10:38 2023 -0800 +++ b/src/njs_module.c Wed Dec 13 18:38:47 2023 -0800 @@ -48,9 +48,9 @@ njs_parser_module(njs_parser_t *parser, external = parser; loader = njs_default_module_loader; -if (vm->options.ops != NULL && vm->options.ops->module_loader != NULL) { -loader = vm->options.ops->module_loader; -external = vm->external; +if (vm->module_loader != NULL) { +loader = vm->module_loader; +external = vm->module_loader_opaque; } module = loader(vm, external, name); diff -r 34df3f0796cf -r ad1a7ad3c715 src/njs_vm.c --- a/src/njs_vm.c Mon Dec 11 19:10:38 2023 -0800 +++ b/src/njs_vm.c Wed Dec 13 18:38:47 2023 -0800 @@ -730,6 +730,15 @@ njs_vm_execute_pending_job(njs_vm_t *vm) } +void +njs_vm_set_module_loader(njs_vm_t *vm, njs_module_loader_t module_loader, +void *opaque) +{ +vm->module_loader = module_loader; +vm->module_loader_opaque = opaque; +} + + njs_int_t njs_vm_add_path(njs_vm_t *vm, const njs_str_t *path) { diff -r 34df3f0796cf -r ad1a7ad3c715 src/njs_vm.h --- a/src/njs_vm.h Mon Dec 11 19:10:38 2023 -0800 +++ b/src/njs_vm.h Wed Dec 13 18:38:47 2023 -0800 @@ -182,6 +182,9 @@ struct njs_vm_s { njs_rbtree_t global_symbols; uint64_t symbol_generator; + +njs_module_loader_t module_loader; +void *module_loader_opaque; }; ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel
[njs] Refactored asynchronous events.
details: https://hg.nginx.org/njs/rev/bc80bcb3102c branches: changeset: 2245:bc80bcb3102c user: Dmitry Volyntsev date: Tue Dec 05 08:54:18 2023 -0800 description: Refactored asynchronous events. To align njs with other JS engines, async events are removed from njs core. The following functions were removed: njs_vm_add_event(), njs_vm_del_event(), njs_vm_waiting(). Instead the host is expected to manage async events by itself. In addition, the posted events are renamed to jobs, to better align with the ECMA specs. The following methods are removed: njs_vm_run(). Instead, the host is expected to call njs_vm_execute_pending_job() in a loop to execute pending jobs. The following functions were added: njs_vm_enqueue_job(). diffstat: auto/sources|1 - external/njs_fs_module.c| 17 +-- external/njs_shell.c| 16 ++- external/njs_webcrypto_module.c |8 +- nginx/ngx_http_js_module.c | 99 +++--- nginx/ngx_js.c | 107 nginx/ngx_js.h | 33 - nginx/ngx_js_fetch.c| 59 ++ nginx/ngx_stream_js_module.c| 133 + src/njs.h | 59 +-- src/njs_event.c | 95 -- src/njs_event.h | 24 src/njs_promise.c | 39 +-- src/njs_vm.c| 208 ++- src/njs_vm.h|4 +- src/test/njs_externals_test.c | 35 -- src/test/njs_externals_test.h |2 +- src/test/njs_unit_test.c| 24 ++- 18 files changed, 329 insertions(+), 634 deletions(-) diffs (truncated from 1774 to 1000 lines): diff -r 439ea33e531c -r bc80bcb3102c auto/sources --- a/auto/sources Wed Nov 29 20:46:36 2023 -0800 +++ b/auto/sources Tue Dec 05 08:54:18 2023 -0800 @@ -34,7 +34,6 @@ NJS_LIB_SRCS=" \ src/njs_generator.c \ src/njs_disassembler.c \ src/njs_module.c \ - src/njs_event.c \ src/njs_extern.c \ src/njs_boolean.c \ src/njs_number.c \ diff -r 439ea33e531c -r bc80bcb3102c external/njs_fs_module.c --- a/external/njs_fs_module.c Wed Nov 29 20:46:36 2023 -0800 +++ b/external/njs_fs_module.c Tue Dec 05 08:54:18 2023 -0800 @@ -3264,7 +3264,6 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v const njs_value_t *callback, njs_uint_t nargs, njs_value_t *retval) { njs_int_t ret; -njs_vm_event_t vm_event; njs_function_t *cb; njs_opaque_value_t promise, callbacks[2], arguments[2]; @@ -3290,16 +3289,11 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v return NJS_ERROR; } -vm_event = njs_vm_add_event(vm, cb, 1, NULL, NULL); -if (njs_slow_path(vm_event == NULL)) { -return NJS_ERROR; -} - njs_value_assign([0], [njs_value_is_error(njs_value_arg(result))]); njs_value_assign([1], result); -ret = njs_vm_post_event(vm, vm_event, njs_value_arg(), 2); +ret = njs_vm_enqueue_job(vm, cb, njs_value_arg(), 2); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } @@ -3318,13 +3312,8 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v njs_value_assign([1], result); } -vm_event = njs_vm_add_event(vm, njs_value_function(callback), 1, NULL, -NULL); -if (njs_slow_path(vm_event == NULL)) { -return NJS_ERROR; -} - -ret = njs_vm_post_event(vm, vm_event, njs_value_arg(), 2); +ret = njs_vm_enqueue_job(vm, njs_value_function(callback), + njs_value_arg(), 2); if (njs_slow_path(ret == NJS_ERROR)) { return NJS_ERROR; } diff -r 439ea33e531c -r bc80bcb3102c external/njs_shell.c --- a/external/njs_shell.c Wed Nov 29 20:46:36 2023 -0800 +++ b/external/njs_shell.c Tue Dec 05 08:54:18 2023 -0800 @@ -1096,12 +1096,18 @@ njs_process_script(njs_vm_t *vm, void *r } for ( ;; ) { -ret = njs_vm_run(vm); -if (ret == NJS_ERROR) { -njs_process_output(vm, njs_value_arg(), ret); +for ( ;; ) { +ret = njs_vm_execute_pending_job(vm); +if (ret <= NJS_OK) { +if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) { +njs_process_output(vm, NULL, ret); -if (!njs_vm_options(vm)->interactive) { -return NJS_ERROR; +if (!njs_vm_options(vm)->interactive) { +return NJS_ERROR; +} +} + +break; } } diff -r 439ea33e531c -r bc80bcb3102c external/njs_webcrypto_module.c --- a/external/njs_webcrypto_module.c Wed Nov 29 20:46:36 2023 -0800 +++ b/external/njs_webcrypto_module.c Tue D
[njs] Modules: simplified setTimeout() timer callback.
details: https://hg.nginx.org/njs/rev/f64d1f9f19e5 branches: changeset: 2242:f64d1f9f19e5 user: Dmitry Volyntsev date: Wed Nov 29 18:43:45 2023 -0800 description: Modules: simplified setTimeout() timer callback. diffstat: nginx/ngx_js.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diffs (19 lines): diff -r 9a6a79e21822 -r f64d1f9f19e5 nginx/ngx_js.c --- a/nginx/ngx_js.cWed Nov 29 18:43:37 2023 -0800 +++ b/nginx/ngx_js.cWed Nov 29 18:43:45 2023 -0800 @@ -973,14 +973,12 @@ ngx_js_timer_handler(ngx_event_t *ev) ngx_js_event_t *event; ngx_connection_t*c; njs_external_ptr_t external; -njs_opaque_value_t retval; event = (ngx_js_event_t *) ((u_char *) ev - offsetof(ngx_js_event_t, ev)); vm = event->vm; -ret = njs_vm_invoke(vm, event->function, event->args, event->nargs, -njs_value_arg()); +ret = njs_vm_call(vm, event->function, event->args, event->nargs); external = njs_vm_external_ptr(vm); ctx = ngx_external_ctx(vm, external); ___ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel