[njs] Refactored externals.

Dmitry Volyntsev xeioex at nginx.com
Fri Mar 20 14:56:40 UTC 2020


details:   https://hg.nginx.org/njs/rev/573d264cb7e7
branches:  
changeset: 1358:573d264cb7e7
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Mar 20 17:33:06 2020 +0300
description:
Refactored externals.

This closes #16 issue on Github.

diffstat:

 nginx/ngx_http_js_module.c      |  1115 +++++++++++++++++++-------------------
 nginx/ngx_stream_js_module.c    |   473 +++++++---------
 src/njs.h                       |   122 +++-
 src/njs_array.c                 |     5 +-
 src/njs_array.h                 |     5 +-
 src/njs_array_buffer.c          |     1 +
 src/njs_crypto.c                |     1 +
 src/njs_date.c                  |     1 +
 src/njs_error.c                 |     2 +
 src/njs_extern.c                |   529 ++++++++---------
 src/njs_extern.h                |    45 -
 src/njs_function.c              |     2 +-
 src/njs_function.h              |     2 +-
 src/njs_json.c                  |    17 +-
 src/njs_main.h                  |     1 -
 src/njs_module.c                |     1 +
 src/njs_object.c                |     9 +-
 src/njs_object_prop.c           |    32 +-
 src/njs_promise.c               |     1 +
 src/njs_regexp.c                |     1 +
 src/njs_shell.c                 |   185 ++---
 src/njs_symbol.h                |    19 -
 src/njs_value.c                 |   225 +------
 src/njs_value.h                 |    74 +-
 src/njs_vm.c                    |    41 +-
 src/njs_vm.h                    |    11 -
 src/test/njs_benchmark.c        |    45 +-
 src/test/njs_externals_test.c   |   705 +++++++++++++-----------
 src/test/njs_externals_test.h   |     3 +-
 src/test/njs_interactive_test.c |     6 +-
 src/test/njs_unit_test.c        |   535 +++++++++++-------
 test/njs_expect_test.exp        |    26 +-
 32 files changed, 2120 insertions(+), 2120 deletions(-)

diffs (truncated from 6020 to 1000 lines):

diff -r 224494c53bbf -r 573d264cb7e7 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c	Wed Mar 18 18:29:17 2020 +0300
+++ b/nginx/ngx_http_js_module.c	Fri Mar 20 17:33:06 2020 +0300
@@ -13,34 +13,34 @@
 
 
 typedef struct {
-    njs_vm_t            *vm;
-    ngx_array_t         *paths;
-    const njs_extern_t  *req_proto;
+    njs_vm_t              *vm;
+    ngx_array_t           *paths;
+    njs_external_proto_t   req_proto;
 } ngx_http_js_main_conf_t;
 
 
 typedef struct {
-    ngx_str_t            content;
+    ngx_str_t              content;
 } ngx_http_js_loc_conf_t;
 
 
 typedef struct {
-    njs_vm_t            *vm;
-    ngx_log_t           *log;
-    ngx_uint_t           done;
-    ngx_int_t            status;
-    njs_opaque_value_t   request;
-    njs_opaque_value_t   request_body;
-    ngx_str_t            redirect_uri;
-    njs_opaque_value_t   promise_callbacks[2];
+    njs_vm_t              *vm;
+    ngx_log_t             *log;
+    ngx_uint_t             done;
+    ngx_int_t              status;
+    njs_opaque_value_t     request;
+    njs_opaque_value_t     request_body;
+    ngx_str_t              redirect_uri;
+    njs_opaque_value_t     promise_callbacks[2];
 } ngx_http_js_ctx_t;
 
 
 typedef struct {
-    ngx_http_request_t  *request;
-    njs_vm_event_t       vm_event;
-    void                *unused;
-    ngx_int_t            ident;
+    ngx_http_request_t    *request;
+    njs_vm_event_t         vm_event;
+    void                  *unused;
+    ngx_int_t              ident;
 } ngx_http_js_event_t;
 
 
