]> git.kaiwu.me - njs.git/log
njs.git
2 months agoGenerator: factor property assignment reads.
Dmitry Volyntsev [Sat, 28 Feb 2026 23:32:20 +0000 (15:32 -0800)]
Generator: factor property assignment reads.

2 months agoGenerator: factor test jump emission.
Dmitry Volyntsev [Sat, 28 Feb 2026 23:31:47 +0000 (15:31 -0800)]
Generator: factor test jump emission.

2 months agoGenerator: factor property assignment helpers.
Dmitry Volyntsev [Sat, 28 Feb 2026 23:31:24 +0000 (15:31 -0800)]
Generator: factor property assignment helpers.

2 months agoParser: factor right-link pop helper.
Dmitry Volyntsev [Sat, 28 Feb 2026 23:52:09 +0000 (15:52 -0800)]
Parser: factor right-link pop helper.

2 months agoParser: refactor call argument setup.
Dmitry Volyntsev [Sat, 28 Feb 2026 01:41:26 +0000 (17:41 -0800)]
Parser: refactor call argument setup.

2 months agoCI: added extra debug flags and enabled ASAN for njs basic tests.
Dmitry Volyntsev [Wed, 18 Feb 2026 02:08:41 +0000 (18:08 -0800)]
CI: added extra debug flags and enabled ASAN for njs basic tests.

2 months agoShell: fixed interactive mode detection for piped stdin.
Dmitry Volyntsev [Fri, 13 Feb 2026 05:31:23 +0000 (21:31 -0800)]
Shell: fixed interactive mode detection for piped stdin.

Previously, libedit callback API (rl_callback_read_char) was used for
interactive input processing.  Unlike the blocking readline() API, the
callback interface does not work correctly when stdin is a pipe: input
characters are silently dropped and the line handler is never invoked.

The issue was introduced in 4988565c6ea7 (0.8.0).

The fix is to check isatty(STDIN_FILENO) and fall back to the file
processing mode when stdin is not a terminal.

2 months agoReplace per-VM indexed array for modules with hash-based lookup.
Dmitry Volyntsev [Wed, 18 Feb 2026 01:56:22 +0000 (17:56 -0800)]
Replace per-VM indexed array for modules with hash-based lookup.

Previously, evaluated module values were cached in a separate
vm->modules array indexed by module->index assigned at compile time.
This required keeping the array size in sync with shared->module_items,
which was error-prone in interactive mode where new modules could be
compiled across commands.

Instead, store evaluated module values directly in the per-VM module
copy already maintained by vm->modules_hash.  This unifies the import
and require() caching paths and eliminates the index-based array along
with module->index and shared->module_items fields.

This fixes `make shell_test` when configured with --debug=YES.

2 months agoModules: suppressed slab log_nomem for evict shared dict zones.
Dmitry Volyntsev [Wed, 25 Feb 2026 07:13:54 +0000 (23:13 -0800)]
Modules: suppressed slab log_nomem for evict shared dict zones.

When evict is enabled, memory allocation failures are expected
and handled by evicting old entries.  The slab allocator's
"no memory" log messages are now suppressed for such zones.

2 months agoModules: fixed expire field truncation in shared dict state files.
Dmitry Volyntsev [Fri, 20 Feb 2026 23:45:25 +0000 (15:45 -0800)]
Modules: fixed expire field truncation in shared dict state files.

The njs_sprintf buffer for the expire field was sized for 10-digit
numbers, but current millisecond timestamps are 13 digits. This caused
silent truncation, making entries appear expired on a full restart.

The issue has been present since eca03622 (0.9.1), which introduced
the shared dictionary state file support.

2 months agoFixed heap-buffer-overflow in atom hash caused by Symbol().
Dmitry Volyntsev [Tue, 17 Feb 2026 00:20:20 +0000 (16:20 -0800)]
Fixed heap-buffer-overflow in atom hash caused by Symbol().

Previously, there was a key_hash collision between strings and
symbols in the atom hash table that led to use of uninitialized memory
and desynchronization of vm->atom_id_generator.

In the atom hash, string entries used djb_hash(content) as key_hash
while symbol entries used raw atom_id. Since djb_hash produces arbitrary
uint32_t values and atom_ids grow monotonically from NJS_ATOM_SIZE,
these spaces overlapped. When a symbol's atom_id matched an existing
string's djb_hash, njs_flathsh_insert() invoked the test function which
read uninitialized fhq.key fields (the function expected string data,
but the caller never initialized it for symbols). Additionally,
atom_id_generator was incremented before the insert, so on failure the
counter diverged from the actual element count, causing subsequent
njs_atom_to_value() calls to read out of bounds.

The fix is to partition the key_hash space using bit 31.

Found by OSS-Fuzz.

