[njs] Using nxt_regex interface in nJSVM.
Igor Sysoev
igor at sysoev.ru
Wed Jun 1 12:50:37 UTC 2016
details: http://hg.nginx.org/njs/rev/c72fd0d1fabc
branches:
changeset: 113:c72fd0d1fabc
user: Igor Sysoev <igor at sysoev.ru>
date: Wed Jun 01 15:31:34 2016 +0300
description:
Using nxt_regex interface in nJSVM.
diffstat:
Makefile | 2 +
njs/njs_disassembler.c | 1 -
njs/njs_lexer_keyword.c | 1 -
njs/njs_regexp.c | 238 ++++++++++++++++++++--------------------------
njs/njs_regexp.h | 3 +-
njs/njs_regexp_pattern.h | 4 +-
njs/njs_string.c | 91 +++++++++++++----
njs/njs_string.h | 2 +
njs/njs_vm.h | 13 ++-
njs/njscript.c | 15 +-
njs/test/njs_unit_test.c | 3 +
11 files changed, 205 insertions(+), 168 deletions(-)
diffs (773 lines):
diff -r b8084a72d667 -r c72fd0d1fabc Makefile
--- a/Makefile Wed Jun 01 15:30:50 2016 +0300
+++ b/Makefile Wed Jun 01 15:31:34 2016 +0300
@@ -36,6 +36,7 @@ NXT_BUILDDIR = build
$(NXT_BUILDDIR)/nxt_rbtree.o \
$(NXT_BUILDDIR)/nxt_lvlhsh.o \
$(NXT_BUILDDIR)/nxt_random.o \
+ $(NXT_BUILDDIR)/nxt_pcre.o \
$(NXT_BUILDDIR)/nxt_malloc.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
@@ -67,6 +68,7 @@ NXT_BUILDDIR = build
$(NXT_BUILDDIR)/nxt_rbtree.o \
$(NXT_BUILDDIR)/nxt_lvlhsh.o \
$(NXT_BUILDDIR)/nxt_random.o \
+ $(NXT_BUILDDIR)/nxt_pcre.o \
$(NXT_BUILDDIR)/nxt_malloc.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_disassembler.c
--- a/njs/njs_disassembler.c Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_disassembler.c Wed Jun 01 15:31:34 2016 +0300
@@ -14,7 +14,6 @@
#include <njscript.h>
#include <njs_vm.h>
#include <njs_object.h>
-#include <njs_regexp.h>
#include <njs_variable.h>
#include <njs_parser.h>
#include <stdio.h>
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_lexer_keyword.c Wed Jun 01 15:31:34 2016 +0300
@@ -16,7 +16,6 @@
#include <njs_vm.h>
#include <njs_number.h>
#include <njs_object.h>
-#include <njs_regexp.h>
#include <njs_variable.h>
#include <njs_parser.h>
#include <string.h>
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_regexp.c
--- a/njs/njs_regexp.c Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_regexp.c Wed Jun 01 15:31:34 2016 +0300
@@ -14,6 +14,7 @@
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
#include <nxt_random.h>
+#include <nxt_pcre.h>
#include <nxt_malloc.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
@@ -30,17 +31,51 @@
#include <string.h>
+static void *njs_regexp_malloc(size_t size, void *memory_data);
+static void njs_regexp_free(void *p, void *memory_data);
static njs_regexp_flags_t njs_regexp_flags(u_char **start, u_char *end,
nxt_bool_t bound);
-static int njs_regexp_pattern_compile(pcre **code, pcre_extra **extra,
+static int njs_regexp_pattern_compile(njs_vm_t *vm, nxt_regex_t *regex,
u_char *source, int options);
static njs_ret_t njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp,
- u_char *string, int *captures, nxt_uint_t utf8);
+ u_char *string, nxt_regex_match_data_t *match_data, nxt_uint_t utf8);
static njs_ret_t njs_regexp_string_create(njs_vm_t *vm, njs_value_t *value,
u_char *start, uint32_t size, int32_t length);
njs_ret_t
+njs_regexp_init(njs_vm_t *vm)
+{
+ vm->regex_context = nxt_regex_context_create(njs_regexp_malloc,
+ njs_regexp_free, vm->mem_cache_pool);
+ if (nxt_slow_path(vm->regex_context == NULL)) {
+ return NXT_ERROR;
+ }
+
+ vm->single_match_data = nxt_regex_match_data(NULL, vm->regex_context);
+ if (nxt_slow_path(vm->single_match_data == NULL)) {
+ return NXT_ERROR;
+ }
+
+ return NXT_OK;
+}
+
+
+static void *
+njs_regexp_malloc(size_t size, void *memory_data)
+{
+ return nxt_mem_cache_alloc(memory_data, size);
+}
+
+
+static void
+njs_regexp_free(void *p, void *memory_data)
+{
+ nxt_mem_cache_free(memory_data, p);
+}
+
+
+njs_ret_t
njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
@@ -205,18 +240,14 @@ njs_regexp_pattern_create(njs_vm_t *vm,
size += ((flags & NJS_REGEXP_IGNORE_CASE) != 0);
size += ((flags & NJS_REGEXP_MULTILINE) != 0);
- pattern = nxt_mem_cache_alloc(vm->mem_cache_pool,
- sizeof(njs_regexp_pattern_t)
- + 1 + length + size + 1);
+ pattern = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+ sizeof(njs_regexp_pattern_t)
+ + 1 + length + size + 1);
if (nxt_slow_path(pattern == NULL)) {
return NULL;
}
pattern->flags = size;
- pattern->code[0] = NULL;
- pattern->code[1] = NULL;
- pattern->extra[0] = NULL;
- pattern->extra[1] = NULL;
pattern->next = NULL;
p = (u_char *) pattern + sizeof(njs_regexp_pattern_t);
@@ -254,18 +285,16 @@ njs_regexp_pattern_create(njs_vm_t *vm,
*p++ = '\0';
- ret = njs_regexp_pattern_compile(&pattern->code[0], &pattern->extra[0],
+ ret = njs_regexp_pattern_compile(vm, &pattern->regex[0],
&pattern->source[1], options);
-
if (nxt_slow_path(ret < 0)) {
return NULL;
}
pattern->ncaptures = ret;
- ret = njs_regexp_pattern_compile(&pattern->code[1], &pattern->extra[1],
+ ret = njs_regexp_pattern_compile(vm, &pattern->regex[1],
&pattern->source[1], options | PCRE_UTF8);
-
if (nxt_fast_path(ret >= 0)) {
if (nxt_slow_path((u_int) ret != pattern->ncaptures)) {
@@ -273,75 +302,35 @@ njs_regexp_pattern_create(njs_vm_t *vm,
"and UTF-8 versions of RegExp \"%s\" vary: %d vs %d",
&pattern->source[1], pattern->ncaptures, ret);
- njs_regexp_pattern_free(pattern);
+ nxt_mem_cache_free(vm->mem_cache_pool, pattern);
return NULL;
}
} else if (ret != NXT_DECLINED) {
- njs_regexp_pattern_free(pattern);
+ nxt_mem_cache_free(vm->mem_cache_pool, pattern);
return NULL;
}
*end = '/';
- pattern->next = vm->pattern;
- vm->pattern = pattern;
-
return pattern;
}
static int
-njs_regexp_pattern_compile(pcre **code, pcre_extra **extra, u_char *source,
+njs_regexp_pattern_compile(njs_vm_t *vm, nxt_regex_t *regex, u_char *source,
int options)
{
- int ret, erroff, captures;
- u_char *error;
- const char *errstr;
-
- *code = pcre_compile((char *) source, options, &errstr, &erroff, NULL);
-
- if (nxt_slow_path(*code == NULL)) {
-
- if ((options & PCRE_UTF8) != 0) {
- return NXT_DECLINED;
- }
+ nxt_int_t ret;
- error = source + erroff;
+ /* Zero length means a zero-terminated string. */
+ ret = nxt_regex_compile(regex, source, 0, options, vm->regex_context);
- if (*error != '\0') {
- nxt_thread_log_error(NXT_LOG_ERR,
- "pcre_compile(\"%s\") failed: %s at \"%s\"",
- source, errstr, error);
- } else {
- nxt_thread_log_error(NXT_LOG_ERR,
- "pcre_compile(\"%s\") failed: %s",
- source, errstr);
- }
-
- return NXT_ERROR;
+ if (nxt_fast_path(ret == NXT_OK)) {
+ return regex->ncaptures;
}
- *extra = pcre_study(*code, 0, &errstr);
-
- if (nxt_slow_path(errstr != NULL)) {
- nxt_thread_log_error(NXT_LOG_ERR, "pcre_study(\"%s\") failed: %s",
- source, errstr);
- return NXT_ERROR;
- }
-
- ret = pcre_fullinfo(*code, NULL, PCRE_INFO_CAPTURECOUNT, &captures);
-
- if (nxt_fast_path(ret >= 0)) {
- /* Reserve additional elements for the first "$0" capture. */
- return captures + 1;
- }
-
- nxt_thread_log_error(NXT_LOG_ERR,
- "pcre_fullinfo(\"%s\", PCRE_INFO_CAPTURECOUNT) failed: %d",
- source, ret);
-
- return NXT_ERROR;
+ return njs_string_exception(vm, NJS_SYNTAX_ERROR, vm->regex_context->error);
}
@@ -491,16 +480,15 @@ njs_regexp_prototype_test(njs_vm_t *vm,
pattern = args[0].data.u.regexp->pattern;
- if (pattern->code[n] != NULL) {
- ret = pcre_exec(pattern->code[n], pattern->extra[n],
- (char *) string.start, string.size, 0, 0, NULL, 0);
-
+ if (nxt_regex_is_valid(&pattern->regex[n])) {
+ ret = nxt_regex_match(&pattern->regex[n], string.start, string.size,
+ vm->single_match_data, vm->regex_context);
if (ret >= 0) {
retval = &njs_value_true;
- } else if (ret != PCRE_ERROR_NOMATCH) {
- vm->exception = &njs_exception_internal_error;
- return NXT_ERROR;
+ } else if (ret != NGX_REGEX_NOMATCH) {
+ return njs_string_exception(vm, NJS_INTERNAL_ERROR,
+ vm->regex_context->error);
}
}
@@ -514,13 +502,13 @@ njs_ret_t
njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
- int *captures, ncaptures;
- njs_ret_t ret;
- nxt_uint_t n, utf8;
- njs_value_t *value;
- njs_regexp_t *regexp;
- njs_string_prop_t string;
- njs_regexp_pattern_t *pattern;
+ njs_ret_t ret;
+ nxt_uint_t n, utf8;
+ njs_value_t *value;
+ njs_regexp_t *regexp;
+ njs_string_prop_t string;
+ njs_regexp_pattern_t *pattern;
+ nxt_regex_match_data_t *match_data;
if (!njs_is_regexp(&args[0])) {
vm->exception = &njs_exception_type_error;
@@ -553,27 +541,28 @@ njs_regexp_prototype_exec(njs_vm_t *vm,
pattern = regexp->pattern;
- if (pattern->code[n] != NULL) {
+ if (nxt_regex_is_valid(&pattern->regex[n])) {
string.start += regexp->last_index;
string.size -= regexp->last_index;
- /* Each capture is stored in 3 vector elements. */
- ncaptures = pattern->ncaptures * 3;
-
- captures = alloca(ncaptures * sizeof(int));
-
- ret = pcre_exec(pattern->code[n], pattern->extra[n],
- (char *) string.start, string.size,
- 0, 0, captures, ncaptures);
-
- if (ret >= 0) {
- return njs_regexp_exec_result(vm, regexp, string.start,
- captures, utf8);
+ match_data = nxt_regex_match_data(&pattern->regex[n],
+ vm->regex_context);
+ if (nxt_slow_path(match_data == NULL)) {
+ return NXT_ERROR;
}
- if (nxt_slow_path(ret != PCRE_ERROR_NOMATCH)) {
- vm->exception = &njs_exception_internal_error;
- return NXT_ERROR;
+ ret = nxt_regex_match(&pattern->regex[n], string.start, string.size,
+ match_data, vm->regex_context);
+ if (ret >= 0) {
+ return njs_regexp_exec_result(vm, regexp, string.start, match_data,
+ utf8);
+ }
+
+ if (nxt_slow_path(ret != NGX_REGEX_NOMATCH)) {
+ nxt_regex_match_data_free(match_data, vm->regex_context);
+
+ return njs_string_exception(vm, NJS_INTERNAL_ERROR,
+ vm->regex_context->error);
}
}
@@ -586,8 +575,9 @@ njs_regexp_prototype_exec(njs_vm_t *vm,
static njs_ret_t
njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp, u_char *string,
- int *captures, nxt_uint_t utf8)
+ nxt_regex_match_data_t *match_data, nxt_uint_t utf8)
{
+ int *captures;
u_char *start;
int32_t size, length;
njs_ret_t ret;
@@ -601,9 +591,11 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
array = njs_array_alloc(vm, regexp->pattern->ncaptures, 0);
if (nxt_slow_path(array == NULL)) {
- return NXT_ERROR;
+ goto fail;
}
+ captures = nxt_regex_captures(match_data);
+
for (i = 0; i < regexp->pattern->ncaptures; i++) {
n = 2 * i;
@@ -626,7 +618,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
ret = njs_regexp_string_create(vm, &array->start[i],
start, size, length);
if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
+ goto fail;
}
} else {
@@ -636,7 +628,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
prop = njs_object_prop_alloc(vm, &njs_string_index);
if (nxt_slow_path(prop == NULL)) {
- return NXT_ERROR;
+ goto fail;
}
/* TODO: Non UTF-8 position */
@@ -657,13 +649,12 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
ret = nxt_lvlhsh_insert(&array->object.hash, &lhq);
if (nxt_slow_path(ret != NXT_OK)) {
- /* Only NXT_ERROR can be returned here. */
- return ret;
+ goto fail;
}
prop = njs_object_prop_alloc(vm, &njs_string_input);
if (nxt_slow_path(prop == NULL)) {
- return NXT_ERROR;
+ goto fail;
}
njs_string_copy(&prop->value, ®exp->string);
@@ -674,16 +665,25 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
lhq.value = prop;
ret = nxt_lvlhsh_insert(&array->object.hash, &lhq);
- if (nxt_slow_path(ret != NXT_OK)) {
- /* Only NXT_ERROR can be returned here. */
- return ret;
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ vm->retval.data.u.array = array;
+ vm->retval.type = NJS_ARRAY;
+ vm->retval.data.truth = 1;
+
+ ret = NXT_OK;
+ goto done;
}
- vm->retval.data.u.array = array;
- vm->retval.type = NJS_ARRAY;
- vm->retval.data.truth = 1;
+fail:
- return NXT_OK;
+ ret = NXT_ERROR;
+
+done:
+
+ nxt_regex_match_data_free(match_data, vm->regex_context);
+
+ return ret;
}
@@ -789,29 +789,3 @@ const njs_object_init_t njs_regexp_prot
njs_regexp_prototype_properties,
nxt_nitems(njs_regexp_prototype_properties),
};
-
-
-void
-njs_regexp_pattern_free(njs_regexp_pattern_t *pattern)
-{
- /*
- * pcre_free() is enough to free PCRE extra study data.
- * pcre_free_study() is required for JIT optimization, pcreapi(3):
- *
- * When you are finished with a pattern, you can free the memory used
- * for the study data by calling pcre_free_study(). This function was
- * added to the API for release 8.20. For earlier versions, the memory
- * could be freed with pcre_free(), just like the pattern itself. This
- * will still work in cases where JIT optimization is not used, but it
- * is advisable to change to the new function when convenient.
- */
- while (pattern != NULL) {
- pcre_free(pattern->extra[0]);
- pcre_free(pattern->code[0]);
-
- pcre_free(pattern->extra[1]);
- pcre_free(pattern->code[1]);
-
- pattern = pattern->next;
- }
-}
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_regexp.h
--- a/njs/njs_regexp.h Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_regexp.h Wed Jun 01 15:31:34 2016 +0300
@@ -32,6 +32,7 @@ struct njs_regexp_s {
};
+njs_ret_t njs_regexp_init(njs_vm_t *vm);
njs_ret_t njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
nxt_int_t njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser,
@@ -41,7 +42,7 @@ njs_regexp_pattern_t *njs_regexp_pattern
njs_regexp_t *njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern);
njs_ret_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
-void njs_regexp_pattern_free(njs_regexp_pattern_t *pattern);
+
extern const njs_object_init_t njs_regexp_constructor_init;
extern const njs_object_init_t njs_regexp_prototype_init;
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_regexp_pattern.h
--- a/njs/njs_regexp_pattern.h Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_regexp_pattern.h Wed Jun 01 15:31:34 2016 +0300
@@ -11,8 +11,8 @@
struct njs_regexp_pattern_s {
- pcre *code[2];
- pcre_extra *extra[2];
+ nxt_regex_t regex[2];
+
njs_regexp_pattern_t *next;
/*
* A pattern source is used by RegExp.toString() method and
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_string.c
--- a/njs/njs_string.c Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_string.c Wed Jun 01 15:31:34 2016 +0300
@@ -14,6 +14,7 @@
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
#include <nxt_random.h>
+#include <nxt_pcre.h>
#include <nxt_malloc.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
@@ -1409,12 +1410,11 @@ static njs_ret_t
njs_string_prototype_search(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
- int ret;
+ int ret, *captures;
nxt_int_t index;
nxt_uint_t n;
njs_string_prop_t string;
njs_regexp_pattern_t *pattern;
- int captures[3];
index = 0;
@@ -1450,17 +1450,16 @@ njs_string_prototype_search(njs_vm_t *vm
n = (string.length != 0 && string.length != string.size);
- if (pattern->code[n] != NULL) {
- ret = pcre_exec(pattern->code[n], pattern->extra[n],
- (char *) string.start, string.size,
- 0, 0, captures, 3);
-
+ if (nxt_regex_is_valid(&pattern->regex[n])) {
+ ret = nxt_regex_match(&pattern->regex[n], string.start, string.size,
+ vm->single_match_data, vm->regex_context);
if (ret >= 0) {
+ captures = nxt_regex_captures(vm->single_match_data);
index = njs_string_index(&string, captures[0]);
- } else if (ret != PCRE_ERROR_NOMATCH) {
- vm->exception = &njs_exception_internal_error;
- return NXT_ERROR;
+ } else if (ret != NGX_REGEX_NOMATCH) {
+ return njs_string_exception(vm, NJS_INTERNAL_ERROR,
+ vm->regex_context->error);
}
}
}
@@ -1489,7 +1488,7 @@ njs_string_prototype_match(njs_vm_t *vm,
njs_array_t *array;
njs_string_prop_t string;
njs_regexp_pattern_t *pattern;
- int captures[3];
+ int *captures;
if (nargs == 1) {
goto empty;
@@ -1549,14 +1548,12 @@ njs_string_prototype_match(njs_vm_t *vm,
}
}
- if (pattern->code[n] != NULL) {
+ if (nxt_regex_is_valid(&pattern->regex[n])) {
array = NULL;
do {
- ret = pcre_exec(pattern->code[n], pattern->extra[n],
- (char *) string.start, string.size,
- 0, 0, captures, 3);
-
+ ret = nxt_regex_match(&pattern->regex[n], string.start, string.size,
+ vm->single_match_data, vm->regex_context);
if (ret >= 0) {
if (array != NULL) {
if (array->length == array->size) {
@@ -1577,6 +1574,7 @@ njs_string_prototype_match(njs_vm_t *vm,
vm->retval.data.truth = 1;
}
+ captures = nxt_regex_captures(vm->single_match_data);
start = &string.start[captures[0]];
string.start += captures[1];
@@ -1595,8 +1593,10 @@ njs_string_prototype_match(njs_vm_t *vm,
default:
length = nxt_utf8_length(start, size);
+
if (nxt_slow_path(length < 0)) {
- goto error;
+ vm->exception = &njs_exception_internal_error;
+ return NXT_ERROR;
}
break;
@@ -1610,11 +1610,12 @@ njs_string_prototype_match(njs_vm_t *vm,
array->length++;
- } else if (ret == PCRE_ERROR_NOMATCH) {
+ } else if (ret == NGX_REGEX_NOMATCH) {
break;
} else {
- goto error;
+ return njs_string_exception(vm, NJS_INTERNAL_ERROR,
+ vm->regex_context->error);
}
} while (string.size > 0);
@@ -1626,12 +1627,6 @@ njs_string_prototype_match(njs_vm_t *vm,
return NXT_OK;
-error:
-
- vm->exception = &njs_exception_internal_error;
-
- return NXT_ERROR;
-
empty:
array = njs_array_alloc(vm, 1, 0);
@@ -2049,3 +2044,49 @@ njs_value_index(njs_vm_t *vm, njs_parser
return (njs_index_t) value;
}
+
+
+nxt_int_t
+njs_string_exception(njs_vm_t *vm, njs_exception_error_t exception, u_char *msg)
+{
+ u_char *p, *start;
+ uint32_t msg_length, size, length;
+ nxt_str_t *error;
+ njs_value_t *value;
+
+ static nxt_str_t errors[] = {
+ nxt_string("SyntaxError: "),
+ nxt_string("InternalError: "),
+ };
+
+ value = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_value_t));
+ if (nxt_slow_path(value == NULL)) {
+ return NXT_ERROR;
+ }
+
+ error = &errors[exception];
+
+ msg_length = (msg != NULL) ? strlen((char *) msg) : 0;
+ length = nxt_utf8_length(msg, msg_length);
+
+ size = error->len + msg_length;
+ length += error->len;
+
+ start = njs_string_alloc(vm, value, size, length);
+
+ if (nxt_fast_path(start != NULL)) {
+ memcpy(start, error->data, error->len);
+ p = start + error->len;
+
+ memcpy(p, msg, msg_length);
+
+ if (size != length && length >= NJS_STRING_MAP_OFFSET) {
+ njs_string_offset_map_init(start, size);
+ }
+ }
+
+ vm->exception = value;
+
+ return NXT_ERROR;
+}
+
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_string.h
--- a/njs/njs_string.h Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_string.h Wed Jun 01 15:31:34 2016 +0300
@@ -107,6 +107,8 @@ double njs_string_to_number(njs_value_t
njs_index_t njs_value_index(njs_vm_t *vm, njs_parser_t *parser,
const njs_value_t *src);
+nxt_int_t njs_string_exception(njs_vm_t *vm, njs_exception_error_t exception,
+ u_char *msg);
extern const njs_object_init_t njs_string_constructor_init;
extern const njs_object_init_t njs_string_prototype_init;
diff -r b8084a72d667 -r c72fd0d1fabc njs/njs_vm.h
--- a/njs/njs_vm.h Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njs_vm.h Wed Jun 01 15:31:34 2016 +0300
@@ -8,6 +8,9 @@
#define _NJS_VM_H_INCLUDED_
+#include <nxt_regex.h>
+
+
/*
* Negative return values handled by nJSVM interpreter as special events.
* The values must be in range from -1 to -11, because -12 is minimal jump
@@ -790,7 +793,9 @@ struct njs_vm_s {
njs_vm_shared_t *shared;
njs_parser_t *parser;
- njs_regexp_pattern_t *pattern;
+
+ nxt_regex_context_t *regex_context;
+ nxt_regex_match_data_t *single_match_data;
nxt_array_t *code; /* of njs_vm_code_t */
@@ -822,6 +827,12 @@ struct njs_vm_shared_s {
};
+typedef enum {
+ NJS_SYNTAX_ERROR = 0,
+ NJS_INTERNAL_ERROR,
+} njs_exception_error_t;
+
+
nxt_int_t njs_vmcode_interpreter(njs_vm_t *vm);
void njs_value_retain(njs_value_t *value);
diff -r b8084a72d667 -r c72fd0d1fabc njs/njscript.c
--- a/njs/njscript.c Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/njscript.c Wed Jun 01 15:31:34 2016 +0300
@@ -116,12 +116,16 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp,
if (nxt_fast_path(vm != NULL)) {
vm->mem_cache_pool = mcp;
+ ret = njs_regexp_init(vm);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
if (shared != NULL && *shared != NULL) {
vm->shared = *shared;
} else {
vm->shared = nxt_mem_cache_zalloc(mcp, sizeof(njs_vm_shared_t));
-
if (nxt_slow_path(vm->shared == NULL)) {
return NULL;
}
@@ -133,7 +137,6 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp,
nxt_lvlhsh_init(&vm->shared->keywords_hash);
ret = njs_lexer_keywords_init(mcp, &vm->shared->keywords_hash);
-
if (nxt_slow_path(ret != NXT_OK)) {
return NULL;
}
@@ -141,7 +144,6 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp,
nxt_lvlhsh_init(&vm->shared->values_hash);
ret = njs_builtin_objects_create(vm);
-
if (nxt_slow_path(ret != NXT_OK)) {
return NULL;
}
@@ -161,8 +163,6 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp,
void
njs_vm_destroy(njs_vm_t *vm)
{
- njs_regexp_pattern_free(vm->pattern);
-
nxt_mem_cache_pool_destroy(vm->mem_cache_pool);
}
@@ -312,6 +312,11 @@ njs_vm_clone(njs_vm_t *vm, nxt_mem_cache
memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope,
vm->scope_size);
+ ret = njs_regexp_init(nvm);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
+
ret = njs_builtin_objects_clone(nvm);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
diff -r b8084a72d667 -r c72fd0d1fabc njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Wed Jun 01 15:30:50 2016 +0300
+++ b/njs/test/njs_unit_test.c Wed Jun 01 15:31:34 2016 +0300
@@ -3369,6 +3369,9 @@ static njs_unit_test_t njs_test[] =
/* RegExp. */
+ { nxt_string("/(/.test('')"),
+ nxt_string("SyntaxError: pcre_compile(\"(\") failed: missing )") },
+
{ nxt_string("/^$/.test('')"),
nxt_string("true") },
More information about the nginx-devel
mailing list