Browse Source

Merge pull request #273 from sebastienros/pr/272

Fixing RegExp mutable array
Sébastien Ros 9 years ago
parent
commit
e9571dbbc9

+ 38 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -1638,5 +1638,43 @@ namespace Jint.Tests.Runtime
                 assert(String(a) === String(b));
             ");
         }
+
+        [Fact]
+        public void RegExpResultIsMutable()
+        {
+            RunTest(@"
+                var match = /quick\s(brown).+?(jumps)/ig.exec('The Quick Brown Fox Jumps Over The Lazy Dog');
+                var result = match.shift();
+                assert(result === 'Quick Brown Fox Jumps');
+            ");
+        }
+
+        [Fact]
+        public void RegExpSupportsMultiline()
+        {
+            RunTest(@"
+                var rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg;
+                var headersString = 'X-AspNetMvc-Version: 4.0\r\nX-Powered-By: ASP.NET\r\n\r\n';
+                match = rheaders.exec(headersString);
+                assert('X-AspNetMvc-Version' === match[1]);
+                assert('4.0' === match[2]);
+            ");
+
+            RunTest(@"
+                var rheaders = /^(.*?):[ \t]*(.*?)$/mg;
+                var headersString = 'X-AspNetMvc-Version: 4.0\r\nX-Powered-By: ASP.NET\r\n\r\n';
+                match = rheaders.exec(headersString);
+                assert('X-AspNetMvc-Version' === match[1]);
+                assert('4.0' === match[2]);
+            ");
+
+            RunTest(@"
+                var rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg;
+                var headersString = 'X-AspNetMvc-Version: 4.0\nX-Powered-By: ASP.NET\n\n';
+                match = rheaders.exec(headersString);
+                assert('X-AspNetMvc-Version' === match[1]);
+                assert('4.0' === match[2]);
+            ");
+        }
     }
 }

+ 23 - 1
Jint/Native/RegExp/RegExpConstructor.cs

@@ -138,7 +138,29 @@ namespace Jint.Native.RegExp
             var options = ParseOptions(r, flags);
             try
             {
-                r.Value = new Regex(pattern, options);
+                if((RegexOptions.Multiline & options) == RegexOptions.Multiline)
+                {
+                    // Replace all non-escaped $ occurences by \r?$
+                    // c.f. http://programmaticallyspeaking.com/regular-expression-multiline-mode-whats-a-newline.html
+
+                    int index = 0;
+                    var newPattern = pattern;
+                    while((index = newPattern.IndexOf("$", index)) != -1)
+                    {
+                        if(index > 0 && newPattern[index - 1] != '\\')
+                        {
+                            newPattern = newPattern.Substring(0, index) + @"\r?" + newPattern.Substring(index);
+                            index += 4;
+                        }
+                    }
+
+                    r.Value = new Regex(newPattern, options);
+                }
+                else
+                {
+                    r.Value = new Regex(pattern, options);
+                }
+                
             }
             catch (Exception e)
             {

+ 1 - 1
Jint/Native/RegExp/RegExpPrototype.cs

@@ -125,7 +125,7 @@ namespace Jint.Native.RegExp
         {
             array.DefineOwnProperty("index", new PropertyDescriptor(indexValue, writable: true, enumerable: true, configurable: true), true);
             array.DefineOwnProperty("input", new PropertyDescriptor(inputValue, writable: true, enumerable: true, configurable: true), true);
-            array.DefineOwnProperty("length", new PropertyDescriptor(value: lengthValue, writable: false, enumerable: false, configurable: false), true);
+            array.DefineOwnProperty("length", new PropertyDescriptor(value: lengthValue, writable: true, enumerable: false, configurable: false), true);
             return array;
         }
     }