summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorZhidao HONG <z.hong@f5.com>2022-11-20 23:16:51 +0800
committerZhidao HONG <z.hong@f5.com>2022-11-20 23:16:51 +0800
commit4d6d146e920667a8afeacd355e4fb6a94387066e (patch)
treed25e70f93a4f91960434c4d631072e9936f80e36
parent4735931ace321752c387dae04c8b217ef22897ee (diff)
downloadunit-4d6d146e920667a8afeacd355e4fb6a94387066e.tar.gz
unit-4d6d146e920667a8afeacd355e4fb6a94387066e.tar.bz2
Basic njs support.
-rw-r--r--auto/help2
-rw-r--r--auto/njs41
-rw-r--r--auto/options4
-rw-r--r--auto/sources4
-rw-r--r--auto/summary1
-rwxr-xr-xconfigure4
-rw-r--r--docs/changes.xml6
-rw-r--r--src/nxt_conf_validation.c33
-rw-r--r--src/nxt_http.h2
-rw-r--r--src/nxt_http_request.c2
-rw-r--r--src/nxt_http_return.c2
-rw-r--r--src/nxt_http_route.c2
-rw-r--r--src/nxt_http_static.c2
-rw-r--r--src/nxt_js.c230
-rw-r--r--src/nxt_js.h34
-rw-r--r--src/nxt_router.c7
-rw-r--r--src/nxt_router_access_log.c2
-rw-r--r--src/nxt_tstr.c128
-rw-r--r--src/nxt_tstr.h38
-rw-r--r--src/nxt_var.h7
20 files changed, 507 insertions, 44 deletions
diff --git a/auto/help b/auto/help
index e2b81bc7..a3884679 100644
--- a/auto/help
+++ b/auto/help
@@ -41,6 +41,8 @@ cat << END
--openssl enable OpenSSL library usage
+ --njs enable NJS library usage
+
--debug enable debug logging
diff --git a/auto/njs b/auto/njs
new file mode 100644
index 00000000..72304793
--- /dev/null
+++ b/auto/njs
@@ -0,0 +1,41 @@
+
+# Copyright (C) NGINX, Inc.
+
+
+nxt_found=no
+NXT_HAVE_NJS=NO
+
+NXT_NJS_CFLAGS=
+NXT_NJS_AUX_CFLAGS=
+NXT_NJS_LIBS="-lnjs"
+NXT_NJS_AUX_LIBS="$NXT_LIBM $NXT_LIB_AUX_LIBS"
+
+nxt_feature="NJS"
+nxt_feature_name=NXT_HAVE_NJS
+nxt_feature_run=no
+nxt_feature_incs="$NXT_NJS_CFLAGS $NXT_NJS_AUX_CFLAGS"
+nxt_feature_libs="$NXT_NJS_LIBS $NXT_NJS_AUX_LIBS"
+nxt_feature_test="#include <njs.h>
+
+ int main(void) {
+ njs_vm_t *vm;
+ njs_vm_opt_t opts;
+
+ njs_vm_opt_init(&opts);
+
+ vm = njs_vm_create(&opts);
+ if (vm == NULL)
+ return 1;
+ return 0;
+ }"
+. auto/feature
+
+if [ $nxt_found = no ]; then
+ $echo
+ $echo $0: error: no NJS library found.
+ $echo
+ exit 1;
+fi
+
+NXT_LIB_AUX_CFLAGS="$NXT_LIB_AUX_CFLAGS $NXT_NJS_CFLAGS"
+NXT_LIB_AUX_LIBS="$NXT_NJS_LIBS $NXT_LIB_AUX_LIBS"
diff --git a/auto/options b/auto/options
index 572d8a9b..abcf531d 100644
--- a/auto/options
+++ b/auto/options
@@ -28,6 +28,8 @@ NXT_GNUTLS=NO
NXT_CYASSL=NO
NXT_POLARSSL=NO
+NXT_NJS=NO
+
NXT_TEST_BUILD_EPOLL=NO
NXT_TEST_BUILD_EVENTPORT=NO
NXT_TEST_BUILD_DEVPOLL=NO
@@ -85,6 +87,8 @@ do
--cyassl) NXT_CYASSL=YES ;;
--polarssl) NXT_POLARSSL=YES ;;
+ --njs) NXT_NJS=YES ;;
+
--test-build-epoll) NXT_TEST_BUILD_EPOLL=YES ;;
--test-build-eventport) NXT_TEST_BUILD_EVENTPORT=YES ;;
--test-build-devpoll) NXT_TEST_BUILD_DEVPOLL=YES ;;
diff --git a/auto/sources b/auto/sources
index 7d3f62cf..9f9a27f7 100644
--- a/auto/sources
+++ b/auto/sources
@@ -135,6 +135,10 @@ NXT_LIB_POLARSSL_SRCS="src/nxt_polarssl.c"
NXT_LIB_PCRE_SRCS="src/nxt_pcre.c"
NXT_LIB_PCRE2_SRCS="src/nxt_pcre2.c"
+if [ "$NXT_NJS" != "NO" ]; then
+ NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_js.c"
+fi
+
NXT_LIB_EPOLL_SRCS="src/nxt_epoll_engine.c"
NXT_LIB_KQUEUE_SRCS="src/nxt_kqueue_engine.c"
NXT_LIB_EVENTPORT_SRCS="src/nxt_eventport_engine.c"
diff --git a/auto/summary b/auto/summary
index 79e7ce34..c8a49d08 100644
--- a/auto/summary
+++ b/auto/summary
@@ -28,6 +28,7 @@ Unit configuration summary:
Unix domain sockets support: $NXT_UNIX_DOMAIN
TLS support: ............... $NXT_OPENSSL
Regex support: ............. $NXT_REGEX
+ NJS support: ............... $NXT_NJS
process isolation: ......... $NXT_ISOLATION
diff --git a/configure b/configure
index ea86e18e..c21973eb 100755
--- a/configure
+++ b/configure
@@ -171,5 +171,9 @@ NXT_LIB_AUX_LIBS="$NXT_OPENSSL_LIBS $NXT_GNUTLS_LIBS \\
$NXT_CYASSL_LIBS $NXT_POLARSSL_LIBS \\
$NXT_PCRE_LIB"
+if [ $NXT_NJS != NO ]; then
+ . auto/njs
+fi
+
. auto/make
. auto/summary
diff --git a/docs/changes.xml b/docs/changes.xml
index 014f243d..0c52c628 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -45,6 +45,12 @@ prefer system crypto policy, instead of hardcoding a default.
<change type="feature">
<para>
+njs support with the basic syntax of JS template literals.
+</para>
+</change>
+
+<change type="feature">
+<para>
compatibility with OpenSSL 3.
</para>
</change>
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index 09b3be55..e650b44d 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -34,7 +34,7 @@ typedef enum {
typedef enum {
NXT_CONF_VLDT_REQUIRED = 1 << 0,
- NXT_CONF_VLDT_VAR = 1 << 1,
+ NXT_CONF_VLDT_TSTR = 1 << 1,
} nxt_conf_vldt_flags_t;
@@ -367,7 +367,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
.name = nxt_string("pass"),
.type = NXT_CONF_VLDT_STRING,
.validator = nxt_conf_vldt_pass,
- .flags = NXT_CONF_VLDT_VAR,
+ .flags = NXT_CONF_VLDT_TSTR,
}, {
.name = nxt_string("application"),
.type = NXT_CONF_VLDT_STRING,
@@ -652,7 +652,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = {
.name = nxt_string("pass"),
.type = NXT_CONF_VLDT_STRING,
.validator = nxt_conf_vldt_pass,
- .flags = NXT_CONF_VLDT_VAR,
+ .flags = NXT_CONF_VLDT_TSTR,
},
NXT_CONF_VLDT_END
@@ -667,7 +667,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = {
}, {
.name = nxt_string("location"),
.type = NXT_CONF_VLDT_STRING,
- .flags = NXT_CONF_VLDT_VAR,
+ .flags = NXT_CONF_VLDT_TSTR,
},
NXT_CONF_VLDT_END
@@ -697,7 +697,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
.validator = nxt_conf_vldt_unsupported,
.u.string = "chroot",
#endif
- .flags = NXT_CONF_VLDT_VAR,
+ .flags = NXT_CONF_VLDT_TSTR,
}, {
.name = nxt_string("follow_symlinks"),
.type = NXT_CONF_VLDT_BOOLEAN,
@@ -1226,8 +1226,9 @@ nxt_int_t
nxt_conf_validate(nxt_conf_validation_t *vldt)
{
nxt_int_t ret;
+ u_char error[NXT_MAX_ERROR_STR];
- vldt->tstr_state = nxt_tstr_state_new(vldt->pool);
+ vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1);
if (nxt_slow_path(vldt->tstr_state == NULL)) {
return NXT_ERROR;
}
@@ -1237,7 +1238,17 @@ nxt_conf_validate(nxt_conf_validation_t *vldt)
return ret;
}
- return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
+ ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+
+ ret = nxt_tstr_state_done(vldt->tstr_state, error);
+ if (ret != NXT_OK) {
+ return nxt_conf_vldt_error(vldt, "%s", error);
+ }
+
+ return NXT_OK;
}
@@ -1721,7 +1732,7 @@ nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,
nxt_conf_get_string(value, &str);
- if (nxt_is_var(&str)) {
+ if (nxt_is_tstr(&str)) {
return nxt_conf_vldt_var(vldt, &share, &str);
}
@@ -2501,12 +2512,12 @@ nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
continue;
}
- if (vals->flags & NXT_CONF_VLDT_VAR
+ if (vals->flags & NXT_CONF_VLDT_TSTR
&& nxt_conf_type(member) == NXT_CONF_STRING)
{
nxt_conf_get_string(member, &var);
- if (nxt_is_var(&var)) {
+ if (nxt_is_tstr(&var)) {
ret = nxt_conf_vldt_var(vldt, &name, &var);
if (ret != NXT_OK) {
return ret;
@@ -3147,7 +3158,7 @@ nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
"The \"path\" string must not be empty.");
}
- if (nxt_is_var(&conf.format)) {
+ if (nxt_is_tstr(&conf.format)) {
return nxt_conf_vldt_var(vldt, &format_str, &conf.format);
}
diff --git a/src/nxt_http.h b/src/nxt_http.h
index e29fe60a..a8725d9f 100644
--- a/src/nxt_http.h
+++ b/src/nxt_http.h
@@ -170,7 +170,7 @@ struct nxt_http_request_s {
void *timer_data;
nxt_tstr_query_t *tstr_query;
- nxt_var_cache_t var_cache;
+ nxt_tstr_cache_t tstr_cache;
void *req_rpc_data;
diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c
index 84a67415..73ffd2f0 100644
--- a/src/nxt_http_request.c
+++ b/src/nxt_http_request.c
@@ -282,7 +282,7 @@ nxt_http_request_create(nxt_task_t *task)
task->thread->engine->requests_cnt++;
- r->var_cache.pool = mp;
+ r->tstr_cache.var.pool = mp;
return r;
diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c
index 63c7e06f..b50e4ad0 100644
--- a/src/nxt_http_return.c
+++ b/src/nxt_http_return.c
@@ -126,7 +126,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r,
rtcf = r->conf->socket_conf->router_conf;
ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state,
- &r->var_cache, r, r->mem_pool);
+ &r->tstr_cache, r, r->mem_pool);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c
index 77a59e9c..7081ff7e 100644
--- a/src/nxt_http_route.c
+++ b/src/nxt_http_route.c
@@ -1306,7 +1306,7 @@ nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r,
rtcf = r->conf->socket_conf->router_conf;
- ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->var_cache,
+ ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache,
r, r->mem_pool);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c
index 7143ecd3..68174b9d 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -276,7 +276,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
rtcf = r->conf->socket_conf->router_conf;
ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state,
- &r->var_cache, r, r->mem_pool);
+ &r->tstr_cache, r, r->mem_pool);
if (nxt_slow_path(ret != NXT_OK)) {
nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
return;
diff --git a/src/nxt_js.c b/src/nxt_js.c
new file mode 100644
index 00000000..52596fe6
--- /dev/null
+++ b/src/nxt_js.c
@@ -0,0 +1,230 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+
+
+struct nxt_js_s {
+ uint32_t index;
+ njs_vm_t *vm;
+};
+
+
+struct nxt_js_conf_s {
+ nxt_mp_t *pool;
+ njs_vm_t *vm;
+ nxt_array_t *funcs;
+};
+
+
+nxt_js_conf_t *
+nxt_js_conf_new(nxt_mp_t *mp)
+{
+ njs_vm_opt_t opts;
+ nxt_js_conf_t *jcf;
+
+ jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t));
+ if (nxt_slow_path(jcf == NULL)) {
+ return NULL;
+ }
+
+ jcf->pool = mp;
+
+ njs_vm_opt_init(&opts);
+
+ jcf->vm = njs_vm_create(&opts);
+ if (nxt_slow_path(jcf->vm == NULL)) {
+ return NULL;
+ }
+
+ jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t));
+ if (nxt_slow_path(jcf->funcs == NULL)) {
+ return NULL;
+ }
+
+ return jcf;
+}
+
+
+nxt_js_t *
+nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
+{
+ size_t size;
+ u_char *p, *start;
+ nxt_js_t *js;
+ nxt_str_t *func;
+
+ static nxt_str_t func_str = nxt_string("function() {"
+ " return ");
+
+ /*
+ * Appending a terminating null character if strz is true.
+ */
+ static nxt_str_t strz_str = nxt_string(" + '\\x00'");
+
+ size = func_str.length + str->length + 1;
+
+ if (strz) {
+ size += strz_str.length;
+ }
+
+ start = nxt_mp_nget(jcf->pool, size);
+ if (nxt_slow_path(start == NULL)) {
+ return NULL;
+ }
+
+ p = start;
+
+ p = nxt_cpymem(p, func_str.start, func_str.length);
+ p = nxt_cpymem(p, str->start, str->length);
+
+ if (strz) {
+ p = nxt_cpymem(p, strz_str.start, strz_str.length);
+ }
+
+ *p++ = '}';
+
+ js = nxt_mp_get(jcf->pool, sizeof(nxt_js_t));
+ if (nxt_slow_path(js == NULL)) {
+ return NULL;
+ }
+
+ js->vm = jcf->vm;
+
+ func = nxt_array_add(jcf->funcs);
+ if (nxt_slow_path(func == NULL)) {
+ return NULL;
+ }
+
+ func->start = start;
+ func->length = p - start;
+
+ js->index = jcf->funcs->nelts - 1;
+
+ return js;
+}
+
+
+nxt_int_t
+nxt_js_compile(nxt_js_conf_t *jcf)
+{
+ size_t size;
+ u_char *p, *start;
+ njs_int_t ret;
+ nxt_str_t *func;
+ nxt_uint_t i;
+
+ size = 2;
+ func = jcf->funcs->elts;
+
+ for (i = 0; i < jcf->funcs->nelts; i++) {
+ size += func[i].length + 1;
+ }
+
+ start = nxt_mp_nget(jcf->pool, size);
+ if (nxt_slow_path(start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ p = start;
+ *p++ = '[';
+
+ func = jcf->funcs->elts;
+
+ for (i = 0; i < jcf->funcs->nelts; i++) {
+ p = nxt_cpymem(p, func[i].start, func[i].length);
+ *p++ = ',';
+ }
+
+ *p++ = ']';
+
+ ret = njs_vm_compile(jcf->vm, &start, p);
+
+ return (ret == NJS_OK) ? NXT_OK : NXT_ERROR;
+}
+
+
+nxt_int_t
+nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error)
+{
+ u_char *start;
+ nxt_str_t err;
+ njs_int_t ret;
+ njs_str_t res;
+
+ start = nxt_mp_nget(jcf->pool, str->length);
+ if (nxt_slow_path(start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nxt_memcpy(start, str->start, str->length);
+
+ ret = njs_vm_compile(jcf->vm, &start, start + str->length);
+
+ if (nxt_slow_path(ret != NJS_OK)) {
+ (void) njs_vm_retval_string(jcf->vm, &res);
+
+ err.start = res.start;
+ err.length = res.length;
+
+ nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err);
+
+ return NXT_ERROR;
+ }
+
+ return NXT_OK;
+}
+
+
+nxt_int_t
+nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
+ nxt_str_t *str, void *ctx)
+{
+ njs_vm_t *vm;
+ njs_int_t rc, ret;
+ njs_str_t res;
+ njs_value_t *array, *value;
+ njs_function_t *func;
+ njs_opaque_value_t opaque_value;
+
+ vm = cache->vm;
+
+ if (vm == NULL) {
+ vm = njs_vm_clone(js->vm, ctx);
+ if (nxt_slow_path(vm == NULL)) {
+ return NXT_ERROR;
+ }
+
+ ret = njs_vm_start(vm);
+ if (ret != NJS_OK) {
+ return NXT_ERROR;
+ }
+
+ array = njs_vm_retval(vm);
+
+ cache->vm = vm;
+ cache->array = *array;
+ }
+
+ value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value);
+ func = njs_value_function(value);
+
+ ret = njs_vm_call(vm, func, NULL, 0);
+
+ rc = njs_vm_retval_string(vm, &res);
+ if (rc != NJS_OK) {
+ return NXT_ERROR;
+ }
+
+ if (ret != NJS_OK) {
+ nxt_alert(task, "js exception: %V", &res);
+ return NXT_ERROR;
+ }
+
+ str->length = res.length;
+ str->start = res.start;
+
+ return NXT_OK;
+}
diff --git a/src/nxt_js.h b/src/nxt_js.h
new file mode 100644
index 00000000..321041ae
--- /dev/null
+++ b/src/nxt_js.h
@@ -0,0 +1,34 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_JS_H_INCLUDED_
+#define _NXT_JS_H_INCLUDED_
+
+#if (NXT_HAVE_NJS)
+
+#include <njs_main.h>
+
+
+typedef struct nxt_js_s nxt_js_t;
+typedef struct nxt_js_conf_s nxt_js_conf_t;
+
+
+typedef struct {
+ njs_vm_t *vm;
+ njs_value_t array;
+} nxt_js_cache_t;
+
+
+nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp);
+nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz);
+nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf);
+nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error);
+nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
+ nxt_str_t *str, void *ctx);
+
+
+#endif /* NXT_HAVE_NJS */
+
+#endif /* _NXT_JS_H_INCLUDED_ */
diff --git a/src/nxt_router.c b/src/nxt_router.c
index 3ad78fa4..26aa9fb1 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -1060,7 +1060,7 @@ nxt_router_temp_conf(nxt_task_t *task)
rtcf->mem_pool = mp;
- rtcf->tstr_state = nxt_tstr_state_new(mp);
+ rtcf->tstr_state = nxt_tstr_state_new(mp, 0);
if (nxt_slow_path(rtcf->tstr_state == NULL)) {
goto fail;
}
@@ -2042,6 +2042,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
}
}
+ ret = nxt_tstr_state_done(rtcf->tstr_state, NULL);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
+
nxt_queue_add(&deleting_sockets, &router->sockets);
nxt_queue_init(&router->sockets);
diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c
index 9da366f4..ccbddb96 100644
--- a/src/nxt_router_access_log.c
+++ b/src/nxt_router_access_log.c
@@ -161,7 +161,7 @@ nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r,
rtcf = r->conf->socket_conf->router_conf;
ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state,
- &r->var_cache, r, r->mem_pool);
+ &r->tstr_cache, r, r->mem_pool);
if (nxt_slow_path(ret != NXT_OK)) {
return;
}
diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c
index dff61952..fd01797c 100644
--- a/src/nxt_tstr.c
+++ b/src/nxt_tstr.c
@@ -9,12 +9,22 @@
typedef enum {
NXT_TSTR_CONST = 0,
NXT_TSTR_VAR,
+#if (NXT_HAVE_NJS)
+ NXT_TSTR_JS,
+#endif
} nxt_tstr_type_t;
struct nxt_tstr_s {
nxt_str_t str;
- nxt_var_t *var;
+
+ union {
+ nxt_var_t *var;
+#if (NXT_HAVE_NJS)
+ nxt_js_t *js;
+#endif
+ } u;
+
nxt_tstr_flags_t flags;
nxt_tstr_type_t type;
};
@@ -24,7 +34,7 @@ struct nxt_tstr_query_s {
nxt_mp_t *pool;
nxt_tstr_state_t *state;
- nxt_var_cache_t *cache;
+ nxt_tstr_cache_t *cache;
nxt_uint_t waiting;
nxt_uint_t failed; /* 1 bit */
@@ -37,8 +47,12 @@ struct nxt_tstr_query_s {
};
+#define nxt_tstr_is_js(str) \
+ nxt_strchr_start(str, '`')
+
+
nxt_tstr_state_t *
-nxt_tstr_state_new(nxt_mp_t *mp)
+nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test)
{
nxt_tstr_state_t *state;
@@ -48,12 +62,20 @@ nxt_tstr_state_new(nxt_mp_t *mp)
}
state->pool = mp;
+ state->test = test;
state->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t));
if (nxt_slow_path(state->var_fields == NULL)) {
return NULL;
}
+#if (NXT_HAVE_NJS)
+ state->jcf = nxt_js_conf_new(mp);
+ if (nxt_slow_path(state->jcf == NULL)) {
+ return NULL;
+ }
+#endif
+
return state;
}
@@ -88,18 +110,38 @@ nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str,
tstr->flags = flags;
- p = nxt_memchr(str->start, '$', str->length);
+ if (nxt_tstr_is_js(str)) {
+
+#if (NXT_HAVE_NJS)
+
+ nxt_str_t tpl;
- if (p != NULL) {
- tstr->type = NXT_TSTR_VAR;
+ tstr->type = NXT_TSTR_JS;
- tstr->var = nxt_var_compile(&tstr->str, state->pool, state->var_fields);
- if (nxt_slow_path(tstr->var == NULL)) {
+ nxt_tstr_str(tstr, &tpl);
+
+ tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, strz);
+ if (nxt_slow_path(tstr->u.js == NULL)) {
return NULL;
}
+#endif
+
} else {
- tstr->type = NXT_TSTR_CONST;
+ p = memchr(str->start, '$', str->length);
+
+ if (p != NULL) {
+ tstr->type = NXT_TSTR_VAR;
+
+ tstr->u.var = nxt_var_compile(&tstr->str, state->pool,
+ state->var_fields);
+ if (nxt_slow_path(tstr->u.var == NULL)) {
+ return NULL;
+ }
+
+ } else {
+ tstr->type = NXT_TSTR_CONST;
+ }
}
return tstr;
@@ -109,7 +151,46 @@ nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str,
nxt_int_t
nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error)
{
- return nxt_var_test(str, state->var_fields, error);
+ u_char *p;
+
+ if (nxt_tstr_is_js(str)) {
+#if (NXT_HAVE_NJS)
+ return nxt_js_test(state->jcf, str, error);
+
+#else
+ nxt_sprintf(error, error + NXT_MAX_ERROR_STR,
+ "Unit is built without support of njs: "
+ "\"--njs\" ./configure option is missing.");
+ return NXT_ERROR;
+#endif
+
+ } else {
+ p = memchr(str->start, '$', str->length);
+
+ if (p != NULL) {
+ return nxt_var_test(str, state->var_fields, error);
+ }
+ }
+
+ return NXT_OK;
+}
+
+
+nxt_int_t
+nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error)
+{
+#if (NXT_HAVE_NJS)
+ if (!state->test) {
+ nxt_int_t ret;
+
+ ret = nxt_js_compile(state->jcf);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+#endif
+
+ return NXT_OK;
}
@@ -133,7 +214,7 @@ nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str)
nxt_int_t
nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state,
- nxt_var_cache_t *cache, void *ctx, nxt_mp_t *mp)
+ nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp)
{
nxt_tstr_query_t *query;
@@ -172,11 +253,24 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr,
return;
}
- ret = nxt_var_interpreter(task, query->cache, tstr->var, val, query->ctx,
- tstr->flags & NXT_TSTR_LOGGING);
- if (nxt_slow_path(ret != NXT_OK)) {
- query->failed = 1;
- return;
+ if (tstr->type == NXT_TSTR_VAR) {
+ ret = nxt_var_interpreter(task, &query->cache->var, tstr->u.var, val,
+ query->ctx, tstr->flags & NXT_TSTR_LOGGING);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ query->failed = 1;
+ return;
+ }
+
+ } else {
+#if (NXT_HAVE_NJS)
+ ret = nxt_js_call(task, &query->cache->js, tstr->u.js, val, query->ctx);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ query->failed = 1;
+ return;
+ }
+#endif
}
if (tstr->flags & NXT_TSTR_STRZ) {
@@ -188,7 +282,7 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr,
nxt_tstr_str(tstr, &str);
- nxt_debug(task, "tstr: \"%V\" -> \"%V\"", &str, val);
+ nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val);
#endif
}
diff --git a/src/nxt_tstr.h b/src/nxt_tstr.h
index 692b9d28..0cc24292 100644
--- a/src/nxt_tstr.h
+++ b/src/nxt_tstr.h
@@ -7,6 +7,8 @@
#define _NXT_TSTR_H_INCLUDED_
+#include <nxt_js.h>
+
typedef struct nxt_tstr_s nxt_tstr_t;
typedef struct nxt_tstr_query_s nxt_tstr_query_t;
@@ -14,25 +16,38 @@ typedef struct nxt_tstr_query_s nxt_tstr_query_t;
typedef struct {
nxt_mp_t *pool;
nxt_array_t *var_fields;
+#if (NXT_HAVE_NJS)
+ nxt_js_conf_t *jcf;
+#endif
+ uint8_t test; /* 1 bit */
} nxt_tstr_state_t;
+typedef struct {
+ nxt_var_cache_t var;
+#if (NXT_HAVE_NJS)
+ nxt_js_cache_t js;
+#endif
+} nxt_tstr_cache_t;
+
+
typedef enum {
NXT_TSTR_STRZ = 1 << 0,
NXT_TSTR_LOGGING = 1 << 1,
} nxt_tstr_flags_t;
-nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp);
+nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test);
nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str,
nxt_tstr_flags_t flags);
nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error);
+nxt_int_t nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error);
nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr);
void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str);
nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p,
- nxt_tstr_state_t *state, nxt_var_cache_t *cache, void *ctx,
+ nxt_tstr_state_t *state, nxt_tstr_cache_t *cache, void *ctx,
nxt_mp_t *mp);
void nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr,
nxt_str_t *val);
@@ -42,4 +57,23 @@ void nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query,
nxt_bool_t failed);
+nxt_inline nxt_bool_t
+nxt_is_tstr(nxt_str_t *str)
+{
+ u_char *p;
+
+ p = memchr(str->start, '`', str->length);
+ if (p != NULL) {
+ return 1;
+ }
+
+ p = memchr(str->start, '$', str->length);
+ if (p != NULL) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
#endif /* _NXT_TSTR_H_INCLUDED_ */
diff --git a/src/nxt_var.h b/src/nxt_var.h
index 2c6f13bd..4f30a002 100644
--- a/src/nxt_var.h
+++ b/src/nxt_var.h
@@ -39,13 +39,6 @@ typedef struct {
} nxt_var_cache_t;
-nxt_inline nxt_bool_t
-nxt_is_var(nxt_str_t *str)
-{
- return (memchr(str->start, '$', str->length) != NULL);
-}
-
-
nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n);
nxt_int_t nxt_var_index_init(void);