[njs] Added "zlib" module.
Dmitry Volyntsev
xeioex at nginx.com
Wed Mar 29 04:38:51 UTC 2023
details: https://hg.nginx.org/njs/rev/5e7fc8efebdc
branches:
changeset: 2077:5e7fc8efebdc
user: Dmitry Volyntsev <xeioex at 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,
More information about the nginx-devel
mailing list