Browse Source

Fixing global flag regular expressions

Sebastien Ros 8 years ago
parent
commit
8e28849fd2

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

@@ -1827,5 +1827,15 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void ShouldUseReplaceMarkers()
+        {
+            RunTest(@"
+                var re = /a/g;
+                var str = 'abab';
+                var newstr = str.replace(re, '$\'x');
+                equal('babxbbxb', newstr);
+            ");
+        }
     }
 }

+ 1 - 4
Jint/Engine.cs

@@ -61,7 +61,7 @@ namespace Jint
             { typeof(UInt32), (Engine engine, object v) => new JsValue((UInt32)v) },
             { typeof(UInt64), (Engine engine, object v) => new JsValue((UInt64)v) },
             { typeof(JsValue), (Engine engine, object v) => (JsValue)v },
-            { typeof(System.Text.RegularExpressions.Regex), (Engine engine, object v) => engine.RegExp.Construct((System.Text.RegularExpressions.Regex)v) }
+            { typeof(System.Text.RegularExpressions.Regex), (Engine engine, object v) => engine.RegExp.Construct((System.Text.RegularExpressions.Regex)v, "") }
         };
 
         internal JintCallStack CallStack = new JintCallStack();
@@ -465,9 +465,6 @@ namespace Jint
                 case Nodes.Literal:
                     return _expressions.EvaluateLiteral(expression.As<Literal>());
 
-                case Nodes.RegularExpressionLiteral:
-                    return _expressions.EvaluateLiteral(expression.As<Literal>());
-
                 case Nodes.LogicalExpression:
                     return _expressions.EvaluateLogicalExpression(expression.As<BinaryExpression>());
 

+ 24 - 13
Jint/Native/RegExp/RegExpConstructor.cs

@@ -111,6 +111,7 @@ namespace Jint.Native.RegExp
 
             r.Flags = f;
             r.Source = s;
+            AssignFlags(r, f);
 
             r.FastAddProperty("global", r.Global, false, false, false);
             r.FastAddProperty("ignoreCase", r.IgnoreCase, false, false, false);
@@ -133,6 +134,7 @@ namespace Jint.Native.RegExp
             r.Value = scanner.TestRegExp(body, flags);
 
             r.Flags = flags;
+            AssignFlags(r, flags);
             r.Source = System.String.IsNullOrEmpty(body) ? "(?:)" : body;
 
             r.FastAddProperty("global", r.Global, false, false, false);
@@ -144,25 +146,15 @@ namespace Jint.Native.RegExp
             return r;
         }
 
-        public RegExpInstance Construct(Regex regExp)
+        public RegExpInstance Construct(Regex regExp, string flags)
         {
             var r = new RegExpInstance(Engine);
             r.Prototype = PrototypeObject;
             r.Extensible = true;
 
-            string flags = "";
-
-            if (regExp.Options.HasFlag(RegexOptions.Multiline))
-            {
-                flags += "m";
-            }
-
-            if (regExp.Options.HasFlag(RegexOptions.IgnoreCase))
-            {
-                flags += "i";
-            }
-
             r.Flags = flags;
+            AssignFlags(r, flags);
+
             r.Source = regExp.ToString();
             r.Value = regExp;
 
@@ -175,6 +167,25 @@ namespace Jint.Native.RegExp
             return r;
         }
 
+        private void AssignFlags(RegExpInstance r, string flags)
+        {
+            for(var i=0; i < flags.Length; i++)
+            {
+                switch (flags[i])
+                {
+                    case 'i':
+                        r.IgnoreCase = true;
+                        break;
+                    case 'm':
+                        r.Multiline = true;
+                        break;
+                    case 'g':
+                        r.Global = true;
+                        break;
+                }
+            }
+        }
+
         public RegExpPrototype PrototypeObject { get; private set; }
     }
 }

+ 13 - 6
Jint/Runtime/ExpressionIntepreter.cs

@@ -625,16 +625,15 @@ namespace Jint.Runtime
 
         public JsValue EvaluateLiteral(Literal literal)
         {
-            // TODO: Esprima
-
-            //if(literal.Cached)
+            // TODO: Esprima; Cached value is a JsValue
+            //if (literal.Cached)
             //{
             //    return literal.CachedValue;
             //}
 
             //if (literal.Type == Nodes.RegularExpressionLiteral)
             //{
-            //    literal.CachedValue = _engine.RegExp.Construct(literal.Raw);
+            //    literal.CachedValue = _engine.RegExp.Construct(literal.RegexValue, literal.Regex.Flags);
             //}
             //else
             //{
@@ -642,9 +641,17 @@ namespace Jint.Runtime
             //}
 
             //literal.Cached = true;
-            // return literal.CachedValue;
+            //return literal.CachedValue;
+
+            if (literal.RegexValue != null) //(literal.Type == Nodes.RegularExpressionLiteral)
+            {
+                return _engine.RegExp.Construct(literal.RegexValue, literal.Regex.Flags);
+            }
+            else
+            {
+                return JsValue.FromObject(_engine, literal.Value);
+            }
 
-            return JsValue.FromObject(_engine, literal.Value);
         }
 
         public JsValue EvaluateObjectExpression(ObjectExpression objectExpression)