2 months agoRefactored atom hash into orthogonal find and add operations.
Dmitry Volyntsev [Tue, 17 Feb 2026 00:16:12 +0000 (16:16 -0800)]
Refactored atom hash into orthogonal find and add operations.

Previously, njs_atom_find_or_add() and njs_atom_find_or_add_string()
duplicated the lookup logic and coupled find with insert. Splitting
them into njs_atom_find() and njs_atom_add() separates concerns:
find does a pure lookup with raw bytes, add inserts a pre-built value.

2 months agoAlign SyntaxError reporting with other JS engines.
Dmitry Volyntsev [Tue, 10 Feb 2026 00:39:31 +0000 (16:39 -0800)]
Align SyntaxError reporting with other JS engines.

Previously, "in <file>:<file>" was a part of the error message. Now
the file name is reported as "stack" property.

This fixes #1005 issue on Github.

3 months agoAttach JS stack trace for exceptions thrown by C code.
Dmitry Volyntsev [Sat, 7 Feb 2026 00:29:20 +0000 (16:29 -0800)]
Attach JS stack trace for exceptions thrown by C code.

This fixes #1019 issue on Github.

3 months agoModules: fixed stack attach for native fetch exceptions for qjs.
Dmitry Volyntsev [Wed, 4 Feb 2026 02:17:16 +0000 (18:17 -0800)]
Modules: fixed stack attach for native fetch exceptions for qjs.

JS_ThrowInternalError() captures backtrace outside of JS call, resulting
in empty "stack" string.  Later, while unwinding, is_backtrace_needed()
returns false because "stack" property exists.

JS_NewError() does not try to attach stack, as a result a stack is
attached later during unwinding.

3 months agoAttach stack in error constructors.
Dmitry Volyntsev [Fri, 30 Jan 2026 01:18:31 +0000 (17:18 -0800)]
Attach stack in error constructors.

This aligns njs with QuickJS and most other JS engines.

3 months agoMark anonymous and unknown functions with <>.
Dmitry Volyntsev [Fri, 30 Jan 2026 00:13:13 +0000 (16:13 -0800)]
Mark anonymous and unknown functions with <>.

To separate from normal functions with the same name.

3 months agoMake Error.stack faster.
Dmitry Volyntsev [Thu, 29 Jan 2026 02:36:39 +0000 (18:36 -0800)]
Make Error.stack faster.

Previously, error.stack reported full names for native function (for
example Array.prototype.map -> map), but it was achieved by iteration
through a global object which is slow.

The fix is to report only function name at hand, this loses a bit
of verbosity but make it ~100 times faster.

make benchmark
before
        ...
exception.stack: 38.421µs, 26027 times/s
exception.native.stack: 226.711µs, 4410 times/s
after
        ...
exception.stack: 1.239µs, 807356 times/s
exception.native.stack: 2.419µs, 413339 times/s

3 months agoFixed stack attaching by stringifying function addresses in place.
Dmitry Volyntsev [Wed, 28 Jan 2026 22:54:29 +0000 (14:54 -0800)]
Fixed stack attaching by stringifying function addresses in place.

This fixed Error stack output on CLI.

3 months agoFixed PTR macro compatibility with newer BFD library.
Dmitry Volyntsev [Wed, 4 Feb 2026 04:17:51 +0000 (20:17 -0800)]
Fixed PTR macro compatibility with newer BFD library.

The deprecated PTR macro was removed in recent versions of binutils.
Replaced with (void **) cast.

3 months agoFixed build on MacOS after 220b9b03 (0.9.5).
Dmitry Volyntsev [Tue, 27 Jan 2026 02:19:05 +0000 (18:19 -0800)]
Fixed build on MacOS after 220b9b03 (0.9.5).

MacOS linker does not support -Wl,-E as it exports binary
symbols by default.

This fixes #1015 on Github.

3 months agoauto/cc: Use portable/POSIX 'command -v' instead of 'which'
Zurab Kvachadze [Mon, 26 Jan 2026 14:54:51 +0000 (15:54 +0100)]
auto/cc: Use portable/POSIX 'command -v' instead of 'which'

'which' is not a portable utility as it is not specified by POSIX. Since
auto/cc is already a shell script, use the more direct and portable
'command' builtin to detect $CC.

There are two bugs linked here. The first one is a downstream report of
this issue. The second one is more general information on why 'which'
usage is an issue and should be avoided.

Bug: https://bugs.gentoo.org/969288
Bug: https://bugs.gentoo.org/646588
Signed-off-by: Zurab Kvachadze <zurabid2016@gmail.com>
3 months agoShell: fixed fuzzer harness to add NULL termination.
OwenSanzas [Thu, 15 Jan 2026 00:15:35 +0000 (00:15 +0000)]
Shell: fixed fuzzer harness to add NULL termination.

