[njs] Fixed RegExp constructor for regexp value arguments.
Dmitry Volyntsev
xeioex at nginx.com
Thu Apr 18 15:15:04 UTC 2019
details: https://hg.nginx.org/njs/rev/664d366b515a
branches:
changeset: 903:664d366b515a
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Apr 18 18:14:56 2019 +0300
description:
Fixed RegExp constructor for regexp value arguments.
This closes #59 issue on Github.
diffstat:
njs/njs_builtin.c | 3 +-
njs/njs_regexp.c | 101 ++++++++++++++++++++++++++++++++++++++--------
njs/test/njs_unit_test.c | 33 +++++++++++++++
3 files changed, 117 insertions(+), 20 deletions(-)
diffs (193 lines):
diff -r e4ba35c2844b -r 664d366b515a njs/njs_builtin.c
--- a/njs/njs_builtin.c Thu Apr 18 15:44:37 2019 +0300
+++ b/njs/njs_builtin.c Thu Apr 18 18:14:56 2019 +0300
@@ -146,8 +146,7 @@ const njs_function_init_t njs_native_co
{ njs_number_constructor, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
{ njs_string_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
{ njs_function_constructor, { 0 } },
- { njs_regexp_constructor,
- { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_STRING_ARG } },
+ { njs_regexp_constructor, { 0 } },
{ njs_date_constructor, { 0 } },
{ njs_hash_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
{ njs_hmac_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG,
diff -r e4ba35c2844b -r 664d366b515a njs/njs_regexp.c
--- a/njs/njs_regexp.c Thu Apr 18 15:44:37 2019 +0300
+++ b/njs/njs_regexp.c Thu Apr 18 18:14:56 2019 +0300
@@ -15,6 +15,8 @@ static void *njs_regexp_malloc(size_t si
static void njs_regexp_free(void *p, void *memory_data);
static njs_regexp_flags_t njs_regexp_flags(u_char **start, u_char *end,
nxt_bool_t bound);
+static njs_ret_t njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *value,
+ njs_value_t *setval, njs_value_t *retval);
static int njs_regexp_pattern_compile(njs_vm_t *vm, nxt_regex_t *regex,
u_char *source, int options);
static u_char *njs_regexp_compile_trace_handler(nxt_trace_t *trace,
@@ -63,43 +65,106 @@ njs_regexp_free(void *p, void *memory_da
}
+static njs_regexp_flags_t
+njs_regexp_value_flags(njs_vm_t *vm, const njs_value_t *regexp)
+{
+ njs_regexp_flags_t flags;
+ njs_regexp_pattern_t *pattern;
+
+ flags = 0;
+
+ pattern = regexp->data.u.regexp->pattern;
+
+ if (pattern->global) {
+ flags |= NJS_REGEXP_GLOBAL;
+ }
+
+ if (pattern->ignore_case) {
+ flags |= NJS_REGEXP_IGNORE_CASE;
+ }
+
+ if (pattern->multiline) {
+ flags |= NJS_REGEXP_MULTILINE;
+ }
+
+ return flags;
+}
+
+
njs_ret_t
njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
u_char *start;
+ njs_ret_t ret;
nxt_str_t string;
- njs_regexp_flags_t flags;
+ njs_value_t source, flags_string;
+ const njs_value_t *pattern, *flags;
+ njs_regexp_flags_t re_flags;
+
+ pattern = njs_arg(args, nargs, 1);
+
+ if (!njs_is_regexp(pattern) && !njs_is_primitive(pattern)) {
+ njs_vm_trap_value(vm, &args[1]);
- flags = 0;
+ return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ }
+
+ flags = njs_arg(args, nargs, 2);
- switch (nargs) {
+ if (!njs_is_primitive(flags)) {
+ njs_vm_trap_value(vm, &args[2]);
+
+ return njs_trap(vm, NJS_TRAP_STRING_ARG);
+ }
+
+ re_flags = 0;
- case 1:
- string.start = NULL;
- string.length = 0;
- break;
+ if (njs_is_regexp(pattern)) {
+ ret = njs_regexp_prototype_source(vm, (njs_value_t *) pattern, NULL,
+ &source);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ re_flags = njs_regexp_value_flags(vm, pattern);
+
+ pattern = &source;
+
+ } else {
+ if (njs_is_undefined(pattern)) {
+ pattern = &njs_string_empty;
+ }
- default:
- njs_string_get(&args[2], &string);
+ ret = njs_primitive_value_to_string(vm, &source, pattern);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ pattern = &source;
+ }
+
+ if (!njs_is_undefined(flags)) {
+ ret = njs_primitive_value_to_string(vm, &flags_string, flags);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ njs_string_get(&flags_string, &string);
start = string.start;
- flags = njs_regexp_flags(&start, start + string.length, 1);
- if (nxt_slow_path(flags < 0)) {
+ re_flags = njs_regexp_flags(&start, start + string.length, 1);
+ if (nxt_slow_path(re_flags < 0)) {
njs_syntax_error(vm, "Invalid RegExp flags \"%V\"", &string);
return NXT_ERROR;
}
-
- /* Fall through. */
-
- case 2:
- njs_string_get(&args[1], &string);
- break;
}
+ njs_string_get(pattern, &string);
+
return njs_regexp_create(vm, &vm->retval, string.start, string.length,
- flags);
+ re_flags);
}
diff -r e4ba35c2844b -r 664d366b515a njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Apr 18 15:44:37 2019 +0300
+++ b/njs/test/njs_unit_test.c Thu Apr 18 18:14:56 2019 +0300
@@ -6967,6 +6967,39 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("new RegExp('', 'x')"),
nxt_string("SyntaxError: Invalid RegExp flags \"x\"") },
+ { nxt_string("RegExp({})"),
+ nxt_string("/[object Object]/") },
+
+ { nxt_string("RegExp(true)"),
+ nxt_string("/true/") },
+
+ { nxt_string("RegExp(undefined)"),
+ nxt_string("/(?:)/") },
+
+ { nxt_string("RegExp('abc', undefined)"),
+ nxt_string("/abc/") },
+
+ { nxt_string("RegExp('abc', {})"),
+ nxt_string("SyntaxError: Invalid RegExp flags \"[object Object]\"") },
+
+ { nxt_string("RegExp(/expr/)"),
+ nxt_string("/expr/") },
+
+ { nxt_string("RegExp(/expr/i).ignoreCase"),
+ nxt_string("true") },
+
+ { nxt_string("RegExp(/expr/, 'x')"),
+ nxt_string("SyntaxError: Invalid RegExp flags \"x\"") },
+
+ { nxt_string("RegExp(new RegExp('expr'))"),
+ nxt_string("/expr/") },
+
+ { nxt_string("RegExp(new RegExp('expr')).multiline"),
+ nxt_string("false") },
+
+ { nxt_string("RegExp(new RegExp('expr'), 'm').multiline"),
+ nxt_string("true") },
+
{ nxt_string("new RegExp('[')"),
nxt_string("SyntaxError: pcre_compile(\"[\") failed: missing terminating ] for character class") },
More information about the nginx-devel
mailing list