Browse Source

Fix string.split method and unit tests

Fix string.split method and unit tests
Frederic Torres 11 years ago
parent
commit
4e00cae57c
3 changed files with 82 additions and 5 deletions
  1. 13 0
      Jint/Native/Array/ArrayInstance.cs
  2. 23 0
      Jint/Native/JsValue.cs
  3. 46 5
      Jint/Native/String/StringPrototype.cs

+ 13 - 0
Jint/Native/Array/ArrayInstance.cs

@@ -164,6 +164,19 @@ namespace Jint.Native.Array
             return base.DefineOwnProperty(propertyName, desc, throwOnError);
             return base.DefineOwnProperty(propertyName, desc, throwOnError);
         }
         }
 
 
+        internal long Length
+        {
+            get
+            {
+                var v = this.Get("length");
+                if (v.IsNumber())
+                {
+                    return (long)v.AsNumber();
+                }
+                return -1;
+            }
+        }
+
         public static bool IsArrayIndex(JsValue p)
         public static bool IsArrayIndex(JsValue p)
         {
         {
             return TypeConverter.ToString(TypeConverter.ToUint32(p)) == TypeConverter.ToString(p) && TypeConverter.ToUint32(p) != uint.MaxValue;
             return TypeConverter.ToString(TypeConverter.ToUint32(p)) == TypeConverter.ToString(p) && TypeConverter.ToUint32(p) != uint.MaxValue;

+ 23 - 0
Jint/Native/JsValue.cs

@@ -2,6 +2,7 @@
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Diagnostics.Contracts;
 using System.Diagnostics.Contracts;
 using Jint.Native.Object;
 using Jint.Native.Object;
+using Jint.Native.RegExp;
 using Jint.Runtime;
 using Jint.Runtime;
 
 
 namespace Jint.Native
 namespace Jint.Native
@@ -80,6 +81,18 @@ namespace Jint.Native
         {
         {
             return _type == Types.Undefined;
             return _type == Types.Undefined;
         }
         }
+
+        [Pure]
+        public bool IsArray()
+        {
+            return this.IsObject() && this.AsObject() is Jint.Native.Array.ArrayInstance;
+        }
+
+        [Pure]
+        public bool IsRegExp()
+        {
+            return this.IsObject() && this.AsObject() is RegExpInstance;
+        }
         
         
         [Pure]
         [Pure]
         public bool IsObject()
         public bool IsObject()
@@ -122,6 +135,16 @@ namespace Jint.Native
             return _object;
             return _object;
         }
         }
 
 
+        [Pure]
+        public Jint.Native.Array.ArrayInstance AsArray()
+        {
+            if (!this.IsArray())
+            {
+                throw new ArgumentException("The value is not an array");
+            }
+            return this.AsObject() as Jint.Native.Array.ArrayInstance;            
+        }
+
         [Pure]
         [Pure]
         public T TryCast<T>(Action<JsValue> fail = null) where T: class
         public T TryCast<T>(Action<JsValue> fail = null) where T: class
         {
         {

+ 46 - 5
Jint/Native/String/StringPrototype.cs

@@ -132,8 +132,9 @@ namespace Jint.Native.String
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
 
 
             var separator = arguments.At(0);
             var separator = arguments.At(0);
-            var l = arguments.At(1);
 
 
+            // Coerce into a number, true will become 1 
+            var l = arguments.At(1);
             var a = (ArrayInstance) Engine.Array.Construct(Arguments.Empty);
             var a = (ArrayInstance) Engine.Array.Construct(Arguments.Empty);
             var limit = l == Undefined.Instance ? UInt32.MaxValue : TypeConverter.ToUint32(l);
             var limit = l == Undefined.Instance ? UInt32.MaxValue : TypeConverter.ToUint32(l);
             var len = s.Length;
             var len = s.Length;
@@ -143,12 +144,24 @@ namespace Jint.Native.String
                 return a;
                 return a;
             }
             }
 
 
-            if (separator == Undefined.Instance)
+            if (separator == Null.Instance)
+            {
+                separator = Null.Text;
+            }
+            else if (separator == Undefined.Instance)
             {
             {
-                return (ArrayInstance) Engine.Array.Construct(Arguments.From(s));
+                return (ArrayInstance)Engine.Array.Construct(Arguments.From(s));
+            }
+            else
+            {
+                if (!separator.IsRegExp())
+                {
+                    separator = TypeConverter.ToString(separator); // Coerce into a string, for an object call toString()
+                }
             }
             }
 
 
             var rx = TypeConverter.ToObject(Engine, separator) as RegExpInstance;
             var rx = TypeConverter.ToObject(Engine, separator) as RegExpInstance;
+
             if (rx != null)
             if (rx != null)
             {
             {
                 var match = rx.Value.Match(s, 0);
                 var match = rx.Value.Match(s, 0);
@@ -190,6 +203,10 @@ namespace Jint.Native.String
                     }
                     }
 
 
                     match = match.NextMatch();
                     match = match.NextMatch();
+                    if (!match.Success) // Add the last part of the split
+                    {
+                        a.DefineOwnProperty(index++.ToString(), new PropertyDescriptor(s.Substring(lastIndex), true, true, true), false);                        
+                    }
                 }
                 }
 
 
                 return a;
                 return a;
@@ -197,8 +214,7 @@ namespace Jint.Native.String
             else
             else
             {
             {
                 var sep = TypeConverter.ToString(separator);
                 var sep = TypeConverter.ToString(separator);
-
-
+                
                 var segments = s.Split(new [] { sep }, StringSplitOptions.None);
                 var segments = s.Split(new [] { sep }, StringSplitOptions.None);
                 for (int i = 0; i < segments.Length && i < limit; i++)
                 for (int i = 0; i < segments.Length && i < limit; i++)
                 {
                 {
@@ -215,8 +231,23 @@ namespace Jint.Native.String
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
 
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
+
             var start = TypeConverter.ToNumber(arguments.At(0));
             var start = TypeConverter.ToNumber(arguments.At(0));
+            if (start == double.NegativeInfinity)
+            {
+                start = 0;
+            }
+            if (start == double.PositiveInfinity)
+            {
+                return string.Empty;
+            }
+            
             var end = TypeConverter.ToNumber(arguments.At(1));
             var end = TypeConverter.ToNumber(arguments.At(1));
+            if (end == double.PositiveInfinity)
+            {
+                end = s.Length;
+            }
+
             var len = s.Length;
             var len = s.Length;
             var intStart = (int)TypeConverter.ToInteger(start);
             var intStart = (int)TypeConverter.ToInteger(start);
             var intEnd = arguments.At(1) == Undefined.Instance ? len : (int)TypeConverter.ToInteger(end);
             var intEnd = arguments.At(1) == Undefined.Instance ? len : (int)TypeConverter.ToInteger(end);
@@ -234,6 +265,16 @@ namespace Jint.Native.String
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
 
 
             var regex = arguments.At(0);
             var regex = arguments.At(0);
+
+            if (regex.IsUndefined())
+            {
+                regex = string.Empty;
+            }
+            else if (regex.IsNull())
+            {
+                regex = Null.Text;
+            }
+
             var rx = TypeConverter.ToObject(Engine, regex) as RegExpInstance ?? (RegExpInstance)Engine.RegExp.Construct(new[] { regex });
             var rx = TypeConverter.ToObject(Engine, regex) as RegExpInstance ?? (RegExpInstance)Engine.RegExp.Construct(new[] { regex });
             var match = rx.Value.Match(s);
             var match = rx.Value.Match(s);
             if (!match.Success)
             if (!match.Success)