Browse Source

Merge pull request #4 from fredericaltorres/master

Fixed string.lastIndexOf
Sébastien Ros 11 years ago
parent
commit
b20a162da8
1 changed files with 64 additions and 3 deletions
  1. 64 3
      Jint/Native/String/StringPrototype.cs

+ 64 - 3
Jint/Native/String/StringPrototype.cs

@@ -595,19 +595,80 @@ namespace Jint.Native.String
             return string.CompareOrdinal(s, that);
             return string.CompareOrdinal(s, that);
         }
         }
 
 
+        private static List<int> AllIndexesOf(string str, string value)
+        {
+            if (string.IsNullOrEmpty(value))
+                return new List<int>();
+
+            var indexes = new List<int>();
+            for (int index = 0; ; index += value.Length)
+            {
+                index = str.IndexOf(value, index);
+                if (index == -1) // no more fond
+                    return indexes;
+                indexes.Add(index);
+            }
+        }
+
+        private int LastIndexJavaScriptImplementation(string s, string searchStr, int pos = -1)
+        {
+            if (pos == -1)
+                pos = s.Length;
+
+            var len          = s.Length;
+            var start        = System.Math.Min(System.Math.Max(pos, 0), len);
+            var searchLen    = searchStr.Length;
+            var kPositions   = AllIndexesOf(s, searchStr);
+
+            if (kPositions.Count == 0) // Nothing found
+            {
+                return -1;
+            }
+            else if (kPositions.Count == 1) // Only one found
+            {
+                return kPositions[0] <= start ? kPositions[0] : -1;
+            }
+
+            // Return the largest possible nonnegative integer k not larger than start 
+            // such that k+ searchLen is not greater than len
+            for (var i = 0; i < kPositions.Count; i++)
+            {
+                if (kPositions[i] <= start)
+                {
+                    // ok move to the next one to find a greater pos
+                }
+                else
+                {
+                    if ((i > 0) && ((kPositions[i - 1] + searchLen) <= len))
+                        return kPositions[i - 1];
+                    else
+                        return -1;
+                }
+            }
+            return kPositions[kPositions.Count - 1];
+        }
+
         private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         {
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
 
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             var searchStr = TypeConverter.ToString(arguments.At(0));
             var searchStr = TypeConverter.ToString(arguments.At(0));
-            double numPos = arguments.At(0) == Undefined.Instance ? double.NaN : TypeConverter.ToNumber(arguments.At(0));
+            double numPos = arguments.At(1) == Undefined.Instance ? s.Length : TypeConverter.ToNumber(arguments.At(1));
             double pos = double.IsNaN(numPos) ? double.PositiveInfinity : TypeConverter.ToInteger(numPos);
             double pos = double.IsNaN(numPos) ? double.PositiveInfinity : TypeConverter.ToInteger(numPos);
             var len = s.Length;
             var len = s.Length;
             var start = System.Math.Min(len, System.Math.Max(pos, 0));
             var start = System.Math.Min(len, System.Math.Max(pos, 0));
-            var searchLen = searchStr.Length;
 
 
-            return s.LastIndexOf(searchStr, len - (int) start, StringComparison.Ordinal);
+            // The JavaScript spec of string.lastIndexOf does match the C# spec
+            // Therefore we need to write our own specific implementation.
+            // Enjoy the fact that Ecma spec and Mozilla spec have different definition which
+            // I guess mean the same thing.
+            // Ecma spec
+            // http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4.8
+            // Mozilla spec
+            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf
+
+            return LastIndexJavaScriptImplementation(s, searchStr, (int)start);
         }
         }
 
 
         private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)
         private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)