diff options
-rw-r--r-- | auto/help | 2 | ||||
-rw-r--r-- | auto/njs | 41 | ||||
-rw-r--r-- | auto/options | 4 | ||||
-rw-r--r-- | auto/sources | 4 | ||||
-rw-r--r-- | auto/summary | 1 | ||||
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | docs/changes.xml | 6 | ||||
-rw-r--r-- | src/nxt_conf_validation.c | 33 | ||||
-rw-r--r-- | src/nxt_http.h | 2 | ||||
-rw-r--r-- | src/nxt_http_request.c | 2 | ||||
-rw-r--r-- | src/nxt_http_return.c | 2 | ||||
-rw-r--r-- | src/nxt_http_route.c | 2 | ||||
-rw-r--r-- | src/nxt_http_static.c | 2 | ||||
-rw-r--r-- | src/nxt_js.c | 230 | ||||
-rw-r--r-- | src/nxt_js.h | 34 | ||||
-rw-r--r-- | src/nxt_router.c | 7 | ||||
-rw-r--r-- | src/nxt_router_access_log.c | 2 | ||||
-rw-r--r-- | src/nxt_tstr.c | 128 | ||||
-rw-r--r-- | src/nxt_tstr.h | 38 | ||||
-rw-r--r-- | src/nxt_var.h | 7 |
20 files changed, 507 insertions, 44 deletions
@@ -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 @@ -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); |