Guided-by: Dmitry Volyntsev <xeioex@nginx.com>
Signed-off-by: Ze Sheng <OwenSanzas@gmail.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
3 months agoMaking unit tests less brittle when libpcre2 changes.
Dmitry Volyntsev [Wed, 14 Jan 2026 22:43:58 +0000 (14:43 -0800)]
Making unit tests less brittle when libpcre2 changes.

This fixes #1011 issue on Github.

3 months agoVersion bump.
Dmitry Volyntsev [Wed, 14 Jan 2026 22:46:11 +0000 (14:46 -0800)]
Version bump.

3 months ago Version 0.9.5. 0.9.5
Dmitry Volyntsev [Mon, 12 Jan 2026 23:01:50 +0000 (15:01 -0800)]
 Version 0.9.5.

3 months agoQuickJS: added native module support in CLI.
Dmitry Volyntsev [Thu, 8 Jan 2026 02:09:20 +0000 (18:09 -0800)]
QuickJS: added native module support in CLI.

3 months agoQuickJS: added native module support.
Dmitry Volyntsev [Wed, 3 Dec 2025 01:39:44 +0000 (17:39 -0800)]
QuickJS: added native module support.

Added "js_load_http_native_module" and "js_load_stream_native_module"
main nginx.conf level directives. The directives load a dynamic
library. For security reason it is only allowed in the main context.
Later, JS code may import modules loaded with these directives
with standard import syntax.

