} ngx_http_js_ctx_t;
-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;
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,
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,
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,
NULL,
NULL,
NULL,
- NULL,
offsetof(ngx_http_request_t, uri) },
{ njs_str("method"),
NULL,
NULL,
NULL,
- NULL,
offsetof(ngx_http_request_t, method_name) },
{ njs_str("httpVersion"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("remoteAddress"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("parent"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("requestBody"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("responseBody"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("headersIn"),
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 },
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 },
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("status"),
NULL,
NULL,
NULL,
- NULL,
offsetof(ngx_http_request_t, headers_out.status) },
{ njs_str("headersOut"),
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 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_subrequest,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_log,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_warn,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_error,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_send_header,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_send,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_finish,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_return,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_http_js_ext_internal_redirect,
0 },
};
NULL,
NULL,
NULL,
- NULL,
0 },
};
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;
+ 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;
- entry = ngx_palloc(r->pool, sizeof(ngx_http_js_table_entry_t));
- if (entry == NULL) {
+ rc = njs_vm_array_alloc(vm, keys, 8);
+ if (rc != NJS_OK) {
return NJS_ERROR;
}
headers = (ngx_list_t *) (p + data);
+ part = &headers->part;
+ item = 0;
- entry->part = &headers->part;
- entry->item = 0;
+ cookie = 0;
+ x_for = 0;
- e = (ngx_http_js_table_entry_t **) next;
- *e = entry;
+ while (part) {
- return NJS_OK;
-}
+ if (item >= part->nelts) {
+ part = part->next;
+ item = 0;
+ continue;
+ }
+ header = part->elts;
+ h = &header[item++];
-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;
+ if (h->hash == 0) {
+ continue;
+ }
- ngx_table_elt_t *header, *h;
- ngx_http_js_table_entry_t *entry;
+ if (h->key.len == njs_length("Cookie")
+ && ngx_strncasecmp(h->key.data, (u_char *) "Cookie",
+ h->key.len) == 0)
+ {
+ if (cookie) {
+ continue;
+ }
- entry = *e;
+ cookie = 1;
+ }
- while (entry->part) {
+ 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;
+ }
- if (entry->item >= entry->part->nelts) {
- entry->part = entry->part->next;
- entry->item = 0;
- continue;
+ x_for = 1;
}
- header = entry->part->elts;
- h = &header[entry->item++];
-
- if (h->hash == 0) {
- continue;
+ value = njs_vm_array_push(vm, keys);
+ if (value == NULL) {
+ return NJS_ERROR;
}
- return njs_vm_value_string_set(vm, value, h->key.data, h->key.len);
+ 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;
}
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));
}
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));
}
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;
-
- 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;
+ start = r->args.data;
+ end = start + r->args.len;
- p = ngx_strlchr(start, end, '&');
- if (p == NULL) {
- p = end;
- }
+ while (start < end) {
+ p = ngx_strlchr(start, end, '&');
+ if (p == NULL) {
+ p = end;
+ }
- v = ngx_strlchr(start, p, '=');
- if (v == NULL) {
- v = p;
- }
+ v = ngx_strlchr(start, p, '=');
+ if (v == NULL) {
+ v = p;
+ }
- len = v - start;
+ if (v != start) {
+ value = njs_vm_array_push(vm, keys);
+ if (value == NULL) {
+ return NJS_ERROR;
+ }
- if (p != end) {
- entry->data = &p[1];
- entry->len = end - entry->data;
+ rc = njs_vm_value_string_set(vm, value, start, v - start);
+ if (rc != NJS_OK) {
+ return NJS_ERROR;
+ }
+ }
- } else {
- entry->len = 0;
+ start = p + 1;
}
- return njs_vm_value_string_set(vm, value, start, len);
+ return NJS_OK;
}
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("variables"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("allow"),
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_done,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_deny,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_decline,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_done,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_log,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_warn,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_error,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_on,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_off,
0 },
NULL,
NULL,
NULL,
- NULL,
ngx_stream_js_ext_send,
0 },
NULL,
NULL,
NULL,
- NULL,
0 },
};
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);
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;
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) {
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;
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);
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_log,
0 },
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_dump,
0 },
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_help,
0 },
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_time,
0 },
NULL,
NULL,
NULL,
- NULL,
njs_ext_console_time_end,
0 },
};
NULL,
NULL,
NULL,
- NULL,
0 },
};
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);
}
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);
}
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,
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:
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);
vm->retval.data.u.next = next;
-done:
-
code = (njs_vmcode_prop_foreach_t *) pc;
return code->offset;
}
-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)
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") },
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;
+ njs_int_t rc, i;
+ njs_value_t *value;
+ u_char k[2];
- s = next;
- s[0] = '0';
- s[1] = '0';
-
- return NJS_OK;
-}
+ rc = njs_vm_array_alloc(vm, keys, 4);
+ if (rc != NJS_OK) {
+ return NJS_ERROR;
+ }
+ k[0] = '0';
+ k[1] = '1';
-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;
+ for (i = 0; i < 3; i++) {
+ value = njs_vm_array_push(vm, keys);
+ if (value == NULL) {
+ return NJS_ERROR;
+ }
- s = next;
- s[1]++;
+ (void) njs_vm_value_string_set(vm, value, k, 2);
- if (s[1] == '4') {
- return NJS_DONE;
+ k[1]++;
}
- return njs_vm_value_string_set(vm, value, s, 2);
+ return NJS_OK;
}
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("b"),
NULL,
NULL,
NULL,
- NULL,
42 },
};
NULL,
NULL,
NULL,
- NULL,
offsetof(njs_unit_test_req_t, uri) },
{ njs_str("host"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("props"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("vars"),
njs_unit_test_r_del_vars,
NULL,
NULL,
- NULL,
0 },
{ njs_str("consts"),
NULL,
NULL,
NULL,
- NULL,
0 },
{ njs_str("header"),
njs_unit_test_header_external,
NULL,
NULL,
- njs_unit_test_header_foreach_external,
- njs_unit_test_header_next_external,
+ njs_unit_test_header_keys_external,
NULL,
0 },
NULL,
NULL,
NULL,
- NULL,
njs_unit_test_method_external,
0 },
NULL,
NULL,
NULL,
- NULL,
njs_unit_test_create_external,
0 },
NULL,
NULL,
NULL,
- NULL,
0 },
};