details: https://hg.nginx.org/njs/rev/664d366b515a branches: changeset: 903:664d366b515a user: Dmitry Volyntsev <xei...@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") }, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel