[njs] Refactoring iteration over external objects.
Dmitry Volyntsev
xeioex at nginx.com
Wed Oct 23 11:47:15 UTC 2019
details: https://hg.nginx.org/njs/rev/9e327cd3a33e
branches:
changeset: 1197:9e327cd3a33e
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Wed Oct 23 14:42:38 2019 +0300
description:
Refactoring iteration over external objects.
Previously, two callbacks were required to support
array-like iteration for external objects (foreach, next).
Instead using only one callback (keys) to simplify.
diffstat:
nginx/ngx_http_js_module.c | 242 ++++++++++++++++++------------------------
nginx/ngx_stream_js_module.c | 13 --
src/njs.h | 8 +-
src/njs_extern.c | 3 +-
src/njs_extern.h | 3 +-
src/njs_json.c | 8 +-
src/njs_shell.c | 6 -
src/njs_value.c | 42 +++++++
src/njs_vmcode.c | 94 +---------------
src/test/njs_unit_test.c | 61 ++++------
10 files changed, 187 insertions(+), 293 deletions(-)
diffs (truncated from 1094 to 1000 lines):
diff -r 5e136f9a5954 -r 9e327cd3a33e nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Wed Oct 23 14:42:38 2019 +0300
+++ b/nginx/ngx_http_js_module.c Wed Oct 23 14:42:38 2019 +0300
@@ -36,12 +36,6 @@ typedef struct {
typedef struct {
- ngx_list_part_t *part;
- ngx_uint_t item;
-} ngx_http_js_table_entry_t;
-
-
-typedef struct {
ngx_http_request_t *request;
njs_vm_event_t vm_event;
void *unused;
@@ -62,10 +56,8 @@ static void ngx_http_js_cleanup_vm(void
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_foreach_header(njs_vm_t *vm, void *obj,
- void *next, uintptr_t data);
-static njs_int_t ngx_http_js_ext_next_header(njs_vm_t *vm, njs_value_t *value,
- void *obj, void *next);
+static njs_int_t ngx_http_js_ext_keys_header(njs_vm_t *vm, void *obj,
+ 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,
@@ -74,8 +66,8 @@ static njs_int_t ngx_http_js_ext_set_hea
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_foreach_header_out(njs_vm_t *vm, void *obj,
- void *next); /*FIXME*/
+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,
@@ -108,14 +100,12 @@ static njs_int_t ngx_http_js_ext_get_req
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_foreach_header_in(njs_vm_t *vm, void *obj,
- void *next); /*FIXME*/
+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_foreach_arg(njs_vm_t *vm, void *obj,
- void *next);
-static njs_int_t ngx_http_js_ext_next_arg(njs_vm_t *vm, njs_value_t *value,
- void *obj, void *next);
+static njs_int_t ngx_http_js_ext_keys_arg(njs_vm_t *vm, void *obj,
+ 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,
@@ -229,7 +219,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
offsetof(ngx_http_request_t, uri) },
{ njs_str("method"),
@@ -241,7 +230,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
offsetof(ngx_http_request_t, method_name) },
{ njs_str("httpVersion"),
@@ -253,7 +241,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("remoteAddress"),
@@ -265,7 +252,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("parent"),
@@ -277,7 +263,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("requestBody"),
@@ -289,7 +274,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("responseBody"),
@@ -301,7 +285,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("headersIn"),
@@ -311,8 +294,7 @@ static njs_external_t ngx_http_js_ext_r
ngx_http_js_ext_get_header_in,
NULL,
NULL,
- ngx_http_js_ext_foreach_header_in,
- ngx_http_js_ext_next_header,
+ ngx_http_js_ext_keys_header_in,
NULL,
0 },
@@ -323,8 +305,7 @@ static njs_external_t ngx_http_js_ext_r
ngx_http_js_ext_get_arg,
NULL,
NULL,
- ngx_http_js_ext_foreach_arg,
- ngx_http_js_ext_next_arg,
+ ngx_http_js_ext_keys_arg,
NULL,
0 },
@@ -337,7 +318,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("status"),
@@ -349,7 +329,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
offsetof(ngx_http_request_t, headers_out.status) },
{ njs_str("headersOut"),
@@ -359,8 +338,7 @@ static njs_external_t ngx_http_js_ext_r
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_foreach_header_out,
- ngx_http_js_ext_next_header,
+ ngx_http_js_ext_keys_header_out,
NULL,
0 },
@@ -372,7 +350,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_subrequest,
0 },
@@ -384,7 +361,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_log,
0 },
@@ -396,7 +372,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_warn,
0 },
@@ -408,7 +383,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_error,
0 },
@@ -420,7 +394,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_send_header,
0 },
@@ -432,7 +405,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_send,
0 },
@@ -444,7 +416,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_finish,
0 },
@@ -456,7 +427,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_return,
0 },
@@ -468,7 +438,6 @@ static njs_external_t ngx_http_js_ext_r
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_internal_redirect,
0 },
};
@@ -485,7 +454,6 @@ static njs_external_t ngx_http_js_exter
NULL,
NULL,
NULL,
- NULL,
0 },
};
@@ -822,64 +790,79 @@ ngx_http_js_ext_get_string(njs_vm_t *vm,
static njs_int_t
-ngx_http_js_ext_foreach_header(njs_vm_t *vm, void *obj, void *next,
+ngx_http_js_ext_keys_header(njs_vm_t *vm, void *obj, njs_value_t *keys,
uintptr_t data)
{
char *p = obj;
- ngx_list_t *headers;
- ngx_http_request_t *r;
- ngx_http_js_table_entry_t *entry, **e;
-
- r = (ngx_http_request_t *) obj;
-
- entry = ngx_palloc(r->pool, sizeof(ngx_http_js_table_entry_t));
- if (entry == NULL) {
+ 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;
+
+ rc = njs_vm_array_alloc(vm, keys, 8);
+ if (rc != NJS_OK) {
return NJS_ERROR;
}
headers = (ngx_list_t *) (p + data);
-
- entry->part = &headers->part;
- entry->item = 0;
-
- e = (ngx_http_js_table_entry_t **) next;
- *e = entry;
-
- return NJS_OK;
-}
-
-
-static njs_int_t
-ngx_http_js_ext_next_header(njs_vm_t *vm, njs_value_t *value, void *obj,
- void *next)
-{
- ngx_http_js_table_entry_t **e = next;
-
- ngx_table_elt_t *header, *h;
- ngx_http_js_table_entry_t *entry;
-
- entry = *e;
-
- while (entry->part) {
-
- if (entry->item >= entry->part->nelts) {
- entry->part = entry->part->next;
- entry->item = 0;
+ part = &headers->part;
+ item = 0;
+
+ cookie = 0;
+ x_for = 0;
+
+ while (part) {
+
+ if (item >= part->nelts) {
+ part = part->next;
+ item = 0;
continue;
}
- header = entry->part->elts;
- h = &header[entry->item++];
+ header = part->elts;
+ h = &header[item++];
if (h->hash == 0) {
continue;
}
- return njs_vm_value_string_set(vm, value, h->key.data, h->key.len);
+ if (h->key.len == njs_length("Cookie")
+ && ngx_strncasecmp(h->key.data, (u_char *) "Cookie",
+ h->key.len) == 0)
+ {
+ if (cookie) {
+ continue;
+ }
+
+ cookie = 1;
+ }
+
+ if (h->key.len == njs_length("X-Forwarded-For")
+ && ngx_strncasecmp(h->key.data, (u_char *) "X-Forwarded-For",
+ h->key.len) == 0)
+ {
+ if (x_for) {
+ continue;
+ }
+
+ x_for = 1;
+ }
+
+ value = njs_vm_array_push(vm, keys);
+ if (value == NULL) {
+ return NJS_ERROR;
+ }
+
+ rc = njs_vm_value_string_set(vm, value, h->key.data, h->key.len);
+ if (rc != NJS_OK) {
+ return NJS_ERROR;
+ }
}
- return NJS_DONE;
+ return NJS_OK;
}
@@ -1078,9 +1061,9 @@ ngx_http_js_ext_delete_header_out(njs_vm
static njs_int_t
-ngx_http_js_ext_foreach_header_out(njs_vm_t *vm, void *obj, void *next)
+ngx_http_js_ext_keys_header_out(njs_vm_t *vm, void *obj, njs_value_t *keys)
{
- return ngx_http_js_ext_foreach_header(vm, obj, next,
+ return ngx_http_js_ext_keys_header(vm, obj, keys,
offsetof(ngx_http_request_t, headers_out.headers));
}
@@ -1604,9 +1587,9 @@ multi:
static njs_int_t
-ngx_http_js_ext_foreach_header_in(njs_vm_t *vm, void *obj, void *next)
+ngx_http_js_ext_keys_header_in(njs_vm_t *vm, void *obj, njs_value_t *keys)
{
- return ngx_http_js_ext_foreach_header(vm, obj, next,
+ return ngx_http_js_ext_keys_header(vm, obj, keys,
offsetof(ngx_http_request_t, headers_in.headers));
}
@@ -1632,71 +1615,54 @@ ngx_http_js_ext_get_arg(njs_vm_t *vm, nj
static njs_int_t
-ngx_http_js_ext_foreach_arg(njs_vm_t *vm, void *obj, void *next)
+ngx_http_js_ext_keys_arg(njs_vm_t *vm, void *obj, njs_value_t *keys)
{
- ngx_str_t *entry, **e;
+ u_char *v, *p, *start, *end;
+ njs_int_t rc;
+ njs_value_t *value;
ngx_http_request_t *r;
r = (ngx_http_request_t *) obj;
- entry = ngx_palloc(r->pool, sizeof(ngx_str_t));
- if (entry == NULL) {
+ rc = njs_vm_array_alloc(vm, keys, 8);
+ if (rc != NJS_OK) {
return NJS_ERROR;
}
- *entry = r->args;
-
- e = (ngx_str_t **) next;
- *e = entry;
+ start = r->args.data;
+ end = start + r->args.len;
+
+ while (start < end) {
+ p = ngx_strlchr(start, end, '&');
+ if (p == NULL) {
+ p = end;
+ }
+
+ v = ngx_strlchr(start, p, '=');
+ if (v == NULL) {
+ v = p;
+ }
+
+ if (v != start) {
+ value = njs_vm_array_push(vm, keys);
+ if (value == NULL) {
+ return NJS_ERROR;
+ }
+
+ rc = njs_vm_value_string_set(vm, value, start, v - start);
+ if (rc != NJS_OK) {
+ return NJS_ERROR;
+ }
+ }
+
+ start = p + 1;
+ }
return NJS_OK;
}
static njs_int_t
-ngx_http_js_ext_next_arg(njs_vm_t *vm, njs_value_t *value, void *obj,
- void *next)
-{
- ngx_str_t **e = next;
-
- size_t len;
- u_char *v, *p, *start, *end;
- ngx_str_t *entry;
-
- entry = *e;
-
- if (entry->len == 0) {
- return NJS_DONE;
- }
-
- start = entry->data;
- end = start + entry->len;
-
- p = ngx_strlchr(start, end, '&');
- if (p == NULL) {
- p = end;
- }
-
- v = ngx_strlchr(start, p, '=');
- if (v == NULL) {
- v = p;
- }
-
- len = v - start;
-
- if (p != end) {
- entry->data = &p[1];
- entry->len = end - entry->data;
-
- } else {
- entry->len = 0;
- }
-
- return njs_vm_value_string_set(vm, value, start, len);
-}
-
-
-static njs_int_t
ngx_http_js_ext_get_variable(njs_vm_t *vm, njs_value_t *value, void *obj,
uintptr_t data)
{
diff -r 5e136f9a5954 -r 9e327cd3a33e nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Wed Oct 23 14:42:38 2019 +0300
+++ b/nginx/ngx_stream_js_module.c Wed Oct 23 14:42:38 2019 +0300
@@ -211,7 +211,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("variables"),
@@ -223,7 +222,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("allow"),
@@ -234,7 +232,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_done,
0 },
@@ -246,7 +243,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_deny,
0 },
@@ -258,7 +254,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_decline,
0 },
@@ -270,7 +265,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_done,
0 },
@@ -282,7 +276,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_log,
0 },
@@ -294,7 +287,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_warn,
0 },
@@ -306,7 +298,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_error,
0 },
@@ -318,7 +309,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_on,
0 },
@@ -330,7 +320,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_off,
0 },
@@ -342,7 +331,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_send,
0 },
@@ -360,7 +348,6 @@ static njs_external_t ngx_stream_js_ext
NULL,
NULL,
NULL,
- NULL,
0 },
};
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs.h
--- a/src/njs.h Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs.h Wed Oct 23 14:42:38 2019 +0300
@@ -66,9 +66,8 @@ typedef njs_int_t (*njs_extern_set_t)(nj
njs_str_t *value);
typedef njs_int_t (*njs_extern_find_t)(njs_vm_t *vm, void *obj, uintptr_t data,
njs_bool_t delete);
-typedef njs_int_t (*njs_extern_foreach_t)(njs_vm_t *vm, void *obj, void *next);
-typedef njs_int_t (*njs_extern_next_t)(njs_vm_t *vm, njs_value_t *value,
- void *obj, void *next);
+typedef njs_int_t (*njs_extern_keys_t)(njs_vm_t *vm, void *obj,
+ njs_value_t *keys);
typedef njs_int_t (*njs_extern_method_t)(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused);
@@ -92,8 +91,7 @@ struct njs_external_s {
njs_extern_set_t set;
njs_extern_find_t find;
- njs_extern_foreach_t foreach;
- njs_extern_next_t next;
+ njs_extern_keys_t keys;
njs_extern_method_t method;
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs_extern.c
--- a/src/njs_extern.c Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs_extern.c Wed Oct 23 14:42:38 2019 +0300
@@ -89,8 +89,7 @@ njs_vm_external_add(njs_vm_t *vm, njs_lv
ext->get = external->get;
ext->set = external->set;
ext->find = external->find;
- ext->foreach = external->foreach;
- ext->next = external->next;
+ ext->keys = external->keys;
ext->data = external->data;
if (external->method != NULL) {
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs_extern.h
--- a/src/njs_extern.h Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs_extern.h Wed Oct 23 14:42:38 2019 +0300
@@ -26,8 +26,7 @@ struct njs_extern_s {
njs_extern_set_t set;
njs_extern_find_t find;
- njs_extern_foreach_t foreach;
- njs_extern_next_t next;
+ njs_extern_keys_t keys;
njs_function_t *function;
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs_json.c
--- a/src/njs_json.c Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs_json.c Wed Oct 23 14:42:38 2019 +0300
@@ -2295,12 +2295,8 @@ njs_dump_value(njs_json_stringify_t *str
njs_dump_item("\"find\"");
}
- if (ext_proto->foreach != NULL) {
- njs_dump_item("\"foreach\"");
- }
-
- if (ext_proto->next != NULL) {
- njs_dump_item("\"next\"");
+ if (ext_proto->keys != NULL) {
+ njs_dump_item("\"keys\"");
}
return njs_json_buf_append(stringify, "]}", 2);
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs_shell.c
--- a/src/njs_shell.c Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs_shell.c Wed Oct 23 14:42:38 2019 +0300
@@ -112,7 +112,6 @@ static njs_external_t njs_ext_console[]
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_log,
0 },
@@ -124,7 +123,6 @@ static njs_external_t njs_ext_console[]
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_dump,
0 },
@@ -136,7 +134,6 @@ static njs_external_t njs_ext_console[]
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_help,
0 },
@@ -148,7 +145,6 @@ static njs_external_t njs_ext_console[]
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_time,
0 },
@@ -160,7 +156,6 @@ static njs_external_t njs_ext_console[]
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_time_end,
0 },
};
@@ -176,7 +171,6 @@ static njs_external_t njs_externals[] =
NULL,
NULL,
NULL,
- NULL,
0 },
};
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs_value.c
--- a/src/njs_value.c Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs_value.c Wed Oct 23 14:42:38 2019 +0300
@@ -191,13 +191,34 @@ njs_array_t *
njs_value_enumerate(njs_vm_t *vm, const njs_value_t *value,
njs_object_enum_t kind, njs_bool_t all)
{
+ void *obj;
+ njs_int_t ret;
+ njs_value_t keys;
njs_object_value_t obj_val;
+ const njs_extern_t *ext_proto;
if (njs_is_object(value)) {
return njs_object_enumerate(vm, njs_object(value), kind, all);
}
if (value->type != NJS_STRING) {
+ if (kind == NJS_ENUM_KEYS && njs_is_external(value)) {
+ ext_proto = value->external.proto;
+
+ if (ext_proto->keys != NULL) {
+ obj = njs_extern_object(vm, value);
+
+ ret = ext_proto->keys(vm, obj, &keys);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NULL;
+ }
+
+ return njs_array(&keys);
+ }
+
+ return njs_extern_keys_array(vm, ext_proto);
+ }
+
return njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
}
@@ -212,13 +233,34 @@ njs_array_t *
njs_value_own_enumerate(njs_vm_t *vm, const njs_value_t *value,
njs_object_enum_t kind, njs_bool_t all)
{
+ void *obj;
+ njs_int_t ret;
+ njs_value_t keys;
njs_object_value_t obj_val;
+ const njs_extern_t *ext_proto;
if (njs_is_object(value)) {
return njs_object_own_enumerate(vm, njs_object(value), kind, all);
}
if (value->type != NJS_STRING) {
+ if (kind == NJS_ENUM_KEYS && njs_is_external(value)) {
+ ext_proto = value->external.proto;
+
+ if (ext_proto->keys != NULL) {
+ obj = njs_extern_object(vm, value);
+
+ ret = ext_proto->keys(vm, obj, &keys);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NULL;
+ }
+
+ return njs_array(&keys);
+ }
+
+ return njs_extern_keys_array(vm, ext_proto);
+ }
+
return njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
}
diff -r 5e136f9a5954 -r 9e327cd3a33e src/njs_vmcode.c
--- a/src/njs_vmcode.c Wed Oct 23 14:42:38 2019 +0300
+++ b/src/njs_vmcode.c Wed Oct 23 14:42:38 2019 +0300
@@ -31,8 +31,6 @@ static njs_jump_off_t njs_vmcode_propert
njs_value_t *value, njs_value_t *key);
static njs_jump_off_t njs_vmcode_property_foreach(njs_vm_t *vm,
njs_value_t *object, njs_value_t *invld, u_char *pc);
-static njs_jump_off_t njs_vmcode_property_next(njs_vm_t *vm,
- njs_value_t *object, njs_value_t *value, u_char *pc);
static njs_jump_off_t njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
njs_value_t *constructor);
static njs_jump_off_t njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value,
@@ -771,25 +769,21 @@ next:
break;
case NJS_VMCODE_PROPERTY_NEXT:
- if (!njs_is_external(value1)) {
- pnext = (njs_vmcode_prop_next_t *) pc;
- retval = njs_vmcode_operand(vm, pnext->retval);
+ pnext = (njs_vmcode_prop_next_t *) pc;
+ retval = njs_vmcode_operand(vm, pnext->retval);
- next = value2->data.u.next;
+ next = value2->data.u.next;
- if (next->index < next->array->length) {
- *retval = next->array->data[next->index++];
+ if (next->index < next->array->length) {
+ *retval = next->array->data[next->index++];
- ret = pnext->offset;
- break;
- }
+ ret = pnext->offset;
+ break;
}
- ret = njs_vmcode_property_next(vm, value1, value2, pc);
- if (njs_slow_path(ret == NJS_ERROR)) {
- goto error;
- }
+ njs_mp_free(vm->mem_pool, next);
+ ret = sizeof(njs_vmcode_prop_next_t);
break;
case NJS_VMCODE_THIS:
@@ -1306,27 +1300,9 @@ static njs_jump_off_t
njs_vmcode_property_foreach(njs_vm_t *vm, njs_value_t *object,
njs_value_t *invld, u_char *pc)
{
- void *obj;
- njs_jump_off_t ret;
- const njs_extern_t *ext_proto;
njs_property_next_t *next;
njs_vmcode_prop_foreach_t *code;
- if (njs_is_external(object)) {
- ext_proto = object->external.proto;
-
- if (ext_proto->foreach != NULL) {
- obj = njs_extern_object(vm, object);
-
- ret = ext_proto->foreach(vm, obj, &vm->retval);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
- }
-
- goto done;
- }
-
next = njs_mp_alloc(vm->mem_pool, sizeof(njs_property_next_t));
if (njs_slow_path(next == NULL)) {
njs_memory_error(vm);
@@ -1342,8 +1318,6 @@ njs_vmcode_property_foreach(njs_vm_t *vm
vm->retval.data.u.next = next;
-done:
-
code = (njs_vmcode_prop_foreach_t *) pc;
return code->offset;
@@ -1351,56 +1325,6 @@ done:
static njs_jump_off_t
-njs_vmcode_property_next(njs_vm_t *vm, njs_value_t *object, njs_value_t *value,
- u_char *pc)
-{
- void *obj;
- njs_value_t *retval;
- njs_jump_off_t ret;
- njs_property_next_t *next;
- const njs_extern_t *ext_proto;
- njs_vmcode_prop_next_t *code;
-
- code = (njs_vmcode_prop_next_t *) pc;
- retval = njs_vmcode_operand(vm, code->retval);
-
- if (njs_is_external(object)) {
- ext_proto = object->external.proto;
-
- if (ext_proto->next != NULL) {
- obj = njs_extern_object(vm, object);
-
- ret = ext_proto->next(vm, retval, obj, value);
-
- if (ret == NJS_OK) {
- return code->offset;
- }
-
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
- }
-
- /* ret == NJS_DONE. */
- }
-
- return sizeof(njs_vmcode_prop_next_t);
- }
-
- next = value->data.u.next;
-
- if (next->index < next->array->length) {
- *retval = next->array->data[next->index++];
-
- return code->offset;
- }
-
- njs_mp_free(vm->mem_pool, next);
-
- return sizeof(njs_vmcode_prop_next_t);
-}
-
-
-static njs_jump_off_t
njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
njs_value_t *constructor)
{
diff -r 5e136f9a5954 -r 9e327cd3a33e src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Wed Oct 23 14:42:38 2019 +0300
+++ b/src/test/njs_unit_test.c Wed Oct 23 14:42:38 2019 +0300
@@ -14029,7 +14029,7 @@ static njs_unit_test_t njs_test[] =
njs_str("{a:{type:\"property\",props:[\"getter\"]},b:{type:\"property\",props:[\"getter\"]}}") },
{ njs_str("njs.dump($r.header)"),
- njs_str("{type:\"object\",props:[\"getter\",\"foreach\",\"next\"]}") },
+ njs_str("{type:\"object\",props:[\"getter\",\"keys\"]}") },
{ njs_str("njs.dump(njs) == `{version:'${njs.version}'}`"),
njs_str("true") },
@@ -14988,36 +14988,36 @@ njs_unit_test_header_external(njs_vm_t *
static njs_int_t
-njs_unit_test_header_foreach_external(njs_vm_t *vm, void *obj, void *next)
+njs_unit_test_header_keys_external(njs_vm_t *vm, void *obj, njs_value_t *keys)
{
- u_char *s;
-
- s = next;
- s[0] = '0';
- s[1] = '0';
+ njs_int_t rc, i;
+ njs_value_t *value;
+ u_char k[2];
+
+ rc = njs_vm_array_alloc(vm, keys, 4);
+ if (rc != NJS_OK) {
+ return NJS_ERROR;
+ }
+
+ k[0] = '0';
+ k[1] = '1';
+
+ for (i = 0; i < 3; i++) {
+ value = njs_vm_array_push(vm, keys);
+ if (value == NULL) {
+ return NJS_ERROR;
+ }
+
+ (void) njs_vm_value_string_set(vm, value, k, 2);
+
+ k[1]++;
+ }
return NJS_OK;
}
static njs_int_t
-njs_unit_test_header_next_external(njs_vm_t *vm, njs_value_t *value, void *obj,
- void *next)
-{
- u_char *s;
-
- s = next;
- s[1]++;
-
- if (s[1] == '4') {
- return NJS_DONE;
- }
-
- return njs_vm_value_string_set(vm, value, s, 2);
-}
-
-
More information about the nginx-devel
mailing list