example.conf:
    ...
    js_load_http_native_module /path/to/lib.so;
    js_load_http_native_module /path/to/lib2.so as lib2;

    http {
        js_import main.js;
...

main.js:
    import * as lib from 'lib.so';
    import * as lib2 from 'lib2';
    ...

See quickjs.h for the complete QuickJS API reference and
nginx/t/js_native_module.t for a working example.

This closes #968 feature request on Github.

3 months agoModules: extracted config-time merging into separate function.
Dmitry Volyntsev [Sat, 6 Dec 2025 01:08:54 +0000 (17:08 -0800)]
Modules: extracted config-time merging into separate function.

This introduces ngx_js_merge_conftime_loc_conf() to handle merging
of configuration-time properties.

Normally ngx_js_merge_conf() does all the default value initialization
for child location configurations.

There is a special case for global "http" or "stream" configuration
where the parent configuration needs to be initialized (so it can be
reused by server configurations if no additional directives were
defined in them). But parent configurations are not initialized by
ngx_js_merge_conf().

Most of the ngx_js_loc_conf_t values are only used at runtime, so
only configuration-time values need to be merged in the parent.
The runtime values will be provided from the appropriate
ngx_js_loc_conf_t during request processing.

Previously, configuration-time merging was done inline. Extracting
it into a dedicated function simplifies adding new configuration-time
properties.

3 months agoQuickJS: fixed js_body_filter with multiple chunks.
Dmitry Volyntsev [Sat, 10 Jan 2026 02:08:56 +0000 (18:08 -0800)]
QuickJS: fixed js_body_filter with multiple chunks.

Previously, last_key atoms was freed too early. Also, js_body_filter.t
is modified to ensure js_body_filter sees multiple data chains to catch
the issue.

4 months agoHTTP: improved r.subrequest() error handling after d34fcb0 (0.8.5).
Dmitry Volyntsev [Tue, 6 Jan 2026 01:23:50 +0000 (17:23 -0800)]
HTTP: improved r.subrequest() error handling after d34fcb0 (0.8.5).

This reverts code changes introduced in d34fcb0. To fix the original
problem JS errors are not propagated as nginx errors in r.subrequest().

This also fixes a problem of a lost write event when the njs handler
making r.subrequest() is called from a lua handler as a subrequest:

nginx.conf:
    ...
    location = /subrequest {
        access_by_lua_file scripts/subrequest.lua;
proxy_pass  http://localhost:8080/pass;
    }

    location = /nested/subrequest {
        internal;
        js_content main.getToken;
    }

scripts/subrequest.lua:
    local res = ngx.location.capture('/nested/subrequest')
    ngx.log(ngx.STDERR, "Subrequest  status: " .. res.status)

    if res.status ~= 200 then
      ngx.log(ngx.STDERR, "Subrequest failed with status: " .. res.status)
      return nil
    end

    return res.body

main.js:
    async function getToken(r) {
        var reply = await r.subrequest('/api/auth');
        r.error("reply.status :: " + reply.status);

        var status = reply.status;
        r.return(status, "{"result":"OK!"}");
    }

    export default { getToken };

$ curl localhost:8080/subrequest

error.log (before the fix):
    ...
    *1 http js event finalize rc: 0
    *1 post event 0000B4BCA64C5FF0
    *1 http log handler
    *1 http request count:3 blk:0
    timer delta: 0
    posted event 0000B4BCA64C5FF0
    *1 delete posted event 0000B4BCA64C5FF0
    *1 http run request: "/subrequest?"
    *1 access phase: 11
    *1 lua access handler, uri:"/subrequest" c:2
    *1 lua run write event handler: timedout:0, ready:1, writing_raw_req_socket:0
    *1 useless lua write event handler <<<---

error.log (after the fix):
    ...
    *1 http js event finalize rc: 0
    *1 http posted request: "/nested/subrequest?"
    *1 http js content write event handler
    *1 http js content rc: 0
    *1 http finalize request: 0, "/nested/subrequest?" a:0, c:3
    *1 lua run post subrequest handler, rc:0 c:3
    *1 http log handler
    *1 http wake parent request: "/subrequest?"
    *1 http posted request: "/subrequest?"
    *1 access phase: 11
    *1 lua access handler, uri:"/subrequest" c:2
    *1 lua run subrequests done, resuming lua thread

4 months agoTypes: fixed CipherAlgorithm and Pbkdf2Params
Martin Kaesberger [Sun, 14 Dec 2025 15:29:17 +0000 (16:29 +0100)]
Types: fixed CipherAlgorithm and Pbkdf2Params

4 months agoConfigure: respecting user provided CFLAGS.
Dmitry Volyntsev [Tue, 25 Nov 2025 00:19:59 +0000 (16:19 -0800)]
Configure: respecting user provided CFLAGS.

See https://www.gnu.org/prep/standards/html_node/Command-Variables.html
and discussion in #990 issue on Github.

4 months agoConfigure: added option to configure position independent code flag.
Dmitry Volyntsev [Tue, 25 Nov 2025 01:49:35 +0000 (17:49 -0800)]
Configure: added option to configure position independent code flag.

4 months agoHTTP: fixed buffer_type inheritance in if blocks.
Dmitry Volyntsev [Fri, 12 Dec 2025 05:57:18 +0000 (21:57 -0800)]
HTTP: fixed buffer_type inheritance in if blocks.

Previously, when js_body_filter was used inside an if block that
evaluated to true, the data parameter received Buffer type instead
of the expected String type. This happened because buffer_type field
in ngx_http_js_loc_conf_t was not properly initialized, causing the
configuration merge to fail when nginx created a new location context
for if blocks.

This fixes #999 issue on Github.

5 months agoFixed js_body_filter when data is not in memory.
Dmitry Volyntsev [Tue, 2 Dec 2025 01:03:25 +0000 (17:03 -0800)]
Fixed js_body_filter when data is not in memory.

Previously, when upstream data was delivered from nginx cache
js_body_filter was not able to process it correctly. In particular,
it was treated as a chain of empty buffers.

The fix is to set r->filter_need_in_memory flag, which ensures
that ngx_http_core_module reads the data into memory before
js_body_filter sees it.

This fixes #992 issue on Github.

5 months agoFS: fixed path restoration in fs.mkdir() and friends on error.
Dmitry Volyntsev [Wed, 26 Nov 2025 03:08:33 +0000 (19:08 -0800)]
FS: fixed path restoration in fs.mkdir() and friends on error.

5 months agoFS: fixed fs.mkdir() and friends.
Dmitry Volyntsev [Wed, 26 Nov 2025 03:08:10 +0000 (19:08 -0800)]
FS: fixed fs.mkdir() and friends.

5 months agoFixed missed allocation check in promise code.
Dmitry Volyntsev [Tue, 25 Nov 2025 23:58:38 +0000 (15:58 -0800)]
Fixed missed allocation check in promise code.

Found by Coverity (CID 16469311646932).

5 months agoXML: fixed XMLNode update.
Dmitry Volyntsev [Sat, 22 Nov 2025 01:41:53 +0000 (17:41 -0800)]
XML: fixed XMLNode update.

5 months agoXML: fixed XMLAttr object.
Dmitry Volyntsev [Sat, 22 Nov 2025 00:32:15 +0000 (16:32 -0800)]
XML: fixed XMLAttr object.

Pointer to xmlAttr to which XMLAttr used to point might become invalid
when the parent XMLNode was modified.

The fix is to hold a pointer to xmlNode.

5 months agoRemoved non-compliant Buffer.prototype.length.
Dmitry Volyntsev [Thu, 20 Nov 2025 23:28:49 +0000 (15:28 -0800)]
Removed non-compliant Buffer.prototype.length.

5 months agoFixed ArrayBuffer with detached buffers.
Dmitry Volyntsev [Thu, 20 Nov 2025 23:07:07 +0000 (15:07 -0800)]
Fixed ArrayBuffer with detached buffers.

5 months agoAdded missing detached array checks.
Dmitry Volyntsev [Tue, 18 Nov 2025 02:55:16 +0000 (18:55 -0800)]
Added missing detached array checks.

5 months agoPreserving strings are zero-terminated in njs_string_truncate().
Dmitry Volyntsev [Tue, 18 Nov 2025 03:37:48 +0000 (19:37 -0800)]
Preserving strings are zero-terminated in njs_string_truncate().

This is linked to changes introduced in e7caa46.

5 months agoCI: cancel stale workflows.
Dmitry Volyntsev [Wed, 19 Nov 2025 01:57:37 +0000 (17:57 -0800)]
CI: cancel stale workflows.

5 months agoCI: using meson and pkg-config for QuickJS-NG.
Dmitry Volyntsev [Wed, 19 Nov 2025 01:54:45 +0000 (17:54 -0800)]
CI: using meson and pkg-config for QuickJS-NG.

5 months agoAdded pkg-config discovery for QuickJS-NG.
Dmitry Volyntsev [Wed, 19 Nov 2025 01:46:41 +0000 (17:46 -0800)]
Added pkg-config discovery for QuickJS-NG.

5 months agoQuickJS: fixed compatibility issue with QuickJS-NG 0.11.0.
Dmitry Volyntsev [Wed, 19 Nov 2025 00:10:52 +0000 (16:10 -0800)]
QuickJS: fixed compatibility issue with QuickJS-NG 0.11.0.

5 months agoModules: removed extra not needed QuickJS checks.
Dmitry Volyntsev [Wed, 19 Nov 2025 01:12:48 +0000 (17:12 -0800)]
Modules: removed extra not needed QuickJS checks.

5 months agoUsing printing and parsing library from QuickJS.
Dmitry Volyntsev [Fri, 24 Oct 2025 03:06:42 +0000 (20:06 -0700)]
Using printing and parsing library from QuickJS.

- Number.prototype.toString(radix)
    Improved accuracy for edge cases
    Reimplemented using njs_dtoa2() with JS_DTOA_FORMAT_FREE | JS_DTOA_EXP_DISABLED
- Number.prototype.toFixed(frac)
    Reimplemented using njs_dtoa2() with JS_DTOA_FORMAT_FIXED
    Removed old njs_fixed_dtoa() implementation
- Number.prototype.toPrecision(prec)
    Reimplemented using njs_dtoa2() with precision format
    Removed old njs_dtoa_precision() implementation
- Number.prototype.toExponential(frac)
    Reimplemented using njs_dtoa2() with exponential format
    Removed old njs_dtoa_exponential() implementation
- parseInt()
    Simplified parsing implementation
    Removed custom njs_number_radix_parse() helper
- parseFloat()
    Simplified parsing implementation

Removed custom njs_number_bin_parse(), njs_number_oct_parse(),
njs_number_dec_parse() and njs_strtod.c module Better handling of large
numbers and denormal floats and invalid inputs.

5 months agoEnsuring string values are zero-terminated.
Dmitry Volyntsev [Sat, 15 Nov 2025 02:22:56 +0000 (18:22 -0800)]
Ensuring string values are zero-terminated.

This helps when some code requires a string value to be zero-terminated
to avoid copying and adding \0 byte.

It adds small overhead (less than 3% in worst case of an empty string
value) to existing sizeof(njs_value_t) + sizeof(njs_string_t) = 32.

5 months agoFixed --debug=YES build after d4cedc0.
Dmitry Volyntsev [Fri, 14 Nov 2025 21:07:20 +0000 (13:07 -0800)]
Fixed --debug=YES build after d4cedc0.

5 months agoAdded Symbol.toPrimitive to Date and Symbol prototypes.
Vadim Zhestikov [Tue, 11 Nov 2025 18:01:01 +0000 (10:01 -0800)]
Added Symbol.toPrimitive to Date and Symbol prototypes.

5 months agoAdded Object.hasOwn().
Vadim Zhestikov [Mon, 10 Nov 2025 17:50:48 +0000 (09:50 -0800)]
Added Object.hasOwn().

5 months agoFixed Object prototype methods according to the spec.
Vadim Zhestikov [Mon, 10 Nov 2025 16:56:28 +0000 (08:56 -0800)]
Fixed Object prototype methods according to the spec.

6 months agoAdded promises execution after njs.on('exit', ..) hook.
Vadim Zhestikov [Wed, 5 Nov 2025 01:35:35 +0000 (17:35 -0800)]
Added promises execution after njs.on('exit', ..) hook.

6 months agoModules: improved handling of results of async handlers.
Vadim Zhestikov [Fri, 25 Jul 2025 00:10:36 +0000 (17:10 -0700)]
Modules: improved handling of results of async handlers.

Previously, r.setReturnValue() had to be used when returning a value from async js_set handler.

async function hash(r) {
    let hash = await crypto.subtle.digest('SHA-512', r.headersIn.host);
    r.setReturnValue(Buffer.from(hash).toString('hex'));
}

Now r.setReturnValue() is not needed:

async function hash(r) {
    let hash = await crypto.subtle.digest('SHA-512', r.headersIn.host);
    return Buffer.from(hash).toString('hex');
}

Also added promise handling in global qjs code.

6 months agoAdded API to work with promises.
Vadim Zhestikov [Tue, 4 Nov 2025 16:23:39 +0000 (08:23 -0800)]
Added API to work with promises.

6 months agoVersion bump.
Vadim Zhestikov [Wed, 5 Nov 2025 00:12:37 +0000 (16:12 -0800)]
Version bump.

6 months agoFetch: making sure catch handler is executed asynchronously.
Vadim Zhestikov [Mon, 27 Oct 2025 21:14:02 +0000 (14:14 -0700)]
Fetch: making sure catch handler is executed asynchronously.

6 months agoVersion 0.9.4. 0.9.4
Dmitry Volyntsev [Mon, 27 Oct 2025 22:45:00 +0000 (15:45 -0700)]
Version 0.9.4.

6 months agoFetch: added forward proxy support with HTTPS tunneling.
Dmitry Volyntsev [Thu, 9 Oct 2025 23:28:24 +0000 (16:28 -0700)]
Fetch: added forward proxy support with HTTPS tunneling.

Supports Basic authentication via Proxy-Authorization header.

- js_fetch_proxy - configures forward proxy URL. It takes proxy URL
    as a parameter. The URL may optionally contain user and password.
     Parameter value can contain variables. If value is empty,
     forward proxy is disabled.

example.conf:
...
  http {
      js_import main.js;

      server {
          listen 8080;

          resolver   127.0.0.1:5353;

          location /api {
              js_fetch_proxy http://user:pass@proxy.example.com:3128;
              js_content main.fetch_handler;
          }
      }
  }

This implements #956 feature request on Github.

6 months agoFetch: added default user agent.
Dmitry Volyntsev [Thu, 16 Oct 2025 01:56:48 +0000 (18:56 -0700)]
Fetch: added default user agent.

6 months agoFetch: introduced ngx_js_chain_to_buf() helper function.
Dmitry Volyntsev [Wed, 15 Oct 2025 00:42:07 +0000 (17:42 -0700)]
Fetch: introduced ngx_js_chain_to_buf() helper function.

6 months agoFetch: refactored request building logic into separate function.
Dmitry Volyntsev [Thu, 9 Oct 2025 23:16:54 +0000 (16:16 -0700)]
Fetch: refactored request building logic into separate function.

6 months agoFetch: introduced port and protocol helper macros.
Dmitry Volyntsev [Thu, 9 Oct 2025 22:57:44 +0000 (15:57 -0700)]
Fetch: introduced port and protocol helper macros.

6 months agoTests: making sure dns stub in js_fetch_https.t resolves only known hosts.
Dmitry Volyntsev [Thu, 9 Oct 2025 01:41:47 +0000 (18:41 -0700)]
Tests: making sure dns stub in js_fetch_https.t resolves only known hosts.

6 months agoFetch: simplified ngx_js_http_resolve().
Dmitry Volyntsev [Wed, 15 Oct 2025 22:29:14 +0000 (15:29 -0700)]
Fetch: simplified ngx_js_http_resolve().

6 months agoModules: added error handling when logging a js exception string.
Vadim Zhestikov [Thu, 23 Oct 2025 20:27:41 +0000 (13:27 -0700)]
Modules: added error handling when logging a js exception string.

6 months agoQuickJS: fixed r.subrequest() to a location with JS handler.
Dmitry Volyntsev [Tue, 14 Oct 2025 00:37:11 +0000 (17:37 -0700)]
QuickJS: fixed r.subrequest() to a location with JS handler.

Previously, when a subrequest location had a JS handler, an object of a
subrequest JS context was provided as an argument to a parent contexts.
This may cause all sorts of problems due to incorrect reference
counting.

After this change in bellard/quickjs@42eb2795 the bug became apparent.

6 months agoVersion bump.
Dmitry Volyntsev [Thu, 9 Oct 2025 01:42:16 +0000 (18:42 -0700)]
Version bump.

7 months agoVersion 0.9.3. 0.9.3
Dmitry Volyntsev [Mon, 6 Oct 2025 16:13:36 +0000 (09:13 -0700)]
Version 0.9.3.

7 months agoFixed heap-use-after-free in js_set handler.
Dmitry Volyntsev [Tue, 30 Sep 2025 01:30:15 +0000 (18:30 -0700)]
Fixed heap-use-after-free in js_set handler.

The issue was introduced in commit 04f6dfb (0.9.2) by moving VM
destruction from the pool cleanup handler to the http cleanup handler.

Moving VM destruction to the http cleanup handler broke js_set variable
usage during the log phase, because these variables are called after the
VM has been destroyed.

The fix is to move VM destruction back to the pool cleanup handler, but
use a temporary pool while njs.on('exit', ...) is executing.

This fixes #969 and #971 issues on Github.

7 months agoModule: fixed heap-use-after-free while module loading.
Dmitry Volyntsev [Thu, 2 Oct 2025 03:07:14 +0000 (20:07 -0700)]
Module: fixed heap-use-after-free while module loading.

Making a copy of file argument because the engine may outlive
current ngx_cycle.

The bug became visible since 283282f (0.8.8).

7 months agoModules: fixed memory leak when module loading failed.
Dmitry Volyntsev [Thu, 2 Oct 2025 03:23:08 +0000 (20:23 -0700)]
Modules: fixed memory leak when module loading failed.

7 months agoFixed potential heap-use-after-free in njs_vm_compile_module().
Dmitry Volyntsev [Thu, 2 Oct 2025 03:10:43 +0000 (20:10 -0700)]
Fixed potential heap-use-after-free in njs_vm_compile_module().

Passing a local copy of name argument to njs_parser_init().

7 months agoVersion bump.
Dmitry Volyntsev [Tue, 30 Sep 2025 05:43:11 +0000 (22:43 -0700)]
Version bump.

7 months agoReadme: updated hero graphic.
Michael Vernik [Thu, 2 Oct 2025 21:41:16 +0000 (14:41 -0700)]
Readme: updated hero graphic.

7 months agoVersion 0.9.2. 0.9.2
Dmitry Volyntsev [Mon, 22 Sep 2025 17:12:15 +0000 (10:12 -0700)]
Version 0.9.2.

7 months agoModules: fixed building when http_ssl and stream_ssl unavailable.
Dmitry Volyntsev [Wed, 17 Sep 2025 22:34:19 +0000 (15:34 -0700)]
Modules: fixed building when http_ssl and stream_ssl unavailable.

This fixes issue introduced in 7b3c8a66.

7 months agoFixed build with gcc-15 and -O3.
Dmitry Volyntsev [Wed, 17 Sep 2025 01:28:05 +0000 (18:28 -0700)]
Fixed build with gcc-15 and -O3.

build/src/njs_object.dep -MT build/src/njs_object.o \ src/njs_object.c
In file included from src/njs_main.h:18, from src/njs_object.c:8: In
function ‘njs_utf8_copy’, inlined from ‘njs_object_enumerate_string’ at
src/njs_object.c:769:21: src/njs_utf8.h:115:20: error: writing 1 byte
into a region of size 0 [-Werror=stringop-overflow=] 115 |
*dst++ = c; |             ~~~~~~~^~~ src/njs_object.c: In function
‘njs_object_enumerate_string’: src/njs_object.c:719:24: note: at offset
4 into destination object ‘buf’ of size 4 719 |     u_char
buf[4], *c; |                        ^~~ In function ‘njs_utf8_copy’,
inlined from ‘njs_object_enumerate_string’ at src/njs_object.c:769:21:
src/njs_utf8.h:115:20: error: writing 1 byte into a region of size 0
[-Werror=stringop-overflow=]

GCC-15 does not know that the loop in njs_utf8_copy() is bounded
because the input is a valid UTF-8 here.

This fixes #967 issue on Github.

7 months agoFetch: added keepalive support for ngx.fetch() API.
Dmitry Volyntsev [Thu, 4 Sep 2025 03:27:16 +0000 (20:27 -0700)]
Fetch: added keepalive support for ngx.fetch() API.

This closes #957 feature request on Github.

7 months agoFetch: added parsing of HTTP version.
Dmitry Volyntsev [Sat, 13 Sep 2025 02:10:32 +0000 (19:10 -0700)]
Fetch: added parsing of HTTP version.

7 months agoModules: simplified access to nginx values from JS engines.
Dmitry Volyntsev [Thu, 4 Sep 2025 05:44:04 +0000 (22:44 -0700)]
Modules: simplified access to nginx values from JS engines.

8 months agoQuickJS: added njs.on('exit') API support.
Dmitry Volyntsev [Tue, 26 Aug 2025 21:22:19 +0000 (14:22 -0700)]
QuickJS: added njs.on('exit') API support.

This closes #955 issue on Github.

8 months agoQuickJS: removed extra copy of body argument in ngx.fetch().
Dmitry Volyntsev [Fri, 29 Aug 2025 02:15:01 +0000 (19:15 -0700)]
QuickJS: removed extra copy of body argument in ngx.fetch().

8 months agoQuickJS: fixed potential heap-use-after-free.
Dmitry Volyntsev [Thu, 28 Aug 2025 22:20:31 +0000 (15:20 -0700)]
QuickJS: fixed potential heap-use-after-free.

Previously in QuickJS engine, fields allocated from memory pool linked
to QuickJS engine lifetime were stored in nginx data structs.

This causes a heap-use-after-free if QuickJS engine is destroyed
earlier than a last access from nginx. For example, it becomes
visible when moving NJS cleanup handler from pool->cleanup to
r->cleanup.

The fix is to only store references in nginx objects allocated from
nginx memory pool.

8 months agoQuickJS: freeing temporary strings.
Dmitry Volyntsev [Thu, 28 Aug 2025 23:29:22 +0000 (16:29 -0700)]
QuickJS: freeing temporary strings.

8 months agoQuickJS: using enum instead of manual opaque id table.
Dmitry Volyntsev [Tue, 26 Aug 2025 05:26:24 +0000 (22:26 -0700)]
QuickJS: using enum instead of manual opaque id table.

8 months agoQuickJS: fix nginx configure with not configured njs module.
Vadim Zhestikov [Fri, 29 Aug 2025 16:42:18 +0000 (09:42 -0700)]
QuickJS: fix nginx configure with not configured njs module.

This fixes issue #960 which was introduced in 8259f9a.

8 months agoModules: optimized memory consumption while streaming in qjs.
Dmitry Volyntsev [Tue, 19 Aug 2025 04:21:09 +0000 (21:21 -0700)]
Modules: optimized memory consumption while streaming in qjs.

This allows to stream long tcp streams or large http response bodies
with low memory consumption.

This works only for qjs engine, because njs has no GC.

This fixes #943 issue on Github.

8 months agoModules: removing extra copy while streaming in qjs.
Dmitry Volyntsev [Thu, 14 Aug 2025 06:19:46 +0000 (23:19 -0700)]
Modules: removing extra copy while streaming in qjs.

8 months agoTests: added TypedArray test for js_filter in stream.
Dmitry Volyntsev [Wed, 20 Aug 2025 00:16:22 +0000 (17:16 -0700)]
Tests: added TypedArray test for js_filter in stream.

8 months agoFixed building QuickJS support with clang 19.
Dmitry Volyntsev [Mon, 25 Aug 2025 23:47:43 +0000 (16:47 -0700)]
Fixed building QuickJS support with clang 19.

checking for QuickJS library -lquickjs In file included from
build/autotest.c:6:
/home/xeioex/workspace/nginx/nginScript/quickjs/quickjs.h:1052:34:
error: cast from 'JSCFunctionMagic *' (aka 'struct JSValue (*)(struct
JSContext *, struct JSValue, int, struct JSValue *, int)') to
'JSCFunction *' (aka 'struct JSValue (*)(struct JSContext *, struct
JSValue, int, struct JSValue *)') converts to incompatible function type
[-Werror,-Wcast-function-type-mismatch] 1052 | return
JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);

