Browse Source

Implementing Array.prototype.reduce

Sebastien Ros 12 years ago
parent
commit
6000a8c4f3
1 changed files with 63 additions and 9 deletions
  1. 63 9
      Jint/Native/Array/ArrayPrototype.cs

+ 63 - 9
Jint/Native/Array/ArrayPrototype.cs

@@ -50,10 +50,10 @@ namespace Jint.Native.Array
             FastAddProperty("every", new ClrFunctionInstance<object, bool>(Engine, Every, 1), true, false, true);
             FastAddProperty("some", new ClrFunctionInstance<object, bool>(Engine, Some, 1), true, false, true);
             FastAddProperty("forEach", new ClrFunctionInstance<object, object>(Engine, ForEach, 1), true, false, true);
-            FastAddProperty("map", new ClrFunctionInstance<object, object>(Engine, Map, 1), true, false, true);
-            FastAddProperty("filter", new ClrFunctionInstance<object, object>(Engine, Filter, 1), true, false, true);
-            FastAddProperty("reduce", new ClrFunctionInstance<ArrayInstance, object>(Engine, Reduce), true, false, true);
-            FastAddProperty("reduceRight", new ClrFunctionInstance<ArrayInstance, object>(Engine, ReduceRight), true, false, true);
+            FastAddProperty("map", new ClrFunctionInstance<object, ArrayInstance>(Engine, Map, 1), true, false, true);
+            FastAddProperty("filter", new ClrFunctionInstance<object, ArrayInstance>(Engine, Filter, 1), true, false, true);
+            FastAddProperty("reduce", new ClrFunctionInstance<object, object>(Engine, Reduce, 1), true, false, true);
+            FastAddProperty("reduceRight", new ClrFunctionInstance<object, object>(Engine, ReduceRight, 1), true, false, true);
         }
 
         private int LastIndexOf(object thisObj, object[] arguments)
@@ -96,10 +96,64 @@ namespace Jint.Native.Array
 
         private object Reduce(object thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
+            var initialValue = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+
+            var o = TypeConverter.ToObject(Engine, thisObj);
+            var lenValue = o.Get("length");
+            var len = TypeConverter.ToUint32(lenValue);
+
+            var callable = callbackfn as ICallable;
+            if (callable == null)
+            {
+                throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
+            }
+
+            if (len == 0 && arguments.Length < 2)
+            {
+                throw new JavaScriptException(Engine.TypeError);
+            }
+
+            var k = 0;
+            object accumulator = Undefined.Instance;
+            if (arguments.Length > 2)
+            {
+                accumulator = initialValue;
+            }
+            else
+            {
+                var kPresent = false;
+                while (kPresent == false && k < len)
+                {
+                    var pk = k.ToString();
+                    var kpresent = o.HasProperty(pk);
+                    if (kpresent)
+                    {
+                        accumulator = o.Get(pk);
+                    }
+                    k++;
+                }
+                if (kPresent == false)
+                {
+                    throw new JavaScriptException(Engine.TypeError);
+                }
+            }
+
+            for (; k < len; k++)
+            {
+                var pk = k.ToString();
+                var kpresent = o.HasProperty(pk);
+                if (kpresent)
+                {
+                    var kvalue = o.Get(pk);
+                    accumulator = callable.Call(Undefined.Instance, new object[] { kvalue, k, o });
+                }
+            }
+
+            return accumulator;
         }
 
-        private object Filter(object thisObj, object[] arguments)
+        private ArrayInstance Filter(object thisObj, object[] arguments)
         {
             var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
             var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
@@ -114,7 +168,7 @@ namespace Jint.Native.Array
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
             }
 
-            var a = Engine.Array.Construct(Arguments.Empty);
+            var a = (ArrayInstance)Engine.Array.Construct(Arguments.Empty);
 
             var to = 0;
             for (var k = 0; k < len; k++)
@@ -136,7 +190,7 @@ namespace Jint.Native.Array
             return a;
         }
 
-        private object Map(object thisObj, object[] arguments)
+        private ArrayInstance Map(object thisObj, object[] arguments)
         {
             var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
             var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
@@ -151,7 +205,7 @@ namespace Jint.Native.Array
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
             }
 
-            var a = Engine.Array.Construct(Arguments.Empty);
+            var a = (ArrayInstance)Engine.Array.Construct(Arguments.Empty);
 
             for (var k = 0; k < len; k++)
             {