From: Dmitry Volyntsev Date: Tue, 10 Nov 2026 02:47:44 +0000 (-0800) Subject: Modules: embed the common opaque prefix in QuickJS wrappers X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=9719fc9a8f0e35bc18560726f395ca9af7e968a0;p=njs.git Modules: embed the common opaque prefix in QuickJS wrappers Context detach accesses the native pointer through a shared opaque layout. Embed that layout explicitly in HTTP and stream wrappers instead of relying on unrelated first pointer fields. This prepares shared lifetime invalidation without changing behavior. --- diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 1ed20f10..93a94225 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -159,10 +159,10 @@ typedef int (*njs_http_qjs_header_handler_t)(JSContext *cx, typedef struct { - ngx_http_request_t *request; - JSValue args; - JSValue request_body; - JSValue response_body; + ngx_js_opaque_t opaque; + JSValue args; + JSValue request_body; + JSValue response_body; } ngx_http_qjs_request_t; #endif @@ -6173,7 +6173,7 @@ ngx_http_qjs_ext_args(JSContext *cx, JSValueConst this_val) NJS_CHB_CTX_INIT(&chain, cx); - r = req->request; + r = req->opaque.external; rc = ngx_http_qjs_query_string_decode(&chain, r->args.data, r->args.len); if (rc != NGX_OK) { @@ -6530,7 +6530,8 @@ ngx_http_qjs_ext_periodic_variables(JSContext *cx, * Using lowest bit of the pointer to store the buffer type. */ type = (type == NGX_JS_BUFFER) ? 1 : 0; - JS_SetOpaque(obj, (void *) ((uintptr_t) req->request | (uintptr_t) type)); + JS_SetOpaque(obj, (void *) ((uintptr_t) req->opaque.external + | (uintptr_t) type)); return obj; } @@ -6602,7 +6603,7 @@ ngx_http_qjs_ext_response_body(JSContext *cx, JSValueConst this_val, int type) req->response_body = JS_UNDEFINED; } - r = req->request; + r = req->opaque.external; b = r->out ? r->out->buf : NULL; @@ -6656,7 +6657,7 @@ ngx_http_qjs_ext_request_body(JSContext *cx, JSValueConst this_val, int type) JS_FreeValue(cx, req->request_body); } - r = req->request; + r = req->opaque.external; if (r->request_body == NULL || r->request_body->bufs == NULL) { return JS_UNDEFINED; @@ -6778,7 +6779,7 @@ ngx_http_qjs_ext_read_request_body(JSContext *cx, JSValueConst this_val, return JS_ThrowTypeError(cx, "\"this\" is not a request object"); } - r = req->request; + r = req->opaque.external; ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); if (r->request_body) { @@ -6931,7 +6932,7 @@ ngx_http_qjs_ext_read_request_form(JSContext *cx, JSValueConst this_val, return JS_EXCEPTION; } - r = req->request; + r = req->opaque.external; ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); if (r->request_body) { @@ -9399,7 +9400,7 @@ ngx_http_qjs_request(JSValueConst val) return NULL; } - return req->request; + return req->opaque.external; } @@ -9421,7 +9422,7 @@ ngx_http_qjs_request_make(JSContext *cx, ngx_int_t proto_id, return JS_ThrowOutOfMemory(cx); } - req->request = r; + req->opaque.external = r; req->args = JS_UNDEFINED; req->request_body = JS_UNDEFINED; req->response_body = JS_UNDEFINED; diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index f544e108..bd6e6a79 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -87,8 +87,8 @@ typedef struct { } ngx_stream_qjs_event_t; typedef struct { - ngx_stream_session_t *session; - JSValue callbacks[NGX_JS_EVENT_MAX]; + ngx_js_opaque_t opaque; + JSValue callbacks[NGX_JS_EVENT_MAX]; } ngx_stream_qjs_session_t; #endif @@ -2287,6 +2287,7 @@ ngx_stream_qjs_ext_on(JSContext *cx, JSValueConst this_val, int argc, JSValueConst *argv) { ngx_stream_js_ctx_t *ctx; + ngx_stream_session_t *s; ngx_stream_qjs_session_t *ses; const ngx_stream_qjs_event_t *e; @@ -2295,9 +2296,10 @@ ngx_stream_qjs_ext_on(JSContext *cx, JSValueConst this_val, int argc, return JS_ThrowTypeError(cx, "\"this\" is not a session object"); } - ctx = ngx_stream_get_module_ctx(ses->session, ngx_stream_js_module); + s = ses->opaque.external; + ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module); - e = ngx_stream_qjs_event(ses->session, cx, argv[0]); + e = ngx_stream_qjs_event(s, cx, argv[0]); if (e == NULL) { return JS_EXCEPTION; } @@ -2365,7 +2367,8 @@ ngx_stream_qjs_ext_periodic_variables(JSContext *cx, * Using lowest bit of the pointer to store the buffer type. */ type = (type == NGX_JS_BUFFER) ? 1 : 0; - JS_SetOpaque(obj, (void *) ((uintptr_t) ses->session | (uintptr_t) type)); + JS_SetOpaque(obj, (void *) ((uintptr_t) ses->opaque.external + | (uintptr_t) type)); return obj; } @@ -3015,7 +3018,7 @@ ngx_stream_qjs_session(JSValueConst val) return NULL; } - return ses->session; + return ses->opaque.external; } @@ -3038,7 +3041,7 @@ ngx_stream_qjs_session_make(JSContext *cx, ngx_int_t proto_id, return JS_ThrowOutOfMemory(cx); } - ses->session = s; + ses->opaque.external = s; for (i = 0; i < NGX_JS_EVENT_MAX; i++) { ses->callbacks[i] = JS_UNDEFINED;