[njs] Added support for functions in regexp with global match.
Alexander Borisov
alexander.borisov at nginx.com
Mon Jul 1 18:28:13 UTC 2019
details: https://hg.nginx.org/njs/rev/f66b593ef3da
branches:
changeset: 1022:f66b593ef3da
user: Alexander Borisov <alexander.borisov at nginx.com>
date: Mon Jul 01 19:57:34 2019 +0300
description:
Added support for functions in regexp with global match.
This closes #183 issue on GitHub.
diffstat:
njs/njs_string.c | 36 ++++++++++++++++++++++++++++--------
njs/test/njs_unit_test.c | 6 ++++++
2 files changed, 34 insertions(+), 8 deletions(-)
diffs (104 lines):
diff -r e123c7406264 -r f66b593ef3da njs/njs_string.c
--- a/njs/njs_string.c Mon Jul 01 19:24:10 2019 +0300
+++ b/njs/njs_string.c Mon Jul 01 19:57:34 2019 +0300
@@ -49,6 +49,8 @@ typedef struct {
nxt_regex_match_data_t *match_data;
+ nxt_bool_t empty;
+
njs_utf8_t utf8:8;
njs_regexp_utf8_t type:8;
} njs_string_replace_t;
@@ -3143,6 +3145,11 @@ njs_string_replace_regexp(njs_vm_t *vm,
r->part[2].start = start + 1;
}
+ if (r->function != NULL) {
+ return njs_string_replace_regexp_function(vm, args, r,
+ captures, ret);
+ }
+
r->part[0] = replace;
} else {
@@ -3194,11 +3201,12 @@ static njs_ret_t
njs_string_replace_regexp_function(njs_vm_t *vm, njs_value_t *args,
njs_string_replace_t *r, int *captures, nxt_uint_t n)
{
- u_char *start;
- size_t size, length;
- njs_ret_t ret;
- nxt_uint_t i, k;
- njs_value_t *arguments;
+ u_char *start;
+ size_t size, length;
+ njs_ret_t ret;
+ nxt_uint_t i, k;
+ njs_value_t *arguments;
+ njs_string_prop_t string;
r->u.cont.function = njs_string_replace_regexp_continuation;
njs_set_invalid(&r->retval);
@@ -3225,14 +3233,18 @@ njs_string_replace_regexp_function(njs_v
}
}
+ r->empty = (captures[0] == captures[1]);
+
/* The offset of the matched substring. */
njs_value_number_set(&arguments[n + 1], captures[0]);
/* The whole string being examined. */
length = njs_string_calc_length(r->utf8, r->part[0].start, r->part[0].size);
- ret = njs_string_new(vm, &arguments[n + 2], r->part[0].start,
- r->part[0].size, length);
+ (void) njs_string_prop(&string, &args[0]);
+
+ ret = njs_string_new(vm, &arguments[n + 2], string.start, string.size,
+ length);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
@@ -3249,15 +3261,23 @@ static njs_ret_t
njs_string_replace_regexp_continuation(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused)
{
+ njs_string_prop_t string;
njs_string_replace_t *r;
r = njs_vm_continuation(vm);
+ (void) njs_string_prop(&string, &args[0]);
+
if (njs_is_string(&r->retval)) {
- njs_string_replacement_copy(&r->part[1], &r->retval);
+ njs_string_replacement_copy(&r->part[r->empty ? 0 : 1], &r->retval);
if (args[1].data.u.regexp->pattern->global) {
r->part += 2;
+
+ if (r->part[0].start > (string.start + string.size)) {
+ return njs_string_replace_regexp_join(vm, r);
+ }
+
return njs_string_replace_regexp(vm, args, r);
}
diff -r e123c7406264 -r f66b593ef3da njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Mon Jul 01 19:24:10 2019 +0300
+++ b/njs/test/njs_unit_test.c Mon Jul 01 19:57:34 2019 +0300
@@ -5560,6 +5560,12 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("'12345'.replace(3, () => ({toString: () => 'aaaa'}))"),
nxt_string("12aaaa45") },
+ { nxt_string("'abc'.replace(/(z*)/g, function v0() {return '124'})"),
+ nxt_string("124a124b124c124") },
+
+ { nxt_string("'abc'.replace(/(a*)/g, function v0() {return '124'})"),
+ nxt_string("124124b124c124") },
+
{ nxt_string("/]/"),
nxt_string("/\\]/") },
More information about the nginx-devel
mailing list