static njs_int_t ngx_http_js_ext_internal_redirect(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(njs_vm_t *vm, njs_value_t *args,
- njs_uint_t nargs, njs_index_t level);
-
static njs_int_t ngx_http_js_ext_get_http_version(njs_vm_t *vm,
njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
njs_value_t *retval);
.configurable = 1,
.enumerable = 1,
.u.method = {
- .native = ngx_http_js_ext_log,
+ .native = ngx_js_ext_log,
.magic8 = NGX_LOG_INFO,
}
},
.configurable = 1,
.enumerable = 1,
.u.method = {
- .native = ngx_http_js_ext_log,
+ .native = ngx_js_ext_log,
.magic8 = NGX_LOG_WARN,
}
},
.configurable = 1,
.enumerable = 1,
.u.method = {
- .native = ngx_http_js_ext_log,
+ .native = ngx_js_ext_log,
.magic8 = NGX_LOG_ERR,
}
},
};
+static uintptr_t ngx_http_js_uptr[] = {
+ offsetof(ngx_http_request_t, connection),
+};
+
+
+static njs_vm_meta_t ngx_http_js_metas = {
+ .size = 1,
+ .values = ngx_http_js_uptr
+};
+
+
static ngx_int_t
ngx_http_js_content_handler(ngx_http_request_t *r)
{
}
-static njs_int_t
-ngx_http_js_ext_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t level)
-{
- njs_str_t msg;
- ngx_connection_t *c;
- ngx_log_handler_pt handler;
- ngx_http_request_t *r;
-
- r = njs_vm_external(vm, njs_arg(args, nargs, 0));
- if (r == NULL) {
- return NJS_ERROR;
- }
-
- c = r->connection;
-
- if (njs_vm_value_to_string(vm, &msg, njs_arg(args, nargs, 1))
- == NJS_ERROR)
- {
- return NJS_ERROR;
- }
-
- handler = c->log->handler;
- c->log->handler = NULL;
-
- ngx_log_error(level, c->log, 0, "js: %*s", msg.length, msg.start);
-
- c->log->handler = handler;
-
- njs_value_undefined_set(njs_vm_retval(vm));
-
- return NJS_OK;
-}
-
-
static njs_int_t
ngx_http_js_ext_get_http_version(njs_vm_t *vm, njs_object_prop_t *prop,
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
options.backtrace = 1;
options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW;
options.ops = &ngx_http_js_ops;
+ options.metas = &ngx_http_js_metas;
options.argv = ngx_argv;
options.argc = ngx_argc;
}
jmcf->req_proto = proto;
+
+ rc = ngx_js_core_init(jmcf->vm, cf->log);
+ if (njs_slow_path(rc != NJS_OK)) {
+ return NGX_CONF_ERROR;
+ }
+
end = start + size;
rc = njs_vm_compile(jmcf->vm, &start, end);
#include "ngx_js.h"
+static njs_external_t ngx_js_ext_core[] = {
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("log"),
+ .writable = 1,
+ .configurable = 1,
+ .enumerable = 1,
+ .u.method = {
+ .native = ngx_js_ext_log,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("INFO"),
+ .u.property = {
+ .handler = ngx_js_ext_constant,
+ .magic32 = NGX_LOG_INFO,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("WARN"),
+ .u.property = {
+ .handler = ngx_js_ext_constant,
+ .magic32 = NGX_LOG_WARN,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("ERR"),
+ .u.property = {
+ .handler = ngx_js_ext_constant,
+ .magic32 = NGX_LOG_ERR,
+ }
+ },
+};
+
+
ngx_int_t
ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, njs_opaque_value_t *value,
ngx_log_t *log)
}
+ngx_int_t
+ngx_js_integer(njs_vm_t *vm, njs_value_t *value, ngx_int_t *n)
+{
+ if (!njs_value_is_valid_number(value)) {
+ njs_vm_error(vm, "is not a number");
+ return NGX_ERROR;
+ }
+
+ *n = njs_value_number(value);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str)
+{
+ if (value != NULL && !njs_value_is_null_or_undefined(value)) {
+ if (njs_vm_value_to_string(vm, str, value) == NJS_ERROR) {
+ return NGX_ERROR;
+ }
+
+ } else {
+ str->start = NULL;
+ str->length = 0;
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_js_core_init(njs_vm_t *vm, ngx_log_t *log)
+{
+ njs_int_t ret;
+ njs_str_t name;
+ njs_opaque_value_t value;
+ njs_external_proto_t proto;
+
+ proto = njs_vm_external_prototype(vm, ngx_js_ext_core,
+ njs_nitems(ngx_js_ext_core));
+ if (proto == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, log, 0, "failed to add js core proto");
+ return NGX_ERROR;
+ }
+
+ ret = njs_vm_external_create(vm, njs_value_arg(&value), proto, NULL, 1);
+ if (njs_slow_path(ret != NJS_OK)) {
+ ngx_log_error(NGX_LOG_EMERG, log, 0,
+ "njs_vm_external_create() failed\n");
+ return NGX_ERROR;
+ }
+
+ name.length = 3;
+ name.start = (u_char *) "ngx";
+
+ ret = njs_vm_bind(vm, &name, njs_value_arg(&value), 1);
+ if (njs_slow_path(ret != NJS_OK)) {
+ ngx_log_error(NGX_LOG_EMERG, log, 0, "njs_vm_bind() failed\n");
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
njs_int_t
ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value,
njs_value_t *setval, njs_value_t *retval)
}
-ngx_int_t
-ngx_js_integer(njs_vm_t *vm, njs_value_t *value, ngx_int_t *n)
+njs_int_t
+ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop,
+ njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
{
- if (!njs_value_is_valid_number(value)) {
- njs_vm_error(vm, "is not a number");
- return NGX_ERROR;
- }
-
- *n = njs_value_number(value);
+ njs_value_number_set(retval, njs_vm_prop_magic32(prop));
- return NGX_OK;
+ return NJS_OK;
}
-ngx_int_t
-ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str)
+njs_int_t
+ngx_js_ext_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t level)
{
- if (value != NULL && !njs_value_is_null_or_undefined(value)) {
- if (njs_vm_value_to_string(vm, str, value) == NJS_ERROR) {
- return NGX_ERROR;
+ char *p;
+ ngx_int_t lvl;
+ njs_str_t msg;
+ njs_value_t *value;
+ ngx_connection_t *c;
+ ngx_log_handler_pt handler;
+
+ p = njs_vm_external(vm, njs_arg(args, nargs, 0));
+ if (p == NULL) {
+ njs_vm_error(vm, "\"this\" is not an external");
+ return NJS_ERROR;
+ }
+
+ value = njs_arg(args, nargs, (level != 0) ? 1 : 2);
+
+ if (level == 0) {
+ if (ngx_js_integer(vm, njs_arg(args, nargs, 1), &lvl) != NGX_OK) {
+ return NJS_ERROR;
}
- } else {
- str->start = NULL;
- str->length = 0;
+ level = lvl;
}
- return NGX_OK;
+ if (ngx_js_string(vm, value, &msg) != NGX_OK) {
+ return NJS_ERROR;
+ }
+
+ c = ngx_external_connection(vm, p);
+ handler = c->log->handler;
+ c->log->handler = NULL;
+
+ ngx_log_error(level, c->log, 0, "js: %*s", msg.length, msg.start);
+
+ c->log->handler = handler;
+
+ njs_value_undefined_set(njs_vm_retval(vm));
+
+ return NJS_OK;
}
+
+
#include <njs.h>
+#define ngx_external_connection(vm, ext) \
+ (*((ngx_connection_t **) ((u_char *) ext + njs_vm_meta(vm, 0))))
+
+
ngx_int_t ngx_js_call(njs_vm_t *vm, ngx_str_t *s, njs_opaque_value_t *value,
ngx_log_t *log);
+njs_int_t ngx_js_ext_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t level);
+
njs_int_t ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop,
njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
+njs_int_t ngx_js_ext_constant(njs_vm_t *vm, njs_object_prop_t *prop,
+ njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
+
+ngx_int_t ngx_js_core_init(njs_vm_t *vm, ngx_log_t *log);
ngx_int_t ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str);
ngx_int_t ngx_js_integer(njs_vm_t *vm, njs_value_t *value, ngx_int_t *n);
static njs_int_t ngx_stream_js_ext_done(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused);
-static njs_int_t ngx_stream_js_ext_log(njs_vm_t *vm, njs_value_t *args,
- njs_uint_t nargs, njs_index_t unused);
static njs_int_t ngx_stream_js_ext_on(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused);
static njs_int_t ngx_stream_js_ext_off(njs_vm_t *vm, njs_value_t *args,
.configurable = 1,
.enumerable = 1,
.u.method = {
- .native = ngx_stream_js_ext_log,
+ .native = ngx_js_ext_log,
.magic8 = NGX_LOG_INFO,
}
},
.configurable = 1,
.enumerable = 1,
.u.method = {
- .native = ngx_stream_js_ext_log,
+ .native = ngx_js_ext_log,
.magic8 = NGX_LOG_WARN,
}
},
.configurable = 1,
.enumerable = 1,
.u.method = {
- .native = ngx_stream_js_ext_log,
+ .native = ngx_js_ext_log,
.magic8 = NGX_LOG_ERR,
}
},
};
+static uintptr_t ngx_stream_js_uptr[] = {
+ offsetof(ngx_stream_session_t, connection),
+};
+
+
+static njs_vm_meta_t ngx_stream_js_metas = {
+ .size = 1,
+ .values = ngx_stream_js_uptr
+};
+
+
static ngx_stream_filter_pt ngx_stream_next_filter;
}
-static njs_int_t
-ngx_stream_js_ext_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t level)
-{
- njs_str_t msg;
- ngx_connection_t *c;
- ngx_log_handler_pt handler;
- ngx_stream_session_t *s;
-
- s = njs_vm_external(vm, njs_arg(args, nargs, 0));
- if (s == NULL) {
- njs_vm_error(vm, "\"this\" is not an external");
- return NJS_ERROR;
- }
-
- c = s->connection;
-
- if (njs_vm_value_to_string(vm, &msg, njs_arg(args, nargs, 1))
- == NJS_ERROR)
- {
- return NJS_ERROR;
- }
-
- handler = c->log->handler;
- c->log->handler = NULL;
-
- ngx_log_error(level, c->log, 0, "js: %*s", msg.length, msg.start);
-
- c->log->handler = handler;
-
- njs_value_undefined_set(njs_vm_retval(vm));
-
- return NJS_OK;
-}
-
-
static njs_int_t
ngx_stream_js_ext_on(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
options.backtrace = 1;
options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW;
options.ops = &ngx_stream_js_ops;
+ options.metas = &ngx_stream_js_metas;
options.argv = ngx_argv;
options.argc = ngx_argc;
} njs_vm_ops_t;
+typedef struct {
+ size_t size;
+ uintptr_t *values;
+} njs_vm_meta_t;
+
+
typedef struct {
njs_external_ptr_t external;
njs_vm_shared_t *shared;
njs_vm_ops_t *ops;
+ njs_vm_meta_t *metas;
njs_str_t file;
char **argv;
njs_external_proto_t proto, njs_external_ptr_t external, njs_bool_t shared);
NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
const njs_value_t *value);
+NJS_EXPORT uintptr_t njs_vm_meta(njs_vm_t *vm, njs_uint_t index);
NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm,
njs_function_native_t native);
njs_external_ptr_t
njs_vm_external(njs_vm_t *vm, const njs_value_t *value)
{
+ njs_external_ptr_t external;
+
if (njs_fast_path(njs_is_object_data(value, NJS_DATA_TAG_EXTERNAL))) {
- return njs_object_data(value);
+ external = njs_object_data(value);
+ if (external == NULL) {
+ external = vm->external;
+ }
+
+ return external;
}
return NULL;
}
+uintptr_t
+njs_vm_meta(njs_vm_t *vm, njs_uint_t index)
+{
+ njs_vm_meta_t *metas;
+
+ metas = vm->options.metas;
+ if (njs_slow_path(metas == NULL || metas->size <= index)) {
+ return -1;
+ }
+
+ return metas->values[index];
+}
+
+
void
njs_vm_retval_set(njs_vm_t *vm, const njs_value_t *value)
{