-Wcast-function-type-mismatch become enabled by -Werror since
clang 19.

8 months agoModules: fixed incorrect config rejections introduced in d157f56.
Dmitry Volyntsev [Sat, 16 Aug 2025 00:28:47 +0000 (17:28 -0700)]
Modules: fixed incorrect config rejections introduced in d157f56.

d157f56 introduced configure time checks for js_set and js_periodic
directives. It turned out to be too strict.

The fix is to remove them completely as there is no way to track
variable usage context in configure time.

8 months agoModules: added configure time check when "js_import" is not defined.
Dmitry Volyntsev [Tue, 12 Aug 2025 06:26:12 +0000 (23:26 -0700)]
Modules: added configure time check when "js_import" is not defined.

8 months agoModules: fixed merging of js_path directives.
Dmitry Volyntsev [Tue, 12 Aug 2025 01:55:18 +0000 (18:55 -0700)]
Modules: fixed merging of js_path directives.

The issue initially appeared in 1b54abb (0.7.7).

8 months agoChange: increasing the default stack size to 160k.
Dmitry Volyntsev [Mon, 11 Aug 2025 23:25:47 +0000 (16:25 -0700)]
Change: increasing the default stack size to 160k.

This change allows EarleyBoyer benchmark from
arewefastyet/benchmarks/v8-v7 to pass with default settings.

Previous commit 5e9a6d5 (v0.7.9) reduced the stack size to prevent stack
overflow when compiling with -O0 in computed goto mode, where native
stack frames for njs_vmcode_interpreter() consume ~80KB each. To address
this, we now set a lower maximum stack size specifically for unit tests.

This fixes #939 issue on Github.

9 months agoAdded CLA workflow.
Vadim Zhestikov [Fri, 8 Aug 2025 00:41:09 +0000 (17:41 -0700)]
Added CLA workflow.