pos = njs_max(njs_min(pos, (int64_t) s.size), 0);
- if (njs_fast_path(njs_is_fast_array(r))) {
+ if (njs_fast_path(njs_is_fast_array(r) && njs_array_len(r) != 0)) {
array = njs_array(r);
arguments = array->start;
arguments[0] = matched;
- ncaptures = array->length;
+ ncaptures = njs_max((int64_t) array->length - 1, 0);
- for (n = 1; n < ncaptures; n++) {
+ for (n = 1; n <= ncaptures; n++) {
if (njs_is_undefined(&arguments[n])) {
continue;
}
goto exception;
}
- array = njs_array_alloc(vm, 0, ncaptures, 0);
+ ncaptures = njs_max(ncaptures - 1, 0);
+
+ array = njs_array_alloc(vm, 0, ncaptures + 1, 0);
if (njs_slow_path(array == NULL)) {
goto exception;
}
arguments = array->start;
arguments[0] = matched;
- for (n = 1; n < ncaptures; n++) {
+ for (n = 1; n <= ncaptures; n++) {
ret = njs_value_property_i64(vm, r, n, &arguments[n]);
if (njs_slow_path(ret == NJS_ERROR)) {
goto exception;
}
ret = njs_string_get_substitution(vm, &matched, string, pos,
- arguments, ncaptures - 1, &groups,
+ arguments, ncaptures, &groups,
replace, &retval);
} else {
{ njs_str("/b(c)(z)?(.)/[Symbol.replace]('abcde', '[$01$02$03$04$00]')"),
njs_str("a[cd$04$00]e") },
+ { njs_str("var r = /./; r.exec = () => {return {}};"
+ "r[Symbol.replace]('ABCD', 'b')"),
+ njs_str("b") },
+
+ { njs_str("var r = /./; r.exec = () => {return {}};"
+ "r[Symbol.replace]('ABCD', (m,p,o) => `${m}|${p}|${o}`)"),
+ njs_str("undefined|0|ABCD") },
+
+ { njs_str("var r = /./; r.exec = () => Buffer.from([]).toJSON().data;"
+ "r[Symbol.replace]('ABCD', 'b')"),
+ njs_str("b") },
+
{ njs_str("'α'.replace(/(h*)/g, '$1βγ')"),
njs_str("βγαβγ") },