]> git.kaiwu.me - njs.git/commit
QuickJS: make Fetch finalization pool-independent
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 14 Aug 2026 02:10:28 +0000 (19:10 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Fri, 14 Aug 2026 23:05:54 +0000 (16:05 -0700)
commit72d3150a4d99522c242888a578d61b161a70ad97
tree08331a5ef07790f6c5eba690d71bfc9add268030
parent2ca3f08c79f4ce1ab6248baf0f00a28824950464
QuickJS: make Fetch finalization pool-independent

QuickJS may defer finalization of a Fetch object until after its native
backing pools have been destroyed.  Context reuse is not required: a
local JavaScript cycle is sufficient.

    function content(r) {
        const response = new Response("body");

        response.self = response;
        r.return(200);
    }

With context reuse disabled, the cycle is collected while
JS_FreeContext() destroys the per-request context.  At that point the
engine pool has already been destroyed.  The Response finalizer accessed
the pool-backed native structure and attempted to destroy its response
chain, causing a use-after-free.  Request finalization had the same
lifetime dependency through its cached Headers value.

The fix introduces a QuickJS-runtime-owned wrapper for Fetch Request and
Response objects.  It owns the cached Headers value and keeps only a
non-owning pointer to the pool-backed data.  Finalizers now release only
runtime-owned state, while response chains continue to be reclaimed in
bulk with the engine pool.
nginx/ngx_qjs_fetch.c
nginx/t/js_fetch_object_lifetime.t [new file with mode: 0644]