]> git.kaiwu.me - njs.git/commitdiff
Modules: introduced global "ngx" object.
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 2 Oct 2020 18:38:12 +0000 (18:38 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Fri, 2 Oct 2020 18:38:12 +0000 (18:38 +0000)
nginx/ngx_http_js_module.c
nginx/ngx_js.c
nginx/ngx_js.h
nginx/ngx_stream_js_module.c
src/njs.h
src/njs_extern.c
src/njs_vm.c

index 842c6b5238543baa540b95c2de9b262347cb01a1..8685be88022408df6cc2c2d775246a6a7382e6f6 100644 (file)
@@ -122,9 +122,6 @@ static njs_int_t ngx_http_js_ext_return(njs_vm_t *vm, njs_value_t *args,
 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);
@@ -429,7 +426,7 @@ static njs_external_t  ngx_http_js_ext_request[] = {
         .configurable = 1,
         .enumerable = 1,
         .u.method = {
-            .native = ngx_http_js_ext_log,
+            .native = ngx_js_ext_log,
             .magic8 = NGX_LOG_INFO,
         }
     },
@@ -441,7 +438,7 @@ static njs_external_t  ngx_http_js_ext_request[] = {
         .configurable = 1,
         .enumerable = 1,
         .u.method = {
-            .native = ngx_http_js_ext_log,
+            .native = ngx_js_ext_log,
             .magic8 = NGX_LOG_WARN,
         }
     },
@@ -453,7 +450,7 @@ static njs_external_t  ngx_http_js_ext_request[] = {
         .configurable = 1,
         .enumerable = 1,
         .u.method = {
-            .native = ngx_http_js_ext_log,
+            .native = ngx_js_ext_log,
             .magic8 = NGX_LOG_ERR,
         }
     },
@@ -522,6 +519,17 @@ static njs_vm_ops_t ngx_http_js_ops = {
 };
 
 
+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)
 {
@@ -1788,41 +1796,6 @@ ngx_http_js_ext_internal_redirect(njs_vm_t *vm, njs_value_t *args,
 }
 
 
-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)
@@ -2946,6 +2919,7 @@ ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf)
     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;
 
@@ -3011,6 +2985,12 @@ ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf)
     }
 
     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);
index d5e9a4e0a45fc3f786cf07ed134d245ddf5afaeb..03c7877725e1dc4775a41ed4256f526350241384 100644 (file)
 #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)
@@ -45,6 +87,72 @@ ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, njs_opaque_value_t *value,
 }
 
 
+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)
@@ -64,32 +172,58 @@ ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value,
 }
 
 
-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;
 }
+
+
index f56cc0f0bba8b0f4105517abbc2e2ff70d74111e..2bd90e25ffb9f410cd937385341592a0f838ad84 100644 (file)
 #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);
index 1777d763dca0e4fc49159f6117f3b2aca7ebed4f..e177b935349a58e5245893cc630d02ed493be75d 100644 (file)
@@ -89,8 +89,6 @@ static njs_int_t ngx_stream_js_ext_get_remote_address(njs_vm_t *vm,
 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,
@@ -291,7 +289,7 @@ static njs_external_t  ngx_stream_js_ext_session[] = {
         .configurable = 1,
         .enumerable = 1,
         .u.method = {
-            .native = ngx_stream_js_ext_log,
+            .native = ngx_js_ext_log,
             .magic8 = NGX_LOG_INFO,
         }
     },
@@ -303,7 +301,7 @@ static njs_external_t  ngx_stream_js_ext_session[] = {
         .configurable = 1,
         .enumerable = 1,
         .u.method = {
-            .native = ngx_stream_js_ext_log,
+            .native = ngx_js_ext_log,
             .magic8 = NGX_LOG_WARN,
         }
     },
@@ -315,7 +313,7 @@ static njs_external_t  ngx_stream_js_ext_session[] = {
         .configurable = 1,
         .enumerable = 1,
         .u.method = {
-            .native = ngx_stream_js_ext_log,
+            .native = ngx_js_ext_log,
             .magic8 = NGX_LOG_ERR,
         }
     },
@@ -362,6 +360,17 @@ static njs_vm_ops_t ngx_stream_js_ops = {
 };
 
 
+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;
 
 
@@ -918,42 +927,6 @@ ngx_stream_js_ext_done(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 }
 
 
-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)
@@ -1418,6 +1391,7 @@ ngx_stream_js_init_main_conf(ngx_conf_t *cf, void *conf)
     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;
 
index aae784423fb9828551530a02ef79644253fd9be2..00d4e0e53188e4c50f45a8a2c0800f4d659f0cac 100644 (file)
--- a/src/njs.h
+++ b/src/njs.h
@@ -186,10 +186,17 @@ typedef struct {
 } 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;
@@ -295,6 +302,7 @@ NJS_EXPORT njs_int_t njs_vm_external_create(njs_vm_t *vm, njs_value_t *value,
     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);
index 04bd5873a9263e0ee669828650ffb93acbb64d0b..8d0ddf59e7e7e0c060f6946f0b8265c0770cbea9 100644 (file)
@@ -322,8 +322,15 @@ njs_vm_external_create(njs_vm_t *vm, njs_value_t *value,
 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;
index a574060336cdf3c972905509422927ef6273f9d4..de85bc926e69a1baa4284ca5110cd89af402d47a 100644 (file)
@@ -612,6 +612,20 @@ njs_vm_retval(njs_vm_t *vm)
 }
 
 
+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)
 {