[njs] Added support '$&' substitution in String.prototype.replace().
Alexander Borisov
alexander.borisov at nginx.com
Wed Jul 17 15:21:26 UTC 2019
details: https://hg.nginx.org/njs/rev/0960f0568b94
branches:
changeset: 1057:0960f0568b94
user: Alexander Borisov <alexander.borisov at nginx.com>
date: Wed Jul 17 14:24:00 2019 +0300
description:
Added support '$&' substitution in String.prototype.replace().
diffstat:
njs/njs_string.c | 25 ++++++++++++++-----------
njs/test/njs_unit_test.c | 16 ++++++++++++----
2 files changed, 26 insertions(+), 15 deletions(-)
diffs (119 lines):
diff -r 377db9ae390d -r 0960f0568b94 njs/njs_string.c
--- a/njs/njs_string.c Wed Jul 17 16:28:30 2019 +0300
+++ b/njs/njs_string.c Wed Jul 17 14:24:00 2019 +0300
@@ -3516,6 +3516,9 @@ skip:
} else if (c == '`') {
type = NJS_SUBST_PRECEDING;
+ } else if (c == '&') {
+ type = 0;
+
} else if (c == '\'') {
type = NJS_SUBST_FOLLOWING;
@@ -3540,12 +3543,13 @@ static njs_ret_t
njs_string_replace_substitute(njs_vm_t *vm, njs_string_replace_t *r,
int *captures)
{
- uint32_t i, n, last, index;
+ int *capture;
+ uint32_t i, n, last;
const u_char *end;
njs_string_subst_t *s;
njs_string_replace_part_t *part, *subject;
- index = 0;
+ capture = NULL;
last = r->substitutions->items;
end = r->part[0].start + r->part[0].size;
@@ -3607,15 +3611,14 @@ njs_string_replace_substitute(njs_vm_t *
break;
/*
- * "$n" substitutions.
- * "$&" is the same as "$0", the "$0" however is not supported.
+ * "$n" and "$&" substitutions.
*/
default:
if (captures[n] == captures[n + 1]) {
/* Empty match. */
- if (captures[n - 1] == captures[n]) {
+ if (n > 0 && captures[n - 1] == captures[n]) {
/*
* Consecutive empty matches as in
@@ -3626,11 +3629,11 @@ njs_string_replace_substitute(njs_vm_t *
break;
}
- index = n;
+ capture = &captures[n];
continue;
}
- if (index != 0) {
+ if (capture != NULL) {
/*
* Inserting a single character after a series of
@@ -3638,14 +3641,14 @@ njs_string_replace_substitute(njs_vm_t *
*/
if (part->start < end) {
- part->start = r->part[0].start + captures[index];
+ part->start = r->part[0].start + *capture;
part->size = nxt_utf8_next(part->start, end) - part->start;
} else {
part->size = 0;
}
- index = 0;
+ capture = NULL;
break;
}
@@ -3658,8 +3661,8 @@ njs_string_replace_substitute(njs_vm_t *
part++;
}
- if (index != 0) {
- part->start = r->part[0].start + captures[index];
+ if (capture != NULL) {
+ part->start = r->part[0].start + *capture;
if (part->start < end) {
part->size = nxt_utf8_next(part->start, end) - part->start;
diff -r 377db9ae390d -r 0960f0568b94 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Wed Jul 17 16:28:30 2019 +0300
+++ b/njs/test/njs_unit_test.c Wed Jul 17 14:24:00 2019 +0300
@@ -5681,14 +5681,22 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("'abc'.replace(/(a*)/g, function v0() {return '124'})"),
nxt_string("124124b124c124") },
- { nxt_string("typeof '0'.replace(/^/g, '$0')"),
- nxt_string("string") },
+ { nxt_string("'abc'.replace(/b/g, '$0')"),
+ nxt_string("a$0c") },
{ nxt_string("typeof String.bytesFrom(Array(15).fill(0xE3)).replace(/^/g, 1)"),
nxt_string("string") },
- { nxt_string("typeof '0'.replace(/^/g, '$&')"),
- nxt_string("string") },
+#if 0 /* FIXME: PCRE limitation */
+ { nxt_string("'abc'.replace(/^/g, '|$&|')"),
+ nxt_string("||abc") },
+#endif
+
+ { nxt_string("'abc'.replace(/b/g, '|$&|')"),
+ nxt_string("a|b|c") },
+
+ { nxt_string("'ABC'.replace(/((A)B)/g, '($1|$&|$2)')"),
+ nxt_string("(AB|AB|A)C") },
{ nxt_string("/]/"),
nxt_string("/\\]/") },
More information about the nginx-devel
mailing list