details: https://hg.nginx.org/njs/rev/5e7fc8efebdc branches: changeset: 2077:5e7fc8efebdc user: Dmitry Volyntsev <xei...@nginx.com> date: Mon Mar 27 22:41:27 2023 -0700 description: Added "zlib" module.
- zlib.deflateRawSync(string|buffer, options?) compresses data using deflate, and do not append a zlib header, returns Buffer. - zlib.deflateSync(string|buffer, options?) compresses data using deflate, returns Buffer. - zlib.inflateRawSync(string|buffer) decompresses a raw deflate stream, returns Buffer. - zlib.inflateSync(string|buffer) decompresses a deflate stream, return Buffer. diffstat: auto/help | 4 + auto/modules | 8 + auto/options | 2 + auto/summary | 4 + auto/zlib | 61 ++++ configure | 1 + external/njs_zlib_module.c | 566 +++++++++++++++++++++++++++++++++++++++++++++ nginx/config | 5 +- nginx/config.make | 2 +- nginx/ngx_js.c | 2 + src/test/njs_unit_test.c | 79 ++++++ 11 files changed, 731 insertions(+), 3 deletions(-) diffs (867 lines): diff -r ec007866a53b -r 5e7fc8efebdc auto/help --- a/auto/help Wed Mar 22 15:22:37 2023 +0200 +++ b/auto/help Mon Mar 27 22:41:27 2023 -0700 @@ -39,6 +39,10 @@ default: "$NJS_LD_OPT" 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. + --address-sanitizer=YES enables build with address sanitizer, \ default: "$NJS_ADDRESS_SANITIZER" --addr2line=YES enables native function symbolization, \ diff -r ec007866a53b -r 5e7fc8efebdc auto/modules --- a/auto/modules Wed Mar 22 15:22:37 2023 +0200 +++ b/auto/modules Mon Mar 27 22:41:27 2023 -0700 @@ -29,6 +29,14 @@ if [ $NJS_LIBXML2 = YES -a $NJS_HAVE_LIB . auto/module fi +if [ $NJS_ZLIB = YES -a $NJS_HAVE_ZLIB = YES ]; then + njs_module_name=njs_zlib_module + njs_module_incs= + njs_module_srcs=external/njs_zlib_module.c + + . auto/module +fi + njs_module_name=njs_fs_module njs_module_incs= njs_module_srcs=external/njs_fs_module.c diff -r ec007866a53b -r 5e7fc8efebdc auto/options --- a/auto/options Wed Mar 22 15:22:37 2023 +0200 +++ b/auto/options Mon Mar 27 22:41:27 2023 -0700 @@ -17,6 +17,7 @@ NJS_TEST262=YES NJS_OPENSSL=YES NJS_LIBXML2=YES +NJS_ZLIB=YES NJS_PCRE=YES NJS_TRY_PCRE2=YES @@ -50,6 +51,7 @@ do --no-openssl) NJS_OPENSSL=NO ;; --no-libxml2) NJS_LIBXML2=NO ;; + --no-zlib) NJS_ZLIB=NO ;; --no-pcre) NJS_PCRE=NO ;; --no-pcre2) NJS_TRY_PCRE2=NO ;; diff -r ec007866a53b -r 5e7fc8efebdc auto/summary --- a/auto/summary Wed Mar 22 15:22:37 2023 +0200 +++ b/auto/summary Mon Mar 27 22:41:27 2023 -0700 @@ -26,6 +26,10 @@ if [ $NJS_HAVE_LIBXML2 = YES ]; then echo " + using libxml2 library: $NJS_LIBXML2_LIB" fi +if [ $NJS_HAVE_ZLIB = YES ]; then + echo " + using zlib library: $NJS_ZLIB_LIB" +fi + if [ $NJS_HAVE_COMPUTED_GOTO = YES ]; then echo " + using computed goto" fi diff -r ec007866a53b -r 5e7fc8efebdc auto/zlib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/zlib Mon Mar 27 22:41:27 2023 -0700 @@ -0,0 +1,61 @@ + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +NJS_ZLIB_LIB= +NJS_HAVE_ZLIB=NO + +if [ $NJS_ZLIB = YES ]; then + njs_found=no + njs_feature_name=NJS_HAVE_ZLIB + njs_feature_run=no + njs_feature_test="#include <zlib.h> + + int main() { + int rc; + z_stream z; + + rc = deflate(&z, Z_NO_FLUSH); + + return (rc == Z_OK) ? 0 : 1; + }" + + + if /bin/sh -c "(pkg-config zlib --exists)" >> $NJS_AUTOCONF_ERR 2>&1; then + + # pkg-config + + njs_feature="zlib via pkg-config" + njs_feature_incs=`pkg-config zlib --cflags | sed -n -e 's/.*-I *\([^ ][^ ]*\).*/\1/p'` + njs_feature_libs=`pkg-config zlib --libs` + + . auto/feature + fi + + if [ $njs_found = no ]; then + + njs_feature="zlib" + njs_feature_libs="-lz" + + . auto/feature + fi + + if [ $njs_found = yes ]; then + njs_feature="zlib version" + njs_feature_name=NJS_ZLIB_VERSION + njs_feature_run=value + njs_feature_test="#include <stdio.h> + #include <zlib.h> + + int main() { + printf(\"\\\"%s\\\"\", zlibVersion()); + return 0; + }" + . auto/feature + + NJS_HAVE_ZLIB=YES + NJS_ZLIB_LIB="$njs_feature_libs" + NJS_LIB_INCS="$NJS_LIB_INCS $njs_feature_incs" + NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $njs_feature_libs" + fi +fi diff -r ec007866a53b -r 5e7fc8efebdc configure --- a/configure Wed Mar 22 15:22:37 2023 +0200 +++ b/configure Mon Mar 27 22:41:27 2023 -0700 @@ -52,6 +52,7 @@ NJS_LIB_AUX_LIBS= . auto/readline . auto/openssl . auto/libxml2 +. auto/zlib . auto/libbfd . auto/link diff -r ec007866a53b -r 5e7fc8efebdc external/njs_zlib_module.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/external/njs_zlib_module.c Mon Mar 27 22:41:27 2023 -0700 @@ -0,0 +1,566 @@ +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + + +#include <njs.h> +#include <string.h> +#include <zlib.h> + +#define NJS_ZLIB_CHUNK_SIZE 1024 + +static njs_int_t njs_zlib_ext_deflate(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused); +static njs_int_t njs_zlib_ext_inflate(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused); +njs_int_t njs_zlib_contant(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t njs_zlib_init(njs_vm_t *vm); +static void *njs_zlib_alloc(void *opaque, u_int items, u_int size); +static void njs_zlib_free(void *opaque, void *address); + + +static njs_external_t njs_ext_zlib_constants[] = { + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_NO_COMPRESSION"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_NO_COMPRESSION, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_BEST_SPEED"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_BEST_SPEED, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_BEST_COMPRESSION"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_BEST_COMPRESSION, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_FILTERED"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_FILTERED, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_HUFFMAN_ONLY"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_HUFFMAN_ONLY, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_RLE"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_RLE, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_FIXED"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_FIXED, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("Z_DEFAULT_STRATEGY"), + .enumerable = 1, + .u.property = { + .handler = njs_zlib_contant, + .magic32 = Z_DEFAULT_STRATEGY, + } + }, + +}; + + +static njs_external_t njs_ext_zlib[] = { + + { + .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL, + .name.symbol = NJS_SYMBOL_TO_STRING_TAG, + .u.property = { + .value = "zlib", + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("deflateRawSync"), + .writable = 1, + .configurable = 1, + .u.method = { + .native = njs_zlib_ext_deflate, + .magic8 = 1, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("deflateSync"), + .writable = 1, + .configurable = 1, + .u.method = { + .native = njs_zlib_ext_deflate, + .magic8 = 0, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("inflateRawSync"), + .writable = 1, + .configurable = 1, + .u.method = { + .native = njs_zlib_ext_inflate, + .magic8 = 1, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("inflateSync"), + .writable = 1, + .configurable = 1, + .u.method = { + .native = njs_zlib_ext_inflate, + .magic8 = 0, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("constants"), + .writable = 1, + .configurable = 1, + .u.object = { + .properties = njs_ext_zlib_constants, + .nproperties = njs_nitems(njs_ext_zlib_constants), + } + }, + +}; + + +njs_module_t njs_zlib_module = { + .name = njs_str("zlib"), + .init = njs_zlib_init, +}; + + +static njs_int_t +njs_zlib_ext_deflate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t raw) +{ + int rc, level, mem_level, strategy, window_bits; + u_char *buffer; + size_t chunk_size; + ssize_t size; + njs_chb_t chain; + z_stream stream; + njs_int_t ret; + njs_str_t data, dictionary; + njs_value_t *options, *value; + njs_opaque_value_t lvalue; + + static const njs_str_t chunk_size_key = njs_str("chunkSize"); + static const njs_str_t dict_key = njs_str("dictionary"); + static const njs_str_t level_key = njs_str("level"); + static const njs_str_t mem_level_key = njs_str("memLevel"); + static const njs_str_t strategy_key = njs_str("strategy"); + static const njs_str_t window_bits_key = njs_str("windowBits"); + + ret = njs_vm_value_to_bytes(vm, &data, njs_arg(args, nargs, 1)); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + chunk_size = NJS_ZLIB_CHUNK_SIZE; + dictionary.start = NULL; + mem_level = 8; + level = Z_DEFAULT_COMPRESSION; + strategy = Z_DEFAULT_STRATEGY; + window_bits = raw ? -MAX_WBITS : MAX_WBITS; + + options = njs_arg(args, nargs, 2); + + if (njs_value_is_object(options)) { + value = njs_vm_object_prop(vm, options, &chunk_size_key, &lvalue); + if (value != NULL) { + chunk_size = njs_value_number(value); + + if (njs_slow_path(chunk_size < 64)) { + njs_vm_error(vm, "chunkSize must be >= 64"); + return NJS_ERROR; + } + } + + value = njs_vm_object_prop(vm, options, &level_key, &lvalue); + if (value != NULL) { + level = njs_value_number(value); + + if (njs_slow_path(level < Z_DEFAULT_COMPRESSION + || level > Z_BEST_COMPRESSION)) + { + njs_vm_error(vm, "level must be in the range %d..%d", + Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); + return NJS_ERROR; + } + } + + value = njs_vm_object_prop(vm, options, &window_bits_key, &lvalue); + if (value != NULL) { + window_bits = njs_value_number(value); + + if (raw) { + if (njs_slow_path(window_bits < -15 || window_bits > -9)) { + njs_vm_error(vm, "windowBits must be in the range -15..-9"); + return NJS_ERROR; + } + + } else { + if (njs_slow_path(window_bits < 9 || window_bits > 15)) { + njs_vm_error(vm, "windowBits must be in the range 9..15"); + return NJS_ERROR; + } + } + } + + value = njs_vm_object_prop(vm, options, &mem_level_key, &lvalue); + if (value != NULL) { + mem_level = njs_value_number(value); + + if (njs_slow_path(mem_level < 1 || mem_level > 9)) { + njs_vm_error(vm, "memLevel must be in the range 0..9"); + return NJS_ERROR; + } + } + + value = njs_vm_object_prop(vm, options, &strategy_key, &lvalue); + if (value != NULL) { + strategy = njs_value_number(value); + + switch (strategy) { + case Z_FILTERED: + case Z_HUFFMAN_ONLY: + case Z_RLE: + case Z_FIXED: + case Z_DEFAULT_STRATEGY: + break; + + default: + njs_vm_error(vm, "unknown strategy: %d", strategy); + return NJS_ERROR; + } + } + + value = njs_vm_object_prop(vm, options, &dict_key, &lvalue); + if (value != NULL) { + ret = njs_vm_value_to_bytes(vm, &dictionary, value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } + } + + stream.next_in = data.start; + stream.avail_in = data.length; + + stream.zalloc = njs_zlib_alloc; + stream.zfree = njs_zlib_free; + stream.opaque = njs_vm_memory_pool(vm); + + rc = deflateInit2(&stream, level, Z_DEFLATED, window_bits, mem_level, + strategy); + if (njs_slow_path(rc != Z_OK)) { + njs_vm_error(vm, "deflateInit2() failed"); + return NJS_ERROR; + } + + if (dictionary.start != NULL) { + rc = deflateSetDictionary(&stream, dictionary.start, dictionary.length); + if (njs_slow_path(rc != Z_OK)) { + njs_vm_error(vm, "deflateSetDictionary() failed"); + return NJS_ERROR; + } + } + + njs_chb_init(&chain, njs_vm_memory_pool(vm)); + + do { + stream.next_out = njs_chb_reserve(&chain, chunk_size); + if (njs_slow_path(stream.next_out == NULL)) { + njs_vm_memory_error(vm); + goto fail; + } + + stream.avail_out = chunk_size; + + rc = deflate(&stream, Z_FINISH); + if (njs_slow_path(rc < 0)) { + njs_vm_error(vm, "failed to deflate the data: %s", stream.msg); + goto fail; + } + + njs_chb_written(&chain, chunk_size - stream.avail_out); + + } while (stream.avail_out == 0); + + deflateEnd(&stream); + + size = njs_chb_size(&chain); + if (njs_slow_path(size < 0)) { + njs_vm_memory_error(vm); + return NJS_ERROR; + } + + buffer = njs_mp_alloc(njs_vm_memory_pool(vm), size); + if (njs_slow_path(buffer == NULL)) { + return NJS_ERROR; + } + + njs_chb_join_to(&chain, buffer); + + njs_chb_destroy(&chain); + + return njs_vm_value_buffer_set(vm, njs_vm_retval(vm), buffer, size); + +fail: + + deflateEnd(&stream); + njs_chb_destroy(&chain); + + return NJS_ERROR; +} + + +static njs_int_t +njs_zlib_ext_inflate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t raw) +{ + int rc, window_bits; + u_char *buffer; + size_t chunk_size; + ssize_t size; + njs_chb_t chain; + z_stream stream; + njs_int_t ret; + njs_str_t data, dictionary; + njs_value_t *options, *value; + njs_opaque_value_t lvalue; + + static const njs_str_t chunk_size_key = njs_str("chunkSize"); + static const njs_str_t dict_key = njs_str("dictionary"); + static const njs_str_t window_bits_key = njs_str("windowBits"); + + ret = njs_vm_value_to_bytes(vm, &data, njs_arg(args, nargs, 1)); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + chunk_size = NJS_ZLIB_CHUNK_SIZE; + dictionary.start = NULL; + window_bits = raw ? -MAX_WBITS : MAX_WBITS; + + options = njs_arg(args, nargs, 2); + + if (njs_value_is_object(options)) { + value = njs_vm_object_prop(vm, options, &chunk_size_key, &lvalue); + if (value != NULL) { + chunk_size = njs_value_number(value); + + if (njs_slow_path(chunk_size < 64)) { + njs_vm_error(vm, "chunkSize must be >= 64"); + return NJS_ERROR; + } + } + + value = njs_vm_object_prop(vm, options, &window_bits_key, &lvalue); + if (value != NULL) { + window_bits = njs_value_number(value); + + if (raw) { + if (njs_slow_path(window_bits < -15 || window_bits > -8)) { + njs_vm_error(vm, "windowBits must be in the range -15..-8"); + return NJS_ERROR; + } + + } else { + if (njs_slow_path(window_bits < 8 || window_bits > 15)) { + njs_vm_error(vm, "windowBits must be in the range 8..15"); + return NJS_ERROR; + } + } + } + + value = njs_vm_object_prop(vm, options, &dict_key, &lvalue); + if (value != NULL) { + ret = njs_vm_value_to_bytes(vm, &dictionary, value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + } + } + + stream.next_in = data.start; + stream.avail_in = data.length; + + stream.zalloc = njs_zlib_alloc; + stream.zfree = njs_zlib_free; + stream.opaque = njs_vm_memory_pool(vm); + + rc = inflateInit2(&stream, window_bits); + if (njs_slow_path(rc != Z_OK)) { + njs_vm_error(vm, "inflateInit2() failed"); + return NJS_ERROR; + } + + if (dictionary.start != NULL) { + rc = inflateSetDictionary(&stream, dictionary.start, dictionary.length); + if (njs_slow_path(rc != Z_OK)) { + njs_vm_error(vm, "deflateSetDictionary() failed"); + return NJS_ERROR; + } + } + + njs_chb_init(&chain, njs_vm_memory_pool(vm)); + + while (stream.avail_in > 0) { + stream.next_out = njs_chb_reserve(&chain, chunk_size); + if (njs_slow_path(stream.next_out == NULL)) { + njs_vm_memory_error(vm); + goto fail; + } + + stream.avail_out = chunk_size; + + rc = inflate(&stream, Z_NO_FLUSH); + if (njs_slow_path(rc < 0)) { + njs_vm_error(vm, "failed to inflate the compressed data: %s", + stream.msg); + goto fail; + } + + if (rc == Z_NEED_DICT) { + njs_vm_error(vm, "failed to inflate, dictionary is required"); + goto fail; + } + + njs_chb_written(&chain, chunk_size - stream.avail_out); + } + + rc = inflateEnd(&stream); + if (njs_slow_path(rc != Z_OK)) { + njs_vm_error(vm, "failed to end the inflate stream"); + return NJS_ERROR; + } + + size = njs_chb_size(&chain); + if (njs_slow_path(size < 0)) { + njs_vm_memory_error(vm); + return NJS_ERROR; + } + + buffer = njs_mp_alloc(njs_vm_memory_pool(vm), size); + if (njs_slow_path(buffer == NULL)) { + return NJS_ERROR; + } + + njs_chb_join_to(&chain, buffer); + + njs_chb_destroy(&chain); + + return njs_vm_value_buffer_set(vm, njs_vm_retval(vm), buffer, size); + +fail: + + inflateEnd(&stream); + njs_chb_destroy(&chain); + + return NJS_ERROR; +} + + +njs_int_t +njs_zlib_contant(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_value_number_set(retval, njs_vm_prop_magic32(prop)); + + return NJS_OK; +} + + +static njs_int_t +njs_zlib_init(njs_vm_t *vm) +{ + njs_int_t ret, proto_id; + njs_mod_t *module; + njs_opaque_value_t value; + + proto_id = njs_vm_external_prototype(vm, njs_ext_zlib, + njs_nitems(njs_ext_zlib)); + if (njs_slow_path(proto_id < 0)) { + return NJS_ERROR; + } + + ret = njs_vm_external_create(vm, njs_value_arg(&value), proto_id, NULL, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + module = njs_vm_add_module(vm, &njs_str_value("zlib"), + njs_value_arg(&value)); + if (njs_slow_path(module == NULL)) { + return NJS_ERROR; + } + + return NJS_OK; +} + + +static void * +njs_zlib_alloc(void *opaque, u_int items, u_int size) +{ + return njs_mp_alloc(opaque, items * size); +} + + +static void +njs_zlib_free(void *opaque, void *address) +{ + /* Do nothing. */ +} + diff -r ec007866a53b -r 5e7fc8efebdc nginx/config --- a/nginx/config Wed Mar 22 15:22:37 2023 +0200 +++ b/nginx/config Mon Mar 27 22:41:27 2023 -0700 @@ -6,6 +6,7 @@ NJS_SRCS="$ngx_addon_dir/ngx_js.c \ $ngx_addon_dir/ngx_js_fetch.c \ $ngx_addon_dir/ngx_js_regex.c \ $ngx_addon_dir/../external/njs_webcrypto_module.c + $ngx_addon_dir/../external/njs_zlib_module.c $ngx_addon_dir/../external/njs_xml_module.c" if [ $HTTP != NO ]; then @@ -14,7 +15,7 @@ if [ $HTTP != NO ]; then ngx_module_incs="$ngx_addon_dir/../src $ngx_addon_dir/../build" ngx_module_deps="$ngx_addon_dir/../build/libnjs.a $NJS_DEPS" ngx_module_srcs="$ngx_addon_dir/ngx_http_js_module.c $NJS_SRCS" - ngx_module_libs="PCRE OPENSSL LIBXSLT $ngx_addon_dir/../build/libnjs.a -lm" + ngx_module_libs="PCRE OPENSSL ZLIB LIBXSLT $ngx_addon_dir/../build/libnjs.a -lm" . auto/module @@ -29,7 +30,7 @@ if [ $STREAM != NO ]; then ngx_module_incs="$ngx_addon_dir/../src $ngx_addon_dir/../build" ngx_module_deps="$ngx_addon_dir/../build/libnjs.a $NJS_DEPS" ngx_module_srcs="$ngx_addon_dir/ngx_stream_js_module.c $NJS_SRCS" - ngx_module_libs="PCRE OPENSSL LIBXSLT $ngx_addon_dir/../build/libnjs.a -lm" + ngx_module_libs="PCRE OPENSSL ZLIB LIBXSLT $ngx_addon_dir/../build/libnjs.a -lm" . auto/module fi diff -r ec007866a53b -r 5e7fc8efebdc nginx/config.make --- a/nginx/config.make Wed Mar 22 15:22:37 2023 +0200 +++ b/nginx/config.make Mon Mar 27 22:41:27 2023 -0700 @@ -3,7 +3,7 @@ cat << END $ngx_addon_dir/../build/libnjs.a: $NGX_MAKEFILE cd $ngx_addon_dir/.. \\ && if [ -f build/Makefile ]; then \$(MAKE) clean; fi \\ - && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl --no-libxml2 --no-pcre \\ + && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl --no-libxml2 --no-zlib --no-pcre \\ && \$(MAKE) libnjs END diff -r ec007866a53b -r 5e7fc8efebdc nginx/ngx_js.c --- a/nginx/ngx_js.c Wed Mar 22 15:22:37 2023 +0200 +++ b/nginx/ngx_js.c Mon Mar 27 22:41:27 2023 -0700 @@ -19,6 +19,7 @@ static void ngx_js_cleanup_vm(void *data extern njs_module_t njs_webcrypto_module; extern njs_module_t njs_xml_module; +extern njs_module_t njs_zlib_module; static njs_external_t ngx_js_ext_core[] = { @@ -89,6 +90,7 @@ static njs_external_t ngx_js_ext_core[] njs_module_t *njs_js_addon_modules[] = { &njs_webcrypto_module, &njs_xml_module, + &njs_zlib_module, NULL, }; diff -r ec007866a53b -r 5e7fc8efebdc src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Mar 22 15:22:37 2023 +0200 +++ b/src/test/njs_unit_test.c Mon Mar 27 22:41:27 2023 -0700 @@ -22153,6 +22153,74 @@ static njs_unit_test_t njs_xml_test[] = }; +static njs_unit_test_t njs_zlib_test[] = +{ + { njs_str("const zlib = require('zlib');" + "['C3f0dgQA', 'O7fx3KZzmwE=']" + ".map(v => zlib.inflateRawSync(Buffer.from(v, 'base64')).toString())"), + njs_str("WAKA,αβγ") }, + + { njs_str("const zlib = require('zlib');" + "['eJwLd/R2BAAC+gEl', 'eJw7t/HcpnObAQ/sBIE=']" + ".map(v => zlib.inflateSync(Buffer.from(v, 'base64')).toString())"), + njs_str("WAKA,αβγ") }, + + { njs_str("const zlib = require('zlib');" + "['WAKA', 'αβγ']" + ".map(v => zlib.deflateRawSync(v).toString('base64'))"), + njs_str("C3f0dgQA,O7fx3KZzmwE=") }, + + { njs_str("const zlib = require('zlib');" + "['WAKA', 'αβγ']" + ".map(v => zlib.deflateRawSync(v, {dictionary: Buffer.from('WAKA')}).toString('base64'))"), + njs_str("CwdiAA==,O7fx3KZzmwE=") }, + + { njs_str("const zlib = require('zlib');" + "['WAKA', 'αβγ']" + ".map(v => zlib.deflateRawSync(v, {level: zlib.constants.Z_NO_COMPRESSION}).toString('base64'))"), + njs_str("AQQA+/9XQUtB,AQYA+f/Osc6yzrM=") }, + + { njs_str("const zlib = require('zlib');" + "[zlib.constants.Z_FIXED, zlib.constants.Z_RLE]" + ".map(v => zlib.deflateRawSync('WAKA'.repeat(10), {strategy: v}).toString('base64'))"), + njs_str("C3f0dgwnAgMA,BcExAQAAAMKgbNwLYP8mwmQymUwmk8lkcg==") }, + + { njs_str("const zlib = require('zlib');" + "[1, 8]" + ".map(v => zlib.deflateRawSync('WAKA'.repeat(35)," + " {strategy: zlib.constants.Z_RLE, memLevel: v})" + " .toString('base64'))"), + njs_str("BMExAQAAAMKgbNwLYP8mwmQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk+lzDHf0dgx39HYMd/R2BAA=," + "BcExAQAAAMKgbNwLYP8mwmQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMjk=") }, + + { njs_str("const zlib = require('zlib');" + "['WAKA', 'αβγ']" + ".map(v => zlib.deflateSync(v).toString('base64'))"), + njs_str("eJwLd/R2BAAC+gEl,eJw7t/HcpnObAQ/sBIE=") }, + + { 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())"), + njs_str("true") }, + + { njs_str("const zlib = require('zlib');" + "['WAKA'.repeat(1024), 'αβγ'.repeat(1024)]" + ".map(v => [v, zlib.deflateRawSync(v, {chunkSize:64}).toString('base64')])" + ".every(pair => pair[0] == zlib.inflateRawSync(Buffer.from(pair[1], 'base64')," + " {chunkSize:64}).toString())"), + njs_str("true") }, + + { njs_str("const zlib = require('zlib');" + "['WAKA', 'αβγ']" + ".map(v => [v, zlib.deflateRawSync(v, {dictionary: Buffer.from('WAKA')}).toString('base64')])" + ".every(pair => pair[0] == zlib.inflateRawSync(Buffer.from(pair[1], 'base64')," + " {dictionary: Buffer.from('WAKA')}).toString())"), + njs_str("true") }, + +}; + + static njs_unit_test_t njs_module_test[] = { { njs_str("function f(){return 2}; var f; f()"), @@ -24994,6 +25062,17 @@ static njs_test_suite_t njs_suites[] = njs_nitems(njs_xml_test), njs_unit_test }, + { +#if (NJS_HAVE_ZLIB && !NJS_HAVE_MEMORY_SANITIZER) + njs_str("zlib"), +#else + njs_str(""), +#endif + { .externals = 1, .repeat = 1, .unsafe = 1 }, + njs_zlib_test, + njs_nitems(njs_zlib_test), + njs_unit_test }, + { njs_str("module"), { .repeat = 1, .module = 1, .unsafe = 1 }, njs_module_test, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel