njs_trace_data_t *td, u_char *start);
static u_char *njs_regexp_match_trace_handler(njs_trace_t *trace,
njs_trace_data_t *td, u_char *start);
+#define NJS_REGEXP_FLAG_TEST 1
+static njs_int_t njs_regexp_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s,
+ unsigned flags, njs_value_t *retval);
static njs_array_t *njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r,
njs_utf8_t utf8, njs_string_prop_t *string, njs_regex_match_data_t *data);
static njs_int_t njs_regexp_string_create(njs_vm_t *vm, njs_value_t *value,
return NJS_ERROR;
}
- ret = njs_regexp_exec(vm, r, string, &value);
+ ret = njs_regexp_exec(vm, r, string, NJS_REGEXP_FLAG_TEST, &value);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
*/
static njs_int_t
njs_regexp_builtin_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s,
- njs_value_t *retval)
+ unsigned flags, njs_value_t *retval)
{
- size_t length, offset;
+ size_t c, length, offset;
int64_t last_index;
+ uint32_t index;
njs_int_t ret;
njs_utf8_t utf8;
njs_value_t value;
ret = njs_regexp_match(vm, &pattern->regex[type], string.start, offset,
string.size, match_data);
if (ret >= 0) {
+ if (pattern->global || pattern->sticky) {
+ c = njs_regex_capture(match_data, 1);
+
+ if (utf8 == NJS_STRING_UTF8) {
+ index = njs_string_index(&string, c);
+
+ } else {
+ index = c;
+ }
+
+ njs_set_number(&value, index);
+ ret = njs_value_property_set(vm, r,
+ njs_value_arg(&njs_string_lindex),
+ &value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_regex_match_data_free(match_data, vm->regex_generic_ctx);
+ return NJS_ERROR;
+ }
+ }
+
+ if (flags & NJS_REGEXP_FLAG_TEST) {
+ njs_regex_match_data_free(match_data, vm->regex_generic_ctx);
+ njs_set_boolean(retval, 1);
+ return NJS_OK;
+ }
+
result = njs_regexp_exec_result(vm, r, utf8, &string, match_data);
njs_regex_match_data_free(match_data, vm->regex_generic_ctx);
}
+static njs_exotic_slots_t njs_regexp_prototype_exotic_slots = {
+ .prop_handler = NULL,
+ .keys = NULL,
+};
+
+
static njs_array_t *
njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, njs_utf8_t utf8,
njs_string_prop_t *string, njs_regex_match_data_t *match_data)
njs_int_t ret;
njs_uint_t i, n;
njs_array_t *array;
- njs_value_t name, value;
+ njs_value_t name;
njs_object_t *groups;
njs_regexp_t *regexp;
njs_object_prop_t *prop;
goto fail;
}
+ array->object.slots = &njs_regexp_prototype_exotic_slots;
+
for (i = 0; i < pattern->ncaptures; i++) {
n = 2 * i;
c = njs_regex_capture(match_data, n);
njs_set_number(&prop->u.value, index);
- if (pattern->global || pattern->sticky) {
- c = njs_regex_capture(match_data, 1);
-
- if (utf8 == NJS_STRING_UTF8) {
- index = njs_string_index(string, c);
-
- } else {
- index = c;
- }
-
- njs_set_number(&value, index);
- ret = njs_value_property_set(vm, r, njs_value_arg(&njs_string_lindex),
- &value);
- if (njs_slow_path(ret != NJS_OK)) {
- goto fail;
- }
- }
-
lhq.key_hash = NJS_INDEX_HASH;
lhq.key = njs_str_value("index");
lhq.replace = 0;
return ret;
}
- return njs_regexp_builtin_exec(vm, r, s, retval);
+ return njs_regexp_builtin_exec(vm, r, s,
+ njs_number(njs_arg(args, nargs, 2)), retval);
}
-njs_int_t
-njs_regexp_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s,
+static njs_int_t
+njs_regexp_exec(njs_vm_t *vm, njs_value_t *r, njs_value_t *s, unsigned flags,
njs_value_t *retval)
{
njs_int_t ret;
njs_value_t exec;
+ njs_value_t arguments[2];
static const njs_value_t string_exec = njs_string("exec");
}
if (njs_is_function(&exec)) {
- ret = njs_function_call(vm, njs_function(&exec), r, s, 1, retval);
+ njs_value_assign(&arguments[0], s);
+
+ if (flags) {
+ njs_set_number(&arguments[1], flags);
+ }
+
+ ret = njs_function_call(vm, njs_function(&exec), r, arguments,
+ flags ? 2 : 1, retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return NJS_ERROR;
}
- if (njs_slow_path(!njs_is_object(retval) && !njs_is_null(retval))) {
+ if (njs_slow_path(!njs_is_null(retval)
+ && (flags & NJS_REGEXP_FLAG_TEST
+ && !njs_is_boolean(retval))))
+ {
+ njs_type_error(vm, "unexpected \"%s\" retval in njs_regexp_exec()",
+ njs_type_string(retval->type));
+ return NJS_ERROR;
+ }
+
+ if (njs_slow_path(!njs_is_null(retval)
+ && (!flags && !njs_is_object(retval))))
+ {
njs_type_error(vm, "unexpected \"%s\" retval in njs_regexp_exec()",
njs_type_string(retval->type));
return NJS_ERROR;
return NJS_ERROR;
}
- return njs_regexp_builtin_exec(vm, r, s, retval);
+ return njs_regexp_builtin_exec(vm, r, s, flags, retval);
}
goto exception;
}
- ret = njs_regexp_exec(vm, rx, string, r);
+ ret = njs_regexp_exec(vm, rx, string, 0, r);
if (njs_slow_path(ret != NJS_OK)) {
goto exception;
}
length = njs_string_prop(&s, string);
if (njs_slow_path(s.size == 0)) {
- ret = njs_regexp_exec(vm, rx, string, &z);
+ ret = njs_regexp_exec(vm, rx, string, NJS_REGEXP_FLAG_TEST, &z);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
return NJS_ERROR;
}
- ret = njs_regexp_exec(vm, rx, string, &z);
+ ret = njs_regexp_exec(vm, rx, string, 0, &z);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}