Bug 1322035 - Do not strip leading .* pattern in RegExp.prototype.test with global/sticky flags. r=h4writer
authorTooru Fujisawa <arai_a@mac.com>
Thu, 08 Dec 2016 16:29:19 +0900
changeset 325402 82aeade4d0073cd0c2da2d61543fe0a50430cfbb
parent 325401 f7e0dfe88d42e4c326fdb75b1ebd4228fd1d2f01
child 325403 387b89eeed54d07238a2e0e878e44ca7cdbd26cb
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersh4writer
bugs1322035
milestone53.0a1
Bug 1322035 - Do not strip leading .* pattern in RegExp.prototype.test with global/sticky flags. r=h4writer
js/src/irregexp/RegExpParser.cpp
js/src/tests/ecma_6/RegExp/test-emptyMatch.js
--- a/js/src/irregexp/RegExpParser.cpp
+++ b/js/src/irregexp/RegExpParser.cpp
@@ -1832,35 +1832,33 @@ template class irregexp::RegExpParser<La
 template class irregexp::RegExpParser<char16_t>;
 
 template <typename CharT>
 static bool
 ParsePattern(frontend::TokenStream& ts, LifoAlloc& alloc, const CharT* chars, size_t length,
              bool multiline, bool match_only, bool unicode, bool ignore_case,
              bool global, bool sticky, RegExpCompileData* data)
 {
-    if (match_only) {
+    // We shouldn't strip pattern for exec, or test with global/sticky,
+    // to reflect correct match position and lastIndex.
+    if (match_only && !global && !sticky) {
         // Try to strip a leading '.*' from the RegExp, but only if it is not
         // followed by a '?' (which will affect how the .* is parsed). This
         // pattern will affect the captures produced by the RegExp, but not
         // whether there is a match or not.
         if (length >= 3 && chars[0] == '.' && chars[1] == '*' && chars[2] != '?') {
             chars += 2;
             length -= 2;
         }
 
         // Try to strip a trailing '.*' from the RegExp, which as above will
         // affect the captures but not whether there is a match. Only do this
-        // when the following conditions are met:
-        //   1. there are no other meta characters in the RegExp, so that we
-        //      are sure this will not affect how the RegExp is parsed
-        //   2. global and sticky flags are not set, as lastIndex needs to be
-        //      set properly on global or sticky match
+        // when there are no other meta characters in the RegExp, so that we
+        // are sure this will not affect how the RegExp is parsed.
         if (length >= 3 && !HasRegExpMetaChars(chars, length - 2) &&
-            !global && !sticky &&
             chars[length - 2] == '.' && chars[length - 1] == '*')
         {
             length -= 2;
         }
     }
 
     RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, multiline, unicode, ignore_case);
     data->tree = parser.ParsePattern();
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/RegExp/test-emptyMatch.js
@@ -0,0 +1,23 @@
+var BUGNUMBER = 1322035;
+var summary = 'RegExp.prototype.test should update lastIndex to correct position even if pattern starts with .*';
+
+print(BUGNUMBER + ": " + summary);
+
+var regExp = /.*x?/g;
+regExp.test('12345');
+assertEq(regExp.lastIndex, 5);
+
+regExp = /.*x*/g;
+regExp.test('12345');
+assertEq(regExp.lastIndex, 5);
+
+regExp = /.*()/g;
+regExp.test('12345');
+assertEq(regExp.lastIndex, 5);
+
+regExp = /.*(x|)/g;
+regExp.test('12345');
+assertEq(regExp.lastIndex, 5);
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);