From 4949d75dafcd3401aac4cc75e76bbd680fc67b47 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Sat, 9 Dec 2023 12:28:13 +0100 Subject: [PATCH] Retrieve RegExp 'g' flag in spec conformant way (original patch by bnoordhuis) --- quickjs.c | 35 +++++++++++++++++++++++++++-------- test262_errors.txt | 12 ------------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/quickjs.c b/quickjs.c index efe78e8..83c8b87 100644 --- a/quickjs.c +++ b/quickjs.c @@ -42551,7 +42551,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, { // [Symbol.match](str) JSValueConst rx = this_val; - JSValue A, S, result, matchStr; + JSValue A, S, flags, result, matchStr; int global, n, fullUnicode, isEmpty; JSString *p; @@ -42559,16 +42559,23 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeErrorNotAnObject(ctx); A = JS_UNDEFINED; + flags = JS_UNDEFINED; result = JS_UNDEFINED; matchStr = JS_UNDEFINED; S = JS_ToString(ctx, argv[0]); if (JS_IsException(S)) goto exception; - global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global)); - if (global < 0) + flags = JS_GetProperty(ctx, rx, JS_ATOM_flags); + if (JS_IsException(flags)) goto exception; + flags = JS_ToStringFree(ctx, flags); + if (JS_IsException(flags)) + goto exception; + p = JS_VALUE_GET_STRING(flags); + // TODO(bnoordhuis) query 'u' flag the same way? + global = (-1 != string_indexof_char(p, 'g', 0)); if (!global) { A = JS_RegExpExec(ctx, rx, S); } else { @@ -42612,12 +42619,14 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, } } JS_FreeValue(ctx, result); + JS_FreeValue(ctx, flags); JS_FreeValue(ctx, S); return A; exception: JS_FreeValue(ctx, A); JS_FreeValue(ctx, result); + JS_FreeValue(ctx, flags); JS_FreeValue(ctx, S); return JS_EXCEPTION; } @@ -42860,8 +42869,8 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, // [Symbol.replace](str, rep) JSValueConst rx = this_val, rep = argv[1]; JSValueConst args[6]; - JSValue str, rep_val, matched, tab, rep_str, namedCaptures, res; - JSString *sp, *rp; + JSValue flags, str, rep_val, matched, tab, rep_str, namedCaptures, res; + JSString *p, *sp, *rp; StringBuffer b_s, *b = &b_s; ValueBuffer v_b, *results = &v_b; int nextSourcePosition, n, j, functionalReplace, is_global, fullUnicode; @@ -42877,6 +42886,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, rep_val = JS_UNDEFINED; matched = JS_UNDEFINED; tab = JS_UNDEFINED; + flags = JS_UNDEFINED; rep_str = JS_UNDEFINED; namedCaptures = JS_UNDEFINED; @@ -42893,10 +42903,18 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, goto exception; rp = JS_VALUE_GET_STRING(rep_val); } - fullUnicode = 0; - is_global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global)); - if (is_global < 0) + + flags = JS_GetProperty(ctx, rx, JS_ATOM_flags); + if (JS_IsException(flags)) goto exception; + flags = JS_ToStringFree(ctx, flags); + if (JS_IsException(flags)) + goto exception; + p = JS_VALUE_GET_STRING(flags); + + // TODO(bnoordhuis) query 'u' flag the same way? + fullUnicode = 0; + is_global = (-1 != string_indexof_char(p, 'g', 0)); if (is_global) { fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode)); if (fullUnicode < 0) @@ -43030,6 +43048,7 @@ done1: value_buffer_free(results); JS_FreeValue(ctx, rep_val); JS_FreeValue(ctx, matched); + JS_FreeValue(ctx, flags); JS_FreeValue(ctx, tab); JS_FreeValue(ctx, rep_str); JS_FreeValue(ctx, namedCaptures); diff --git a/test262_errors.txt b/test262_errors.txt index 81b1ea2..c18143a 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -11,18 +11,6 @@ test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: Test262Er test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: strict mode: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: SyntaxError: invalid group name test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: strict mode: SyntaxError: invalid group name -test262/test/built-ins/RegExp/prototype/Symbol.match/flags-tostring-error.js:22: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.match/flags-tostring-error.js:22: strict mode: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.match/get-flags-err.js:23: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.match/get-flags-err.js:23: strict mode: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.match/get-unicode-error.js:22: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all -test262/test/built-ins/RegExp/prototype/Symbol.match/get-unicode-error.js:22: strict mode: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all -test262/test/built-ins/RegExp/prototype/Symbol.replace/flags-tostring-error.js:26: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.replace/flags-tostring-error.js:26: strict mode: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.replace/get-flags-err.js:27: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.replace/get-flags-err.js:27: strict mode: Test262Error: Expected a CustomError but got a Test262Error -test262/test/built-ins/RegExp/prototype/Symbol.replace/get-unicode-error.js:26: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all -test262/test/built-ins/RegExp/prototype/Symbol.replace/get-unicode-error.js:26: strict mode: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all test262/test/built-ins/RegExp/unicode_full_case_folding.js:20: Test262Error: \u0390 does not match \u1fd3 test262/test/built-ins/RegExp/unicode_full_case_folding.js:20: strict mode: Test262Error: \u0390 does not match \u1fd3 test262/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js:62: Test262Error: String.prototype.localeCompare considers ö (\u006f\u0308) ≠ ö (\u00f6).