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);
+ unsigned flags, njs_value_t *retval, njs_bool_t *builtin);
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);
+typedef struct {
+ njs_value_t value;
+ njs_bool_t builtin;
+} njs_regexp_result_t;
+
+
njs_int_t
njs_regexp_init(njs_vm_t *vm)
{
return NJS_ERROR;
}
- ret = njs_regexp_exec(vm, r, string, NJS_REGEXP_FLAG_TEST, &value);
+ ret = njs_regexp_exec(vm, r, string, NJS_REGEXP_FLAG_TEST, &value, NULL);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
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_value_t *retval, njs_bool_t *builtin)
{
- njs_int_t ret;
- njs_value_t exec;
- njs_value_t arguments[2];
+ njs_int_t ret;
+ njs_bool_t builtin_exec;
+ njs_value_t exec;
+ njs_function_t *function;
+ njs_value_t arguments[2];
+
+ if (builtin != NULL) {
+ *builtin = 0;
+ }
ret = njs_value_property(vm, r, NJS_ATOM_STRING_exec, &exec);
if (njs_slow_path(ret == NJS_ERROR)) {
}
if (njs_is_function(&exec)) {
+ function = njs_function(&exec);
+ builtin_exec = function->native
+ && function->u.native == njs_regexp_prototype_exec;
+
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);
+ ret = njs_function_call(vm, function, r, arguments, flags ? 2 : 1,
+ retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return NJS_ERROR;
}
return NJS_ERROR;
}
+ if (builtin != NULL && builtin_exec && !njs_is_null(retval)) {
+ *builtin = 1;
+ }
+
return NJS_OK;
}
return NJS_ERROR;
}
- return njs_regexp_builtin_exec(vm, r, s, flags, retval);
+ ret = njs_regexp_builtin_exec(vm, r, s, flags, retval);
+
+ if (ret == NJS_OK && builtin != NULL && !njs_is_null(retval)) {
+ *builtin = 1;
+ }
+
+ return ret;
}
njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval)
{
- int64_t n, last_index, ncaptures, pos, length, next, mlength;
- const u_char *p, *start;
- njs_str_t rep, m, head, tail;
- njs_int_t ret;
- njs_arr_t results;
- njs_chb_t chain;
- njs_uint_t i;
- njs_bool_t global;
- njs_array_t *array;
- njs_value_t *arguments, *r, *rx, *string, *replace;
- njs_value_t s_lvalue, r_lvalue, value, matched, groups;
- njs_function_t *func_replace;
- njs_string_prop_t s, ms;
+ int64_t n, last_index, ncaptures, pos, length, next, mlength;
+ const u_char *p, *start;
+ njs_str_t rep, m, head, tail;
+ njs_int_t ret;
+ njs_arr_t results;
+ njs_chb_t chain;
+ njs_uint_t i;
+ njs_bool_t global;
+ njs_array_t *array;
+ njs_value_t *arguments, *r, *rx, *string, *replace;
+ njs_value_t s_lvalue, r_lvalue, value, matched, groups;
+ njs_function_t *func_replace;
+ njs_regexp_result_t *result;
+ njs_string_prop_t s, ms;
rx = njs_argument(args, 0);
results.separate = 0;
results.pointer = 0;
- r = njs_arr_init(vm->mem_pool, &results, NULL, 4, sizeof(njs_value_t));
- if (njs_slow_path(r == NULL)) {
+ result = njs_arr_init(vm->mem_pool, &results, NULL, 4,
+ sizeof(njs_regexp_result_t));
+ if (njs_slow_path(result == NULL)) {
return NJS_ERROR;
}
for ( ;; ) {
- r = njs_arr_add(&results);
- if (njs_slow_path(r == NULL)) {
+ result = njs_arr_add(&results);
+ if (njs_slow_path(result == NULL)) {
ret = NJS_ERROR;
goto exception;
}
- ret = njs_regexp_exec(vm, rx, string, 0, r);
+ r = &result->value;
+
+ ret = njs_regexp_exec(vm, rx, string, 0, r, &result->builtin);
if (njs_slow_path(ret != NJS_OK)) {
goto exception;
}
next = 0;
while (i < results.items) {
- r = njs_arr_item(&results, i++);
+ result = njs_arr_item(&results, i++);
+ r = &result->value;
if (njs_slow_path(njs_is_null(r))) {
break;
next = pos + mlength;
}
- if (!func_replace && njs_object_slots(r)) {
+ if (!func_replace && result->builtin) {
/*
* Doing free here ONLY for non-function replace, because
* otherwise we cannot be certain the result of match
ssize_t len;
uint32_t limit;
njs_int_t ret;
- njs_bool_t sticky;
+ njs_bool_t builtin, sticky;
njs_utf8_t utf8;
njs_array_t *array;
njs_value_t *rx, *string, *value;
length = njs_string_prop(vm, &s, string);
if (njs_slow_path(s.size == 0)) {
- ret = njs_regexp_exec(vm, rx, string, NJS_REGEXP_FLAG_TEST, &z);
+ ret = njs_regexp_exec(vm, rx, string, NJS_REGEXP_FLAG_TEST, &z,
+ NULL);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
return NJS_ERROR;
}
- ret = njs_regexp_exec(vm, rx, string, 0, &z);
+ ret = njs_regexp_exec(vm, rx, string, 0, &z, &builtin);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
e = njs_min(e, length);
if (e == p) {
- if (njs_object_slots(&z)) {
+ if (builtin) {
njs_regexp_exec_result_free(vm, njs_array(&z));
}
}
if (array->length == limit) {
- if (njs_object_slots(&z)) {
+ if (builtin) {
njs_regexp_exec_result_free(vm, njs_array(&z));
}
}
if (array->length == limit) {
- if (njs_object_slots(&z)) {
+ if (builtin) {
njs_regexp_exec_result_free(vm, njs_array(&z));
}
}
}
- if (njs_object_slots(&z)) {
+ if (builtin) {
njs_regexp_exec_result_free(vm, njs_array(&z));
}