@@ -55,24 +55,20 @@ static ngx_int_t ngx_http_js_init_vm(ngx
 static void ngx_http_js_cleanup_ctx(void *data);
 static void ngx_http_js_cleanup_vm(void *data);
 
-static njs_int_t ngx_http_js_ext_get_string(njs_vm_t *vm, njs_value_t *value,
-    void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_keys_header(njs_vm_t *vm, void *obj,
+static njs_int_t ngx_http_js_ext_get_string(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 ngx_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value,
     njs_value_t *keys, uintptr_t data);
 static ngx_table_elt_t *ngx_http_js_get_header(ngx_list_part_t *part,
     u_char *data, size_t len);
-static njs_int_t ngx_http_js_ext_get_header_out(njs_vm_t *vm,
-    njs_value_t *value, void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_set_header_out(njs_vm_t *vm, void *obj,
-    uintptr_t data, njs_str_t *value);
-static njs_int_t ngx_http_js_ext_delete_header_out(njs_vm_t *vm, void *obj,
-    uintptr_t data, njs_bool_t delete);
-static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, void *obj,
-    njs_value_t *keys); /*FIXME*/
-static njs_int_t ngx_http_js_ext_get_status(njs_vm_t *vm, njs_value_t *value,
-    void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_set_status(njs_vm_t *vm, void *obj,
-    uintptr_t data, njs_str_t *value);
+static njs_int_t ngx_http_js_ext_header_out(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 ngx_http_js_ext_keys_header_out(njs_vm_t *vm,
+    njs_value_t *value, njs_value_t *keys);
+static njs_int_t ngx_http_js_ext_status(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 ngx_http_js_ext_send_header(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused);
 static njs_int_t ngx_http_js_ext_send(njs_vm_t *vm, njs_value_t *args,
@@ -85,32 +81,30 @@ static njs_int_t ngx_http_js_ext_interna
     njs_value_t *args, njs_uint_t nargs, njs_index_t unused);
 
 static njs_int_t ngx_http_js_ext_log(njs_vm_t *vm, njs_value_t *args,
-    njs_uint_t nargs, njs_index_t unused);
-static njs_int_t ngx_http_js_ext_warn(njs_vm_t *vm, njs_value_t *args,
-    njs_uint_t nargs, njs_index_t unused);
-static njs_int_t ngx_http_js_ext_error(njs_vm_t *vm, njs_value_t *args,
-    njs_uint_t nargs, njs_index_t unused);
-static njs_int_t ngx_http_js_ext_log_core(njs_vm_t *vm, njs_value_t *args,
-    njs_uint_t nargs, ngx_uint_t level);
+    njs_uint_t nargs, njs_index_t level);
 
 static njs_int_t ngx_http_js_ext_get_http_version(njs_vm_t *vm,
-    njs_value_t *value, void *obj, uintptr_t data);
+    njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
+    njs_value_t *retval);
 static njs_int_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm,
-    njs_value_t *value, void *obj, uintptr_t data);
+    njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
+    njs_value_t *retval);
 static njs_int_t ngx_http_js_ext_get_request_body(njs_vm_t *vm,
-    njs_value_t *value, void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_get_header_in(njs_vm_t *vm, njs_value_t *value,
-    void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_keys_header_in(njs_vm_t *vm, void *obj,
-    njs_value_t *keys); /*FIXME*/
-static njs_int_t ngx_http_js_ext_get_arg(njs_vm_t *vm, njs_value_t *value,
-    void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_keys_arg(njs_vm_t *vm, void *obj,
+    njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
+    njs_value_t *retval);
+static njs_int_t ngx_http_js_ext_get_header_in(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 ngx_http_js_ext_keys_header_in(njs_vm_t *vm,
+    njs_value_t *value, njs_value_t *keys);
+static njs_int_t ngx_http_js_ext_get_arg(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 ngx_http_js_ext_keys_arg(njs_vm_t *vm, njs_value_t *value,
     njs_value_t *keys);
-static njs_int_t ngx_http_js_ext_get_variable(njs_vm_t *vm, njs_value_t *value,
-    void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_set_variable(njs_vm_t *vm, void *obj,
-       uintptr_t data, njs_str_t *value);
+static njs_int_t ngx_http_js_ext_variables(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 ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused);
 static ngx_int_t ngx_http_js_subrequest(ngx_http_request_t *r,
@@ -118,10 +112,12 @@ static ngx_int_t ngx_http_js_subrequest(
     ngx_http_request_t **sr);
 static ngx_int_t ngx_http_js_subrequest_done(ngx_http_request_t *r,
     void *data, ngx_int_t rc);
-static njs_int_t ngx_http_js_ext_get_parent(njs_vm_t *vm, njs_value_t *value,
-    void *obj, uintptr_t data);
-static njs_int_t ngx_http_js_ext_get_reply_body(njs_vm_t *vm,
-    njs_value_t *value, void *obj, uintptr_t data);
+static njs_int_t ngx_http_js_ext_get_parent(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 ngx_http_js_ext_get_response_body(njs_vm_t *vm,
+    njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
+    njs_value_t *retval);
 
 static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external,
     uint64_t delay, njs_vm_event_t vm_event);
@@ -211,251 +207,234 @@ ngx_module_t  ngx_http_js_module = {
 
 static njs_external_t  ngx_http_js_ext_request[] = {
 
-    { njs_str("uri"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_string,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      offsetof(ngx_http_request_t, uri) },
-
-    { njs_str("method"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_string,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      offsetof(ngx_http_request_t, method_name) },
-
-    { njs_str("httpVersion"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_http_version,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("remoteAddress"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_remote_address,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("parent"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_parent,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("requestBody"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_request_body,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("responseBody"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_reply_body,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("headersIn"),
-      NJS_EXTERN_OBJECT,
-      NULL,
-      0,
-      ngx_http_js_ext_get_header_in,
-      NULL,
-      NULL,
-      ngx_http_js_ext_keys_header_in,
-      NULL,
-      0 },
-
-    { njs_str("args"),
-      NJS_EXTERN_OBJECT,
-      NULL,
-      0,
-      ngx_http_js_ext_get_arg,
-      NULL,
-      NULL,
-      ngx_http_js_ext_keys_arg,
-      NULL,
-      0 },
-
-    { njs_str("variables"),
-      NJS_EXTERN_OBJECT,
-      NULL,
-      0,
-      ngx_http_js_ext_get_variable,
-      ngx_http_js_ext_set_variable,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("status"),
-      NJS_EXTERN_PROPERTY,
-      NULL,
-      0,
-      ngx_http_js_ext_get_status,
-      ngx_http_js_ext_set_status,
-      NULL,
-      NULL,
-      NULL,
-      0 },
-
-    { njs_str("headersOut"),
-      NJS_EXTERN_OBJECT,
-      NULL,
-      0,
-      ngx_http_js_ext_get_header_out,
-      ngx_http_js_ext_set_header_out,
-      ngx_http_js_ext_delete_header_out,
-      ngx_http_js_ext_keys_header_out,
-      NULL,
-      0 },
-
-    { njs_str("subrequest"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_subrequest,
-      0 },
-
-    { njs_str("log"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_log,
-      0 },
-
-    { njs_str("warn"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_warn,
-      0 },
-
-    { njs_str("error"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_error,
-      0 },
-
-    { njs_str("sendHeader"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_send_header,
-      0 },
-
-    { njs_str("send"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_send,
-      0 },
-
-    { njs_str("finish"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_finish,
-      0 },
-
-    { njs_str("return"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_return,
-      0 },
-
-    { njs_str("internalRedirect"),
-      NJS_EXTERN_METHOD,
-      NULL,
-      0,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      ngx_http_js_ext_internal_redirect,
-      0 },
-};
-
-
-static njs_external_t  ngx_http_js_externals[] = {
-
-    { njs_str("request"),
-      NJS_EXTERN_OBJECT,
-      ngx_http_js_ext_request,
-      njs_nitems(ngx_http_js_ext_request),
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0 },
+    {
+        .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL,
+        .name.symbol = NJS_SYMBOL_TO_STRING_TAG,
+        .u.property = {
+            .value = "Request",
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("uri"),
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_get_string,
+            .magic32 = offsetof(ngx_http_request_t, uri),
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("method"),
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_get_string,
+            .magic32 = offsetof(ngx_http_request_t, method_name),
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("httpVersion"),
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_get_http_version,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("remoteAddress"),
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_get_remote_address,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("requestBody"),
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_get_request_body,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("parent"),
+        .u.property = {
+            .handler = ngx_http_js_ext_get_parent,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("responseBody"),
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_get_response_body,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("headersIn"),
+        .enumerable = 1,
+        .u.object = {
+            .enumerable = 1,
+            .prop_handler = ngx_http_js_ext_get_header_in,
+            .keys = ngx_http_js_ext_keys_header_in,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("args"),
+        .enumerable = 1,
+        .u.object = {
+            .enumerable = 1,
+            .prop_handler = ngx_http_js_ext_get_arg,
+            .keys = ngx_http_js_ext_keys_arg,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("variables"),
+        .u.object = {
+            .writable = 1,
+            .prop_handler = ngx_http_js_ext_variables,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_PROPERTY,
+        .name.string = njs_str("status"),
+        .writable = 1,
+        .enumerable = 1,
+        .u.property = {
+            .handler = ngx_http_js_ext_status,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("headersOut"),
+        .enumerable = 1,
+        .u.object = {
+            .writable = 1,
+            .configurable = 1,
+            .enumerable = 1,
+            .prop_handler = ngx_http_js_ext_header_out,
+            .keys = ngx_http_js_ext_keys_header_out,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("subrequest"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_subrequest,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("log"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_log,
+            .magic8 = NGX_LOG_INFO,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("warn"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_log,
+            .magic8 = NGX_LOG_WARN,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("error"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_log,
+            .magic8 = NGX_LOG_ERR,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("sendHeader"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_send_header,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("send"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_send,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("finish"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_finish,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("return"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_return,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("internalRedirect"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = ngx_http_js_ext_internal_redirect,
+        }
+    },
+
 };
 
 
@@ -745,7 +724,7 @@ ngx_http_js_init_vm(ngx_http_request_t *
     }
 
     rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->request),
-                                jmcf->req_proto, r);
+                                jmcf->req_proto, r, 0);
     if (rc != NJS_OK) {
         return NGX_ERROR;
     }
@@ -777,29 +756,32 @@ ngx_http_js_cleanup_vm(void *data)
 
 
 static njs_int_t
-ngx_http_js_ext_get_string(njs_vm_t *vm, njs_value_t *value, void *obj,
-    uintptr_t data)
+ngx_http_js_ext_get_string(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
 {
-    char *p = obj;
-
+    char       *p;
     ngx_str_t  *field;
 
-    field = (ngx_str_t *) (p + data);
-
-    return njs_vm_value_string_set(vm, value, field->data, field->len);
+    p = njs_vm_external(vm, value);
+    if (p == NULL) {
+        njs_value_undefined_set(retval);
+        return NJS_DECLINED;
+    }
+
+    field = (ngx_str_t *) (p + njs_vm_prop_magic32(prop));
+
+    return njs_vm_value_string_set(vm, retval, field->data, field->len);
 }
 
 
 static njs_int_t
-ngx_http_js_ext_keys_header(njs_vm_t *vm, void *obj, njs_value_t *keys,
+ngx_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys,
     uintptr_t data)
 {
-    char *p = obj;
-
+    char             *p;
     njs_int_t         rc, cookie, x_for;
     ngx_uint_t        item;
     ngx_list_t       *headers;
-    njs_value_t      *value;
     ngx_list_part_t  *part;
     ngx_table_elt_t  *header, *h;
 
@@ -808,6 +790,11 @@ ngx_http_js_ext_keys_header(njs_vm_t *vm
         return NJS_ERROR;
     }
 
+    p = njs_vm_external(vm, value);
+    if (p == NULL) {
+        return NJS_OK;
+    }
+
     headers = (ngx_list_t *) (p + data);
     part = &headers->part;
     item = 0;
@@ -903,78 +890,96 @@ ngx_http_js_get_header(ngx_list_part_t *
 
 
 static njs_int_t
-ngx_http_js_ext_get_header_out(njs_vm_t *vm, njs_value_t *value, void *obj,
-    uintptr_t data)
+ngx_http_js_ext_header_out(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
 {
     u_char              *p, *start;
-    njs_str_t           *v;
+    njs_int_t            rc;
+    ngx_int_t            n;
+    njs_str_t           *v, s, name;
     ngx_str_t           *hdr;
     ngx_table_elt_t     *h;
     ngx_http_request_t  *r;
     u_char               content_len[NGX_OFF_T_LEN];
 
-    r = (ngx_http_request_t *) obj;
-    v = (njs_str_t *) data;
+    r = njs_vm_external(vm, value);
+    if (r == NULL) {
+        if (retval != NULL) {
+            njs_value_undefined_set(retval);
+        }
+
+        return NJS_DECLINED;
+    }
+
+    rc = njs_vm_prop_name(vm, prop, &name);
+    if (rc != NJS_OK) {
+        if (retval != NULL) {
+            njs_value_undefined_set(retval);
+        }
+
+        return NJS_DECLINED;
+    }
+
+    v = &name;
+
+    if (retval != NULL && setval == NULL) {
+        if (v->length == njs_length("Content-Type")
+            && ngx_strncasecmp(v->start, (u_char *) "Content-Type",
+                               v->length) == 0)
+        {
+            hdr = &r->headers_out.content_type;
+            return njs_vm_value_string_set(vm, retval, hdr->data, hdr->len);
+        }
+
+        if (v->length == njs_length("Content-Length")
+            && ngx_strncasecmp(v->start, (u_char *) "Content-Length",
+                               v->length) == 0)
+        {
+            if (r->headers_out.content_length == NULL
+                && r->headers_out.content_length_n >= 0)
+            {
+                p = ngx_sprintf(content_len, "%O",
+                                r->headers_out.content_length_n);
+
+                start = njs_vm_value_string_alloc(vm, retval, p - content_len);
+                if (start == NULL) {
+                    return NJS_ERROR;
+                }
+
+                ngx_memcpy(start, content_len, p - content_len);
+
+                return NJS_OK;
+            }
+        }
+
+        h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start,
+                                   v->length);
+        if (h == NULL) {
+            njs_value_undefined_set(retval);
+            return NJS_DECLINED;
+        }
+
+        return njs_vm_value_string_set(vm, retval, h->value.data, h->value.len);
+    }
+
+    if (setval != NULL) {
+        rc = ngx_http_js_string(vm, setval, &s);
+        if (rc != NJS_OK) {
+            return NJS_ERROR;
+        }
+
+    } else {
+        s.length = 0;
+        s.start = NULL;
+    }
 
     if (v->length == njs_length("Content-Type")
         && ngx_strncasecmp(v->start, (u_char *) "Content-Type",
                            v->length) == 0)
     {
-        hdr = &r->headers_out.content_type;
-        return njs_vm_value_string_set(vm, value, hdr->data, hdr->len);
-    }
-
-    if (v->length == njs_length("Content-Length")
-        && ngx_strncasecmp(v->start, (u_char *) "Content-Length",
-                           v->length) == 0)
-    {
-        if (r->headers_out.content_length == NULL
-            && r->headers_out.content_length_n >= 0)
-        {
-            p = ngx_sprintf(content_len, "%O", r->headers_out.content_length_n);
-
-            start = njs_vm_value_string_alloc(vm, value, p - content_len);
-            if (start == NULL) {
-                return NJS_ERROR;
-            }
-
-            ngx_memcpy(start, content_len, p - content_len);
-
-            return NJS_OK;
-        }
-    }
-
-    h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start,
-                               v->length);
-    if (h == NULL) {
-        njs_value_undefined_set(value);
-        return NJS_OK;
-    }
-
-    return njs_vm_value_string_set(vm, value, h->value.data, h->value.len);
-}
-
-
-static njs_int_t
-ngx_http_js_ext_set_header_out(njs_vm_t *vm, void *obj, uintptr_t data,
-    njs_str_t *value)
-{
-    u_char              *p;
-    ngx_int_t            n;
-    njs_str_t           *v;
-    ngx_table_elt_t     *h;
-    ngx_http_request_t  *r;
-
-    r = (ngx_http_request_t *) obj;
-    v = (njs_str_t *) data;
-
-    if (v->length == njs_length("Content-Type")
-        && ngx_strncasecmp(v->start, (u_char *) "Content-Type",
-                           v->length) == 0)
-    {
-        r->headers_out.content_type.len = value->length;
+        r->headers_out.content_type.len = s.length;
         r->headers_out.content_type_len = r->headers_out.content_type.len;
-        r->headers_out.content_type.data = value->start;
+        r->headers_out.content_type.data = s.start;
         r->headers_out.content_type_lowcase = NULL;
 
         return NJS_OK;
@@ -983,12 +988,12 @@ ngx_http_js_ext_set_header_out(njs_vm_t 
     h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start,
                                v->length);
 
-    if (h != NULL && value->length == 0) {
+    if (h != NULL && s.length == 0) {
         h->hash = 0;
         h = NULL;
     }
 
-    if (h == NULL && value->length != 0) {
+    if (h == NULL && s.length != 0) {
         h = ngx_list_push(&r->headers_out.headers);
         if (h == NULL) {
             return NJS_ERROR;
@@ -1006,15 +1011,15 @@ ngx_http_js_ext_set_header_out(njs_vm_t 
     }
 
     if (h != NULL) {
-        p = ngx_pnalloc(r->pool, value->length);
+        p = ngx_pnalloc(r->pool, s.length);
         if (p == NULL) {
             return NJS_ERROR;
         }
 
-        ngx_memcpy(p, value->start, value->length);
+        ngx_memcpy(p, s.start, s.length);
 
         h->value.data = p;
-        h->value.len = value->length;
+        h->value.len = s.length;
         h->hash = 1;
     }
 
@@ -1030,7 +1035,7 @@ ngx_http_js_ext_set_header_out(njs_vm_t 
                            v->length) == 0)
     {
         if (h != NULL) {
-            n = ngx_atoi(value->start, value->length);
+            n = ngx_atoi(s.start, s.length);
             if (n == NGX_ERROR) {
                 h->hash = 0;
                 njs_vm_error(vm, "failed converting argument to integer");
@@ -1050,53 +1055,44 @@ ngx_http_js_ext_set_header_out(njs_vm_t 
 
 
 static njs_int_t
-ngx_http_js_ext_delete_header_out(njs_vm_t *vm, void *obj, uintptr_t data,
-    njs_bool_t unused)
+ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value,
+    njs_value_t *keys)
 {
-    njs_str_t  value;
-
-    value = njs_str_value("");
-
-    return ngx_http_js_ext_set_header_out(vm, obj, data, &value);
-}
-
-
-static njs_int_t
-ngx_http_js_ext_keys_header_out(njs_vm_t *vm, void *obj, njs_value_t *keys)
-{
-    return ngx_http_js_ext_keys_header(vm, obj, keys,
+    return ngx_http_js_ext_keys_header(vm, value, keys,
                              offsetof(ngx_http_request_t, headers_out.headers));
 }
 
 
 static njs_int_t
-ngx_http_js_ext_get_status(njs_vm_t *vm, njs_value_t *value, void *obj,
-    uintptr_t data)
+ngx_http_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
 {
+    njs_int_t            rc;
+    ngx_int_t            n;
+    njs_str_t            s;
     ngx_http_request_t  *r;
 
-    r = (ngx_http_request_t *) obj;
-
-    njs_value_number_set(value, r->headers_out.status);
-
-    return NJS_OK;
-}
-
-
-static njs_int_t
-ngx_http_js_ext_set_status(njs_vm_t *vm, void *obj, uintptr_t data,
-    njs_str_t *value)
-{
-    ngx_int_t            n;
-    ngx_http_request_t  *r;
-
-    n = ngx_atoi(value->start, value->length);
+    r = njs_vm_external(vm, value);
+    if (r == NULL) {
+        njs_value_undefined_set(retval);
+        return NJS_DECLINED;
+    }
+
+    if (setval == NULL) {
+        njs_value_number_set(retval, r->headers_out.status);
+        return NJS_OK;
+    }
+
+    rc = ngx_http_js_string(vm, setval, &s);
+    if (rc != NJS_OK) {
+        return NJS_ERROR;
+    }
+
+    n = ngx_atoi(s.start, s.length);
     if (n == NGX_ERROR) {
         return NJS_ERROR;
     }
 
-    r = (ngx_http_request_t *) obj;
-
     r->headers_out.status = n;
 
     return NJS_OK;
@@ -1110,7 +1106,8 @@ ngx_http_js_ext_send_header(njs_vm_t *vm
     ngx_http_request_t  *r;
 
     r = njs_vm_external(vm, njs_arg(args, nargs, 0));
-    if (njs_slow_path(r == NULL)) {
+    if (r == NULL) {
+        njs_vm_error(vm, "\"this\" is not an external");
         return NJS_ERROR;
     }
 
@@ -1139,7 +1136,8 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v
     ngx_http_request_t  *r;
 
     r = njs_vm_external(vm, njs_arg(args, nargs, 0));
-    if (njs_slow_path(r == NULL)) {
+    if (r == NULL) {
+        njs_vm_error(vm, "\"this\" is not an external");
         return NJS_ERROR;


More information about the nginx-devel mailing list